//*****************************************************************************
//
// Functions to initialize and control MSP432 peripherals
//
// the following symbols are used in the C code
//
// MSP432 code symbol   MSP432 schematic net    FPGA schematic net
// ADC_DRDY             ADC_DRDY                ADC_DRDY
// ADC_RESET            FPGA0                   *_RESET
// ADC_PWDN             FPGA1                   *_PWDN
// SYNC_MASK            FPGA2                   *_SYNC
// SIGGEN_SRC           FPGA3                   MLS_SRC
// CAL_SEL              FPGA4
// MLS_START            FPGA5
//                      FPGA6
//                      FPGA7
//                      FPGA8
//                      FPGA9
// POWER_GOOD           FPGA10                  PG*
// FPGA_DONE            FPGADONE                DONE
// FPGAINT1             FPGAINT1                MOD_INT1
// FPGAINT2             FPGAINT2                MOD_INT2
// FPGAINT3             FPGAINT3                REF_STAT_INT
// MOD_AIN2SEL          MOD_AIN2SEL             MOD_VOFFSDAC
// PLL_LOCK             PLL_LOCK                PLL_LOCK
// REF_AIN2SEL          REF_AIN2SEL             REF_VOFFSDAC
// TIMESTAMP            TIMESTAMP               TIMESTAMP
//
//*****************************************************************************

#include "common.h"
#include "msp432.h"

extern void adcReadyFxn(uint_least8_t index);
extern void tempReadyFxn(uint_least8_t index);
extern void tempCallBack(I2C_Handle, I2C_Transaction *, bool);
extern const I2C_Config I2C_config[];

/* Project Global Variables */

/* File Global Variables */
uint8_t  sendMasterTxData = TEMP_ADDR;

int init_CLK(void) {
    uint32_t g_ui32SysClock;

    SysCtlMOSCConfigSet(SYSCTL_MOSC_HIGHFREQ);   // configure main oscillator for frequency > 10MHz
    
#if SYSCLKFREQ > 25000000                        // if target system frequency is > than OSC frequency, use PLL
    g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | // set system clock to run from the PLL at SYSCLKFREQ MHz
                                        SYSCTL_OSC_MAIN |
                                        SYSCTL_USE_PLL |
                                        SYSCTL_CFG_VCO_160), SYSCLKFREQ);
#elif SYSCLKFREQ == 25000000
    g_ui32SysClock = SysCtlClockFreqSet(SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_OSC, SYSCLKFREQ);
    HWREG(SYSCTL_RSCLKCFG) = 0x23300000;         // correct SysCtlClockFreqSet() bug which improperly sets OSCSRC to PIOSC
#else
    g_ui32SysClock = SysCtlClockFreqSet(SYSCTL_OSC_INT | SYSCTL_USE_OSC, SYSCLKFREQ);
#endif  //SYSCLKFREQ

    return (g_ui32SysClock);                     // return the system clock frequency (in Hz) for peripheral initialization
}

//******************************************************************************
//******************************************************************************
int init_GPIO(void) {
    GPIO_init();                                 // call TI GPIO driver initialization routine

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // enable the GPIO peripherals that are used
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);

    GPIO_setConfig(TEMP_DRDY, GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_FALLING); // configure /TEMP_DRDY input as an input
                                                 // with interrupt trigger on falling edge
    GPIO_setCallback(TEMP_DRDY, tempReadyFxn);   // register the /TEMP_DRDY ISR

    return 0;
}

//******************************************************************************
// initialize UART 0 for terminal output at 115200 baud
//******************************************************************************
int init_term_UART(uint32_t g_ui32SysClock) {
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    /* Configure the GPIO Port A for UART 0 */
    MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
    MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
    MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    /* Configure the UART for 115200 bps 8-N-1 format */
    UARTStdioConfig(0, 115200, g_ui32SysClock);

    return 0;
}

//******************************************************************************
/* This function sets up UDMA Channel Control Structures for TX */
//******************************************************************************
void ConfigureuDMATX(void)
{
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))){}

    MAP_uDMAEnable();

    MAP_uDMAControlBaseSet(pui8ControlTable);

    MAP_uDMAChannelAssign(UDMA_CH23_I2C5TX);

    MAP_uDMAChannelAttributeDisable(UDMA_CH23_I2C5TX, UDMA_ATTR_USEBURST |
                                    UDMA_ATTR_ALTSELECT |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);

    MAP_uDMAChannelControlSet(UDMA_CH23_I2C5TX | UDMA_PRI_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE |
                              UDMA_ARB_1);

    MAP_uDMAChannelTransferSet(UDMA_CH23_I2C5TX | UDMA_PRI_SELECT,
                               UDMA_MODE_AUTO, (void *)&sendMasterTxData,
                               (void *)&I2C5->MDR, 1);

    MAP_uDMAChannelEnable(UDMA_CH23_I2C5TX);
}

//******************************************************************************
// initialize I2C5 for temperature sensor
//******************************************************************************
int init_temp_I2C(uint32_t g_ui32SysClock) {
    I2C_Params      i2cParams;
    I2CMSP432E4_HWAttrs *hwattrs;

    I2C_init();                                  // call TI I2C driver initialization routine

    I2C_Params_init(&i2cParams);                 // create I2C for usage
    i2cParams.bitRate = TEMPERATURE_I2C_MAXBITRATE;
    i2cParams.transferMode = I2C_MODE_CALLBACK;
    i2cParams.transferCallbackFxn = tempCallBack;

    tempI2C = I2C_open(TEMPERATURE_I2C, &i2cParams);

    hwattrs = (I2CMSP432E4_HWAttrs *)I2C_config[TEMPERATURE_I2C].hwAttrs;
    I2CMasterInitExpClk(hwattrs->baseAddr, g_ui32SysClock, true); // configure I2C clock for Fast mode (400kHz)

    if (tempI2C == NULL) {
        return (-1);
    }
    else {
        return 0;
    }
}

//******************************************************************************
// Function to enable interrupts used by the application
//******************************************************************************
void int_enable(void) {

    GPIO_clearInt(TEMP_DRDY);                    // clear any pending TMP117 /DRDY interrupts
    GPIO_enableInt(TEMP_DRDY);                   // TMP117 /DRDY interrupt enable to start capturing data on sample trigger

    return;
}

void int_disable(void) {
    GPIO_disableInt(TEMP_DRDY);

    return;
}
