// Button events. // Turn the 5-way button into robot meaning. // Keep raw input separate from behaviour. #![deny(unsafe_code)] #![no_std] #![no_main] use cortex_m_rt::entry; use panic_probe as _; use stm32f1xx_hal::{pac, prelude::*}; #[derive(Debug, Clone, Copy, PartialEq)] enum ButtonDirection { None, Center, Up, Down, Left, Right, } #[derive(Debug, Clone, Copy, PartialEq)] enum RobotEvent { NoEvent, StartStop, BallLeft, BallRight, BallCentered, ObstacleDetected, } /// Turn raw button states into one direction. fn read_direction(center: bool, up: bool, down: bool, left: bool, right: bool) -> ButtonDirection { if center { ButtonDirection::Center } else if up { ButtonDirection::Up } else if down { ButtonDirection::Down } else if left { ButtonDirection::Left } else if right { ButtonDirection::Right } else { ButtonDirection::None } // Q: Why not match? } /// Turn one button direction into one robot event. fn direction_to_event(direction: ButtonDirection) -> RobotEvent { match direction { ButtonDirection::None => RobotEvent::NoEvent, ButtonDirection::Center => RobotEvent::StartStop, ButtonDirection::Left => RobotEvent::BallLeft, ButtonDirection::Right => RobotEvent::BallRight, ButtonDirection::Up => RobotEvent::BallCentered, ButtonDirection::Down => RobotEvent::ObstacleDetected, } } #[entry] fn main() -> ! { let dp = pac::Peripherals::take().unwrap(); let cp = cortex_m::Peripherals::take().unwrap(); let mut rcc = dp.RCC.constrain(); let mut gpioa = dp.GPIOA.split(&mut rcc); let mut gpiob = dp.GPIOB.split(&mut rcc); let mut gpioc = dp.GPIOC.split(&mut rcc); let mut delay = cp.SYST.delay(&rcc.clocks); let center = gpioa.pa8.into_pull_down_input(&mut gpioa.crh); let up = gpioa.pa9.into_pull_down_input(&mut gpioa.crh); let mut vcc = gpioa.pa10.into_push_pull_output(&mut gpioa.crh); let right = gpiob.pb13.into_pull_down_input(&mut gpiob.crh); let down = gpiob.pb14.into_pull_down_input(&mut gpiob.crh); let left = gpiob.pb15.into_pull_down_input(&mut gpiob.crh); let mut gnd = gpiob.pb12.into_push_pull_output(&mut gpiob.crh); let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); vcc.set_high(); gnd.set_low(); led.set_high(); let mut last_event = RobotEvent::NoEvent; loop { let direction = read_direction( center.is_high(), up.is_high(), down.is_high(), left.is_high(), right.is_high(), ); let event = direction_to_event(direction); if event != last_event { last_event = event; if event == RobotEvent::NoEvent { led.set_high(); } else { led.set_low(); } } delay.delay_ms(25u32); } }