jediemil 4 éve
szülő
commit
aed5024dba
1 módosított fájl, 131 hozzáadás és 95 törlés
  1. 131 95
      adc_fft.c

+ 131 - 95
adc_fft.c

@@ -54,114 +54,150 @@ static inline void put_pixel(uint32_t pixel_grb) {
 dma_channel_config cfg;
 uint dma_chan;
 float freqs[NSAMP];
+float freqsInLog[NSAMP];
+float power[NSAMP / 2];
+float powerInLog[NUM_PIXELS];
 
 void setup();
+
 void sample(uint8_t *capture_buf);
 
 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) {
-  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() {
-  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]);
+    }
 }