lab 3

Dependencies:   mbed BSP_DISCO_F746NG mbed-dsp

Files at this revision

API Documentation at this revision

Comitter:
justenmg
Date:
Tue Mar 10 23:55:33 2020 +0000
Parent:
2:78c6c389a744
Commit message:
3/10

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
spectrum.cpp Show annotated file Show diff for this revision Revisions of this file
spectrum.h Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Tue Mar 10 17:25:30 2020 +0000
+++ b/main.cpp	Tue Mar 10 23:55:33 2020 +0000
@@ -21,6 +21,7 @@
 #include "stm32746g_discovery_lcd.h"
 #include "arm_math.h"
 #include "signal_processing.h"
+#include "spectrum.h"
 
 /* The following type definitions are used to control the 
  * buffering of the audio data using a double buffering technique.
@@ -105,6 +106,9 @@
     BSP_LCD_DisplayStringAt(0, OSC_Y_POS - 20, (uint8_t *)"L", LEFT_MODE);
     BSP_LCD_SetTextColor(LCD_COLOR_GREEN);
     BSP_LCD_DisplayStringAt(0, OSC_Y_POS, (uint8_t *)"R", LEFT_MODE);
+    
+    //Set up the spectrum background display
+    Draw_Spectrum_Background();
 
     /* The following code should not be code that you need to worry about - it sets up the audio interfaces. */
         /* Initialize the Audio Interface */
@@ -152,6 +156,8 @@
         Erase_Trace(OSC_START_X_POS, OSC_Y_POS, AUDIO_BLOCK_SAMPLES);
         Draw_Trace(OSC_START_X_POS, OSC_Y_POS, (uint16_t *) AUDIO_BUFFER_IN, AUDIO_BLOCK_SAMPLES);
         
+        
+        
         /* Convert data to floating point representation for processing */
         Audio_to_Float((uint16_t *) AUDIO_BUFFER_IN, L_channel_float_in_p, R_channel_float_in_p, AUDIO_BLOCK_SAMPLES);
 
@@ -159,6 +165,7 @@
             /* Here is where signal processing can be done on the floating point arrays */
 
             process_audio_channel_signals(L_channel_float_in_p, R_channel_float_in_p, L_channel_float_out_p, R_channel_float_out_p, AUDIO_BLOCK_SAMPLES);
+            FFT_audio_input(L_channel_float_in_p, R_channel_float_in_p, AUDIO_BLOCK_SAMPLES);
         
             /* Here is where signal processing can end on the floating point arrays */        
             /* -------------------------------------------------------------------- */    
@@ -196,6 +203,7 @@
             /* Here is where signal processing can be done on the floating point arrays */
 
             process_audio_channel_signals(L_channel_float_in_p, R_channel_float_in_p, L_channel_float_out_p, R_channel_float_out_p, AUDIO_BLOCK_SAMPLES);
+            FFT_audio_input(L_channel_float_in_p, R_channel_float_in_p, AUDIO_BLOCK_SAMPLES);
         
             /* Here is where signal processing can end on the floating point arrays */        
             /* -------------------------------------------------------------------- */    
@@ -290,6 +298,12 @@
    
 }
 
