I have been unable to find a chart that maps out which of the analog read pins is connected to which of the two ADCs on the chip for the Teensy 4.0.
Could anyone help me find this information?
Thank you in advance
I have been unable to find a chart that maps out which of the analog read pins is connected to which of the two ADCs on the chip for the Teensy 4.0.
Could anyone help me find this information?
Thank you in advance
I extracted this from pg3457-3458 of the IMXRT1060 Ref manual and used the pinouts from page 1 of the T4 Beta Thread: Hope it helps:
Code:14/A0 AD_B1_02 ADC1_IN7 Analog channel 1 input 7 15/A1 AD_B1_03 ADC1_IN8 Analog channel 1 input 8 16/A2 AD_B1_07 ADC1_IN12 Analog channel 1 input 12 17/A3 AD_B1_06 ADC1_IN11 Analog channel 1 input 11 18/A4 AD_B1_01 ADC1_IN6 Analog channel 1 input 6 19/A5 AD_B1_00 ADC1_IN5 Analog channel 1 input 5 20/A6 AD_B1_10 ADC1_IN15 Analog channel 1 input 15 21/A7 AD_B1_11 ADC 2_IN0 Analog channel 2 input 0 22/A8 AD_B1_08 ADC1_IN13 Analog channel 1 input 13 23/A9 AD_B1_09 ADC1_IN14 Analog channel 1 input 14 --- ---- 24/A10 AD_B0_12 ADC2_IN1 Analog channel 2 input 1 25/A11 AD_B0_13 ADC2_IN2 Analog channel 2 input 2 26/A12 AD_B1_14 ADC2_IN3 Analog channel 2 input 3 27/A13 AD_B1_15 ADC2_IN4 Analog channel 2 input 4
Last edited by mjs513; 11-14-2019 at 02:15 PM.
I might need to double check my spreadsheet, but I have:
Sorry if things don't align properly...Code:Pin Name GPIO Analog 0 AD_B0_03 1.3 1 AD_B0_02 1.2 2 EMC_04 4.4 3 EMC_05 4.5 4 EMC_06 4.6 5 EMC_08 4.8 6 B0_10 2.10 7 B1_01 2.17 8 B1_00 2.16 9 B0_11 2.11 10 B0_00 2.0 11 B0_02 2.2 12 B0_01 2.1 13 B0_03 2.3 14/A0 AD_B1_02 1.18 A1:7, A2:7 15/A1 AD_B1_03 1.19 A1:8, A2:8 16/A2 AD_B1_07 1.23 A1:12, A2:12 17/A3 AD_B1_06 1.22 A1:11, A2:11 18/A4 AD_B1_01 1.17 A1:6, A2:6 19/A5 AD_B1_00 1.16 A1:5, A2:5 20/A6 AD_B1_10 1.26 A1:15, A2:15 21/A7 AD_B1_11 1.27 A1:0, A2:0 22/A8 AD_B1_08 1.24 A1:13, A2:13 23/A9 AD_B1_09 1.25 A1:14, A2:14 --- ---- ---- ------ 24/A10 AD_B0_12 1.12 A1:1 25/A11 AD_B0_13 1.13 A1:2 26/A12 AD_B1_14 1.30 A2:3 27/A13 AD_B1_15 1.31 A2:4 28 EMC_32 3.18 29 EMC_31 4.31 30 EMC_37 3.23 31 EMC_36 3.22 32 B0_12 2.12 33 EMC_07 4.7 34 SD_B0_03 2.15 35 SD_B0_02 3.14 36 SD_B0_01 3.13 37 SD_B0_00 3.12 38 SD_B0_05 3.17 39 SD_B0_04 3.16
Note: As you can see many of these pins can actually connect to either ADC...
Another side hint is to look at analog.c where it maps pins to channels. Removing the #if 0 stuff... we have:
But this only shows which ones we use, not which ones we could use... Note the 128+ marks those which we map to ADC2.Code:const uint8_t pin_to_channel[] = { // pg 482 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 1, // 24/A10 AD_B0_12 2, // 25/A11 AD_B0_13 128+3, // 26/A12 AD_B1_14 - only on ADC2, 3 128+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 1, // 24/A10 AD_B0_12 2, // 25/A11 AD_B0_13 128+3, // 26/A12 AD_B1_14 - only on ADC2, 3 128+4 // 27/A13 AD_B1_15 - only on ADC2, 4 };
Edit: Side note about this above table. It is setup to look like pin 0 is attached as an analog pin, which it is not, instead this is due to the historical way you can call analogRead. That is analogRead(0) is the same thing as analogRead(A0) which in our case is the same as analogRead(14);
@KurtE
Your list is actually better than mine - I missed the second ADC assignment when I went through your list. I must have an outdated spreadsheet -the one I have doesn't have the analog pins.
Edit: oops - yes it does but is on the beta 1 tab.
Good morning @mjs513... Again not sure who might be interested, but I put my Excel documents up on github: https://github.com/KurtE/TeensyDocuments
Great, thank you both very much.
For the pins that can connect to both ADCs, the decision would be made by choosing an appropriate setting in the code while initializing the pin, correct?
I could be wrong, but I believe for those pins which connect to both, it always uses the first one... i.e. the code table in analog.c does not keep mark that it can use either. But since the code for analogRead(pin) does not return until completed, it probably make much difference.
However hopefully at some point the library ADC will be updated to work on T4. But so far I have not seen anything up on the github project showing any progress toward this.
Hi KurtE,
Any idea how to assign pins to a particular ADC, similar to analogRead(XX, ADC_0/ADC_1) in adc.h? I am trying to sample a 15 MHz sine wave using two analog pins and I want them to happen simultaneously. If I understand correctly, analogRead() will be assigned to ADC and it'll take some time to complete before the next analogRead() is performed. I was hoping to use two separate ADCs to do simultaneous measurements.
Code:v1 = analogRead(A2); v2 = analogRead(A3);
> I am trying to sample a 15 MHz sine wave
You will need to use an external ADC with parallel output. Or an external track and hold with periodic sampling.
@tsaha - As I have mentioned I do most things in digital, so others maybe can help more.
It would be great if the library ADC was ported over to the T4. But it looks like the owner (pedvide) of it, has not been up on the forum for maybe a year and a half, and the last update to the library was over two years ago...
So again another useful library that has been semi-orphaned.
Again as I mentioned, the default call analogRead(pin) will not return until it is done doing the analog conversion. so assigning to the two different ADCs probably would not help you much here..
Again not sure how hard it would be to setup at least a subset of the ADC library for T4, that allows you to do some of this.
More details about this library up in the thread: https://forum.pjrc.com/threads/25532...for-Teensy-3-1
Again I am not sure hard it would be... I might take a quick look to see if at least some of the basics can be ported... But again would be better if someone who really understands and uses Analog stuff would do it!
@tasha
Just to let you know the default settings on initialization is to do a 32 point average using 10bit ADC. You might reduce the time by setting analogReadAveraging. Allowable averages are 4, 8, 16 and 32 point averages.
Looked at the ADC library a while ago - complicated for me to modify the whole thing but a subset of the library is probably doing for the T4. But as @KurtE haven't looked at it for awhile.
@tasha @mjs513 - I hacked up a version of AnalogRead that allowed me to choose a channel 1 or 2 to do conversion.
Also did a version where I broke it into two parts. First starts conversion, second checks or waits for completion... Parts of it sort of work..
Not sure how reliable...
But if you want to take a look:
@KurtE
Thanks. Going to have to update a couple of other functions as well. AnanlogResolution and analogreadaveragering. Just as a note may have to use that other function on reinitialiaztion of changes. Have a couple of other ideas but sick as a dog right now, head in fog argh
@KurtE - @Paul
Was going through analog.c again and was thinking since this is a lite version in order support the second ADC would it be better just to update analog.c to support the second adc?
I checked and verified that analogReadAveraging(3) will speed things up. The result with analogRead() was 5 usec per sample.
With the right code, I'd expect < 1 usec per sample and 2x faster than that when alternating between two ADCs.
Perhaps others have hard data wrt "how fast is teensy 4 ADC?".
@KurtE - @tasha
Ok tried the other route and adds too much complexity to the situation. So I just added T4AnalogReadRes(pin, adc) as well as T4AnalogReadAveraging(pin, adc) .
T4_ADC_Lite.zip
My quick look through the functions, analogResolution and analogReadAveraging, I thought they were both already handling both ADC1 and ADC2
Example analogReadRes:
Currently analog.c only supports doing one analog operation at a time. So it only bothers to use ADC2 if you asked for one of the few pins that only have support on ADC2.Code:void analogReadRes(unsigned int bits) { uint32_t tmp32, mode; if (bits == 8) { // 8 bit conversion (17 clocks) plus 8 clocks for input settling mode = ADC_CFG_MODE(0) | ADC_CFG_ADSTS(3); } else if (bits == 10) { // 10 bit conversion (17 clocks) plus 20 clocks for input settling mode = ADC_CFG_MODE(1) | ADC_CFG_ADSTS(2) | ADC_CFG_ADLSMP; } else { // 12 bit conversion (25 clocks) plus 24 clocks for input settling mode = ADC_CFG_MODE(2) | ADC_CFG_ADSTS(3) | ADC_CFG_ADLSMP; } tmp32 = (ADC1_CFG & (0xFFFFFC00)); tmp32 |= (ADC1_CFG & (0x03)); // ADICLK tmp32 |= (ADC1_CFG & (0xE0)); // ADIV & ADLPC tmp32 |= mode; ADC1_CFG = tmp32; tmp32 = (ADC2_CFG & (0xFFFFFC00)); tmp32 |= (ADC2_CFG & (0x03)); // ADICLK tmp32 |= (ADC2_CFG & (0xE0)); // ADIV & ADLPC tmp32 |= mode; ADC2_CFG = tmp32; }
And likewise in "lite ADC" code I put in above sketch, there are a few pins that only are on ADC1... Which I marked (actually there are a couple of them I did not mark yet (that is most of the pins are in this table twice (one for the actual pin number and the other for the A number)...
I am not sure what else to do for a Light version... Could create another simple method like:
Obviously there is a ton of other stuff that one could try, like DMA support or other form of continuous updates, ...Code:bool T4AnalogRead(uint8_t adc1_pin, uint16_t &adc1_val, uint8_t adc2_pin, uint16_t &adc2_val);
But that probably is a very big diversion![]()
@KurtE
Yep it handles them but it setups up the same resolution and averaging for both channels (ADC1 and ADC2). At least I think that is how it is currently working. Changing it this way allows you to change them on a channel basis. Again haven't tested it yet.
Oh - big diversion! [EDIT] and I just went back to playing with usbhostOriginally Posted by KurtE
![]()
@mjs513 I went ahead and hacked in the function I mentioned...
Also put in loop calls to set the averaging... Although I just used the default one so far..
T4_ADC_Lite-191202b.zip
usbHost - Something new and shiny to play with?
Based on the manual, 0.85 us is possible. Also, analogReadAveraging(X), where X<4, should turn off hardware averaging, is that correct?
Code:void analogReadAveraging(unsigned int num) { uint32_t mode, mode1; //disable averaging, ADC1 and ADC2 ADC1_GC &= ~0x20; mode = ADC1_CFG & ~0xC000; ADC2_GC &= ~0x20; mode1 = ADC2_CFG & ~0xC000; if (num >= 32) { mode |= ADC_CFG_AVGS(3); mode1 |= ADC_CFG_AVGS(3); } else if (num >= 16) { mode |= ADC_CFG_AVGS(2); mode1 |= ADC_CFG_AVGS(2); } else if (num >= 8) { mode |= ADC_CFG_AVGS(1); mode1 |= ADC_CFG_AVGS(1); } else if (num >= 4) { mode |= ADC_CFG_AVGS(0); mode1 |= ADC_CFG_AVGS(0); } else { mode |= 0; mode1 |= 0; } ADC1_CFG |= mode; ADC2_CFG |= mode1; if(num >= 4){ ADC1_GC |= ADC_GC_AVGE;// turns on averaging ADC2_GC |= ADC_GC_AVGE;// turns on averaging } }
Looks like there is some kind of bug. The first time it hits 4 the time is 36. The second time it is 279.
Quick and dirty T4 Analog Read stuff
1> 4 2 10 : 2 3 10 : 1 3 5 : 1 2 5
2> 1 2 10 : 2 0 10 : 0 1 5 : 1 0 5
4> 5 6 36 : 6 3 36 : 6 4 18 : 6 4 18
8> 7 6 71 : 7 4 71 : 6 4 35 : 6 4 36
16> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
32> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
64> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
1> 1 2 10 : 2 0 10 : 1 2 5 : 1 1 5
2> 0 2 10 : 2 0 10 : 1 5 5 : 0 5 5
4> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
8> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
16> 7 7 279 : 7 4 280 : 7 4 142 : 7 4 141
32> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
64> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
Yep does sort of look like maybe a bug? Will take a look later
Yes it is a bug in the analogReadAveraging
As you can see it is not properly updating the ADC1_CFG field (assume ADC2 as well)Code:1(000006b7 00000000)> 7 507 10 : 19 507 10 : 1 507 5 : 2 507 5 2(000006b7 00000000)> 1 507 10 : 19 507 10 : 1 514 5 : 1 507 5 4(000006b7 00000020)> 8 515 36 : 12 515 36 : 8 517 18 : 8 513 19 8(000046b7 00000020)> 9 517 71 : 11 517 71 : 9 516 36 : 9 517 35 16(0000c6b7 00000020)> 10 517 280 : 10 517 281 : 9 517 141 : 9 517 142 32(0000c6b7 00000020)> 10 517 280 : 10 518 281 : 9 518 141 : 9 517 142 64(0000c6b7 00000020)> 9 518 280 : 10 517 281 : 9 518 141 : 9 517 142 1(0000c6b7 00000000)> 1 507 10 : 19 507 10 : 1 507 5 : 1 507 5 2(0000c6b7 00000000)> 1 507 10 : 19 507 10 : 1 513 5 : 1 507 5 4(0000c6b7 00000020)> 9 518 280 : 10 517 281 : 9 518 141 : 9 517 142 8(0000c6b7 00000020)> 10 517 280 : 10 517 281 : 9 518 141 : 9 517 141 16(0000c6b7 00000020)> 9 518 280 : 10 517 281 : 9 518 141 : 9 518 141 32(0000c6b7 00000020)> 10 517 280 : 10 517 281 : 9 517 141 : 10 518 141 64(0000c6b7 00000020)> 9 517 280 : 10 518 281 : 9 518 141 : 9 518 141
Looks like: void analogReadAveraging is buggy!Code:Serial.printf("%u(%08x %08x)> %d %d %u : %d %d %u : %d %d %u : %u %u %u\n", averaging_count,ADC1_CFG, ADC1_GC, a0, a1, t2 - t1, a0_4, a1_4, t3 - t2, a0_4C, a1_4C, t4 - t3, a0_both, a1_both, t5 - t4);
That is: look at how ADC1_CFG is updated.
If you look at the RED lines. The variable mode is assigned the current value of the ADC1_CFG minus the bits associated with ADC_CFG_AVGS(n)... Which is fine, and then we update the mode variable to have the proper value for those bits, and then we or mode back into ADC1_CFGCode:void analogReadAveraging(unsigned int num) { uint32_t mode, mode1; //disable averaging, ADC1 and ADC2 ADC1_GC &= ~0x20; mode = ADC1_CFG & ~0xC000; ADC2_GC &= ~0x20; mode1 = ADC2_CFG & ~0xC000; if (num >= 32) { mode |= ADC_CFG_AVGS(3); mode1 |= ADC_CFG_AVGS(3); } else if (num >= 16) { mode |= ADC_CFG_AVGS(2); mode1 |= ADC_CFG_AVGS(2); } else if (num >= 8) { mode |= ADC_CFG_AVGS(1); mode1 |= ADC_CFG_AVGS(1); } else if (num >= 4) { mode |= ADC_CFG_AVGS(0); mode1 |= ADC_CFG_AVGS(0); } else { mode |= 0; mode1 |= 0; } ADC1_CFG |= mode; ADC2_CFG |= mode1; if(num >= 4){ ADC1_GC |= ADC_GC_AVGE;// turns on averaging ADC2_GC |= ADC_GC_AVGE;// turns on averaging } }
First fix attempt:
That appears to work, so I pushed the change up to github coresCode:ADC1_CFG = mode; ADC2_CFG = mode1;
@Paul - if you are looking it is in my currently pending PR in cores: https://github.com/PaulStoffregen/cores/pull/404
Also updated sketch version as well, and change sketch to use it...T4_ADC_Lite-191202c.zip