Skip to main content

wm8731_another_hal/
interface.rs

1//! Handle communication details
2use core::fmt;
3use core::marker::PhantomData;
4use embedded_hal::blocking::{i2c, spi};
5use embedded_hal::digital::v2::OutputPin;
6
7///Represent a frame sended through I2C or SPI interface.
8#[derive(Debug, Eq, PartialEq, Copy, Clone)]
9pub struct Frame {
10    pub(crate) data: u16,
11}
12
13impl From<Frame> for [u8; 2] {
14    ///Allow to convert frame to an array directly usable with SPI and I2C abstraction from embedded-hal.
15    fn from(frame: Frame) -> [u8; 2] {
16        frame.data.to_be_bytes()
17    }
18}
19
20impl From<Frame> for [u16; 1] {
21    ///Allow to convert frame to an array directly usable with 16 bit word SPI abstraction from embedded-hal.
22    fn from(frame: Frame) -> [u16; 1] {
23        [frame.data]
24    }
25}
26
27impl From<Frame> for u16 {
28    ///Allow to convert frame in u16.
29    fn from(frame: Frame) -> u16 {
30        frame.data
31    }
32}
33
34/// Serial Interface abstraction for the wm8731 generic driver.
35pub trait WriteFrame {
36    fn write(&mut self, frame: Frame);
37}
38
39/// I2C communication implementation using embedded-hal.
40pub struct I2CInterface<I2C> {
41    i2c: I2C,
42    address: u8,
43}
44
45impl<I2C> core::fmt::Debug for I2CInterface<I2C> {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        write!(f, "I2CInterface<I2C>{{ address:{:0b} }}", self.address)
48    }
49}
50
51impl<I2C> I2CInterface<I2C>
52where
53    I2C: i2c::Write,
54{
55    pub fn new(i2c: I2C, address: u8) -> Self {
56        Self { i2c, address }
57    }
58    pub fn release(self) -> I2C {
59        self.i2c
60    }
61}
62
63impl<I2C> WriteFrame for I2CInterface<I2C>
64where
65    I2C: i2c::Write,
66{
67    fn write(&mut self, frame: Frame) {
68        let frame: [u8; 2] = frame.into();
69        let _ = self.i2c.write(self.address, &frame);
70    }
71}
72
73/// Generic blocking SPI communication implementation using embedded-hal.
74pub struct SPIInterface<SPI, CS, W> {
75    spi: SPI,
76    cs: CS,
77    w: PhantomData<W>,
78}
79
80impl<SPI, CS, W> core::fmt::Debug for SPIInterface<SPI, CS, W> {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        write!(f, "SPIInterface<SPI, CS, W>")
83    }
84}
85
86impl<SPI, CS, W> SPIInterface<SPI, CS, W> {
87    pub fn new(spi: SPI, cs: CS) -> Self {
88        Self {
89            spi,
90            cs,
91            w: PhantomData::<W>,
92        }
93    }
94    pub fn release(self) -> (SPI, CS) {
95        (self.spi, self.cs)
96    }
97}
98
99/// 8 bits words SPI communication implementation using embedded-hal.
100pub type SPIInterfaceU8<SPI, CS> = SPIInterface<SPI, CS, u8>;
101
102/// 16 bits words SPI communication implementation using embedded-hal.
103pub type SPIInterfaceU16<SPI, CS> = SPIInterface<SPI, CS, u16>;
104
105impl<SPI, CS> WriteFrame for SPIInterfaceU8<SPI, CS>
106where
107    SPI: spi::Write<u8>,
108    CS: OutputPin,
109{
110    fn write(&mut self, frame: Frame) {
111        let frame: [u8; 2] = frame.into();
112        let _ = self.spi.write(&frame[0..1]);
113        let _ = self.cs.set_low();
114        let _ = self.spi.write(&frame[1..2]);
115        let _ = self.cs.set_high();
116    }
117}
118
119impl<SPI, CS> WriteFrame for SPIInterfaceU16<SPI, CS>
120where
121    SPI: spi::Write<u16>,
122    CS: OutputPin,
123{
124    fn write(&mut self, frame: Frame) {
125        let frame: [u16; 1] = frame.into();
126        let _ = self.cs.set_low();
127        let _ = self.spi.write(&frame);
128        let _ = self.cs.set_high();
129    }
130}