//******************************************************************************
// EEG-DBS SYSTEM PROGRAM
//
// This program configures the EEG-DBS system 
//
// Richard Pinnell, 2011
// 
//******************************************************************************

#include <stdint.h>
#include <signal.h>
#include <msp430x20x3.h>

#include "CC1100-CC2500.h"
#include "TI_CC_CC1100-CC2500.h"
#include "TI_CC_msp430.h"
#include "TI_CC_spi.h"
#include "TI_CC_hardware_board.h"

#define TX_PAYLOADSIZE  17                
#define DESTIN_ADDR  0xBB
#define RX_PAYLOADSIZE  11             

extern char paTable[];
extern char paTableLen;

char txBuffer[TX_PAYLOADSIZE];   
char rxBuffer[RX_PAYLOADSIZE];

unsigned int tx_lsb, tx_mid, tx_msb, dbscheck, offreq, pcount, p, l, pw;
unsigned int a2d_lsb, a2d_msb, counter, counter2;
unsigned int x, i, j, bn, n, b, k;
unsigned int val;

uint16_t time1, time2;
uint32_t offcounter;

void SetupIO(void)
{
   P2SEL &= 0x00;                                   
   TI_CC_GDO0_PxDIR &= 0x00;                    
   TI_CC_GDO0_PxIES = TI_CC_GDO0_PIN;           
   TI_CC_GDO0_PxIFG = 0;                        
   TI_CC_GDO0_PxIE = TI_CC_GDO0_PIN;            

   P1DIR |= 0x04;
   P1OUT &= ~0x04;
   P1DIR |= 0x08;
   P1OUT &= ~0x08;
   counter = 0;
}

void setup_cc2500(void)
{
   TI_CC_SPISetup();                            
   TI_CC_PowerupResetCCxxxx();                  
   writeRFSettings();                           
   TI_CC_SPIWriteBurstReg(TI_CCxxx0_PATABLE, paTable, paTableLen);
   TI_CC_SPIStrobe(TI_CCxxx0_SCAL);             
   for(j=0;j<50000;j++);                        
   TI_CC_SPIStrobe(TI_CCxxx0_SRX);              
}

void setupDBS(void)
{
  P2DIR |= 0x40;
  P2OUT &= ~0x40;                    
  CCTL0 = ~CCIE;                             
  TACCR0 = 60800;
  TACTL = TASSEL_2 + MC_1 + TACLR;                  
}

void SetupA2D(void)
{  
  SD16CTL = SD16REFON + SD16SSEL_1;	
  SD16CCTL0 = SD16SNGL + SD16OSR_256 + SD16IE;                           
  SD16INCTL0 = SD16GAIN_1 + SD16INCH_0 + SD16INTDLY_0;       
  SD16AE = SD16AE0 + SD16AE1;                              
}

void receive_packet()
{  
  if (TI_CC_SPIReadStatus(TI_CCxxx0_RXBYTES)>=RX_PAYLOADSIZE)           
  {                      
    TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, rxBuffer, RX_PAYLOADSIZE);      
    
    if (rxBuffer[0] == 0xAA)
    {
      if (rxBuffer[8] == 0x23) 
      {
        if (rxBuffer[10] == 0xEF)
        {
          if (rxBuffer[1] == 0x0A)     
          {
            dbscheck = 1;
            CCTL0 = CCIE;                                 
          }
          else if (rxBuffer[1] == 0x0B)
          {
            dbscheck = 0;
            CCTL0 = ~CCIE;
            P2OUT &= ~0x40;
          }    
          else if (rxBuffer[1] == 0x0C)   // if the first byte is 0x0C, raise the 'switch-off' flag
          {
            offreq = 1;
          }
          else if (rxBuffer[1] == 0x0D)   // Reset / Power-up the system
          {        
            WDTCTL = 0x34;           // force a system reset
          }     
          else if (rxBuffer[1] == 0x89) // Change Frequency and pulse-width
          {
            // CHANGE PW VALUE
            pw = (rxBuffer[3] & 0x3F);
            time1 = pw*80;      
            
            // CHANGE FREQ VALUE      
            time2 = rxBuffer[2] & 0x3F;
            time2 = 40000/time2;
            l = (time2/80) -1;
            
            // CHANGE PW MULTIPLIER        
            b = ((rxBuffer[6] << 8) | rxBuffer[7]);
            p = b * pw;
            
            // CHANGE FREQ MULTIPLIER        
            n = ((rxBuffer[4] << 8) | rxBuffer[5]);
          }
          
          pcount = p;
          x = 0;
          P2OUT &= ~0x40;
          
        }
      }
    }
  }
}

