
//***** Headers

#include <stdint.h>
#include <iostream>
#include <math.h>
#include <string.h>
#include <msp430f2112.h>
#include <cc2msp430f2112.h>
#include <cc2500_regs.h>


char initial_power[6];
uint8_t nRSSI;
char txBuffer[65];
uint8_t length;
uint8_t status;
int nClock = 32768/3;

unsigned int nTXwait = 0;
uint8_t nState;
  
int8_t rssi_dec;
uint8_t rssi_dBm;
uint8_t rssi_offset = 69; 

//***** Function Defs
void spi_setup(void);
void cc_powerup_reset(void);
void wait_cycles(uint16_t);
void writeRFSettings(void);
void cc_write_burst_reg(uint8_t, char*, uint8_t);
void cc_strobe(uint8_t);
void cc_write_reg(uint8_t, uint8_t);
uint8_t cc_read_status(uint8_t);
void cc_read_burst_reg(uint8_t addr, uint8_t *buffer, uint8_t count);
void send_packet( uint8_t*, uint8_t );
uint8_t receive_packet( uint8_t* p_buffer, uint8_t* length );
uint8_t cc_read_reg(uint8_t addr);
void TI_CC_SPIReadBurstReg(char, char *, char);
void sendpacket(void);
int hex2Dec(const uint8_t& hex);

int hexCharToDecimal(char ch);

//***** Functions

void spi_setup(void)//////////////////////////////////
{
  CSn_PxOUT |= CSn_PIN;
  CSn_PxDIR |= CSn_PIN;         // /CS disable

  UCB0CTL1 |= UCSWRST;                      // **Disable USCI state machine**
  UCB0CTL0 |= UCMST+UCCKPH+UCMSB+UCSYNC;    // 3-pin, 8-bit SPI master
  UCB0CTL1 |= UCSSEL_2;                     // SMCLK
  UCB0BR0 = 0x02;                           // UCLK/2
  UCB0BR1 = 0x00;
  SPI_USCIB0_PxSEL |= SPI_USCIB0_SIMO
                         | SPI_USCIB0_SOMI
                         | SPI_USCIB0_UCLK;
                                            // SPI option select
  SPI_USCIB0_PxDIR |= SPI_USCIB0_SIMO | SPI_USCIB0_UCLK;
                                            // SPI TXD out direction
  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
}

// Delay function. # of CPU cycles delayed is similar to "cycles". Specifically,
// it's ((cycles-15) % 6) + 15.  Not exact, but gives a sense of the real-time
// delay.  Also, if MCLK ~1MHz, "cycles" is similar to # of useconds delayed.
void TI_CC_Wait(unsigned int cycles)
{
  while(cycles>15)                          // 15 cycles consumed by overhead
    cycles = cycles - 6;                    // 6 cycles consumed each iteration
}

void cc_powerup_reset(void)////////////////////
{
  CSn_PxOUT |= CSn_PIN;
  TI_CC_Wait(30);
  CSn_PxOUT &= ~CSn_PIN;
  TI_CC_Wait(30);
  CSn_PxOUT |= CSn_PIN;
  TI_CC_Wait(45);

  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = TI_CCxxx0_SRES;               // Send strobe
  // Strobe addr is now being TX'ed
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  CSn_PxOUT |= CSn_PIN;         // /CS disable

}

/*******************************************************************************
 * @fn void cc_write_reg(uint8_t addr, uint8_t value)
 * @brief Write single register value to CCxxxx
 * ****************************************************************************/
void cc_write_reg(uint8_t addr, uint8_t value)//////////////////
{
  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = addr;                         // Send address
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = value;                        // Send data
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  CSn_PxOUT |= CSn_PIN;         // /CS disable
}



