diff --git a/.cargo/config.toml b/.cargo/config.toml index 08e79ba..65ada11 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,14 +1,15 @@ [target.riscv32imc-unknown-none-elf] -runner = "espflash flash --monitor --chip esp32c3" +runner = "espflash flash --monitor --chip esp32c3 --partition-table ./partitions.csv" [env] -ESP_LOG="info" +ESP_LOG = "info" [build] rustflags = [ - # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) - # NOTE: May negatively impact performance of produced code - "-C", "force-frame-pointers", + # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) + # NOTE: May negatively impact performance of produced code + "-C", + "force-frame-pointers", ] target = "riscv32imc-unknown-none-elf" diff --git a/Cargo.lock b/Cargo.lock index d3bf475..ffa4b65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,15 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -111,7 +120,7 @@ dependencies = [ "embedded-io", "embedded-io-async", "futures-intrusive", - "heapless", + "heapless 0.8.0", ] [[package]] @@ -147,6 +156,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] + [[package]] name = "critical-section" version = "1.2.0" @@ -266,7 +284,7 @@ dependencies = [ "embassy-time", "embedded-io-async", "embedded-nal-async", - "heapless", + "heapless 0.8.0", "managed", "smoltcp", ] @@ -288,7 +306,7 @@ dependencies = [ "embedded-io-async", "futures-sink", "futures-util", - "heapless", + "heapless 0.8.0", ] [[package]] @@ -302,7 +320,7 @@ dependencies = [ "embedded-io-async", "futures-sink", "futures-util", - "heapless", + "heapless 0.8.0", ] [[package]] @@ -338,7 +356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83" dependencies = [ "embassy-executor", - "heapless", + "heapless 0.8.0", ] [[package]] @@ -487,6 +505,17 @@ dependencies = [ "termcolor", ] +[[package]] +name = "esp-build" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "837020ff95fbf4c15c206541dda7994f1bbe6e1505e36a6a5ecb51fdb61656d7" +dependencies = [ + "quote", + "syn 2.0.104", + "termcolor", +] + [[package]] name = "esp-config" version = "0.3.1" @@ -520,10 +549,10 @@ dependencies = [ "embedded-io", "embedded-io-async", "enumset", - "esp-build", + "esp-build 0.2.0", "esp-config", "esp-hal-procmacros", - "esp-metadata", + "esp-metadata 0.6.0", "esp-riscv-rt", "esp32c3", "fugit", @@ -555,11 +584,11 @@ dependencies = [ "embassy-time", "embassy-time-driver", "embassy-time-queue-utils", - "esp-build", + "esp-build 0.2.0", "esp-config", "esp-hal", "esp-hal-procmacros", - "esp-metadata", + "esp-metadata 0.6.0", "portable-atomic", "static_cell", ] @@ -592,6 +621,18 @@ dependencies = [ "strum 0.26.3", ] +[[package]] +name = "esp-metadata" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0154d59933c2419ef25a01938517cc6969f47b6af53ebb34c279393aa20d9654" +dependencies = [ + "anyhow", + "basic-toml", + "serde", + "strum 0.27.1", +] + [[package]] name = "esp-println" version = "0.13.1" @@ -599,7 +640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "960703930f9f3c899ddedd122ea27a09d6a612c22323157e524af5b18876448e" dependencies = [ "critical-section", - "esp-build", + "esp-build 0.2.0", "log", "portable-atomic", ] @@ -615,6 +656,19 @@ dependencies = [ "riscv-rt-macros", ] +[[package]] +name = "esp-storage" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b6502654e5750e8162e66512d7e8d84f7eb51d17ec6aa7e0da95cd102769425" +dependencies = [ + "critical-section", + "document-features", + "embedded-storage", + "esp-build 0.3.0", + "esp-metadata 0.7.0", +] + [[package]] name = "esp-wifi" version = "0.13.0" @@ -631,12 +685,12 @@ dependencies = [ "embedded-io-async", "enumset", "esp-alloc", - "esp-build", + "esp-build 0.2.0", "esp-config", "esp-hal", - "esp-metadata", + "esp-metadata 0.6.0", "esp-wifi-sys", - "heapless", + "heapless 0.8.0", "libm", "log", "num-derive", @@ -758,6 +812,15 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hash32" version = "0.3.1" @@ -773,13 +836,27 @@ version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + [[package]] name = "heapless" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "hash32", + "hash32 0.3.1", "portable-atomic", "stable_deref_trait", ] @@ -894,14 +971,18 @@ dependencies = [ "embassy-time", "embedded-io", "embedded-io-async", + "embedded-storage", "esp-alloc", "esp-hal", "esp-hal-embassy", "esp-println", + "esp-storage", "esp-wifi", - "heapless", + "heapless 0.8.0", "libm", "log", + "postcard", + "serde", "smart-leds", "smoltcp", "static_cell", @@ -1015,6 +1096,17 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "postcard" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c1de96e20f51df24ca73cafcc4690e044854d803259db27a00a461cb3b9d17a" +dependencies = [ + "cobs", + "heapless 0.7.17", + "serde", +] + [[package]] name = "proc-macro-crate" version = "3.3.0" @@ -1150,6 +1242,15 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustversion" version = "1.0.21" @@ -1162,6 +1263,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + [[package]] name = "serde" version = "1.0.219" @@ -1218,10 +1325,19 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "cfg-if", - "heapless", + "heapless 0.8.0", "managed", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1318,6 +1434,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "toml" version = "0.8.23" diff --git a/Cargo.toml b/Cargo.toml index ef58a31..1f5e0cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,10 @@ ws2812-spi = "0.5.0" embassy-futures = "0.1.1" embassy-sync = "0.7.0" libm = "0.2.15" +esp-storage = { version = "0.6.0", features = ["esp32c3"] } +embedded-storage = "0.3.1" +postcard = { version = "1.1.2", features = [] } +serde = { version = "1.0.219", features = ["derive"], default-features = false } [profile.dev] # Rust debug is too slow. diff --git a/partitions.csv b/partitions.csv new file mode 100644 index 0000000..8d9f325 --- /dev/null +++ b/partitions.csv @@ -0,0 +1,8 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, + +# TODO Keep in sync with main.rs APP_DATA_OFFSET +app_store,0x40, 0x01, 0x10000, 0x10000, +factory, app, factory, 0x20000, 1M, diff --git a/src/bin/main.rs b/src/bin/main.rs index f512d9f..61246b3 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,29 +1,28 @@ #![no_std] #![no_main] -use alloc::boxed::Box; -use core::ops::BitXor; -use core::ops::Rem; -use core::pin::Pin; use embassy_executor::Spawner; -use embassy_futures::select::{Either, select}; +use embassy_futures::select::select; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::{Channel, Sender}; use embassy_sync::mutex::Mutex; -use embassy_sync::watch::{self, Watch}; -use embassy_time::{Duration, Instant, Timer, WithTimeout}; +use embassy_time::Timer; +use embedded_storage::nor_flash::NorFlash; +use embedded_storage::nor_flash::ReadNorFlash; +use esp_hal::Blocking; use esp_hal::clock::CpuClock; -use esp_hal::gpio::{DriveMode, Input, InputConfig, Pull}; -use esp_hal::peripherals::GPIO; -use esp_hal::rng; +use esp_hal::gpio::{Input, InputConfig, Pull}; use esp_hal::spi::master::{Config, Spi}; use esp_hal::time::Rate; use esp_hal::timer::systimer::SystemTimer; use esp_hal::timer::timg::TimerGroup; -use esp_hal::{Async, Blocking, DriverMode}; -use libm::sin; +use esp_storage::FlashStorage; use log::info; +use postcard::from_bytes; +use postcard::to_vec; +use serde::Deserialize; +use serde::Serialize; use smart_leds::RGB8; use smart_leds::SmartLedsWrite; use static_cell::StaticCell; @@ -36,17 +35,14 @@ fn panic(_: &core::panic::PanicInfo) -> ! { extern crate alloc; -#[derive(Clone, Debug, PartialEq, Eq)] -struct TargetState { - enabled: [bool; 12], +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +struct State { + pub count: u8, } -impl Default for TargetState { - fn default() -> Self { - TargetState { - enabled: [false; 12], - } - } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] +struct TargetState { + enabled: [bool; 12], } static CHANNEL: StaticCell> = StaticCell::new(); @@ -56,11 +52,12 @@ static STATE: Mutex = Mutex::new(TargetSta const ORDER: [usize; 12] = [5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11]; +//Keep in syn with partitions.csv +const APP_DATA_OFFSET: u32 = 0x10_000; + #[esp_hal_embassy::main] async fn main(spawner: Spawner) { let channel = CHANNEL.init(Channel::new()); - //let state_watch = STATE.init(Arc::new(Mutex::new(TargetState::default()))); - // generator version: 0.3.1 esp_println::logger::init_logger_from_env(); @@ -74,6 +71,21 @@ async fn main(spawner: Spawner) { info!("Embassy initialized!"); + let mut flash = FlashStorage::new(); + info!("Flash: {flash:?}"); + + let mut state = { + let mut bytes = [0; 128]; + flash.read(APP_DATA_OFFSET, &mut bytes[..]).unwrap(); + info!("{bytes:x?}"); + if let Ok(data) = from_bytes::(&bytes[..]) { + info!("Successfully restored data."); + data + } else { + State { count: 0 } + } + }; + let timer1 = TimerGroup::new(peripherals.TIMG0); let _init = esp_wifi::init( timer1.timer0, @@ -107,19 +119,36 @@ async fn main(spawner: Spawner) { .unwrap(); spawner.spawn(render_gems(led_strip)).unwrap(); - let mut state = TargetState::default(); - let mut cnt = 0; loop { - let delta = channel.receive().await; - cnt = (cnt + delta).clamp(0, 12); - - state.enabled = [false; 12]; - for i in (0..12) { - state.enabled[ORDER[i]] = (cnt > i as i32); + // Process State + let mut target_state = TargetState { + enabled: [false; 12], + }; + for i in 0..12 { + target_state.enabled[ORDER[i]] = (state.count > i as u8); } { let mut state_lock = STATE.lock().await; - *state_lock = state.clone(); + *state_lock = target_state.clone(); + } + + //Wait for updates + let delta = channel.receive().await; + state.count = state.count.saturating_add_signed(delta as i8).clamp(0, 12); + + //Write Updated state + let mut d = [10u8; 128]; + postcard::to_slice(&state, d.as_mut_slice()).unwrap(); + info!("{d:x?}"); + let r = flash.erase(APP_DATA_OFFSET, APP_DATA_OFFSET + (4 << 10)); + info!("{r:?}"); + let r = flash.write(APP_DATA_OFFSET, d.as_slice()); + info!("{r:?}"); + + { + let mut bytes = [0; 128]; + flash.read(APP_DATA_OFFSET, &mut bytes[..]).unwrap(); + info!("Write -> Reaa: {bytes:x?}"); } } @@ -161,6 +190,8 @@ async fn render_gems( for i in (0..12) { if target.enabled[i] && !last_state.enabled[i] { temp[i] = 3.0; + } else if !target.enabled[i] && last_state.enabled[i] { + temp[i] = -1.0; } else { let trg = if target.enabled[i] { 1.0 } else { 0.0 }; let speed = ((temp[i] - trg).abs() * 0.2).clamp(0.1, 0.5); @@ -196,6 +227,12 @@ async fn render_gems( g: (50.0 + (255.0 - 50.0) * (temp - 1.0)) as u8, b: (255.0 * (temp - 1.0)) as u8, } + } else if temp < 0.0 { + RGB8 { + r: 0u8, + g: (green_tint * temp.abs()) as u8, + b: (20.0 + (255.0 - 20.0) * (temp.abs())) as u8, + } } else { RGB8 { r: (255.0 * temp) as u8,