multimode starting..

multi-mode
Ondřej Hruška 9 years ago
parent df386cd594
commit 7af5f0e35e
  1. 6
      f103-ledmatrix.pro
  2. 1
      project/com/com_fileio.c
  3. 4
      project/com/com_fileio.h
  4. 74
      project/dotmatrix.c
  5. 18
      project/dotmatrix.h
  6. 82
      project/hw_init.c
  7. 2
      project/hw_init.h
  8. 171
      project/main.c
  9. 3
      project/main.h
  10. 150
      project/mode_audio.c
  11. 8
      project/mode_audio.h

@ -90,7 +90,8 @@ HEADERS += \
lib/cmsis/DSP_Lib/Include/arm_math.h \ lib/cmsis/DSP_Lib/Include/arm_math.h \
lib/cmsis/DSP_Lib/Include/core_cmFunc.h \ lib/cmsis/DSP_Lib/Include/core_cmFunc.h \
lib/cmsis/DSP_Lib/Include/core_cmInstr.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 += \ SOURCES += \
lib/cmsis/core_cm3.c \ 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_q15.c \
lib/cmsis/DSP_Lib/Source/TransformFunctions/arm_rfft_init_q31.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_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 += \ DISTFILES += \
style.astylerc \ style.astylerc \

@ -7,6 +7,7 @@
// Holding fields for ifaces // Holding fields for ifaces
ComIface *debug_iface = NULL; ComIface *debug_iface = NULL;
ComIface *data_iface = NULL; ComIface *data_iface = NULL;
ComIface *gamepad_iface = NULL;
// --- File descriptor names ------------------------------ // --- File descriptor names ------------------------------

@ -8,8 +8,8 @@ extern ComIface *debug_iface;
/** ESP8266 com iface */ /** ESP8266 com iface */
extern ComIface *data_iface; extern ComIface *data_iface;
/** Do-nothing iface */ /** Gamepad iface */
extern ComIface *com_iface_noop; extern ComIface *gamepad_iface;
/** File descriptors for use with built-in "files" */ /** File descriptors for use with built-in "files" */

