/*
 * Adc_onchip.c
 *
 *  Created on: Mar 12, 2018
 *      Author: tm
 */



#include "system.h"

#include "user_io.h"
#include "uartstdio.h"
#include "adc_onchip.h"
#include "driverlib/adc.h"

uint32_t  adc_data[12];

//ADC Definitions
#define ADC_SEQ_NUMBER          0       // make this 1 for 4 channel
#define ADC_PRIORITY_LEVEL      0
#define ADC0_OVERSAMPLE_RATE    64  //Must be exponent of two, no more then 64


void adc_onchip_init(void)
{

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ROM_ADCSequenceDisable(ADC0_BASE, 1);                   //Configure ADC0

    ROM_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_5);        // pressure sensor AIN6
    ROM_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_7);        // battery AIN4

    ROM_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4);        // humidity  AIN10

    ROM_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0);        // battery AIN16
    ROM_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_1);        // battery AIN17

    ROM_ADCSequenceConfigure(ADC0_BASE, ADC_SEQ_NUMBER, ADC_TRIGGER_PROCESSOR, ADC_PRIORITY_LEVEL);

    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 0, ADC_CTL_CH4);     // AIN4 is PD7  VBAT
    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 1, ADC_CTL_CH6);     // AIN6 is PD5  VPRESS
    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 2, ADC_CTL_CH10);    // AIN10 is PB4 VHUM
    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 3, ADC_CTL_CH16);    // AIN16 is PK0 VWATER
    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 4, ADC_CTL_CH17);    // AIN17 is PK1 VTEMP
    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 5, ADC_CTL_CH4);     // AIN4 is PD7  VBAT
    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 6, ADC_CTL_CH4);     // AIN4 is PD7  VBAT
    ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQ_NUMBER, 7, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END);  // chip temperature, final step: give int, stop

    ROM_ADCSequenceEnable(ADC0_BASE, ADC_SEQ_NUMBER);                             // Since sample sequence 1 is now configured, it must be enabled.

    // Clear the interrupt status flag.  This is done to make sure the
    // interrupt flag is cleared before we sample.
    ROM_ADCIntClear(ADC0_BASE, ADC_SEQ_NUMBER);


}

uint32_t * read_all_adc(void)
{
    unsigned long int  count = 0;

    ROM_ADCProcessorTrigger(ADC0_BASE, ADC_SEQ_NUMBER);     // Trigger the ADC conversion.

    while(! ROM_ADCIntStatus(ADC0_BASE, ADC_SEQ_NUMBER, false))  // Wait for conversion to be completed.
    {
        if(count++ > 100000)
        {
            // Thom TODO - handle hang case (print something)
            uprintf("\r\nhang in read_all_adc() waiting for ADC complete\r\n");
        }
    }

    ROM_ADCIntClear(ADC0_BASE, ADC_SEQ_NUMBER);             // Clear the ADC interrupt flag.

    ROM_ADCSequenceDataGet(ADC0_BASE, ADC_SEQ_NUMBER, adc_data);        // Read ADC Value.

    return(adc_data);

}

uint16_t read_adc(uint32_t chan)
{
    uint32_t pui32ADC0Value[1];

    // Need to turn on PM6 for battery voltage
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_6); // PM6, pin 83
    ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0xFF);    // Set (turns on FET which provides Vbat to a voltage divider
    ROM_SysCtlDelay(MILLISECOND * 200);  // timeconstant of 500K resistor divider with 0.22 uF cap is about 100msec

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);     // The ADC0 peripheral must be enabled for use.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    ROM_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_7);        // Select the analog ADC function for these pins.

    // Enable sample sequence 3 with a processor signal trigger.  Sequence 3
    // will do a single sample when the processor sends a signal to start the
    // conversion.  Each ADC module has 4 programmable sequences, sequence 0
    // to sequence 3.  This example is arbitrarily using sequence 3.
    ROM_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

    //
    // Configure step 0 on sequence 3.  Sample channel 0 (ADC_CTL_CH0) in
    // single-ended mode (default) and configure the interrupt flag
    // (ADC_CTL_IE) to be set when the sample is done.  Tell the ADC logic
    // that this is the last conversion on sequence 3 (ADC_CTL_END).  Sequence
    // 3 has only one programmable step.  Sequence 1 and 2 have 4 steps, and
    // sequence 0 has 8 programmable steps.  Since we are only doing a single
    // conversion using sequence 3 we will only configure step 0.  For more
    // information on the ADC sequences and steps, reference the datasheet.
    //
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE |
                             ADC_CTL_END);

    ROM_ADCHardwareOversampleConfigure(ADC0_BASE,64);   // NEW, average 64 samples

    ROM_ADCSequenceEnable(ADC0_BASE, 3);            // Since sample sequence 3 is now configured, it must be enabled.

    ROM_ADCIntClear(ADC0_BASE, 3);          // Clear the interrupt status flag

    ROM_ADCProcessorTrigger(ADC0_BASE, 3);      // Trigger the ADC conversion.

    while(! ROM_ADCIntStatus(ADC0_BASE, 3, false))      // Wait for conversion to be completed.
    {
    }

    ROM_ADCIntClear(ADC0_BASE, 3);      // Clear the ADC interrupt flag.

    ROM_ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);       // Read ADC Value.

    // DEBUG
    //uprintf("AIN0 = %4d\r", pui32ADC0Value[0]);        // Display the AIN0 (PE3) digital value on the console.

    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_6); // PM6, pin 83
    ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0x00);    // Clear - turn off battery voltage

    return(pui32ADC0Value[0]);
}

uint16_t read_adc_temperature(void)
{
    uint32_t ADCValues[1];
    uint32_t TempValueC;

    ROM_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

    ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_TS | ADC_CTL_IE |
                             ADC_CTL_END);

    ROM_ADCHardwareOversampleConfigure(ADC0_BASE,64);   // NEW, average 64 samples
    ROM_ADCSequenceEnable(ADC0_BASE, 3);
    ROM_ADCIntClear(ADC0_BASE, 3);
    ROM_ADCProcessorTrigger(ADC0_BASE, 3);

    while(!ROM_ADCIntStatus(ADC0_BASE, 3, false))           // Wait for conversion to be completed.
    {
    }

    ROM_ADCIntClear(ADC0_BASE, 3);                          // Clear the ADC interrupt flag.
    ROM_ADCSequenceDataGet(ADC0_BASE, 3, ADCValues);        // Read ADC Value.

    TempValueC = (uint32_t)(147.5 - ((75.0*3.3 *(float)ADCValues[0])) / 4096.0);

    return((uint16_t)TempValueC);

}


