#include <msp.h>
/* Standard Includes */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>



#include "ads1292.h"

volatile uint32_t RX_DATA = 0;
volatile uint16_t SPI_TX_BUF[10];
extern volatile uint32_t SPI_RX_COUNT;
extern volatile uint32_t SPI_RX_BUFF[8]={};
extern volatile bool ads1292dataReceived;
extern volatile bool Read_1292;

void ads1292_Init(void){


    /*DEFINE GPIO PINS DIRECTION*/
    gpioPinsDirection();
    /*INITIALIZE THE DATA READY*/
    initAds1292rDrdy();
    /*CLOCK CONFIGURATION*/
    clockSystem();
    /*SPI PINS CONFIGURATION*/
    ads1292rSpiBusConf();
    /*SPI DEVICE FREQUENCY CONFIGURATION*/
    ads1292rSPI();

    /*ADS1292R RESET*/
    ads1292rReset();
    /*ADS1292R DISABLE START*/
    ads1292rStartDisable();
    /*ADS1292R ENABLE START*/
    ads1292rStartEnable();
    /*ADS1292r HARD STOP*/
    ads1292rHardStop();
    /*START DATA CONVERTION COMMAND*/
    startDataConvertionCommand();
    /*STOP DATA CONVERTION COMMAND*/
    stopDataConvertionCommand();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(50);
    /*STOP READ DATA CONTINUOUS*/
    stopContinuousConvertionCommand();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(300);

    /*ADS1292R REGISTER WRITE*/
    ads1292rRegisterWrite(ADS1292_REG_CONFIG1, 0b00000010);     /*SET SAMPLING RATE TO 500 SPS*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_CONFIG2, 0b10100000);       /*LEAD-OFF COMP OFF, TEST SIGNAL DISABLE*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_LOFF, 0b00010000);          /*LEAD-OFF DEFAULTS*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_CH1SET, 0b01000000);          /*CH1 ENABLE, GAIN, CONNECTED TO ELECTRODE*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_CH2SET, 0b01100000);          /*CH2 ENABLE, GAIN, CONNECTED TO ELECTRODE*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_RLDSENS, 0b00101100);         /*RLD SETTINGS:FMOD/16, RLD ENABLE, RLD INPUT FROM CH2 ONLY*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_LOFFSENS, 0x00);                /*LOFF SETTINGS: ALL DISABLED*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_RESP1, 0b11110010);         /*RESPIRATION: MOD/DEMOD TURNED ONLY, PHASE 0*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    ads1292rRegisterWrite(ADS1292_REG_RESP2, 0b00000011);         /*RESPIRATION: CALIB OFF, RESPIRATION FREW DEFAULTS*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    /*START READ DATA CONTINUOUS*/
    startContinuousConvertionCommand();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(10);
    /*ADS1292R ENABLE START*/
    ads1292rStartEnable();

}


/*SET GPIO PINS DIRECTION*/
void gpioPinsDirection(void){
    P2->SEL0 |= ADS1292_PWDN  | ADS1292_START  ;
    P2->SEL1 |= ADS1292_PWDN  | ADS1292_START  ;
    /*DEFINE LIKE OUTPUT*/
    P2->DIR  |= ADS1292_PWDN  | ADS1292_START;
    /*SET THIS PORTS LIKE PERIPHERALS*/
    P3->SEL0 |= ADS1292_CS;
    P3->SEL1 |= ADS1292_CS;
    /*DEFINE LIKE OUTPUT*/
    P3->DIR  |= ADS1292_CS;
}

/*CLOCK SYSTEM CONTROL*/
void clockSystem(void){
    CS->KEY  = CS_KEY_VAL;                             /*UNLOCK CS MODULE ACCESS*/
    CS->CTL0 = CS_CTL0_DCORSEL_4;                      /*SELECT DCO = 24MHz*/
    CS->CTL1 = CS_CTL1_DIVS_3 |                        /*SOURCE DIV = f(SMCLK)/8 = 3MHz*/
               CS_CTL1_SELA_2 |                        /*SELECT ACLK  = REFOCLK*/
               CS_CTL1_SELS_3 |                        /*SELECT SMCLK = DCOCLK*/
               CS_CTL1_SELM_3;                         /*SELECT MCLK  = DCOCLK*/
    CS->KEY = 0x00;                                    /*LOCK CS MODULE ACCESS*/
    /*ADJUST CLOCK TO 1MHZ*/
}

/*PORT SPI BUS CONFIGURATION*/
void ads1292rSpiBusConf(void){
    /*SET SPI OPTION SELECT*/
    P1->SEL0 |= ADS1292_MOSI | ADS1292_MISO |
                ADS1292_CLK;                           /*SET 3 PIN SPI PERIPHERAL BITS*/
    /*SET SPI OUT DIRECTION*/
    P1->DIR |=  ADS1292_MOSI | ADS1292_CLK;            /*CLOCK AND DIROUT AS OUTPUT*/
    /*CLEAR SPI OUT DIRECTION*/
    P1->DIR &= ~(ADS1292_MISO);                        /*DIN AS INPUT*/
}

