A personal rust firmware for the Badger 2040 W

Working partial updates

+1
Cargo.toml
··· 108 108 debug = 2 109 109 110 110 [profile.dev] 111 + debug = 1 111 112 lto = true 112 113 opt-level = "z" 113 114
cyw43-firmware/43439A0.bin

This is a binary file and will not be displayed.

cyw43-firmware/43439A0_btfw.bin

This is a binary file and will not be displayed.

cyw43-firmware/43439A0_clm.bin

This is a binary file and will not be displayed.

+15 -10
src/control_driver.rs
··· 2 2 use cyw43_pio::PioSpi; 3 3 use defmt::unwrap; 4 4 use embassy_executor::Spawner; 5 + use embassy_net_wiznet::Device; 5 6 use embassy_rp::bind_interrupts; 6 7 use embassy_rp::gpio::{Level, Output}; 7 8 use embassy_rp::peripherals::{DMA_CH0, PIO0}; ··· 14 15 }); 15 16 16 17 #[embassy_executor::task] 17 - async fn wifi_task( 18 + async fn cyw43_task( 18 19 runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>, 19 20 ) -> ! { 20 21 runner.run().await 21 22 } 22 23 23 - pub async fn setup_control<'a>( 24 + pub async fn setup_cyw43<'a>( 24 25 pio0: PIO0, 25 26 p_23: PIN_23, 26 27 p_24: PIN_24, ··· 28 29 p_29: PIN_29, 29 30 dma_ch0: DMA_CH0, 30 31 spawner: Spawner, 31 - ) -> Control<'a> { 32 - let fw = include_bytes!("../cyw43-firmware/43439A0.bin"); 33 - let clm = include_bytes!("../cyw43-firmware/43439A0_clm.bin"); 32 + ) -> (Device<'a>, Control<'a>) { 33 + // let fw = include_bytes!("../cyw43-firmware/43439A0.bin"); 34 + // let clm = include_bytes!("../cyw43-firmware/43439A0_clm.bin"); 35 + // let btfw = include_bytes!("../cyw43-firmware/43439A0_btfw.bin"); 34 36 35 37 // To make flashing faster for development, you may want to flash the firmwares independently 36 38 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: 37 39 // probe-rs download 43439A0.bin --binary-format bin --chip RP2040 --base-address 0x10100000 38 40 // probe-rs download 43439A0_clm.bin --binary-format bin --chip RP2040 --base-address 0x10140000 39 - // let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; 40 - // let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 230321) }; 41 + // probe-rs download 43439A0_btfw.bin --binary-format bin --chip RP2040 --base-address 0x10141400 42 + let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; 43 + let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; 44 + let btfw = unsafe { core::slice::from_raw_parts(0x10141400 as *const u8, 6164) }; 41 45 42 46 let pwr = Output::new(p_23, Level::Low); 43 47 let cs = Output::new(p_25, Level::High); ··· 46 50 47 51 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 48 52 let state = STATE.init(cyw43::State::new()); 49 - let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 50 - unwrap!(spawner.spawn(wifi_task(runner))); 53 + let (net_device, _bt_device, mut control, runner) = 54 + cyw43::new_with_bluetooth(state, pwr, spi, fw, btfw).await; 55 + unwrap!(spawner.spawn(cyw43_task(runner))); 51 56 52 57 control.init(clm).await; 53 58 control 54 59 .set_power_management(cyw43::PowerManagementMode::PowerSave) 55 60 .await; 56 - control 61 + (net_device, control) 57 62 }
+59 -16
src/main.rs
··· 4 4 5 5 #![no_std] 6 6 #![no_main] 7 - use control_driver::setup_control; 7 + use control_driver::setup_cyw43; 8 + use defmt::info; 8 9 use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice; 9 10 use embassy_executor::Spawner; 10 11 use embassy_rp::gpio; ··· 13 14 use embassy_rp::spi::{self}; 14 15 use embassy_sync::blocking_mutex::raw::NoopRawMutex; 15 16 use embassy_sync::mutex::Mutex; 16 - use embassy_time::Delay; 17 + use embassy_time::{Delay, Duration, Timer}; 18 + use embedded_graphics::pixelcolor::Rgb565; 19 + use embedded_graphics::primitives::PrimitiveStyleBuilder; 20 + use embedded_graphics::text::Text; 17 21 use embedded_graphics::{ 18 22 mono_font::{ascii::*, MonoTextStyle}, 19 23 pixelcolor::BinaryColor, ··· 26 30 TextBox, 27 31 }; 28 32 use gpio::{Level, Output, Pull}; 33 + use heapless::String; 29 34 use uc8151::asynch::Uc8151; 30 - use uc8151::LUT; 31 35 use uc8151::WIDTH; 36 + use uc8151::{UpdateRegion, LUT}; 32 37 use {defmt_rtt as _, panic_probe as _}; 33 38 mod control_driver; 34 39 35 40 #[embassy_executor::main] 36 41 async fn main(spawner: Spawner) { 37 42 let p = embassy_rp::init(Default::default()); 38 - let mut control = setup_control( 43 + let (_net_device, mut control) = setup_cyw43( 39 44 p.PIO0, p.PIN_23, p.PIN_24, p.PIN_25, p.PIN_29, p.DMA_CH0, spawner, 40 45 ) 41 46 .await; ··· 80 85 let spi_bus: Mutex<NoopRawMutex, _> = Mutex::new(spi); 81 86 let spi_dev = SpiDevice::new(&spi_bus, cs); 82 87 let mut display = Uc8151::new(spi_dev, dc, busy, reset, Delay); 88 + 83 89 display.reset().await; 84 90 85 91 // Initialise display. Using the default LUT speed setting 86 - let _ = display.setup(LUT::Internal).await; 92 + let _ = display.setup(LUT::Fast).await; 87 93 88 94 // 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. 89 95 let character_style = MonoTextStyle::new(&FONT_9X18_BOLD, BinaryColor::Off); ··· 94 100 .build(); 95 101 96 102 // Bounding box for our text. Fill it with the opposite color so we can read the text. 97 - let bounds = Rectangle::new(Point::new(10, 10), Size::new(WIDTH - 157, 0)); 103 + let bounds = Rectangle::new(Point::new(0, 40), Size::new(WIDTH - 157, 0)); 98 104 bounds 99 105 .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)) 100 106 .draw(&mut display) 101 107 .unwrap(); 102 108 103 109 // Create the text box and apply styling options. 104 - let text = "Written In\nRust!"; 110 + let text = "Written In\nRust!!"; 105 111 let text_box = TextBox::with_textbox_style(text, bounds, character_style, textbox_style); 106 112 107 113 // Draw the text box. 108 114 text_box.draw(&mut display).unwrap(); 115 + 109 116 let _ = display.update().await; 110 - control.gpio_set(0, true).await; 117 + 118 + let delay: Duration = Duration::from_secs(1); 119 + let mut count = 0; 120 + let mut text: String<16> = String::<16>::new(); 121 + 122 + loop { 123 + info!("led on!"); 124 + control.gpio_set(0, true).await; 125 + Timer::after(delay).await; 126 + 127 + info!("led off!"); 128 + control.gpio_set(0, false).await; 129 + 130 + Timer::after(delay).await; 111 131 112 - // loop { 113 - // info!("led on!"); 114 - // control.gpio_set(0, true).await; 115 - // Timer::after(delay).await; 132 + let _ = core::fmt::write(&mut text, format_args!("Count: {}", count)); 133 + let count_bounds = Rectangle::new(Point::new(0, 0), Size::new(WIDTH, 24)); 134 + count_bounds 135 + .into_styled( 136 + PrimitiveStyleBuilder::default() 137 + .stroke_color(BinaryColor::Off) 138 + .fill_color(BinaryColor::On) 139 + .stroke_width(1) 140 + .build(), 141 + ) 142 + .draw(&mut display) 143 + .unwrap(); 116 144 117 - // info!("led off!"); 118 - // control.gpio_set(0, false).await; 145 + Text::new(text.as_str(), Point::new(8, 16), character_style) 146 + .draw(&mut display) 147 + .unwrap(); 119 148 120 - // Timer::after(delay).await; 121 - // } 149 + // // Draw the text box. 150 + let result = display 151 + .partial_update(count_bounds.try_into().unwrap()) 152 + .await; 153 + match result { 154 + Ok(_) => {} 155 + Err(_) => { 156 + info!("Error updating display"); 157 + } 158 + } 159 + text.clear(); 160 + // let _ = display.clear(Rgb565::WHITE.into()); 161 + // let _ = display.update().await; 162 + count += 1; 163 + // Timer::after(Duration::from_secs(10)).await; 164 + } 122 165 }