/****************************************************************/
/* FILENAME: main.c                            		        */
/* DESCRIPTION: This program uses the MSP430F449 to read 500 	*/
/*    samples from the TLC3578 EVM board.                       */
/*    The samples are display on the LCD Screen of the HPA449.  */
/*    Refer to the .map file created by the compiler for the    */
/*    address in memory for adc_data                            */
/*    AUTHOR: T. Hendrick, Data Acquisition Products,           */
/*            Dallas Texas                                      */
/*    CREATED 2004(C) BY TEXAS INSTRUMENTS INCORPORATED.  	*/
/*    VERSION: 01 						*/
/****************************************************************/
#include <msp430x44x.h>
#include <math.h>
#include "SBLCDA2.h"

#define Resonator (0)

/***************************************************************/

#define Samples 200
#define UD_P1_C               (0xD1)
#define UD_P2_H               (0x76)

/**************** Function prototypes ***********************************/
/*                                                                      */
void init_sys(void);                /* MSP430 Initialisation routine    */
void setupClock(int);
void init_adc(void);                /* adc initialisation routine       */
void delay(int);                   /* Software delay                   */
void TX_complete(void);                /* Transmit / Receive ready         */
void RX_complete(void);                /* Transmit / Receive ready         */
void adc_convert(int);             /* Do the adc conversion            */
void adc_convertCH1(int);             /* Do the adc conversion            */
void display(void);                 /* Indicate Program complete        */
void InitializeLCD( void );
void clearDisplay( void );
void clearMajor( void );
void sortMajor( unsigned int );
void sortFloat( double );
void displaySpecial( long int );
void displayMinor( int, int );
void displayHPA449(void);
void displayTest(int, int);	
/*                                                                      */
/************************************************************************/

/************************************************************************/
/*                                                                      */
/* Global variable declarations                                         */
/*                                                                      */
/************************************************************************/

int    adc_data[Samples];        // Storage for converted data
int    adc_dataCH2[Samples];        // Storage for converted data
int    byte0, byte1, byte2, byte3, trash;

int i, j, min, max, CH = 0;
double result, value;

/************************************************************************/
/*                                                                      */
/* Local Functions                                         */
/*                                                                      */
/************************************************************************/
double display_volts(int *codes, int ct)
{
	int i;
	double sum=0, average=0;
	for (i=0;i<ct;i+=10)
	  sum += ((codes[i]*.001220703125)-10);
	average = sum/(ct/10);
	return average;
}
/************************************************************************/
/*                                                                      */
/* main() variable declarations                                         */
/*                                                                      */
/************************************************************************/
  #define   ADC_FS            0x20  //p3.5
  #define   ADC_CS            0x80  //p3.7

void main(void)
{
  setupClock(Resonator);
  init_sys();                   	// Initialise the MSP430
  init_adc();
  InitializeLCD();
  clearDisplay();
  displaySpecial(SoftBaugh);

      do {

         for(i=0; i<Samples; i++)
         {
          adc_convert(i);            // Do conversions from each channel
          delay(0);
          adc_convertCH1(i);            // Do conversions from each channel
          //displayTest(CH, i);
         }
         clearMajor();
         displaySpecial(SoftBaugh|AR);
         }

       while (1);              //
}			      	

/************************************************************/
/* Prototype - init_sys                                     */
/*                                                          */
/*  Description                                             */
/*  This prototype initialises the MSP430F149               */
/************************************************************/
void init_sys(void)
{
    /* Local function prototype         */
void setupports(void);  /* Local function prototype         */
void setupSPI(void);    /* Local function prototype         */

setupports();
setupSPI();
  _EINT();                              // Enable interrupts
}
/************************************************************/
/* Prototype - setupClock                                     */
/*                                                          */
/*  Description                                             */
/*  This prototype sets-up the XT2 oscillator and tests     */
/*  that it has settled before moving on                    */
/************************************************************/
void setupClock (int RES)
{
    switch (RES)
    {
        case  0:
          { WDTCTL = WDTPW + WDTHOLD;
            /* D=2, N=121, no mod */
            SCFQCTL=121;
            // SCFI0 = 0100 0100
            SCFI0=0x44;
            // DCOPLUS=1, XTS_FLL=0
            // XCAPXPF=00
            FLL_CTL0=0x80;
            // SMCLK=0, XT2OFF=1, SELMX=00, SELS=0, FLL_DIVX=10
            // FLL_CTL1= 0010 0010
            FLL_CTL1=0x22;
          }
          break;
        case  1:
          { WDTCTL = WDTPW + WDTHOLD;           // Stop watchdog timer
            FLL_CTL0&=XT2OFF;                    // Switch on the XT2 osc.
            FLL_CTL1|=SELM_XT2+SELS;                // Select XT2 osc. for
            // Test the osc. flag bit
            do {
                IFG1 &= ~OFIFG;            // Clear the OFIFG bit
                } while (OFIFG&IFG1);      //
          }
          break;
    }
}

/************************************************************/
/* Prototype - setupports                                   */
/*  Description                                             */
/*  This prototype sets-up the GPIO ports as appropriate    */
/************************************************************/
void setupports (void)
{
// SPI port for ADC
P3SEL = BIT3 + BIT2 + BIT1;                     // Bits 3, 2 & 1 are assigned as SPI specific pins
P3DIR = ADC_FS + ADC_CS;                           // Set the ADC_CS bit as an output
P3OUT = ADC_FS + ADC_CS;                            // De-assert ADC_CS for the adc - HIGH

//SetupInterrupts
P1IFG |= 0x00;
P1IES |= 0x40;
P1IE |= 0x40;
}

/************************************************************/
/* Prototype - setupSPI                                     */
/*                                                          */
/*  Description                                             */
/*  This prototype sets-up the P3 for communication via SPI */
/************************************************************/
void setupSPI (void)