/*SPI DEVICE CONFIGUATION*/
void ads1292rSPI(void){


    EUSCI_B0->CTLW0  = EUSCI_B_CTLW0_SWRST |           /*REMAIN eUSCI STATE MACHINE IN RESET*/
                       EUSCI_B_CTLW0_MST   |           /*SET AS SPI MASTER*/
                       EUSCI_B_CTLW0_SYNC  |           /*SET AS SYNCHRONOUS MODE*/
                       EUSCI_B_CTLW0_CKPH  |           /*SET CLOCK POLARITY H*/
                       EUSCI_B_CTLW0_MSB   ;           /*MSB FIRST*/

    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SSEL__ACLK;       /*ACLK*/
    EUSCI_B0->BRW = 6;                                 /*fBitClock = fBRCLK/UCBRx[~500KHz]*/
    EUSCI_B0->CTLW0 &= ~(EUSCI_B_CTLW0_SWRST);         /*CLEAR SW RESET, RESUME OPERATION*/
    EUSCI_B0->IE |= EUSCI_B_IE_RXIE;                // Enable USCI_B0 RX interrupt


}

/*ADS1292R RESET CONFIGURATION*/
void ads1292rReset(void){
   P3->OUT |= ADS1292_PWDN;                            /*RESET PIN HIGH*/
   delayADS1292R(100);                                 /*WAIT 1 mSec*/
   P3->OUT &= ~(ADS1292_PWDN);                         /*RESET PIN LOW*/
   delayADS1292R(100);                                 /*WAIT 1 mSec*/
   P3->OUT |= ADS1292_PWDN;                            /*RESET PIN HIGH*/
   delayADS1292R(100);                                 /*WAIT 1 mSec*/
}
/*ADS1292r CS ENABLE*/
void ads1292rCsEnable(void){
    P3->OUT |= ADS1292_CS;                              /*SET CS SPI TO LOW*/
}
/*ADS1292r CS DISABLE*/
void ads1292rCsDisable(void){
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(100);
    P3->OUT &= ~(ADS1292_CS);                                /*SET CS SPI TO HIGH*/
}
/*ADS1292R DISABLE START CONFIGURATION*/
void ads1292rStartDisable(void){
   //unsigned short i;
   P3->OUT &= ~(ADS1292_START);
   /*SMALL DELAY TO SETTLE*/
   delayADS1292R(20);
}
/*ADS1292R ENABLE START CONFIGURATION*/
void ads1292rStartEnable(void){
   //unsigned short i;
   P3->OUT |= ADS1292_START;
   /*SMALL DELAY TO SETTLE*/
   delayADS1292R(20);
}
/*ADS1292r HARD STOP*/
void ads1292rHardStop(void){
//  unsigned short i,j;
    P3->OUT &= ~(ADS1292_START);                            /*SET START PIN TO LOW*/
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(100);
}
/*#######################################################################################*/

/*START DATA CONVERTION COMMAND*/
void startDataConvertionCommand(void){
    ads1292rSpiCommandData(START_);                /*SET 0x08 TO THE ADS1292R*/
}

/*STOP DATA CONVERTION COMMAND*/
void stopDataConvertionCommand(void){
    ads1292rSpiCommandData(STOP_);                 /*SET 0x0A TO THE ADS1292R*/
}
/*STOP READ DATA CONTINUOUS*/
void stopContinuousConvertionCommand(void){
    ads1292rSpiCommandData(S_DATA_C);               /*SET 0x11 TO THE ADS1292R*/
}

/*START READ DATA CONTINUOUS*/
void startContinuousConvertionCommand(void){
    ads1292rSpiCommandData(R_DATA_C);              /*SET 0x10 TO THE ADS1292R*/
}

/*ADS1292R SPI COMMAND DATA*/
void ads1292rSpiCommandData(uint32_t data){
    /*ADS1292r CS DISABLE*/
    ads1292rCsDisable();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(50);
    /*ADS1292r CS ENABLE*/
    ads1292rCsEnable();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(50);
    /*ADS1292r CS DISABLE*/
    ads1292rCsDisable();
    while(!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG));
    EUSCI_B0->TXBUF = data;
    while(EUSCI_B0->STATW & EUSCI_B_STATW_BBUSY);
    /*ADS1292r CS ENABLE*/
    ads1292rCsEnable();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(2);
}

