High speed (10Mhz) parallel transfers from a 10MSPS ADC on a Teensy 3.6?

Status
Not open for further replies.

Scientist

Well-known member
Hi all,

We have been using Teensy 3.2's and more recently Teensy 3.6s to implement control functions on a variety of instruments for atmospheric science. It is a fantastic platform - great performance (even at low temperatures), feature rich and easy to develop. Now we are thinking about using a Teensy 3.6 for a data acquisition project that involves detecting pulse heights using a high speed ADC. We would like to sample a burst of samples (using a TI ADC10321 10 Bit parallel ADC) at 10MSPS and find the lowest value in the a burst of ~100 samples - before we buy parts and spin a board, a couple of questions for those wo have done high speed work before:

Are the GPIO pins capable of receiving data at 10Mhz (it seems like they should be with a 60Mhz Bus Clock)?

Will we need to setup a DMA channel to store the data and then find the valley after we have collected the data, or do you think we can do this in real time with simple comparison operators on the incoming bytes?

Any other pointers on high speed ADCs?

Thanks in advance!
 
A quick update - I can read the from PORT_C at better than 10Mhz by just reading the port with a series of calls like this:
Code:
  in_buff[0] = GPIOC_PDIR;  
  in_buff[1] = GPIOC_PDIR; 
  in_buff[2] = GPIOC_PDIR;

This would be fast enough for the ADC, but the problem is that the data from the ADC is only guaranteed to be valid on the rising edge of the clock. If I trigger a read using an interrupt from the rising edge of a clock things slow way down and I can only read at ~2MHz. Any pointers on how to do a high read from a digital port, clocked by an external source?
 
It is possible to configure a pin to trigger a DMA request on rising, falling, or both edges. Check the "Port Control and Interrupts (PORT)" chapter. The DMA transfer control descriptor has plenty of configuration options, and it's likely to meet your project's needs.

Edit: Assuming your description requiring finding the lowest value from a block of samples, then the earliest the application can deliver a result is after the last sample (either immediately or after a small latency...) The processor would blast through a short linear list of elements *very* quickly.
 
Last edited:
I think it can be done in real time. First, poll on the clock for a rising edge. My TeensyLogicAnalyzer is able to poll every 4-5 clock cycles. Assuming the clock is on the same port as the data, it would take 5-6 clocks to compare and save if the lowest value. If you don't optimize too much (i.e. no assembly language :) ), maybe 12 clocks per sample. So a CPU clock of 120 MHz should be able to sample at 10 MHz.

Your example code probably takes 5-7 clock cycles. Best case is 2 cycles to read port, 2 to store, and 1 to increment storage pointer. If you oversample by at least 2x, you can post-process the data, looking for first sample after the clock goes high.

This could be done with a 3.5 or 3.6, or even a 3.2 by overclocking. A 3.6 at 180 MHz should be able to do it without worrying too much about optimization. Be sure to disable interrupts while sampling.

DMA would work, but it is more complicated. When I tried it for sampling, it was not as fast as I thought it would be, and not as consistent.
 
Using the simple code shown above I can get at least 2 samples on both the high and low phases of the clock (which I can put on the same port), so as a fallback solution I can just grab a bunch of samples and filter them for the first sample after the clock goes high as suggested by LAtimes. I will play around with both DMA and polling the clock to see if either of these approaches will be fast enough and report back. Thanks for the link to the Logic Analyzer project - that will be useful both in terms of code examples, but also to use as a logic analyzer to debug this mess.
 
Also, it turns out we may need to interface to two ADCS in parallel to support two gain stages. This would be easy of there were 20 pins of one port available, but that doesn't appear to be the case - so we will have to read PORTC and PORTD which both have 10 pins broken out to pins on the T3.6. I still think it is doable.

It is possible to overclock F_BUS? I have read posts mentioning this, but don't see how it is actually done.
 
