1use embassy_futures::yield_now;
2use embassy_rp::{
3 Peripheral,
4 pio::{Common, Config, Instance, Pin, Pio, PioPin, ShiftDirection, StateMachine},
5};
6use embassy_sync::semaphore::{FairSemaphore, Semaphore};
7use embassy_time::Timer;
8use fixed::traits::ToFixed;
9use rktk::{drivers::interface::split::SplitDriver, utils::RawMutex};
10
11pub const SPLIT_BITRATE: f64 = 1000000.0;
12pub const SPLIT_CLK_DIVIDER: f64 = 62_000_000.0 / (SPLIT_BITRATE * 8.0);
13
14fn rx_init<'a, I: Instance>(
22 common: &mut Common<'a, I>,
23 sm: &mut StateMachine<'a, I, 0>,
24 data_pin: &Pin<'a, I>,
25) {
26 let prg = pio::pio_asm!(
27 "set pindirs 0",
28 ".wrap_target",
29 "wait 0 pin 0",
30 "set x 9 [8]",
31 "bitloop:",
32 "in pins 1 [6]",
33 "jmp x-- bitloop",
34 "push",
35 ".wrap"
36 );
37 let mut cfg = Config::default();
38 cfg.use_program(&common.load_program(&prg.program), &[]);
39
40 cfg.set_in_pins(&[data_pin]);
41
42 cfg.shift_in.direction = ShiftDirection::Left;
43
44 cfg.fifo_join = embassy_rp::pio::FifoJoin::RxOnly;
45
46 cfg.clock_divider = SPLIT_CLK_DIVIDER.to_fixed();
47 sm.set_config(&cfg);
48 sm.set_enable(true);
49}
50
51fn tx_init<'a, I: Instance>(
52 common: &mut Common<'a, I>,
53 sm: &mut StateMachine<'a, I, 1>,
54 data_pin: &Pin<'a, I>,
55) {
56 let prg = pio::pio_asm!(
57 "set pindirs 0",
58 ".wrap_target",
59 "pull",
60 "set x 9 [2]",
61 "set pins 0",
62 "set pindirs 1 [7]",
63 "bitloop:",
64 "out pins 1 [6]",
65 "jmp x-- bitloop",
66 "set pins 1",
67 "set pindirs 0 [6]",
68 ".wrap"
69 );
70 let mut cfg = Config::default();
71 cfg.use_program(&common.load_program(&prg.program), &[]);
72
73 cfg.set_out_pins(&[data_pin]);
74 cfg.set_set_pins(&[data_pin]);
75
76 cfg.shift_out.direction = ShiftDirection::Left;
77
78 cfg.fifo_join = embassy_rp::pio::FifoJoin::TxOnly;
79
80 cfg.clock_divider = SPLIT_CLK_DIVIDER.to_fixed();
81 sm.set_config(&cfg);
82 sm.set_enable(false);
83}
84
85pub struct PioHalfDuplexSplitDriver<'a, I: Instance> {
86 rx_sm: StateMachine<'a, I, 0>,
87 tx_sm: StateMachine<'a, I, 1>,
88 pin: Pin<'a, I>,
89}
90
91static COMM_SEMAPHORE: FairSemaphore<RawMutex, 3> = FairSemaphore::new(1);
92
93impl<'a, I: Instance> PioHalfDuplexSplitDriver<'a, I> {
94 pub fn new<'b: 'a>(
95 pio: Pio<'static, I>,
96 data_pin: impl Peripheral<P = impl PioPin + 'a> + 'a,
97 ) -> PioHalfDuplexSplitDriver<'a, I> {
98 let mut common = pio.common;
99 let mut sm0 = pio.sm0;
100 let mut sm1 = pio.sm1;
101
102 let mut out_pin = common.make_pio_pin(data_pin);
103 out_pin.set_pull(embassy_rp::gpio::Pull::Up);
104
105 rx_init(&mut common, &mut sm0, &out_pin);
106 tx_init(&mut common, &mut sm1, &out_pin);
107
108 Self {
109 rx_sm: sm0,
110 tx_sm: sm1,
111 pin: out_pin,
112 }
113 }
114
115 async fn enter_rx(&mut self) {
116 while !self.tx_sm.tx().empty() {
117 yield_now().await;
118 }
119
120 Timer::after_micros(300).await;
121
122 self.tx_sm.set_enable(false);
123 self.pin.set_drive_strength(embassy_rp::gpio::Drive::_2mA);
124 self.rx_sm.restart();
125 self.rx_sm.set_enable(true);
126 }
127
128 async fn enter_tx(&mut self) {
129 self.rx_sm.set_enable(false);
130 self.pin.set_drive_strength(embassy_rp::gpio::Drive::_12mA);
131 self.tx_sm.restart();
132 self.tx_sm.set_enable(true);
133 }
134
135 pub async fn recv_byte(&mut self) -> (bool, bool, u8) {
136 let mut data = self.rx_sm.rx().wait_pull().await;
137 let end_bit = data & 1;
138 data >>= 1;
139 let start_bit = data & 1;
140 data >>= 1;
141 (start_bit == 1, end_bit == 1, data as u8)
142 }
143}
144
145#[derive(Debug)]
146#[cfg_attr(feature = "defmt", derive(defmt::Format))]
147pub enum Error {
148 GeneralError(&'static str),
149}
150
151impl rktk::drivers::interface::Error for Error {}
152
153impl<I: Instance + 'static> SplitDriver for PioHalfDuplexSplitDriver<'static, I> {
154 type Error = Error;
155
156 async fn init(&mut self) -> Result<(), Self::Error> {
157 self.enter_rx().await;
158 Ok(())
159 }
160
161 async fn recv(&mut self, buf: &mut [u8], _is_master: bool) -> Result<usize, Self::Error> {
162 let _permit = loop {
163 let (start, end, data) = self.recv_byte().await;
164
165 let permit = COMM_SEMAPHORE.try_acquire(1);
166
167 if !start {
168 continue;
169 }
170
171 buf[0] = data;
172
173 if end {
174 return Ok(0);
175 }
176
177 break permit;
178 };
179
180 for (i, b) in buf.iter_mut().skip(1).enumerate() {
181 let (_start, end, data) = self.recv_byte().await;
182
183 *b = data;
184
185 if end {
186 return Ok(i);
187 }
188 }
189
190 Err(Self::Error::GeneralError("Buffer overflow"))
191 }
192
193 async fn send_all(&mut self, buf: &[u8], _is_master: bool) -> Result<(), Self::Error> {
194 let _permit = COMM_SEMAPHORE.acquire(1).await;
195
196 self.enter_tx().await;
197
198 for (i, data) in buf.iter().enumerate() {
199 let mut data = (*data as u32) << 24;
200
201 if i == 0 {
202 data |= 1 << 23;
203 }
204 if i == buf.len() - 1 {
205 data |= 1 << 22;
206 }
207
208 self.tx_sm.tx().wait_push(data).await;
209 embassy_time::Timer::after_ticks(300).await;
210 }
211
212 self.enter_rx().await;
213
214 Ok(())
215 }
216}