void writeRFSettings(void)
{
  // Write register settings
  cc_write_reg(TI_CCxxx0_IOCFG2,   0x0F);  // GDO2 output pin config. //YEs
  cc_write_reg(TI_CCxxx0_IOCFG0,   0x06);  // GDO0 output pin config. //YES
  cc_write_reg(TI_CCxxx0_PKTLEN,   0x3D);  // Packet length.    //YES
  cc_write_reg(TI_CCxxx0_PKTCTRL1, 0x04);  // Packet automation control.// 01 = Addresing //00 = Stock //YES
  cc_write_reg(TI_CCxxx0_PKTCTRL0, 0x05);  // Packet automation control.// //YES
  cc_write_reg(TI_CCxxx0_ADDR,     0x01);  // Device address.// YES
  cc_write_reg(TI_CCxxx0_CHANNR,   0x00); // Channel number.// 
  cc_write_reg(TI_CCxxx0_FSCTRL1,  0x0A); // Freq synthesizer control.// YES
  cc_write_reg(TI_CCxxx0_FSCTRL0,  0x00); // Freq synthesizer control. //Yes
  cc_write_reg(TI_CCxxx0_FREQ2,    0x5D); // Freq control word, high byte //Yes
  cc_write_reg(TI_CCxxx0_FREQ1,    0x44); // Freq control word, mid byte. //Yes
  cc_write_reg(TI_CCxxx0_FREQ0,    0xEC); // Freq control word, low byte. //YEs
  cc_write_reg(TI_CCxxx0_MDMCFG4,  0x4D); // Modem configuration.// YES //10k=48
  cc_write_reg(TI_CCxxx0_MDMCFG3,  0x3B); // Modem configuration. //YES //10k=93
  cc_write_reg(TI_CCxxx0_MDMCFG2,  0x73); // Modem configuration.// YES 70=No Syn
  cc_write_reg(TI_CCxxx0_MDMCFG1,  0x23); // Modem configuration.//  YES 4 Pre Bytes
  cc_write_reg(TI_CCxxx0_MDMCFG0,  0xF8); // Modem configuration.// YERSD
  cc_write_reg(TI_CCxxx0_DEVIATN,  0x44); // Modem dev (when FSK mod en) //yES
  cc_write_reg(TI_CCxxx0_MCSM1 ,   0x0C); //MainRadio Cntrl State Machine //3c
  cc_write_reg(TI_CCxxx0_MCSM0 ,   0x18); //MainRadio Cntrl State Machine
  cc_write_reg(TI_CCxxx0_FOCCFG,   0x16); // Freq Offset Compens. Config //YES
  cc_write_reg(TI_CCxxx0_BSCFG,    0x1C); //  Bit synchronization config.
  cc_write_reg(TI_CCxxx0_AGCCTRL2, 0xC7); // AGC control.
  cc_write_reg(TI_CCxxx0_AGCCTRL1, 0x00); // AGC control.
  cc_write_reg(TI_CCxxx0_AGCCTRL0, 0xB0); // AGC control.
  cc_write_reg(TI_CCxxx0_FREND1,   0x56); // Front end RX configuration.
  cc_write_reg(TI_CCxxx0_FREND0,   0x10); // Front end RX configuration.
 cc_write_reg(TI_CCxxx0_FSCAL3,   0xEA); // Frequency synthesizer cal. //10k = A9
cc_write_reg(TI_CCxxx0_FSCAL2,   0x0A); // Frequency synthesizer cal.
cc_write_reg(TI_CCxxx0_FSCAL1,   0x00); // Frequency synthesizer cal.
cc_write_reg(TI_CCxxx0_FSCAL0,   0x11); // Frequency synthesizer cal.
    
  cc_write_reg(TI_CCxxx0_FSTEST,   0x59); // Frequency synthesizer cal.
  cc_write_reg(TI_CCxxx0_FSTEST,   0x59); // Frequency synthesizer cal.
  
  cc_write_reg(TI_CCxxx0_TEST2,    0x88); // Various test settings.
  cc_write_reg(TI_CCxxx0_TEST1,    0x31); // Various test settings.
  cc_write_reg(TI_CCxxx0_TEST0,    0x0B);  // Various test settings.
}




