A personal rust firmware for the Badger 2040 W

Compare changes

Choose any two refs to compare.

Changed files
+87 -37
src
pcf85063a
+80 -29
src/main.rs
··· 1 1 #![no_std] 2 2 #![no_main] 3 3 4 - use crate::pcf85063a::Control; 4 + use crate::pcf85063a::{Control, Error}; 5 5 use badge_display::display_image::DisplayImage; 6 6 use badge_display::{ 7 7 CHANGE_IMAGE, CURRENT_IMAGE, DISPLAY_CHANGED, FORCE_SCREEN_REFRESH, RECENT_WIFI_NETWORKS, ··· 10 10 use core::cell::RefCell; 11 11 use core::fmt::Write; 12 12 use core::str::from_utf8; 13 - use cortex_m::asm::delay; 14 13 use cyw43::JoinOptions; 15 14 use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; 16 15 use defmt::info; ··· 24 23 use embassy_rp::clocks::RoscRng; 25 24 use embassy_rp::flash::Async; 26 25 use embassy_rp::gpio::Input; 27 - use embassy_rp::i2c::{Error, I2c}; 26 + use embassy_rp::i2c::I2c; 28 27 use embassy_rp::peripherals::{DMA_CH0, I2C0, PIO0, SPI0}; 29 28 use embassy_rp::pio::{InterruptHandler, Pio}; 30 29 use embassy_rp::rtc::{DateTime, DayOfWeek}; 31 30 use embassy_rp::spi::Spi; 32 31 use embassy_rp::spi::{self}; 32 + use embassy_rp::watchdog::Watchdog; 33 33 use embassy_rp::{bind_interrupts, gpio, i2c}; 34 34 use embassy_sync::blocking_mutex::NoopMutex; 35 35 use embassy_sync::blocking_mutex::raw::NoopRawMutex; ··· 125 125 let btn_b = Input::new(p.PIN_13, Pull::Down); 126 126 let btn_c = Input::new(p.PIN_14, Pull::Down); 127 127 let rtc_alarm = Input::new(p.PIN_8, Pull::Down); 128 + let mut watchdog = Watchdog::new(p.WATCHDOG); 129 + 130 + //Setup i2c bus 131 + let config = embassy_rp::i2c::Config::default(); 132 + let i2c = i2c::I2c::new_blocking(p.I2C0, p.PIN_5, p.PIN_4, config); 133 + static I2C_BUS: StaticCell<I2c0Bus> = StaticCell::new(); 134 + let i2c_bus = NoopMutex::new(RefCell::new(i2c)); 135 + let i2c_bus = I2C_BUS.init(i2c_bus); 136 + 137 + let i2c_dev = I2cDevice::new(i2c_bus); 138 + let mut rtc_device = PCF85063::new(i2c_dev); 139 + 140 + if btn_a.is_high() { 141 + //Clears the alarm on start if A button is pressed (manual start) 142 + _ = rtc_device.disable_all_alarms(); 143 + _ = rtc_device.clear_alarm_flag(); 144 + } 145 + 146 + // //RTC alarm stuff 147 + // let mut go_to_sleep = false; 148 + // let mut reset_cycles_till_sleep = 0; 149 + // //Like 15ish mins?? 150 + // let sleep_after_cycles = 2; 151 + // 152 + // if rtc_alarm.is_high() { 153 + // //sleep happened 154 + // go_to_sleep = true; 155 + // info!("Alarm went off"); 156 + // _ = rtc_device.disable_all_alarms(); 157 + // _ = rtc_device.clear_alarm_flag(); 158 + // } else { 159 + // info!("Alarm was clear") 160 + // } 128 161 129 162 let spi = Spi::new( 130 163 p.SPI0, ··· 158 191 seed, 159 192 ); 160 193 161 - //rtc setup 162 - // let mut rtc = embassy_rp::rtc::Rtc::new(p.RTC); 194 + //If the watch dog isn't fed in 8 seconds reboot to help with hang up 195 + watchdog.start(Duration::from_secs(8)); 163 196 164 197 spawner.must_spawn(net_task(runner)); 165 198 //Attempt to connect to wifi to get RTC time loop for 2 minutes ··· 169 202 let wifi_ssid = env_value("WIFI_SSID"); 170 203 let wifi_password = env_value("WIFI_PASSWORD"); 171 204 while wifi_connection_attempts < 30 { 205 + watchdog.feed(); 172 206 match control 173 207 .join(wifi_ssid, JoinOptions::new(wifi_password.as_bytes())) 174 208 .await ··· 186 220 wifi_connection_attempts += 1; 187 221 } 188 222 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 223 if connected_to_wifi { 224 + //Feed the dog if it makes it this far 225 + watchdog.feed(); 200 226 info!("waiting for DHCP..."); 201 227 while !stack.is_config_up() { 202 228 Timer::after_millis(100).await; ··· 233 259 234 260 let url = env_value("TIME_API"); 235 261 info!("connecting to {}", &url); 262 + 263 + // Feeds the dog again for one last time 264 + watchdog.feed(); 236 265 237 266 //If the call goes through set the rtc 238 267 match http_client.request(Method::GET, &url).await { ··· 329 358 let cycle = Duration::from_millis(100); 330 359 let mut current_cycle = 0; 331 360 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; 361 + //5 minutes(ish) idk it's late and my math is so bad rn 362 + let reset_cycle = 3_000; 334 363 335 364 //Turn off led to signify that the badge is ready 336 - user_led.set_low(); 365 + // user_led.set_low(); 337 366 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(); 367 + loop { 368 + //Keep feeding the dog 369 + watchdog.feed(); 348 370 349 - loop { 350 371 //Change Image Button 351 372 if btn_c.is_high() { 352 373 info!("Button C pressed"); 374 + // reset_cycles_till_sleep = 0; 353 375 let current_image = CURRENT_IMAGE.load(core::sync::atomic::Ordering::Relaxed); 354 376 let new_image = DisplayImage::from_u8(current_image).unwrap().next(); 355 377 CURRENT_IMAGE.store(new_image.as_u8(), core::sync::atomic::Ordering::Relaxed); ··· 361 383 if btn_a.is_high() { 362 384 println!("{:?}", current_cycle); 363 385 info!("Button A pressed"); 386 + // reset_cycles_till_sleep = 0; 364 387 user_led.toggle(); 365 388 Timer::after(Duration::from_millis(500)).await; 366 389 continue; ··· 368 391 369 392 if btn_down.is_high() { 370 393 info!("Button Down pressed"); 394 + // reset_cycles_till_sleep = 0; 371 395 SCREEN_TO_SHOW.lock(|screen| { 372 396 screen.replace(Screen::WifiList); 373 397 }); ··· 378 402 379 403 if btn_up.is_high() { 380 404 info!("Button Up pressed"); 405 + // reset_cycles_till_sleep = 0; 381 406 SCREEN_TO_SHOW.lock(|screen| { 382 407 screen.replace(Screen::Badge); 383 408 }); ··· 388 413 389 414 if btn_b.is_high() { 390 415 info!("Button B pressed"); 416 + // reset_cycles_till_sleep = 0; 391 417 SCREEN_TO_SHOW.lock(|screen| { 392 418 if *screen.borrow() == Screen::Badge { 393 419 //IF on badge screen and b pressed reset wifi count ··· 447 473 448 474 if time_to_scan { 449 475 info!("Scanning for wifi networks"); 476 + // reset_cycles_till_sleep += 1; 450 477 time_to_scan = false; 451 478 let mut scanner = control.scan(Default::default()).await; 452 479 while let Some(bss) = scanner.next().await { ··· 460 487 current_cycle = 0; 461 488 time_to_scan = true; 462 489 } 490 + 491 + // if reset_cycles_till_sleep >= sleep_after_cycles { 492 + // info!("Going to sleep"); 493 + // reset_cycles_till_sleep = 0; 494 + // go_to_sleep = true; 495 + // } 496 + // 497 + // if go_to_sleep { 498 + // info!("going to sleep"); 499 + // //SO i need to wait for 25 seconds to make sure the display updates fully...But i need to keep feeding the dog atleast every 8 seconds 500 + // for _ in 0..25 { 501 + // //watchdog.feed(); 502 + // Timer::after(Duration::from_secs(1)).await; 503 + // } 504 + // //Set the rtc and sleep for 15 minutes 505 + // //goes to sleep for 15 mins 506 + // _ = rtc_device.disable_all_alarms(); 507 + // _ = rtc_device.clear_alarm_flag(); 508 + // _ = rtc_device.set_alarm_minutes(5); 509 + // _ = rtc_device.control_alarm_minutes(Control::On); 510 + // _ = rtc_device.control_alarm_interrupt(Control::On); 511 + // power.set_low(); 512 + // } 513 + 463 514 current_cycle += 1; 464 515 Timer::after(cycle).await; 465 516 }
+7 -8
src/pcf85063a/mod.rs
··· 1 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 2 5 pub mod alarm; 3 6 pub mod datetime; 4 7 5 8 use embedded_hal_1::i2c::I2c; 6 9 7 10 /// All possible errors in this crate 8 - #[derive(Debug)] 9 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 11 + #[derive(Debug, defmt::Format)] 10 12 pub enum Error<E> { 11 13 /// I2C bus error 12 14 I2C(E), ··· 80 82 81 83 /// Two possible choices, used for various enable/disable bit flags 82 84 #[allow(non_camel_case_types)] 83 - #[derive(Copy, Clone, Debug)] 84 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 85 + #[derive(Copy, Clone, Debug, defmt::Format)] 85 86 pub enum Control { 86 87 /// Enable some feature, eg. timer 87 88 On, ··· 90 91 } 91 92 92 93 /// PCF8563 driver 93 - #[derive(Debug, Default)] 94 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 94 + #[derive(Debug, Default, defmt::Format)] 95 95 pub struct PCF85063<I2C> { 96 96 /// The concrete I2C device implementation. 97 97 i2c: I2C, ··· 193 193 } 194 194 } 195 195 196 - #[derive(Debug, Clone, Copy, PartialEq, Eq)] 197 - #[cfg_attr(feature = "defmt", derive(defmt::Format))] 196 + #[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] 198 197 #[repr(u8)] 199 198 pub enum OutputFrequency { 200 199 Hz32768 = 0b000,