rp-hal icon indicating copy to clipboard operation
rp-hal copied to clipboard

WIP: ADC FIFO

Open 9names opened this issue 2 years ago • 2 comments

Trying to flesh out what ADC FIFO/free running IRQ functionality will look like. Working towards #322

9names avatar Apr 12 '22 13:04 9names

ADC FIFO is now returning correct results for my test program (which reads 4 analog channels). Back-to-back transfers generates data faster than I can consume it, so it's now set to 1000hz like the example in the datasheet. (this program is not in the PR. something approximating it is in the example, which runs but I haven't checked the results)

9names avatar Apr 13 '22 11:04 9names

Changed API so you don't have to calculate the clock divisor yourself, so instead of

// capture channel 1000 times/sec
adc.start_many_round_robin(0b1, 47999, 0);

you have

adc.start_many_round_robin(0b1, 1000);

Also, the calculated divisor also factors in the number of channels - the previous example would have required

// capture both channels 1000 times/sec
adc.start_many_round_robin(0b11, 23999, 0);

to capture 2 channels at the same rate, now we can use

adc.start_many_round_robin(0b11, 1000);

9names avatar Apr 15 '22 12:04 9names

I would benefit from this too. I skimmed through your commits, can I help in any way?

badrbouslikhin avatar Jan 19 '23 23:01 badrbouslikhin

I would benefit from this too. I skimmed through your commits, can I help in any way?

Sure! This is functional now, but I'm not happy with the API and I'm not sure when I'll get back to it - so if you want to take over this PR please do.

9names avatar Jan 20 '23 02:01 9names

@9names this is a great start! I took some inspiration from it and tried to come up with a better API, see #626.

To paraphrase your example:

adc.start_many_round_robin(0b11, 23999, 0);

would become:

let fifo = adc.free_running()
  .clock_divisor(23999, 0)
  .round_robin((&mut adc_pin0, &mut adc_pin1))
  .start_fifo();

// do something with the `fifo` object...

The round_robin method takes a tuple of channels instead of raw binary values, to avoid mistakes (similar to how OneShot.read takes a channel object instead of a raw number).

In addition to the clock_divisor method a sample_freq method could be added which computes the int and frac values (like you did in this PR). I'm thinking such a method would need some bound checks though. From what I understand the minimum sample rate is something like 723 Hz (48 MHz / (1 + 2^16 - 1 + (2^8 - 1 ) / 256)), when the dividers are set to their maximum.

nilclass avatar May 31 '23 18:05 nilclass

Closing this PR as #626 and #636 are better solutions

9names avatar Jul 12 '23 09:07 9names