/*******************************************************************************
 * @fn cc_write_burst_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
 * @brief Write multiple values to CCxxxx
 * ****************************************************************************/
void cc_write_burst_reg(uint8_t addr, char *buffer, uint8_t count)/////////////
{  
  unsigned int i;

  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = addr | TI_CCxxx0_WRITE_BURST; // Send address
  for (i = 0; i < count; i++)
  {
    while (!(IFG2&UCB0TXIFG));              // Wait for TXBUF ready
    UCB0TXBUF = buffer[i];                  // Send data
  }
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  CSn_PxOUT |= CSn_PIN;         // /CS disable
}

void cc_strobe(uint8_t strobe) ////////////////////////
{
  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = strobe;                       // Send strobe
  // Strobe addr is now being TX'ed
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  CSn_PxOUT |= CSn_PIN;         // /CS disable
}

/*******************************************************************************
 * @fn uint8_t cc_read_reg(uint8_t addr)
 * @brief read single register from CCxxxx
 * ****************************************************************************/
uint8_t cc_read_reg(uint8_t addr)///////////////
{
  char x;

  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = (addr | TI_CCxxx0_READ_SINGLE);// Send address
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = 0;                            // Dummy write so we can read data
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  x = UCB0RXBUF;                            // Read data
  CSn_PxOUT |= CSn_PIN;         // /CS disable

  return x;
}

/*******************************************************************************
 * @fn cc_read_burst_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
 * @brief read multiple registers from CCxxxx
 * ****************************************************************************/
/*
void cc_read_burst_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
{
  uint8_t i;

  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = (addr | TI_CCxxx0_READ_BURST);// Send address
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  UCB0TXBUF = 0;                            // Dummy write to read 1st data byte
  // Addr byte is now being TX'ed, with dummy byte to follow immediately after
  IFG2 &= ~UCB0RXIFG;                       // Clear flag
  while (!(IFG2&UCB0RXIFG));                // Wait for end of 1st data byte TX
  // First data byte now in RXBUF
  for (i = 0; i < (count-1); i++)
  {
    UCB0TXBUF = 0;                          //Initiate next data RX, meanwhile..
    buffer[i] = UCB0RXBUF;                  // Store data from last data RX
    while (!(IFG2&UCB0RXIFG));              // Wait for RX to finish
  }
  buffer[count-1] = UCB0RXBUF;              // Store last RX byte in buffer
  CSn_PxOUT |= CSn_PIN;         // /CS disable
}
*/
void TI_CC_SPIReadBurstReg(char addr, char *buffer, char count)////////////////
{
  char i;

  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = (addr | TI_CCxxx0_READ_BURST);// Send address
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  UCB0TXBUF = 0;                            // Dummy write to read 1st data byte
  // Addr byte is now being TX'ed, with dummy byte to follow immediately after
  IFG2 &= ~UCB0RXIFG;                       // Clear flag
  while (!(IFG2&UCB0RXIFG));                // Wait for end of 1st data byte TX
  // First data byte now in RXBUF
  for (i = 0; i < (count-1); i++)
  {
    UCB0TXBUF = 0;                          //Initiate next data RX, meanwhile..
    buffer[i] = UCB0RXBUF;                  // Store data from last data RX
    while (!(IFG2&UCB0RXIFG));              // Wait for RX to finish
  }
  buffer[count-1] = UCB0RXBUF;              // Store last RX byte in buffer
  CSn_PxOUT |= CSn_PIN;         // /CS disable
}

/*******************************************************************************
 * @fn uint8_t cc_read_status(uint8_t addr)
 * @brief send status command and read returned status byte
 * ****************************************************************************/
uint8_t cc_read_status(uint8_t addr) ////////////////////
{
  uint8_t status;

  CSn_PxOUT &= ~CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = (addr | TI_CCxxx0_READ_BURST);// Send address
  while (!(IFG2&UCB0TXIFG));                // Wait for TXBUF ready
  UCB0TXBUF = 0;                            // Dummy write so we can read data
  while (UCB0STAT & UCBUSY);                // Wait for TX to complete
  status = UCB0RXBUF;                       // Read data
  CSn_PxOUT |= CSn_PIN;         // /CS disable

  return status;
}



     


