Refactor to remove use of unsafe constructs.

master
Levi Pearson 2020-03-10 22:09:35 -06:00
parent 4d043688d3
commit 3bcca9ff0b
2 changed files with 51 additions and 28 deletions

View File

@ -14,7 +14,6 @@ embedded-hal = "0.2.3"
nb = "0.1.2" nb = "0.1.2"
ssd1306 = "0.3.0-alpha.4" ssd1306 = "0.3.0-alpha.4"
switch-hal = "0.3.2" switch-hal = "0.3.2"
rotary-encoder-hal = "0.2.1"
[dependencies.arrayvec] [dependencies.arrayvec]
version = "0.5.1" version = "0.5.1"

View File

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