/**
 * radio/nrf.c: interface to radiowaves
 * 2015 by true
 *
 * ----
 *
 * This is a nasty hack implementation of the NRF24L01+.
 * Modify as necessary if using on another STM32; see nrf.h
 *   and the NRF24L01 library.
**/

#include <pirate.h>
#include "nrf.h"


/* variables */
  // general radio
uint8_t nrf_detected;
uint8_t nrf_myaddr;

static uint8_t nrf_tx_addr[5] = {0x00, '8', 'r', 'i', 'P'};
uint8_t nrf_tx_buf[NRF_PAYLOAD_LEN];

static uint8_t nrf_rx_addr_p0[5] = {0x00, '8', 'r', 'i', 'P'};
static uint8_t nrf_rx_addr_p1[5] = {0x01, '8', 'r', 'i', 'P'};


  // pingpong
uint8_t nrf_last_ping_id; 	// sender's last byte
uint8_t nrf_last_ping_idx; 	// index byte


  // encryption
static uint32_t xxtea_key[2][4];
static uint8_t xxtea_key_done[2];


/* functions */
uint8_t nrf_checksum(uint8_t *data, uint8_t len, int32_t offset) {
	int32_t ret = 0;

	while (len) {
		ret += *data++;
		len--;
	}

	return (ret + offset);
}

void nrf_process_data(uint8_t pipe, uint8_t *pBuf, uint8_t len)
{
	int32_t w = 0;

	if (len != NRF_PAYLOAD_LEN) return;

	// first see if there are any unencrypted commands
	// TODO: verify checksum to see if packet is valid
	switch (pBuf[0]) {
		case NRF_CMD_GETKEY: {
			// check to see if the message is formatted correctly
			// we will oblige and send out the keys we have
			// TODO: send key
			break;
		}
		case NRF_CMD_SETKEY: {
			// check to see if the message is formatted correctly
			// we are a DC22 badge, so we have the keys already
			break;
		}

		case NRF_CMD_PING: {
			// get received address for this packet
			nrf_last_ping_id = pipe;

			// and pull the index
			nrf_last_ping_idx = pBuf[2];
			return;
		}
	}

	// decode with dc22 public key and see if checksum matches
	if (xxtea_key_done[0]) {
		btea((uint32_t *)pBuf, -2, xxtea_key[0]);
		if (!nrf_checksum(pBuf, 7, pBuf[7])) {
			w = 22;
		}
	}

	// decode with dc22 shared key and see if it matches
	if (xxtea_key_done[1] && !w) {
		btea((uint32_t *)pBuf, -2, xxtea_key[1]);
		if (!nrf_checksum(pBuf, 7, pBuf[7])) {
			w = 23;
		}
	}

	// try to process this data
	if (w) {
		// yes, we can
		// TODO: process radio data
		switch (pBuf[0]) {

		}
	}
}

void nrf_init()
{
	// initialize nRF24 library
	nRF24_init(SystemCoreClock);
	// clear any pending interrupts, we don't give a shit about them
	nRF24_clear_irq_flags();

	// set nrf data callbacks
	nRF24_rx_cb = nrf_process_data;


	nrf_myaddr = *(uint8_t *)NRF_MYADDR_EEPROM;

	nrf_detected = 0;
	if (nRF24_is_present()) {
		nrf_detected = 1;
	}

	// and finally, configure the radio and turn it on in listen mode
	nRF24_set_payload_size(0, NRF_PAYLOAD_LEN);
	nRF24_set_payload_size(1, NRF_PAYLOAD_LEN);
	nRF24_set_autoack(1, 0); 	// no autoack on general receive pipe
	nRF24_set_dynack(1); 		// allows us to NO_ACK packets
	nRF24_update_config(_TRNRF_UPDATE_ALL);

	nRF24_set_txaddr(nrf_tx_addr);
	nRF24_set_rxaddr(0, nrf_rx_addr_p0);
	nRF24_set_rxaddr(1, nrf_rx_addr_p1);

	nRF24_mode_rx();
}
