/*
 * I2C.c
 *
 *  Created on: Jan 31, 2018
 *      Author: biza
 */

#include "msp.h"
#include "I2C.h"


/* IRQHandler */
static volatile uint8_t * rtx_data;
static volatile int8_t status;

/*I2C MASTER CONFIGURATION PARAMETER*/
void I2C_setupDevice(void){
    /*SET SWRST*/
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SWRST;                 /*SOFTWARE RESET ENABLE*/

    /*INITIALIZE EUSCI_B REGISTERS  */
    EUSCI_B0->CTLW0 = EUSCI_B_CTLW0_SWRST |                 /*REMAIN EUSCI IN RESET MODE*/
                      EUSCI_B_CTLW0_MODE_3 |                /*I2C MODE*/
                      EUSCI_B_CTLW0_MST |                   /*MASTER MODE*/
                      EUSCI_B_CTLW0_SYNC |                  /*SYNC MODE*/
                      EUSCI_B_CTLW0_SSEL__SMCLK;            /*SMCLK*/
    /*CONFIGURE PORTS*/
    I2C_PORT();
    /*RESET SWRST*/
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SWRST;                 /*SOFTWARE RESET ENABLE*/
    /*ENABLE INTERRUPT*/
    I2C_enableInterrupt();
}

/*CONFIGURE I2C PIN PORT*/
void I2C_PORT(void){
    I2C_PxSEL0 |= I2C_SCL | I2C_SDA;                         /*CONFIGURE I2C_SCL(P6.5) & I2C_SDA(P6.4)*/
    I2C_PxSEL1 &= ~(I2C_SCL | I2C_SDA);                      /*RELEASE I2C_SCL(P6.5) & I2C_SDA(P6.4)*/
}

/*CONFIGURE I2C*/
void I2C_init(void){
/*INITIALIZE  EUSCI_B0 AND I2C MASTER TO COMUNICATE  WITH SLAVE DEVICE*/
    I2C_setupDevice();
}
/*ENABLE I2C MODULE TO START OPERATION*/
void I2C_enableInterrupt(void){
    EUSCI_B0->IE |= EUSCI_B_IE_BCNTIE |                     /*BYTE COUNT INTERRUPT ENABLE*/
                    EUSCI_B_IE_NACKIE |                     /*NOT-ACKNOWLEDGE INTERRUPT ENABLE*/
                    EUSCI_B_IE_TXIE0  |                     /*TRANSMIT INTERRUPT ENABLE 0*/
                    EUSCI_B_IE_RXIE0;                       /*RECEIVE INTERRUPT ENABLE 0*/

    /*ENABLE EUSCI_B0 INTERRUPT IN NVIC MODULE*/
    NVIC->ISER[0] = 1 << ((EUSCIB0_IRQn) & 31);

}

void I2C_frequency(void){
    EUSCI_B0->CTLW0 |=  EUSCI_B_CTLW0_SWRST;                /*SOFTWARE RESET ENABLE*/
    EUSCI_B0->BRW = 30;                                     /*BAUDERATE = SMCLK/30=100Khz*/
    EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;                /*SOFTWARE RESET RELEASED FOR OPERATION*/
    /*ENABLE INTERRUPT*/
    I2C_enableInterrupt();

}

void I2C_byteToProcess(uint8_t counter){
    EUSCI_B0->CTLW0 |=  EUSCI_B_CTLW0_SWRST;                /*SOFTWARE RESET ENABLE*/
    EUSCI_B0->TBCNT &= ~(EUSCI_B_TBCNT_TBCNT_MASK);         /*RESET COUNT TRESHOLD REGISTER*/
    EUSCI_B0->TBCNT = counter;                               /*NUMBER OF BYTES TO BE RECEIVED*/
    EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;                /*SOFTWARE RESET RELEASED FOR OPERATION*/
    /*ENABLE INTERRUPT*/
    I2C_enableInterrupt();
}

