#include <MKL03Z4.h> 
#include "hardware.h"
#include "si4468.h"

uint8_t SPI_buf[32];
const uint8_t TX_pac[] = {0x07, 0x66, 0x05, 0xAA, 'M', 'A', 'I', 'L'};	// packet to broadcast

//-------Radio Commands----------------------------------------------
const uint8_t SI4468_sleep[] = {0x02, 0x34, 0x01};				// put radio on sleep (MOVE_TO_SLEEP)
const uint8_t SI4468_fifo_info[] = {0x02, 0x15, 0x00};		// FIFO_INFO
const uint8_t SI4468_clear_fifo[] = {0x02, 0x15, 0x03};		// CLEAR_FIFO
const uint8_t SI4468_read_cmd_buff[] = {0x44};					// READ_CMD_BUFF
const uint8_t SI4468_read_rx_fifo[] =  {0x77};					// READ_RX_FIFO
const uint8_t SI4468_frr_a_read[] =    {0x50};					// FRR_A_READ
const uint8_t SI4468_clear_irq[] = {0x01, 0x20};				// CLEAR_IRQ
const uint8_t SI4468_move_to_rx[] = {0x02, 0x34, 0x08};		// MOVE_TO_RX
const uint8_t SI4468_start_rx[] = {0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x08};	// START_RX opeation
const uint8_t SI4468_start_tx[] = {0x07, 0x31, 0x00, 0x30, 0x00, 0x06, 0, 0}; 				// start TX operation
const uint8_t SI4468_last_tx[]  = {0x07, 0x31, 0x00, 0x10, 0x00, 0x06, 0, 0};	// TX and go to sleep
const uint8_t SI4468_rqst_device_state[] = {0x01, 0x33};		// REQUEST_DEVICE_STATE

// 903MHz, 1.2kbps, 5.15KHz,  5 bytes payload + CRC16, 4 bytes preamble, D3 91 synch
const uint8_t SI4468_Config[] = {//0x23,    						// config data size (# of lines)
	0x07, 0x02, 0x01, 0x00, 0x01, 0xC9, 0xC3, 0x80,				// RF_POWER_UP
   0x08, 0x13, 0x01, 0x08, 0x01, 0x01, 0x01, 0x0B, 0x00,		// GPIO_PIN_CFG: int. disabled
   0x06, 0x11, 0x00, 0x02, 0x00, 0x52, 0x00,						// GLOBAL_XO_TUNE
   0x05, 0x11, 0x00, 0x01, 0x03, 0x20, 							// GLOBAL_CONFIG
   0x05, 0x11, 0x01, 0x01, 0x00, 0x00,								// INT_CTL_ENABLE int disable
   0x08, 0x11, 0x02, 0x04, 0x00, 0x0A, 0x04, 0x06, 0x08,		// FRR_CTL_A_MODE
   0x07, 0x11, 0x10, 0x03, 0x00, 0x04, 0x14, 0x00,				// PREAMBLE_TX_LENGTH
   0x09, 0x11, 0x10, 0x05, 0x04, 0x31, 0x00, 0x00, 0x00, 0x00,	// PREAMBLE_CONFIG
   0x0E, 0x11, 0x11, 0x0A, 0x00, 0x03, 0xCB, 0x89, 0xCB, 0x89, 0,0,0,0,0,// SYNC_CONFIG (2 bytes 0xD3 0x91)
	0x0B, 0x11, 0x12, 0x07, 0x00, 0x84, 0x01, 0x08, 0xFF, 0xFF, 0x00, 0x02,  // PKT_CRC_CONFIG  
   0x05, 0x11, 0x12, 0x01, 0x0B, 0x30,								// PKT_TX_THRESHOLD
	0x10, 0x11, 0x12, 0x0C, 0x0D, 0x00, 0x05, 0x04, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x0C, 0x11, 0x12, 0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RF_PKT_FIELD_LENGTH	
	0x08, 0x11, 0x12, 0x04, 0x36, 0xFF, 0xFF, 0xFF, 0xFF,		// CRC seed FF FF FF FF 
	0x10, 0x11, 0x20, 0x0C, 0x00, 0x02, 0x00, 0x07, 0x00, 0x2E, 0xE0, 0x01, 0xC9, 0xC3, 0x80, 0x00, 0x00,
   0x05, 0x11, 0x20, 0x01, 0x0C, 0xB4,								// MODEM_FREQ_DEV (5.15 KHz)
   0x0E, 0x11, 0x20, 0x0A, 0x18, 0x01, 0x80, 0x08, 0x03, 0xC0, 0x00, 0x24, 0x20, 0x0C, 0xE8,
   0x0D, 0x11, 0x20, 0x09, 0x22, 0x03, 0x0D, 0x00, 0xA7, 0xC6, 0x00, 0x54, 0x02, 0xC2, // 903 MHz
   0x0B, 0x11, 0x20, 0x07, 0x2C, 0x04, 0x23, 0x80, 0x01, 0x5D, 0x07, 0x80,
   0x05, 0x11, 0x20, 0x01, 0x35, 0xE0,
	0x10, 0x11, 0x20, 0x0C, 0x38, 0x11, 0xAB, 0xAB, 0x80, 0x02, 0xFF, 0xFF, 0x00, 0x2B, 0x0C, 0xA4, 0x22,
	0x09, 0x11, 0x20, 0x05, 0x45, 0x81, 0x01, 0x5F, 0x01, 0x00,
	0x05, 0x11, 0x20, 0x01, 0x4B, 0x06,
	0x06, 0x11, 0x20, 0x02, 0x4D, 0x18, 0x40,
	0x06, 0x11, 0x20, 0x02, 0x50, 0x84, 0x08,
	0x06, 0x11, 0x20, 0x02, 0x54, 0x03, 0x07,
	0x05, 0x11, 0x20, 0x01, 0x57, 0x00,
	0x09, 0x11, 0x20, 0x05, 0x5B, 0x40, 0x04, 0x07, 0x78, 0x20,	// RF_MODEM_CLKGEN_BAND
	0x10, 0x11, 0x21, 0x0C, 0x00, 0xA2, 0x81, 0x26, 0xAF, 0x3F, 0xEE, 0xC8, 0xC7, 0xDB, 0xF2, 0x02, 0x08,
	0x10, 0x11, 0x21, 0x0C, 0x0C, 0x07, 0x03, 0x15, 0xFC, 0x0F, 0x00, 0xA2, 0x81, 0x26, 0xAF, 0x3F, 0xEE,
	0x10, 0x11, 0x21, 0x0C, 0x18, 0xC8, 0xC7, 0xDB, 0xF2, 0x02, 0x08, 0x07, 0x03, 0x15, 0xFC, 0x0F, 0x00,
	0x08, 0x11, 0x22, 0x04, 0x00, 0x08, 0x7F, 0x00, 0x1D,		// RF_PA_MODE
	0x0B, 0x11, 0x23, 0x07, 0x00, 0x2C, 0x0E, 0x0B, 0x04, 0x0C, 0x73, 0x03,
	0x10, 0x11, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x0C, 0x11, 0x40, 0x08, 0x00, 0x3B, 0x09, 0x99, 0x99, 0x22, 0x22, 0x20, 0xFF,
	0};