It is possible to overclock F_BUS (don't tell anybody, but I've run up to 240 MHz on a 3.6 for SPI :cool:), but the GPIO Ports are not tied to F_BUS, they are just a function of F_CPU (2 clocks per read/write except in special cases). So it wouldn't make a difference in this case.
 
OK, so it seems that the only way I am able to sustain 10MHz throughput on a digital port is by successive reads. Adding either polling or an interrupt on the rising edge of a clock pin slows things down to 1-2Mhz and using a free running DMA transfer (as described here: https://forum.pjrc.com/threads/3872...in-read-method?p=121468&viewfull=1#post121468 ) seems to give the same response. Using the code below, and then filtering the data to only use the first of two reads on the high phase of the clock will work, but with two channels I can only read at 5MHz. This will probably be sufficient, but I am wondering if anyone sees any ways to speed things up? I have been reading about whether I could use the digital filter on the GPIO pins to make sure the data is stable for 30ns (which is the settling time on my ADC) so that I can be assured that any read it accurate, but I haven't convinces myself that would help.
Code:
/* Set up pins for PORTC */
#define P0 15
#define P1 22
#define P2 23
#define P3 9
#define P4 10
#define P5 13
#define P6 11
#define P7 12
#define P8 35
#define P9 36

#define CLK 14
#define PULSE 16

volatile uint16_t in_buff[64];
volatile uint16_t in_buff2[64];
volatile int cnt = 0;
volatile uint16_t dummy;


void setup() {
 //Set fast slew rate for PORCT_C[0] and CLK and turn off passive fitler
CORE_PIN16_CONFIG &= ~PORT_PCR_SRE;
CORE_PIN15_CONFIG &= ~PORT_PCR_SRE;
CORE_PIN14_CONFIG &= ~PORT_PCR_SRE;
CORE_PIN15_CONFIG = 0x100; 
CORE_PIN14_CONFIG = 0x100;   

pinMode(P0, INPUT); // put a function generator on this pin 5 - 10MHz square wave
pinMode(P1, OUTPUT);
pinMode(P2, OUTPUT);
pinMode(P3, OUTPUT);
pinMode(P4, OUTPUT);
pinMode(P5, OUTPUT);
pinMode(P6, OUTPUT);
pinMode(P7, OUTPUT);
pinMode(P8, OUTPUT);
pinMode(P9, OUTPUT);

pinMode(PULSE, INPUT); //Simulated pulse above threshold signal

pinMode(CLK, INPUT); //CLK Pin - also tied to 10Mhz square wave

/*Set all the other bits LOW to avoid confusion*/
digitalWrite(P1, LOW);
digitalWrite(P2, LOW);
digitalWrite(P3, LOW);
digitalWrite(P4, LOW);
digitalWrite(P5, LOW);
digitalWrite(P6, LOW);
digitalWrite(P7, LOW);
digitalWrite(P8, LOW);
digitalWrite(P9, LOW);


Serial.begin(115200);
delay(1000);

}

void loop() 
{
 int i;

  GetSamples();

  for(i = 0; i < 64; i++)
    {
    Serial.print(in_buff[i]);
    Serial.print(" ");
    }
    Serial.println(" ");    
    delay(1000); 

}


FASTRUN void GetSamples(void)
{
  in_buff[0] = GPIOC_PDIR; in_buff2[0] = GPIOD_PDIR;
  in_buff[1] = GPIOC_PDIR; in_buff2[1] = GPIOD_PDIR;
  in_buff[2] = GPIOC_PDIR; in_buff2[2] = GPIOD_PDIR;
  in_buff[3] = GPIOC_PDIR; in_buff2[3] = GPIOD_PDIR;
  in_buff[4] = GPIOC_PDIR; in_buff2[4] = GPIOD_PDIR;
  in_buff[5] = GPIOC_PDIR; in_buff2[5] = GPIOD_PDIR;
  in_buff[6] = GPIOC_PDIR; in_buff2[6] = GPIOD_PDIR;
  in_buff[7] = GPIOC_PDIR; in_buff2[7] = GPIOD_PDIR;
  in_buff[8] = GPIOC_PDIR; in_buff2[8] = GPIOD_PDIR;
  in_buff[9] = GPIOC_PDIR; in_buff2[9] = GPIOD_PDIR;
  in_buff[10] = GPIOC_PDIR; in_buff2[10] = GPIOD_PDIR;
  in_buff[11] = GPIOC_PDIR; in_buff2[11] = GPIOD_PDIR;
  in_buff[12] = GPIOC_PDIR; in_buff2[12] = GPIOD_PDIR;
  in_buff[13] = GPIOC_PDIR; in_buff2[13] = GPIOD_PDIR;
  in_buff[14] = GPIOC_PDIR; in_buff2[14] = GPIOD_PDIR;
  in_buff[15] = GPIOC_PDIR; in_buff2[15] = GPIOD_PDIR;
  in_buff[16] = GPIOC_PDIR; in_buff2[16] = GPIOD_PDIR;
  in_buff[17] = GPIOC_PDIR; in_buff2[17] = GPIOD_PDIR;
  in_buff[18] = GPIOC_PDIR; in_buff2[18] = GPIOD_PDIR;
  in_buff[19] = GPIOC_PDIR; in_buff2[19] = GPIOD_PDIR;
  in_buff[20] = GPIOC_PDIR; in_buff2[20] = GPIOD_PDIR;
  in_buff[21] = GPIOC_PDIR; in_buff2[21] = GPIOD_PDIR;
  in_buff[22] = GPIOC_PDIR; in_buff2[22] = GPIOD_PDIR;
  in_buff[23] = GPIOC_PDIR; in_buff2[23] = GPIOD_PDIR;
  in_buff[24] = GPIOC_PDIR; in_buff2[24] = GPIOD_PDIR;
  in_buff[25] = GPIOC_PDIR; in_buff2[25] = GPIOD_PDIR;
  in_buff[26] = GPIOC_PDIR; in_buff2[26] = GPIOD_PDIR;
  in_buff[27] = GPIOC_PDIR; in_buff2[27] = GPIOD_PDIR;
  in_buff[28] = GPIOC_PDIR; in_buff2[28] = GPIOD_PDIR;
  in_buff[29] = GPIOC_PDIR; in_buff2[29] = GPIOD_PDIR;
  in_buff[30] = GPIOC_PDIR; in_buff2[30] = GPIOD_PDIR;
  in_buff[31] = GPIOC_PDIR; in_buff2[31] = GPIOD_PDIR;
  in_buff[32] = GPIOC_PDIR; in_buff2[32] = GPIOD_PDIR;
  in_buff[33] = GPIOC_PDIR; in_buff2[33] = GPIOD_PDIR;
  in_buff[34] = GPIOC_PDIR; in_buff2[34] = GPIOD_PDIR;
  in_buff[35] = GPIOC_PDIR; in_buff2[35] = GPIOD_PDIR;
  in_buff[36] = GPIOC_PDIR; in_buff2[36] = GPIOD_PDIR;
  in_buff[37] = GPIOC_PDIR; in_buff2[37] = GPIOD_PDIR;
  in_buff[38] = GPIOC_PDIR; in_buff2[38] = GPIOD_PDIR;
  in_buff[39] = GPIOC_PDIR; in_buff2[39] = GPIOD_PDIR;
  in_buff[40] = GPIOC_PDIR; in_buff2[40] = GPIOD_PDIR;
  in_buff[41] = GPIOC_PDIR; in_buff2[41] = GPIOD_PDIR;
  in_buff[42] = GPIOC_PDIR; in_buff2[42] = GPIOD_PDIR;
  in_buff[43] = GPIOC_PDIR; in_buff2[43] = GPIOD_PDIR;
  in_buff[44] = GPIOC_PDIR; in_buff2[44] = GPIOD_PDIR;
  in_buff[45] = GPIOC_PDIR; in_buff2[45] = GPIOD_PDIR;
  in_buff[46] = GPIOC_PDIR; in_buff2[46] = GPIOD_PDIR;
  in_buff[47] = GPIOC_PDIR; in_buff2[47] = GPIOD_PDIR;
  in_buff[48] = GPIOC_PDIR; in_buff2[48] = GPIOD_PDIR;
  in_buff[49] = GPIOC_PDIR; in_buff2[49] = GPIOD_PDIR;
  in_buff[50] = GPIOC_PDIR; in_buff2[50] = GPIOD_PDIR;
  in_buff[51] = GPIOC_PDIR; in_buff2[51] = GPIOD_PDIR;
  in_buff[52] = GPIOC_PDIR; in_buff2[52] = GPIOD_PDIR;
  in_buff[53] = GPIOC_PDIR; in_buff2[53] = GPIOD_PDIR;
  in_buff[54] = GPIOC_PDIR; in_buff2[54] = GPIOD_PDIR;
  in_buff[55] = GPIOC_PDIR; in_buff2[55] = GPIOD_PDIR;
  in_buff[56] = GPIOC_PDIR; in_buff2[56] = GPIOD_PDIR;
  in_buff[57] = GPIOC_PDIR; in_buff2[57] = GPIOD_PDIR;
  in_buff[58] = GPIOC_PDIR; in_buff2[58] = GPIOD_PDIR;
  in_buff[59] = GPIOC_PDIR; in_buff2[59] = GPIOD_PDIR;
  in_buff[60] = GPIOC_PDIR; in_buff2[60] = GPIOD_PDIR;
  in_buff[61] = GPIOC_PDIR; in_buff2[61] = GPIOD_PDIR;
  in_buff[62] = GPIOC_PDIR; in_buff2[62] = GPIOD_PDIR;
  in_buff[63] = GPIOC_PDIR; in_buff2[63] = GPIOD_PDIR;
 
}

Here is the output at 5MHz:
Code:
1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0

Which gives 2 samples on the high and low phases, which is enough to ensure the data is valid.

And here is the output at 10MHz:
Code:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
Which would work if the GPIO was synchronized, but is not fast enough if I have to detect the rising edge by looking at the clock phase.
 
What Board and CPU Speed are you using to compile this? I'll look at the assembly language it generates and see if it can be optimized. I haven't checked if any optimization levels are used for the 3.6 - for 3.2, it says 'optimize speed' or 'reduce code size', but 3.6 doesn't say either.

On paper it looks like it could read both ports and store them in 8 clock cycles, so it should be feasible at 180 MHz (18 cycles per sample).
 
I am using a Teensy 3.6, at 240Mhz. At 180Mhz, I can't guarantee 2 samples per clock phase. This is the only thing this board needs to do, so code size is not an issue.

Thanks for your help!

What Board and CPU Speed are you using to compile this? I'll look at the assembly language it generates and see if it can be optimized. I haven't checked if any optimization levels are used for the 3.6 - for 3.2, it says 'optimize speed' or 'reduce code size', but 3.6 doesn't say either.

On paper it looks like it could read both ports and store them in 8 clock cycles, so it should be feasible at 180 MHz (18 cycles per sample).
 
On further consideration - we are actually coming pretty close to 4 cycles per sample. I can over sample by a factor of 4 at 5Mhz for two channels - that comes to 40 million samples per second. At 240MHz that is 6 clock cycles per sample.

I could do much better if we didn't have to worry about the valid data issue - which brings me back to the digital filter. I can't find a detailed description of this works - but my understanding is that you set the number of clock cycles that an input must be constant for, and it only updates the input register when the signal on the pin has been constant for that period. So if I set up the digital filter with a period of half a clock cycle, the PDIR would always be valid - and I could read both ports at 10MHz without having to look for the rising edge of the clock. Am I on the right track here?
 
Here's what I have so far. Your code as is reads a value (ports c and d) every 12 clocks. At 240 MHz, this is 2 values per ADC clock - right at the edge of aliasing. I found a way to cut it down to 8 clocks by storing a single 32 bit value that is port c << 16 + port d. This gets it to 3 values per ADC clock, which is nicer.

I was able to get polling just the clock at 5 clocks. However, if the 2 ADCs are running asynchronously, then polling each one individually will be difficult.

I've never looked at the digital filtering.

I'll clean up my code and maybe try a couple more things tomorrow, then post it.
 
Here's what I came up with. If you only had a single ADC, you could use GetSamplesOnClockEdge, which polls for the rising edge of the clock. For 2 ADCs, I modified GetSamples to read ports C and D every 10 CPU clocks. This is fast enough to see every clock edge when post-processing.

I left in some timing code to count the CPU cycles. There is also some commented out code in setup that can generate PWM signals to simulate the clock and 3 data bits without any external signals. That's what I used to generate this output (port D is 0002, port C tries to cycle between 00F, 10F, 007, 107, 003, 103, 001, 101, 00F, ..., but isn't always synced up between clock and data):

