diff --git a/Cargo.lock b/Cargo.lock index 53418ee..286e5ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -775,9 +775,9 @@ dependencies = [ [[package]] name = "hsmc" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497ed9593e4baf6ef120b24aff80cb898f6832d32cdf01be9d90be0c06624e77" +checksum = "18bb06fda289e60e17bc7483a222fc6d9d6865b92648f836242b7a79115cc91d" dependencies = [ "defmt 0.3.100", "embassy-futures", @@ -789,9 +789,9 @@ dependencies = [ [[package]] name = "hsmc-macros" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d0b1413ed69ba168f9d0edbf4a8ea21569eaf352edf4e11335ae3d765ba004" +checksum = "289a7c9f1b677168229c8ad4e992380c3951d0908b52b1d2bfae8ff3c980c35d" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 30735f2..782092f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ embassy-rp = { version = "0.10.0", features = ["rp2040", "time-driver", "c embassy-sync = "0.8" embassy-futures = "0.1" embassy-usb = "0.6.0" -hsmc = { version = "0.5.1", default-features = false } +hsmc = { version = "0.6.0", default-features = false } usbd-hid = "0.10.0" smart-leds = "0.4" libm = "0.2" diff --git a/src/main.rs b/src/main.rs index 097b903..6925e39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -73,6 +73,13 @@ const YELLOW_PERIOD: EDuration = EDuration::from_secs(3); const RED_PERIOD: EDuration = EDuration::from_secs(2); const FAST_RED_PERIOD: EDuration = EDuration::from_millis(500); +// Wake-up LED feedback periods. Blue on WakingHost (kbd+mouse), white on +// Settling, then a linear white→green fade across the Spinning duration so +// the LED hands off cleanly to Active's green breathing. +const WAKING_PULSE_PERIOD: EDuration = EDuration::from_millis(800); +const SETTLING_PULSE_PERIOD: EDuration = EDuration::from_millis(1200); +const SPINNER_FADE_DURATION: EDuration = EDuration::from_millis(600); + // LED brightness (raw WS2812 PWM, 0..=255). const BREATHE_FLOOR: u8 = 1; const BREATHE_PEAK: u8 = 16; @@ -214,6 +221,7 @@ Jiggly { // its own internal deadline; the chart timer is what advances the // chart. No durings, no events — purely entry + timer. state WakingHost { + during: pulse_blue(neo); default(WakingWithKeyboard); state WakingWithKeyboard { @@ -230,11 +238,13 @@ Jiggly { // Quiet pause so the display has time to come out of sleep before the // cursor starts drawing the spinner. state Settling { + during: pulse_white(neo); on(after SETTLING_DELAY) => Spinning; } state Spinning { during: animate_spinner(mouse); + during: fade_to_green(neo); on(SpinDone) => Active; } @@ -542,6 +552,37 @@ async fn blink_fast_red(neo: &mut Neo) -> Ev { } } +async fn pulse_blue(neo: &mut Neo) -> Ev { + let start = Instant::now(); + loop { + let level = sin_breath(WAKING_PULSE_PERIOD, start.elapsed(), BREATHE_FLOOR, BREATHE_PEAK); + paint(neo, 0, 0, level).await; + Timer::after(LED_TICK).await; + } +} + +async fn pulse_white(neo: &mut Neo) -> Ev { + let start = Instant::now(); + loop { + let level = sin_breath(SETTLING_PULSE_PERIOD, start.elapsed(), BREATHE_FLOOR, BREATHE_PEAK); + paint(neo, level, level, level).await; + Timer::after(LED_TICK).await; + } +} + +// Linear fade from white(peak) → green(peak) so the LED hands off into +// Active's green breathing without a visible jump. +async fn fade_to_green(neo: &mut Neo) -> Ev { + let start = Instant::now(); + let total_ms = SPINNER_FADE_DURATION.as_millis() as f32; + loop { + let t = ((start.elapsed().as_millis() as f32) / total_ms).min(1.0); + let rb = (BREATHE_PEAK as f32 * (1.0 - t)) as u8; + paint(neo, rb, BREATHE_PEAK, rb).await; + Timer::after(LED_TICK).await; + } +} + // ── Color / breathing helpers ────────────────────────────────────── fn run_before_shutdown_e() -> EDuration {