#include <ADCL_t4.h>
#define USE_TIMED_READS
#define USE_PIT0
const int readPin = A0;
const int readPin2 = A1;
const int readPin3 = A2;
const int readPin4 = A3;
ADCL *adc = new ADCL(); // adc object
// chain A0 A1 AD_B1_02 AD_B1_03 ADC1 IN7 8
#define PRREG(x) Serial.print(#x" 0x"); Serial.println(x,HEX)
volatile uint32_t val0, val1;
volatile uint32_t adcValues[4];
void adcetc0_isr() {
digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
ADC_ETC_DONE0_1_IRQ |= 1; // clear
//val0 = ADC_ETC_TRIG0_RESULT_1_0 & 4095;
adcValues[0] = ADC_ETC_GetADCConversionValue(0U, 0U ); /* Get trigger0 chain0 result. */
adcValues[1] = ADC_ETC_GetADCConversionValue( 0U, 1U ); /* Get trigger0 chain1 result. */
adcValues[2] = ADC_ETC_GetADCConversionValue( 0U, 2U );
adcValues[3] = ADC_ETC_GetADCConversionValue( 0U, 3U );
asm("dsb");
}
void adcetc1_isr() {
//digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
ADC_ETC_DONE0_1_IRQ |= 1; // clear
//val0 = ADC_ETC_TRIG0_RESULT_1_0 & 4095;
adcValues[0] = ADC_ETC_GetADCConversionValue(0U, 0U ); /* Get trigger0 chain0 result. */
adcValues[1] = ADC_ETC_GetADCConversionValue( 0U, 1U ); /* Get trigger0 chain1 result. */
adcValues[2] = ADC_ETC_GetADCConversionValue( 0U, 2U );
adcValues[3] = ADC_ETC_GetADCConversionValue( 0U, 3U );
asm("dsb");
}
void setup() {
while (!Serial && millis() < 5000) ;
pinMode(LED_BUILTIN, OUTPUT);
pinMode(readPin, INPUT); //pin 23 single ended
pinMode(readPin2, INPUT); //pin 23 single ended
pinMode(readPin3, INPUT); //pin 23 single ended
pinMode(readPin4, INPUT); //pin 23 single ended
Serial.begin(9600);
Serial.println("Setup ADC_0");
// reference can be ADC_REFERENCE::REF_3V3, ADC_REFERENCE::REF_1V2 (not for Teensy LC) or ADC_REF_EXT.
//adc->setReference(ADC_REFERENCE::REF_1V2, ADC_0); // change all 3.3 to 1.2 if you change the reference to 1V2
adc->setAveraging(8); // set number of averages
adc->setResolution(12); // set bits of resolution
// 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
#ifdef USE_TIMED_READS
setup_adc_hardware_trigger(readPin, readPin2);
#else
adc->analogRead(readPin, ADC_0);
#endif
Serial.println("End Setup");
}
void loop() {
Serial.printf("%d %d %d %d\n", adcValues[0], adcValues[1], adcValues[2], adcValues[3]);
delay(500);
}
/*!
* 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.
*/
uint32_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;
}
void setup_adc_hardware_trigger(uint8_t pin,uint8_t pin2)
{
xbar_init();
Serial.println("After XBAR"); Serial.flush();
adc_init();
// dma_init(); // hopefully already done.
adc_etc_init(pin, pin2);
Serial.println("After ADC/ADC_ETC"); Serial.flush();
#ifdef USE_PIT0
pit_init(24 * 1000); // 1 khz 1000 ADCs/sec
#else
qtimer_init(3000.0); // try at 20 hz for test...
#endif
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);
}
#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 xbar_init() {
CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); //turn clock on for xbara1
#ifdef USE_PIT0
xbar_connect(XBARA1_IN_PIT_TRIGGER0, XBARA1_OUT_ADC_ETC_TRIG00); // pit to adc_etc
#else
xbar_connect(XBARA1_IN_QTIMER4_TIMER0, XBARA1_OUT_ADC_ETC_TRIG00); // pit to adc_etc
#endif
}
void adc_init() {
ADC1_CFG |= ADC_CFG_ADTRG; // hardware trigger
ADC1_HC0 = 16; // ADC_ETC channel
ADC1_HC1 = 16; // ADC_ETC channel
//ADC1_GC &= ~ADC_GC_ADCO;
attachInterruptVector(IRQ_ADC_ETC0, adcetc0_isr);
NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
attachInterruptVector(IRQ_ADC_ETC1, adcetc0_isr);
NVIC_ENABLE_IRQ(IRQ_ADC_ETC1);
}
void adc_etc_init(uint8_t pin, uint8_t pin2) {
IMXRT_ADC_ETC.CTRL = ADC_ETC_CTRL_SOFTRST; // SOFTRST
IMXRT_ADC_ETC.CTRL &= ~ADC_ETC_CTRL_SOFTRST; // SOFTRST
delay(5);
uint8_t adc_pin_channel = ADCL::mapPinToChannel(pin);
Serial.print("ADC Pin1 Channel: "); Serial.println(adc_pin_channel);
IMXRT_ADC_ETC.CTRL = (ADC_ETC_CTRL_TSC_BYPASS | ADC_ETC_CTRL_TRIG_ENABLE(1)); // 0x40000001; // start with trigger 0
Serial.printf("ADC_ETC_CTRL: %x %x\n", IMXRT_ADC_ETC.CTRL, ADC_ETC_CTRL_TRIG_ENABLE(1));
IMXRT_ADC_ETC.TRIG[0].CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(3); // chainlength -1 only us
IMXRT_ADC_ETC.TRIG[0].CHAIN_1_0 = ADC_ETC_TRIG_CHAIN_B2B0 |
ADC_ETC_TRIG_CHAIN_IE0(1) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel) ;
adc_pin_channel = ADCL::mapPinToChannel(pin2);
Serial.print("ADC Pin2 Channel: "); Serial.println(adc_pin_channel);
IMXRT_ADC_ETC.TRIG[0].CHAIN_1_0 |= ADC_ETC_TRIG_CHAIN_B2B1 |
ADC_ETC_TRIG_CHAIN_IE1(2) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS1(2) | ADC_ETC_TRIG_CHAIN_CSEL1(adc_pin_channel);
Serial.print("TRIG[0].CHAIN_1_0: "); Serial.println(IMXRT_ADC_ETC.TRIG[0].CHAIN_1_0, HEX);
//ADC_ETC_TRIG0_CHAIN_1_0 = 0x1017; // ADC1 7 chain channel, HWTS, BB? TODO
// From other sample
//ADC_ETC_TRIG0_CTRL = ADC_ETC_TRIG_CTRL_SYNC_MODE; // 0x100; // chainlength -1
//ADC_ETC_TRIG0_CHAIN_1_0 = 0x50283017; // ADC1 7 8, chain channel, HWTS, IE, B2B
uint32_t tmp, tmp32;
adc_pin_channel = ADCL::mapPinToChannel(readPin3);
Serial.print("ADC Pin3 Channel: "); Serial.println(adc_pin_channel);
IMXRT_ADC_ETC.TRIG[0].CHAIN_3_2 = ADC_ETC_TRIG_CHAIN_B2B0 |
ADC_ETC_TRIG_CHAIN_IE0(1) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel) ;
adc_pin_channel = ADCL::mapPinToChannel(readPin4);
Serial.print("ADC Pin4 Channel: "); Serial.println(adc_pin_channel);
IMXRT_ADC_ETC.TRIG[0].CHAIN_3_2 |= ADC_ETC_TRIG_CHAIN_B2B1 |
ADC_ETC_TRIG_CHAIN_IE1(2) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
| ADC_ETC_TRIG_CHAIN_HWTS1(2) | 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);
attachInterruptVector(IRQ_ADC_ETC0, adcetc0_isr);
NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
attachInterruptVector(IRQ_ADC_ETC1, adcetc0_isr);
NVIC_ENABLE_IRQ(IRQ_ADC_ETC1);
}
#ifdef USE_PIT0
void pit_init(uint32_t cycles)
{
CCM_CCGR1 |= CCM_CCGR1_PIT(CCM_CCGR_ON);
PIT_MCR = 0;
IMXRT_PIT_CHANNELS[0].LDVAL = cycles;
IMXRT_PIT_CHANNELS[0].TCTRL = PIT_TCTRL_TEN;
}
#else
void qtimer_init(float freq) // try at 20 hz for test...
{
Serial.println("Try to init QTimer"); Serial.flush();
quadtimer_init(&IMXRT_TMR4);
quadtimerFrequency(&IMXRT_TMR4, 0, freq);
quadtimerWrite(&IMXRT_TMR4, 0, 5);
Serial.println("After Qtimer init"); Serial.flush();
}
#endif
#endif