GetSamples : 10 CPU clock ticks per sample (650 total)
2010F 2010F 20007 20107 20007 20103 20003 20001 20101 20001 2010F 2000F 20107 20107 20003 20103 20003 20101 20001 2010F 2010F 2000F 20107 20007 20103 20103 ...
GetSamplesOnClockEdge : 24 CPU clock ticks per sample (1546 total)
7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F 7 3 1 F

Code:
/* Set up pins for PORTC */
#define P0 15
#define P1 22
#define P2 23
#define P3 9
#define P4 10
#define P5 13
#define P6 11
#define P7 12
#define P8 35
#define P9 36

#define CLK 14
#define PULSE 16

#define MAX_SAMPLES 64

volatile uint32_t in_buff[MAX_SAMPLES];
volatile int cnt = 0;
volatile uint16_t dummy;


void setup() {
 //Set fast slew rate for PORCT_C[0] and CLK and turn off passive fitler
CORE_PIN16_CONFIG &= ~PORT_PCR_SRE;
CORE_PIN15_CONFIG &= ~PORT_PCR_SRE;
CORE_PIN14_CONFIG &= ~PORT_PCR_SRE;
CORE_PIN15_CONFIG = 0x100; 
CORE_PIN14_CONFIG = 0x100;   

pinMode(P0, INPUT); // put a function generator on this pin 5 - 10MHz square wave
pinMode(P1, OUTPUT);
pinMode(P2, OUTPUT);
pinMode(P3, OUTPUT);
pinMode(P4, OUTPUT);
pinMode(P5, OUTPUT);
pinMode(P6, OUTPUT);
pinMode(P7, OUTPUT);
pinMode(P8, OUTPUT);
pinMode(P9, OUTPUT);

pinMode(PULSE, INPUT); //Simulated pulse above threshold signal

pinMode(CLK, INPUT); //CLK Pin - also tied to 10Mhz square wave

/*Set all the other bits LOW to avoid confusion*/
digitalWrite(P1, LOW);
digitalWrite(P2, LOW);
digitalWrite(P3, LOW);
digitalWrite(P4, LOW);
digitalWrite(P5, LOW);
digitalWrite(P6, LOW);
digitalWrite(P7, LOW);
digitalWrite(P8, LOW);
digitalWrite(P9, LOW);

/***  uncommenting this will put test output signals on pins 9,22,23,35

// simulated clock
analogWriteFrequency (P8, 10000000);
analogWrite (P8, 128);

// delay to sync up clock and data (so that data changes on falling edge of clock)
for (int index = 0; index < 5; ++index);

// simulated data (E,6,2,0,E,6,2,0,E,...
analogWriteFrequency (P1, 2500000);
analogWrite (P1, 192);  // 75% duty cycle
analogWrite (P2, 128);  // 50% duty cycle
analogWrite (P3, 64);   // 25% duty cycle

***/

Serial.begin(115200);
delay(1000);

}

