A personal rust firmware for the Badger 2040 W

Good enough

+66 -35
+59 -27
src/main.rs
··· 10 use core::cell::RefCell; 11 use core::fmt::Write; 12 use core::str::from_utf8; 13 - use cortex_m::asm::delay; 14 use cyw43::JoinOptions; 15 use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; 16 use defmt::info; 17 use defmt::*; 18 - use embassy_embedded_hal::shared_bus::I2cDeviceError; 19 use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; 20 use embassy_executor::Spawner; 21 use embassy_net::StackResources; ··· 24 use embassy_rp::clocks::RoscRng; 25 use embassy_rp::flash::Async; 26 use embassy_rp::gpio::Input; 27 - use embassy_rp::i2c::{Error, I2c}; 28 use embassy_rp::peripherals::{DMA_CH0, I2C0, PIO0, SPI0}; 29 use embassy_rp::pio::{InterruptHandler, Pio}; 30 use embassy_rp::rtc::{DateTime, DayOfWeek}; ··· 126 let btn_c = Input::new(p.PIN_14, Pull::Down); 127 let rtc_alarm = Input::new(p.PIN_8, Pull::Down); 128 129 let spi = Spi::new( 130 p.SPI0, 131 clk, ··· 158 seed, 159 ); 160 161 - //rtc setup 162 - // let mut rtc = embassy_rp::rtc::Rtc::new(p.RTC); 163 - 164 spawner.must_spawn(net_task(runner)); 165 //Attempt to connect to wifi to get RTC time loop for 2 minutes 166 let mut wifi_connection_attempts = 0; ··· 185 Timer::after(Duration::from_secs(1)).await; 186 wifi_connection_attempts += 1; 187 } 188 - 189 - //Setup i2c bus 190 - let config = embassy_rp::i2c::Config::default(); 191 - let i2c = i2c::I2c::new_blocking(p.I2C0, p.PIN_5, p.PIN_4, config); 192 - static I2C_BUS: StaticCell<I2c0Bus> = StaticCell::new(); 193 - let i2c_bus = NoopMutex::new(RefCell::new(i2c)); 194 - let i2c_bus = I2C_BUS.init(i2c_bus); 195 - 196 - let i2c_dev = I2cDevice::new(i2c_bus); 197 - let mut rtc_device = PCF85063::new(i2c_dev); 198 199 if connected_to_wifi { 200 info!("waiting for DHCP..."); ··· 329 let cycle = Duration::from_millis(100); 330 let mut current_cycle = 0; 331 let mut time_to_scan = true; 332 - //15 minutes(ish) idk it's late and my math is so bad rn 333 - let reset_cycle = 9_000; 334 335 //Turn off led to signify that the badge is ready 336 user_led.set_low(); 337 338 //RTC alarm stuff 339 - // info!("going to sleep"); 340 - // Timer::after(Duration::from_millis(5_000)).await; 341 - // //Set the rtc and sleep for 15 minutes 342 - // //goes to sleep for 15 mins 343 - // _ = rtc_device.clear_alarm_flag(); 344 - // _ = rtc_device.set_alarm_minutes(5); 345 - // _ = rtc_device.control_alarm_minutes(Control::On); 346 - // _ = rtc_device.control_alarm_interrupt(Control::On); 347 - // power.set_low(); 348 349 loop { 350 //Change Image Button 351 if btn_c.is_high() { 352 info!("Button C pressed"); 353 let current_image = CURRENT_IMAGE.load(core::sync::atomic::Ordering::Relaxed); 354 let new_image = DisplayImage::from_u8(current_image).unwrap().next(); 355 CURRENT_IMAGE.store(new_image.as_u8(), core::sync::atomic::Ordering::Relaxed); ··· 361 if btn_a.is_high() { 362 println!("{:?}", current_cycle); 363 info!("Button A pressed"); 364 user_led.toggle(); 365 Timer::after(Duration::from_millis(500)).await; 366 continue; ··· 368 369 if btn_down.is_high() { 370 info!("Button Down pressed"); 371 SCREEN_TO_SHOW.lock(|screen| { 372 screen.replace(Screen::WifiList); 373 }); ··· 378 379 if btn_up.is_high() { 380 info!("Button Up pressed"); 381 SCREEN_TO_SHOW.lock(|screen| { 382 screen.replace(Screen::Badge); 383 }); ··· 388 389 if btn_b.is_high() { 390 info!("Button B pressed"); 391 SCREEN_TO_SHOW.lock(|screen| { 392 if *screen.borrow() == Screen::Badge { 393 //IF on badge screen and b pressed reset wifi count ··· 447 448 if time_to_scan { 449 info!("Scanning for wifi networks"); 450 time_to_scan = false; 451 let mut scanner = control.scan(Default::default()).await; 452 while let Some(bss) = scanner.next().await { ··· 460 current_cycle = 0; 461 time_to_scan = true; 462 } 463 current_cycle += 1; 464 Timer::after(cycle).await; 465 }
··· 10 use core::cell::RefCell; 11 use core::fmt::Write; 12 use core::str::from_utf8; 13 use cyw43::JoinOptions; 14 use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; 15 use defmt::info; 16 use defmt::*; 17 use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; 18 use embassy_executor::Spawner; 19 use embassy_net::StackResources; ··· 22 use embassy_rp::clocks::RoscRng; 23 use embassy_rp::flash::Async; 24 use embassy_rp::gpio::Input; 25 + use embassy_rp::i2c::I2c; 26 use embassy_rp::peripherals::{DMA_CH0, I2C0, PIO0, SPI0}; 27 use embassy_rp::pio::{InterruptHandler, Pio}; 28 use embassy_rp::rtc::{DateTime, DayOfWeek}; ··· 124 let btn_c = Input::new(p.PIN_14, Pull::Down); 125 let rtc_alarm = Input::new(p.PIN_8, Pull::Down); 126 127 + //Setup i2c bus 128 + let config = embassy_rp::i2c::Config::default(); 129 + let i2c = i2c::I2c::new_blocking(p.I2C0, p.PIN_5, p.PIN_4, config); 130 + static I2C_BUS: StaticCell<I2c0Bus> = StaticCell::new(); 131 + let i2c_bus = NoopMutex::new(RefCell::new(i2c)); 132 + let i2c_bus = I2C_BUS.init(i2c_bus); 133 + 134 + let i2c_dev = I2cDevice::new(i2c_bus); 135 + let mut rtc_device = PCF85063::new(i2c_dev); 136 + 137 + if btn_a.is_high() { 138 + //Clears the alarm on start if A button is pressed (manual start) 139 + _ = rtc_device.disable_all_alarms(); 140 + _ = rtc_device.clear_alarm_flag(); 141 + } 142 + 143 let spi = Spi::new( 144 p.SPI0, 145 clk, ··· 172 seed, 173 ); 174 175 spawner.must_spawn(net_task(runner)); 176 //Attempt to connect to wifi to get RTC time loop for 2 minutes 177 let mut wifi_connection_attempts = 0; ··· 196 Timer::after(Duration::from_secs(1)).await; 197 wifi_connection_attempts += 1; 198 } 199 200 if connected_to_wifi { 201 info!("waiting for DHCP..."); ··· 330 let cycle = Duration::from_millis(100); 331 let mut current_cycle = 0; 332 let mut time_to_scan = true; 333 + //5 minutes(ish) idk it's late and my math is so bad rn 334 + let reset_cycle = 3_000; 335 336 //Turn off led to signify that the badge is ready 337 user_led.set_low(); 338 339 //RTC alarm stuff 340 + let mut go_to_sleep = false; 341 + let mut reset_cycles_till_sleep = 0; 342 + //Like 15ish mins?? 343 + let sleep_after_cycles = 4; 344 + 345 + if rtc_alarm.is_high() { 346 + //sleep happened 347 + go_to_sleep = true; 348 + info!("Alarm went off"); 349 + _ = rtc_device.disable_all_alarms(); 350 + _ = rtc_device.clear_alarm_flag(); 351 + } else { 352 + info!("Alarm was clear") 353 + } 354 355 loop { 356 //Change Image Button 357 if btn_c.is_high() { 358 info!("Button C pressed"); 359 + reset_cycles_till_sleep = 0; 360 let current_image = CURRENT_IMAGE.load(core::sync::atomic::Ordering::Relaxed); 361 let new_image = DisplayImage::from_u8(current_image).unwrap().next(); 362 CURRENT_IMAGE.store(new_image.as_u8(), core::sync::atomic::Ordering::Relaxed); ··· 368 if btn_a.is_high() { 369 println!("{:?}", current_cycle); 370 info!("Button A pressed"); 371 + reset_cycles_till_sleep = 0; 372 user_led.toggle(); 373 Timer::after(Duration::from_millis(500)).await; 374 continue; ··· 376 377 if btn_down.is_high() { 378 info!("Button Down pressed"); 379 + reset_cycles_till_sleep = 0; 380 SCREEN_TO_SHOW.lock(|screen| { 381 screen.replace(Screen::WifiList); 382 }); ··· 387 388 if btn_up.is_high() { 389 info!("Button Up pressed"); 390 + reset_cycles_till_sleep = 0; 391 SCREEN_TO_SHOW.lock(|screen| { 392 screen.replace(Screen::Badge); 393 }); ··· 398 399 if btn_b.is_high() { 400 info!("Button B pressed"); 401 + reset_cycles_till_sleep = 0; 402 SCREEN_TO_SHOW.lock(|screen| { 403 if *screen.borrow() == Screen::Badge { 404 //IF on badge screen and b pressed reset wifi count ··· 458 459 if time_to_scan { 460 info!("Scanning for wifi networks"); 461 + reset_cycles_till_sleep += 1; 462 time_to_scan = false; 463 let mut scanner = control.scan(Default::default()).await; 464 while let Some(bss) = scanner.next().await { ··· 472 current_cycle = 0; 473 time_to_scan = true; 474 } 475 + 476 + if reset_cycles_till_sleep >= sleep_after_cycles { 477 + info!("Going to sleep"); 478 + reset_cycles_till_sleep = 0; 479 + go_to_sleep = true; 480 + } 481 + 482 + if go_to_sleep { 483 + info!("going to sleep"); 484 + Timer::after(Duration::from_secs(25)).await; 485 + //Set the rtc and sleep for 15 minutes 486 + //goes to sleep for 15 mins 487 + _ = rtc_device.disable_all_alarms(); 488 + _ = rtc_device.clear_alarm_flag(); 489 + _ = rtc_device.set_alarm_seconds(5); 490 + _ = rtc_device.control_alarm_seconds(Control::On); 491 + _ = rtc_device.control_alarm_interrupt(Control::On); 492 + power.set_low(); 493 + } 494 + 495 current_cycle += 1; 496 Timer::after(cycle).await; 497 }
+7 -8
src/pcf85063a/mod.rs
··· 1 #![allow(dead_code)] 2 pub mod alarm; 3 pub mod datetime; 4 5 use embedded_hal_1::i2c::I2c; 6 7 /// All possible errors in this crate 8 - #[derive(Debug)] 9 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 10 pub enum Error<E> { 11 /// I2C bus error 12 I2C(E), ··· 80 81 /// Two possible choices, used for various enable/disable bit flags 82 #[allow(non_camel_case_types)] 83 - #[derive(Copy, Clone, Debug)] 84 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 85 pub enum Control { 86 /// Enable some feature, eg. timer 87 On, ··· 90 } 91 92 /// PCF8563 driver 93 - #[derive(Debug, Default)] 94 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 95 pub struct PCF85063<I2C> { 96 /// The concrete I2C device implementation. 97 i2c: I2C, ··· 193 } 194 } 195 196 - #[derive(Debug, Clone, Copy, PartialEq, Eq)] 197 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 198 #[repr(u8)] 199 pub enum OutputFrequency { 200 Hz32768 = 0b000,
··· 1 #![allow(dead_code)] 2 + 3 + ///None of this code is mine. It's https://crates.io/crates/pcf85063a 4 + /// I just needed a synchronous version so did a local clone and pulled the async and awaits 5 pub mod alarm; 6 pub mod datetime; 7 8 use embedded_hal_1::i2c::I2c; 9 10 /// All possible errors in this crate 11 + #[derive(Debug, defmt::Format)] 12 pub enum Error<E> { 13 /// I2C bus error 14 I2C(E), ··· 82 83 /// Two possible choices, used for various enable/disable bit flags 84 #[allow(non_camel_case_types)] 85 + #[derive(Copy, Clone, Debug, defmt::Format)] 86 pub enum Control { 87 /// Enable some feature, eg. timer 88 On, ··· 91 } 92 93 /// PCF8563 driver 94 + #[derive(Debug, Default, defmt::Format)] 95 pub struct PCF85063<I2C> { 96 /// The concrete I2C device implementation. 97 i2c: I2C, ··· 193 } 194 } 195 196 + #[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] 197 #[repr(u8)] 198 pub enum OutputFrequency { 199 Hz32768 = 0b000,