#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pge.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_adc.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "driverlib/interrupt.h"

#include "inc/hw_gpio.h"
#include "driverlib/gpio.h"



#define CASE_6


static void ADC0_IntAdcSeq0Handler(void);
static void ADC0_IntAdcSeq1Handler(void);
static void ADC1_IntAdcSeq0Handler(void);
static void ADC1_IntAdcSeq1Handler(void);

void Initialize_ADCs(void)
{
  uint32_t sequence = 0;
  uint32_t pwm_module = 1;
  uint32_t temp = 0;

  /************************  ADC Module 0 ********************************/
  // Enable ADC0 peripheral with dummy read to insert a few cycles.
  SysCtlPeripheralEnable( SYSCTL_PERIPH_ADC0 );
  temp = SYSCTL_RCGC2_R;
  temp = SYSCTL_RCGC2_R;
  temp = SYSCTL_RCGC2_R;


  // Set the ADC speed.
  // SysCtlADCSpeedSet( SYSCTL_ADCSPEED_125KSPS );  LM3 Legacy Function breaks PWM's
  // ADCSpeedSet( ADC0_BASE, ADC_PC_SR_125K );  // Missing new TivaWare function.
  ADC0_PC_R = 0x01;   // Set the register directly

  // Set reference source
  ADCReferenceSet( ADC0_BASE, ADC_REF_INT );

  // Disable the hardware over-sampling
  ADCHardwareOversampleConfigure( ADC0_BASE, sequence );

  /********************** Configure Sequence 0 in ADC0    *****************/
  sequence = 0;
  ADCSequenceDisable( ADC0_BASE, sequence );

  // Set the PWM Module the sequences will be triggered from
  HWREG(ADC0_BASE + ADC_O_TSSEL) |= (pwm_module) << ((8 * sequence) + 4);

  // Assign the Sequencer to the PWM and set it's priority to the Seq #
#if defined(CASE_2) || defined(CASE_1) || defined(CASE_3) || defined(CASE_4)
  ADCSequenceConfigure( ADC0_BASE, sequence, ADC_TRIGGER_PWM0, 0 );
  ADCSequenceStepConfigure( ADC0_BASE, sequence, 0, ADC_CTL_CH20 );
  ADCSequenceStepConfigure( ADC0_BASE, sequence, 1, ADC_CTL_CH21 | (ADC_CTL_IE | ADC_CTL_END) );
#elif defined(CASE_6)
  ADCSequenceConfigure( ADC0_BASE, sequence, ADC_TRIGGER_PWM1, 0 );
  ADCSequenceStepConfigure( ADC0_BASE, sequence, 0, ADC_CTL_CH20 );
  ADCSequenceStepConfigure( ADC0_BASE, sequence, 1, ADC_CTL_CH21 | (ADC_CTL_IE | ADC_CTL_END) );
#endif
  ADCSequenceEnable( ADC0_BASE, sequence );
  ADCIntClear( ADC0_BASE, sequence );
  ADCIntRegister( ADC0_BASE, sequence, ADC0_IntAdcSeq0Handler );
  ADCIntEnable( ADC0_BASE, sequence );
  IntEnable( INT_ADC0SS0 );


  /********************** Configure Sequence 1 in ADC0    *****************/
#if defined(CASE_4)
  sequence = 1;
  ADCSequenceDisable( ADC0_BASE, sequence );

  // Set the PWM Module the sequences will be triggered from
  HWREG(ADC0_BASE + ADC_O_TSSEL) |= (pwm_module) << ((8 * sequence) + 4);

  // Assign the Sequencer to the PWM and set it's priority to the Seq #
  ADCSequenceConfigure( ADC0_BASE, sequence, ADC_TRIGGER_PWM1, 0 );
  ADCSequenceStepConfigure( ADC0_BASE, sequence, 0, ADC_CTL_CH8 );
  ADCSequenceStepConfigure( ADC0_BASE, sequence, 1, ADC_CTL_CH9 );
  ADCSequenceStepConfigure( ADC0_BASE, sequence, 2, ADC_CTL_CH3 | (ADC_CTL_IE | ADC_CTL_END) );
  ADCSequenceEnable( ADC0_BASE, sequence );
  ADCIntClear( ADC0_BASE, sequence );
  ADCIntRegister( ADC0_BASE, sequence, ADC0_IntAdcSeq1Handler );
  ADCIntEnable( ADC0_BASE, sequence );
  IntEnable( INT_ADC0SS1 );
#endif


  /************************  ADC Module 1 ********************************/
  // Enable ADC0 peripheral with dummy read to insert a few cycles.
  SysCtlPeripheralEnable( SYSCTL_PERIPH_ADC1 );
  temp = SYSCTL_RCGC2_R;
  temp = SYSCTL_RCGC2_R;
  temp = SYSCTL_RCGC2_R;


  // Set the ADC speed.
  // SysCtlADCSpeedSet( SYSCTL_ADCSPEED_125KSPS );  LM3 Legacy Function breaks PWM's
  // ADCSpeedSet( ADC0_BASE, ADC_PC_SR_125K );  // Missing new TivaWare function.
  ADC1_PC_R = 0x01;   // Set the register directly

  // Set reference source
  ADCReferenceSet( ADC1_BASE, ADC_REF_INT );

  // Disable the hardware over-sampling
  ADCHardwareOversampleConfigure( ADC1_BASE, sequence );

  /********************** Configure Sequence 0 in ADC1    *****************/
  sequence = 0;
  ADCSequenceDisable( ADC1_BASE, sequence );

  // Set the PWM Module the sequences will be triggered from
  HWREG(ADC1_BASE + ADC_O_TSSEL) |= (pwm_module) << ((8 * sequence) + 4);

  // Assign the Sequencer to the PWM and set it's priority to the Seq #
#if defined(CASE_1)
  ADCSequenceConfigure( ADC1_BASE, sequence, ADC_TRIGGER_PWM1, 0 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 0, ADC_CTL_CH8 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 1, ADC_CTL_CH9 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 2, ADC_CTL_CH3 | (ADC_CTL_IE | ADC_CTL_END) );
#elif defined(CASE_2)
  ADCSequenceConfigure( ADC1_BASE, sequence, ADC_TRIGGER_PWM0, 0 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 0, ADC_CTL_CH20 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 1, ADC_CTL_CH21 | (ADC_CTL_IE | ADC_CTL_END) );
#elif defined(CASE_3)
  ADCSequenceConfigure( ADC1_BASE, sequence, ADC_TRIGGER_PWM0, 0 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 0, ADC_CTL_CH8 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 1, ADC_CTL_CH9 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 2, ADC_CTL_CH3 | (ADC_CTL_IE | ADC_CTL_END) );
#elif defined(CASE_6)
  ADCSequenceConfigure( ADC1_BASE, sequence, ADC_TRIGGER_PWM1, 0 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 0, ADC_CTL_CH8 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 1, ADC_CTL_CH9 );
  ADCSequenceStepConfigure( ADC1_BASE, sequence, 2, ADC_CTL_CH3 | (ADC_CTL_IE | ADC_CTL_END) );
#endif
  ADCSequenceEnable( ADC1_BASE, sequence );
  ADCIntClear( ADC1_BASE, sequence );
  ADCIntRegister( ADC1_BASE, sequence, ADC1_IntAdcSeq0Handler );
  ADCIntEnable( ADC1_BASE, sequence );
  IntEnable( INT_ADC1SS0 );
}


static void ADC0_IntAdcSeq0Handler(void)
{
  ADCIntClear( ADC0_BASE, 0 );
}

static void ADC0_IntAdcSeq1Handler(void)
{
  ADCIntClear( ADC0_BASE, 1 );
}

static void ADC1_IntAdcSeq0Handler(void)
{
  ADCIntClear( ADC1_BASE, 0 );
}

static void ADC1_IntAdcSeq1Handler(void)
{
  ADCIntClear( ADC1_BASE, 1 );
}