int main (void)
{  
  WDTCTL = WDTPW + WDTHOLD;                     
  _EINT();				           
  _BIS_SR(GIE);                                  
  BCSCTL1 = CALBC1_8MHZ;                      
  DCOCTL = CALDCO_8MHZ;                       
  
  SetupIO();
  SetupA2D();
  setup_cc2500();   
//  x = 0;
  setupDBS(); 
 
  // set initial values for the variables. The DBS is initially set to         
  dbscheck = 0;
  time1 = 720;   // this is 80 * base pulse-width
  time2 = 3077; // this is 40000 / base frequency
  n = 20;       // 2000 = x0.1, 200 = x1, 20 = x10, 2 = x100
  b = 1;       // 1 = x0.1, 10 = x1, 100 = x10, 1000 = x100
  p = 9;       // p = b * base_pw
  pcount = 9;  // pcount = p
  l =37;    // (time2/80) -1   
  
  for(;;)
  {         
    for (j=0;j<165; j++);
     
     for (i=0; i<4; i++)
     {    
       SD16CCTL0 |= SD16SC;           
       _BIS_SR(LPM0_bits);           
       val = SD16MEM0;

       if(counter == 0)
       {
         counter2 = counter;
         counter++;
         P1OUT |= 0x04;
         P1OUT |= 0x08;         
       }
       else if(counter == 1)
       {
         counter2 = counter;
         counter++;
         P1OUT &= ~0x04;
         P1OUT |= 0x08;
       }
       else if(counter == 2)
       {
         counter2 = counter;
         counter++;
         P1OUT |= 0x04;
         P1OUT &= ~0x08;
       }
       else if(counter == 3)
       {
         counter2 = counter;
         counter = 0;
         P1OUT &= ~0x04;
         P1OUT &= ~0x08;
       }                 

                     
         a2d_lsb = val & 0xFF;		
         a2d_msb = val >> 8;		         
       
       
       tx_mid = ((a2d_msb & 0x07) << 4) | ((a2d_lsb & 0xF0) >> 4);
       tx_msb = ((a2d_msb & 0xF8) >> 3) | (counter2 << 5) | 128;
       tx_lsb = (((a2d_lsb & 0x0F) << 3) | dbscheck) & 127;                
       
       txBuffer[0] = DESTIN_ADDR;      
       txBuffer[3*i+1] = tx_msb;
       txBuffer[3*i+2] = tx_mid;
       txBuffer[3*i+3] = tx_lsb;
         
         
     }        
          
     TI_CC_SPIWriteReg(TI_CCxxx0_PKTLEN,   TX_PAYLOADSIZE);
     RFSendPacket(txBuffer, TX_PAYLOADSIZE);                    
     _BIS_SR(LPM0_bits + GIE);
     TI_CC_SPIWriteReg(TI_CCxxx0_PKTLEN,   RX_PAYLOADSIZE);
     receive_packet();


     if (offreq == 1)
     {  
       SD16CCTL0 &= ~SD16IE;
       if (dbscheck == 0) 
       {
         CCTL0 = ~CCIE;
       }
       
       TI_CC_SPIWriteReg(TI_CCxxx0_MCSM2,    0x06);
       TI_CC_SPIWriteReg(TI_CCxxx0_WORCTRL,  0x78);
       TI_CC_SPIStrobe(TI_CCxxx0_SIDLE);
       TI_CC_SPIStrobe(TI_CCxxx0_SWOR);

       while (offreq == 1)
       {
         if (dbscheck == 1) _BIS_SR(LPM0_bits + GIE);
         else _BIS_SR(LPM4_bits + GIE);
         
         receive_packet();
         if (offreq == 1)
         {
           TI_CC_SPIStrobe(TI_CCxxx0_SIDLE);
           TI_CC_SPIStrobe(TI_CCxxx0_SWOR);           
         }
       }
     } 
     
     
   }
}

#pragma vector = PORT2_VECTOR
__interrupt void PORT2_ISR (void)
{
   TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN;         
   __low_power_mode_off_on_exit();              
}



#pragma vector = SD16_VECTOR
__interrupt void SD16_ISR (void)
{
      SD16CCTL0 &= ~SD16IFG;                       
      __low_power_mode_off_on_exit();                     
}

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)

{

  if (x < n)
  {
    P2OUT &= ~0x40;
    if (pcount == 0) TACCR0 = time2;
    else if (pcount <= l)
    {
      TACCR0 = time2 - (pcount*80);
      pcount = 0;
    }
    else if (pcount > l)
    {
      TACCR0 = time2 - (l*80);
      pcount -= l;
    }
    x++;
  }
  else if (x < (n+b))
  {
    if (dbscheck == 1) P2OUT |= 0x40;
    TACCR0 = time1;
    x++;
    if (x == (n+b))
    {
      x = 0;
      pcount = p;
    }
  }
}
