commit ce70442a2abaf2ae8c546fae846600038e09384e Author: Lucas Schumacher Date: Wed Nov 15 21:11:31 2023 -0500 first commit diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..c2924b9 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,17 @@ +[build] +target = "xtensa-esp32-espidf" + +[target.xtensa-esp32-espidf] +linker = "ldproxy" +# runner = "espflash --monitor" # Select this runner for espflash v1.x.x +runner = "espflash flash --monitor" # Select this runner for espflash v2.x.x +rustflags = [ "--cfg", "espidf_time64"] # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110 + +[unstable] +build-std = ["std", "panic_abort"] + +[env] +MCU="esp32" +# Note: this variable is not used by the pio builder (`cargo build --features pio`) +ESP_IDF_VERSION = "v5.1.1" + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73a638b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.vscode +/.embuild +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9d0ae97 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "esp32-sound" +version = "0.1.0" +authors = ["Lucas Schumacher "] +edition = "2021" +resolver = "2" +rust-version = "1.71" + +[profile.release] +opt-level = "s" + +[profile.dev] +debug = true # Symbols are nice and they don't increase the size on Flash +opt-level = "z" + +[features] +default = ["std", "embassy", "esp-idf-svc/native"] + +pio = ["esp-idf-svc/pio"] +std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"] +alloc = ["esp-idf-svc/alloc"] +nightly = ["esp-idf-svc/nightly"] +experimental = ["esp-idf-svc/experimental"] +embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"] + +[dependencies] +log = { version = "0.4", default-features = false } +esp-idf-svc = { version = "0.47.3", default-features = false } + +[build-dependencies] +embuild = "0.31.3" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..112ec3f --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + embuild::espidf::sysenv::output(); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..a2f5ab5 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "esp" diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..9ea5d73 --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,10 @@ +# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 + +# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). +# This allows to use 1 ms granuality for thread sleeps (10 ms by default). +#CONFIG_FREERTOS_HZ=1000 + +# Workaround for https://github.com/espressif/esp-idf/issues/7631 +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6d70a4d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,70 @@ +use std::{mem::transmute, time::Duration}; + +use esp_idf_svc::hal::{ + delay::TickType, + gpio::AnyIOPin, + i2s::{ + config::{DataBitWidth, StdConfig}, + I2sDriver, I2sTx, + }, + peripherals::Peripherals, +}; + +const TBL_LEN: usize = 1024; +const RATE: u32 = 48000; + +fn main() -> ! { + // 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(); + + log::info!("Hello, world!"); + let peripherals = Peripherals::take().unwrap(); + + let mut wav_tbl: [i16; TBL_LEN] = [0; TBL_LEN]; + + log::info!("Generating wave table..."); + for (i, sample) in wav_tbl.iter_mut().enumerate() { + *sample = ((2.0 * std::f32::consts::PI * (i as f32 / TBL_LEN as f32)).sin() + * std::i16::MAX as f32) as i16; + } + log::info!("Done generating wave table!"); + + //TODO! setup SGTL5000 via i2c + // + // start i2c + // + + //i2s setup + let std_config = StdConfig::philips(RATE, DataBitWidth::Bits16); + let bclk = peripherals.pins.gpio1; + let _din = peripherals.pins.gpio4; + let dout = peripherals.pins.gpio6; + let mclk = AnyIOPin::none(); + let ws = peripherals.pins.gpio2; + let mut i2s = + I2sDriver::::new_std_tx(peripherals.i2s0, &std_config, bclk, dout, mclk, ws) + .unwrap(); + i2s.tx_enable().unwrap(); + + let mut buffer: [i16; 1024] = [0; 1024]; // Should be even length + let mut phase: f32 = 0.0; + let phase_delta = (440.0 / RATE as f32) * TBL_LEN as f32; + let timeout = TickType::from(Duration::from_secs_f32( + 2. * buffer.len() as f32 / RATE as f32, + )); + loop { + // Generate 440hz tone + for i in (0..buffer.len() - 1).step_by(2) { + buffer[i] = wav_tbl[phase as usize]; + buffer[i + 1] = wav_tbl[phase as usize]; + phase = (phase + phase_delta) % (TBL_LEN as f32); + } + let bytes: &[u8; 2048] = unsafe { transmute(&buffer) }; + // Send samples to i2s device + i2s.write_all(bytes, timeout.0).unwrap(); + } +}