stm32f446re/
l6360_hw.rs

1use defmt::info;
2use embassy_stm32::bind_interrupts;
3use embassy_stm32::usart::{self, Uart};
4use embassy_stm32::peripherals;
5use embassy_stm32::gpio::{Output, Input, Level, Speed, Pull};
6use embassy_stm32::Peripheral;
7use embassy_stm32::mode::Blocking;
8
9bind_interrupts!(struct UartIrqs {
10    USART1 => usart::InterruptHandler<peripherals::USART1>;
11});
12
13#[derive(Copy, Clone, PartialEq)]
14pub enum Mode {
15    Gpio,
16    Uart,
17}
18
19// Note: bind_interrupts is not generic. This leads to having concrete types.
20#[allow(non_camel_case_types)]
21pub struct L6360_HW<'a> {
22    uart_instance: Option<peripherals::USART1>,
23    tx_pin: Option<peripherals::PA9>,
24    rx_pin: Option<peripherals::PA10>,
25    enl_plus: Output<'a>,
26    en_cq: Output<'a>,
27    in_cq: Option<Output<'a>>,
28    out_cq: Option<Input<'a>>,
29    uart: Option<Uart<'a, Blocking>>,
30    mode: Mode,
31}
32
33impl<'a> L6360_HW<'a> {
34    pub fn new(
35        uart_instance: peripherals::USART1,
36        tx_pin: peripherals::PA9,
37        rx_pin: peripherals::PA10,
38        enl_plus: peripherals::PA6,
39        en_cq: peripherals::PC0,
40    ) -> Self {
41        // Note: This struct uses unsafe to be able to switch between gpio and uart.
42        #[allow(unsafe_code)]
43        let tx_clone = unsafe { tx_pin.clone_unchecked() };
44        #[allow(unsafe_code)]
45        let rx_clone = unsafe { rx_pin.clone_unchecked() };
46
47        Self {
48            uart_instance: Some(uart_instance),
49            tx_pin: Some(tx_pin),
50            rx_pin: Some(rx_pin),
51            enl_plus: Output::new(enl_plus, Level::Low, Speed::Low),
52            en_cq: Output::new(en_cq, Level::Low, Speed::Low),
53            in_cq: Some(Output::new(tx_clone, Level::Low, Speed::Low)),
54            out_cq: Some(Input::new(rx_clone, Pull::None)),
55            uart: None,
56            mode: Mode::Gpio,
57        }
58    }
59
60    pub fn switch_to_uart(&mut self) {
61        // Drop gpios before initalizing uart.
62        drop(self.in_cq.take());
63        drop(self.out_cq.take());
64
65        let mut config = usart::Config::default();
66        config.baudrate = 38_400; //TODO: COM2 for the moment but fix it!
67        config.data_bits = usart::DataBits::DataBits8;
68        config.stop_bits = usart::StopBits::STOP1;
69        config.parity = usart::Parity::ParityEven;
70        config.detect_previous_overrun = true;
71        config.assume_noise_free = false;
72        config.rx_pull = Pull::None;
73
74        self.uart = Some(Uart::new_blocking(
75            self.uart_instance.take().unwrap(),
76            self.rx_pin.take().unwrap(),
77            self.tx_pin.take().unwrap(),
78            config,
79        ).unwrap());
80
81        self.mode = Mode::Uart;
82    }
83
84    pub fn get_mode(&self) -> Mode {
85        self.mode
86    }
87}
88
89impl<'a> l6360::HardwareAccess for L6360_HW<'a> {
90    fn enl_plus(&mut self, level: l6360::PinState) {
91        match level {
92            l6360::PinState::High => self.enl_plus.set_level(Level::High),
93            l6360::PinState::Low => self.enl_plus.set_level(Level::Low),
94        }
95    }
96
97    fn en_cq(&mut self, level: l6360::PinState) {
98        match level {
99            l6360::PinState::High => self.en_cq.set_level(Level::High),
100            l6360::PinState::Low => self.en_cq.set_level(Level::Low),
101        }
102    }
103
104    fn in_cq(&mut self, level: l6360::PinState) {
105        let pin = self.in_cq.as_mut().unwrap();
106        match level {
107            l6360::PinState::High => pin.set_level(Level::High),
108            l6360::PinState::Low => pin.set_level(Level::Low),
109        }
110    }
111
112    fn out_cq(&self) -> l6360::PinState {
113        match self.out_cq.as_ref().unwrap().get_level() {
114            Level::High => l6360::PinState::High,
115            Level::Low => l6360::PinState::Low,
116        }
117    }
118
119    async fn exchange(&mut self, data: &[u8], answer: &mut [u8]) {
120        self.en_cq(l6360::PinState::High);
121        self.uart.as_mut().unwrap().blocking_write(data).unwrap();
122        self.uart.as_mut().unwrap().blocking_flush().unwrap();
123
124        self.en_cq(l6360::PinState::Low);
125        self.uart.as_mut().unwrap().blocking_read(answer).unwrap();
126
127        for byte in answer{
128            info!("answer: {:#04x}", byte);
129        }
130    }
131}