To validate the samplerate from the teensy 4 ADC's I wanted to timestamp each time an ADC_ETC_DONE interrupt was triggered using micros(). This works up to about 2.3kHz, at higher frequencies micro(s) returns wrong values >50% of the times. I know that micro(s) can be called a lot more frequently inside of adcetc0_isr() below. I have tested the code with just the time stamping inside of adcetc0_isr, but the same still occurs. Is there some codepency with QTimer4_X and micros() ?
I have looked into pwm.c and how the TMRx_CTRLn registers are set but did not see anything that could cause it. Is it better to forget this idea and use a signal generator to check if the sampling rate is still in accordance with the QTIMER4 frequency above 2.3kHz?
The code was based on the work of @mjs513 (ADCLpitxbadacV7) https://forum.pjrc.com/threads/58387-Teensy-4-0-which-pins-for-which-ADC?p=224915&viewfull=1#post224915. I store the data in circular buffers (tonton81 https://github.com/tonton81/Circular_Buffer)
I have changed the code somewhat for my purpose, for instance only getting an interrupt when the final pin/channel of the triggerchain has been converted and using a dedicated IRQ for each ADC.
My code (use it inside of Visual Studio Code/Platform.io )
I have looked into pwm.c and how the TMRx_CTRLn registers are set but did not see anything that could cause it. Is it better to forget this idea and use a signal generator to check if the sampling rate is still in accordance with the QTIMER4 frequency above 2.3kHz?
The code was based on the work of @mjs513 (ADCLpitxbadacV7) https://forum.pjrc.com/threads/58387-Teensy-4-0-which-pins-for-which-ADC?p=224915&viewfull=1#post224915. I store the data in circular buffers (tonton81 https://github.com/tonton81/Circular_Buffer)
I have changed the code somewhat for my purpose, for instance only getting an interrupt when the final pin/channel of the triggerchain has been converted and using a dedicated IRQ for each ADC.
My code (use it inside of Visual Studio Code/Platform.io )
Code:
#include <Arduino.h>
#include <ADC.h>
#include <circular_buffer.h>
#define USE_TIMED_READS
int adc_0_pins[] = {A0, A1, A2, A3, A4, A5};
int adc_1_pins[] = {A6, A7, A8, A9,A10,A11};
const uint8_t channels = 6;
const uint8_t trigger_adc_0 = 0; // linked to adc_0
const uint8_t trigger_adc_1 = 4; // linked to adc_1
//uint8_t chain_len_0 = 6; // chain length max 8
const uint8_t chain_len_0 = 6; // chain length max 8, also number of items
const uint8_t chain_len_1 = 6;
float freqsamp_1 = 2000.0;
float freqsamp_2 = 2000.0;
const uint32_t buflen_0 = 640; // buffer length adc 1
const uint32_t buflen_1 = 256; // buffer length adc 2
ADC *adc = new ADC(); // adc object
#define PRREG(x) Serial.print(#x" 0x"); Serial.println(x,HEX)
volatile uint32_t val0, val1;
//debug parameters
uint32_t t1; // start time;
uint32_t t2; // end time;
int32_t dt; // elapsed time;
//timestamp vars
const uint32_t n_stamps = 200;
uint32_t stnr = 0 ; // time array index
bool printing = true;
bool first = true;
// uint32_t time_st[n_stamps];
uint8_t ch_adc0 = 0; // adc0 channel index
uint8_t ch_adc1 = 0; // adc1 channel index
// connect parameters
uint8_t XBAR_IN;
uint8_t XBAR_OUT;
uint8_t priority = 16; // interrupt priority 0-255, low numbers= high priority
//uint8_t QTIMER4_INDEX;
//int8_t ADC_ETC_TRIGGER_INDEX;
// declaration of functions
void setup_adc_hardware_trigger();
void adc_init();
void adc_etc_init();
void connectTimer(uint8_t ADC_num);
void startTimer(uint8_t timer, float freq);
void adcetc0_isr();
void adcetc1_isr();
void adc_etc_reset();
void adc0_etc_ctrl_init(uint8_t chainLength_0,
int adc_0_pinArray[],
uint8_t trigger_adc_0, bool DMA);
void adc1_etc_ctrl_init(uint8_t chainLength_1,
int adc_1_pinArray[],
uint8_t trigger_adc_1, bool DMA);
void ADC_ETC_SetTriggerChainConfig(uint8_t adc_num,
uint8_t done,
uint32_t triggerGroup,
uint32_t chainGroup, //0, 1, 2, 3 (0_1, 3_2....
uint8_t pin1, uint8_t pin2);
uint16_t ADC_ETC_GetADCConversionValue(uint32_t triggerGroup, uint32_t chainGroup);
uint8_t mapPinToChannel(uint8_t pin, int8_t adc_num);
// Assign circular buffers
// circularbuffer setup ADC_0 <datatype , slots, items
Circular_Buffer<uint16_t,buflen_0> rb_adc_0[6];
Circular_Buffer<uint16_t,buflen_1> rb_adc_1[6];
Circular_Buffer<int32_t,buflen_0> timest;
void setup() {
while (!Serial && millis() < 5000) ;
//pinMode(LED_BUILTIN, OUTPUT);
for (int i = 0; i < channels; i++)
{
pinMode(adc_0_pins[i], INPUT);
pinMode(adc_1_pins[i], INPUT);
}
Serial.begin(9600);
Serial.println("Setup ADC_0");
// adc settings;
// averaging options 1/4/8/16/32
// resolution 8/10/12 ADCK cycles: 17/21/25
adc->adc0->setAveraging(1); // set number of averages
adc->adc0->setResolution(10); // set bits of resolution
adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // ADCK at 40MHz
adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED); // adds 10 ADCK cycles, impedance dependant
adc->adc0->singleMode();
//adc->adc0->startQuadTimer();
adc->adc1->setAveraging(4); // set number of averages
adc->adc1->setResolution(10);
adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // ADCK at 40MHz
adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED); // adds 10 ADCK cycles, impedance dependant
adc->adc1->singleMode();
// always call the compare functions after changing the resolution!
//adc->enableCompare(1.0/3.3*adc->getMaxValue(ADC_0), 0, ADC_0); // measurement will be ready if value < 1.0V
//adc->enableCompareRange(1.0*adc->getMaxValue(ADC_1)/3.3, 2.0*adc->getMaxValue(ADC_1)/3.3, 0, 1, ADC_1); // ready if value lies out of [1.0,2.0] V
setup_adc_hardware_trigger();
Serial.println("End Setup");
}
void loop() {
// Serial.printf("ADC0: %d %d %d %d %d %d\n", rb_adc_0[0].peek(0), rb_adc_0[1].peek(0), rb_adc_0[2].peek(0),
// rb_adc_0[3].peek(0), rb_adc_0[4].peek(0), rb_adc_0[5].peek(0));
// Serial.printf("ADC1: %d %d %d %d %d %d\n", rb_adc_1[0].peek(0), rb_adc_1[1].peek(0), rb_adc_1[2].peek(0),
// rb_adc_1[3].peek(0), rb_adc_1[4].peek(0), rb_adc_1[5].peek(0));
// delay(100);
// for (uint8_t i = 0; i < 10; i++){
// Serial.printf("%d \n",timest[i]);
// }
//delay(100); // time to type 'pio device monitor > log.txt' in the PlatformIO CLI terminal
delay(10000);
if(printing) {
uint16_t buffer0_1 [64];
int32_t printstamps[64]; // printbuffer filled from timestamps ringbuffer
timest.readBytes(printstamps,64);
rb_adc_0[1].readBytes(buffer0_1,64);
for (uint8_t i=0; i < 64;i++){
Serial.printf("%d %d\n",printstamps[i]),buffer0_1[i];
delayMicroseconds(2);
}
printing = false;
}
}
void setup_adc_hardware_trigger()
{
adc_init();
adc_etc_init();
Serial.println("After ADC/ADC_ETC"); Serial.flush();
//timer 1 = QTIMER4_0 / timer2=QTIMER4_3 / PIT timer
connectTimer(1); //connect QTIMER to ADC_ETC with XBAR
connectTimer(0); //connect QTIMER to ADC_ETC with XBAR
Serial.println("After XBAR"); Serial.flush();
startTimer(1, freqsamp_1); // 1 khz 1000 ADCs/sec
startTimer(2, freqsamp_2); // try at 20 hz for test...
}
void adc_init() {
ADC1_CFG |= ADC_CFG_ADTRG; // hardware trigger
ADC1_HC0 = 16; // ADC_ETC channel, 144 int enabled, 16 int disabled
ADC1_GC &= ~ADC_GC_ADCO; // continuous conversion disabled, same as adc->adcX->singleMode()
ADC2_CFG |= ADC_CFG_ADTRG; // hardware trigger
ADC2_HC0 = 16; // ADC_ETC channel
ADC2_GC &= ~ADC_GC_ADCO; // continuous conversion disabled
}
void adc_etc_init() {
adc_etc_reset();
adc0_etc_ctrl_init(chain_len_0, //chainLength_0, chainLength_1
adc_0_pins, //*adc_0_pinArray, *adc_1_pinArray
trigger_adc_0, //trigger_adc_0, trigger_adc_1
false); //bool DMA,
adc1_etc_ctrl_init(chain_len_1, //chainLength_0, chainLength_1
adc_1_pins, //*adc_0_pinArray, *adc_1_pinArray
trigger_adc_1, //trigger_adc_0, trigger_adc_1
false); //bool DMA
// ADC_ETC_SetTriggerChainConfig(ADC,done#, trigger#, channel Group#, pin1, pin2);
// continue the chain with pairs of 2
ADC_ETC_SetTriggerChainConfig(ADC_0, 1, trigger_adc_0, 0, adc_0_pins[0], adc_0_pins[1]);
ADC_ETC_SetTriggerChainConfig(ADC_0, 1, trigger_adc_0, 1, adc_0_pins[2], adc_0_pins[3]);
ADC_ETC_SetTriggerChainConfig(ADC_0, 1, trigger_adc_0, 2, adc_0_pins[4], adc_0_pins[5]);
ADC_ETC_SetTriggerChainConfig(ADC_1, 2, trigger_adc_1, 0, adc_1_pins[0], adc_1_pins[1]);
ADC_ETC_SetTriggerChainConfig(ADC_1, 2, trigger_adc_1, 1, adc_1_pins[2], adc_1_pins[3]);
ADC_ETC_SetTriggerChainConfig(ADC_1, 2, trigger_adc_1, 2, adc_1_pins[4], adc_1_pins[5]);
// attach ADC_ETC0 IRQ to ADC1
attachInterruptVector(IRQ_ADC_ETC0, adcetc0_isr);
//attachInterruptVector(IRQ_ADC_ETC0, timestamp);
NVIC_SET_PRIORITY(IRQ_ADC_ETC0, priority);
NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
attachInterruptVector(IRQ_ADC_ETC1, adcetc1_isr);
NVIC_SET_PRIORITY(IRQ_ADC_ETC1, priority);
NVIC_ENABLE_IRQ(IRQ_ADC_ETC1);
//Maakt het uit dat ik nu IRQ_ADC_ETC0 verbind met beiden, dat staat
// toch haaks op het idee dat ik twee onafhankelijke trigger frequenties heb?
//attachInterruptVector(IRQ_ADC_ETC0, adcetc1_isr);
//NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
//attachInterruptVector(IRQ_ADC_ETC0, adcetc1_isr);
//NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
}
// modified version from T4 analog.c
// 0x80 bit - Only on ADC2
// 0x40 bit - only on ADC1
const uint8_t t4_pin_to_channel[] = {
7, // 0/A0 AD_B1_02
8, // 1/A1 AD_B1_03
12, // 2/A2 AD_B1_07
11, // 3/A3 AD_B1_06
6, // 4/A4 AD_B1_01
5, // 5/A5 AD_B1_00
15, // 6/A6 AD_B1_10
0, // 7/A7 AD_B1_11
13, // 8/A8 AD_B1_08
14, // 9/A9 AD_B1_09
0x40 + 1, // 24/A10 AD_B0_12
0x40 + 2, // 25/A11 AD_B0_13
0x80 + 3, // 26/A12 AD_B1_14 - only on ADC2, 3
0x80 + 4, // 27/A13 AD_B1_15 - only on ADC2, 4
7, // 14/A0 AD_B1_02
8, // 15/A1 AD_B1_03
12, // 16/A2 AD_B1_07
11, // 17/A3 AD_B1_06
6, // 18/A4 AD_B1_01
5, // 19/A5 AD_B1_00
15, // 20/A6 AD_B1_10
0, // 21/A7 AD_B1_11
13, // 22/A8 AD_B1_08
14, // 23/A9 AD_B1_09
0x40 + 1, // 24/A10 AD_B0_12
0x40 + 2, // 25/A11 AD_B0_13
0x80 + 3, // 26/A12 AD_B1_14 - only on ADC2, 3
0x80 + 4 // 27/A13 AD_B1_15 - only on ADC2, 4
};
#ifdef USE_TIMED_READS
// try to use some teensy core functions...
// mainly out of pwm.c
extern "C" {
extern void xbar_connect(unsigned int input, unsigned int output);
extern void quadtimer_init(IMXRT_TMR_t *p);
extern void quadtimerWrite(IMXRT_TMR_t *p, unsigned int submodule, uint16_t val);
extern void quadtimerFrequency(IMXRT_TMR_t *p, unsigned int submodule, float frequency);
}
void connectTimer(uint8_t adc_num) {
CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); //turn clock on for xbara1
// setup connections for ADC0 or ADC1
if(adc_num){
XBAR_IN = XBARA1_IN_QTIMER4_TIMER3; //QTIMER4_0 for ADC1
XBAR_OUT = XBARA1_OUT_ADC_ETC_TRIG10;
}
else{
XBAR_IN = XBARA1_IN_QTIMER4_TIMER0; //QTIMER4_3 for ADC0
XBAR_OUT = XBARA1_OUT_ADC_ETC_TRIG00;
}
xbar_connect(XBAR_IN, XBAR_OUT);
}
void startTimer(uint8_t timer, float freq)
{
Serial.printf("Timer: %d, Freq: %f\n", timer, freq);
if (timer == 1) {
Serial.println("Try to init QTimer4_0"); Serial.flush();
//quadtimer_init(&IMXRT_TMR4);
quadtimerFrequency(&IMXRT_TMR4, 0, freq);
quadtimerWrite(&IMXRT_TMR4, 0, 5);
Serial.println("After Qtimer4_0 init"); Serial.flush();
}
if (timer == 2){
Serial.println("Try to init QTimer4_3"); Serial.flush();
//quadtimer_init(&IMXRT_TMR4);
quadtimerFrequency(&IMXRT_TMR4, 3, freq);
quadtimerWrite(&IMXRT_TMR4, 3, 5);
Serial.println("After Qtimer4_3 init"); Serial.flush();
}
}
#endif
void adcetc0_isr() {
ADC_ETC_DONE0_1_IRQ |= 1 << trigger_adc_0; // clear
for (uint8_t i = 0; i < channels; i++) {
rb_adc_0[i].push_back(ADC_ETC_GetADCConversionValue( trigger_adc_0, i ));
}
timest.push_back(micros());
//timest.push_back(ARM_DWT_CYCCNT);
asm("dsb");
}
void adcetc1_isr() {
ADC_ETC_DONE0_1_IRQ |= (1 << (trigger_adc_1+16)); // clear
for (uint8_t k = 0; k < channels; k++) {
rb_adc_1[k].push_back(ADC_ETC_GetADCConversionValue( trigger_adc_1, k ));
}
asm("dsb");
}
void adc_etc_reset() {
// first do soft reset and/or let complete
IMXRT_ADC_ETC.CTRL = ADC_ETC_CTRL_SOFTRST; // SOFTRST
IMXRT_ADC_ETC.CTRL &= ~ADC_ETC_CTRL_SOFTRST; // SOFTRST
delay(5);
}
void adc0_etc_ctrl_init(uint8_t chainLength_0,
int adc_0_pinArray[],
uint8_t trigger_adc_0, bool DMA)
{
int numPins_adc_0 = sizeof(adc_0_pinArray);
uint8_t adc_pin_channel;
delay(5);
// Now lets process ADC1(ADC_0) pin...
for (uint8_t i = 0; i < numPins_adc_0; i++) {
adc_pin_channel = ADC::channel2sc1aADC0[adc_0_pinArray[i]];
if (adc_pin_channel == 0xff)
Serial.printf("ADC_ETC_INIT: pin:%d did not map to channnel on %d\n", adc_0_pinArray[i], ADC_0);
}
IMXRT_ADC_ETC.CTRL = (ADC_ETC_CTRL_DMA_MODE_SEL | ADC_ETC_CTRL_TRIG_ENABLE(1 << trigger_adc_0)); // 0x40000001; // start with trigger 0
IMXRT_ADC_ETC.TRIG[trigger_adc_0].CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(chainLength_0 - 1);
if (DMA)
IMXRT_ADC_ETC.DMA_CTRL = ADC_ETC_DMA_CTRL_TRIQ_ENABLE(trigger_adc_0);
Serial.printf("ADC1: HC0:%x HS:%x CFG:%x GC:%x GS:%x\n", ADC1_HC0, ADC1_HS, ADC1_CFG, ADC1_GC, ADC1_GS);
Serial.printf("ADC_ETC: CTRL:%x DMA: %x TRIG0: CTRL: %x CHAIN01:%x\n",
IMXRT_ADC_ETC.CTRL, IMXRT_ADC_ETC.DMA_CTRL, ADC_ETC_TRIG0_CTRL, ADC_ETC_TRIG0_CHAIN_1_0);
}
void adc1_etc_ctrl_init(uint8_t chainLength_1, int adc_1_pinArray[],
uint8_t trigger_adc_1, bool DMA)
{
int numPins_adc_1 = sizeof(adc_1_pinArray);
uint8_t adc_pin_channel;
delay(5);
// Now lets do ADC2(ADC_1)
if (chainLength_1 >= 0) {
for (uint8_t i = 0; i < numPins_adc_1; i++) {
adc_pin_channel = ADC::channel2sc1aADC1[adc_1_pinArray[i]];
if (adc_pin_channel == 0xff)
Serial.printf("ADC_ETC_INIT: pin:%d did not 2map to channnel on %d\n", adc_1_pinArray[i], ADC_1);
}
// ADC2 (ADC_1)
IMXRT_ADC_ETC.CTRL |= ADC_ETC_CTRL_TRIG_ENABLE(1 << trigger_adc_1); // Add in our trigger
Serial.printf("ADC_ETC_CTRL: %x\n", IMXRT_ADC_ETC.CTRL);
IMXRT_ADC_ETC.TRIG[trigger_adc_1].CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(chainLength_1 - 1);
if (DMA)
IMXRT_ADC_ETC.DMA_CTRL |= ADC_ETC_DMA_CTRL_TRIQ_ENABLE(trigger_adc_1);
}
Serial.printf("ADC2: HC0:%x HS:%x CFG:%x GC:%x GS:%x\n", ADC2_HC0, ADC2_HS, ADC2_CFG, ADC2_GC, ADC2_GS);
Serial.printf("ADC_ETC: CTRL:%x DMA: %x TRIG0: CTRL: %x CHAIN01:%x\n",
IMXRT_ADC_ETC.CTRL, IMXRT_ADC_ETC.DMA_CTRL, ADC_ETC_TRIG0_CTRL, ADC_ETC_TRIG0_CHAIN_1_0);
}
void ADC_ETC_SetTriggerChainConfig(uint8_t adc_num,
uint8_t done,
uint32_t triggerGroup,
uint32_t chainGroup, //0, 1, 2, 3 (0_1, 3_2....
uint8_t pin1, uint8_t pin2)
{
uint8_t adc_pin_channel;
switch (chainGroup)
{
case 0U: /* Configurate trigger chain0 and chain 1. */
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin1];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin1];
}
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_1_0 |= ADC_ETC_TRIG_CHAIN_B2B0 |
ADC_ETC_TRIG_CHAIN_IE0(0) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel) ;
if(pin2 > -1)
{
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin2];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin2];
}
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_1_0 |= ADC_ETC_TRIG_CHAIN_B2B1 |
ADC_ETC_TRIG_CHAIN_IE1(0) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS1(1) | ADC_ETC_TRIG_CHAIN_CSEL1(adc_pin_channel);
}
break;
case 1U: /* Configurate trigger chain2 and chain 3. */
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin1];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin1];
}
//Serial.print("ADC Pin3 Channel: "); Serial.println(adc_pin_channel);
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_3_2 =
ADC_ETC_TRIG_CHAIN_B2B0 |
ADC_ETC_TRIG_CHAIN_IE0(0) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel) ;
if(pin2 > -1)
{
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin2];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin2];
}
//Serial.print("ADC Pin4 Channel: "); Serial.println(adc_pin_channel);
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_3_2 |= ADC_ETC_TRIG_CHAIN_B2B1 |
ADC_ETC_TRIG_CHAIN_IE1(0) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS1(1) | ADC_ETC_TRIG_CHAIN_CSEL1(adc_pin_channel);
//Serial.print("TRIG[0].CHAIN_3_2: "); Serial.println(IMXRT_ADC_ETC.TRIG[0].CHAIN_3_2, HEX);
}
break;
case 2U: /* Configurate trigger chain4 and chain 5. */
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin1];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin1];
}
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_5_4 =
ADC_ETC_TRIG_CHAIN_B2B0 |
ADC_ETC_TRIG_CHAIN_IE0(0) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel) ;
if(pin2 > -1)
{
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin2];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin2];
}
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_5_4 |= ADC_ETC_TRIG_CHAIN_B2B1 |
ADC_ETC_TRIG_CHAIN_IE1(done) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS1(1) | ADC_ETC_TRIG_CHAIN_CSEL1(adc_pin_channel);
}
break;
case 3U: /* Configurate trigger chain6 and chain 7. */
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin1];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin1];
}
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_7_6 =
ADC_ETC_TRIG_CHAIN_B2B0 |
ADC_ETC_TRIG_CHAIN_IE0(done) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel) ;
if(pin2 > -1)
{
if(adc_num == 1) {
adc_pin_channel = ADC::channel2sc1aADC1[pin2];
}
else {
adc_pin_channel = ADC::channel2sc1aADC0[pin2];
}
IMXRT_ADC_ETC.TRIG[triggerGroup].CHAIN_7_6 |= ADC_ETC_TRIG_CHAIN_B2B1 |
ADC_ETC_TRIG_CHAIN_IE1(done) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS1(1) | ADC_ETC_TRIG_CHAIN_CSEL1(adc_pin_channel);
}
break;
default:
break;
}
}
/*!
Taken from SDK
brief Get ADC conversion result from external XBAR sources.
For example, if triggerGroup is set to 0U and chainGroup is set to 1U, which means the API would
return Trigger0 source's chain1 conversion result.
param base ADC_ETC peripheral base address.
param triggerGroup Trigger group index. Available number is 0~7.
param chainGroup Trigger chain group index. Available number is 0~7.
return ADC conversion result value.
Zo te zien kan dit nog best beter, ik denk dat de trigger chains te kort zijn (meer dan 2 pins).
Het resultaat is iig 12 bits en NIET 32, dus een 16bits output voor het resultout zou veel corrector zijn!
*/
uint16_t ADC_ETC_GetADCConversionValue(uint32_t triggerGroup, uint32_t chainGroup)
{
//assert(triggerGroup < ADC_ETC_TRIGn_RESULT_1_0_COUNT);
uint32_t mADCResult;
uint8_t mRemainder = chainGroup % 2U;
switch (chainGroup / 2U)
{
case 0U:
if (0U == mRemainder)
{
mADCResult = (0xFFFU) & (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_1_0);
}
else
{
mADCResult = (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_1_0) >> (16U);
}
break;
case 1U:
if (0U == mRemainder)
{
mADCResult = (0xFFFU) & (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_3_2);
}
else
{
mADCResult = (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_3_2) >> (16U);
}
break;
case 2U:
if (0U == mRemainder)
{
mADCResult = (0xFFFU) & (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_5_4);
}
else
{
mADCResult = (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_5_4) >> (16U);
}
break;
case 3U:
if (0U == mRemainder)
{
mADCResult = (0xFFFU) & (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_7_6);
}
else
{
mADCResult = (IMXRT_ADC_ETC.TRIG[triggerGroup].RESULT_7_6) >> (16U);
}
break;
default:
return 0U;
}
return mADCResult;
}