---
sub_title: "Real Time Systems 10"
class_code: "ELERTS10"
toc: true
auther:
  - name: "Finley van Reenen (0964590)"
    email: "mail@lailatheelf.nl"
    name_short: "E.L.F. van Reenen"
---

# Rust Verslag

## Opdracht 8.2

> 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&.

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
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.
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
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:

```rust
use embedded_hal::digital::{ErrorType as DigitalErrorType, OutputPin, PinState};

struct Leds<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> {
    red: &'a mut Red,
    red_state: PinState,
    green: &'a mut Green,
    green_state: PinState,
    blue: &'a mut Blue,
    blue_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 {
        let _  = red.set_low();
        let _  = green.set_low();
        let _  = blue.set_low();
        Self {
            red,
            red_state: PinState::Low,
            green,
            green_state: PinState::Low,
            blue,
            blue_state: PinState::Low,
        }
    }

    pub fn red_toggle(&mut self) -> Result<(), <Red as DigitalErrorType>::Error> {
        if self.red_state == PinState::Low {
            self.red_state = PinState::High;
        } else {
            self.red_state = PinState::Low;
        }
        self.red.set_state(self.red_state)
    }
}
```

Daarnaast is ook de main functie aangepast naar het volgende:

```rust
#[entry]
fn main() -> ! {
    if let (Some(dp), Some(cp)) = (
        pac::Peripherals::take(),
        cortex_m::peripheral::Peripherals::take(),
    ) {       
        //GPIOD ophalen
        let gpiod = dp.GPIOD.split();
        // 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();
        // create leds struct
        let mut leds = Leds::new(&mut red, &mut green, &mut blue);

        //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 status:bool = false;
        loop {
            // On for 1s, off for 1s.
            let _ = leds.red_toggle();
            status ^= true;
            delay.delay_ms(1000_u32);

            //dit verschijnt in een van de open terminals in vscode
            hprintln!("Led {:?}", status.then(|| "aan!").unwrap_or("uit!"));
        }
    }

    loop {}
}
```

### state machine

De statemachine is geimplementeerd in zijn eigen struct 

- Box is not available without malloc. switch to an enum


Ik heb niet genoeg tijd gehad om dat dit vak te werken, dus mijn code werkt niet
zoals dat het moet, het werkt wel. Ik heb veel geëxperimenteerd met Rustlings,
ik hierdoor nog enthousiaster geworden om Rust beter te leren. Het is echt een
andere denkwijze als C/C++. Rust laat je echt goed denken hoe de code moet
werkten en maakt het erg moeilijk om onzichtbare bugs te maken.

## code

```rust
#![deny(unsafe_code)]
#![allow(clippy::empty_loop)]
#![no_main]
#![no_std]

// Halt on panic
use panic_halt as _; // panic handler

use cortex_m_rt::entry;
use stm32f4xx_hal as hal;

use crate::hal::{pac, prelude::*};
use cortex_m_semihosting::hprintln;

enum MainStates {
    Rood,
    Groen,
    Orange,
    BrugOpen_on,
    BrugOpen_off
}

#[entry]
fn main() -> ! {
    if let (Some(dp), Some(cp)) = (
        pac::Peripherals::take(),
        cortex_m::peripheral::Peripherals::take(),
    ) {
        //GPIOD ophalen
        let gpiod = dp.GPIOD.split();
        let mut led_rood = gpiod.pd14.into_push_pull_output();
        let mut led_groen = gpiod.pd12.into_push_pull_output();
        let mut led_orange = gpiod.pd13.into_push_pull_output();

        //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 main_state : MainStates = MainStates::Rood;
        loop {
            match main_state {
                MainStates::Rood => {
                    hprintln!("Rood");
                    led_rood.set_high();
                    led_groen.set_low();
                    led_orange.set_low();
                    delay.delay(4.secs());
                    main_state = MainStates::Groen;
                },
                MainStates::Groen => {
                    hprintln!("Groen");
                    led_rood.set_low();
                    led_groen.set_high();
                    led_orange.set_low();
                    delay.delay(3.secs());
                    main_state = MainStates::Orange;
                },
                MainStates::Orange => {
                    hprintln!("Orange");
                    led_rood.set_low();
                    led_groen.set_low();
                    led_orange.set_high();
                    delay.delay(1.secs());
                    main_state = MainStates::BrugOpen_on;
                },
                MainStates::BrugOpen_on => {
                    hprintln!("Brug open - on");
                    led_rood.set_high();
                    led_groen.set_low();
                    led_orange.set_low();
                    delay.delay(2.secs());
                    main_state = MainStates::BrugOpen_off;
                },
                MainStates::BrugOpen_off => {
                    hprintln!("Brug open - off");
                    led_rood.set_low();
                    led_groen.set_low();
                    led_orange.set_low();
                    delay.delay(1.secs());
                    main_state = MainStates::BrugOpen_on;
                }
            }
        }
    }

    loop {}
}
```