void loop() 
{

  GetSamples(MAX_SAMPLES);
  PrintSamples(MAX_SAMPLES);
  delay(1000); 

  GetSamplesOnClockEdge (MAX_SAMPLES);
  PrintSamples(MAX_SAMPLES);
  delay(5000); 
}

void PrintSamples(int numSamples)
{
  int i;

  for(i = 0; i < numSamples; i++)
  {
    Serial.print(in_buff[i], HEX);
    Serial.print(" ");
  }
  Serial.println(" ");
}

// reads a single ADC on a rising clock edge
void GetSamplesOnClockEdge(int numSamples)
{
  uint32_t *ptr = (uint32_t *)in_buff;
  register uint16_t data;

  int timeStart = SYST_CVR;  // time how long it takes

  // this reads a data sample when the clock goes high.
  // It uses a clock on bit 8 and bits 0-7 for data. Adjust as needed

  // counting down saves 1 CPU cycle
  for (int index = numSamples; index > 0; --index)
  {
    while (GPIOC_PDIR & 0x0100);              // wait for clock low
    while (!((data = GPIOC_PDIR) & 0x0100));  // wait for clock high
    *(ptr++) = data & 0x00FF;                 // save data
  }

  int timeEnd = SYST_CVR;
  int delta = timeStart - timeEnd - 2;  // time counts down; subtract 2 for timing instructions

  Serial.print ("GetSamplesOnClockEdge : ");
  Serial.print (delta / numSamples);  // time is in system clocks
  Serial.print (" CPU clock ticks per sample (");
  Serial.print (delta);
  Serial.print (" total)");
  Serial.println ("");
}

