116 lines
3.7 KiB
Rust
116 lines
3.7 KiB
Rust
pub mod audio_input;
|
|
pub mod audio_process;
|
|
pub mod config;
|
|
pub mod effects;
|
|
pub mod helpers;
|
|
pub mod led_output;
|
|
pub mod triple_buffer;
|
|
|
|
use esp_idf_svc::{
|
|
hal::peripherals::Peripherals,
|
|
sys::{esp_dsp, esp_nofail},
|
|
};
|
|
|
|
use embassy_executor::Spawner;
|
|
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
|
use static_cell::StaticCell;
|
|
|
|
use audio_input::mic_input_task;
|
|
use audio_process::{process_audio, AudioBuffer, AudioStats, DspBuffer};
|
|
use config::{AUDIO_SAMPLES_PER_BUF, LED_COUNT};
|
|
use effects::{
|
|
bass_sparks::LedEffectBassSparks,
|
|
led_effect::{LedData, LedEffect},
|
|
};
|
|
use led_output::output_leds;
|
|
use triple_buffer::{Receiver, Sender, TripleBuffer};
|
|
|
|
#[embassy_executor::task]
|
|
async fn effect_task(
|
|
mut led_effect: LedEffectBassSparks,
|
|
input: Receiver<'static, NoopRawMutex, (DspBuffer, AudioStats)>,
|
|
output: Sender<'static, NoopRawMutex, LedData>,
|
|
) {
|
|
led_effect.process_led_effect(input, output).await;
|
|
}
|
|
|
|
#[embassy_executor::main]
|
|
async fn main(spawner: Spawner) {
|
|
// It is necessary to call this function once. Otherwise some patches to the runtime
|
|
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
|
esp_idf_svc::sys::link_patches();
|
|
|
|
// Bind the log crate to the ESP Logging facilities
|
|
esp_idf_svc::log::EspLogger::initialize_default();
|
|
|
|
let peripherals = Peripherals::take().unwrap();
|
|
|
|
// mic buffers
|
|
static AUDIO_BUFFER_CELL: StaticCell<[AudioBuffer; 3]> = StaticCell::new();
|
|
let audio_buffer = AUDIO_BUFFER_CELL.init([[0; AUDIO_SAMPLES_PER_BUF]; 3]);
|
|
|
|
static AUDIO_CHANNEL_CELL: StaticCell<TripleBuffer<'_, NoopRawMutex, AudioBuffer>> =
|
|
StaticCell::new();
|
|
let audio_channel = AUDIO_CHANNEL_CELL.init(TripleBuffer::new(audio_buffer));
|
|
let (audio_sender, audio_receiver) = audio_channel.split();
|
|
|
|
// fft buffers
|
|
static FFT_BUFFER_CELL: StaticCell<[(DspBuffer, AudioStats); 3]> = StaticCell::new();
|
|
let fft_buffer =
|
|
FFT_BUFFER_CELL.init([([0f32; AUDIO_SAMPLES_PER_BUF], AudioStats::default()); 3]);
|
|
|
|
static FFT_CHANNEL_CELL: StaticCell<TripleBuffer<'_, NoopRawMutex, (DspBuffer, AudioStats)>> =
|
|
StaticCell::new();
|
|
let fft_channel = FFT_CHANNEL_CELL.init(TripleBuffer::new(fft_buffer));
|
|
let (fft_sender, fft_receiver) = fft_channel.split();
|
|
|
|
// leds
|
|
static LED_DATA: StaticCell<[LedData; 3]> = StaticCell::new();
|
|
let leds = LED_DATA.init([LedData::default(); 3]);
|
|
|
|
static LED_CHANNEL: StaticCell<TripleBuffer<'_, NoopRawMutex, LedData>> = StaticCell::new();
|
|
let led_channel = LED_CHANNEL.init(TripleBuffer::new(leds));
|
|
let (led_sender, led_receiver) = led_channel.split();
|
|
|
|
unsafe {
|
|
esp_nofail!(esp_dsp::dsps_fft2r_init_fc32(
|
|
std::ptr::null_mut(),
|
|
(AUDIO_SAMPLES_PER_BUF / 2) as i32
|
|
));
|
|
esp_nofail!(esp_dsp::dsps_fft4r_init_fc32(
|
|
std::ptr::null_mut(),
|
|
(AUDIO_SAMPLES_PER_BUF / 2) as i32
|
|
));
|
|
}
|
|
|
|
spawner
|
|
.spawn(mic_input_task(
|
|
peripherals.i2s0,
|
|
peripherals.pins.gpio5,
|
|
peripherals.pins.gpio4,
|
|
peripherals.pins.gpio6,
|
|
audio_sender,
|
|
))
|
|
.expect("spawn failed");
|
|
|
|
spawner
|
|
.spawn(process_audio(audio_receiver, fft_sender))
|
|
.expect("spawn failed");
|
|
|
|
spawner
|
|
.spawn(effect_task(
|
|
LedEffectBassSparks::default(),
|
|
fft_receiver,
|
|
led_sender,
|
|
))
|
|
.expect("spawn failed");
|
|
|
|
spawner
|
|
.spawn(output_leds(
|
|
peripherals.spi2,
|
|
peripherals.pins.gpio11,
|
|
peripherals.pins.gpio12,
|
|
led_receiver,
|
|
))
|
|
.expect("spawn failed");
|
|
}
|