#include "Arduino.h"
#include "mrf24j40.h"
#include "protocol.h"
#include "extra-protocol.h"

#include <SPI/SPI.h>
#include "assert.h"

#define VERSION "v0.3"

#define PANID 0x0001
#define SADDR 0x0002
#define DADDR 0x0001

#define PIN_SS 10
#define PIN_LED 13

#define DEFAULT_CHANNEL 26

const unsigned char MAC_ADDR[8]= {1, 2, 3, 4, 5, 6, 7, 8};

void frame_cb(unsigned char *frame, unsigned int size)
{
  cli_error();
}

void control_cb(enum prot_ctype type, unsigned char *data, unsigned int size)
{
  unsigned short channel;
  switch(type) {
  case(PROT_CTYPE_CONFIG_CHANNEL):
    if(size != 2)
      cli_error();
    channel = *((unsigned short *)data);

    /* reconfigure the transceiver */
    mrf24j40_init(NULL, PANID, SADDR, MAC_ADDR, channel, 0);
    mrf24j40_promiscuous(NULL, 1);
    send_info("configure");

    break;
  default:
    cli_error();
  }
}

void send(const unsigned char *data, unsigned int size)
{
  Serial.write(data, size);
}

void setup(void)
{
  /* setup UART */
  Serial.begin(115200);

  /* setup SPI */
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  SPI.setBitOrder(MSBFIRST);
  pinMode(PIN_SS, OUTPUT);
  SPI.begin();

  /* setup MRF24J40 */
  mrf24j40_init(NULL, PANID, SADDR, MAC_ADDR, DEFAULT_CHANNEL, 0);
  mrf24j40_promiscuous(NULL, 1);

  protocol_init(frame_cb,
                control_cb,
                send);

  send_info("Sniffer Firmware " VERSION "\n");
}

void serialEvent()
{
  /* serial */
  input_step((unsigned char)Serial.read());
}

static unsigned char buf[128];
static unsigned char rssi;
static unsigned char lqi;

void loop()
{
  int status;

  unsigned char v;
  int len;

  /* poll register */
  mrf24j40_intstat_read(NULL, &status);

  if(status & MRF24J40_INTSTAT_RXIF) {
    mrf24j40_short_read(NULL, MRF24J40_SREG_RXFLUSH, &v);
    v |= 0x1;
    mrf24j40_short_write(NULL, MRF24J40_SREG_RXFLUSH, v);
    len = mrf24j40_rx_raw(NULL, buf, 128, &rssi, &lqi);

    /* send the frame */
    if(len > 0)
      send_frame(buf, len);

    /* empty frame are ignored */
  }
}
