adc_fft.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #include <sys/cdefs.h>
  2. // Sample from the ADC continuously at a particular sample rate
  3. // and then compute an FFT over the data
  4. //
  5. // much of this code is from pico-examples/adc/dma_capture/dma_capture.c
  6. // the rest is written by Alex Wulff (www.AlexWulff.com)
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include "pico/stdlib.h"
  10. #include "hardware/adc.h"
  11. #include "hardware/dma.h"
  12. #include "pico/multicore.h"
  13. #include "kiss_fftr.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include "pico/stdlib.h"
  17. #include "hardware/pio.h"
  18. #include "hardware/clocks.h"
  19. #include "ws2812.pio.h"
  20. #define IS_RGBW false
  21. #define NUM_PIXELS 150
  22. #ifdef PICO_DEFAULT_WS2812_PIN
  23. #define WS2812_PIN PICO_DEFAULT_WS2812_PIN
  24. #else
  25. // default to pin 2 if the board doesn't have a default WS2812 pin defined
  26. #define WS2812_PIN 6
  27. #endif
  28. typedef struct {
  29. double r; // a fraction between 0 and 1
  30. double g; // a fraction between 0 and 1
  31. double b; // a fraction between 0 and 1
  32. } rgb;
  33. static inline void put_pixel(uint32_t pixel_grb) {
  34. pio_sm_put_blocking(pio0, 0, pixel_grb << 8u);
  35. }
  36. // set this to determine sample rate
  37. // 0 = 500,000 Hz
  38. // 960 = 50,000 Hz
  39. // 9600 = 5,000 Hz
  40. #define CLOCK_DIV 960
  41. #define FSAMP 50000
  42. // Channel 0 is GPIO26
  43. #define CAPTURE_CHANNEL 0
  44. #define LED_PIN 25
  45. // BE CAREFUL: anything over about 9000 here will cause things
  46. // to silently break. The code will compile and upload, but due
  47. // to memory issues nothing will work properly
  48. #define NSAMP 2048 //4096
  49. // globals
  50. dma_channel_config cfg;
  51. uint dma_chan;
  52. float freqs[NSAMP];
  53. float freqsInLog[NSAMP];
  54. float power[NSAMP / 2];
  55. float powerInLog[NUM_PIXELS];
  56. uint8_t cap_buf[NSAMP];
  57. uint8_t cap_res[NSAMP];
  58. uint64_t lastColorChange;
  59. void setup();
  60. void sample(uint8_t *capture_buf);
  61. void startSample();
  62. rgb hsv2rgb(double h, double s, double v);
  63. int main() {
  64. kiss_fft_scalar fft_in[NSAMP]; // kiss_fft_scalar is a float
  65. kiss_fft_cpx fft_out[NSAMP];
  66. kiss_fftr_cfg cfg = kiss_fftr_alloc(NSAMP, false, 0, 0);
  67. // setup ports and outputs
  68. setup();
  69. multicore_reset_core1();
  70. multicore_launch_core1(startSample);
  71. printf("Started\n");
  72. while (1) {
  73. //printf("Loop\n");
  74. // get NSAMP samples at FSAMP
  75. //uint64_t sampleStart = to_us_since_boot(get_absolute_time());
  76. //sample(cap_buf);
  77. //printf("Sample time: %llu \n", to_us_since_boot(get_absolute_time())-sampleStart);
  78. // fill fourier transform input while subtracting DC component
  79. uint64_t sum = 0;
  80. for (int i = 0; i < NSAMP; i++) { sum += cap_res[i]; }
  81. float avg = (float) sum / NSAMP;
  82. for (int i = 0; i < NSAMP; i++) { fft_in[i] = (float) cap_res[i] - avg; }
  83. // compute fast fourier transform
  84. kiss_fftr(cfg, fft_in, fft_out);
  85. // compute power and calculate max freq component
  86. // any frequency bin over NSAMP/2 is aliased (nyquist sampling theorum)
  87. for (int i = 0; i < NSAMP / 2; i++) {
  88. power[i] = fft_out[i].r * fft_out[i].r + fft_out[i].i * fft_out[i].i;
  89. }
  90. float f_max = FSAMP;
  91. float f_res = f_max / NSAMP;
  92. for (int i = 0; i < NUM_PIXELS; i++) {
  93. float lowFreq = freqsInLog[i];//freqs[i]; //freqsInLog[i];
  94. float highFreq;
  95. if (i != NUM_PIXELS - 1) {
  96. highFreq = freqsInLog[i + 1];//freqs[i+1]; //freqsInLog[i + 1];
  97. } else {
  98. highFreq = FSAMP / 2;
  99. }
  100. int lowInd = lowFreq / f_res;
  101. int highInd = highFreq / f_res;
  102. float totalPower = 0;
  103. for (int j = lowInd; j < highInd + 1; j++) {
  104. totalPower += power[j];
  105. }
  106. //printf("lowInd = %d, highInd = %d, lowFreq = %f, highFreq = %f, freq[lowInd] = %f, freq[highInd] = %f\n", lowInd, highInd, lowFreq, highFreq, freqs[lowInd], freqs[highInd]);
  107. float div_power = totalPower / (highInd + 1 - lowInd);
  108. powerInLog[i] = 20 * log(fmax(div_power/100000, 1));//div_power/1000.0; //20 * log(fmax(div_power - 1000000, 1));
  109. }
  110. //for (int i = 0; i < NUM_PIXELS - 1; i++) {
  111. // printf("Power for freq %f to %f = %f (%f)\n", freqsInLog[i], freqsInLog[i + 1], powerInLog[i], power[i]);
  112. //}
  113. //uint64_t timmmme = to_us_since_boot(get_absolute_time()) - lastColorChange;
  114. //printf("%llu \n", timmmme);
  115. if (to_us_since_boot(get_absolute_time()) - lastColorChange < 300) {
  116. sleep_us(300 - (to_us_since_boot(get_absolute_time()) - lastColorChange));
  117. }
  118. for (int i = 0; i < NUM_PIXELS; i++) {
  119. //uint32_t value = (uint32_t)(fmin(255, powerInLog[i]/400.0 * 255));
  120. rgb color = hsv2rgb(359 - fmin(359, powerInLog[i]/200.0 * 359), 1, fmin(0.5, powerInLog[i]/100.0));
  121. //printf("power = %f, color = %f, %f, %f\n", powerInLog[i]/200.0, color.r, color.g, color.b);
  122. uint32_t value = ((uint32_t)(fmin(color.r, 1) * 255) << 8) | ((uint32_t)(fmin(color.g, 1) * 255) << 16) | (uint32_t)(fmin(color.b, 1) * 255);
  123. //printf("b = %f\n", color.b*255);
  124. //printf("Color = %lu, pixel = %d\n", value, i);
  125. put_pixel(value);
  126. put_pixel(value);
  127. }
  128. lastColorChange = to_us_since_boot(get_absolute_time());
  129. //sleep_ms(50);
  130. }
  131. // should never get here
  132. kiss_fft_free(cfg);
  133. }
  134. rgb hsv2rgb(double h, double s, double v) {
  135. double hh, p, q, t, ff;
  136. long i;
  137. rgb out;
  138. if(s <= 0.0) { // < is bogus, just shuts up warnings
  139. out.r = v;
  140. out.g = v;
  141. out.b = v;
  142. return out;
  143. }
  144. hh = h;
  145. if(hh >= 360.0) hh = 0.0;
  146. hh /= 60.0;
  147. i = (long)hh;
  148. ff = hh - i;
  149. p = v * (1.0 - s);
  150. q = v * (1.0 - (s * ff));
  151. t = v * (1.0 - (s * (1.0 - ff)));
  152. switch(i) {
  153. case 0:
  154. out.r = v;
  155. out.g = t;
  156. out.b = p;
  157. break;
  158. case 1:
  159. out.r = q;
  160. out.g = v;
  161. out.b = p;
  162. break;
  163. case 2:
  164. out.r = p;
  165. out.g = v;
  166. out.b = t;
  167. break;
  168. case 3:
  169. out.r = p;
  170. out.g = q;
  171. out.b = v;
  172. break;
  173. case 4:
  174. out.r = t;
  175. out.g = p;
  176. out.b = v;
  177. break;
  178. case 5:
  179. default:
  180. out.r = v;
  181. out.g = p;
  182. out.b = q;
  183. break;
  184. }
  185. return out;
  186. }
  187. void sample(uint8_t *capture_buf) {
  188. adc_fifo_drain();
  189. adc_run(false);
  190. dma_channel_configure(dma_chan, &cfg,
  191. capture_buf, // dst
  192. &adc_hw->fifo, // src
  193. NSAMP, // transfer count
  194. true // start immediately
  195. );
  196. gpio_put(LED_PIN, 1);
  197. adc_run(true);
  198. dma_channel_wait_for_finish_blocking(dma_chan);
  199. gpio_put(LED_PIN, 0);
  200. }
  201. void startSample() {
  202. while(1) {
  203. adc_fifo_drain();
  204. adc_run(false);
  205. dma_channel_configure(dma_chan, &cfg,
  206. cap_buf, // dst
  207. &adc_hw->fifo, // src
  208. NSAMP, // transfer count
  209. true // start immediately
  210. );
  211. gpio_put(LED_PIN, 1);
  212. adc_run(true);
  213. dma_channel_wait_for_finish_blocking(dma_chan);
  214. gpio_put(LED_PIN, 0);
  215. memcpy(cap_res, cap_buf, sizeof cap_res);
  216. }
  217. }
  218. void setup() {
  219. stdio_init_all();
  220. // todo get free sm
  221. PIO pio = pio0;
  222. int sm = 0;
  223. uint offset = pio_add_program(pio, &ws2812_program);
  224. ws2812_program_init(pio, sm, offset, WS2812_PIN, 800000, IS_RGBW);
  225. //gpio_init(LED_PIN);
  226. //gpio_set_dir(LED_PIN, GPIO_OUT);
  227. adc_gpio_init(26 + CAPTURE_CHANNEL);
  228. adc_init();
  229. adc_select_input(CAPTURE_CHANNEL);
  230. adc_fifo_setup(
  231. true, // Write each completed conversion to the sample FIFO
  232. true, // Enable DMA data request (DREQ)
  233. 1, // DREQ (and IRQ) asserted when at least 1 sample present
  234. false, // We won't see the ERR bit because of 8 bit reads; disable.
  235. true // Shift each sample to 8 bits when pushing to FIFO
  236. );
  237. // set sample rate
  238. adc_set_clkdiv(CLOCK_DIV);
  239. sleep_ms(1000);
  240. // Set up the DMA to start transferring data as soon as it appears in FIFO
  241. uint dma_chan = dma_claim_unused_channel(true);
  242. cfg = dma_channel_get_default_config(dma_chan);
  243. // Reading from constant address, writing to incrementing byte addresses
  244. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8);
  245. channel_config_set_read_increment(&cfg, false);
  246. channel_config_set_write_increment(&cfg, true);
  247. // Pace transfers based on availability of ADC samples
  248. channel_config_set_dreq(&cfg, DREQ_ADC);
  249. printf("Starting\n");
  250. // calculate frequencies of each bin
  251. float f_max = FSAMP;
  252. float f_res = f_max / NSAMP;
  253. for (int i = 0; i < NSAMP; i++) {
  254. freqs[i] = f_res * i;
  255. }
  256. // Or 20kHz?
  257. float max_power = log(FSAMP / 2.0);
  258. float min_power = log(80);
  259. for (int i = 0; i < NUM_PIXELS; i++) {
  260. freqsInLog[i] = exp(i / (float) NUM_PIXELS * (max_power - min_power) + min_power);
  261. printf("freqsInLog[%d] = %f.1\n", i, freqsInLog[i]);
  262. }
  263. }