diff --git a/Cargo.toml b/Cargo.toml index 90a8c33..c250ece 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ embedded-hal = "0.2.3" nb = "0.1.2" ssd1306 = "0.3.0-alpha.4" switch-hal = "0.3.2" -rotary-encoder-hal = "0.2.1" [dependencies.arrayvec] version = "0.5.1" diff --git a/src/main.rs b/src/main.rs index aa71156..c2db462 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,22 @@ #![no_std] #![no_main] -use core::mem::MaybeUninit; +use core::{ + cell::RefCell, + fmt::Write, +}; use panic_halt as _; use cortex_m_rt::entry; -use cortex_m::peripheral::NVIC; +use cortex_m::{ + interrupt::Mutex, +}; use stm32f1xx_hal::{ afio, - device::EXTI, + device::{EXTI, NVIC}, delay::Delay, i2c::{BlockingI2c, DutyCycle, Mode}, gpio::{ @@ -48,11 +53,13 @@ use embedded_graphics::{ }; use arrayvec::ArrayString; -use core::fmt::Write; -static mut CLK_PIN: MaybeUninit>> = MaybeUninit::uninit(); -static mut DT_PIN: MaybeUninit>> = MaybeUninit::uninit(); -static mut COUNT: i32 = 0; +type CLKPIN = PA8>; +type DTPIN = PA9>; + +static CLK_PIN: Mutex>> = Mutex::new(RefCell::new(None)); +static DT_PIN: Mutex>> = Mutex::new(RefCell::new(None)); +static COUNT: Mutex> = Mutex::new(RefCell::new(0)); #[entry] fn main() -> ! { @@ -162,8 +169,8 @@ fn main() -> ! { // Microcontroller programs never exit main, so we must loop! loop { // Check our inputs - let counter = unsafe { &mut COUNT }; let button = sw.is_active().unwrap(); + let counter = cortex_m::interrupt::free(|cs| *COUNT.borrow(cs).borrow()); if button_last && !button { led.toggle().unwrap(); } @@ -172,20 +179,21 @@ fn main() -> ! { let c = Circle::new(Point::new(cx, cy), C_RADIUS as u32) .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)); + // Show the position of the knob and thus the ball let mut textbuf = ArrayString::<[u8; 15]>::new(); - write!(&mut textbuf, "count: {}", *counter).unwrap(); + write!(&mut textbuf, "count: {}", counter).unwrap(); let count = Text::new(&textbuf, Point::new(20, 36)) .into_styled(TextStyle::new(Font6x8, BinaryColor::On)); + display.clear(); c.draw(&mut display); t.draw(&mut display); count.draw(&mut display); display.flush().unwrap(); - // Move down+right, come back from the other side if we go off-screen - cx = *counter; - //cx += 1; - //if cx > (DISPLAY_W + C_RADIUS) { cx = -C_RADIUS }; + // Control the horizontal position with the knob + cx = counter.min(0).max(DISPLAY_W); + // Wrap the ball back to the top when it falls off the bottom cy += 1; if cy > (DISPLAY_H + C_RADIUS) { cy = -C_RADIUS }; @@ -193,30 +201,38 @@ fn main() -> ! { } fn init_encoder_pins( - clk: PA8>, + mut clk: PA8>, dt: PA9>, afio: &mut afio::Parts, exti: &EXTI, ) { - let clk_pin = unsafe { &mut *CLK_PIN.as_mut_ptr() }; - let dt_pin = unsafe { &mut *DT_PIN.as_mut_ptr() }; + cortex_m::interrupt::free(|cs| { + clk.make_interrupt_source(afio); + clk.trigger_on_edge(exti, Edge::RISING_FALLING); + clk.enable_interrupt(exti); - *clk_pin = clk; - *dt_pin = dt; - - clk_pin.make_interrupt_source(afio); - clk_pin.trigger_on_edge(exti, Edge::RISING_FALLING); - clk_pin.enable_interrupt(exti); + CLK_PIN.borrow(cs).replace(Some(clk)).unwrap(); + DT_PIN.borrow(cs).replace(Some(dt)).unwrap(); + }); } #[interrupt] fn EXTI9_5() { + static mut CLK: Option = None; + static mut DT: Option = None; static mut PREV_A: bool = false; static mut PREV_C: bool = false; - let clk_pin = unsafe { &mut *CLK_PIN.as_mut_ptr() }; - let dt_pin = unsafe { &mut *DT_PIN.as_mut_ptr() }; - let counter = unsafe { &mut COUNT }; + let clk_pin = CLK.get_or_insert_with(|| { + cortex_m::interrupt::free(|cs| { + CLK_PIN.borrow(cs).replace(None).unwrap() + }) + }); + let dt_pin = DT.get_or_insert_with(|| { + cortex_m::interrupt::free(|cs| { + DT_PIN.borrow(cs).replace(None).unwrap() + }) + }); if clk_pin.check_interrupt() { let a = clk_pin.is_high().unwrap(); @@ -228,9 +244,17 @@ fn EXTI9_5() { if b != *PREV_C { *PREV_C = b; if a == b { // Up - *counter = counter.wrapping_add(1); + cortex_m::interrupt::free(|cs| { + COUNT + .borrow(cs) + .replace_with(|count| count.wrapping_add(1)) + }); } else { // Down - *counter = counter.wrapping_add(-1); + cortex_m::interrupt::free(|cs| { + COUNT + .borrow(cs) + .replace_with(|count| count.wrapping_add(-1)) + }); } } }