/************************************************************/
/* System definitions                                       */
/************************************************************/
#define     SPI0en       0x40
#define     SPI1en       0x10

{
ME1 |= USPIE0;                      // Module Enable - SPI
                                    //
U0CTL &= ~SWRST;                    // Make sure the RESET bit is off
U0CTL |= CHAR + SYNC + MM;          // USART0 module operation
                                    // CHAR = 1 => 8-bit data
                                    // SYNC = 1 => SPI selected
                                    // MM = 1 => master mode,
                                    //     MSP is the master
U0TCTL |= SSEL0 + SSEL1 + STC;      // USART0 Tranmit control register
                                    // SSEL0 = 1 & SSEL1 = 1
                                    // => SMCLK is used for baud-rate generation
                                    // STC = 1 => 3-pin SPI mode selected

U0BR0  = 0x02;                      // Divide SMCLK by 4 => transfer clock
U0BR1  = 0x00;                      //
U0MCTL = 0x00;                      // Modulation control - not used. Ensure
                                    // all these bits are reset
}

/************************************************************/
/* Prototype - init_adc                                     */
/*                                                          */
/*  Description                                             */
/*  This prototype sets-up the TLV2553 ADC                  */
/************************************************************/
void init_adc (void)
{
P3OUT |= (ADC_FS);                             // Assert ADC_CS LOW
P3OUT &= ~(ADC_CS);                       // Assert ADC_CS* LOW
while ((IFG1 & UTXIFG0) == 0);
trash = U0RXBUF;
U0TXBUF = 0xA2;                     // Start SCLK to ADC

while ((IFG1 & UTXIFG0) == 0);
trash = U0RXBUF;
U0TXBUF = 0x00;                     // Start SCLK to ADC

while ((IFG1 & UTXIFG0) == 0);
trash = U0RXBUF;
U0TXBUF = 0x00;                     // Start SCLK to AD

while ((IFG1 & UTXIFG0) == 0);
trash = U0RXBUF;
U0TXBUF = 0x00;                     // Start SCLK to AD
delay(10);
P3OUT |= (ADC_CS); 		    // De-assert ADC_CS* HIGH
}

/************************************************************/
/* Prototype - delay                                        */
/*  Description                                             */
/*  This prototype gives a delay of around 1 second         */
/************************************************************/
void delay(int time)
      {
      unsigned int i;
      for (i = 0; i < time; i++);
      }

/************************************************************/
/* Prototype - convert                                      */
/*  Description                                             */
/*  This prototype does the adc conversion                  */
/************************************************************/
void adc_convert (int cnt)
{
P3OUT &= ~(ADC_CS);                             // Assert ADC_CS LOW
while ((IFG1 & UTXIFG0) == 0);
      byte0 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x00; //CH<<4;                     // Send clocks to the ADC, this shifts

while ((IFG1 & UTXIFG0) == 0);
      byte1 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x00;                     // Send clocks to the ADC, this shifts

while ((IFG1 & UTXIFG0) == 0);
      byte2 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x00;                     // Send clocks to the ADC, this shifts

while ((IFG1 & UTXIFG0) == 0);
      byte3 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x00;                     // Send clocks to the ADC, this shifts


delay(10);                                          // sampling.
//      RX_complete();
P3OUT |= (ADC_CS);                              // De-assert ADC_CS HIGH

     adc_data[cnt] = ((byte2 << 8 | byte3 )>>2 & 0x3FFF);

}

void adc_convertCH1 (int cnt)
{
P3OUT &= ~(ADC_CS);                             // Assert ADC_CS LOW
while ((IFG1 & UTXIFG0) == 0);
      byte0 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x01; //CH<<4;                     // Send clocks to the ADC, this shifts

while ((IFG1 & UTXIFG0) == 0);
      byte1 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x00;                     // Send clocks to the ADC, this shifts

while ((IFG1 & UTXIFG0) == 0);
      byte2 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x00;                     // Send clocks to the ADC, this shifts

while ((IFG1 & UTXIFG0) == 0);
      byte3 = U0RXBUF;		  // Store this data in the hi-byte variable.
      U0TXBUF = 0x00;                     // Send clocks to the ADC, this shifts

delay(10);                                          // sampling.
//      RX_complete();
P3OUT |= (ADC_CS);                              // De-assert ADC_CS HIGH

     adc_dataCH2[cnt] = ((byte2 << 8 | byte3 )>>2 & 0x3FFF);


}
void displayTest(int channel, int cnt)
{
    switch (channel)
    {

        case  0:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_ZERO);
             sortFloat(display_volts(adc_data,Samples));
            break;
        case  1:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_ONE);
             sortMajor(adc_data[cnt]);
            break;
        case  2:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_TWO);
             sortFloat(display_volts(adc_data,Samples));
            break;
        case  3:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_THREE);
             sortFloat(display_volts(adc_data,Samples));
            break;
        case  4:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_FOUR);
             sortMajor(adc_data[cnt]);
            break;
        case  5:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_FIVE);
             sortMajor(adc_data[cnt]);
            break;
        case  6:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_SIX);
             sortFloat(display_volts(adc_data,Samples));
            break;
        case  7:
             displayMinor(5,UD_P1_C);
             displayMinor(4,UD_P2_H);
             displayMinor(3,UR_ZERO);
             displayMinor(2,UR_SEVEN);
             sortFloat(display_volts(adc_data,Samples));
            break;
     }

}

#pragma vector=PORT1_VECTOR
__interrupt void CH_switch (void)
{
  _DINT();
  clearMajor();
  P1IFG &= ~BIT6;
  CH = CH + 1;
  if (CH >= 8) CH = 0;
  delay(1000);
  _EINT();
}