// FASTRUN - the 3.6 has a larger code cache so FASTRUN doesn't make much difference, if any

// reads 2 ADCs as fast as possible. Needs post-processing for clock edges
FASTRUN void GetSamples(int numSamples)
{
  uint32_t *ptr = (uint32_t *)in_buff;

  cli();  // disable interrupts

  int timeStart = SYST_CVR;  // time how long it takes

  // counting down saves 1 CPU cycle
  for (int index = numSamples; index > 0; --index)
  {
    *(ptr++) = (GPIOD_PDIR << 16) + GPIOC_PDIR;
  }

  int timeEnd = SYST_CVR;
  int delta = timeStart - timeEnd - 2;  // time counts down; subtract 2 for timing instructions

  sei();  // enable interrupts

  Serial.print ("GetSamples : ");
  Serial.print (delta / numSamples);  // time is in system clocks
  Serial.print (" CPU clock ticks per sample (");
  Serial.print (delta);
  Serial.print (" total)");
  Serial.println ("");
}

FYI - the reason I dove into this is because I can use it to add an external clock input to the logic analyzer, which is on the TODO list.
 
Sorry for the delay in response, but I finally had a chance to test this - I modified your code above to read two ports to simulate dual ADCs using both the clock edge method and the polling method. Either case gives me ~6Mhz throughput from the ADCs. The Polling method is obviously much faster in the raw throughput (24Mhz with the Teensy overclocked to 240Mhz), but I need to over sample by a factor of 4, leaving me with a net through put of 6MHz on each ADC. With the clock edge mode (both ADCs are on the same clock) I can almost get 7MHz from each ADC, but would probably limit this to 5-6MHz to avoid issues. This is sufficient for my application. Thanks again for all your help!
 
