lab 3
Dependencies: mbed BSP_DISCO_F746NG mbed-dsp
Revision 3:02dd3dd9120a, committed 2020-03-10
- Comitter:
- justenmg
- Date:
- Tue Mar 10 23:55:33 2020 +0000
- Parent:
- 2:78c6c389a744
- Commit message:
- 3/10
Changed in this revision
--- 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