rktk_drivers_nrf/esb/
reporter.rs1use core::{convert::Infallible, marker::PhantomData, sync::atomic::AtomicBool};
2
3use embassy_nrf::{
4 interrupt::{self, typelevel::Binding},
5 pac::Interrupt,
6 radio::{self},
7 timer,
8};
9use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
10use esb_ng::{
11 EsbApp, EsbBuffer, EsbHeader, EsbIrq, IrqTimer, bbq2::queue::BBQueue, irq::StatePTX,
12 peripherals::PtrTimer as _,
13};
14use postcard::experimental::max_size::MaxSize as _;
15use rktk::{
16 drivers::interface::{
17 dongle::DongleData,
18 reporter::{ReporterDriver, ReporterDriverBuilder},
19 wireless::WirelessReporterDriver,
20 },
21 utils::Channel,
22};
23use rktk_log::{debug, helper::Debug2Format, warn};
24
25macro_rules! use_peripheral {
26 ($radio:ident, $timer:ident, $esb_timer:ident) => {
27 type DongleRadio = embassy_nrf::peripherals::$radio;
28 const DONGLE_RADIO_PAC: embassy_nrf::pac::radio::Radio = embassy_nrf::pac::$radio;
29 type DongleTimer = embassy_nrf::peripherals::$timer;
30 type DongleTimerEsb = esb_ng::peripherals::$esb_timer;
31 };
32}
33
34use_peripheral!(RADIO, TIMER0, Timer0);
35
36static IRQ_TIMER: Mutex<CriticalSectionRawMutex, Option<IrqTimer<DongleTimerEsb>>> =
37 Mutex::new(None);
38
39pub struct TimerInterruptHandler {
40 _phantom: PhantomData<()>,
41}
42
43impl interrupt::typelevel::Handler<<DongleTimer as timer::Instance>::Interrupt>
44 for TimerInterruptHandler
45{
46 unsafe fn on_interrupt() {
47 if let Ok(mut irq_timer) = IRQ_TIMER.try_lock() {
48 if let Some(irq_timer) = &mut *irq_timer {
49 irq_timer.timer_interrupt();
50 }
51 }
52 }
53}
54
55static ESB_IRQ: Mutex<
56 CriticalSectionRawMutex,
57 Option<EsbIrq<1024, 1024, DongleTimerEsb, StatePTX>>,
58> = Mutex::new(None);
59
60pub struct EsbInterruptHandler {
61 _phantom: PhantomData<()>,
62}
63
64impl interrupt::typelevel::Handler<<DongleRadio as radio::Instance>::Interrupt>
65 for EsbInterruptHandler
66{
67 unsafe fn on_interrupt() {
68 if let Ok(mut esb_irq) = ESB_IRQ.try_lock() {
69 if let Some(esb_irq) = &mut *esb_irq {
70 if let Err(e) = esb_irq.radio_interrupt() {
71 rktk_log::warn!("Irq error: {:?}", Debug2Format(&e));
72 }
73 }
74 }
75 }
76}
77
78static REPORT_SEND_CHAN: Channel<DongleData, 16> = Channel::new();
81const MAX_PAYLOAD_SIZE: u8 = 192;
82
83pub struct EsbReporterDriverBuilder {
84 _phantom: PhantomData<()>,
85 config: super::Config,
86}
87
88impl EsbReporterDriverBuilder {
89 pub fn new(
90 _timer: DongleTimer,
91 _radio: DongleRadio,
92 _irqs: impl Binding<<DongleTimer as timer::Instance>::Interrupt, TimerInterruptHandler>
93 + Binding<<DongleRadio as radio::Instance>::Interrupt, EsbInterruptHandler>,
94 config: super::Config,
95 ) -> Self {
96 Self {
97 _phantom: PhantomData,
98 config,
99 }
100 }
101}
102
103impl ReporterDriverBuilder for EsbReporterDriverBuilder {
104 type Output = EsbReporterDriver;
105
106 type Error = &'static str;
107
108 async fn build(self) -> Result<(Self::Output, impl Future<Output = ()>), Self::Error> {
109 static BUFFER: EsbBuffer<1024, 1024> = EsbBuffer {
110 app_to_radio_buf: BBQueue::new(),
111 radio_to_app_buf: BBQueue::new(),
112 timer_flag: AtomicBool::new(false),
113 };
114 let config = self
115 .config
116 .config
117 .max_payload_size(192)
118 .check()
119 .map_err(|_| "Config error")?;
120
121 let (esb_app, esb_irq, esb_timer) = BUFFER
122 .try_split(
123 unsafe { DongleTimerEsb::take() },
124 DONGLE_RADIO_PAC,
125 self.config.addresses,
126 config,
127 )
128 .unwrap();
129 let esb_irq = esb_irq.into_ptx();
130 ESB_IRQ.lock().await.replace(esb_irq);
131 IRQ_TIMER.lock().await.replace(esb_timer);
132 unsafe {
133 cortex_m::peripheral::NVIC::unmask(Interrupt::RADIO);
134 cortex_m::peripheral::NVIC::unmask(Interrupt::TIMER0);
135 }
136
137 Ok((EsbReporterDriver {}, esb_task(esb_app)))
138 }
139}
140
141async fn esb_task(esb_app: EsbApp<1024, 1024>) {
142 let mut cnt: u8 = 0;
143 let mut pid = 0;
144 let (mut s, mut r) = esb_app.split();
145 embassy_futures::join::join(
146 async move {
147 loop {
148 let report = REPORT_SEND_CHAN.receive().await;
149 let mut buf = [0; DongleDataWithCnt::POSTCARD_MAX_SIZE];
150 let Ok(slice) = postcard::to_slice(&(cnt, report), &mut buf) else {
151 warn!("Postcard error");
152 continue;
153 };
154
155 let esb_header = EsbHeader::build()
156 .max_payload(MAX_PAYLOAD_SIZE)
157 .pid(pid)
158 .pipe(0)
159 .no_ack(false)
160 .check()
161 .unwrap();
162 let mut packet = match s.wait_grant_packet(esb_header).await {
163 Ok(p) => p,
164 Err(e) => {
165 warn!("Grant packet error: {:?}", Debug2Format(&e));
166 continue;
167 }
168 };
169 packet[..slice.len()].copy_from_slice(slice);
170 packet.commit(slice.len());
171 s.start_tx();
172
173 debug!("Sent report: {:?}", slice);
174
175 cnt = cnt.wrapping_add(1);
176 if pid == 3 {
177 pid = 0;
178 } else {
179 pid += 1;
180 }
181 }
182 },
183 async move {
184 loop {
185 let p = r.wait_read_packet().await;
186 p.release();
187 }
188 },
189 )
190 .await;
191}
192
193pub struct EsbReporterDriver {}
196
197#[derive(Debug)]
198#[cfg_attr(feature = "defmt", derive(defmt::Format))]
199pub struct ErrorMsg(pub &'static str);
200
201impl rktk::drivers::interface::Error for ErrorMsg {}
202
203type DongleDataWithCnt = (usize, DongleData);
204
205impl ReporterDriver for EsbReporterDriver {
206 type Error = ErrorMsg;
207
208 fn try_send_keyboard_report(
209 &self,
210 report: usbd_hid::descriptor::KeyboardReport,
211 ) -> Result<(), Self::Error> {
212 REPORT_SEND_CHAN
213 .try_send(DongleData::Keyboard(report.into()))
214 .map_err(|_| ErrorMsg("Send error"))
215 }
216
217 fn try_send_media_keyboard_report(
218 &self,
219 report: usbd_hid::descriptor::MediaKeyboardReport,
220 ) -> Result<(), Self::Error> {
221 REPORT_SEND_CHAN
222 .try_send(DongleData::MediaKeyboard(report.into()))
223 .map_err(|_| ErrorMsg("Send error"))
224 }
225
226 fn try_send_mouse_report(
227 &self,
228 report: usbd_hid::descriptor::MouseReport,
229 ) -> Result<(), Self::Error> {
230 REPORT_SEND_CHAN
231 .try_send(DongleData::Mouse(report.into()))
232 .map_err(|_| ErrorMsg("Send error"))
233 }
234
235 async fn send_rrp_data(&self, _data: &[u8]) -> Result<(), Self::Error> {
236 Ok(())
237 }
238
239 fn wakeup(&self) -> Result<bool, Self::Error> {
240 Ok(false)
241 }
242}
243
244impl WirelessReporterDriver for EsbReporterDriver {
245 type Error = Infallible;
246
247 async fn clear_bond_data(&self) -> Result<(), <Self as WirelessReporterDriver>::Error> {
248 Ok(())
249 }
250}