Your problem seems to be quite similar than mine, check https://forum.pjrc.com/threads/31029-Feasability-of-using-Teensy-3-1-for-a-telescope-autoguider-(processing-small-images)?goto=newpost
I managed to get only 4 MHz out of Teensy 3.2 with a bit less sophisticated code (with zero jitter) - still figuring out how to port it to T3.6.

Somewhere in the forums I saw somebody asking about using a FIFO memory device (AL422B), maybe something like that could help you?

LAtimes - Thanks so much for the code you posted, I see quite a few things I might try to implement in my code!
Is while (GPIOC_PDIR & 0x0100); a lot faster than while(digitalReadFast(27)); ?
And I presume that using the clock input on the same port as the data kills two birds with one stone and saves some cycles :)
What about the line with the pointer *(ptr++) = data & 0x00FF;, how do you save there compared to just using: inbuff[index] = data & 0x00FF; ?
 
Samo,

Code:
Is while (GPIOC_PDIR & 0x0100); a lot faster than while(digitalReadFast(27)); ?
digitalReadFast is very efficient as long as the pin number is a constant - if you use int pix_clk = 27, it will slow down since you could change it to another value at any time, but #define pix_clk 27 should be just as fast as reading the port directly. You could look into bitbanding to maybe make it faster - I may try that with my code.

