diff --git a/Cargo.toml b/Cargo.toml index 6952c45..bb3f3ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ panic-halt = "1.0.0" panic-semihosting = "0.6" stm32f3 = { version = "0.16.0", features = ["stm32f303"] } stm32f3xx-hal = { version = "0.10.0", features = ["stm32f303xc"] } +switch-hal = "0.4.0" # Uncomment for the panic example. # panic-itm = "0.4.1" diff --git a/src/main.rs b/src/main.rs index 84e2f18..6158f17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ #![no_main] use core::fmt::Write; +use core::slice::Iter; use cortex_m_semihosting::hprintln; // pick a panicking behavior @@ -13,8 +14,120 @@ use panic_semihosting as _; // logs messages to the host stderr; requires a debu use cortex_m::peripheral::{syst, Peripherals}; use cortex_m_rt::entry; +use stm32f3xx_hal::delay; use stm32f3xx_hal::serial::Serial; -use stm32f3xx_hal::{self as hal, pac, prelude::*}; +use stm32f3xx_hal::{ + gpio::{self, gpioe}, + pac, + prelude::*, +}; +use switch_hal::{ActiveHigh, IntoSwitch, OutputSwitch, Switch}; + +enum Direction { + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest, +} + +impl Direction { + pub fn iter() -> Iter<'static, Direction> { + static DIRECTIONS: [Direction; 8] = [ + Direction::North, + Direction::NorthEast, + Direction::East, + Direction::SouthEast, + Direction::South, + Direction::SouthWest, + Direction::West, + Direction::NorthWest, + ]; + DIRECTIONS.iter() + } +} + +type Led = Switch>, ActiveHigh>; +struct Leds { + ld3: Led, + ld4: Led, + ld5: Led, + ld6: Led, + ld7: Led, + ld8: Led, + ld9: Led, + ld10: Led, +} + +impl Leds { + fn new( + pe8: gpioe::PE8, + pe9: gpioe::PE9, + pe10: gpioe::PE10, + pe11: gpioe::PE11, + pe12: gpioe::PE12, + pe13: gpioe::PE13, + pe14: gpioe::PE14, + pe15: gpioe::PE15, + moder: &mut gpioe::MODER, + otyper: &mut gpioe::OTYPER, + ) -> Self { + let mut leds = Self { + ld3: pe9 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + ld4: pe8 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + ld5: pe10 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + ld6: pe15 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + ld7: pe11 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + ld8: pe14 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + ld9: pe12 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + ld10: pe13 + .into_push_pull_output(moder, otyper) + .downgrade() + .into_active_high_switch(), + }; + for dir in Direction::iter() { + leds.for_direction(dir).off().ok(); + } + leds + } + + pub fn for_direction(&mut self, direction: &Direction) -> &mut Led { + match direction { + Direction::North => &mut self.ld3, + Direction::NorthEast => &mut self.ld5, + Direction::East => &mut self.ld7, + Direction::SouthEast => &mut self.ld9, + Direction::South => &mut self.ld10, + Direction::SouthWest => &mut self.ld8, + Direction::West => &mut self.ld6, + Direction::NorthWest => &mut self.ld4, + } + } +} #[entry] fn main() -> ! { @@ -32,19 +145,19 @@ fn main() -> ! { systick.set_reload(8_000_000); // 1s systick.clear_current(); - // PE9: LD3 (red) - // PE8: LD4 (blue) - // PE10: LD5 (orange) let mut gpioe = dp.GPIOE.split(&mut rcc.ahb); - let mut ld3 = gpioe - .pe9 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); - let mut ld4 = gpioe - .pe8 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); - let mut ld5 = gpioe - .pe10 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); + let mut leds = Leds::new( + gpioe.pe8, + gpioe.pe9, + gpioe.pe10, + gpioe.pe11, + gpioe.pe12, + gpioe.pe13, + gpioe.pe14, + gpioe.pe15, + &mut gpioe.moder, + &mut gpioe.otyper, + ); let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); let pins = ( @@ -59,14 +172,21 @@ fn main() -> ! { ); let mut uart = Serial::new(dp.USART1, pins, 115200.Bd(), clocks, &mut rcc.apb2); - systick.enable_counter(); + + let mut delay = delay::Delay::new(systick, clocks); + let mut enabled = true; loop { - while !systick.has_wrapped() {} enabled = !enabled; - ld3.toggle().unwrap(); - ld4.toggle().unwrap(); - ld5.toggle().unwrap(); + for dir in Direction::iter() { + let led = leds.for_direction(dir); + if enabled { + led.on().ok(); + } else { + led.off().ok(); + } + delay.delay_ms(50u16); + } uart.write_str("Loop\r\n").unwrap(); hprintln!("Loop"); }