+
+
+
+
+
+
 /**
   * @brief  Converts audio data in buffer to floating point representation.
   * @param  buffer_in: Pointer to Audio buffer start location
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spectrum.cpp	Tue Mar 10 23:55:33 2020 +0000
@@ -0,0 +1,218 @@
+#include "mbed.h"
+#include "stm32746g_discovery_lcd.h"
+#include "arm_math.h"
+#include "arm_const_structs.h"
+
+#define AUDIO_BLOCK_SAMPLES             ((uint32_t)128)         // Number of samples (L and R) in audio block (each samples is 16 bits)
+#define DFT_SIZE                        1024
+#define DFT_CMPLX_DATA_SIZE             2048
+#define FFT_TYPE                        arm_cfft_sR_f32_len1024
+
+/* These definitions define the size of the oscilloscope that is used to display data. */
+#define SPEC_ORIGIN_X_POS        100
+#define SPEC_X_LIMIT             256
+#define SPEC_ORIGIN_Y_POS        15
+#define SPEC_Y_LIMIT             100
+
+/* For Lab Exercise */
+#define Spectrum_Type              0
+
+
+float32_t l_input_buf[DFT_CMPLX_DATA_SIZE];
+float32_t r_input_buf[DFT_CMPLX_DATA_SIZE];
+
+float32_t l_fft_buf[DFT_CMPLX_DATA_SIZE];
+float32_t r_fft_buf[DFT_CMPLX_DATA_SIZE];
+
+float32_t l_display_spectrum[DFT_SIZE];
+float32_t r_display_spectrum[DFT_SIZE];
+
+
+void complx_dft(float32_t* dft_buffer, uint16_t dft_length)
+{
+    uint16_t complx_dft_length = 2*dft_length;
+    float32_t result[complx_dft_length];
+    float32_t W_n[2];
+    float32_t product[2];
+    
+    // k-loop
+    for(uint16_t k = 0; k < dft_length; k++)
+    {
+        //n-loop
+        for(int n=0; n < dft_length; n++)
+        {
+            //generate W_N^{kn}
+            //calc theta
+            float32_t theta = (2*k*n*PI)/dft_length;
+            //calc real and imag parts of W
+            arm_sin_cos_f32(theta, W_n+1, W_n);
+            
+            //do the multiply
+            arm_cmplx_mult_cmplx_f32(W_n, dft_buffer[2*n], product, 1);
+            
+            //summation
+            result[2*k] += product[0];
+            result[2*k+1] += product[1];
+        }
+    }
+    
+    //copy the result
+    for(uint16_t k = 0; k < dft_length; k++)
+    {
+        dft_buffer[2*k] = result[2*k];
+        dft_buffer[2*k+1] = result[2*k+1];
+    }
+}
+
+void FFT_audio_input(float32_t* L_channel_in, float32_t* R_channel_in, uint16_t Signal_Length)
+{
+    Complex_Signal_Length = 2*Signal_Length;   
+    
+    //shift the buffers
+    for(uint16_t i = 0; i < DFT_CMPLX_DATA_SIZE - Complex_Signal_Length; i++)
+    {
+        l_input_buf[i] = l_input_buf[i + Complex_Signal_Length];
+        r_input_buf[i] = r_input_buf[i + Complex_Signal_Length];
+    }
+    
+    //insert the new data
+    for(uint16_t i = DFT_SIZE - Signal_Length; i < DFT_SIZE; i++)
+    {
+        l_input_buf[2*i] = L_channel_in[i - DFT_SIZE + Signal_Length];
+        l_input_buf[2*i+1] = 0;
+        r_input_buf[2*i] = r_input_buf[i - DFT_SIZE + Signal_Length];
+        r_input_buf[2*i+1] = 0;  
+    }
+    
+    //copy to the fft buffer
+    for(uint16_t i = 0; i < DFT_CMPLX_DATA_SIZE; i++)
+    {
+        l_fft_buf = l_input_buf[i];
+        r_fft_buf = r_input_buf[i];
+    }
+    
+    //take the fft's
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, l_fft_buf, 0, 1);
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, r_fft_buf, 0, 1);
+    
+    //do some extra math
+    switch(Spectrum_Type)
+    {        
+        case 0: // Two-channel spectrum analyzer - magnitude-squared version            
+            for(uint16_t i = 0 i < DFT_SIZE; i++)
+            {                
+                l_display_spectrum[i] = l_fft_buf[2*i]^2 + l_fft_buf[2*i + 1]^2;
+                r_display_spectrum[i] = r_fft_buf[2*i]^2 + r_fft_buf[2*i + 1]^2;   
+            }
+            
+            
+            
+            
+        break;
+        
+        case 1: // Two-channel spectrum analyzer - dB version
+        break;
+        
+        case 2: // Two-channel spectrum analyzer - dB Exponentially averaging version
+        break;
+        
+        case 3: // Single-channel spectrogram
+        break;
+    
+    
+    }
+}
+
+
+
+
+
+
+
+void Draw_Spectrum_Background()
+{
+    switch(Spectrum_Type)
+    {        
+        case 0: // Two-channel spectrum analyzer - magnitude-squared version            
+            
+        break;
+        
+        case 1: // Two-channel spectrum analyzer - dB version
+        break;
+        
+        case 2: // Two-channel spectrum analyzer - dB Exponentially averaging version
+        break;
+        
+        case 3: // Single-channel spectrogram
+        break;
+    
+    
+    }
+}
+
+
+
+
+
+
+
+
+/**
+  * @brief  erases the FFT currently being displayed
+  * @param  Xpos: X position
+  * @param  Ypos: Y position
+  * @param  Length: length of trace
+  * @retval None
+  */
+void Erase_FFT(uint16_t Xpos, uint16_t Ypos, uint16_t Length)
+{
+    /* Creates a brown rectangle above and below the axis */
+    BSP_LCD_SetTextColor(LCD_COLOR_BROWN);
+    BSP_LCD_FillRect(Xpos, Ypos - AUDIO_DRAW_LIMIT, Length, AUDIO_DRAW_LIMIT);
+    BSP_LCD_FillRect(Xpos, Ypos+1, Length, AUDIO_DRAW_LIMIT);
+    
+    /* Draw axis for plotting */
+    BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
+    BSP_LCD_DrawHLine(Xpos, Ypos, Length);
+}
+
+
+/**
+  * @brief  Draws an FFT of the data line.
+  * @param  Xpos: X position
+  * @param  Ypos: Y position
+  * @param  Mem_start: Start of memory location
+  * @param  Length: length of trace
+  * @retval None
+  */
+void Draw_FFT(uint16_t Xpos, uint16_t Ypos, uint16_t* Mem_start, uint16_t Length)
+{
+    uint16_t i;
+    uint16_t* mem_address;
+    char buf[10];
+    int16_t L_audio_value;
+    int16_t R_audio_value;
+       
+    mem_address = Mem_start;
+      
+    for (i=0; i<Length; i++)
+   {       
+        R_audio_value = (int16_t) *mem_address;
+        mem_address++;
+        L_audio_value = (int16_t) *mem_address;
+        mem_address++;
+        
+        L_audio_value = L_audio_value / 100;
+        R_audio_value = R_audio_value / 100;
+        
+        if (L_audio_value > AUDIO_DRAW_LIMIT) {L_audio_value = AUDIO_DRAW_LIMIT;}
+        else if (L_audio_value < -AUDIO_DRAW_LIMIT) {L_audio_value = -AUDIO_DRAW_LIMIT;}
+
+        if (R_audio_value > AUDIO_DRAW_LIMIT) {R_audio_value = AUDIO_DRAW_LIMIT;}
+        else if (R_audio_value < -AUDIO_DRAW_LIMIT) {R_audio_value = -AUDIO_DRAW_LIMIT;}
+        
+        BSP_LCD_DrawPixel(Xpos + i, (uint16_t) ((int16_t) Ypos + L_audio_value), LCD_COLOR_BLUE);
+        BSP_LCD_DrawPixel(Xpos + i, (uint16_t) ((int16_t) Ypos + R_audio_value), LCD_COLOR_GREEN);
+   }
+   
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spectrum.h	Tue Mar 10 23:55:33 2020 +0000
@@ -0,0 +1,12 @@
+#include "mbed.h"
+#include "stm32746g_discovery_lcd.h"
+
+
+void complx_dft(float32_t* dft_buffer, uint16_t dft_length);
+
+void Draw_FFT(uint16_t Xpos, uint16_t Ypos, uint16_t* Mem_start, uint16_t Length);
+void Erase_FFT(uint16_t Xpos, uint16_t Ypos, uint16_t Length);
+
+void FFT_audio_input(float32_t* L_channel_in, float32_t* R_channel_in, uint16_t Signal_Length);
+
+void Draw_Spectrum_Background();
\ No newline at end of file