Code:
And I presume that using the clock input on the same port as the data kills two birds with one stone and saves some cycles
Yes, if pix_clk was on the same port as the data, you would already have the data when pix_clk goes high.

Code:
What about the line with the pointer *(ptr++) = data & 0x00FF;, how do you save there compared to just using: inbuff[index] = data & 0x00FF; ?
By storing and incrementing at the same time, the compiler knows it can use a single instruction to save and increment instead of 2 to store the value and increment later.
 
What about the line with the pointer *(ptr++) = data & 0x00FF;, how do you save there compared to just using: inbuff[index] = data & 0x00FF; ?
By storing and incrementing at the same time, the compiler knows it can use a single instruction to save and increment instead of 2 to store the value and increment later.

It may depend on the context.
I found that most of the time actual compiler generates the same code when using pointer and index notation. So I usually stick with index notation as it is easier to read. To speed up significantly it is better to unwrap the code, but this may be difficult when testing the value of a port.
 
I wanted to report back on this project - I spun the boards and after some initial testing it looks like this is going to work very well. It turns out that waiting for the ADC output data to be valid is not going to be an issue. Using a variant of LATimes code, I am able to read both ADC at 10MSPS (in 12uS bursts) with no problem and no weird values. The board has a high speed hardware comparator that detects that the signal has risen above a threshold (set by the teensy DAC) which triggers the teensy to read 128 samples from the ADCs, and then sort through the data to find the highest sample in each channel. So far in bench testing it works beautifully.

Thanks for all the help!
 
Hi there,

I was wondering if things worked at the end. in my case I need to sample a 2 MHz sin wave and I want to sample it with at least 10 MSPS, if things worked out with you at the end can you share the method (the ADC reading part code) that you used or is it the same in comment #8, in my case I will be using only one ADC (this one here http://cds.linear.com/docs/en/datasheet/1420fa.pdf) and if it is possible I might go to 20 MSPS.
 
The code in post #8 worked well, and I went one step further by generating the ADC clock on the Teensy, which removed the need to oversample as we know the phase of the clock. I am running two ADCS with two clocks that are 180 degrees out of phase, that way I can read the data from alternating ADCs on both the high an low phases of the clock. Throughput is about 14MSPS for each ADC. Word of warning though, you can only run this code in short bursts as you quickly fill up the array.

