/**************************************************************************************************
*  Filename:       AFE4404.c
*  Revised:        $Date: 2015-08-10 17:22:05 -0800 (Mon, 10 Aug 2015) $
*  Revision:       $Revision: 42106 $
*
*  Description:    This file contains the drivers for the TI AFE4404.
*
*  Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*    Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/



/*********************************************************************
 * INCLUDES
 */
#include <string.h>
#include <math.h>

#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/pin/PINCC26XX.h>
#include "board.h"
#include "AFE4404.h"
#include "ActivityMonitor.h"
#include "am_i2c.h"

#define delay_us(x)         __delay_cycles(48 * x)           // 1us delay with 48MHz clock
#define delay_ms(x)         Task_sleep( ((x) * 1000) / Clock_tickPeriod )

/*********************************************************************
 * LOCAL VARIABLES
 */

uint8_t txBuf[4];
uint8_t rxBuf[3];

/*********************************************************************
 * @fn      AFE4404_Init
 *
 * @brief   Initialiaze and set default values to the AFE.
 *
 * @param   none
 *
 * @return  none
 */
void AFE4404_Init(void)
{
    PIN_setOutputValue(pinGpioHandle, Board_AFE_RESETZ, 1);

    // Run prelim diagnostics check
    AFE4404_Trigger_HWReset();
    while (AFE4404_Diagnostics_Check());

    // AFE4404 device reset and default initialization
    AFE4404_Enable_HWPDN();
    AFE4404_Disable_HWPDN();
    AFE4404_Trigger_HWReset();
    AFE4404_Reg_Init();
}

/*********************************************************************
 * @fn      AFE4404_Enable_HWPDN
 *
 * @brief   Enter hardware power-down mode of the AFE4404.
 *
 * @param   none
 *
 * @return  none
 */
void AFE4404_Enable_HWPDN (void)
{
    PIN_setOutputValue(pinGpioHandle, Board_AFE_RESETZ, 0);
    delay_ms(10);       // ~10ms delay
}

/*********************************************************************
 * @fn      AFE4404_Disable_HWPDN
 *
 * @brief   Disable hardware power-down mode of the AFE4404.
 *
 * @param   none
 *
 * @return  none
 */
void AFE4404_Disable_HWPDN (void)
{
//    PIN_setOutputValue(PINhandle, Board_AFE_RESETZ, 1);
    PIN_setOutputValue(pinGpioHandle, Board_AFE_RESETZ, 1);
    delay_ms(10);       // ~10ms delay
}

/*********************************************************************
 * @fn      AFE4404_Trigger_HWReset
 *
 * @brief   Reset the registers of the AFE4404.
 *
 * @param   none
 *
 * @return  none
 */
void AFE4404_Trigger_HWReset (void)
{
    PIN_setOutputValue(pinGpioHandle, Board_AFE_RESETZ, 0);
    delay_us(30);       // ~30us  delay
    PIN_setOutputValue(pinGpioHandle, Board_AFE_RESETZ, 1);
    delay_ms(10);       // ~10 ms delay
}

/*********************************************************************
 * @fn      AFE4404_Reg_Init
 *
 * @brief   Default register configuration of the AFE4404.
 *
 * @param   none
 *
 * @return  none
 */
void AFE4404_Reg_Init(void)
{
    AFE4404_Disable_Read();
    AFE4404_Reg_Write(0x01, 80);          //AFE_LED2STC
    AFE4404_Reg_Write(0x02, 399);         //AFE_LED2ENDC
    AFE4404_Reg_Write(0x03, 800);         //AFE_LED1LEDSTC
    AFE4404_Reg_Write(0x04, 1199);        //AFE_LED1LEDENDC
    AFE4404_Reg_Write(0x05, 480);         //AFE_ALED2STC
    AFE4404_Reg_Write(0x06, 799);         //AFE_ALED2ENDC
    AFE4404_Reg_Write(0x07, 880);         //AFE_LED1STC
    AFE4404_Reg_Write(0x08, 1199);        //AFE_LED1ENDC
    AFE4404_Reg_Write(0x09, 0);           //AFE_LED2LEDSTC
    AFE4404_Reg_Write(0x0A, 399);         //AFE_LED2LEDENDC
    AFE4404_Reg_Write(0x0B, 1279);        //AFE_ALED1STC
    AFE4404_Reg_Write(0x0C, 1598);        //AFE_ALED1ENDC
    AFE4404_Reg_Write(0x0D, 408);         //AFE_LED2CONVST
    AFE4404_Reg_Write(0x0E, 1467);        //AFE_LED2CONVEND
    AFE4404_Reg_Write(0x0F, 1476);        //AFE_ALED2CONVST
    AFE4404_Reg_Write(0x10, 2535);        //AFE_ALED2CONVEND
    AFE4404_Reg_Write(0x11, 2544);        //AFE_LED1CONVST
    AFE4404_Reg_Write(0x12, 3603);        //AFE_LED1CONVEND
    AFE4404_Reg_Write(0x13, 3612);        //AFE_ALED1CONVST
    AFE4404_Reg_Write(0x14, 4671);        //AFE_ALED1CONVEND
    AFE4404_Reg_Write(0x15, 401);         //AFE_ADCRSTSTCT0
    AFE4404_Reg_Write(0x16, 407);         //AFE_ADCRSTENDCT0
    AFE4404_Reg_Write(0x17, 1469);        //AFE_ADCRSTSTCT1
    AFE4404_Reg_Write(0x18, 1475);        //AFE_ADCRSTENDCT1
    AFE4404_Reg_Write(0x19, 2537);        //AFE_ADCRSTSTCT2
    AFE4404_Reg_Write(0x1A, 2543);        //AFE_ADCRSTENDCT2
    AFE4404_Reg_Write(0x1B, 3605);        //AFE_ADCRSTSTCT3
    AFE4404_Reg_Write(0x1C, 3611);        //AFE_ADCRSTENDCT3
    AFE4404_Reg_Write(0x36, 400);         //AFE_LED3LEDSTC
    AFE4404_Reg_Write(0x37, 799);         //AFE_LED3LEDENDC
    AFE4404_Reg_Write(0x1D, 39999);       //AFE_PRPCOUNT
    AFE4404_Reg_Write(0x1E, 0x000103);    //AFE_CONTROL1 TimerEN = 1; NUMAV = 2
    AFE4404_Reg_Write(0x20, 0x008003);    //AFE_TIA_SEP_GAIN (LED2) ENSEPGAIN = 1; LED2/LED3 gain = 50K
    AFE4404_Reg_Write(0x21, 0x000003);    //AFE_TIA_GAIN (LED1) LED1/LED1AMB gain = 50K
    AFE4404_Reg_Write(0x3A, 0x000000);    //AFE_DAC_SETTING_REG
    AFE4404_Reg_Write(0x22, 0x0030CF);    //LED3 - 3.125mA; LED2 - 3.125mA; LED1 - 12.5mA
    //AFE4404_Reg_Write(0x22, 0x0030DE);
    //AFE4404_Reg_Write(0x23, 0x124018);
    AFE4404_Reg_Write(0x23, 0x124218);    //DYN1, LEDCurr, DYN2, OSC, DYN3, DYN4 //0x000200); - 0x200 Osc mode //AFE_CONTROL2
    AFE4404_Reg_Write(0x39, 0);           //CLKDIV 100 Hz PRF
    //AFE4404_Reg_Write(0x39, 5);           //CLKDIV_PRF = 5 --> ratio = 4 // PRF = 25 Hz
    AFE4404_Reg_Write(0x32, 5471);        //AFE_DPD1STC
    AFE4404_Reg_Write(0x33, 39199);       //AFE_DPD1ENDC
    AFE4404_Enable_Read();
}

