Code:
#include "DMAChannel.h"
extern "C" void xbar_connect(unsigned int input, unsigned int output);
const uint8_t adc2_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
255, // 10/A10 AD_B0_12 - only on ADC1, 1 - can't use for audio
255, // 11/A11 AD_B0_13 - only on ADC1, 2 - can't use for audio
3, // 12/A12 AD_B1_14
4, // 13/A13 AD_B1_15
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
255, // 24/A10 AD_B0_12 - only on ADC1, 1 - can't use for audio
255, // 25/A11 AD_B0_13 - only on ADC1, 2 - can't use for audio
3, // 26/A12 AD_B1_14 - only on ADC2, do not use analogRead()
4, // 27/A13 AD_B1_15 - only on ADC2, do not use analogRead()
#ifdef ARDUINO_TEENSY41
255, // 28
255, // 29
255, // 30
255, // 31
255, // 32
255, // 33
255, // 34
255, // 35
255, // 36
255, // 37
1, // 38/A14 AD_B1_12 - only on ADC2, do not use analogRead()
2, // 39/A15 AD_B1_13 - only on ADC2, do not use analogRead()
9, // 40/A16 AD_B1_04
10, // 41/A17 AD_B1_05
#endif
};
DMAChannel dma;
uint16_t output;
void setup()
{
while (!Serial);
Serial.println("ADC triggering test");
// configure a timer to trigger ADC
const int comp1load = 58594; // approx 10 Hz with TMR_CTRL_PCS=15
TMR3_ENBL &= ~(1<<3);
TMR3_SCTRL3 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
TMR3_CSCTRL3 = TMR_CSCTRL_CL1(1) | TMR_CSCTRL_TCF1EN;
TMR3_CNTR3 = 0;
TMR3_LOAD3 = 0;
TMR3_COMP13 = comp1load;
TMR3_CMPLD13 = comp1load;
//TMR3_CTRL3 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(9) | TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(3);
TMR3_CTRL3 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(15) | TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(3);
TMR3_DMA3 = TMR_DMA_CMPLD1DE;
//CORE_PIN15_CONFIG = 1 ; // GPIO_AD_B1_03, ALT1 = QTIMER3_TIMER3, page 495
TMR3_CNTR3 = 0;
TMR3_ENBL |= (1<<3);
// connect the timer output the ADC_ETC input
const int trigger = 4; // 0-3 for ADC1, 4-7 for ADC2
CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);
xbar_connect(XBARA1_IN_QTIMER3_TIMER3, XBARA1_OUT_ADC_ETC_TRIG00 + trigger);
// turn on ADC_ETC and configure to receive trigger
if (ADC_ETC_CTRL & (ADC_ETC_CTRL_SOFTRST | ADC_ETC_CTRL_TSC_BYPASS)) {
//Serial.printf("ADC_ETC_CTRL = %08X\n", ADC_ETC_CTRL);
ADC_ETC_CTRL = 0; // clears SOFTRST only
ADC_ETC_CTRL = 0; // clears TSC_BYPASS
//Serial.printf("ADC_ETC_CTRL = %08X\n", ADC_ETC_CTRL);
}
ADC_ETC_CTRL |= ADC_ETC_CTRL_TRIG_ENABLE(1 << trigger) | ADC_ETC_CTRL_DMA_MODE_SEL;
ADC_ETC_DMA_CTRL |= ADC_ETC_DMA_CTRL_TRIQ_ENABLE(trigger);
// configure ADC_ETC trigger4 to make one ADC2 measurement on pin A2
const int len = 1;
const int pin = A2;
IMXRT_ADC_ETC.TRIG[trigger].CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(len - 1) |
ADC_ETC_TRIG_CTRL_TRIG_PRIORITY(7);
IMXRT_ADC_ETC.TRIG[trigger].CHAIN_1_0 = ADC_ETC_TRIG_CHAIN_HWTS0(1) |
ADC_ETC_TRIG_CHAIN_CSEL0(adc2_pin_to_channel[pin]) | ADC_ETC_TRIG_CHAIN_B2B0;
// set up ADC2 for 12 bit mode, hardware trigger
Serial.printf("ADC2_CFG = %08X\n", ADC2_CFG);
ADC2_CFG |= ADC_CFG_ADTRG;
ADC2_CFG = ADC_CFG_MODE(2) | ADC_CFG_ADSTS(3) | ADC_CFG_ADLSMP | ADC_CFG_ADTRG |
ADC_CFG_ADICLK(1) | ADC_CFG_ADIV(0) /*| ADC_CFG_ADHSC*/;
ADC2_GC &= ~ADC_GC_AVGE; // single sample, no averaging
ADC2_HC0 = ADC_HC_ADCH(16); // 16 = controlled by ADC_ETC
// use a DMA channel to capture ADC_ETC output
dma.begin();
dma.TCD->SADDR = &(IMXRT_ADC_ETC.TRIG[4].RESULT_1_0);
dma.TCD->SOFF = 0;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma.TCD->NBYTES_MLNO = 2;
dma.TCD->SLAST = 0;
dma.TCD->DADDR = &output;
dma.TCD->DOFF = 0;
dma.TCD->CITER_ELINKNO = 1;
dma.TCD->DLASTSGA = 0;
dma.TCD->BITER_ELINKNO = 1;
dma.TCD->CSR = DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_ADC_ETC);
dma.enable();
dma.attachInterrupt(isr);
}
void isr()
{
dma.clearInterrupt();
Serial.printf("isr %u\n", output);
}
void loop()
{
// make measurements with ADC1 while ADC_ETC uses ADC2
Serial.printf("\tA0 = %d\n", analogRead(A0));
delay(1000);
}