diff --git a/report-3/rts10_rust/src/leds.rs b/report-3/rts10_rust/src/leds.rs index 5eef33a..2dfad27 100644 --- a/report-3/rts10_rust/src/leds.rs +++ b/report-3/rts10_rust/src/leds.rs @@ -52,37 +52,44 @@ impl<'a, T: OutputPin> Toggle for ToggleLed<'a, T> { pub struct Leds<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle > { pub red: &'a mut RT, pub green: &'a mut GT, + pub orange: &'a mut OT, pub blue: &'a mut BT, // phantom data to convince rustc the generics RP, GP and BP are used. _r: PhantomData, _g: PhantomData, + _o: PhantomData, _b: PhantomData, } impl<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle -> Leds<'a, RP, RT, GP, GT, BP, BT> { - pub fn new(red: &'a mut RT, green: &'a mut GT, blue: &'a mut BT) -> Self { +> Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT> { + pub fn new(red: &'a mut RT, green: &'a mut GT, orange: &'a mut OT, blue: &'a mut BT) -> Self { Self { red, green, + orange, blue, _r: PhantomData, _g: PhantomData, + _o: PhantomData, _b: PhantomData, } } - pub fn set_all(&mut self, red: PinState, green: PinState, blue: PinState) { + pub fn set_all(&mut self, red: PinState, green: PinState, orange: PinState, blue: PinState) { let _ = self.red.set(red); - let _ = self.blue.set(blue); + let _ = self.orange.set(orange); let _ = self.green.set(green); + let _ = self.blue.set(blue); } } diff --git a/report-3/rts10_rust/src/main.rs b/report-3/rts10_rust/src/main.rs index 6d072fe..3e0549f 100644 --- a/report-3/rts10_rust/src/main.rs +++ b/report-3/rts10_rust/src/main.rs @@ -3,6 +3,7 @@ #![no_main] #![no_std] +use embedded_hal::digital::PinState; // Halt on panic use panic_halt as _; // panic handler @@ -27,11 +28,16 @@ fn main() -> ! { //led pinnen uphalen let mut green_pin = &mut gpiod.pd12.into_push_pull_output(); let mut red_pin = &mut gpiod.pd14.into_push_pull_output(); + let mut orange_pin = &mut gpiod.pd13.into_push_pull_output(); let mut blue_pin = &mut gpiod.pd15.into_push_pull_output(); let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led"); let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led"); + let mut orange = ToggleLed::new(&mut orange_pin).expect("faild to set orange led"); let mut blue = ToggleLed::new(&mut blue_pin).expect("faild to set blue led"); - let mut leds = Leds::new(&mut red, &mut green, &mut blue); + let mut leds = Leds::new(&mut red, &mut green, &mut orange, &mut blue); + //user knop + let gpioa = dp.GPIOA.split(); + let button = &mut gpioa.pa0.into_floating_input(); //leds struct en state machine maken let mut state_machine = StateMachine::new(&mut leds); @@ -41,9 +47,20 @@ fn main() -> ! { // Create a delay abstraction based on SysTick let mut delay = cp.SYST.delay(&clocks); + let mut button_high = button.is_high(); loop { let _ = state_machine.second_passed(); - delay.delay_ms(1000_u32); + for _ in 0..99 { + if button_high != button.is_high() { + button_high = button.is_high(); + if button_high { + state_machine.button_press(); + } else { + state_machine.button_release(); + } + } + delay.delay_ms(10_u32); + } } } diff --git a/report-3/rts10_rust/src/state_machine.rs b/report-3/rts10_rust/src/state_machine.rs index dd12658..e240870 100644 --- a/report-3/rts10_rust/src/state_machine.rs +++ b/report-3/rts10_rust/src/state_machine.rs @@ -4,44 +4,67 @@ use crate::leds::{Leds, Toggle}; enum States { Red(StateRed), - Blue(StateBlue), + Orange(StateOrange), Green(StateGreen), + BridgeOpen(StateBridgeOpen) } trait State< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle > { - fn new(leds: &mut Leds) -> Self; - fn second_passed(&self, leds: &mut Leds) -> States; + fn new(leds: &mut Leds) -> Self; + fn second_passed(&self, leds: &mut Leds) -> States; + fn button_press(&self, leds: &mut Leds) -> States; + fn button_release(&self, leds: &mut Leds) -> States; } pub struct StateMachine<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle > { state: States, - leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>, + leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT> } impl<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle -> StateMachine<'a, RP, RT, GP, GT, BP, BT> +> StateMachine<'a, RP, RT, GP, GT, OP, OT, BP, BT> { - pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>) -> Self { + pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT>) -> Self { Self { state: States::Red(StateRed::new(leds)), - leds, + leds } } pub fn second_passed(&mut self) { self.state = match &self.state { States::Red(state) => state.second_passed(self.leds), - States::Blue(state) => state.second_passed(self.leds), + States::Orange(state) => state.second_passed(self.leds), States::Green(state) => state.second_passed(self.leds), + States::BridgeOpen(state) => state.second_passed(self.leds), + } + } + pub fn button_press(&mut self) { + self.state = match &self.state { + States::Red(state) => state.button_press(self.leds), + States::Orange(state) => state.button_press(self.leds), + States::Green(state) => state.button_press(self.leds), + States::BridgeOpen(state) => state.button_press(self.leds), + } + } + pub fn button_release(&mut self) { + self.state = match &self.state { + States::Red(state) => state.button_release(self.leds), + States::Orange(state) => state.button_release(self.leds), + States::Green(state) => state.button_release(self.leds), + States::BridgeOpen(state) => state.button_release(self.leds), } } } @@ -56,15 +79,16 @@ struct StateRed { impl< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle -> State for StateRed { - fn new(leds: &mut Leds) -> Self { - leds.set_all(PinState::High, PinState::Low, PinState::Low); +> State for StateRed { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::High, PinState::Low, PinState::Low, PinState::Low); Self { time_passed: 0 } } - fn second_passed(&self, leds: &mut Leds) -> States { + fn second_passed(&self, leds: &mut Leds) -> States { if self.time_passed + 1 >= 4 { States::Green(StateGreen::new(leds)) } else { @@ -73,6 +97,15 @@ impl< }) } } + + fn button_press(&self, leds: &mut Leds) -> States { + States::BridgeOpen(StateBridgeOpen::new(leds)) + } + fn button_release(&self, _leds: &mut Leds) -> States { + States::Red(Self { + time_passed: self.time_passed + }) + } } // #################################################### @@ -85,40 +118,107 @@ struct StateGreen { impl< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle -> State for StateGreen { - fn new(leds: &mut Leds) -> Self { - leds.set_all(PinState::Low, PinState::High, PinState::Low); +> State for StateGreen { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::Low, PinState::High, PinState::Low, PinState::Low); Self { time_passed: 0 } } - fn second_passed(&self, leds: &mut Leds) -> States { + fn second_passed(&self, leds: &mut Leds) -> States { if self.time_passed + 1 >= 3 { - States::Blue(StateBlue::new(leds)) + States::Orange(StateOrange::new(leds)) } else { States::Green(Self { time_passed: self.time_passed + 1 }) } } + + fn button_press(&self, _leds: &mut Leds) -> States { + States::Green(Self { + time_passed: self.time_passed + }) + } + fn button_release(&self, _leds: &mut Leds) -> States { + States::Green(Self { + time_passed: self.time_passed + }) + } } // #################################################### -// ## BLUE ############################################ +// ## ORANGE ############################################ // #################################################### -struct StateBlue {} +struct StateOrange {} impl< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, BP: OutputPin, BT: Toggle -> State for StateBlue { - fn new(leds: &mut Leds) -> Self { - leds.set_all(PinState::Low, PinState::Low, PinState::High); +> State for StateOrange { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::Low, PinState::Low, PinState::High, PinState::Low); Self {} } - fn second_passed(&self, leds: &mut Leds) -> States { + fn second_passed(&self, leds: &mut Leds) -> States { + States::Red(StateRed::new(leds)) + } + + fn button_press(&self, _leds: &mut Leds) -> States { + States::Orange(Self {}) + } + fn button_release(&self, _leds: &mut Leds) -> States { + States::Orange(Self {}) + } +} + +// #################################################### +// ## BRIDGE_OPEN ##################################### +// #################################################### + +struct StateBridgeOpen { + time_passed: u32 +} +impl< + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> State for StateBridgeOpen { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::Low, PinState::Low, PinState::Low, PinState::High); + Self { + time_passed: 0 + } + } + fn second_passed(&self, leds: &mut Leds) -> States { + if self.time_passed + 1 == 2 { + let _ = leds.blue.low(); + States::BridgeOpen(Self { + time_passed: self.time_passed + 1 + }) + } else if self.time_passed + 1 >= 3 { + let _ = leds.blue.high(); + States::BridgeOpen(Self { + time_passed: 0 + }) + } else { + States::BridgeOpen(Self { + time_passed: self.time_passed + 1 + }) + } + } + + fn button_press(&self, _leds: &mut Leds) -> States { + States::BridgeOpen(Self { + time_passed: self.time_passed + }) + } + fn button_release(&self, leds: &mut Leds) -> States { States::Red(StateRed::new(leds)) } } diff --git a/report-3/rust_report.md b/report-3/rust_report.md index 4cd8ab5..597efdf 100644 --- a/report-3/rust_report.md +++ b/report-3/rust_report.md @@ -14,46 +14,46 @@ auther: > Maak een toestandsmachine volgens de State Pattern methode zoals beschreven in > het boek. Er zijn drie toestanden: rood, groen en oranje. Tussen de toestanden -> wordt geschakeld op basis van tijd: respectievelijk $4s&, &3s& en &1s&. +> wordt geschakeld op basis van tijd: respectievelijk $4s$, $3s$ en $1s$. -De State Pattern methode in rust maakt gebuik van structs en traits. Om dit -mognelijk te maken moet er een struct zijn die de leds kan aansturen. Hiervoor +De State Pattern methode in rust maakt gebruik van structs en traits. Om dit +mogelijk te maken moet er een struct zijn die de leds kan aansturen. Hiervoor is het de Pin struct van de stm32f4xx-hal nodig in in struct. Om mijn implementatie makkelijker onderhoudbaar te maken worden de Pin structs doorgegeven aan de state machine struct. Hiervoor is een triad nodig die -functions voor het aanpassen van de led status beschijft. De `toggle` functie -die gebruikt wordt in het voorbeeld is niet geimplementeerd via een trait. +functions voor het aanpassen van de led status beschrijft. De `toggle` functie +die gebruikt wordt in het voorbeeld is niet geïmplementeerd via een trait. Deze kan dus niet gebruikt worden zonder de hal aan te passen. In de -documentatie van de pin struct implementeerd die de OutputPin trait van de -embedded_hal crate^[https://docs.rs/stm32f4xx-hal/0.22.0/stm32f4xx_hal/gpio/struct.Pin.html#impl-OutputPin-for-Pin%3CP,+N,+Output%3CMODE%3E%3E-1]. Dus deze crate is toegevoed aan het project zodat hier +documentatie van de pin struct implementeert die de OutputPin trait van de +embedded_hal crate^[https://docs.rs/stm32f4xx-hal/0.22.0/stm32f4xx_hal/gpio/struct.Pin.html#impl-OutputPin-for-Pin%3CP,+N,+Output%3CMODE%3E%3E-1]. Dus deze crate is toegevoegd aan het project zodat hier gebruik van gemaakt kan worden. -Om te testen of dit werkt is er een stuct aangemaakt met een simple toggle -functie en de embeded_hal geimporteerd. Dit is gedaan met de volgende code: +Om te testen of dit werkt is er een struct aangemaakt met een simple toggle +functie en de embeded_hal geïmporteerd. Dit is gedaan met de volgende code: ```rust use embedded_hal::digital::{ErrorType as DigitalErrorType, OutputPin, PinState}; -struct Leds<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> { +struct Leds<'a, Red: OutputPin, Green: OutputPin, Orange: OutputPin> { red: &'a mut Red, red_state: PinState, green: &'a mut Green, green_state: PinState, - blue: &'a mut Blue, - blue_state: PinState, + orange: &'a mut Orange, + orange_state: PinState, } -impl<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> Leds<'a, Red, Green, Blue> { - pub fn new(red: &'a mut Red, green: &'a mut Green, blue: &'a mut Blue) -> Self { +impl<'a, Red: OutputPin, Green: OutputPin, Orange: OutputPin> Leds<'a, Red, Green, Orange> { + pub fn new(red: &'a mut Red, green: &'a mut Green, orange: &'a mut Orange) -> Self { let _ = red.set_low(); let _ = green.set_low(); - let _ = blue.set_low(); + let _ = orange.set_low(); Self { red, red_state: PinState::Low, green, green_state: PinState::Low, - blue, - blue_state: PinState::Low, + orange, + orange_state: PinState::Low, } } @@ -82,9 +82,9 @@ fn main() -> ! { // create structs for pins let mut green = gpiod.pd12.into_push_pull_output(); let mut red = gpiod.pd14.into_push_pull_output(); - let mut blue = gpiod.pd15.into_push_pull_output(); + let mut orange = gpiod.pd13.into_push_pull_output(); // create leds struct - let mut leds = Leds::new(&mut red, &mut green, &mut blue); + let mut leds = Leds::new(&mut red, &mut green, &mut orange); //Klok instellen let rcc = dp.RCC.constrain(); @@ -124,34 +124,34 @@ use crate::leds::{Leds, Toggle}; enum States { Red(StateRed), - Blue(StateBlue), + Orange(StateOrange), Green(StateGreen), } trait State< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle + OP: OutputPin, OT: Toggle > { - fn new(leds: &mut Leds) -> Self; - fn second_passed(&self, leds: &mut Leds) -> States; + fn new(leds: &mut Leds) -> Self; + fn second_passed(&self, leds: &mut Leds) -> States; } pub struct StateMachine<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle + OP: OutputPin, OT: Toggle > { state: States, - leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>, + leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT>, } impl<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle -> StateMachine<'a, RP, RT, GP, GT, BP, BT> + OP: OutputPin, OT: Toggle +> StateMachine<'a, RP, RT, GP, GT, OP, OT> { - pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>) -> Self { + pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT>) -> Self { Self { state: States::Red(StateRed::new(leds)), leds, @@ -160,7 +160,7 @@ impl<'a, pub fn second_passed(&mut self) { self.state = match &self.state { States::Red(state) => state.second_passed(self.leds), - States::Blue(state) => state.second_passed(self.leds), + States::Orange(state) => state.second_passed(self.leds), States::Green(state) => state.second_passed(self.leds), } } @@ -238,27 +238,27 @@ Met deze workaround toegepast de `struct Leds` is als volgt geïmplementeerd in pub struct Leds<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle + OP: OutputPin, OT: Toggle > { pub red: &'a mut RT, pub green: &'a mut GT, - pub blue: &'a mut BT, + pub orange: &'a mut OT, - // phantom data to convince rustc the generics RP, GP and BP are used. + // phantom data to convince rustc the generics RP, GP and OP are used. _r: PhantomData, _g: PhantomData, - _b: PhantomData, + _b: PhantomData, } impl<'a, RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle -> Leds<'a, RP, RT, GP, GT, BP, BT> { - pub fn new(red: &'a mut RT, green: &'a mut GT, blue: &'a mut BT) -> Self { + OP: OutputPin, OT: Toggle +> Leds<'a, RP, RT, GP, GT, OP, OT> { + pub fn new(red: &'a mut RT, green: &'a mut GT, orange: &'a mut OT) -> Self { Self { red, green, - blue, + orange, _r: PhantomData, _g: PhantomData, @@ -266,9 +266,9 @@ impl<'a, } } - pub fn set_all(&mut self, red: PinState, green: PinState, blue: PinState) { + pub fn set_all(&mut self, red: PinState, green: PinState, orange: PinState) { let _ = self.red.set(red); - let _ = self.blue.set(blue); + let _ = self.orange.set(orange); let _ = self.green.set(green); } } @@ -291,15 +291,15 @@ struct StateRed { impl< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle -> State for StateRed { - fn new(leds: &mut Leds) -> Self { + OP: OutputPin, OT: Toggle +> State for StateRed { + fn new(leds: &mut Leds) -> Self { leds.set_all(PinState::High, PinState::Low, PinState::Low); Self { time_passed: 0 } } - fn second_passed(&self, leds: &mut Leds) -> States { + fn second_passed(&self, leds: &mut Leds) -> States { if self.time_passed + 1 >= 4 { States::Green(StateGreen::new(leds)) } else { @@ -320,17 +320,17 @@ struct StateGreen { impl< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle -> State for StateGreen { - fn new(leds: &mut Leds) -> Self { + OP: OutputPin, OT: Toggle +> State for StateGreen { + fn new(leds: &mut Leds) -> Self { leds.set_all(PinState::Low, PinState::High, PinState::Low); Self { time_passed: 0 } } - fn second_passed(&self, leds: &mut Leds) -> States { + fn second_passed(&self, leds: &mut Leds) -> States { if self.time_passed + 1 >= 3 { - States::Blue(StateBlue::new(leds)) + States::Orange(StateOrange::new(leds)) } else { States::Green(Self { time_passed: self.time_passed + 1 @@ -340,20 +340,20 @@ impl< } // #################################################### -// ## BLUE ############################################ +// ## ORANGE ############################################ // #################################################### -struct StateBlue {} +struct StateOrange {} impl< RP: OutputPin, RT: Toggle, GP: OutputPin, GT: Toggle, - BP: OutputPin, BT: Toggle -> State for StateBlue { - fn new(leds: &mut Leds) -> Self { + OP: OutputPin, OT: Toggle +> State for StateOrange { + fn new(leds: &mut Leds) -> Self { leds.set_all(PinState::Low, PinState::Low, PinState::High); Self {} } - fn second_passed(&self, leds: &mut Leds) -> States { + fn second_passed(&self, leds: &mut Leds) -> States { States::Red(StateRed::new(leds)) } } @@ -392,11 +392,11 @@ fn main() -> ! { //led pinnen uphalen let mut green_pin = &mut gpiod.pd12.into_push_pull_output(); let mut red_pin = &mut gpiod.pd14.into_push_pull_output(); - let mut blue_pin = &mut gpiod.pd15.into_push_pull_output(); + let mut orange_pin = &mut gpiod.pd15.into_push_pull_output(); let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led"); let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led"); - let mut blue = ToggleLed::new(&mut blue_pin).expect("faild to set blue led"); - let mut leds = Leds::new(&mut red, &mut green, &mut blue); + let mut orange = ToggleLed::new(&mut orange_pin).expect("faild to set orange led"); + let mut leds = Leds::new(&mut red, &mut green, &mut orange); //leds struct en state machine maken let mut state_machine = StateMachine::new(&mut leds); @@ -415,3 +415,424 @@ fn main() -> ! { loop {} } ``` + +## opdracht 8.3 + +> Voeg nu een toestand toe waarbij de blauwe “User” knop aangeeft dat de brug open wilt gaan. Vanuit de rode toestand moet dan naar een andere toestand (brug-open?) worden gesprongen. Wanneer de knop wordt losgelaten springt brug-open naar de rode toestand. In de brug-open-toestand moet de rode led knipperen. Dit knipperen moet elke met een periodetijd van $2s$ ($2s$ aan, $1s$ uit). + +Om deze aanpassing te doen motten de volgende onderdelen aangepast worden: + +- blue led initialiseren en toevoegen aan `struct Leds` en alle plekken waar deze gebuikt wordt +- knop initialiseren +- functies toevoegen voor de knop `trait State` en alle implementaties ervan +- de state `BridgeOpen` toevoegen aan: + - `enum States` + - de tussen functies in `struct StateMachine` + - nieuwe `struct StateBridgeOpen` +- uitlezen van de knop een aanroepen van de nieuwe functies in `trait State` +- de `struct StateRed` aanpassen voor de nieuwe logica +- logica toevoegen aan `struct StateBridgeOpen` + +### resultaat + +#### leds.rs + +```rust +use core::marker::PhantomData; + +use embedded_hal::digital::{OutputPin, PinState}; + +pub trait Toggle { + fn toggle(&mut self) -> Result<(), T::Error>; + fn set(&mut self, state: PinState) -> Result<(), T::Error>; + fn get(&self) -> PinState; + + fn high(&mut self) -> Result<(), T::Error> { + self.set(PinState::High) + } + fn low(&mut self) -> Result<(), T::Error> { + self.set(PinState::Low) + } +} + +pub struct ToggleLed<'a, T: OutputPin> { + pin: &'a mut T, + state: PinState +} +impl<'a, T: OutputPin> ToggleLed<'a, T> { + pub fn new(pin: &'a mut T) -> Result { + match pin.set_low() { + Ok(_) => Ok(Self { pin, state: PinState::Low }), + Err(e) => Err(e) + } + } +} +impl<'a, T: OutputPin> Toggle for ToggleLed<'a, T> { + fn toggle(&mut self) -> Result<(), T::Error> { + if self.state == PinState::High { + self.state = PinState::Low; + } else { + self.state = PinState::Low; + } + self.pin.set_state(self.state) + } + fn set(&mut self, state: PinState) -> Result<(), T::Error> { + if state != self.state { + self.state = state; + self.pin.set_state(self.state) + } else { + Ok(()) + } + } + fn get(&self) -> PinState { + self.state + } +} + +pub struct Leds<'a, + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> { + pub red: &'a mut RT, + pub green: &'a mut GT, + pub orange: &'a mut OT, + pub blue: &'a mut BT, + + // phantom data to convince rustc the generics RP, GP and BP are used. + _r: PhantomData, + _g: PhantomData, + _o: PhantomData, + _b: PhantomData, +} +impl<'a, + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT> { + pub fn new(red: &'a mut RT, green: &'a mut GT, orange: &'a mut OT, blue: &'a mut BT) -> Self { + Self { + red, + green, + orange, + blue, + + _r: PhantomData, + _g: PhantomData, + _o: PhantomData, + _b: PhantomData, + } + } + + pub fn set_all(&mut self, red: PinState, green: PinState, orange: PinState, blue: PinState) { + let _ = self.red.set(red); + let _ = self.orange.set(orange); + let _ = self.green.set(green); + let _ = self.blue.set(blue); + } +} +``` + +#### state_machine.rs + +```rust +use embedded_hal::digital::{OutputPin, PinState}; + +use crate::leds::{Leds, Toggle}; + +enum States { + Red(StateRed), + Orange(StateOrange), + Green(StateGreen), + BridgeOpen(StateBridgeOpen) +} + +trait State< + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> { + fn new(leds: &mut Leds) -> Self; + fn second_passed(&self, leds: &mut Leds) -> States; + fn button_press(&self, leds: &mut Leds) -> States; + fn button_release(&self, leds: &mut Leds) -> States; +} + +pub struct StateMachine<'a, + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> { + state: States, + leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT> +} +impl<'a, + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> StateMachine<'a, RP, RT, GP, GT, OP, OT, BP, BT> +{ + pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT>) -> Self { + Self { + state: States::Red(StateRed::new(leds)), + leds + } + } + pub fn second_passed(&mut self) { + self.state = match &self.state { + States::Red(state) => state.second_passed(self.leds), + States::Orange(state) => state.second_passed(self.leds), + States::Green(state) => state.second_passed(self.leds), + States::BridgeOpen(state) => state.second_passed(self.leds), + } + } + pub fn button_press(&mut self) { + self.state = match &self.state { + States::Red(state) => state.button_press(self.leds), + States::Orange(state) => state.button_press(self.leds), + States::Green(state) => state.button_press(self.leds), + States::BridgeOpen(state) => state.button_press(self.leds), + } + } + pub fn button_release(&mut self) { + self.state = match &self.state { + States::Red(state) => state.button_release(self.leds), + States::Orange(state) => state.button_release(self.leds), + States::Green(state) => state.button_release(self.leds), + States::BridgeOpen(state) => state.button_release(self.leds), + } + } +} + +// #################################################### +// ## RED ############################################# +// #################################################### + +struct StateRed { + time_passed: u32 +} +impl< + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> State for StateRed { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::High, PinState::Low, PinState::Low, PinState::Low); + Self { + time_passed: 0 + } + } + fn second_passed(&self, leds: &mut Leds) -> States { + if self.time_passed + 1 >= 4 { + States::Green(StateGreen::new(leds)) + } else { + States::Red(Self { + time_passed: self.time_passed + 1 + }) + } + } + + fn button_press(&self, leds: &mut Leds) -> States { + States::BridgeOpen(StateBridgeOpen::new(leds)) + } + fn button_release(&self, _leds: &mut Leds) -> States { + States::Red(Self { + time_passed: self.time_passed + }) + } +} + +// #################################################### +// ## GREEN ########################################### +// #################################################### + +struct StateGreen { + time_passed: u32 +} +impl< + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> State for StateGreen { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::Low, PinState::High, PinState::Low, PinState::Low); + Self { + time_passed: 0 + } + } + fn second_passed(&self, leds: &mut Leds) -> States { + if self.time_passed + 1 >= 3 { + States::Orange(StateOrange::new(leds)) + } else { + States::Green(Self { + time_passed: self.time_passed + 1 + }) + } + } + + fn button_press(&self, _leds: &mut Leds) -> States { + States::Green(Self { + time_passed: self.time_passed + }) + } + fn button_release(&self, _leds: &mut Leds) -> States { + States::Green(Self { + time_passed: self.time_passed + }) + } +} + +// #################################################### +// ## ORANGE ############################################ +// #################################################### + +struct StateOrange {} +impl< + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> State for StateOrange { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::Low, PinState::Low, PinState::High, PinState::Low); + Self {} + } + fn second_passed(&self, leds: &mut Leds) -> States { + States::Red(StateRed::new(leds)) + } + + fn button_press(&self, _leds: &mut Leds) -> States { + States::Orange(Self {}) + } + fn button_release(&self, _leds: &mut Leds) -> States { + States::Orange(Self {}) + } +} + +// #################################################### +// ## BRIDGE_OPEN ##################################### +// #################################################### + +struct StateBridgeOpen { + time_passed: u32 +} +impl< + RP: OutputPin, RT: Toggle, + GP: OutputPin, GT: Toggle, + OP: OutputPin, OT: Toggle, + BP: OutputPin, BT: Toggle +> State for StateBridgeOpen { + fn new(leds: &mut Leds) -> Self { + leds.set_all(PinState::Low, PinState::Low, PinState::Low, PinState::High); + Self { + time_passed: 0 + } + } + fn second_passed(&self, leds: &mut Leds) -> States { + if self.time_passed + 1 == 2 { + let _ = leds.blue.low(); + States::BridgeOpen(Self { + time_passed: self.time_passed + 1 + }) + } else if self.time_passed + 1 >= 3 { + let _ = leds.blue.high(); + States::BridgeOpen(Self { + time_passed: 0 + }) + } else { + States::BridgeOpen(Self { + time_passed: self.time_passed + 1 + }) + } + } + + fn button_press(&self, _leds: &mut Leds) -> States { + States::BridgeOpen(Self { + time_passed: self.time_passed + }) + } + fn button_release(&self, leds: &mut Leds) -> States { + States::Red(StateRed::new(leds)) + } +} +``` + +#### main.rs + +```rust +#![deny(unsafe_code)] +#![allow(clippy::empty_loop)] +#![no_main] +#![no_std] + +use embedded_hal::digital::PinState; +// Halt on panic +use panic_halt as _; // panic handler + +use cortex_m_rt::entry; +use stm32f4xx_hal::{self as hal}; + +use crate::hal::{pac, prelude::*}; + +mod leds; +use crate::leds::{Leds, ToggleLed}; +mod state_machine; +use crate::state_machine::StateMachine; + +#[entry] +fn main() -> ! { + if let (Some(dp), Some(cp)) = ( + pac::Peripherals::take(), + cortex_m::peripheral::Peripherals::take(), + ) { + //GPIOD ophalen + let gpiod = dp.GPIOD.split(); + //led pinnen uphalen + let mut green_pin = &mut gpiod.pd12.into_push_pull_output(); + let mut red_pin = &mut gpiod.pd14.into_push_pull_output(); + let mut orange_pin = &mut gpiod.pd13.into_push_pull_output(); + let mut blue_pin = &mut gpiod.pd15.into_push_pull_output(); + let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led"); + let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led"); + let mut orange = ToggleLed::new(&mut orange_pin).expect("faild to set orange led"); + let mut blue = ToggleLed::new(&mut blue_pin).expect("faild to set blue led"); + let mut leds = Leds::new(&mut red, &mut green, &mut orange, &mut blue); + //user knop + let gpioa = dp.GPIOA.split(); + let button = &mut gpioa.pa0.into_floating_input(); + //leds struct en state machine maken + let mut state_machine = StateMachine::new(&mut leds); + + //Klok instellen + let rcc = dp.RCC.constrain(); + let clocks = rcc.cfgr.sysclk(48.MHz()).freeze(); + + // Create a delay abstraction based on SysTick + let mut delay = cp.SYST.delay(&clocks); + let mut button_high = button.is_high(); + loop { + let _ = state_machine.second_passed(); + for _ in 0..99 { + if button_high != button.is_high() { + button_high = button.is_high(); + if button_high { + state_machine.button_press(); + } else { + state_machine.button_release(); + } + } + delay.delay_ms(10_u32); + } + } + } + + loop {} +} +``` \ No newline at end of file