1use embassy_nrf::{
8 Peripheral,
9 buffered_uarte::{BufferedUarteRx, BufferedUarteTx, InterruptHandler},
10 gpio::{AnyPin, Flex},
11 interrupt,
12 ppi::AnyGroup,
13 uarte::{Baudrate, Instance, Parity},
14};
15use embedded_io_async::{Read as _, Write};
16use rktk::drivers::interface::split::SplitDriver;
17
18#[derive(Debug)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub enum UartHalfDuplexSplitDriverError {
21 GeneralError(&'static str),
22}
23
24impl rktk::drivers::interface::Error for UartHalfDuplexSplitDriverError {}
25
26pub struct UartHalfDuplexSplitDriver<
27 UARTE: Instance,
28 UARTEP: Peripheral<P = UARTE>,
29 IRQ: interrupt::typelevel::Binding<UARTE::Interrupt, InterruptHandler<UARTE>>,
30 TIMER: embassy_nrf::timer::Instance,
31 TIMERP: Peripheral<P = TIMER>,
32 CH1: embassy_nrf::ppi::ConfigurableChannel,
33 CH1P: Peripheral<P = CH1>,
34 CH2: embassy_nrf::ppi::ConfigurableChannel,
35 CH2P: Peripheral<P = CH2>,
36> {
37 pin: AnyPin,
38 uarte: UARTEP,
39 irq: IRQ,
40 timer: TIMERP,
41 ppi_ch1: CH1P,
42 ppi_ch2: CH2P,
43 ppi_group: AnyGroup,
44 read_buffer: [u8; 256],
45 write_buffer: [u8; 256],
46}
47
48impl<
49 UARTE: Instance,
50 UARTEP: Peripheral<P = UARTE>,
51 IRQ: interrupt::typelevel::Binding<UARTE::Interrupt, InterruptHandler<UARTE>> + Clone,
52 TIMER: embassy_nrf::timer::Instance,
53 TIMERP: Peripheral<P = TIMER>,
54 CH1: embassy_nrf::ppi::ConfigurableChannel,
55 CH1P: Peripheral<P = CH1>,
56 CH2: embassy_nrf::ppi::ConfigurableChannel,
57 CH2P: Peripheral<P = CH2>,
58> UartHalfDuplexSplitDriver<UARTE, UARTEP, IRQ, TIMER, TIMERP, CH1, CH1P, CH2, CH2P>
59{
60 pub fn new(
61 mut pin: AnyPin,
62 uarte: UARTEP,
63 irq: IRQ,
64 timer: TIMERP,
65 ppi_ch1: CH1P,
66 ppi_ch2: CH2P,
67 ppi_group: AnyGroup,
68 ) -> Self {
69 {
70 let mut pin = Flex::new(&mut pin);
71 pin.set_as_input_output(
72 embassy_nrf::gpio::Pull::Up,
73 embassy_nrf::gpio::OutputDrive::HighDrive0Disconnect1,
74 );
75 }
76 Self {
77 pin,
78 uarte,
79 irq,
80 timer,
81 ppi_ch1,
82 ppi_ch2,
83 ppi_group,
84 read_buffer: [0; 256],
85 write_buffer: [0; 256],
86 }
87 }
88}
89
90impl<
91 UARTE: Instance,
92 UARTEP: Peripheral<P = UARTE> + 'static,
93 IRQ: interrupt::typelevel::Binding<UARTE::Interrupt, InterruptHandler<UARTE>> + Clone + 'static,
94 TIMER: embassy_nrf::timer::Instance,
95 TIMERP: Peripheral<P = TIMER> + 'static,
96 CH1: embassy_nrf::ppi::ConfigurableChannel,
97 CH1P: Peripheral<P = CH1> + 'static,
98 CH2: embassy_nrf::ppi::ConfigurableChannel,
99 CH2P: Peripheral<P = CH2> + 'static,
100> SplitDriver
101 for UartHalfDuplexSplitDriver<UARTE, UARTEP, IRQ, TIMER, TIMERP, CH1, CH1P, CH2, CH2P>
102{
103 type Error = UartHalfDuplexSplitDriverError;
104
105 async fn recv(&mut self, buf: &mut [u8], _is_master: bool) -> Result<usize, Self::Error> {
106 let mut config = embassy_nrf::uarte::Config::default();
107 config.baudrate = Baudrate::BAUD1M;
108 config.parity = Parity::EXCLUDED;
109 let mut rx = BufferedUarteRx::new(
110 &mut self.uarte,
111 &mut self.timer,
112 &mut self.ppi_ch1,
113 &mut self.ppi_ch2,
114 &mut self.ppi_group,
115 self.irq.clone(),
116 &mut self.pin,
117 config,
118 &mut self.read_buffer,
119 );
120 let mut reader = [0u8];
121 let mut i = 0;
122 loop {
123 rx.read_exact(&mut reader)
124 .await
125 .map_err(|_| UartHalfDuplexSplitDriverError::GeneralError("read error"))?;
126 if reader[0] == 0 {
127 buf[i] = reader[0];
128 break;
129 } else {
130 buf[i] = reader[0];
131 i += 1;
132 }
133 }
134 drop(rx);
135
136 Ok(i)
137 }
138
139 async fn send_all(&mut self, buf: &[u8], _is_master: bool) -> Result<(), Self::Error> {
140 let mut config = embassy_nrf::uarte::Config::default();
141 config.baudrate = Baudrate::BAUD1M;
142 config.parity = Parity::EXCLUDED;
143 let mut tx = BufferedUarteTx::new(
144 &mut self.uarte,
145 self.irq.clone(),
146 &mut self.pin,
147 config,
148 &mut self.write_buffer,
149 );
150
151 tx.write_all(buf)
152 .await
153 .map_err(|_| UartHalfDuplexSplitDriverError::GeneralError("write error"))?;
154 tx.flush()
155 .await
156 .map_err(|_| UartHalfDuplexSplitDriverError::GeneralError("flush error"))?;
157 drop(tx);
158
159 embassy_time::Timer::after_micros(50).await;
160
161 Ok(())
162 }
163}