A personal rust firmware for the Badger 2040 W

Refactor wip

Changed files
+144 -119
src
+138
src/badge_display/mod.rs
··· 1 + pub mod display_image; 2 + 3 + use core::sync::atomic::{AtomicBool, AtomicU32, AtomicU8}; 4 + use display_image::get_current_image; 5 + use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice; 6 + use embassy_rp::gpio; 7 + use embassy_rp::gpio::Input; 8 + use embassy_time::{Delay, Duration, Timer}; 9 + use embedded_graphics::{ 10 + image::Image, 11 + mono_font::{ascii::*, MonoTextStyle}, 12 + pixelcolor::BinaryColor, 13 + prelude::*, 14 + primitives::{PrimitiveStyle, Rectangle}, 15 + }; 16 + use embedded_text::{ 17 + alignment::HorizontalAlignment, 18 + style::{HeightMode, TextBoxStyleBuilder}, 19 + TextBox, 20 + }; 21 + use gpio::Output; 22 + use heapless::String; 23 + use tinybmp::Bmp; 24 + use uc8151::asynch::Uc8151; 25 + use uc8151::LUT; 26 + use uc8151::WIDTH; 27 + use {defmt_rtt as _, panic_probe as _}; 28 + 29 + use crate::Spi0Bus; 30 + 31 + pub static CURRENT_IMAGE: AtomicU8 = AtomicU8::new(0); 32 + pub static CHANGE_IMAGE: AtomicBool = AtomicBool::new(true); 33 + 34 + static WIFI_COUNT: AtomicU32 = AtomicU32::new(0); 35 + 36 + #[embassy_executor::task] 37 + pub async fn run_the_display( 38 + spi_bus: &'static Spi0Bus, 39 + cs: Output<'static>, 40 + dc: Output<'static>, 41 + busy: Input<'static>, 42 + reset: Output<'static>, 43 + ) { 44 + let spi_dev = SpiDevice::new(&spi_bus, cs); 45 + 46 + let mut display = Uc8151::new(spi_dev, dc, busy, reset, Delay); 47 + 48 + display.reset().await; 49 + 50 + // Initialise display. Using the default LUT speed setting 51 + let _ = display.setup(LUT::Fast).await; 52 + 53 + // Note we're setting the Text color to `Off`. The driver is set up to treat Off as Black so that BMPs work as expected. 54 + let character_style = MonoTextStyle::new(&FONT_9X18_BOLD, BinaryColor::Off); 55 + let textbox_style = TextBoxStyleBuilder::new() 56 + .height_mode(HeightMode::FitToText) 57 + .alignment(HorizontalAlignment::Left) 58 + .paragraph_spacing(6) 59 + .build(); 60 + 61 + // Bounding box for our text. Fill it with the opposite color so we can read the text. 62 + let name_and_detail_bounds = Rectangle::new(Point::new(0, 40), Size::new(WIDTH - 75, 0)); 63 + name_and_detail_bounds 64 + .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)) 65 + .draw(&mut display) 66 + .unwrap(); 67 + 68 + // Create the text box and apply styling options. 69 + 70 + let text = "Bailey Townsend\nSoftware Dev"; 71 + // \nWritten in rust\nRunning on a pico w"; 72 + let name_and_detail_box = 73 + TextBox::with_textbox_style(text, name_and_detail_bounds, character_style, textbox_style); 74 + 75 + // Draw the text box. 76 + name_and_detail_box.draw(&mut display).unwrap(); 77 + 78 + let _ = display.update().await; 79 + 80 + let delay: Duration = Duration::from_secs(30); 81 + let mut text: String<16> = String::<16>::new(); 82 + 83 + loop { 84 + let count = WIFI_COUNT.load(core::sync::atomic::Ordering::Relaxed); 85 + // let _ = core::fmt::write(&mut text, format_args!("Count: {}", count)); 86 + // let count_bounds = Rectangle::new(Point::new(0, 0), Size::new(WIDTH, 24)); 87 + // count_bounds 88 + // .into_styled( 89 + // PrimitiveStyleBuilder::default() 90 + // .stroke_color(BinaryColor::Off) 91 + // .fill_color(BinaryColor::On) 92 + // .stroke_width(1) 93 + // .build(), 94 + // ) 95 + // .draw(&mut display) 96 + // .unwrap(); 97 + 98 + // Text::new(text.as_str(), Point::new(8, 16), character_style) 99 + // .draw(&mut display) 100 + // .unwrap(); 101 + 102 + // // // Draw the text box. 103 + // let result = display 104 + // .partial_update(count_bounds.try_into().unwrap()) 105 + // .await; 106 + // match result { 107 + // Ok(_) => {} 108 + // Err(_) => { 109 + // info!("Error updating display"); 110 + // } 111 + // } 112 + // text.clear(); 113 + // let _ = display.clear(Rgb565::WHITE.into()); 114 + // let _ = display.update().await; 115 + WIFI_COUNT.store(count + 1, core::sync::atomic::Ordering::Relaxed); 116 + 117 + if CHANGE_IMAGE.load(core::sync::atomic::Ordering::Relaxed) { 118 + let current_image = get_current_image(); 119 + let tga: Bmp<BinaryColor> = Bmp::from_slice(&current_image.image()).unwrap(); 120 + let image = Image::new(&tga, current_image.image_location()); 121 + //clear image location by writing a white rectangle over previous image location 122 + let clear_bounds = Rectangle::new( 123 + current_image.previous().image_location(), 124 + Size::new(157, 101), 125 + ); 126 + clear_bounds 127 + .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)) 128 + .draw(&mut display) 129 + .unwrap(); 130 + 131 + let _ = image.draw(&mut display); 132 + let _ = display.update().await; 133 + CHANGE_IMAGE.store(false, core::sync::atomic::Ordering::Relaxed); 134 + } 135 + 136 + Timer::after(Duration::from_millis(500)).await; 137 + } 138 + }
+3 -4
src/image_handler.rs src/badge_display/display_image.rs
··· 2 2 3 3 use embedded_graphics::prelude::Point; 4 4 5 - pub static CURRENT_IMAGE: AtomicU8 = AtomicU8::new(0); 6 - pub static CHANGE_IMAGE: AtomicBool = AtomicBool::new(true); 5 + use super::CURRENT_IMAGE; 7 6 8 7 static NUMBER_OF_IMAGES: u8 = 2; 9 - static FERRIS_IMG: &[u8; 15722] = include_bytes!("../images/ferris_w_a_knife.bmp"); 10 - static REPO_IMG: &[u8; 11262] = include_bytes!("../images/repo.bmp"); 8 + static FERRIS_IMG: &[u8; 15722] = include_bytes!("../../images/ferris_w_a_knife.bmp"); 9 + static REPO_IMG: &[u8; 11262] = include_bytes!("../../images/repo.bmp"); 11 10 12 11 pub enum DisplayImage { 13 12 Ferris = 0,
+3 -115
src/main.rs
··· 4 4 5 5 #![no_std] 6 6 #![no_main] 7 - use core::sync::atomic::AtomicU32; 7 + use badge_display::display_image::DisplayImage; 8 + use badge_display::{run_the_display, CHANGE_IMAGE, CURRENT_IMAGE}; 8 9 use defmt::info; 9 - use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice; 10 10 use embassy_executor::Spawner; 11 11 use embassy_rp::gpio; 12 12 use embassy_rp::gpio::Input; ··· 29 29 TextBox, 30 30 }; 31 31 use gpio::{Level, Output, Pull}; 32 - use heapless::String; 33 - use image_handler::{get_current_image, DisplayImage, CHANGE_IMAGE, CURRENT_IMAGE}; 34 32 use static_cell::StaticCell; 35 - use tinybmp::Bmp; 36 - use uc8151::asynch::Uc8151; 37 - use uc8151::LUT; 38 - use uc8151::WIDTH; 39 33 use {defmt_rtt as _, panic_probe as _}; 40 34 35 + mod badge_display; 41 36 mod cyw43_driver; 42 - mod image_handler; 43 37 44 38 type Spi0Bus = Mutex<NoopRawMutex, Spi<'static, SPI0, spi::Async>>; 45 - 46 - static WIFI_COUNT: AtomicU32 = AtomicU32::new(0); 47 39 48 40 #[embassy_executor::main] 49 41 async fn main(spawner: Spawner) { ··· 111 103 Timer::after(Duration::from_millis(100)).await; 112 104 } 113 105 } 114 - 115 - #[embassy_executor::task] 116 - async fn run_the_display( 117 - spi_bus: &'static Spi0Bus, 118 - cs: Output<'static>, 119 - dc: Output<'static>, 120 - busy: Input<'static>, 121 - reset: Output<'static>, 122 - ) { 123 - let spi_dev = SpiDevice::new(&spi_bus, cs); 124 - 125 - let mut display = Uc8151::new(spi_dev, dc, busy, reset, Delay); 126 - 127 - display.reset().await; 128 - 129 - // Initialise display. Using the default LUT speed setting 130 - let _ = display.setup(LUT::Fast).await; 131 - 132 - // Note we're setting the Text color to `Off`. The driver is set up to treat Off as Black so that BMPs work as expected. 133 - let character_style = MonoTextStyle::new(&FONT_9X18_BOLD, BinaryColor::Off); 134 - let textbox_style = TextBoxStyleBuilder::new() 135 - .height_mode(HeightMode::FitToText) 136 - .alignment(HorizontalAlignment::Left) 137 - .paragraph_spacing(6) 138 - .build(); 139 - 140 - // Bounding box for our text. Fill it with the opposite color so we can read the text. 141 - let name_and_detail_bounds = Rectangle::new(Point::new(0, 40), Size::new(WIDTH - 75, 0)); 142 - name_and_detail_bounds 143 - .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)) 144 - .draw(&mut display) 145 - .unwrap(); 146 - 147 - // Create the text box and apply styling options. 148 - 149 - let text = "Bailey Townsend\nSoftware Dev"; 150 - // \nWritten in rust\nRunning on a pico w"; 151 - let name_and_detail_box = 152 - TextBox::with_textbox_style(text, name_and_detail_bounds, character_style, textbox_style); 153 - 154 - // Draw the text box. 155 - name_and_detail_box.draw(&mut display).unwrap(); 156 - 157 - let _ = display.update().await; 158 - 159 - let delay: Duration = Duration::from_secs(30); 160 - let mut text: String<16> = String::<16>::new(); 161 - 162 - loop { 163 - let count = WIFI_COUNT.load(core::sync::atomic::Ordering::Relaxed); 164 - // let _ = core::fmt::write(&mut text, format_args!("Count: {}", count)); 165 - // let count_bounds = Rectangle::new(Point::new(0, 0), Size::new(WIDTH, 24)); 166 - // count_bounds 167 - // .into_styled( 168 - // PrimitiveStyleBuilder::default() 169 - // .stroke_color(BinaryColor::Off) 170 - // .fill_color(BinaryColor::On) 171 - // .stroke_width(1) 172 - // .build(), 173 - // ) 174 - // .draw(&mut display) 175 - // .unwrap(); 176 - 177 - // Text::new(text.as_str(), Point::new(8, 16), character_style) 178 - // .draw(&mut display) 179 - // .unwrap(); 180 - 181 - // // // Draw the text box. 182 - // let result = display 183 - // .partial_update(count_bounds.try_into().unwrap()) 184 - // .await; 185 - // match result { 186 - // Ok(_) => {} 187 - // Err(_) => { 188 - // info!("Error updating display"); 189 - // } 190 - // } 191 - // text.clear(); 192 - // let _ = display.clear(Rgb565::WHITE.into()); 193 - // let _ = display.update().await; 194 - WIFI_COUNT.store(count + 1, core::sync::atomic::Ordering::Relaxed); 195 - 196 - if CHANGE_IMAGE.load(core::sync::atomic::Ordering::Relaxed) { 197 - let current_image = get_current_image(); 198 - let tga: Bmp<BinaryColor> = Bmp::from_slice(&current_image.image()).unwrap(); 199 - let image = Image::new(&tga, current_image.image_location()); 200 - //clear image location by writing a white rectangle over previous image location 201 - let clear_bounds = Rectangle::new( 202 - current_image.previous().image_location(), 203 - Size::new(157, 91), 204 - ); 205 - clear_bounds 206 - .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)) 207 - .draw(&mut display) 208 - .unwrap(); 209 - 210 - let _ = image.draw(&mut display); 211 - let _ = display.update().await; 212 - CHANGE_IMAGE.store(false, core::sync::atomic::Ordering::Relaxed); 213 - } 214 - 215 - Timer::after(Duration::from_millis(500)).await; 216 - } 217 - }