Here is the code to grab 128 samples from each ADC:
Code:
//***********************************************************************************************
//***********************************************************************************************
//
//  -- takes two ADC clock cycles to start up the data pipe line
//  -- HG and LG ADC clocks are 180 deg out of phase to make sampling as fast as poosible
//  -- ADC samples analog value on negative clock edge, data valid 25ns after negative edge
//  -- Low Gain ADC is on Port D, High Gain ADC is on Port C
//
//***********************************************************************************************
//***********************************************************************************************
FASTRUN void Get_Pulse(void)
{
  while(digitalReadFast(TRIGGER_PULSE) == HIGH) {}       // wait for any old pulse to finish befor looking for new pulse
  while(digitalReadFast(TRIGGER_PULSE) == LOW) {}        // wait for new pulse
  
  cli();  // disable interrupts

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[0] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[0] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[1] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[1] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[2] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[2] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[3] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[3] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[4] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[4] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[5] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[5] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[6] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[6] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[7] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[7] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[8] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[8] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[9] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[9] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[10] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[10] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[11] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[11] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[12] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[12] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[13] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[13] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[14] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[14] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[15] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[15] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[16] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[16] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[17] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[17] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[18] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[18] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[19] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[19] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[20] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[20] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[21] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[21] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[22] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[22] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[23] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[23] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[24] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[24] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[25] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[25] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[26] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[26] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[27] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[27] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[28] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[28] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[29] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[29] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[30] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[30] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[31] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[31] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[32] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[32] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[33] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[33] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[34] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[34] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[35] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[35] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[36] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[36] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[37] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[37] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[38] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[38] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[39] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[39] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[40] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[40] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[41] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[41] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[42] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[42] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[43] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[43] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[44] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[44] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[45] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[45] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[46] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[46] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[47] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[47] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[48] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[48] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[49] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[49] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[50] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[50] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[51] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[51] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[52] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[52] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[53] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[53] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[54] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[54] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[55] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[55] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[56] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[56] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[57] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[57] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[58] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[58] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[59] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[59] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[60] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[60] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[61] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[61] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[62] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[62] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[63] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[63] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[64] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[64] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[65] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[65] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[66] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[66] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[67] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[67] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[68] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[68] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[69] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[69] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[70] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[70] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[71] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[71] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[72] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[72] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[73] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[73] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[74] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[74] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[75] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[75] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[76] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[76] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[77] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[77] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[78] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[78] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[79] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[79] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[80] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[80] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[81] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[81] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[82] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[82] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[83] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[83] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[84] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[84] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[85] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[85] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[86] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[86] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[87] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[87] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[88] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[88] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[89] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[89] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[90] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[90] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[91] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[91] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[92] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[92] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[93] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[93] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[94] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[94] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[95] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[95] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[96] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[96] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[97] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[97] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[98] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[98] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[99] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[99] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[100] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[100] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[101] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[101] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[102] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[102] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[103] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[103] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[104] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[104] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[105] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[105] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[106] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[106] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[107] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[107] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[108] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[108] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[109] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[109] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[110] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[110] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[111] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[111] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[112] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[112] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[113] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[113] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[114] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[114] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[115] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[115] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[116] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[116] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[117] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[117] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[118] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[118] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[119] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[119] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[120] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[120] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[121] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[121] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[122] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[122] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[123] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[123] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[124] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[124] = GPIOD_PDIR;
  
  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[125] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[125] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[126] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[126] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[127] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[127] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[128] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[128] = GPIOD_PDIR;

  digitalWriteFast(HG_ADC_CLK, LOW);  digitalWriteFast(LG_ADC_CLK, HIGH); HG_buff[129] = GPIOC_PDIR;
  digitalWriteFast(HG_ADC_CLK, HIGH); digitalWriteFast(LG_ADC_CLK, LOW);  LG_buff[129] = GPIOD_PDIR;
  
  digitalWriteFast(LG_ADC_CLK, HIGH);
  sei();  // enable interrupts
}
 
That's great thank you so much this would really help a lot. so we can say that the maximum we can go to is 28 MSPS if we used a 10 bit ADCs right? .. regarding what you said about the short bursts what I am planning to do is taking around 1024 sample at frequencies from 1 Hz to 1 MHz, I believe I can simply use the interrupts (Pdb_isr) to sample for lower frequencies and use this method to get the higher frequencises(say above 1 MSPS), but the question is if this is ok for the teensy to use this code multiple times (I mean running it this fast to take multiple samples at different frequencies).

Thanks again for the code :D
 
Hi Scientist,

I tried testing your code, but I received errors. It states that variables, such as TRIGGER_PULSE, HG_ADC_CLK, and LG_ADC_CLK, were not declared within scope. Would you have any suggestions on how to fix this?

Thank you for your time.
 
Hi Scientist,

I tried testing your code, but I received errors. It states that variables, such as TRIGGER_PULSE, HG_ADC_CLK, and LG_ADC_CLK, were not declared within scope. Would you have any suggestions on how to fix this?

Thank you for your time.

These are aliases for the pins to which my ADC is attached to. You need to define these for the hardware you are talking to.
 
Status
Not open for further replies.
Back
Top