diff --git a/f103-ledmatrix.pro b/f103-ledmatrix.pro index 4af7f5b..05ff5f4 100644 --- a/f103-ledmatrix.pro +++ b/f103-ledmatrix.pro @@ -90,7 +90,8 @@ HEADERS += \ lib/cmsis/DSP_Lib/Include/arm_math.h \ lib/cmsis/DSP_Lib/Include/core_cmFunc.h \ lib/cmsis/DSP_Lib/Include/core_cmInstr.h \ - lib/cmsis/DSP_Lib/Include/core_cmSimd.h + lib/cmsis/DSP_Lib/Include/core_cmSimd.h \ + project/mode_audio.h SOURCES += \ lib/cmsis/core_cm3.c \ @@ -420,7 +421,8 @@ SOURCES += \ lib/cmsis/DSP_Lib/Source/TransformFunctions/arm_rfft_init_q15.c \ lib/cmsis/DSP_Lib/Source/TransformFunctions/arm_rfft_init_q31.c \ lib/cmsis/DSP_Lib/Source/TransformFunctions/arm_rfft_q15.c \ - lib/cmsis/DSP_Lib/Source/TransformFunctions/arm_rfft_q31.c + lib/cmsis/DSP_Lib/Source/TransformFunctions/arm_rfft_q31.c \ + project/mode_audio.c DISTFILES += \ style.astylerc \ diff --git a/project/com/com_fileio.c b/project/com/com_fileio.c index c6cfd9c..a081ded 100644 --- a/project/com/com_fileio.c +++ b/project/com/com_fileio.c @@ -7,6 +7,7 @@ // Holding fields for ifaces ComIface *debug_iface = NULL; ComIface *data_iface = NULL; +ComIface *gamepad_iface = NULL; // --- File descriptor names ------------------------------ diff --git a/project/com/com_fileio.h b/project/com/com_fileio.h index f1159ec..d7bf3c5 100644 --- a/project/com/com_fileio.h +++ b/project/com/com_fileio.h @@ -8,8 +8,8 @@ extern ComIface *debug_iface; /** ESP8266 com iface */ extern ComIface *data_iface; -/** Do-nothing iface */ -extern ComIface *com_iface_noop; +/** Gamepad iface */ +extern ComIface *gamepad_iface; /** File descriptors for use with built-in "files" */ diff --git a/project/dotmatrix.c b/project/dotmatrix.c index 5679112..909672e 100644 --- a/project/dotmatrix.c +++ b/project/dotmatrix.c @@ -1,108 +1,110 @@ -#include "max2719.h" #include "dotmatrix.h" #include "malloc_safe.h" #include "com/debug.h" +DotMatrix_Cfg *dmtx; + + DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init) { - DotMatrix_Cfg *dmtx = calloc_s(1, sizeof(DotMatrix_Cfg)); + DotMatrix_Cfg *disp = calloc_s(1, sizeof(DotMatrix_Cfg)); - dmtx->drv.SPIx = init->SPIx; - dmtx->drv.CS_GPIOx = init->CS_GPIOx; - dmtx->drv.CS_PINx = init->CS_PINx; - dmtx->drv.chain_len = init->cols * init->rows; - dmtx->cols = init->cols; - dmtx->rows = init->rows; + disp->drv.SPIx = init->SPIx; + disp->drv.CS_GPIOx = init->CS_GPIOx; + disp->drv.CS_PINx = init->CS_PINx; + disp->drv.chain_len = init->cols * init->rows; + disp->cols = init->cols; + disp->rows = init->rows; - dmtx->screen = calloc_s(init->cols * init->rows * 8, 1); // 8 bytes per driver + disp->screen = calloc_s(init->cols * init->rows * 8, 1); // 8 bytes per driver - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_DECODE_MODE, 0x00); // no decode - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SCAN_LIMIT, 0x07); // scan all 8 - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SHUTDOWN, 0x01); // not shutdown - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_DISPLAY_TEST, 0x00); // not test - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_INTENSITY, 0x07); // half intensity + max2719_cmd_all(&disp->drv, MAX2719_CMD_DECODE_MODE, 0x00); // no decode + max2719_cmd_all(&disp->drv, MAX2719_CMD_SCAN_LIMIT, 0x07); // scan all 8 + max2719_cmd_all(&disp->drv, MAX2719_CMD_SHUTDOWN, 0x01); // not shutdown + max2719_cmd_all(&disp->drv, MAX2719_CMD_DISPLAY_TEST, 0x00); // not test + max2719_cmd_all(&disp->drv, MAX2719_CMD_INTENSITY, 0x07); // half intensity // clear for (uint8_t i = 0; i < 8; i++) { - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_DIGIT0+i, 0); + max2719_cmd_all(&disp->drv, MAX2719_CMD_DIGIT0+i, 0); } - return dmtx; + return disp; } -void dmtx_show(DotMatrix_Cfg* dmtx) +void dmtx_show(DotMatrix_Cfg* disp) { for (uint8_t i = 0; i < 8; i++) { // show each digit's array in turn - max2719_cmd_all_data(&dmtx->drv, MAX2719_CMD_DIGIT0+i, dmtx->screen + (i * dmtx->drv.chain_len)); + max2719_cmd_all_data(&disp->drv, MAX2719_CMD_DIGIT0+i, disp->screen + (i * disp->drv.chain_len)); } } -void dmtx_clear(DotMatrix_Cfg* dmtx) +void dmtx_clear(DotMatrix_Cfg* disp) { - memset(dmtx->screen, 0, dmtx->drv.chain_len*8); + memset(disp->screen, 0, disp->drv.chain_len*8); } -void dmtx_intensity(DotMatrix_Cfg* dmtx, uint8_t intensity) +void dmtx_intensity(DotMatrix_Cfg* disp, uint8_t intensity) { - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_INTENSITY, intensity & 0x0F); + max2719_cmd_all(&disp->drv, MAX2719_CMD_INTENSITY, intensity & 0x0F); } -void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank) +void dmtx_blank(DotMatrix_Cfg* disp, bool blank) { - max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SHUTDOWN, blank & 0x01); + max2719_cmd_all(&disp->drv, MAX2719_CMD_SHUTDOWN, blank & 0x01); } /** * @brief Get a cell pointer - * @param dmtx : driver inst + * @param disp : driver inst * @param x : x coord * @param y : y coord * @param xd : pointer to store the offset in the cell * @return cell ptr */ -static uint8_t* cell_ptr(DotMatrix_Cfg* dmtx, int32_t x, int32_t y, uint8_t *xd) +static uint8_t* cell_ptr(DotMatrix_Cfg* disp, int32_t x, int32_t y, uint8_t *xd) { if (x < 0 || y < 0) return NULL; - if ((uint32_t)x >= dmtx->cols*8 || (uint32_t)y >= dmtx->rows*8) return NULL; + if ((uint32_t)x >= disp->cols*8 || (uint32_t)y >= disp->rows*8) return NULL; uint32_t cell_x = (uint32_t)x >> 3; *xd = x & 7; // resolve cell uint32_t digit = y & 7; - cell_x += ((uint32_t)y >> 3) * dmtx->cols; + cell_x += ((uint32_t)y >> 3) * disp->cols; - uint32_t cell_idx = (digit * dmtx->drv.chain_len) + cell_x; + uint32_t cell_idx = (digit * disp->drv.chain_len) + cell_x; - return &dmtx->screen[cell_idx]; + return &disp->screen[cell_idx]; } -bool dmtx_get(DotMatrix_Cfg* dmtx, int32_t x, int32_t y) +bool dmtx_get(DotMatrix_Cfg* disp, int32_t x, int32_t y) { uint8_t xd; - uint8_t *cell = cell_ptr(dmtx, x, y, &xd); + uint8_t *cell = cell_ptr(disp, x, y, &xd); if (cell == NULL) return 0; return (bool)(*cell & (1 << xd)); } -void dmtx_toggle(DotMatrix_Cfg* dmtx, int32_t x, int32_t y) +void dmtx_toggle(DotMatrix_Cfg* disp, int32_t x, int32_t y) { uint8_t xd; - uint8_t *cell = cell_ptr(dmtx, x, y, &xd); + uint8_t *cell = cell_ptr(disp, x, y, &xd); if (cell == NULL) return; *cell ^= 1 << xd; } -void dmtx_set(DotMatrix_Cfg* dmtx, int32_t x, int32_t y, bool bit) +void dmtx_set(DotMatrix_Cfg* disp, int32_t x, int32_t y, bool bit) { uint8_t xd; - uint8_t *cell = cell_ptr(dmtx, x, y, &xd); + uint8_t *cell = cell_ptr(disp, x, y, &xd); if (cell == NULL) return; if (bit) { diff --git a/project/dotmatrix.h b/project/dotmatrix.h index 7d35e6e..e95a3aa 100644 --- a/project/dotmatrix.h +++ b/project/dotmatrix.h @@ -4,6 +4,7 @@ #include "main.h" #include "max2719.h" + typedef struct { MAX2719_Cfg drv; uint8_t *screen; /*!< Screen array, organized as series of [all #1 digits], [all #2 digits] ... */ @@ -19,6 +20,9 @@ typedef struct { uint32_t rows; /*!< Number of drivers vertically */ } DotMatrix_Init; +// global inst +extern DotMatrix_Cfg *dmtx; + DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init); @@ -26,13 +30,13 @@ DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init); * @brief Display the whole screen array * @param dmtx : driver struct */ -void dmtx_show(DotMatrix_Cfg* dmtx); +void dmtx_show(DotMatrix_Cfg* disp); /** Set intensity 0-16 */ -void dmtx_intensity(DotMatrix_Cfg* dmtx, uint8_t intensity); +void dmtx_intensity(DotMatrix_Cfg* disp, uint8_t intensity); /** Display on/off */ -void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank); +void dmtx_blank(DotMatrix_Cfg* disp, bool blank); /** * @brief Send a single bit @@ -41,15 +45,15 @@ void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank); * @param y : pixel Y * @param bit : 1 or 0 */ -void dmtx_set(DotMatrix_Cfg* dmtx, int32_t x, int32_t y, bool bit); +void dmtx_set(DotMatrix_Cfg* disp, int32_t x, int32_t y, bool bit); /** Get a single bit */ -bool dmtx_get(DotMatrix_Cfg* dmtx, int32_t x, int32_t y); +bool dmtx_get(DotMatrix_Cfg* disp, int32_t x, int32_t y); /** Toggle a single bit */ -void dmtx_toggle(DotMatrix_Cfg* dmtx, int32_t x, int32_t y); +void dmtx_toggle(DotMatrix_Cfg* disp, int32_t x, int32_t y); /** Clear the screen (not showing) */ -void dmtx_clear(DotMatrix_Cfg* dmtx); +void dmtx_clear(DotMatrix_Cfg* disp); #endif // MATRIXDSP_H diff --git a/project/hw_init.c b/project/hw_init.c index 60687ca..cc73f8f 100644 --- a/project/hw_init.c +++ b/project/hw_init.c @@ -2,7 +2,7 @@ #include "com/iface_usart.h" #include "com/com_fileio.h" -#include "com/datalink.h" +//#include "com/datalink.h" #include "utils/debounce.h" #include "utils/timebase.h" @@ -10,6 +10,8 @@ #include "bus/event_queue.h" #include "com/debug.h" +#include "dotmatrix.h" + // ---- Private prototypes -------- static void conf_gpio(void); @@ -19,6 +21,7 @@ static void conf_systick(void); static void conf_subsystems(void); static void conf_irq_prios(void); static void conf_adc(void); +static void init_display(void); // ---- Public functions ---------- /** @@ -39,7 +42,6 @@ void hw_init(void) // ---- Private functions --------- - static void conf_irq_prios(void) { NVIC_SetPriorityGrouping(0); // 0 bits for sub-priority @@ -65,7 +67,25 @@ static void conf_subsystems(void) queues_init(30, 30); // initialize SBMP for ESP8266 - dlnk_init(); +// dlnk_init(); + + // dot matrix + init_display(); +} + + +static void init_display(void) +{ + DotMatrix_Init dmtx_cfg; + dmtx_cfg.CS_GPIOx = GPIOA; + dmtx_cfg.CS_PINx = GPIO_Pin_4; + dmtx_cfg.SPIx = SPI1; + dmtx_cfg.cols = 2; + dmtx_cfg.rows = 2; + + dmtx = dmtx_init(&dmtx_cfg); + + dmtx_intensity(dmtx, 7); } @@ -87,12 +107,15 @@ static void conf_gpio(void) gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOC, &gpio_cnf); - // UARTs + // [ UARTs ] + + // Tx gpio_cnf.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_9; gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP; gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA, &gpio_cnf); + // Rx gpio_cnf.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_3; gpio_cnf.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &gpio_cnf); @@ -123,14 +146,17 @@ static void conf_gpio(void) static void conf_usart(void) { // Debug interface, working as stdout/stderr. - debug_iface = usart_iface_init(USART2, 115200, 256, 256); + debug_iface = usart_iface_init(USART1, 115200, 256, 256); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); debug_iface->file = stdout; - // Datalink iface - data_iface = usart_iface_init(USART1, 460800, 256, 256); + gamepad_iface = usart_iface_init(USART2, 115200, 16, 16); + + + // Datalink iface + //data_iface = usart_iface_init(USART1, 460800, 256, 256); } /** @@ -205,46 +231,4 @@ static void conf_adc(void) TIM_TimeBaseInit(TIM3, &tim_cnf); TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); - - //TIM3->CR1 |= TIM_CR1_URS; // generate update on overflow - //TIM3->CR2 |= TIM_CR2_MMS_1; // trig on update -} - - -void start_adc_dma(uint32_t *memory, uint32_t count) -{ - ADC_Cmd(ADC1, DISABLE); - DMA_DeInit(DMA1_Channel1); - DMA_InitTypeDef dma_cnf; - dma_cnf.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; - dma_cnf.DMA_MemoryBaseAddr = (uint32_t)memory; - dma_cnf.DMA_DIR = DMA_DIR_PeripheralSRC; - dma_cnf.DMA_BufferSize = count; - dma_cnf.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - dma_cnf.DMA_MemoryInc = DMA_MemoryInc_Enable; - dma_cnf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; - dma_cnf.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; - dma_cnf.DMA_Mode = DMA_Mode_Normal; - dma_cnf.DMA_Priority = DMA_Priority_Low; - dma_cnf.DMA_M2M = DMA_M2M_Disable; - DMA_Init(DMA1_Channel1, &dma_cnf); - DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE); - - ADC_Cmd(ADC1, ENABLE); - ADC_DMACmd(ADC1, ENABLE); - DMA_Cmd(DMA1_Channel1, ENABLE); - TIM_Cmd(TIM3, ENABLE); -} - - -void DMA1_Channel1_IRQHandler(void) -{ - DMA_ClearITPendingBit(DMA1_IT_TC1); - DMA_ClearITPendingBit(DMA1_IT_TE1); - - DMA_DeInit(DMA1_Channel1); - TIM_Cmd(TIM3, DISABLE); - ADC_DMACmd(ADC1, DISABLE); - - tq_post(audio_capture_done, NULL); } diff --git a/project/hw_init.h b/project/hw_init.h index fc5dcd9..2e1625b 100644 --- a/project/hw_init.h +++ b/project/hw_init.h @@ -3,5 +3,3 @@ #include "main.h" void hw_init(void); - -void start_adc_dma(uint32_t *memory, uint32_t count); diff --git a/project/main.c b/project/main.c index 124587c..54d142a 100644 --- a/project/main.c +++ b/project/main.c @@ -11,165 +11,42 @@ #include "colorled.h" #include "display.h" #include -#include +//#include -//#include "matrixdsp.h" - -#include "max2719.h" #include "dotmatrix.h" #include "arm_math.h" +#include "mode_audio.h" -static volatile bool capture_pending = false; -static volatile bool print_next_fft = false; - -static float virt_zero_value = 2045.0f; static void poll_subsystems(void); -static DotMatrix_Cfg *dmtx; - -#define SAMP_BUF_LEN 256 - -union samp_buf_union { - uint32_t uints[SAMP_BUF_LEN]; - float floats[SAMP_BUF_LEN]; - uint8_t as_bytes[SAMP_BUF_LEN*sizeof(uint32_t)]; -}; - -// sample buffers (static - invalidated when sampling starts anew). -static union samp_buf_union samp_buf; - -void audio_capture_done(void* unused) -{ - (void)unused; - - const int samp_count = SAMP_BUF_LEN/2; - const int bin_count = SAMP_BUF_LEN/4; - - float *bins = samp_buf.floats; - - // Convert to floats - for (int i = 0; i < samp_count; i++) { - samp_buf.floats[i] = (float)samp_buf.uints[i]; - } - - // normalize - float mean; - arm_mean_f32(samp_buf.floats, samp_count, &mean); - virt_zero_value = mean; - - for (int i = 0; i < samp_count; i++) { - samp_buf.floats[i] -= virt_zero_value; - } - - - if (print_next_fft) { - printf("--- Raw (adjusted) ---\n"); - for(int i = 0; i < samp_count; i++) { - printf("%.2f, ", samp_buf.floats[i]); - } - printf("\n"); - } - - for (int i = samp_count - 1; i >= 0; i--) { - bins[i * 2 + 1] = 0; // imaginary - bins[i * 2] = samp_buf.floats[i]; // real - } - - const arm_cfft_instance_f32 *S; - S = &arm_cfft_sR_f32_len128; - - arm_cfft_f32(S, bins, 0, true); // bit reversed FFT - arm_cmplx_mag_f32(bins, bins, bin_count); // get magnitude (extract real values) - - if (print_next_fft) { - printf("--- Bins ---\n"); - for(int i = 0; i < bin_count; i++) { - printf("%.2f, ", bins[i]); - } - printf("\n"); - } - - // normalize - dmtx_clear(dmtx); - float factor = (1.0f/bin_count)*0.2f; - for(int i = 0; i < bin_count-1; i+=2) { - bins[i] *= factor; - bins[i+1] *= factor; - - //float avg = i==0 ? bins[1] : (bins[i] + bins[i+1])/2; - float avg = (bins[i] + bins[i+1])/2; - - for(int j = 0; j < 1+floorf(avg); j++) { - //dmtx_toggle(dmtx, i/2, j); - dmtx_toggle(dmtx, i/2, j); - //dmtx_toggle(dmtx, j, 15-i/2); - //dmtx_toggle(dmtx, 15- i/2, 15-j); - } - } - - dmtx_show(dmtx); - - print_next_fft = false; - capture_pending = false; -} - - -static void capture_audio(void *unused) -{ - (void)unused; - if (capture_pending) return; - - capture_pending = true; - - start_adc_dma(samp_buf.uints, SAMP_BUF_LEN/2); -} - +static task_pid_t capture_task_id; -static void rx_char(ComIface *iface) +static void boot_animation(void) { - uint8_t ch; - while(com_rx(iface, &ch)) { - if (ch == 'p') { - info("PRINT_NEXT"); - print_next_fft = true; - } + // Boot animation (for FFT) + for(int i = 0; i < 16; i++) { + dmtx_set(dmtx, i, 0, 1); + dmtx_show(dmtx); + delay_ms(25); } } -static task_pid_t capture_task_id; - - int main(void) { hw_init(); banner("*** FFT dot matrix display ***"); banner_info("(c) Ondrej Hruska, 2016"); + boot_animation(); - debug_iface->rx_callback = rx_char; - - DotMatrix_Init dmtx_cfg; - dmtx_cfg.CS_GPIOx = GPIOA; - dmtx_cfg.CS_PINx = GPIO_Pin_4; - dmtx_cfg.SPIx = SPI1; - dmtx_cfg.cols = 2; - dmtx_cfg.rows = 2; - - dmtx = dmtx_init(&dmtx_cfg); - - dmtx_intensity(dmtx, 7); - - for(int i = 0; i < 16; i++) { - dmtx_set(dmtx, i, 0, 1); - dmtx_show(dmtx); - delay_ms(25); - } + //debug_iface->rx_callback = rx_char; capture_task_id = add_periodic_task(capture_audio, NULL, 10, false); + ms_time_t last; while (1) { if (ms_loop_elapsed(&last, 500)) { @@ -185,14 +62,14 @@ static void poll_subsystems(void) { // poll serial buffers (runs callback) com_poll(debug_iface); - com_poll(data_iface); + //com_poll(data_iface); + com_poll(gamepad_iface); // run queued tasks tq_poll(); // handle queued events Event evt; - until_timeout(2) { // take 2 ms max if (eq_take(&evt)) { run_event_handler(&evt); @@ -203,7 +80,21 @@ static void poll_subsystems(void) } -void dlnk_rx(SBMP_Datagram *dg) -{ - dbg("Rx dg type %d", dg->type); -} +//static void rx_char(ComIface *iface) +//{ +// uint8_t ch; +// while(com_rx(iface, &ch)) { +// if (ch == 'p') { +// info("PRINT_NEXT"); +// print_next_fft = true; +// } +// } +//} + + + +//void dlnk_rx(SBMP_Datagram *dg) +//{ +// (void)dg; +// //dbg("Rx dg type %d", dg->type); +//} diff --git a/project/main.h b/project/main.h index 83863f1..ad6719a 100644 --- a/project/main.h +++ b/project/main.h @@ -15,7 +15,4 @@ #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) - -void audio_capture_done(void* unused); - #endif // MAIN_H diff --git a/project/mode_audio.c b/project/mode_audio.c new file mode 100644 index 0000000..aa45382 --- /dev/null +++ b/project/mode_audio.c @@ -0,0 +1,150 @@ +#include "mode_audio.h" +#include +#include "bus/event_queue.h" + +#include "dotmatrix.h" + +static volatile bool capture_pending = false; +static volatile bool print_next_fft = false; + +static float virt_zero_value = 2045.0f; + +#define SAMP_BUF_LEN 256 + +union samp_buf_union { + uint32_t uints[SAMP_BUF_LEN]; + float floats[SAMP_BUF_LEN]; + uint8_t as_bytes[SAMP_BUF_LEN*sizeof(uint32_t)]; +}; + +// sample buffers (static - invalidated when sampling starts anew). +static union samp_buf_union samp_buf; + +// prototypes +static void audio_capture_done(void* unused); + + +static void start_adc_dma(uint32_t *memory, uint32_t count) +{ + ADC_Cmd(ADC1, DISABLE); + DMA_DeInit(DMA1_Channel1); + DMA_InitTypeDef dma_cnf; + dma_cnf.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; + dma_cnf.DMA_MemoryBaseAddr = (uint32_t)memory; + dma_cnf.DMA_DIR = DMA_DIR_PeripheralSRC; + dma_cnf.DMA_BufferSize = count; + dma_cnf.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + dma_cnf.DMA_MemoryInc = DMA_MemoryInc_Enable; + dma_cnf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; + dma_cnf.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; + dma_cnf.DMA_Mode = DMA_Mode_Normal; + dma_cnf.DMA_Priority = DMA_Priority_Low; + dma_cnf.DMA_M2M = DMA_M2M_Disable; + DMA_Init(DMA1_Channel1, &dma_cnf); + DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE); + + ADC_Cmd(ADC1, ENABLE); + ADC_DMACmd(ADC1, ENABLE); + DMA_Cmd(DMA1_Channel1, ENABLE); + TIM_Cmd(TIM3, ENABLE); +} + + +void DMA1_Channel1_IRQHandler(void) +{ + DMA_ClearITPendingBit(DMA1_IT_TC1); + DMA_ClearITPendingBit(DMA1_IT_TE1); + + DMA_DeInit(DMA1_Channel1); + TIM_Cmd(TIM3, DISABLE); + ADC_DMACmd(ADC1, DISABLE); + + tq_post(audio_capture_done, NULL); +} + + +static void audio_capture_done(void* unused) +{ + (void)unused; + + const int samp_count = SAMP_BUF_LEN/2; + const int bin_count = SAMP_BUF_LEN/4; + + float *bins = samp_buf.floats; + + // Convert to floats + for (int i = 0; i < samp_count; i++) { + samp_buf.floats[i] = (float)samp_buf.uints[i]; + } + + // normalize + float mean; + arm_mean_f32(samp_buf.floats, samp_count, &mean); + virt_zero_value = mean; + + for (int i = 0; i < samp_count; i++) { + samp_buf.floats[i] -= virt_zero_value; + } + + + if (print_next_fft) { + printf("--- Raw (adjusted) ---\n"); + for(int i = 0; i < samp_count; i++) { + printf("%.2f, ", samp_buf.floats[i]); + } + printf("\n"); + } + + for (int i = samp_count - 1; i >= 0; i--) { + bins[i * 2 + 1] = 0; // imaginary + bins[i * 2] = samp_buf.floats[i]; // real + } + + const arm_cfft_instance_f32 *S; + S = &arm_cfft_sR_f32_len128; + + arm_cfft_f32(S, bins, 0, true); // bit reversed FFT + arm_cmplx_mag_f32(bins, bins, bin_count); // get magnitude (extract real values) + + if (print_next_fft) { + printf("--- Bins ---\n"); + for(int i = 0; i < bin_count; i++) { + printf("%.2f, ", bins[i]); + } + printf("\n"); + } + + // normalize + dmtx_clear(dmtx); + float factor = (1.0f/bin_count)*0.2f; + for(int i = 0; i < bin_count-1; i+=2) { + bins[i] *= factor; + bins[i+1] *= factor; + + //float avg = i==0 ? bins[1] : (bins[i] + bins[i+1])/2; + float avg = (bins[i] + bins[i+1])/2; + + for(int j = 0; j < 1+floorf(avg); j++) { + //dmtx_toggle(dmtx, i/2, j); + dmtx_toggle(dmtx, i/2, j); + //dmtx_toggle(dmtx, j, 15-i/2); + //dmtx_toggle(dmtx, 15- i/2, 15-j); + } + } + + dmtx_show(dmtx); + + print_next_fft = false; + capture_pending = false; +} + + +void capture_audio(void *unused) +{ + (void)unused; + if (capture_pending) return; + + capture_pending = true; + + start_adc_dma(samp_buf.uints, SAMP_BUF_LEN/2); +} diff --git a/project/mode_audio.h b/project/mode_audio.h new file mode 100644 index 0000000..06de92b --- /dev/null +++ b/project/mode_audio.h @@ -0,0 +1,8 @@ +#ifndef MODE_AUDIO_H +#define MODE_AUDIO_H + +#include "main.h" + +void capture_audio(void *unused); + +#endif // MODE_AUDIO_H