//******************************************************************************
// BUFFER PROGRAM
//
// This program configures the RCVR system BUFFER MCU for use with the EEG-DBS system
//
// Richard Pinnell, 2011
// 
//******************************************************************************

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

#define Bitime    0x45            // For UART transmission at 115.2Kbaud/sec
#define Bitime_5  0x02
#define RXD	  0x20		// RXD on P1.1

unsigned int i, count, TXData, RXData, wait, TXData2, RXReady;
unsigned char BitCnt;

void SetupClock(void)
{
  BCSCTL1 = CALBC1_8MHZ;                      // uses internal sub-master clock at 8MHz
  DCOCTL = CALDCO_8MHZ;                       // derives the digitally-controlled oscillator from the internal submaster clock, again at 8MHz
}

void SetupIO(void)
{
  // the following is the interrupt input from the receiver MCU
  P2SEL &= ~0x40;                                      
  P2DIR &= ~0x40;                    
  P2IES &= ~0x40;           
  P2IFG = 0;                       
  P2IE = 0x40;            
  
  // the following is the RS232 interrupt and RS2332 receive pin
  P1SEL &= ~0x02;                            
  P1DIR &= ~0x02;                  
  P1IES = 0x02;           
  P1IFG = 0;            
  P1IE = 0x02;          
  
  // this is the tx out pin that goes to the receiver MCU
  P1DIR |= 0x08;
  P1OUT |= 0x08;
  
  //this output pin is for testing purposes only   
  P1DIR |= 0x01;
  P1OUT &= ~0x01;
  P1DIR |= 0x04;
  P1OUT &= ~0x04;
}

void SetupUART (void)
{
  TACCTL0 = OUT;		// Timer A Capture/Compare Control 0 Register: Output bit = sets the output high. TXD Idle as Mark
  TACTL = TASSEL_2 + MC_1;	// Timer A Control Register: clock source = SMCLK, up mode - counts up to TACCR0 (see below)
  TACCTL0 = CM0 + CCIE;		// Timer A Capture/Compare Control 0 Register: Capture Mode = 'no capture', and enable interrupts
  // at the request of the corresponding CCIFG flag (capture compare interrupt flag)
  // This will be changed to 'capture mode' later on when we actually transmit our frame.
  TACCR0 = Bitime;	        // Timer A Capture/Compare Register 0: We're using 'compare mode' meaning that the value Bitime is
  // compared to the actual timer (TAR - Timer A Register). Basically it's the value that our timer (TAR)
  // counts up to, determined by comparing its current value with the value Bittime.
  P1SEL  |= RXD;		// Port 1 Select Register: Here we're choosing the special function for port 1 pin 5, that is p1.5. In this
  // case the special function is Timer A_0
}

void TX_Byte (void)
{
  
  BitCnt = 0xA;			// Load Bit counter, 8data + ST/SP (10 bits in total = A)
  TXData |= 0x100;			// Add mark stop bit to TXData
  TXData = TXData << 1;				// Add space start bit - remember start bit is 0, and stop bit is 1.
  TACCTL0 =  CM1 + CCIS0 + OUTMOD0 + CCIE;	// Timer A Capture/Compare Control 0 Register: set to capture on rising edge, capture an internal event on CCISA, enable interrupts 
  
  while ( CCTL0 & CCIE );				// Wait for TX completion
}


int main (void)
{  
  WDTCTL = WDTPW + WDTHOLD;                     //stop WDT
  
  SetupClock();
  SetupIO();
  SetupUART();
  
  _EINT();				        // Enable interrupts   
  _BIS_SR(GIE);                                //enable interrupts  
  
  RXData = 0x00;
  TXData2 = 0x11;
  RXReady = 0;
  count = 0;
  wait = 0;
  
  for(;;)
  { 
    _BIS_SR(LPM0_bits + GIE);
      if (RXData > 0x00)
      {
        TXData = RXData;
        TX_Byte();
        RXData = 0;
      }
    _BIS_SR(GIE);
  }
}



#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR (void)
{
  P2IE &= ~0x40;
  P1IFG &= ~0x02;         //clear flag manually
  P1IE &= ~0x02;  
  
  RXReady = 1;
//  TACCR0 = 0;   
//  TACCR0 = Bitime_5;
  TACCR0 = 0x01;   
  TACCTL0 =  CM1 + CCIS0 + OUTMOD0 + CCIE;
  BitCnt = 0x8;
  
//  _BIC_SR_IRQ(LPM0_bits);                      //wake up CPU (clear LPM0 bits from SR)
}

#pragma vector = PORT2_VECTOR
__interrupt void PORT2_ISR (void)
{
  P2IFG &= ~0x40;         //clear flag manually
  _BIC_SR_IRQ(LPM0_bits);                      //wake up CPU (clear LPM0 bits from SR)
}

#pragma vector = TIMERA0_VECTOR
__interrupt void TIMERA0_ISR (void)
{ 
  P1OUT |= 0x01;
  if (RXReady == 1)
  {
    P1OUT |= 0x04;
    if (BitCnt == 0x08) TACCR0 = Bitime;
    RXData |= (P1IN & 0x02);
    if (BitCnt > 1)     RXData = RXData << 1;
    BitCnt --;
    if (BitCnt == 0)
    {
      TACCTL0 &= ~CCIE;
//      _BIC_SR_IRQ(LPM0_bits);
      RXReady = 0;
      P1IE = 0x02;
      P1IFG &= ~0x02;
      RXData = RXData >> 1;
      P2IE |= 0x40;
    }
    P1OUT &= ~0x04;
  }
    
  else
  {  
    // TX Routine
    if ( BitCnt == 0)
    {
      TACCTL0 &= ~CCIE;			// All bits transmitted, disable interrupt
      P1OUT |= 0x08;
    }
    else
    {
//      P1OUT &= ~0x08;      
      if (TXData & 0x01)		// if least significant bit of TXData is high, then set the output bit high correspondingly??
      {
        P1OUT |= 0x08;
      }
      else P1OUT &= ~0x08;
      TXData = TXData >> 1;		// shift the bit to the right by one bit (onto the next bit)
      BitCnt --;				// update the bit counter
    }
  }
  P1OUT &=~0x01;
  
}