@ -1,108 +1,110 @@
#include "max2719.h"
#include "dotmatrix.h" #include "dotmatrix.h"
#include "malloc_safe.h" #include "malloc_safe.h"
#include "com/debug.h" #include "com/debug.h"
DotMatrix_Cfg *dmtx;
DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init) 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; disp->drv.SPIx = init->SPIx;
dmtx->drv.CS_GPIOx = init->CS_GPIOx; disp->drv.CS_GPIOx = init->CS_GPIOx;
dmtx->drv.CS_PINx = init->CS_PINx; disp->drv.CS_PINx = init->CS_PINx;
dmtx->drv.chain_len = init->cols * init->rows; disp->drv.chain_len = init->cols * init->rows;
dmtx->cols = init->cols; disp->cols = init->cols;
dmtx->rows = init->rows; 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(&disp->drv, MAX2719_CMD_DECODE_MODE, 0x00); // no decode
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SCAN_LIMIT, 0x07); // scan all 8 max2719_cmd_all(&disp->drv, MAX2719_CMD_SCAN_LIMIT, 0x07); // scan all 8
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SHUTDOWN, 0x01); // not shutdown max2719_cmd_all(&disp->drv, MAX2719_CMD_SHUTDOWN, 0x01); // not shutdown
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_DISPLAY_TEST, 0x00); // not test max2719_cmd_all(&disp->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_INTENSITY, 0x07); // half intensity
// clear // clear
for (uint8_t i = 0; i < 8; i++) { 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++) { for (uint8_t i = 0; i < 8; i++) {
// show each digit's array in turn // 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 * @brief Get a cell pointer
* @param dmtx : driver inst * @param disp : driver inst
* @param x : x coord * @param x : x coord
* @param y : y coord * @param y : y coord
* @param xd : pointer to store the offset in the cell * @param xd : pointer to store the offset in the cell
* @return cell ptr * @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 (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; uint32_t cell_x = (uint32_t)x >> 3;
*xd = x & 7; *xd = x & 7;
// resolve cell // resolve cell
uint32_t digit = y & 7; 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 xd;
uint8_t *cell = cell_ptr(dmtx, x, y, &xd); uint8_t *cell = cell_ptr(disp, x, y, &xd);
if (cell == NULL) return 0; if (cell == NULL) return 0;
return (bool)(*cell & (1 << xd)); 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 xd;
uint8_t *cell = cell_ptr(dmtx, x, y, &xd); uint8_t *cell = cell_ptr(disp, x, y, &xd);
if (cell == NULL) return; if (cell == NULL) return;
*cell ^= 1 << xd; *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 xd;
uint8_t *cell = cell_ptr(dmtx, x, y, &xd); uint8_t *cell = cell_ptr(disp, x, y, &xd);
if (cell == NULL) return; if (cell == NULL) return;
if (bit) { if (bit) {

@ -4,6 +4,7 @@
#include "main.h" #include "main.h"
#include "max2719.h" #include "max2719.h"
typedef struct { typedef struct {
MAX2719_Cfg drv; MAX2719_Cfg drv;
uint8_t *screen; /*!< Screen array, organized as series of [all #1 digits], [all #2 digits] ... */ 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 */ uint32_t rows; /*!< Number of drivers vertically */
} DotMatrix_Init; } DotMatrix_Init;
// global inst
extern DotMatrix_Cfg *dmtx;
DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init); DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init);
@ -26,13 +30,13 @@ DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init);
* @brief Display the whole screen array * @brief Display the whole screen array
* @param dmtx : driver struct * @param dmtx : driver struct
*/ */
void dmtx_show(DotMatrix_Cfg* dmtx); void dmtx_show(DotMatrix_Cfg* disp);
/** Set intensity 0-16 */ /** 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 */ /** Display on/off */
void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank); void dmtx_blank(DotMatrix_Cfg* disp, bool blank);
/** /**
* @brief Send a single bit * @brief Send a single bit
@ -41,15 +45,15 @@ void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank);
* @param y : pixel Y * @param y : pixel Y
* @param bit : 1 or 0 * @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 */ /** 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 */ /** 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) */ /** Clear the screen (not showing) */
void dmtx_clear(DotMatrix_Cfg* dmtx); void dmtx_clear(DotMatrix_Cfg* disp);
#endif // MATRIXDSP_H #endif // MATRIXDSP_H

@ -2,7 +2,7 @@
#include "com/iface_usart.h" #include "com/iface_usart.h"
#include "com/com_fileio.h" #include "com/com_fileio.h"
#include "com/datalink.h" //#include "com/datalink.h"
#include "utils/debounce.h" #include "utils/debounce.h"
#include "utils/timebase.h" #include "utils/timebase.h"
@ -10,6 +10,8 @@
#include "bus/event_queue.h" #include "bus/event_queue.h"
#include "com/debug.h" #include "com/debug.h"
#include "dotmatrix.h"
// ---- Private prototypes -------- // ---- Private prototypes --------
static void conf_gpio(void); static void conf_gpio(void);
@ -19,6 +21,7 @@ static void conf_systick(void);
static void conf_subsystems(void); static void conf_subsystems(void);
static void conf_irq_prios(void); static void conf_irq_prios(void);
static void conf_adc(void); static void conf_adc(void);
static void init_display(void);
// ---- Public functions ---------- // ---- Public functions ----------
/** /**
@ -39,7 +42,6 @@ void hw_init(void)
// ---- Private functions --------- // ---- Private functions ---------
static void conf_irq_prios(void) static void conf_irq_prios(void)
{ {
NVIC_SetPriorityGrouping(0); // 0 bits for sub-priority NVIC_SetPriorityGrouping(0); // 0 bits for sub-priority
@ -65,7 +67,25 @@ static void conf_subsystems(void)
queues_init(30, 30); queues_init(30, 30);
// initialize SBMP for ESP8266 // 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_cnf.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &gpio_cnf); GPIO_Init(GPIOC, &gpio_cnf);
// UARTs // [ UARTs ]
// Tx
gpio_cnf.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_9; gpio_cnf.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_9;
gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP; gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz; gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &gpio_cnf); GPIO_Init(GPIOA, &gpio_cnf);
// Rx
gpio_cnf.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_3; gpio_cnf.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_3;
gpio_cnf.GPIO_Mode = GPIO_Mode_IN_FLOATING; gpio_cnf.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &gpio_cnf); GPIO_Init(GPIOA, &gpio_cnf);
@ -123,14 +146,17 @@ static void conf_gpio(void)
static void conf_usart(void) static void conf_usart(void)
{ {
// Debug interface, working as stdout/stderr. // 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(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0);
debug_iface->file = stdout; 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_TimeBaseInit(TIM3, &tim_cnf);
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); 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);
} }

@ -3,5 +3,3 @@
#include "main.h" #include "main.h"
void hw_init(void); void hw_init(void);
void start_adc_dma(uint32_t *memory, uint32_t count);

@ -11,165 +11,42 @@
#include "colorled.h" #include "colorled.h"
#include "display.h" #include "display.h"
#include <math.h> #include <math.h>
#include <sbmp.h> //#include <sbmp.h>
//#include "matrixdsp.h"
#include "max2719.h"
#include "dotmatrix.h" #include "dotmatrix.h"
#include "arm_math.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 void poll_subsystems(void);
static DotMatrix_Cfg *dmtx; static task_pid_t capture_task_id;
#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) static void boot_animation(void)
{ {
(void)unused; // Boot animation (for FFT)
for(int i = 0; i < 16; i++) {
const int samp_count = SAMP_BUF_LEN/2; dmtx_set(dmtx, i, 0, 1);
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); dmtx_show(dmtx);
delay_ms(25);
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 void rx_char(ComIface *iface)
{
uint8_t ch;
while(com_rx(iface, &ch)) {
if (ch == 'p') {
info("PRINT_NEXT");
print_next_fft = true;
}
} }
} }
static task_pid_t capture_task_id;
int main(void) int main(void)
{ {
hw_init(); hw_init();
banner("*** FFT dot matrix display ***"); banner("*** FFT dot matrix display ***");
banner_info("(c) Ondrej Hruska, 2016"); 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); capture_task_id = add_periodic_task(capture_audio, NULL, 10, false);
ms_time_t last; ms_time_t last;
while (1) { while (1) {
if (ms_loop_elapsed(&last, 500)) { if (ms_loop_elapsed(&last, 500)) {
@ -185,14 +62,14 @@ static void poll_subsystems(void)
{ {
// poll serial buffers (runs callback) // poll serial buffers (runs callback)
com_poll(debug_iface); com_poll(debug_iface);
com_poll(data_iface); //com_poll(data_iface);
com_poll(gamepad_iface);
// run queued tasks // run queued tasks
tq_poll(); tq_poll();
// handle queued events // handle queued events
Event evt; Event evt;
until_timeout(2) { // take 2 ms max until_timeout(2) { // take 2 ms max
if (eq_take(&evt)) { if (eq_take(&evt)) {
run_event_handler(&evt); run_event_handler(&evt);
@ -203,7 +80,21 @@ static void poll_subsystems(void)
} }
void dlnk_rx(SBMP_Datagram *dg) //static void rx_char(ComIface *iface)
{ //{
dbg("Rx dg type %d", dg->type); // 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);
//}

@ -15,7 +15,4 @@
#define STR_HELPER(x) #x #define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x) #define STR(x) STR_HELPER(x)
void audio_capture_done(void* unused);
#endif // MAIN_H #endif // MAIN_H

@ -0,0 +1,150 @@
#include "mode_audio.h"
#include <arm_math.h>
#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);
}

@ -0,0 +1,8 @@
#ifndef MODE_AUDIO_H
#define MODE_AUDIO_H
#include "main.h"
void capture_audio(void *unused);
#endif // MODE_AUDIO_H
Loading…
Cancel
Save