1use crate::{DjiValidator, UnPackError, Validator};
62use atomic::{AtomicU16, AtomicU64, Ordering::Relaxed};
63use core::fmt::{Display, Formatter, Result as FmtResult};
64use core::marker::PhantomData;
65
66const SOF: u16 = 0x_53_A9;
69const RC_CHANNEL_MID: i16 = 1024;
71const RC_FRAME_LENGTH: usize = 21;
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75#[cfg_attr(feature = "defmt", derive(defmt::Format))]
76#[doc(alias("SwitchState", "3PosSwitch", "3WaySwitch"))]
77pub enum Switch {
78 C = 0,
80 N = 1,
82 S = 2,
84}
85
86#[derive(Debug)]
99#[doc(alias("RemoteControlState", "RCState", "RemoteInput"))]
100pub struct RemoteControl<V: Validator = DjiValidator> {
101 datagroup1: AtomicU64,
103 datagroup2: AtomicU64,
105 keyboard_v: AtomicU16,
107 _marker: PhantomData<V>,
109}
110
111impl<V: Validator> RemoteControl<V> {
112 pub const fn new() -> RemoteControl<V> {
114 Self {
115 datagroup1: AtomicU64::new(0),
116 datagroup2: AtomicU64::new(0),
117 keyboard_v: AtomicU16::new(0),
118 _marker: PhantomData,
119 }
120 }
121
122 pub fn update(&self, data: &[u8]) -> Result<usize, UnPackError> {
132 if data.len() < RC_FRAME_LENGTH {
133 return Err(UnPackError::UnexpectedEnd { read: data.len() });
134 }
135
136 let sof = u16::from_le_bytes([data[0], data[1]]);
137 if sof != SOF {
138 return Err(UnPackError::MissingHeader { skip: 1 });
139 }
140
141 let crc = u16::from_le_bytes([data[19], data[20]]);
142 let calc_crc = V::calculate_crc16(&data[..19]);
143 if crc != calc_crc {
144 return Err(UnPackError::InvalidChecksum { at: 19 });
145 }
146
147 let data = &data[2..19];
148 let datagroup1 = u64::from_le_bytes([
149 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
150 ]);
151 let datagroup2 = u64::from_le_bytes([
152 data[8], data[9], data[10], data[11], data[12], data[13], data[14], 0,
153 ]);
154 let keyboard_v = u16::from_le_bytes([data[15], data[16]]);
155
156 self.datagroup1.store(datagroup1, Relaxed);
157 self.datagroup2.store(datagroup2, Relaxed);
158 self.keyboard_v.store(keyboard_v, Relaxed);
159
160 Ok(RC_FRAME_LENGTH)
161 }
162}
163
164impl<V: Validator> RemoteControl<V> {
165 fn get_datagroup1(&self) -> u64 {
166 self.datagroup1.load(Relaxed)
167 }
168
169 fn get_datagroup2(&self) -> u64 {
170 self.datagroup2.load(Relaxed)
171 }
172
173 fn get_keyboard_v(&self) -> u16 {
174 self.keyboard_v.load(Relaxed)
175 }
176}
177
178impl<V: Validator> RemoteControl<V> {
179 pub fn right_horizontal(&self) -> i16 {
181 let datagroup1 = self.get_datagroup1();
182 let right_horizontal = (datagroup1 & 0x7FF) as i16;
183 right_horizontal - RC_CHANNEL_MID
184 }
185
186 pub fn right_vertical(&self) -> i16 {
188 let datagroup1 = self.get_datagroup1();
189 let right_vertical = ((datagroup1 >> 11) & 0x7FF) as i16;
190 right_vertical - RC_CHANNEL_MID
191 }
192
193 pub fn left_vertical(&self) -> i16 {
195 let datagroup1 = self.get_datagroup1();
196 let left_vertical = ((datagroup1 >> 22) & 0x7FF) as i16;
197 left_vertical - RC_CHANNEL_MID
198 }
199
200 pub fn left_horizontal(&self) -> i16 {
202 let datagroup1 = self.get_datagroup1();
203 let left_horizontal = ((datagroup1 >> 33) & 0x7FF) as i16;
204 left_horizontal - RC_CHANNEL_MID
205 }
206
207 pub fn switch(&self) -> Switch {
209 let datagroup1 = self.get_datagroup1();
210 let switch = ((datagroup1 >> 44) & 0x3) as u8;
211 match switch {
212 0 => Switch::C,
213 1 => Switch::N,
214 2 => Switch::S,
215 _ => unreachable!(),
217 }
218 }
219
220 pub fn pause(&self) -> bool {
222 let datagroup1 = self.get_datagroup1();
223 ((datagroup1 >> 46) & 0x1) != 0
224 }
225
226 pub fn left_fn(&self) -> bool {
228 let datagroup1 = self.get_datagroup1();
229 ((datagroup1 >> 47) & 0x1) != 0
230 }
231
232 pub fn right_fn(&self) -> bool {
234 let datagroup1 = self.get_datagroup1();
235 ((datagroup1 >> 48) & 0x1) != 0
236 }
237
238 pub fn wheel(&self) -> i16 {
240 let datagroup1 = self.get_datagroup1();
241 let wheel = ((datagroup1 >> 49) & 0x7FF) as i16;
242 wheel - RC_CHANNEL_MID
243 }
244
245 pub fn trigger(&self) -> bool {
247 let datagroup1 = self.get_datagroup1();
248 ((datagroup1 >> 60) & 0x1) != 0
249 }
250}
251
252impl<V: Validator> RemoteControl<V> {
253 pub fn mouse_vx(&self) -> i16 {
255 let datagroup2 = self.get_datagroup2();
256 (datagroup2 & 0xFFFF) as i16
257 }
258
259 pub fn mouse_vy(&self) -> i16 {
261 let datagroup2 = self.get_datagroup2();
262 ((datagroup2 >> 16) & 0xFFFF) as i16
263 }
264
265 pub fn mouse_vz(&self) -> i16 {
267 let datagroup2 = self.get_datagroup2();
268 ((datagroup2 >> 32) & 0xFFFF) as i16
269 }
270
271 pub fn left_button(&self) -> bool {
273 let datagroup2 = self.get_datagroup2();
274 ((datagroup2 >> 48) & 0x3) != 0
275 }
276
277 pub fn right_button(&self) -> bool {
279 let datagroup2 = self.get_datagroup2();
280 ((datagroup2 >> 50) & 0x3) != 0
281 }
282
283 pub fn mid_button(&self) -> bool {
285 let datagroup2 = self.get_datagroup2();
286 ((datagroup2 >> 52) & 0x3) != 0
287 }
288}
289
290impl<V: Validator> RemoteControl<V> {
291 pub fn keyboard_w(&self) -> bool {
293 self.get_keyboard_v() & (1 << 0) != 0
294 }
295
296 pub fn keyboard_s(&self) -> bool {
298 (self.get_keyboard_v() & (1 << 1)) != 0
299 }
300
301 pub fn keyboard_a(&self) -> bool {
303 (self.get_keyboard_v() & (1 << 2)) != 0
304 }
305
306 pub fn keyboard_d(&self) -> bool {
308 (self.get_keyboard_v() & (1 << 3)) != 0
309 }
310
311 pub fn keyboard_shift(&self) -> bool {
313 (self.get_keyboard_v() & (1 << 4)) != 0
314 }
315
316 pub fn keyboard_ctrl(&self) -> bool {
318 (self.get_keyboard_v() & (1 << 5)) != 0
319 }
320
321 pub fn keyboard_q(&self) -> bool {
323 (self.get_keyboard_v() & (1 << 6)) != 0
324 }
325
326 pub fn keyboard_e(&self) -> bool {
328 (self.get_keyboard_v() & (1 << 7)) != 0
329 }
330
331 pub fn keyboard_r(&self) -> bool {
333 (self.get_keyboard_v() & (1 << 8)) != 0
334 }
335
336 pub fn keyboard_f(&self) -> bool {
338 (self.get_keyboard_v() & (1 << 9)) != 0
339 }
340
341 pub fn keyboard_g(&self) -> bool {
343 (self.get_keyboard_v() & (1 << 10)) != 0
344 }
345
346 pub fn keyboard_z(&self) -> bool {
348 (self.get_keyboard_v() & (1 << 11)) != 0
349 }
350
351 pub fn keyboard_x(&self) -> bool {
353 (self.get_keyboard_v() & (1 << 12)) != 0
354 }
355
356 pub fn keyboard_c(&self) -> bool {
358 (self.get_keyboard_v() & (1 << 13)) != 0
359 }
360
361 pub fn keyboard_v(&self) -> bool {
363 (self.get_keyboard_v() & (1 << 14)) != 0
364 }
365
366 pub fn keyboard_b(&self) -> bool {
368 (self.get_keyboard_v() & (1 << 15)) != 0
369 }
370}
371
372impl<V: Validator> Clone for RemoteControl<V> {
373 fn clone(&self) -> Self {
374 Self {
375 datagroup1: AtomicU64::new(self.get_datagroup1()),
376 datagroup2: AtomicU64::new(self.get_datagroup2()),
377 keyboard_v: AtomicU16::new(self.get_keyboard_v()),
378 _marker: PhantomData,
379 }
380 }
381}
382
383impl<V: Validator> Default for RemoteControl<V> {
384 fn default() -> Self {
385 Self::new()
386 }
387}
388
389impl<V: Validator> Display for RemoteControl<V> {
390 fn fmt(&self, f: &mut Formatter) -> FmtResult {
391 write!(
392 f,
393 "{{\n\tRH: {}, RV: {}, LV: {}, LH: {},\n\tSW: {:?}, P(HII): {},\n\tFn L: {}, R: {},\n\twheel: {}, trigger: {},\n\tMouse: X: {}, Y: {}, Z: {},\n\tMouse: L: {}, M: {}, R: {},\n\tKeyBoard: 0b{:016b}\n}}",
394 self.right_horizontal(),
395 self.right_vertical(),
396 self.left_vertical(),
397 self.left_horizontal(),
398 self.switch(),
399 self.pause(),
400 self.left_fn(),
401 self.right_fn(),
402 self.wheel(),
403 self.trigger(),
404 self.mouse_vx(),
405 self.mouse_vy(),
406 self.mouse_vz(),
407 self.left_button(),
408 self.mid_button(),
409 self.right_button(),
410 self.get_keyboard_v()
411 )
412 }
413}
414
415#[cfg(feature = "defmt")]
416impl<V: Validator> defmt::Format for RemoteControl<V> {
417 fn format(&self, fmt: defmt::Formatter) {
418 defmt::write!(
419 fmt,
420 "{{\n\tRH: {}, RV: {}, LV: {}, LH: {},\n\tSW: {:?}, P(HII): {},\n\tFn L: {}, R: {},\n\twheel: {}, trigger: {},\n\tMouse: X: {}, Y: {}, Z: {},\n\tMouse: L: {}, M: {}, R: {},\n\tKeyBoard: 0b{:016b}\n}}",
421 self.right_horizontal(),
422 self.right_vertical(),
423 self.left_vertical(),
424 self.left_horizontal(),
425 self.switch(),
426 self.pause(),
427 self.left_fn(),
428 self.right_fn(),
429 self.wheel(),
430 self.trigger(),
431 self.mouse_vx(),
432 self.mouse_vy(),
433 self.mouse_vz(),
434 self.left_button(),
435 self.mid_button(),
436 self.right_button(),
437 self.get_keyboard_v()
438 );
439 }
440}