/*ADS1292R REGISTER WRITE*/
void ads1292rRegisterWrite(uint32_t READ_WRITE_ADDRESS, uint32_t data){

    switch(READ_WRITE_ADDRESS){
        case 1:
            data = data & 0x87;
        break;
        case 2:
            data = data & 0xFB;
            data |= 0x80;
        break;
        case 3:
            data = data & 0xFD;
            data |= 0x10;
        break;
        case 7:
            data = data & 0x3F;
        break;
        case 8:
            data = data & 0x5F;
        break;
        case 9:
            data |= 0x02;
        break;
        case 10:
            data = data & 0x87;
            data |= 0x01;
        break;
        case 11:
            data = data & 0x0F;
        break;
        default:
        break;
    }
    SPI_TX_BUF[0] = READ_WRITE_ADDRESS | W_REG;
    SPI_TX_BUF[1] = 0;                                  /*WRITE SINGLE BYTE*/
    SPI_TX_BUF[2] = data;                               /*WRITE SINGLE BYTE*/
    /*ADS1292r CS DISABLE*/
    ads1292rCsDisable();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(2);
    /*ADS1292r CS ENABLE*/
    ads1292rCsEnable();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(2);
    /*ADS1292r CS DISABLE*/
    ads1292rCsDisable();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(2);

    while(!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG));      /*POLLING TO SEE IF THE TX BUFFER IS READY?*/
    EUSCI_B0->TXBUF = SPI_TX_BUF[0];                  /*SEND THE FIRST DATA TO THE TX BUFFER*/

    while(!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG));      /*POLLING TO SEE IF THE TX BUFFER IS READY?*/
    EUSCI_B0->TXBUF = SPI_TX_BUF[1];                  /*SEND THE FIRST DATA TO THE TX BUFFER*/

    while(!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG));      /*POLLING TO SEE IF THE TX BUFFER IS READY?*/
    EUSCI_B0->TXBUF = SPI_TX_BUF[2];                  /*SEND THE FIRST DATA TO THE TX BUFFER*/
    /*SMALL DELAY TO SETTLE*/
    //printf("TXBUFF = 0x%08X\n",EUSCI_B0->TXBUF);
    delayADS1292R(2);
    /*ADS1292r CS ENABLE*/
    ads1292rCsEnable();
    /*SMALL DELAY TO SETTLE*/
    delayADS1292R(2);
}

void initAds1292rDrdy(void){
    /*P2.5 AS IO*/
   // P2->SEL0 &= ~(ADS1292_DRDY);
    /*P2.5 AS INPUT*/
    P2->DIR &= ~(ADS1292_DRDY);
    /**/
    P2->REN |= ADS1292_DRDY;
    /*P2.5 PULL OUT*/
    P2->OUT |= ADS1292_DRDY;
    /*P2.5 HIGH TO INTERRUPT*/
    P2->IES |= ADS1292_DRDY;
    /*P2.5 CLEAR FLAG*/
    P2->IFG &= ~(ADS1292_DRDY);
    /*P2.5 ENABLE INTERRUPT*/
    P2->IE  &= ~(ADS1292_DRDY);
}

void enableAds1292rDrdy(void){
    /*P2.5 CLEAR FLAG*/
    P2->IFG &= ~(ADS1292_DRDY);
    /*P2.5 ENABLE INTERRUPT*/
    P2->IE  |= ADS1292_DRDY;
}

void disableAds1292rDrdy(void){
    /*P2.5 CLEAR FLAG*/
    P2->IFG &= ~(ADS1292_DRDY);
    /*P2.5 CLEAR INTERRUPT*/
    P2->IE  &= ~(ADS1292_DRDY);
}

void delayADS1292R(unsigned msec){
    unsigned  c;
    for(c=0;c<msec;c++);
}

/*PORT x INTERRUPT SERVICE ROUTINE*/
void PORT2_IRQHandler(void){
    if(P2->IFG &= ADS1292_DRDY){
        /*CLEAR INTERRUPT FLAG i.e DATA DRDY INTERRUPT STATUS*/
        P2->IFG &= ~(ADS1292_DRDY);
        /*DUMMY READ*/
        SPI_RX_COUNT = EUSCI_B0->RXBUF;
        SPI_RX_COUNT = 0;
        EUSCI_B0->TXBUF = 0;
        EUSCI_B0->IE |= EUSCI_B_IE_RXIE;
    }
}



/*SPI INTERRUPT SERVICE ROUTINE*/
void EUSCIB0_IRQHandler(void){
     RX_DATA = EUSCI_B0->RXBUF;
     if (Read_1292 == true){
         printf("data: %d\n",RX_DATA);
         /*STORE THE RESULTS IN ARRAY*/
         SPI_RX_BUFF[SPI_RX_COUNT++] = RX_DATA;
         if(SPI_RX_COUNT > 8){
             ads1292dataReceived = true;
             Read_1292 = false;
             EUSCI_B0->IE &= ~(EUSCI_B_IE_RXIE);
         }else{
             EUSCI_B0->TXBUF = 0;
         }
     }

}

