effects split into functions
This commit is contained in:
parent
f5e663b724
commit
36f896db35
2 changed files with 327 additions and 42 deletions
|
@ -2,5 +2,6 @@ idf_component_register(SRCS "ledstick_main.c"
|
|||
PRIV_REQUIRES
|
||||
spi_flash
|
||||
esp_driver_i2s
|
||||
esp_driver_uart
|
||||
# esp_driver_uart
|
||||
esp_driver_spi
|
||||
INCLUDE_DIRS "")
|
||||
|
|
|
@ -12,8 +12,13 @@
|
|||
#include "sdkconfig.h"
|
||||
|
||||
#include "driver/i2s_std.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/spi_master.h"
|
||||
// #include "driver/uart.h"
|
||||
|
||||
#include "hal/spi_ll.h"
|
||||
|
||||
#include "esp_dsp.h"
|
||||
#include "esp_random.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
|
@ -32,7 +37,7 @@ complex format: buf[0]=re[0], buf[1]=im[0]
|
|||
#define I2S_MIC_WS_PIN GPIO_NUM_6
|
||||
|
||||
#define SAMPLE_RATE 24000
|
||||
#define SAMPLE_COUNT 512
|
||||
#define SAMPLE_COUNT 1024
|
||||
#define SAMPLE_CHANNELS 1
|
||||
#define SAMPLE_TYPE int32_t
|
||||
#define SAMPLE_MAX 2147483648.0f
|
||||
|
@ -41,6 +46,8 @@ complex format: buf[0]=re[0], buf[1]=im[0]
|
|||
|
||||
#define BANDS_COUNT 3
|
||||
|
||||
#define LEDS_COUNT 72
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
/*
|
||||
|
||||
|
@ -66,6 +73,7 @@ treb: 43-255
|
|||
#define ABS(T, v) ((v < 0 ? (((T)0) - v) : v))
|
||||
#define MAX(a, b) ((b > a) ? (b) : (a))
|
||||
#define MIN(a, b) ((b < a) ? (b) : (a))
|
||||
#define DEC(v, delta) (MAX(v, delta) - delta)
|
||||
|
||||
#define SUM_BAND(IDX, BUF, START, END) \
|
||||
current_powers[IDX] = 0; \
|
||||
|
@ -75,7 +83,20 @@ treb: 43-255
|
|||
} \
|
||||
current_powers[IDX] /= (END + 1 - START);
|
||||
|
||||
i2s_chan_handle_t rx_handle = NULL;
|
||||
#define RGB(R, G, B, V) ((uint32_t)(0xe0) | (V) | (B << 8) | (G << 16) | (R << 24))
|
||||
#define SET_RGB(old, R, G, B) ((old&0x000000E0) | (uint32_t)(0xe0) | (V) | (B << 8) | (G << 16) | (R << 24)))
|
||||
#define SET_R(old, R) ((old & 0x00FFFFFF) | (R << 24))
|
||||
#define SET_G(old, G) ((old & 0xFF00FFFF) | (G << 16))
|
||||
#define SET_B(old, B) ((old & 0xFFFF00FF) | (B << 8))
|
||||
#define SET_V(old, V) ((old & 0xFFFFFFE0) | (V))
|
||||
#define GET_R(color) ((color & 0xFF000000) >> 24)
|
||||
#define GET_G(color) ((color & 0x00FF0000) >> 16)
|
||||
#define GET_B(color) ((color & 0x0000FF00) >> 8)
|
||||
#define GET_V(color) ((color & 0x0000001F))
|
||||
|
||||
spi_device_handle_t led_spi_dev = NULL;
|
||||
i2s_chan_handle_t i2s_rx_channel = NULL;
|
||||
|
||||
TaskHandle_t proc_task = NULL;
|
||||
TaskHandle_t output_task = NULL;
|
||||
|
||||
|
@ -90,14 +111,21 @@ float avg_powers[BANDS_COUNT];
|
|||
|
||||
SAMPLE_TYPE floating_max;
|
||||
|
||||
// float recursive_add_f(float* buffer, int start, int end) {
|
||||
/* 111v.vvvv gggg.gggg rrrr.rrrr bbbb.bbbb */
|
||||
typedef struct LedDataStruct
|
||||
{
|
||||
// SK9822 has one start and one stop word
|
||||
uint32_t zeros;
|
||||
uint32_t buffer[LEDS_COUNT];
|
||||
uint32_t ones;
|
||||
} LedData;
|
||||
|
||||
// }
|
||||
LedData leds;
|
||||
|
||||
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));
|
||||
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &i2s_rx_channel));
|
||||
|
||||
i2s_std_config_t i2s_rx_cfg = {
|
||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
|
||||
|
@ -129,38 +157,288 @@ void app_init_mic(void)
|
|||
},
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &i2s_rx_cfg));
|
||||
ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));
|
||||
ESP_ERROR_CHECK(i2s_channel_init_std_mode(i2s_rx_channel, &i2s_rx_cfg));
|
||||
ESP_ERROR_CHECK(i2s_channel_enable(i2s_rx_channel));
|
||||
}
|
||||
|
||||
void app_init_led_spi()
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
spi_bus_config_t bus_cfg = {
|
||||
.mosi_io_num = 11,
|
||||
.sclk_io_num = 12,
|
||||
.miso_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.data4_io_num = -1,
|
||||
.data5_io_num = -1,
|
||||
.data6_io_num = -1,
|
||||
.data7_io_num = -1,
|
||||
.flags =
|
||||
SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_IOMUX_PINS | SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI,
|
||||
.max_transfer_sz = sizeof(leds),
|
||||
};
|
||||
|
||||
ret = spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
spi_device_interface_config_t dev_cfg = {
|
||||
.clock_speed_hz = 10000000,
|
||||
.spics_io_num = 10,
|
||||
.mode = 3,
|
||||
.queue_size = 1,
|
||||
.cs_ena_pretrans = 1,
|
||||
.cs_ena_posttrans = 1,
|
||||
.command_bits = 0,
|
||||
.address_bits = 0,
|
||||
.dummy_bits = 0,
|
||||
};
|
||||
|
||||
ret = spi_bus_add_device(SPI2_HOST, &dev_cfg, &led_spi_dev);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
ret = spi_device_acquire_bus(led_spi_dev, portMAX_DELAY);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
// spi_ll_master_set_mode(&GPSPI2, 3);
|
||||
// spi_ll_set_mosi_free_level(&GPSPI2, 1);
|
||||
// spi_ll_apply_config(&GPSPI2);
|
||||
}
|
||||
|
||||
// static void app_output_task(void *args)
|
||||
// {
|
||||
// uint32_t in_fft_buf_idx;
|
||||
|
||||
// const uint8_t sync_word[] = {0x00, 0x11, 0x80, 0x00, 0x7f, 0xff, 0x11, 0x00};
|
||||
|
||||
// while (1)
|
||||
// {
|
||||
// xTaskNotifyWait(0, 0, &in_fft_buf_idx, portMAX_DELAY);
|
||||
// if (in_fft_buf_idx >= BUF_COUNT)
|
||||
// {
|
||||
// printf("output buf count wrong: %ld", in_fft_buf_idx);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// float *fft_buf = fft_buffer + in_fft_buf_idx * SAMPLE_COUNT;
|
||||
|
||||
// // buf[SAMPLE_COUNT - 1] = floating_max;
|
||||
|
||||
// uart_write_bytes(UART_NUM_0, sync_word, sizeof(sync_word));
|
||||
|
||||
// xSemaphoreTake(output_mutex, portMAX_DELAY);
|
||||
// uart_write_bytes(UART_NUM_0, &floating_max, sizeof(floating_max));
|
||||
// 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);
|
||||
|
||||
// uart_write_bytes(UART_NUM_0, fft_buf, sizeof(float) * SAMPLE_COUNT / 2);
|
||||
// }
|
||||
// }
|
||||
|
||||
static uint32_t random_at_most(uint32_t max)
|
||||
{
|
||||
// impl from https://stackoverflow.com/a/6852396, adapted to uint32/2
|
||||
// Assumes 0 <= max <= INT32_MAX
|
||||
// Returns in the closed interval [0, max]
|
||||
uint32_t
|
||||
// max <= INT32_MAX < UINT32_MAX, so this is okay.
|
||||
num_bins = (uint32_t)max + 1,
|
||||
num_rand = (uint32_t)INT32_MAX + 1, bin_size = num_rand / num_bins, defect = num_rand % num_bins;
|
||||
|
||||
long x;
|
||||
do
|
||||
{
|
||||
x = esp_random() >> 1;
|
||||
}
|
||||
// This is carefully written not to overflow
|
||||
while (num_rand - defect <= (uint32_t)x);
|
||||
|
||||
// Truncated division is intentional
|
||||
return x / bin_size;
|
||||
}
|
||||
|
||||
static void app_init_led_buffer()
|
||||
{
|
||||
leds.zeros = 0;
|
||||
leds.ones = 0; // sic. works as well, and triggers PWM change at the end of frame transfer instead of next one.
|
||||
|
||||
for (int i = 0; i < LEDS_COUNT; i++)
|
||||
{
|
||||
leds.buffer[i] = RGB(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline TickType_t app_effect_blob_run()
|
||||
{
|
||||
uint32_t in_fft_buf_idx;
|
||||
|
||||
if (xTaskNotifyWait(0, 0, &in_fft_buf_idx, pdMS_TO_TICKS(100)) == pdPASS)
|
||||
{
|
||||
if (in_fft_buf_idx >= BUF_COUNT)
|
||||
{
|
||||
printf("output buf count wrong: %ld", in_fft_buf_idx);
|
||||
return pdMS_TO_TICKS(10);
|
||||
}
|
||||
|
||||
xSemaphoreTake(output_mutex, portMAX_DELAY);
|
||||
if (current_powers[0] > 1.2 * avg_powers[0])
|
||||
{
|
||||
leds.buffer[0] = RGB(255, 0, 0, 31);
|
||||
}
|
||||
xSemaphoreGive(output_mutex);
|
||||
}
|
||||
|
||||
for (int i = 0; i < LEDS_COUNT / 2 - 1; i++)
|
||||
{
|
||||
leds.buffer[LEDS_COUNT / 2 + i] = leds.buffer[LEDS_COUNT / 2 + i + 1];
|
||||
leds.buffer[LEDS_COUNT / 2 - 1 - i] = leds.buffer[LEDS_COUNT / 2 - 1 - i - 1];
|
||||
}
|
||||
|
||||
xSemaphoreTake(output_mutex, portMAX_DELAY);
|
||||
uint32_t new_color =
|
||||
RGB(GET_R(leds.buffer[0]) >> 1, GET_G(leds.buffer[0]) >> 1, GET_B(leds.buffer[0]) >> 1, GET_V(leds.buffer[0]));
|
||||
|
||||
if (current_powers[0] > 1.35 * avg_powers[0])
|
||||
{
|
||||
new_color = SET_R(new_color, 255);
|
||||
}
|
||||
if (current_powers[1] > 1.35 * avg_powers[1])
|
||||
{
|
||||
new_color = SET_G(new_color, 255);
|
||||
}
|
||||
if (current_powers[2] > 1.35 * avg_powers[2])
|
||||
{
|
||||
new_color = SET_B(new_color, 255);
|
||||
}
|
||||
xSemaphoreGive(output_mutex);
|
||||
|
||||
leds.buffer[0] = new_color;
|
||||
leds.buffer[LEDS_COUNT - 1] = new_color;
|
||||
return pdMS_TO_TICKS(10);
|
||||
}
|
||||
|
||||
static inline TickType_t app_effect_bass_sparks()
|
||||
{
|
||||
static uint32_t bass_color = RGB(0, 0, 0, 0);
|
||||
|
||||
// if (xTaskNotifyWait(0, 0, &in_fft_buf_idx, pdMS_TO_TICKS(100)) == pdPASS)
|
||||
// {
|
||||
// if (in_fft_buf_idx >= BUF_COUNT)
|
||||
// {
|
||||
// printf("output buf count wrong: %ld", in_fft_buf_idx);
|
||||
// return pdMS_TO_TICKS(10);
|
||||
// }
|
||||
// }
|
||||
|
||||
xSemaphoreTake(output_mutex, portMAX_DELAY);
|
||||
|
||||
if (current_powers[0] > 1.25 * avg_powers[0])
|
||||
{
|
||||
bass_color = RGB(127, 0, 255, 4);
|
||||
}
|
||||
for (int i = 0; i < LEDS_COUNT; i++)
|
||||
{
|
||||
leds.buffer[i] = bass_color;
|
||||
}
|
||||
|
||||
// bass_color = SET_V(bass_color, MAX(GET_V(bass_color), 1) - 1);
|
||||
// bass_color = RGB(GET_R(bass_color) >> 1, GET_G(bass_color) >> 1, GET_B(bass_color) >> 1, GET_V(bass_color));
|
||||
bass_color =
|
||||
RGB(DEC(GET_R(bass_color), 3), DEC(GET_G(bass_color), 5), DEC(GET_B(bass_color), 6), GET_V(bass_color));
|
||||
|
||||
if ((current_powers[1] > 1.35 * avg_powers[1]) && (current_powers[2] > 1.35 * avg_powers[2]))
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
uint32_t led_idx = random_at_most(LEDS_COUNT);
|
||||
leds.buffer[led_idx] = RGB(255, 255, 255, 31);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(output_mutex);
|
||||
return pdMS_TO_TICKS(10);
|
||||
}
|
||||
|
||||
static inline TickType_t app_effect_fft_colors()
|
||||
{
|
||||
uint32_t in_fft_buf_idx;
|
||||
|
||||
if (xTaskNotifyWait(0, 0, &in_fft_buf_idx, pdMS_TO_TICKS(1)) == pdPASS)
|
||||
{
|
||||
if (in_fft_buf_idx >= BUF_COUNT)
|
||||
{
|
||||
printf("output buf count wrong: %ld", in_fft_buf_idx);
|
||||
return pdMS_TO_TICKS(10);
|
||||
}
|
||||
float *fft_buf = fft_buffer + in_fft_buf_idx * SAMPLE_COUNT;
|
||||
for (int i = 0; i < LEDS_COUNT && i < SAMPLE_COUNT / 4; i++)
|
||||
{
|
||||
uint32_t new_color = RGB(0, 0, 0, 2);
|
||||
if (fft_buf[i * 2] < 0.3)
|
||||
{
|
||||
new_color = SET_R(new_color, (uint8_t)(fft_buf[i * 2] * 700));
|
||||
}
|
||||
else if (fft_buf[i * 2] < 0.6)
|
||||
{
|
||||
new_color = SET_G(new_color, (uint8_t)(fft_buf[i * 2] * 400));
|
||||
}
|
||||
else
|
||||
{
|
||||
new_color = SET_B(new_color, (uint8_t)(fft_buf[i * 2] * 200));
|
||||
}
|
||||
leds.buffer[i] = new_color;
|
||||
}
|
||||
}
|
||||
|
||||
xSemaphoreTake(output_mutex, portMAX_DELAY);
|
||||
uint32_t new_color =
|
||||
RGB(GET_R(leds.buffer[0]) >> 1, GET_G(leds.buffer[0]) >> 1, GET_B(leds.buffer[0]) >> 1, GET_V(leds.buffer[0]));
|
||||
|
||||
if (current_powers[0] > 1.35 * avg_powers[0])
|
||||
{
|
||||
new_color = SET_R(new_color, 255);
|
||||
}
|
||||
if (current_powers[1] > 1.35 * avg_powers[1])
|
||||
{
|
||||
new_color = SET_G(new_color, 255);
|
||||
}
|
||||
if (current_powers[2] > 1.35 * avg_powers[2])
|
||||
{
|
||||
new_color = SET_B(new_color, 255);
|
||||
}
|
||||
xSemaphoreGive(output_mutex);
|
||||
|
||||
return pdMS_TO_TICKS(10);
|
||||
}
|
||||
|
||||
static void app_output_task(void *args)
|
||||
{
|
||||
uint32_t in_fft_buf_idx;
|
||||
esp_err_t ret;
|
||||
|
||||
const uint8_t sync_word[] = {0x00, 0x11, 0x80, 0x00, 0x7f, 0xff, 0x11, 0x00};
|
||||
app_init_led_spi();
|
||||
app_init_led_buffer();
|
||||
|
||||
spi_transaction_t trans = {
|
||||
.length = sizeof(leds) * 8, // in bits
|
||||
.tx_buffer = (uint8_t *)&leds,
|
||||
};
|
||||
|
||||
TickType_t last_ticks = xTaskGetTickCount();
|
||||
|
||||
while (1)
|
||||
{
|
||||
xTaskNotifyWait(0, 0, &in_fft_buf_idx, portMAX_DELAY);
|
||||
if (in_fft_buf_idx >= BUF_COUNT)
|
||||
{
|
||||
printf("output buf count wrong: %ld", in_fft_buf_idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
float *fft_buf = fft_buffer + in_fft_buf_idx * SAMPLE_COUNT;
|
||||
// TickType_t next_ticks = app_effect_blob_run();
|
||||
// TickType_t next_ticks = app_effect_fft_colors();
|
||||
TickType_t next_ticks = app_effect_bass_sparks();
|
||||
|
||||
// buf[SAMPLE_COUNT - 1] = floating_max;
|
||||
ret = spi_device_transmit(led_spi_dev, &trans);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
uart_write_bytes(UART_NUM_0, sync_word, sizeof(sync_word));
|
||||
xTaskDelayUntil(&last_ticks, next_ticks);
|
||||
|
||||
xSemaphoreTake(output_mutex, portMAX_DELAY);
|
||||
uart_write_bytes(UART_NUM_0, &floating_max, sizeof(floating_max));
|
||||
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);
|
||||
|
||||
uart_write_bytes(UART_NUM_0, fft_buf, sizeof(float) * SAMPLE_COUNT / 2);
|
||||
// uart_write_bytes(UART_NUM_0, fft_buf, sizeof(float) * SAMPLE_COUNT / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,9 +508,15 @@ static void app_process_task(void *args)
|
|||
|
||||
xSemaphoreTake(output_mutex, portMAX_DELAY);
|
||||
|
||||
SUM_BAND(0, fft_buf, 1, 4);
|
||||
SUM_BAND(1, fft_buf, 5, 45);
|
||||
SUM_BAND(2, fft_buf, 46, 255);
|
||||
SUM_BAND(0, fft_buf, 1, 8);
|
||||
SUM_BAND(1, fft_buf, 9, 86);
|
||||
SUM_BAND(2, fft_buf, 87, 470);
|
||||
|
||||
// 512
|
||||
// SUM_BAND(0, fft_buf, 1, 4);
|
||||
// SUM_BAND(1, fft_buf, 5, 45);
|
||||
// SUM_BAND(2, fft_buf, 46, 255);
|
||||
|
||||
// SUM_BAND(0, fft_buf, 1, 4);
|
||||
// SUM_BAND(1, fft_buf, 5, 42);
|
||||
// SUM_BAND(2, fft_buf, 43, 511);
|
||||
|
@ -259,17 +543,17 @@ void app_main(void)
|
|||
|
||||
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_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);
|
||||
// uart_driver_install(UART_NUM_0, 256, 256, 0, NULL, 0);
|
||||
|
||||
ret = dsps_fft2r_init_fc32(NULL, SAMPLE_COUNT >> 1);
|
||||
if (ret != ESP_OK)
|
||||
|
@ -292,8 +576,8 @@ void app_main(void)
|
|||
|
||||
while (1)
|
||||
{
|
||||
if (i2s_channel_read(rx_handle, (char *)i2s_readraw_buff + (BUF_SIZE_BYTES * next_rx_buf_idx), BUF_SIZE_BYTES,
|
||||
&bytes_read, 1000) == ESP_OK)
|
||||
if (i2s_channel_read(i2s_rx_channel, (char *)i2s_readraw_buff + (BUF_SIZE_BYTES * next_rx_buf_idx),
|
||||
BUF_SIZE_BYTES, &bytes_read, 1000) == ESP_OK)
|
||||
{
|
||||
xTaskNotify(proc_task, next_rx_buf_idx, eSetValueWithOverwrite);
|
||||
next_rx_buf_idx = (next_rx_buf_idx + 1) & (BUF_COUNT - 1);
|
||||
|
|
Loading…
Add table
Reference in a new issue