working fft shite
This commit is contained in:
+41
-5
@@ -53,13 +53,21 @@ void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank)
|
||||
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SHUTDOWN, blank & 0x01);
|
||||
}
|
||||
|
||||
void dmtx_set(DotMatrix_Cfg* dmtx, int32_t x, int32_t y, bool bit)
|
||||
/**
|
||||
* @brief Get a cell pointer
|
||||
* @param dmtx : 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)
|
||||
{
|
||||
if (x < 0 || y < 0) return;
|
||||
if ((uint32_t)x >= dmtx->cols*8 || (uint32_t)y >= dmtx->rows*8) return;
|
||||
if (x < 0 || y < 0) return NULL;
|
||||
if ((uint32_t)x >= dmtx->cols*8 || (uint32_t)y >= dmtx->rows*8) return NULL;
|
||||
|
||||
uint32_t cell_x = (uint32_t)x >> 3;
|
||||
uint8_t xd = x & 7;
|
||||
*xd = x & 7;
|
||||
|
||||
// resolve cell
|
||||
uint32_t digit = y & 7;
|
||||
@@ -67,7 +75,35 @@ void dmtx_set(DotMatrix_Cfg* dmtx, int32_t x, int32_t y, bool bit)
|
||||
|
||||
uint32_t cell_idx = (digit * dmtx->drv.chain_len) + cell_x;
|
||||
|
||||
uint8_t *cell = &dmtx->screen[cell_idx];
|
||||
return &dmtx->screen[cell_idx];
|
||||
}
|
||||
|
||||
|
||||
bool dmtx_get(DotMatrix_Cfg* dmtx, int32_t x, int32_t y)
|
||||
{
|
||||
uint8_t xd;
|
||||
uint8_t *cell = cell_ptr(dmtx, 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)
|
||||
{
|
||||
uint8_t xd;
|
||||
uint8_t *cell = cell_ptr(dmtx, x, y, &xd);
|
||||
if (cell == NULL) return;
|
||||
|
||||
*cell ^= 1 << xd;
|
||||
}
|
||||
|
||||
|
||||
void dmtx_set(DotMatrix_Cfg* dmtx, int32_t x, int32_t y, bool bit)
|
||||
{
|
||||
uint8_t xd;
|
||||
uint8_t *cell = cell_ptr(dmtx, x, y, &xd);
|
||||
if (cell == NULL) return;
|
||||
|
||||
if (bit) {
|
||||
*cell |= bit << xd;
|
||||
|
||||
@@ -43,6 +43,12 @@ void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank);
|
||||
*/
|
||||
void dmtx_set(DotMatrix_Cfg* dmtx, int32_t x, int32_t y, bool bit);
|
||||
|
||||
/** Get a single bit */
|
||||
bool dmtx_get(DotMatrix_Cfg* dmtx, int32_t x, int32_t y);
|
||||
|
||||
/** Toggle a single bit */
|
||||
void dmtx_toggle(DotMatrix_Cfg* dmtx, int32_t x, int32_t y);
|
||||
|
||||
/** Clear the screen (not showing) */
|
||||
void dmtx_clear(DotMatrix_Cfg* dmtx);
|
||||
|
||||
|
||||
+103
-14
@@ -18,7 +18,7 @@ static void conf_spi(void);
|
||||
static void conf_systick(void);
|
||||
static void conf_subsystems(void);
|
||||
static void conf_irq_prios(void);
|
||||
|
||||
static void conf_adc(void);
|
||||
// ---- Public functions ----------
|
||||
|
||||
/**
|
||||
@@ -30,6 +30,7 @@ void hw_init(void)
|
||||
conf_usart();
|
||||
conf_systick();
|
||||
conf_spi();
|
||||
conf_adc();
|
||||
conf_irq_prios();
|
||||
conf_subsystems();
|
||||
}
|
||||
@@ -86,23 +87,23 @@ static void conf_gpio(void)
|
||||
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
GPIO_Init(GPIOC, &gpio_cnf);
|
||||
|
||||
// colorled | sonar trig
|
||||
gpio_cnf.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;
|
||||
gpio_cnf.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
GPIO_Init(GPIOB, &gpio_cnf);
|
||||
|
||||
gpio_cnf.GPIO_Pin = GPIO_Pin_14;
|
||||
gpio_cnf.GPIO_Mode = GPIO_Mode_IPD;
|
||||
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
GPIO_Init(GPIOB, &gpio_cnf);
|
||||
|
||||
// A0-sonar trig | UART2 - debug, UART1 - esp
|
||||
gpio_cnf.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_9 | GPIO_Pin_10;
|
||||
// UARTs
|
||||
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);
|
||||
|
||||
gpio_cnf.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_3;
|
||||
gpio_cnf.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
GPIO_Init(GPIOA, &gpio_cnf);
|
||||
|
||||
|
||||
// A0 - analog input for ADC
|
||||
gpio_cnf.GPIO_Pin = GPIO_Pin_0;
|
||||
gpio_cnf.GPIO_Mode = GPIO_Mode_AIN;
|
||||
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
GPIO_Init(GPIOA, &gpio_cnf);
|
||||
|
||||
// SPI
|
||||
gpio_cnf.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
|
||||
gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
@@ -129,6 +130,7 @@ static void conf_usart(void)
|
||||
|
||||
// Datalink iface
|
||||
data_iface = usart_iface_init(USART1, 460800, 256, 256);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,3 +161,90 @@ static void conf_systick(void)
|
||||
{
|
||||
SysTick_Config(F_CPU / 1000);
|
||||
}
|
||||
|
||||
|
||||
static void conf_adc(void)
|
||||
{
|
||||
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1EN, ENABLE);
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM3EN, ENABLE);
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1EN, ENABLE);
|
||||
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
|
||||
|
||||
// Configure the ADC
|
||||
ADC_DeInit(ADC1);
|
||||
ADC_InitTypeDef adc_cnf;
|
||||
adc_cnf.ADC_Mode = ADC_Mode_Independent;
|
||||
adc_cnf.ADC_ScanConvMode = DISABLE;
|
||||
adc_cnf.ADC_ContinuousConvMode = DISABLE;
|
||||
adc_cnf.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;
|
||||
adc_cnf.ADC_DataAlign = ADC_DataAlign_Right;
|
||||
adc_cnf.ADC_NbrOfChannel = 1;
|
||||
ADC_Init(ADC1, &adc_cnf);
|
||||
ADC_Cmd(ADC1, ENABLE);
|
||||
|
||||
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
|
||||
|
||||
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5);
|
||||
|
||||
// calib
|
||||
ADC_ResetCalibration(ADC1);
|
||||
while(ADC_GetResetCalibrationStatus(ADC1));
|
||||
ADC_StartCalibration(ADC1);
|
||||
while(ADC_GetCalibrationStatus(ADC1));
|
||||
|
||||
|
||||
// Configure the DMA timer
|
||||
TIM_DeInit(TIM3);
|
||||
TIM_TimeBaseInitTypeDef tim_cnf;
|
||||
tim_cnf.TIM_Period = 1800;
|
||||
tim_cnf.TIM_Prescaler = 1;
|
||||
tim_cnf.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
tim_cnf.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
tim_cnf.TIM_RepetitionCounter = 0x0000;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
void hw_init(void);
|
||||
|
||||
void start_adc_dma(uint32_t *memory, uint32_t count);
|
||||
|
||||
+66
-23
@@ -18,10 +18,72 @@
|
||||
#include "max2719.h"
|
||||
#include "dotmatrix.h"
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
static void poll_subsystems(void);
|
||||
|
||||
static DotMatrix_Cfg *dmtx;
|
||||
|
||||
#define SAMP_BUF_LEN 128
|
||||
|
||||
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;
|
||||
|
||||
for (int i = 0; i < samp_count; i++) {
|
||||
samp_buf.floats[i] = samp_buf.uints[i] - 2045.0f;
|
||||
}
|
||||
|
||||
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_len64;
|
||||
|
||||
arm_cfft_f32(S, bins, 0, true); // bit reversed FFT
|
||||
arm_cmplx_mag_f32(bins, bins, bin_count); // get magnitude (extract real values)
|
||||
|
||||
// normalize
|
||||
dmtx_clear(dmtx);
|
||||
float factor = (1.0f/bin_count)*0.1f;
|
||||
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;
|
||||
|
||||
for(int j = 0; j < ceilf(avg); j++) {
|
||||
dmtx_set(dmtx, i/2, j, true);
|
||||
}
|
||||
}
|
||||
|
||||
dmtx_show(dmtx);
|
||||
}
|
||||
|
||||
|
||||
static void capture_audio(void *unused)
|
||||
{
|
||||
(void)unused;
|
||||
|
||||
start_adc_dma(samp_buf.uints, SAMP_BUF_LEN/2);
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
@@ -40,36 +102,17 @@ int main(void)
|
||||
|
||||
dmtx = dmtx_init(&dmtx_cfg);
|
||||
|
||||
dmtx_intensity(dmtx, 2);
|
||||
dmtx_intensity(dmtx, 7);
|
||||
|
||||
add_periodic_task(capture_audio, NULL, 10, false);
|
||||
|
||||
ms_time_t last;
|
||||
while (1) {
|
||||
if (ms_loop_elapsed(&last, 500)) {
|
||||
GPIOC->ODR ^= 1 << 13;
|
||||
}
|
||||
|
||||
poll_subsystems();
|
||||
|
||||
// 1
|
||||
dmtx_clear(dmtx);
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
dmtx_set(dmtx, i, i, true);
|
||||
dmtx_set(dmtx, i+2, i-2, true);
|
||||
dmtx_set(dmtx, i-2, i+2, true);
|
||||
}
|
||||
dmtx_show(dmtx);
|
||||
|
||||
delay_ms(500);
|
||||
|
||||
// 2
|
||||
dmtx_clear(dmtx);
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
dmtx_set(dmtx, 15-i, i, true);
|
||||
dmtx_set(dmtx, 15-(i+2), i-2, true);
|
||||
dmtx_set(dmtx, 15-(i-2), i+2, true);
|
||||
}
|
||||
dmtx_show(dmtx);
|
||||
|
||||
delay_ms(500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,4 +15,7 @@
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
|
||||
void audio_capture_done(void* unused);
|
||||
|
||||
#endif // MAIN_H
|
||||
|
||||
Reference in New Issue
Block a user