void I2C_setslave(uint8_t address, uint8_t r_w){
    /*SPECIFY SLAVE ADDRESS FOR I2C*/
    EUSCI_B0->I2CSA &= ~(EUSCI_B_I2CSA_I2CSA_MASK);         /*RESET SLAVE ADDRESS REGISTERS*/
    EUSCI_B0->I2CSA = address;                              /*I2C SLAVE ADRESS*/

    if(r_w){                                                /*READ*/
        EUSCI_B0->CTLW0 &= ~(EUSCI_B_CTLW0_TR);             /*RECEIVER*/
    }else{                                                  /*WRITE*/
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;                /*TRANSMITER*/
    }
}

int I2C_status(void){
    /*LOCAL DECLARATION*/
    int8_t oldStatus = status;
    /*PROGRAM STATEMENT*/
    status = 0;
    return oldStatus;
}

void I2C_setMode(void){
    EUSCI_B0->CTLW0 = (EUSCI_B0->CTLW0 & (~EUSCI_B_CTLW0_TR))|
                      EUSCI_B_CTLW0_TR ;
}

/*READ DATA FROM SENSOR*/
int I2C_readWrite(uint8_t r_w, uint8_t address, uint8_t *data, uint8_t length){

    while((EUSCI_B0->STATW & EUSCI_B_STATW_BBUSY));            /*WAIT UNTIL I2C BUS IS AVALIABLE*/
    rtx_data = data;
    status = 0;
    I2C_byteToProcess(length);                                 /*SET THE NUMBER OF BYTES TO SET*/
    I2C_setslave(address,r_w);                                 /*SET THE SLAVE ADDRESS IN WRITE OR READ MODE*/
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;                    /*SEND I2C START SIGNAL*/
    /*IRQHANDLER*/
    __sleep();
    return I2C_status();                                       /*RETURN THE NUMBER OF BYTES PROCESSED*/
}
/*WRITE DATA TO SENSOR*/
int I2C_write(uint8_t address, uint8_t *data, uint8_t length){
    return I2C_readWrite(I2C_W, address, data, length);
}
/*READ DATA FROM SENSOR*/
int I2C_read(uint8_t address, uint8_t *data, uint8_t length){
    return I2C_readWrite(I2C_R, address, data, length);
}

/*INTERRUPT SERVICE ROUTINE*/
void EUSCIB0_IRQHandler(void){

    /*TRANSMIT*/
    if(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0){
        /*HERE IS INCREMENTED*/
        EUSCI_B0->TXBUF = rtx_data[(EUSCI_B0->STATW & EUSCI_B_STATW_BCNT_MASK)>>EUSCI_B_STATW_BCNT_OFS];
        EUSCI_B0->IFG &= ~(EUSCI_B_IFG_TXIFG0);


    }
    /*RECEIVE*/
    if(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0){

        EUSCI_B0->IFG &= ~(EUSCI_B_IFG_RXIFG0);
        /*HERE IT'S STUCK AT NUMBER  OF BYTES TO PROCESSED*/
        rtx_data[(EUSCI_B0->STATW & EUSCI_B_STATW_BCNT_MASK)>>EUSCI_B_STATW_BCNT_OFS] = EUSCI_B0->RXBUF;

    }
    /*NOT-ACKNOWLEDGE RECEIVED*/
    if (EUSCI_B0->IFG & EUSCI_B_IFG_NACKIFG) {

            EUSCI_B0->IFG &= ~ (EUSCI_B_IFG_NACKIFG);
            /*I2C STOP CONDITION*/
            EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;
            status = I2C_ERR;
            __low_power_mode_off_on_exit();
   }

    /*BYTE COUNTER*/
    if (EUSCI_B0->IFG & EUSCI_B_IFG_BCNTIFG) {

            EUSCI_B0->IFG &= ~(EUSCI_B_IFG_BCNTIFG);
            status = EUSCI_B0->TBCNT & EUSCI_B_TBCNT_TBCNT_MASK;
            __low_power_mode_off_on_exit();
    }
}