void SI4468_setup(void)
{
	const uint8_t* ptr;
	delay(1000);												// power-up delay
	ptr = SI4468_Config;
	do
	{
		ptr = SI4468_write(ptr);	
	} while(*ptr);
	
	SI4468_write(SI4468_clear_irq);						// Send CLEAR_IRQ command
	SI4468_write(SI4468_sleep);							// put radio on sleep
}

void SI4468_sendPacket(uint8_t mode)					// mode=0: stay in READY, mode=1: SLEEP
{
	SI4468_write(SI4468_clear_fifo);						// clear FIFOs
	SI4468_write(TX_pac);									// load packet into TX FIFO
	if (mode == 0)
	{
		SI4468_write(SI4468_start_tx);					// broadcast the packet
		do {														// wait for transmit completion
			delay(25);
			SI4468_write(SI4468_rqst_device_state);	// Send REQUEST_DEVICE_STATE command
			SI4468_read(SI4468_read_cmd_buff, 3);		// Send READ_CMD_BUFF command
		} while (SPI_buf[1] != 0x03);	
	}
	else
		SI4468_write(SI4468_last_tx);						// transmit last packet and sleep
}

uint8_t* SI4468_write(const uint8_t *buf)
{
	uint8_t i, len;
	len = *buf++;
	while (!(PTB->PDIR & CTS)){}							// wait for CTS
	SPI0->C1 = SPI_C1_MSTR_MASK + SPI_C1_SPTIE_MASK + SPI_C1_SPE_MASK;	
	PTA->PCOR = CS;											// CS down
	for (i=0; i<len; i++)
	{
		while (!(SPI0->S & SPI_S_SPTEF_MASK)){}
		SPI0->D = *buf++;
	}			
	i = SPI0->D;
	while (!(SPI0->S & SPI_S_SPRF_MASK)){}
	i = SPI0->D;
	PTA->PSOR = CS;											// CS up
	return((uint8_t*)buf);	
}

void SI4468_read(const uint8_t *buf, uint8_t rlen)
{
	uint8_t i;
	while (!(PTB->PDIR & CTS)){}							// wait for CTS
	SPI0->C1 = SPI_C1_MSTR_MASK + SPI_C1_SPTIE_MASK + SPI_C1_SPE_MASK;	
	PTA->PCOR = CS;											// CS down
	while (!(SPI0->S & SPI_S_SPTEF_MASK)){}
	SPI0->D = *buf;			
	SPI_buf[0] = SPI0->D;
	while (!(SPI0->S & SPI_S_SPRF_MASK)){}				// wait for the end of RX
	SPI_buf[0] = SPI0->D;									// get CTS status
	for (i=0; i<rlen; i++)
	{		
		SPI0->D = 0;											// send dummy byte
		while (!(SPI0->S & SPI_S_SPRF_MASK)){}
		SPI_buf[i] = SPI0->D;								// get received byte
	}
	PTA->PSOR = CS;											// CS up	
}