/*******************************************************************************
 * @fn void sendpacket(void)
 * @brief Send Packet with to DMU with cart ID
 * ****************************************************************************/
void sendpacket(void)
{
			
				
  cc_write_burst_reg(TI_CCxxx0_TXFIFO, txBuffer, length); // Write TX data

 while (!(P2IN&BIT3));                          // Wait GDO0 to go hi -> sync TX'ed
 while (P2IN&BIT3);                             // Wait GDO0 to clear -> end of pkt

} 

void initTimer(void) {
  P1DIR |= 0xFF;                              // P1 output
  P1SEL |= BIT2;                              // P1.2 pwm
  P2DIR |= 0x00;
  P1OUT = 0x00;

  TA1CCR0 = nClock;
  TA1CTL |= TASSEL_1 + MC_1;                  // ACLK, Count
  TA1CCTL0 |= CCIE;                           // TACCR0 interrupt enabled

}


//***** Main
int main( void )
{
	WDTCTL = WDTPW + WDTHOLD;		// Stop WDT - Required in all code        
        
        
        for(uint8_t nCounter = 1; nCounter < 30; nCounter++){
          txBuffer[nCounter] = 0x31;
        }
        txBuffer[0] = 2;	//Payload Length -> Total packets to send = length+1 (to include length)
        //txBuffer[1] = 0x01;     //Address Byte
        length = 3;             //Length + Address + Data1 + Data2

	//Setup SPI on F2112
	__delay_cycles(5000); 			
	spi_setup();
	//PowerUp reset CC2500
	cc_powerup_reset();
        __delay_cycles(5000); 	
	//Write RFSettings	
	writeRFSettings();	
	//Write Patable
	initial_power[0] = 0xFE; //Max Power Settings for TX
	cc_write_burst_reg( TI_CCxxx0_PATABLE, initial_power, 1);	//Write PATABLE
	//Initialize CC2500 in Idle Mode
	cc_strobe(TI_CCxxx0_SIDLE);     // When a pkt is received, it will
        __delay_cycles(5000);
        cc_strobe(TI_CCxxx0_SFRX);
        __delay_cycles(5000);
        cc_strobe(TI_CCxxx0_SFTX);
        __delay_cycles(5000);
        cc_strobe(TI_CCxxx0_SPWD);  //Sleep mode when CS goes high
        __delay_cycles(2000);
									
 
        GDO0_PxIES |= BIT3;       // Int on falling edge (end of pkt)
        GDO0_PxIFG &= ~BIT3;      // Clear flag
        GDO0_PxIE |= BIT3;        // Enable int on end of packet      
        initTimer();					

        __bis_SR_register(LPM3_bits + GIE);       // Enter LPM0 w/ interrupt


}

// Timer1_A0 interrupt service routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0 (void)
{
  //Reset Vars
  TA1CCR0 = nClock;
  nTXwait = 0x00;
  nRSSI = 255;
  
  //Wake from sleep
  cc_strobe(TI_CCxxx0_SIDLE);
   __delay_cycles(1000);
  
    
  //RX For CCA
  cc_strobe(TI_CCxxx0_SRX);
  __delay_cycles(1000);
  
  //Wait for Clear Channel
  while (!((nRSSI < 203) && (nRSSI >= 128))) {  //Correct Limits based on Spreadsheet
    nRSSI = cc_read_status( TI_CCxxx0_RSSI );
    __delay_cycles(20);
    nTXwait++;
  }
   
 //Channel Clear, Transmit
  cc_strobe(TI_CCxxx0_STX);
 __delay_cycles(1000);
 sendpacket();
 
 //Go to Sleep
  cc_strobe(TI_CCxxx0_SIDLE); 
  __delay_cycles(1000);
 cc_strobe(TI_CCxxx0_SPWD);  //Sleep mode when CS goes high
  
                                      
}