/*********************************************************************
 * @fn      AFE4404_Diagnostics_Check
 *
 * @brief   Detect a short-circuit condition of the photodiode.
 *
 * @param   none
 *
 * @return  TRUE or FALSE
 */
uint8_t AFE4404_Diagnostics_Check (void)
{
    AFE4404_Disable_Read();
    AFE4404_Reg_Write(0x23, 0x000200);  // Enable internal oscillator
    AFE4404_Reg_Write(0x1E, 0x000100);  // TIMER_EN
    AFE4404_Reg_Write(0, 4);            // DIAG_EN
    delay_ms(10);                       // ~10ms delay
    AFE4404_Enable_Read();
    return ((uint8_t) AFE4404_Reg_Read(48));    // DIAG status
}

/*********************************************************************
 * @fn      AFE4404_Reg_Write
 *
 * @brief   Write to specific register of the AFE4404.
 *
 * @param   reg_address - specified register address
 * @param   reg_data - data to be written into the register
 *
 * @return  none
 */
void AFE4404_Reg_Write(unsigned char reg_address, unsigned long reg_data)
{
    amI2cSelect(AFE4404_I2C_DEFAULT_ADDRESS);
    txBuf[0] = reg_address;
    txBuf[1] = (uint8_t) ((reg_data & 0x00FF0000) >> 16);
    txBuf[2] = (uint8_t) ((reg_data & 0x0000FF00) >> 8);
    txBuf[3] = (uint8_t) (reg_data & 0x000000FF);
    amI2cWrite(txBuf, 4);
}

/*********************************************************************
 * @fn      AFE4404_Reg_Read
 *
 * @brief   Read from specific register of the AFE4404.
 *
 * @param   reg_address - specified register address
 *
 * @return  retVal - contents of the register
 */
unsigned long AFE4404_Reg_Read(unsigned char reg_address)
{
    unsigned long retVal;
    amI2cSelect(AFE4404_I2C_DEFAULT_ADDRESS);
    txBuf[0] = reg_address;
    amI2cWriteRead(txBuf, 1, rxBuf, 3);
    retVal = (((uint32_t)rxBuf[0]) << 16) | (((uint32_t)rxBuf[1]) << 8) | ((uint32_t)rxBuf[2]);
    if(reg_address >= 0x2A && reg_address <= 0x2F)
    {
        if(retVal & 0x00200000)             // Check if ADC value is positive or negative
        {
            retVal &= 0x003FFFFF;           // Convert it to a 22-bit value
            return (retVal ^ 0xFFC00000);
        }
    }
    return retVal;
}

/*********************************************************************
 * @fn      AFE4404_Enable_Read
 *
 * @brief   Enable reading of the AFE4404 registers.
 *
 * @param   none
 *
 * @return  none
 */
void AFE4404_Enable_Read (void)
{
    AFE4404_Reg_Write(CONTROL0, 0x000001);
}

/*********************************************************************
 * @fn      AFE4404_Disable_Read
 *
 * @brief   Disable reading of the AFE4404 registers.
 *
 * @param   none
 *
 * @return  none
 */
void AFE4404_Disable_Read (void)
{
    AFE4404_Reg_Write(CONTROL0, 0x000000);
}

/*********************************************************************
*********************************************************************/
