1use embassy_futures::yield_now;
2use embassy_rp::{
3 Peri,
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: Peri<'a, impl PioPin>,
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 { rx_sm: sm0, tx_sm: sm1, pin: out_pin }
109 }
110
111 async fn enter_rx(&mut self) {
112 while !self.tx_sm.tx().empty() {
113 yield_now().await;
114 }
115
116 Timer::after_micros(300).await;
117
118 self.tx_sm.set_enable(false);
119 self.pin.set_drive_strength(embassy_rp::gpio::Drive::_2mA);
120 self.rx_sm.restart();
121 self.rx_sm.set_enable(true);
122 }
123
124 async fn enter_tx(&mut self) {
125 self.rx_sm.set_enable(false);
126 self.pin.set_drive_strength(embassy_rp::gpio::Drive::_12mA);
127 self.tx_sm.restart();
128 self.tx_sm.set_enable(true);
129 }
130
131 pub async fn recv_byte(&mut self) -> (bool, bool, u8) {
132 let mut data = self.rx_sm.rx().wait_pull().await;
133 let end_bit = data & 1;
134 data >>= 1;
135 let start_bit = data & 1;
136 data >>= 1;
137 (start_bit == 1, end_bit == 1, data as u8)
138 }
139}
140
141#[derive(Debug)]
142#[cfg_attr(feature = "defmt", derive(defmt::Format))]
143pub enum Error {
144 GeneralError(&'static str),
145}
146
147impl rktk::drivers::interface::Error for Error {}
148
149impl<I: Instance + 'static> SplitDriver for PioHalfDuplexSplitDriver<'static, I> {
150 type Error = Error;
151
152 async fn init(&mut self) -> Result<(), Self::Error> {
153 self.enter_rx().await;
154 Ok(())
155 }
156
157 async fn recv(&mut self, buf: &mut [u8], _is_master: bool) -> Result<usize, Self::Error> {
158 let _permit = loop {
159 let (start, end, data) = self.recv_byte().await;
160
161 let permit = COMM_SEMAPHORE.try_acquire(1);
162
163 if !start {
164 continue;
165 }
166
167 buf[0] = data;
168
169 if end {
170 return Ok(0);
171 }
172
173 break permit;
174 };
175
176 for (i, b) in buf.iter_mut().skip(1).enumerate() {
177 let (_start, end, data) = self.recv_byte().await;
178
179 *b = data;
180
181 if end {
182 return Ok(i + 2);
183 }
184 }
185
186 Err(Self::Error::GeneralError("Buffer overflow"))
187 }
188
189 async fn send_all(&mut self, buf: &[u8], _is_master: bool) -> Result<(), Self::Error> {
190 let _permit = COMM_SEMAPHORE.acquire(1).await;
191
192 self.enter_tx().await;
193
194 for (i, data) in buf.iter().enumerate() {
195 let mut data = (*data as u32) << 24;
196
197 if i == 0 {
198 data |= 1 << 23;
199 }
200 if i == buf.len() - 1 {
201 data |= 1 << 22;
202 }
203
204 self.tx_sm.tx().wait_push(data).await;
205 embassy_time::Timer::after_ticks(300).await;
206 }
207
208 self.enter_rx().await;
209
210 Ok(())
211 }
212}