A fork of pulp-os for the xteink4 adding custom apps
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

RIP: embassy embassy is simply not needed imo, as ereaders i think are inherently sequential devices

hansmrtn e530500d d50c3f3e

+52 -240
+1 -135
Cargo.lock
··· 94 94 95 95 [[package]] 96 96 name = "darling" 97 - version = "0.20.11" 98 - source = "registry+https://github.com/rust-lang/crates.io-index" 99 - checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" 100 - dependencies = [ 101 - "darling_core 0.20.11", 102 - "darling_macro 0.20.11", 103 - ] 104 - 105 - [[package]] 106 - name = "darling" 107 97 version = "0.21.3" 108 98 source = "registry+https://github.com/rust-lang/crates.io-index" 109 99 checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" ··· 124 114 125 115 [[package]] 126 116 name = "darling_core" 127 - version = "0.20.11" 128 - source = "registry+https://github.com/rust-lang/crates.io-index" 129 - checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" 130 - dependencies = [ 131 - "fnv", 132 - "ident_case", 133 - "proc-macro2", 134 - "quote", 135 - "strsim", 136 - "syn 2.0.117", 137 - ] 138 - 139 - [[package]] 140 - name = "darling_core" 141 117 version = "0.21.3" 142 118 source = "registry+https://github.com/rust-lang/crates.io-index" 143 119 checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" ··· 164 140 165 141 [[package]] 166 142 name = "darling_macro" 167 - version = "0.20.11" 168 - source = "registry+https://github.com/rust-lang/crates.io-index" 169 - checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" 170 - dependencies = [ 171 - "darling_core 0.20.11", 172 - "quote", 173 - "syn 2.0.117", 174 - ] 175 - 176 - [[package]] 177 - name = "darling_macro" 178 143 version = "0.21.3" 179 144 source = "registry+https://github.com/rust-lang/crates.io-index" 180 145 checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" ··· 242 207 ] 243 208 244 209 [[package]] 245 - name = "embassy-executor" 246 - version = "0.9.1" 247 - source = "registry+https://github.com/rust-lang/crates.io-index" 248 - checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" 249 - dependencies = [ 250 - "critical-section", 251 - "document-features", 252 - "embassy-executor-macros", 253 - "embassy-executor-timer-queue", 254 - "log", 255 - ] 256 - 257 - [[package]] 258 - name = "embassy-executor-macros" 259 - version = "0.7.0" 260 - source = "registry+https://github.com/rust-lang/crates.io-index" 261 - checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" 262 - dependencies = [ 263 - "darling 0.20.11", 264 - "proc-macro2", 265 - "quote", 266 - "syn 2.0.117", 267 - ] 268 - 269 - [[package]] 270 - name = "embassy-executor-timer-queue" 271 - version = "0.1.0" 272 - source = "registry+https://github.com/rust-lang/crates.io-index" 273 - checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" 274 - 275 - [[package]] 276 210 name = "embassy-futures" 277 211 version = "0.1.2" 278 212 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 316 250 ] 317 251 318 252 [[package]] 319 - name = "embassy-time" 320 - version = "0.5.0" 321 - source = "registry+https://github.com/rust-lang/crates.io-index" 322 - checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" 323 - dependencies = [ 324 - "cfg-if", 325 - "critical-section", 326 - "document-features", 327 - "embassy-time-driver", 328 - "embedded-hal 0.2.7", 329 - "embedded-hal 1.0.0", 330 - "embedded-hal-async", 331 - "futures-core", 332 - "log", 333 - ] 334 - 335 - [[package]] 336 - name = "embassy-time-driver" 337 - version = "0.2.1" 338 - source = "registry+https://github.com/rust-lang/crates.io-index" 339 - checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6" 340 - dependencies = [ 341 - "document-features", 342 - ] 343 - 344 - [[package]] 345 - name = "embassy-time-queue-utils" 346 - version = "0.3.0" 347 - source = "registry+https://github.com/rust-lang/crates.io-index" 348 - checksum = "80e2ee86063bd028a420a5fb5898c18c87a8898026da1d4c852af2c443d0a454" 349 - dependencies = [ 350 - "embassy-executor-timer-queue", 351 - "heapless 0.8.0", 352 - ] 353 - 354 - [[package]] 355 253 name = "embedded-can" 356 254 version = "0.4.1" 357 255 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 627 525 ] 628 526 629 527 [[package]] 630 - name = "esp-radio-rtos-driver" 631 - version = "0.2.0" 632 - source = "registry+https://github.com/rust-lang/crates.io-index" 633 - checksum = "543bc31d1851afd062357e7810c1a9633f282fd3993583499a841ab497cbca6c" 634 - 635 - [[package]] 636 528 name = "esp-riscv-rt" 637 529 version = "0.13.0" 638 530 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 652 544 "cfg-if", 653 545 "document-features", 654 546 "esp-metadata-generated", 655 - ] 656 - 657 - [[package]] 658 - name = "esp-rtos" 659 - version = "0.2.0" 660 - source = "registry+https://github.com/rust-lang/crates.io-index" 661 - checksum = "162ec711c8d06e79c67b75d01595539e86b0aac209643af98ca87a12250428b3" 662 - dependencies = [ 663 - "allocator-api2", 664 - "cfg-if", 665 - "document-features", 666 - "embassy-executor", 667 - "embassy-sync 0.7.2", 668 - "embassy-time-driver", 669 - "embassy-time-queue-utils", 670 - "esp-alloc", 671 - "esp-config", 672 - "esp-hal", 673 - "esp-hal-procmacros", 674 - "esp-metadata-generated", 675 - "esp-radio-rtos-driver", 676 - "esp-sync", 677 - "log", 678 - "portable-atomic", 679 547 ] 680 548 681 549 [[package]] ··· 1036 904 version = "0.1.0" 1037 905 dependencies = [ 1038 906 "critical-section", 1039 - "embassy-executor", 1040 - "embassy-time", 1041 907 "embedded-hal 1.0.0", 1042 908 "embedded-hal-bus", 1043 909 "esp-alloc", ··· 1045 911 "esp-bootloader-esp-idf", 1046 912 "esp-hal", 1047 913 "esp-println", 1048 - "esp-rtos", 1049 914 "log", 915 + "nb 1.1.0", 1050 916 "ssd1677", 1051 917 "static_cell", 1052 918 ]
+1 -9
Cargo.toml
··· 11 11 [dependencies] 12 12 esp-hal = { version = "~1.0", features = ["esp32c3", "log-04", "unstable"] } 13 13 14 - esp-rtos = { version = "0.2.0", features = [ 15 - "embassy", 16 - "esp-alloc", 17 - "esp32c3", 18 - "log-04", 19 - ] } 20 - 21 14 esp-bootloader-esp-idf = { version = "0.4.0", features = ["esp32c3", "log-04"] } 22 15 log = "0.4.27" 23 16 24 - embassy-executor = { version = "0.9.1", features = ["log"] } 25 - embassy-time = { version = "0.5.0", features = ["log"] } 26 17 esp-alloc = "0.9.0" 27 18 esp-backtrace = { version = "0.18.1", features = [ 28 19 "esp32c3", ··· 36 27 embedded-hal = "1.0.0" 37 28 ssd1677 = "0.1.0" 38 29 embedded-hal-bus = "0.3.0" 30 + nb = "1.1.0" 39 31 40 32 41 33 [profile.dev]
+50 -96
src/bin/main.rs
··· 7 7 )] 8 8 #![deny(clippy::large_stack_frames)] 9 9 10 - use embassy_executor::Spawner; 11 - // use embassy_time::{Duration, Timer}; 12 10 use esp_backtrace as _; 13 11 use esp_hal::analog::adc::{Adc, AdcCalCurve, AdcConfig, Attenuation}; 14 12 use esp_hal::clock::CpuClock; 15 - // use esp_hal::gpio::{Input, InputConfig, Pull}; 16 - // use esp_hal::peripherals::ADC1; 17 - use esp_hal::timer::timg::TimerGroup; 18 - use log::info; 19 - 20 - use embassy_time::{Delay, Duration, Timer}; 13 + use esp_hal::delay::Delay; 21 14 use esp_hal::{ 22 15 gpio::{Input, InputConfig, Output, OutputConfig, Pull}, 23 16 peripherals::ADC1, 24 17 spi::master::{Config as SpiConfig, Spi}, 25 18 time::Rate, 26 19 }; 27 - use ssd1677::{ 28 - Builder, Dimensions, Display, Interface, RefreshMode, Region, Rotation, UpdateRegion, 29 - }; 20 + use log::info; 21 + use ssd1677::{Builder, Dimensions, Display, Interface, RefreshMode, Region, Rotation, UpdateRegion}; 30 22 31 23 extern crate alloc; 32 24 ··· 68 60 /// Decode GPIO1 resistor ladder (Right, Left, Confirm, Back) 69 61 /// Values ordered low → high. Idle = ~2851. 70 62 fn decode_gpio1(mv: u16) -> Option<Button> { 71 - if in_range(mv, 3, 50) { 72 - return Some(Button::Right); 73 - } 74 - if in_range(mv, 1113, TOLERANCE) { 75 - return Some(Button::Left); 76 - } 77 - if in_range(mv, 1984, TOLERANCE) { 78 - return Some(Button::Confirm); 79 - } 80 - if in_range(mv, 2556, TOLERANCE) { 81 - return Some(Button::Back); 82 - } 63 + if in_range(mv, 3, 50) { return Some(Button::Right); } 64 + if in_range(mv, 1113, TOLERANCE) { return Some(Button::Left); } 65 + if in_range(mv, 1984, TOLERANCE) { return Some(Button::Confirm); } 66 + if in_range(mv, 2556, TOLERANCE) { return Some(Button::Back); } 83 67 None 84 68 } 85 69 86 70 /// Decode GPIO2 resistor ladder (Vol Down, Vol Up) 87 71 /// Values ordered low → high. Idle = ~2851. 88 72 fn decode_gpio2(mv: u16) -> Option<Button> { 89 - if in_range(mv, 3, 50) { 90 - return Some(Button::VolDown); 91 - } 92 - if in_range(mv, 1659, TOLERANCE) { 93 - return Some(Button::VolUp); 94 - } 73 + if in_range(mv, 3, 50) { return Some(Button::VolDown); } 74 + if in_range(mv, 1659, TOLERANCE) { return Some(Button::VolUp); } 95 75 None 96 76 } 97 77 ··· 99 79 val >= center.saturating_sub(tol) && val <= center.saturating_add(tol) 100 80 } 101 81 82 + 102 83 #[allow( 103 84 clippy::large_stack_frames, 104 85 reason = "it's not unusual to allocate larger buffers etc. in main" 105 86 )] 106 - #[esp_rtos::main] 107 - async fn main(spawner: Spawner) -> ! { 87 + #[esp_hal::main] 88 + fn main() -> ! { 108 89 esp_println::logger::init_logger_from_env(); 109 90 let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); 110 91 let peripherals = esp_hal::init(config); 111 92 esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 66320); 112 93 113 - let timg0 = TimerGroup::new(peripherals.TIMG0); 114 - let sw_interrupt = 115 - esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); 116 - esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0); 94 + let delay = Delay::new(); 117 95 118 96 info!("pulp-os booting..."); 119 97 120 - // --- ADC setup with calibration --- 98 + // --- ADC setup with calibration (blocking) --- 121 99 let mut adc1_config = AdcConfig::new(); 122 - let mut btn_row1_pin = adc1_config 123 - .enable_pin_with_cal::<_, AdcCalCurve<ADC1>>(peripherals.GPIO1, Attenuation::_11dB); 124 - let mut btn_row2_pin = adc1_config 125 - .enable_pin_with_cal::<_, AdcCalCurve<ADC1>>(peripherals.GPIO2, Attenuation::_11dB); 126 - let mut adc1 = Adc::new(peripherals.ADC1, adc1_config).into_async(); 100 + let mut btn_row1_pin = adc1_config.enable_pin_with_cal::<_, AdcCalCurve<ADC1>>( 101 + peripherals.GPIO1, 102 + Attenuation::_11dB, 103 + ); 104 + let mut btn_row2_pin = adc1_config.enable_pin_with_cal::<_, AdcCalCurve<ADC1>>( 105 + peripherals.GPIO2, 106 + Attenuation::_11dB, 107 + ); 108 + let mut adc1 = Adc::new(peripherals.ADC1, adc1_config); 127 109 128 110 // Power button: digital, active LOW 129 111 let power_btn = Input::new( ··· 131 113 InputConfig::default().with_pull(Pull::Up), 132 114 ); 133 115 134 - let _ = spawner; 135 - 136 116 let mut last_button: Option<Button> = None; 137 117 138 - let config = esp_hal::Config::default().with_cpu_clock(esp_hal::clock::CpuClock::max()); 139 - // let p = esp_hal::init(config); 140 - 141 - // --- EPD pins (Xteink X4 reference) --- 142 - // CS=21, DC=4, RST=5, BUSY=6; SCLK=8, MOSI=10 :contentReference[oaicite:8]{index=8} 143 - let cs = Output::new( 144 - peripherals.GPIO21, 145 - esp_hal::gpio::Level::High, 146 - OutputConfig::default(), 147 - ); 148 - let dc = Output::new( 149 - peripherals.GPIO4, 150 - esp_hal::gpio::Level::Low, 151 - OutputConfig::default(), 152 - ); 153 - let rst = Output::new( 154 - peripherals.GPIO5, 155 - esp_hal::gpio::Level::High, 156 - OutputConfig::default(), 157 - ); 158 - let busy = Input::new( 159 - peripherals.GPIO6, 160 - InputConfig::default().with_pull(Pull::None), 161 - ); 118 + // --- EPD pins --- 119 + let cs = Output::new(peripherals.GPIO21, esp_hal::gpio::Level::High, OutputConfig::default()); 120 + let dc = Output::new(peripherals.GPIO4, esp_hal::gpio::Level::Low, OutputConfig::default()); 121 + let rst = Output::new(peripherals.GPIO5, esp_hal::gpio::Level::High, OutputConfig::default()); 122 + let busy = Input::new(peripherals.GPIO6, InputConfig::default().with_pull(Pull::None)); 162 123 163 - // --- SPI (write-only is fine for most EPD flows) --- 164 - // Pick the correct SPI peripheral for your chip (ESP32-C3 commonly uses SPI2). 165 - let spi_cfg = SpiConfig::default().with_frequency(Rate::from_mhz(10)); // start conservative; you can raise later 166 - let spi_bus = Spi::new(peripherals.SPI2, spi_cfg) 167 - .unwrap() 124 + // --- SPI --- 125 + let spi_cfg = SpiConfig::default() 126 + .with_frequency(Rate::from_mhz(10)); 127 + let spi_bus = Spi::new(peripherals.SPI2, spi_cfg).unwrap() 168 128 .with_sck(peripherals.GPIO8) 169 129 .with_mosi(peripherals.GPIO10); 170 130 171 - let mut spi = embedded_hal_bus::spi::ExclusiveDevice::new(spi_bus, cs, Delay).unwrap(); 131 + let spi = embedded_hal_bus::spi::ExclusiveDevice::new(spi_bus, cs, Delay::new()).unwrap(); 172 132 173 133 // --- SSD1677 driver setup --- 174 134 let interface = Interface::new(spi, dc, rst, busy); 175 135 176 - // Dimensions::new(rows, cols) == (height, width) per driver README. :contentReference[oaicite:10]{index=10} 177 136 let dims = Dimensions::new(480, 800).unwrap(); 178 137 let cfg = Builder::new() 179 138 .dimensions(dims) ··· 183 142 184 143 let mut epd = Display::new(interface, cfg); 185 144 186 - // Blocking delay object that satisfies embedded-hal DelayNs. :contentReference[oaicite:11]{index=11} 187 - let mut delay = Delay; 145 + let mut epd_delay = Delay::new(); 146 + epd.reset(&mut epd_delay); 188 147 189 - epd.reset(&mut delay); 190 - 191 - // --- Memory-friendly: update a small region --- 192 - // Region x and w should be multiples of 8 pixels (byte aligned). :contentReference[oaicite:12]{index=12} 193 - let region = Region::new(0, 0, 800, 480); // 200 must be multiple of 8; change as needed 194 - let n = region.buffer_size(); // compute required bytes :contentReference[oaicite:13]{index=13} 195 - 196 - let mut bw = alloc::vec![0xFFu8; n]; // all white (1=white, 0=black) :contentReference[oaicite:14]{index=14} 197 - // draw something by clearing bits in `bw`... 148 + // Full refresh 149 + let region = Region::new(0, 0, 800, 480); 150 + let n = region.buffer_size(); 151 + let bw = alloc::vec![0xFFu8; n]; // all white 198 152 199 153 let update = UpdateRegion { 200 154 region, 201 155 black_buffer: &bw, 202 - red_buffer: &[], // disables red plane :contentReference[oaicite:15]{index=15} 203 - mode: RefreshMode::Full, // or Full / Partial :contentReference[oaicite:16]{index=16} 156 + red_buffer: &[], 157 + mode: RefreshMode::Full, 204 158 }; 205 - 206 - epd.update_region(update, &mut delay); 207 - 159 + epd.update_region(update, &mut epd_delay); 208 160 info!("refreshed display!"); 209 161 162 + // Main event loop (kernel thing lol) 210 163 loop { 211 - // Read current button state 164 + // Read button state (blocking ADC) 212 165 let current = if power_btn.is_low() { 213 166 Some(Button::Power) 214 167 } else { 215 - let val1: u16 = adc1.read_oneshot(&mut btn_row1_pin).await; 216 - let val2: u16 = adc1.read_oneshot(&mut btn_row2_pin).await; 168 + let val1: u16 = nb::block!(adc1.read_oneshot(&mut btn_row1_pin)).unwrap(); 169 + let val2: u16 = nb::block!(adc1.read_oneshot(&mut btn_row2_pin)).unwrap(); 217 170 decode_gpio1(val1).or_else(|| decode_gpio2(val2)) 218 171 }; 219 172 220 - // Log transitions only 173 + // Handle button transitions 221 174 match (last_button, current) { 222 175 (None, Some(btn)) => { 223 176 info!("[BTN] {} pressed", btn.name()); ··· 231 184 } 232 185 _ => {} 233 186 } 187 + last_button = current; 234 188 235 - last_button = current; 236 - Timer::after(Duration::from_millis(50)).await; 189 + // Poll delay (NOTE: will become WFI + timer interrupt later) 190 + delay.delay_millis(50); 237 191 } 238 192 }