//*****************************************************************************
//
// This is the data acquisition module. It performs acquisition of data from
// selected channels, starting and stopping data logging, storing acquired
// data, and running the strip chart display.
//
//*****************************************************************************
/*
Notes:
12 shared analog input channels
12-bit precision ADC
Hardware averaging of up to 64 samples
As referred before the ADC has a reference of 3V.
Voltage reference selected using the VREF field in the ADCCTL register (page 1217)
J0062
PIN 21 - AN_IDS_PRESSENS_7
PIN 9 - GND
J0252
PIN 21 - AN_IDS_PRESSENS_1
PIN 9 - GND
J0042
PIN 21 - AN_IDS_PRESSENS_3
PIN 9 - GND
J0251
PIN 21 - AN_IDS_PRESSENS_4
PIN 9 - GND
J0262
PIN 21 - AN_IDS_PRESSENS_6
PIN 9 - GND
J0162
PIN 21 - AN_IDS_PRESSENS_5
PIN 9 - GND
-----------------
void ADCAcquireInit(void) // (MillisecInit) ok
void ADCAcquireStart(ProcessCallback _callback, uint32_t _period)// (called by MillisecStart)
//reading Trigger
uint32_t ADC_TriggerCollection(void) // MillisecLoop
//Data Get
void ADC0SS0Handler(void)
each ADC there are 4 sequencers with combined sequence steps of 17 (8+4+4+1).
Hence out of 24 channels any 17 can be mapped.
If all channels are required then both ADC's are required (unless dynamic changes are being sought after).
//----------------------------------------------------
uint32_t ADC_GetReading(int DataItemId)// ADC Data get for a single data read
Void ADCProcessTask(UArg arg0, UArg arg1)
void ADCAcquireStop(void) //MillisecStop
//---------------------------------
for (adc_i = 0; adc_i < MAX_ADC_DEVICES ; adc_i++)
ADC_Data[adc_i] = ADC_GetReading(adc_i);
*/
#include "ADC.h"
#include "include.h"
#include <stdbool.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <driverlib/adc.h>
#include <driverlib/rom_map.h>
#include <driverlib/interrupt.h>
#include <Drivers/I2C_Communication/Previous_Code/I2C.h>
#include <inc/hw_memmap.h>
#include <inc/hw_ints.h>
//*****************************************************************************
//
// The following defines which ADC channel control should be used for each
// kind of data item. Basically it maps how the ADC channels are connected
// on the board. This is a hardware pinmap configuration.
// Physical ADC connected channels in the TIVA
//*****************************************************************************
#define CHAN_AIR_PRESSURE_1 ADC_CTL_CH0
#define CHAN_AIR_PRESSURE_2 ADC_CTL_CH1
#define CHAN_DISPENSE_PRESSURE_1 ADC_CTL_CH2
#define CHAN_DISPENSE_PRESSURE_2 ADC_CTL_CH3
#define CHAN_DISPENSE_PRESSURE_3 ADC_CTL_CH4
#define CHAN_DISPENSE_PRESSURE_4 ADC_CTL_CH5
#define CHAN_DISPENSE_PRESSURE_5 ADC_CTL_CH6
#define CHAN_DISPENSE_PRESSURE_6 ADC_CTL_CH7
#define CHAN_DISPENSE_PRESSURE_7 ADC_CTL_CH8
#define CHAN_DISPENSE_PRESSURE_8 ADC_CTL_CH9
#define CHAN_VOCSENS ADC_CTL_CH10
#define CHAN_SPARE1 ADC_CTL_CH11
#define CHAN_SPARE2 ADC_CTL_CH12
#define CHAN_LEFT_DANCER_1 ADC_CTL_CH13
#define CHAN_LEFT_DANCER_2 ADC_CTL_CH14
#define CHAN_RIGHT_DANCER ADC_CTL_CH15
#define CHAN_DRYER_CURRENT_1 ADC_CTL_CH16
#define CHAN_DRYER_CURRENT_2 ADC_CTL_CH17
#define CHAN_DRYER_CURRENT_3 ADC_CTL_CH18
#define CHAN_3V3_FPGA ADC_CTL_CH19
/*
Connected with pull down to reg GND ADC_CTL_CH20
Connected with pull down to reg GND ADC_CTL_CH21
config as digital input from FPGA 3 ADC_CTL_CH22
config as Digital input from FPGA 3 ADC_CTL_CH23
*/
//*****************************************************************************
//
// The following maps the order that items are acquired and stored by the
// ADC sequencers. Note that 16 samples are specified, using 2 of the
// 8 sample sequencers. The current is sampled multiple times deliberately
// because that value tends to bounce around. It is sampled multiple
// times and will be averaged.
//
//*****************************************************************************
uint32_t g_pui32ADCSeq[MAX_ADC_DEVICES] =
{
CHAN_AIR_PRESSURE_1, //0
CHAN_AIR_PRESSURE_2, //1
CHAN_DISPENSE_PRESSURE_1, //2 J0252 ,PIN 21 - AN_IDS_PRESSENS_1, PIN 9 - GND
CHAN_DISPENSE_PRESSURE_2, //3 J0142 ,PIN 21 - AN_IDS_PRESSENS_2, PIN 9 - GND
CHAN_DISPENSE_PRESSURE_3, //4 J0042 ,PIN 21 - AN_IDS_PRESSENS_3, PIN 9 - GND
CHAN_DISPENSE_PRESSURE_4, //5 J0152 ,PIN 21 - AN_IDS_PRESSENS_4, PIN 9 - GND
CHAN_DISPENSE_PRESSURE_5, //6 J0162 ,PIN 21 - AN_IDS_PRESSENS_5, PIN 9 - GND
CHAN_DISPENSE_PRESSURE_6, //7 J0262 ,PIN 21 - AN_IDS_PRESSENS_6, PIN 9 - GND
CHAN_DISPENSE_PRESSURE_7, //8 J0062 ,PIN 21 - AN_IDS_PRESSENS_7, PIN 9 - GND
CHAN_DISPENSE_PRESSURE_8, //9 J0052 ,PIN 21 - AN_IDS_PRESSENS_8, PIN 9 - GND
CHAN_VOCSENS, //10 J0072 ,PIN 21 - AN_VOCSENS, PIN 9 - GND
CHAN_SPARE1, //11
CHAN_SPARE2, //12
CHAN_LEFT_DANCER_1, //13 J0002 ,PIN 21 - AN5V_LDANCER1, PIN 9 - GND
CHAN_LEFT_DANCER_2, //14 J0002 ,PIN 22 - AN5V_LDANCER1, PIN 10 - GND
CHAN_RIGHT_DANCER, //15 J0102 ,PIN 21 - AN5V_RDANCER, PIN 9 - GND
CHAN_DRYER_CURRENT_1, //16 J1292 ,PIN 7 - AN_DRYER_CURSEN_1p, PIN 19 - AN_DRYER_CURSEN_1n
CHAN_DRYER_CURRENT_2, //17 J1292 ,PIN 8 - AN_DRYER_CURSEN_1p, PIN 20 - AN_DRYER_CURSEN_1n
CHAN_DRYER_CURRENT_3, //18 J1292 ,PIN 9 - AN_DRYER_CURSEN_1p, PIN 21 - AN_DRYER_CURSEN_1n
CHAN_3V3_FPGA, //19
};
//#define NUM_ADC_CHANNELS (sizeof(g_pui32ADCSeq) / \
sizeof(g_pui32ADCSeq[0]))
int DispenserIdToPressureSensorId[MAX_DISPENSERS] = {CHAN_DISPENSE_PRESSURE_1, CHAN_DISPENSE_PRESSURE_2 , CHAN_DISPENSE_PRESSURE_3 , CHAN_DISPENSE_PRESSURE_4 , CHAN_DISPENSE_PRESSURE_5 , CHAN_DISPENSE_PRESSURE_6 , CHAN_DISPENSE_PRESSURE_7 , CHAN_DISPENSE_PRESSURE_8 };
//const uint8_t Num_ADC_Channels = ( sizeof(g_pui32ADCSeq) / sizeof(g_pui32ADCSeq[0]) );
//#define SAMPLE_ARRAY_SIZE (NUM_ADC_CHANNELS + I2C_NUM_OF_CHANNELS)
//#define SAMPLE_ARRAY_SIZE NUM_ADC_CHANNELS
static bool isInitialized = false;
static bool adcCollectActive = false;
static int bufferFlipFlop = 0;
//*****************************************************************************
//
// Global _storage for most recent sampled Sensor Data
//
//*****************************************************************************
//
// A buffer to hold one set of ADC data that is acquired per sample time.
//
//*****************************************************************************
static uint32_t g_pui32ADCData[DOUBLE_BUFFER][MAX_ADC_DEVICES];
//*****************************************************************************
//configured in the cfg file and thats why should be defined as extern
//*****************************************************************************
extern Semaphore_Handle adcResultSem;
static ProcessCallback processCallBack;
//*****************************************************************************
// ADCClockHandle: clock event handler - initiates trigger for the adc sampaling
//*****************************************************************************
// This function starts an ADC Conversion.
//static void ADCClockHandle(UArg arg0)
uint32_t ADC_TriggerCollection(void) // (called by MillisecLoop)
{
//
// Kick off the next ADC acquisition. When these are done they will
// cause an ADC interrupt.
//
if (adcCollectActive == true)
{
MAP_ADCProcessorTrigger(ADC1_BASE, 0);
MAP_ADCProcessorTrigger(ADC0_BASE, 0);
MAP_ADCProcessorTrigger(ADC0_BASE, 1);
}
return 0;
}
//*****************************************************************************
//
// ADC Data get for a single data read
//
//*****************************************************************************
uint32_t ADC_GetReading(int DataItemId) // // ADC Data get for a single data read
{
int bufnotinuse;
assert (DataItemId<MAX_ADC_DEVICES);
if (bufferFlipFlop == 0) bufnotinuse = 1;
else bufnotinuse = 0;
return (g_pui32ADCData[bufnotinuse][DataItemId]);
}
//*****************************************************************************
//
// This is the handler for the ADC interrupt. Even though more than one
// sequencer is used, they are configured so that this one runs last.
// Therefor when this ADC sequencer interrupt occurs, we know all of the ADC
// data has been acquired.
//
//*****************************************************************************
void ADC0SS0Handler(void)
{
//
// Clear the interrupts for all ADC sequencers that are used.
//
MAP_ADCIntClear(ADC0_BASE, 0);
MAP_ADCIntClear(ADC1_BASE, 0);
MAP_ADCIntClear(ADC0_BASE, 1);
if (bufferFlipFlop == 0) bufferFlipFlop = 1;
else bufferFlipFlop = 0;
//
// Retrieve the data from all ADC sequencers
//
MAP_ADCSequenceDataGet(ADC0_BASE, 0, &g_pui32ADCData[bufferFlipFlop][0]);
//offset in the array calculated as sampling of 16 channels each one of 16 bits
MAP_ADCSequenceDataGet(ADC1_BASE, 0, &g_pui32ADCData[bufferFlipFlop][8]);
MAP_ADCSequenceDataGet(ADC0_BASE, 1, &g_pui32ADCData[bufferFlipFlop][16]);
//
// Release adc result semaphore
//
//the ADC Process task is mot currently active. the results will be copied to a second buffer and supplied upon request
//Semaphore_post(adcResultSem);
}
//*****************************************************************************
//
//*****************************************************************************
Void ADCProcessTask(UArg arg0, UArg arg1)
{
while(1)
{
//
// Wait until new ADC data is available
//
Semaphore_pend(adcResultSem, BIOS_WAIT_FOREVER);
//
// Process the ADC data
//
if (processCallBack != NULL)
{
processCallBack(g_pui32ADCData[bufferFlipFlop]);
}
}
}
void ADCAcquireInit(void) // (called by MillisecInit)
{
uint32_t ui32Chan, ui32Base, ui32Seq;
//Avaraging 8 //TODO
//MAP_ADCHardwareOversampleConfigure(ADC0_BASE, 8);
//MAP_ADCHardwareOversampleConfigure(ADC1_BASE, 8);
//
// Initialize both ADC peripherals using sequencer 0 and processor trigger.
//
MAP_ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
MAP_ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
MAP_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 1); //sequencer 1
ADCSequenceDisable(ADC0_BASE, 1);
//
// Enter loop to configure all of the ADC sequencer steps needed to
// acquire the data for the data logger. Multiple ADC and sequencers
// will be used in order to acquire all the channels.
//
for(ui32Chan = 0; ui32Chan < MAX_ADC_DEVICES; ui32Chan++)
{
//
// If this is the first ADC then set the base for ADC0
//
if(ui32Chan < 8)
{
ui32Base = ADC0_BASE;
ui32Seq = 0;
}
else if(ui32Chan < 16)
{
//
// Second ADC, set the base for ADC1
//
ui32Base = ADC1_BASE;
ui32Seq = 0;
}
else
{
ui32Base = ADC0_BASE;
ui32Seq = 1;
}
//
// Get the channel control for each channel. Test to see if it is the
// last channel for the sequencer, and if so then also set the
// interrupt and "end" flags.
//
uint32_t ui32ChCtl = g_pui32ADCSeq[ui32Chan];
//TODO define all the numbers under #define and not here
if((ui32Chan == 7) || (ui32Chan == 15) || (ui32Chan == (MAX_ADC_DEVICES - 1)))
{
ui32ChCtl |= ADC_CTL_IE | ADC_CTL_END;
}
//
// Configure the sequence step
//
MAP_ADCSequenceStepConfigure(ui32Base, ui32Seq, ui32Chan % 8, ui32ChCtl);
}
ADCSequenceEnable(ADC0_BASE, 1);
ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);
ADCReferenceSet(ADC1_BASE, ADC_REF_EXT_3V);
if (!isInitialized)
{
// Create a periodic Clock Instance with _period - triggers the ADC sampling
isInitialized = true;
//InitI2C();
}
}
//*****************************************************************************
//
// This function is called to start an acquisition running. It determines
// which channels are to be logged, enables the ADC/I2C sequencers.
// This will start the acquisition running.
//
//*****************************************************************************
void ADCAcquireStart(ProcessCallback _callback, uint32_t _period) // (called by MillisecStart)
{
//
// Enable the ADC sequencers
//
MAP_ADCSequenceEnable(ADC0_BASE, 0);
MAP_ADCSequenceEnable(ADC1_BASE, 0);
MAP_ADCSequenceEnable(ADC0_BASE, 1);
//
// Flush the ADC sequencers to be sure there is no lingering/ trush data.
//
MAP_ADCSequenceDataGet(ADC0_BASE, 0, g_pui32ADCData[0]);
MAP_ADCSequenceDataGet(ADC1_BASE, 0, g_pui32ADCData[0]);
MAP_ADCSequenceDataGet(ADC1_BASE, 1, g_pui32ADCData[0]);
//
// Enable ADC interrupts
//
MAP_ADCIntClear(ADC0_BASE, 0);
MAP_ADCIntClear(ADC1_BASE, 0);
MAP_ADCIntEnable(ADC0_BASE, 0);
MAP_ADCIntEnable(ADC0_BASE, 1);
ROM_IntEnable(INT_ADC0SS0);
// Store process
processCallBack = _callback;
// Start a periodic Clock Instance with _period - triggers the ADC sampling
adcCollectActive = true;
//
// Logging data should now start running
//
}
//*****************************************************************************
//
// This function is called to stop an acquisition running. It disables the
// ADC sequencers.
//
//*****************************************************************************
void ADCAcquireStop(void)
{
//Stop trigger adc sampling
adcCollectActive = false;
//
// Disable ADC interrupts
//
MAP_IntDisable(INT_ADC0SS0);
MAP_IntDisable(INT_ADC1SS0);
//
// Disable ADC sequencers
//
MAP_ADCSequenceDisable(ADC0_BASE, 0);
MAP_ADCSequenceDisable(ADC1_BASE, 0);
MAP_ADCSequenceDisable(ADC0_BASE, 1);
}