ledstick/main/ledstick_main.c
Patrick Moessler fc4005cc49 v2
2025-02-24 00:29:15 +01:00

269 lines
7.6 KiB
C

/* SPDX - FileCopyrightText : 2025 Asaril
** SPDX - License - Identifier : CC0 - 1.0
*/
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include <inttypes.h>
#include <stdio.h>
#include "driver/i2s_std.h"
#include "driver/uart.h"
#include "esp_dsp.h"
static const char *TAG = "main";
/*
24000 hz sample rate
16bit per channel
2 channel i2s input, second zeros
complex format: buf[0]=re[0], buf[1]=im[0]
*/
#define I2S_MIC_SCLK_PIN GPIO_NUM_4
#define I2S_MIC_SD_PIN GPIO_NUM_5
#define I2S_MIC_WS_PIN GPIO_NUM_6
#define SAMPLE_RATE 24000
#define SAMPLE_COUNT 512
#define SAMPLE_CHANNELS 2
#define SAMPLE_TYPE int16_t
#define BUF_COUNT 4
#define BANDS_COUNT 3
// ----------------------------------------------------------------
/*
512:
bass: 1-4
mid: 5-42
treb: 43-255
*/
#define SAMPLE_BYTES (sizeof(SAMPLE_TYPE))
#define BUF_SIZE_SAMPLES (SAMPLE_COUNT * SAMPLE_CHANNELS)
#define BUF_SIZE_BYTES (BUF_SIZE_SAMPLES * SAMPLE_BYTES)
#define FALLOFF(OLD_V, NEW_V) ((OLD_V >> 1) + (OLD_V >> 2) + (NEW_V >> 2))
#define ABS(T, V) ((v < 0 ? (((T)0) - v) : v))
#define MAX(a, b) ((b > a) ? (b) : (a))
i2s_chan_handle_t rx_handle = NULL;
TaskHandle_t proc_task = NULL;
TaskHandle_t output_task = NULL;
SemaphoreHandle_t output_mutex;
__attribute__((aligned(16))) static SAMPLE_TYPE i2s_readraw_buff[BUF_SIZE_BYTES * BUF_COUNT];
uint32_t current_powers[BANDS_COUNT];
uint32_t avg_powers[BANDS_COUNT];
int16_t floating_max;
void app_init_mic(void)
{
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &rx_handle));
i2s_std_config_t i2s_rx_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
/* The default mono slot is the left slot (whose 'select pin' of the PDM microphone is pulled down) */
.slot_cfg =
{
.data_bit_width = 8 * SAMPLE_BYTES,
.slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT,
.slot_mode = I2S_SLOT_MODE_MONO,
.slot_mask = I2S_STD_SLOT_BOTH,
.ws_width = 32,
.ws_pol = false,
.bit_shift = true,
.left_align = true,
.big_endian = false,
.bit_order_lsb = false,
},
.gpio_cfg =
{
.mclk = I2S_GPIO_UNUSED,
.bclk = I2S_MIC_SCLK_PIN,
.din = I2S_MIC_SD_PIN,
.ws = I2S_MIC_WS_PIN,
.invert_flags =
{
.bclk_inv = false,
.mclk_inv = false,
.ws_inv = false,
},
},
};
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &i2s_rx_cfg));
ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));
}
static void app_process_task(void *args)
{
uint32_t notify_value;
while (1)
{
xTaskNotifyWait(0, 0, &notify_value, portMAX_DELAY);
if (notify_value >= BUF_COUNT)
{
printf("process buf count wrong: %ld", notify_value);
continue;
}
SAMPLE_TYPE *buf = i2s_readraw_buff + notify_value * BUF_SIZE_SAMPLES;
// printf("%08lx - %08lx - %08lx\n", (uint32_t)i2s_readraw_buff, (uint32_t)buf,
// (uint32_t)(buf - i2s_readraw_buff));
int16_t max = 0;
for (int i = 0; i < SAMPLE_COUNT; i++)
{
max = MAX(max, buf[i * 2]);
}
floating_max = (max > floating_max) ? max : FALLOFF(floating_max, FALLOFF(floating_max,max));
// int16_t scale = 0x7fff / floating_max;
int16_t scale = 8;
// for (int16_t max_tmp = floating_max; scale < 15 && ((max_tmp & 0x8000) == 0); scale++, max_tmp <<= 1)
// ;
for (int i = 0; i < SAMPLE_COUNT; i++)
{
buf[i * 2] <<= scale-1;
}
// dsps_mulc_s16_ae32(buf,buf,SAMPLE_COUNT,scale,1,1);
// dsps_fft2r_sc16(buf, SAMPLE_COUNT);
// dsps_bit_rev_sc16_ansi(buf, SAMPLE_COUNT);
// dsps_cplx2real_sc16_ansi(buf, SAMPLE_COUNT);
xSemaphoreTake(output_mutex, portMAX_DELAY);
// current_powers[band] = 0;
// for (int band=START;band<END;band++){
// current_powers[band] = ;
// }
// for (int band = 0; band < BANDS_COUNT; band++)
// {
// current_powers[band] = 0;
// for (int freq = 0; freq < FREQS_PER_BAND; freq++)
// {
// // current_powers[band] += abs(buf[band * FREQS_PER_BAND + freq]);
// SAMPLE_TYPE v = buf[band * FREQS_PER_BAND + freq];
// if (v < 0)
// {
// current_powers[band] -= v;
// }
// else
// {
// current_powers[band] += v;
// }
// if(band==0 && freq<BANDS_COUNT){
// avg_powers[freq] = v; //current_powers[band];
// }
// }
// uint32_t old_band_avg_power = avg_powers[band];
// // avg_powers[band] = 0; // (old_band_avg_power >> 1) + (old_band_avg_power >> 2) + (current_powers[band]
// >> 2);
// }
xSemaphoreGive(output_mutex);
xTaskNotify(output_task, notify_value, eSetValueWithOverwrite);
// printf("[0] %08x [1] %08x [2] %08x [3]%08x ...\n", (buf[0]), (buf[1]), (buf[2]), (buf[3]));
}
}
static void app_output_task(void *args)
{
uint32_t notify_value;
const uint8_t sync_word[] = {0x00,0x11,0x80,0x00,0x7f,0xff,0x11,0x00};
while (1)
{
xTaskNotifyWait(0, 0, &notify_value, portMAX_DELAY);
if (notify_value >= BUF_COUNT)
{
printf("output buf count wrong: %ld", notify_value);
continue;
}
SAMPLE_TYPE *buf = i2s_readraw_buff + notify_value * BUF_SIZE_SAMPLES;
buf[SAMPLE_COUNT - 1] = floating_max;
uart_write_bytes(UART_NUM_0, sync_word, sizeof(sync_word));
uart_write_bytes(UART_NUM_0, buf, BUF_SIZE_BYTES);
// xSemaphoreTake(output_mutex, portMAX_DELAY);
// uart_write_bytes(UART_NUM_0, avg_powers, sizeof(avg_powers));
// uart_write_bytes(UART_NUM_0, current_powers, sizeof(current_powers));
// xSemaphoreGive(output_mutex);
}
}
void app_main(void)
{
size_t bytes_read = 0;
uint32_t next_rx = 0;
esp_err_t ret;
app_init_mic();
uart_config_t uart_cfg = {
.baud_rate = 1000000,
.data_bits = UART_DATA_8_BITS,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
};
uart_param_config(UART_NUM_0, &uart_cfg);
uart_set_pin(UART_NUM_0, 17, 18, -1, -1);
uart_driver_install(UART_NUM_0, 256, 256, 0, NULL, 0);
ret = dsps_fft2r_init_sc16(NULL, SAMPLE_COUNT);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
return;
}
output_mutex = xSemaphoreCreateMutex();
xTaskCreate(&app_output_task, "app_output_task", 4096, NULL, 5, &output_task);
xTaskCreate(&app_process_task, "app_process_task", 4096, NULL, 5, &proc_task);
while (1)
{
if (i2s_channel_read(rx_handle, (char *)i2s_readraw_buff + (BUF_SIZE_BYTES * next_rx), BUF_SIZE_BYTES,
&bytes_read, 1000) == ESP_OK)
{
xTaskNotify(proc_task, next_rx, eSetValueWithOverwrite);
next_rx = (next_rx + 1) & (BUF_COUNT - 1);
// printf("main buf next %ld\n", next_rx);
taskYIELD();
}
}
}