|
@@ -54,114 +54,150 @@ static inline void put_pixel(uint32_t pixel_grb) {
|
|
|
dma_channel_config cfg;
|
|
dma_channel_config cfg;
|
|
|
uint dma_chan;
|
|
uint dma_chan;
|
|
|
float freqs[NSAMP];
|
|
float freqs[NSAMP];
|
|
|
|
|
+float freqsInLog[NSAMP];
|
|
|
|
|
+float power[NSAMP / 2];
|
|
|
|
|
+float powerInLog[NUM_PIXELS];
|
|
|
|
|
|
|
|
void setup();
|
|
void setup();
|
|
|
|
|
+
|
|
|
void sample(uint8_t *capture_buf);
|
|
void sample(uint8_t *capture_buf);
|
|
|
|
|
|
|
|
int main() {
|
|
int main() {
|
|
|
|
|
|
|
|
|
|
|
|
|
- uint8_t cap_buf[NSAMP];
|
|
|
|
|
- kiss_fft_scalar fft_in[NSAMP]; // kiss_fft_scalar is a float
|
|
|
|
|
- kiss_fft_cpx fft_out[NSAMP];
|
|
|
|
|
- kiss_fftr_cfg cfg = kiss_fftr_alloc(NSAMP,false,0,0);
|
|
|
|
|
-
|
|
|
|
|
- // setup ports and outputs
|
|
|
|
|
- setup();
|
|
|
|
|
-
|
|
|
|
|
- while (1) {
|
|
|
|
|
- // get NSAMP samples at FSAMP
|
|
|
|
|
- sample(cap_buf);
|
|
|
|
|
- // fill fourier transform input while subtracting DC component
|
|
|
|
|
- uint64_t sum = 0;
|
|
|
|
|
- for (int i=0;i<NSAMP;i++) {sum+=cap_buf[i];}
|
|
|
|
|
- float avg = (float)sum/NSAMP;
|
|
|
|
|
- for (int i=0;i<NSAMP;i++) {fft_in[i]=(float)cap_buf[i]-avg;}
|
|
|
|
|
-
|
|
|
|
|
- // compute fast fourier transform
|
|
|
|
|
- kiss_fftr(cfg , fft_in, fft_out);
|
|
|
|
|
-
|
|
|
|
|
- // compute power and calculate max freq component
|
|
|
|
|
- float max_power = 0;
|
|
|
|
|
- int max_idx = 0;
|
|
|
|
|
- // any frequency bin over NSAMP/2 is aliased (nyquist sampling theorum)
|
|
|
|
|
- for (int i = 0; i < NSAMP/2; i++) {
|
|
|
|
|
- float power = fft_out[i].r*fft_out[i].r+fft_out[i].i*fft_out[i].i;
|
|
|
|
|
- if (power>max_power) {
|
|
|
|
|
- max_power=power;
|
|
|
|
|
- max_idx = i;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ uint8_t cap_buf[NSAMP];
|
|
|
|
|
+ kiss_fft_scalar fft_in[NSAMP]; // kiss_fft_scalar is a float
|
|
|
|
|
+ kiss_fft_cpx fft_out[NSAMP];
|
|
|
|
|
+ kiss_fftr_cfg cfg = kiss_fftr_alloc(NSAMP, false, 0, 0);
|
|
|
|
|
+
|
|
|
|
|
+ // setup ports and outputs
|
|
|
|
|
+ setup();
|
|
|
|
|
+ printf("Started\n");
|
|
|
|
|
+ while (1) {
|
|
|
|
|
+ //printf("Loop\n");
|
|
|
|
|
+ // get NSAMP samples at FSAMP
|
|
|
|
|
+ sample(cap_buf);
|
|
|
|
|
+ // fill fourier transform input while subtracting DC component
|
|
|
|
|
+ uint64_t sum = 0;
|
|
|
|
|
+ for (int i = 0; i < NSAMP; i++) { sum += cap_buf[i]; }
|
|
|
|
|
+ float avg = (float) sum / NSAMP;
|
|
|
|
|
+ for (int i = 0; i < NSAMP; i++) { fft_in[i] = (float) cap_buf[i] - avg; }
|
|
|
|
|
+
|
|
|
|
|
+ // compute fast fourier transform
|
|
|
|
|
+ kiss_fftr(cfg, fft_in, fft_out);
|
|
|
|
|
+
|
|
|
|
|
+ // compute power and calculate max freq component
|
|
|
|
|
+
|
|
|
|
|
+ // any frequency bin over NSAMP/2 is aliased (nyquist sampling theorum)
|
|
|
|
|
+ for (int i = 0; i < NSAMP / 2; i++) {
|
|
|
|
|
+ power[i] = fft_out[i].r * fft_out[i].r + fft_out[i].i * fft_out[i].i;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ float f_max = FSAMP;
|
|
|
|
|
+ float f_res = f_max / NSAMP;
|
|
|
|
|
+ for (int i = 0; i < NUM_PIXELS; i++) {
|
|
|
|
|
+ float lowFreq = freqsInLog[i];
|
|
|
|
|
+ float highFreq;
|
|
|
|
|
+ if (i != NUM_PIXELS - 1) {
|
|
|
|
|
+ highFreq = freqsInLog[i + 1];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ highFreq = FSAMP / 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ int lowInd = lowFreq / f_res;
|
|
|
|
|
+ int highInd = highFreq / f_res;
|
|
|
|
|
+
|
|
|
|
|
+ float totalPower = 0;
|
|
|
|
|
+ for (int j = lowInd; j < highInd + 1; j++) {
|
|
|
|
|
+ totalPower += power[j];
|
|
|
|
|
+ }
|
|
|
|
|
+ //printf("lowInd = %d, highInd = %d, lowFreq = %f, highFreq = %f, freq[lowInd] = %f, freq[highInd] = %f\n", lowInd, highInd, lowFreq, highFreq, freqs[lowInd], freqs[highInd]);
|
|
|
|
|
+ float div_power = totalPower / (highInd + 1 - lowInd);
|
|
|
|
|
+ powerInLog[i] = 20 * log(fmax(div_power - 1000000, 1));
|
|
|
|
|
+ }
|
|
|
|
|
+ //for (int i = 0; i < NUM_PIXELS - 1; i++) {
|
|
|
|
|
+ // printf("Power for freq %f to %f = %f (%f)\n", freqsInLog[i], freqsInLog[i + 1], powerInLog[i], power[i]);
|
|
|
|
|
+ //}
|
|
|
|
|
+ for (int i = 0; i < NUM_PIXELS; i++) {
|
|
|
|
|
+ uint32_t value = (uint32_t)(fmin(255, powerInLog[i]/400.0 * 255));
|
|
|
|
|
+ //printf("Color = %d, pixel = %d\n", value, i);
|
|
|
|
|
+ put_pixel(value);
|
|
|
|
|
+ }
|
|
|
|
|
+ sleep_ms(50);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- float max_freq = freqs[max_idx];
|
|
|
|
|
- printf("Greatest Frequency Component: %0.1f Hz\n",max_freq);
|
|
|
|
|
- put_pixel(0x00ffff);
|
|
|
|
|
- put_pixel(0xff00ff);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // should never get here
|
|
|
|
|
- kiss_fft_free(cfg);
|
|
|
|
|
|
|
+ // should never get here
|
|
|
|
|
+ kiss_fft_free(cfg);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void sample(uint8_t *capture_buf) {
|
|
void sample(uint8_t *capture_buf) {
|
|
|
- adc_fifo_drain();
|
|
|
|
|
- adc_run(false);
|
|
|
|
|
-
|
|
|
|
|
- dma_channel_configure(dma_chan, &cfg,
|
|
|
|
|
- capture_buf, // dst
|
|
|
|
|
- &adc_hw->fifo, // src
|
|
|
|
|
- NSAMP, // transfer count
|
|
|
|
|
- true // start immediately
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- gpio_put(LED_PIN, 1);
|
|
|
|
|
- adc_run(true);
|
|
|
|
|
- dma_channel_wait_for_finish_blocking(dma_chan);
|
|
|
|
|
- gpio_put(LED_PIN, 0);
|
|
|
|
|
|
|
+ adc_fifo_drain();
|
|
|
|
|
+ adc_run(false);
|
|
|
|
|
+
|
|
|
|
|
+ dma_channel_configure(dma_chan, &cfg,
|
|
|
|
|
+ capture_buf, // dst
|
|
|
|
|
+ &adc_hw->fifo, // src
|
|
|
|
|
+ NSAMP, // transfer count
|
|
|
|
|
+ true // start immediately
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ gpio_put(LED_PIN, 1);
|
|
|
|
|
+ adc_run(true);
|
|
|
|
|
+ dma_channel_wait_for_finish_blocking(dma_chan);
|
|
|
|
|
+ gpio_put(LED_PIN, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void setup() {
|
|
void setup() {
|
|
|
- stdio_init_all();
|
|
|
|
|
-
|
|
|
|
|
- // todo get free sm
|
|
|
|
|
- PIO pio = pio0;
|
|
|
|
|
- int sm = 0;
|
|
|
|
|
- uint offset = pio_add_program(pio, &ws2812_program);
|
|
|
|
|
- ws2812_program_init(pio, sm, offset, WS2812_PIN, 800000, IS_RGBW);
|
|
|
|
|
-
|
|
|
|
|
- //gpio_init(LED_PIN);
|
|
|
|
|
- //gpio_set_dir(LED_PIN, GPIO_OUT);
|
|
|
|
|
-
|
|
|
|
|
- adc_gpio_init(26 + CAPTURE_CHANNEL);
|
|
|
|
|
-
|
|
|
|
|
- adc_init();
|
|
|
|
|
- adc_select_input(CAPTURE_CHANNEL);
|
|
|
|
|
- adc_fifo_setup(
|
|
|
|
|
- true, // Write each completed conversion to the sample FIFO
|
|
|
|
|
- true, // Enable DMA data request (DREQ)
|
|
|
|
|
- 1, // DREQ (and IRQ) asserted when at least 1 sample present
|
|
|
|
|
- false, // We won't see the ERR bit because of 8 bit reads; disable.
|
|
|
|
|
- true // Shift each sample to 8 bits when pushing to FIFO
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- // set sample rate
|
|
|
|
|
- adc_set_clkdiv(CLOCK_DIV);
|
|
|
|
|
-
|
|
|
|
|
- sleep_ms(1000);
|
|
|
|
|
- // Set up the DMA to start transferring data as soon as it appears in FIFO
|
|
|
|
|
- uint dma_chan = dma_claim_unused_channel(true);
|
|
|
|
|
- cfg = dma_channel_get_default_config(dma_chan);
|
|
|
|
|
-
|
|
|
|
|
- // Reading from constant address, writing to incrementing byte addresses
|
|
|
|
|
- channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8);
|
|
|
|
|
- channel_config_set_read_increment(&cfg, false);
|
|
|
|
|
- channel_config_set_write_increment(&cfg, true);
|
|
|
|
|
-
|
|
|
|
|
- // Pace transfers based on availability of ADC samples
|
|
|
|
|
- channel_config_set_dreq(&cfg, DREQ_ADC);
|
|
|
|
|
-
|
|
|
|
|
- // calculate frequencies of each bin
|
|
|
|
|
- float f_max = FSAMP;
|
|
|
|
|
- float f_res = f_max / NSAMP;
|
|
|
|
|
- for (int i = 0; i < NSAMP; i++) {freqs[i] = f_res*i;}
|
|
|
|
|
|
|
+ stdio_init_all();
|
|
|
|
|
+
|
|
|
|
|
+ // todo get free sm
|
|
|
|
|
+ PIO pio = pio0;
|
|
|
|
|
+ int sm = 0;
|
|
|
|
|
+ uint offset = pio_add_program(pio, &ws2812_program);
|
|
|
|
|
+ ws2812_program_init(pio, sm, offset, WS2812_PIN, 800000, IS_RGBW);
|
|
|
|
|
+
|
|
|
|
|
+ //gpio_init(LED_PIN);
|
|
|
|
|
+ //gpio_set_dir(LED_PIN, GPIO_OUT);
|
|
|
|
|
+
|
|
|
|
|
+ adc_gpio_init(26 + CAPTURE_CHANNEL);
|
|
|
|
|
+
|
|
|
|
|
+ adc_init();
|
|
|
|
|
+ adc_select_input(CAPTURE_CHANNEL);
|
|
|
|
|
+ adc_fifo_setup(
|
|
|
|
|
+ true, // Write each completed conversion to the sample FIFO
|
|
|
|
|
+ true, // Enable DMA data request (DREQ)
|
|
|
|
|
+ 1, // DREQ (and IRQ) asserted when at least 1 sample present
|
|
|
|
|
+ false, // We won't see the ERR bit because of 8 bit reads; disable.
|
|
|
|
|
+ true // Shift each sample to 8 bits when pushing to FIFO
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // set sample rate
|
|
|
|
|
+ adc_set_clkdiv(CLOCK_DIV);
|
|
|
|
|
+
|
|
|
|
|
+ sleep_ms(1000);
|
|
|
|
|
+ // Set up the DMA to start transferring data as soon as it appears in FIFO
|
|
|
|
|
+ uint dma_chan = dma_claim_unused_channel(true);
|
|
|
|
|
+ cfg = dma_channel_get_default_config(dma_chan);
|
|
|
|
|
+
|
|
|
|
|
+ // Reading from constant address, writing to incrementing byte addresses
|
|
|
|
|
+ channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8);
|
|
|
|
|
+ channel_config_set_read_increment(&cfg, false);
|
|
|
|
|
+ channel_config_set_write_increment(&cfg, true);
|
|
|
|
|
+
|
|
|
|
|
+ // Pace transfers based on availability of ADC samples
|
|
|
|
|
+ channel_config_set_dreq(&cfg, DREQ_ADC);
|
|
|
|
|
+
|
|
|
|
|
+ printf("Starting\n");
|
|
|
|
|
+ // calculate frequencies of each bin
|
|
|
|
|
+ float f_max = FSAMP;
|
|
|
|
|
+ float f_res = f_max / NSAMP;
|
|
|
|
|
+ for (int i = 0; i < NSAMP; i++) {
|
|
|
|
|
+ freqs[i] = f_res * i;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Or 20kHz?
|
|
|
|
|
+ float max_power = log(FSAMP / 2.0);
|
|
|
|
|
+ float min_power = log(80);
|
|
|
|
|
+ for (int i = 0; i < NUM_PIXELS; i++) {
|
|
|
|
|
+ freqsInLog[i] = exp(i / (float) NUM_PIXELS * (max_power - min_power) + min_power);
|
|
|
|
|
+ printf("freqsInLog[%d] = %f.1\n", i, freqsInLog[i]);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|