1use core::u8;
4
5use alloc::{
6 string::{String, ToString},
7 vec::Vec,
8};
9
10use crate::{
11 Decode, DecodeError, DecodeWithLength, Encode, FixedString, Version,
12 cdc::cmds::USER_CDC,
13 cdc2::{
14 Cdc2CommandPacket, Cdc2ReplyPacket,
15 ecmds::{
16 DEV_STATUS, FDT_STATUS, LOG_READ, LOG_STATUS, RADIO_STATUS, SYS_C_INFO_14,
17 SYS_C_INFO_58, SYS_DASH_SEL, SYS_DASH_TOUCH, SYS_FLAGS, SYS_KV_LOAD, SYS_KV_SAVE,
18 SYS_SCREEN_CAP, SYS_STATUS, SYS_USER_PROG,
19 },
20 },
21 decode::DecodeErrorKind,
22};
23
24pub struct SystemFlags {
25 pub flags: u32,
41
42 pub byte_1: u8,
45
46 pub byte_2: u8,
49
50 pub current_program: u8,
54}
55impl Decode for SystemFlags {
56 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
57 let flags = u32::decode(data)?;
58 let byte_1 = u8::decode(data)?;
59 let byte_2 = u8::decode(data)?;
60 let current_program = u8::decode(data)?;
61
62 Ok(Self {
63 flags,
64 byte_1,
65 byte_2,
66 current_program,
67 })
68 }
69}
70
71#[derive(Debug, Clone, Copy, Eq, PartialEq)]
72pub struct SystemStatus {
73 pub reserved: u8,
75 pub system_version: Option<Version>,
77 pub cpu0_version: Version,
78 pub cpu1_version: Version,
79 pub touch_version: Version,
80 pub details: Option<SystemDetails>,
81}
82impl Decode for SystemStatus {
83 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
84 let reserved = u8::decode(data)?;
85 let system_version = match Version::decode(data)? {
86 Version {
87 major: 0,
88 minor: 0,
89 build: 0,
90 beta: 0,
91 } => None,
92 version => Some(version),
93 };
94
95 let cpu0_version = Version::decode(data)?;
96 let cpu1_version = Version::decode(data)?;
97
98 let touch_version = Version {
100 beta: u8::decode(data)?,
101 build: u8::decode(data)?,
102 minor: u8::decode(data)?,
103 major: u8::decode(data)?,
104 };
105
106 let details = match SystemDetails::decode(data) {
107 Ok(details) => Some(details),
108 Err(e) if e.kind() == DecodeErrorKind::UnexpectedEnd => None,
109 Err(e) => return Err(e),
110 };
111
112 Ok(Self {
113 reserved,
114 system_version,
115 cpu0_version,
116 cpu1_version,
117 touch_version,
118 details,
119 })
120 }
121}
122
123#[derive(Debug, Clone, Copy, Eq, PartialEq)]
124pub struct SystemDetails {
125 pub ssn: u32,
127 pub boot_flags: u32,
128 pub system_flags: u32,
129 pub golden_version: Version,
130 pub nxp_version: Option<Version>,
131}
132impl Decode for SystemDetails {
133 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
134 let ssn = u32::decode(data)?;
135 let boot_flags = u32::decode(data)?;
136 let system_flags = u32::decode(data)?;
137 let golden_version = Version::decode(data)?;
138 let nxp_version = match Version::decode(data) {
139 Ok(version) => Some(version),
140 Err(e) if e.kind() == DecodeErrorKind::UnexpectedEnd => None,
141 Err(e) => return Err(e),
142 };
143
144 Ok(Self {
145 ssn,
146 boot_flags,
147 system_flags,
148 golden_version,
149 nxp_version,
150 })
151 }
152}
153
154pub type SystemFlagsPacket = Cdc2CommandPacket<USER_CDC, SYS_FLAGS, ()>;
155pub type SystemFlagsReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_FLAGS, SystemFlags>;
156
157pub type SystemStatusPacket = Cdc2CommandPacket<USER_CDC, SYS_STATUS, ()>;
158pub type SystemStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_STATUS, SystemStatus>;
159
160#[derive(Debug, Clone, Copy, Eq, PartialEq)]
161pub struct LogEntry {
162 pub code: u8,
164
165 pub log_type: u8,
167
168 pub description: u8,
170
171 pub spare: u8,
173
174 pub time: u32,
176}
177impl Decode for LogEntry {
178 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
179 let code = u8::decode(data)?;
180 let log_type = u8::decode(data)?;
181 let description = u8::decode(data)?;
182 let spare = u8::decode(data)?;
183 let time = u32::decode(data)?;
184
185 Ok(Self {
186 code,
187 log_type,
188 description,
189 spare,
190 time,
191 })
192 }
193}
194
195pub type LogStatusPacket = Cdc2CommandPacket<USER_CDC, LOG_STATUS, ()>;
196pub type LogStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, LOG_STATUS, LogStatusReplyPayload>;
197
198#[derive(Debug, Clone, Copy, Eq, PartialEq)]
199pub struct LogStatusReplyPayload {
200 pub reserved_1: u8,
202
203 pub count: u32,
205
206 pub reserved_2: u32,
208
209 pub reserved_3: u32,
211
212 pub reserved_4: u32,
214}
215impl Decode for LogStatusReplyPayload {
216 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
217 let reserved = u8::decode(data)?;
218 let count = u32::decode(data)?;
219 let reserved_2 = u32::decode(data)?;
220 let reserved_3 = u32::decode(data)?;
221 let reserved_4 = u32::decode(data)?;
222
223 Ok(Self {
224 reserved_1: reserved,
225 count,
226 reserved_2,
227 reserved_3,
228 reserved_4,
229 })
230 }
231}
232
233pub type LogReadPacket = Cdc2CommandPacket<USER_CDC, LOG_READ, LogReadPayload>;
235pub type LogReadReplyPacket = Cdc2ReplyPacket<USER_CDC, LOG_READ, LogReadReplyPayload>;
236
237#[derive(Debug, Clone, Copy, Eq, PartialEq)]
238pub struct LogReadPayload {
239 pub offset: u32,
240 pub count: u32,
241}
242impl Encode for LogReadPayload {
243 fn size(&self) -> usize {
244 8
245 }
246
247 fn encode(&self, data: &mut [u8]) {
248 self.offset.encode(data);
249 self.count.encode(&mut data[4..]);
250 }
251}
252
253#[derive(Debug, Clone, Eq, PartialEq)]
254pub struct LogReadReplyPayload {
255 pub log_size: u8,
257 pub offset: u32,
259 pub count: u16,
261 pub entries: Vec<LogEntry>,
262}
263impl Decode for LogReadReplyPayload {
264 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
265 let log_size = u8::decode(data)?;
266 let offset = u32::decode(data)?;
267 let count = u16::decode(data)?;
268 let entries = Vec::decode_with_len(data, count as _)?;
269
270 Ok(Self {
271 log_size,
272 offset,
273 count,
274 entries,
275 })
276 }
277}
278
279pub type KeyValueLoadPacket = Cdc2CommandPacket<USER_CDC, SYS_KV_LOAD, FixedString<31>>;
280pub type KeyValueLoadReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_KV_LOAD, FixedString<255>>;
281
282pub type KeyValueSavePacket = Cdc2CommandPacket<USER_CDC, SYS_KV_SAVE, KeyValueSavePayload>;
283pub type KeyValueSaveReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_KV_SAVE, ()>;
284
285#[derive(Debug, Clone, Eq, PartialEq)]
286pub struct KeyValueSavePayload {
287 pub key: FixedString<31>,
288 pub value: FixedString<255>,
289}
290impl Encode for KeyValueSavePayload {
291 fn size(&self) -> usize {
292 self.key.size() + self.value.size()
293 }
294
295 fn encode(&self, data: &mut [u8]) {
296 self.key.to_string().encode(data);
297 self.value.to_string().encode(&mut data[self.key.size()..]);
298 }
299}
300
301#[derive(Debug, Clone, Eq, PartialEq)]
302pub struct Slot {
303 pub icon_number: u16,
305 pub name_length: u8,
306 pub name: String,
307}
308impl Decode for Slot {
309 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
310 let icon_number = u16::decode(data)?;
311 let name_length = u8::decode(data)?;
312 let name = String::decode_with_len(data, (name_length - 1) as _)?;
313
314 Ok(Self {
315 icon_number,
316 name_length,
317 name,
318 })
319 }
320}
321
322pub type CatalogSlot1To4InfoPacket = Cdc2CommandPacket<USER_CDC, SYS_C_INFO_14, ()>;
323pub type CatalogSlot1To4InfoReplyPacket =
324 Cdc2CommandPacket<USER_CDC, SYS_C_INFO_14, SlotInfoPayload>;
325pub type CatalogSlot5To8InfoPacket = Cdc2CommandPacket<USER_CDC, SYS_C_INFO_58, ()>;
326pub type CatalogSlot5To8InfoReplyPacket =
327 Cdc2CommandPacket<USER_CDC, SYS_C_INFO_58, SlotInfoPayload>;
328
329#[derive(Debug, Clone, Eq, PartialEq)]
330pub struct SlotInfoPayload {
331 pub flags: u8,
335
336 pub slots: [Slot; 4],
338}
339
340impl Decode for SlotInfoPayload {
341 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
342 let flags = u8::decode(data)?;
343 let slots = <[Slot; 4]>::decode(data)?;
344
345 Ok(Self { flags, slots })
346 }
347}
348
349pub type ProgramControlPacket = Cdc2CommandPacket<USER_CDC, SYS_USER_PROG, ()>;
350pub type ProgramControlReplyPacket = Cdc2CommandPacket<USER_CDC, SYS_USER_PROG, ()>;
351
352#[derive(Debug, Clone, Copy, Eq, PartialEq)]
353#[repr(u8)]
354pub enum DashScreen {
355 Home = 0,
357
358 Battery = 1,
360
361 Led = 3,
366
367 Match = 4,
369
370 TimedRun = 5,
372
373 Wiring = 6,
375
376 Radio = 8,
381
382 Controller1 = 9,
384
385 Brain = 10,
387
388 Running = 13,
396
397 ControlsA = 14,
399
400 Drive = 15,
402
403 Devices = 16,
405
406 UserFolder = 17,
408
409 VexFolder = 18,
411
412 Settings = 19,
414
415 Config = 20,
417
418 Language = 21,
420
421 MotorReverse = 22,
423
424 Confirm = 23,
426
427 UserProgram = 24,
429
430 Off = 25,
432
433 Controller2Mapping = 26,
435
436 Config2 = 27,
438
439 Alert = 28,
441
442 Controller1Mapping = 29,
444
445 ControlsB = 30,
447
448 ControlsC = 31,
450
451 ControlsD = 32,
453
454 Multiplayer = 33,
456
457 EventLog = 34,
459
460 Motor2 = 35,
462
463 UserWiring = 40,
466
467 Clawbot = 41,
469
470 About = 42,
472
473 Language2 = 43,
475
476 Colors = 45,
478
479 SelectSignature = 46,
481
482 LogInfo = 47,
484 }
497
498pub type DashTouchPacket = Cdc2CommandPacket<USER_CDC, SYS_DASH_TOUCH, DashTouchPayload>;
499pub type DashTouchReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_DASH_TOUCH, ()>;
500
501#[derive(Debug, Clone, Copy, Eq, PartialEq)]
502pub struct DashTouchPayload {
503 pub x: u16,
504 pub y: u16,
505 pub pressing: u16,
507}
508impl Encode for DashTouchPayload {
509 fn size(&self) -> usize {
510 6
511 }
512
513 fn encode(&self, data: &mut [u8]) {
514 self.x.encode(data);
515 self.y.encode(&mut data[2..]);
516 self.pressing.encode(&mut data[4..]);
517 }
518}
519
520pub type DashSelectPacket = Cdc2CommandPacket<USER_CDC, SYS_DASH_SEL, DashSelectPayload>;
521pub type DashSelectReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_DASH_SEL, ()>;
522
523#[derive(Debug, Clone, Copy, Eq, PartialEq)]
524pub struct DashSelectPayload {
525 pub screen: DashScreen,
526
527 pub port: u8,
532}
533impl Encode for DashSelectPayload {
534 fn size(&self) -> usize {
535 2
536 }
537
538 fn encode(&self, data: &mut [u8]) {
539 data[0] = self.screen as _;
540 data[1] = self.port;
541 }
542}
543
544pub type ScreenCapturePacket = Cdc2CommandPacket<USER_CDC, SYS_SCREEN_CAP, ScreenCapturePayload>;
545pub type ScreenCaptureReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_SCREEN_CAP, ()>;
546
547#[derive(Debug, Clone, Copy, Eq, PartialEq)]
548pub struct ScreenCapturePayload {
549 pub layer: Option<u8>,
551}
552impl Encode for ScreenCapturePayload {
553 fn size(&self) -> usize {
554 if self.layer.is_some() { 1 } else { 0 }
555 }
556
557 fn encode(&self, data: &mut [u8]) {
558 if let Some(layer) = self.layer {
559 data[0] = layer;
560 }
561 }
562}
563
564#[derive(Debug, Copy, Clone, Eq, PartialEq)]
566#[repr(u8)]
567pub enum DeviceType {
568 NoSensor = 0,
569 Motor = 2,
570 Led = 3,
571 AbsEncoder = 4,
572 CrMotor = 5,
573 Imu = 6,
574 DistanceSensor = 7,
575 Radio = 8,
576 TetheredController = 9,
577 Brain = 10,
578 VisionSensor = 11,
579 AdiExpander = 12,
580 Res1Sensor = 13,
581 Battery = 14,
582 Res3Sensor = 15,
583 OpticalSensor = 16,
584 Magnet = 17,
585 GpsSensor = 20,
586 AicameraSensor = 26,
587 LightTower = 27,
588 ArmDevice = 28,
589 AiVisionSensor = 29,
590 Pneumatic = 30,
591 BumperSensor = 0x40,
592 GyroSensor = 0x46,
593 SonarSensor = 0x47,
594 GenericSensor = 128,
595 GenericSerial = 129,
596 UndefinedSensor = 255,
597}
598impl Decode for DeviceType {
599 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
600 let value = u8::decode(data)?;
601 Ok(match value {
602 0 => DeviceType::NoSensor,
603 2 => DeviceType::Motor,
604 3 => DeviceType::Led,
605 4 => DeviceType::AbsEncoder,
606 5 => DeviceType::CrMotor,
607 6 => DeviceType::Imu,
608 7 => DeviceType::DistanceSensor,
609 8 => DeviceType::Radio,
610 9 => DeviceType::TetheredController,
611 10 => DeviceType::Brain,
612 11 => DeviceType::VisionSensor,
613 12 => DeviceType::AdiExpander,
614 13 => DeviceType::Res1Sensor,
615 14 => DeviceType::Battery,
616 15 => DeviceType::Res3Sensor,
617 16 => DeviceType::OpticalSensor,
618 17 => DeviceType::Magnet,
619 20 => DeviceType::GpsSensor,
620 26 => DeviceType::AicameraSensor,
621 27 => DeviceType::LightTower,
622 28 => DeviceType::ArmDevice,
623 29 => DeviceType::AiVisionSensor,
624 30 => DeviceType::Pneumatic,
625 0x40 => DeviceType::BumperSensor,
626 0x46 => DeviceType::GyroSensor,
627 0x47 => DeviceType::SonarSensor,
628 128 => DeviceType::GenericSensor,
629 129 => DeviceType::GenericSerial,
630 255 => DeviceType::UndefinedSensor,
631 _ => {
632 return Err(DecodeError::new::<Self>(DecodeErrorKind::UnexpectedByte {
633 name: "DeviceType",
634 value,
635 expected: &[
636 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 26, 27, 28,
637 29, 30, 64, 70, 71, 128, 129, 255,
638 ],
639 }));
640 }
641 })
642 }
643}
644
645#[derive(Debug, Clone, Copy, Eq, PartialEq)]
646pub struct DeviceStatus {
647 pub port: u8,
649
650 pub device_type: DeviceType,
652
653 pub status: u8,
655 pub beta_version: u8,
656 pub version: u16,
657 pub boot_version: u16,
658}
659impl Decode for DeviceStatus {
660 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
661 let port = u8::decode(data)?;
662 let device_type = DeviceType::decode(data)?;
663 let status = u8::decode(data)?;
664 let beta_version = u8::decode(data)?;
665 let version = u16::decode(data)?;
666 let boot_version = u16::decode(data)?;
667
668 Ok(Self {
669 port,
670 device_type,
671 status,
672 beta_version,
673 version,
674 boot_version,
675 })
676 }
677}
678
679pub type DeviceStatusPacket = Cdc2CommandPacket<USER_CDC, DEV_STATUS, ()>;
680pub type DeviceStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, DEV_STATUS, DeviceStatusReplyPayload>;
681
682#[derive(Debug, Clone, Eq, PartialEq)]
683pub struct DeviceStatusReplyPayload {
684 pub count: u8,
686 pub devices: Vec<DeviceStatus>,
687}
688impl Decode for DeviceStatusReplyPayload {
689 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
690 let count = u8::decode(data)?;
691 let devices = Vec::decode_with_len(data, count as _)?;
692 Ok(Self { count, devices })
693 }
694}
695
696#[derive(Debug, Clone, Eq, PartialEq)]
697pub struct FdtStatus {
698 pub count: u8,
699 pub files: Vec<Fdt>,
700}
701impl Decode for FdtStatus {
702 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
703 let count = u8::decode(data)?;
704 let entries = Vec::decode_with_len(data, count as _)?;
705
706 Ok(Self {
707 count,
708 files: entries,
709 })
710 }
711}
712
713#[derive(Debug, Clone, Copy, Eq, PartialEq)]
714pub struct Fdt {
715 pub index: u8,
716 pub fdt_type: u8,
717 pub status: u8,
718 pub beta_version: u8,
719 pub version: u16,
720 pub boot_version: u16,
721}
722impl Decode for Fdt {
723 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
724 let index = u8::decode(data)?;
725 let fdt_type = u8::decode(data)?;
726 let status = u8::decode(data)?;
727 let beta_version = u8::decode(data)?;
728 let version = u16::decode(data)?;
729 let boot_version = u16::decode(data)?;
730
731 Ok(Self {
732 index,
733 fdt_type,
734 status,
735 beta_version,
736 version,
737 boot_version,
738 })
739 }
740}
741
742pub type FdtStatusPacket = Cdc2CommandPacket<USER_CDC, FDT_STATUS, ()>;
743pub type FdtStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, FDT_STATUS, FdtStatus>;
744
745#[derive(Debug, Clone, Copy, Eq, PartialEq)]
746pub struct RadioStatus {
747 pub device: u8,
749 pub quality: u16,
751 pub strength: i16,
753 pub channel: u8,
755 pub timeslot: u8,
757}
758impl Decode for RadioStatus {
759 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
760 let device = u8::decode(data)?;
761 let quality = u16::decode(data)?;
762 let strength = i16::decode(data)?;
763 let channel = u8::decode(data)?;
764 let timeslot = u8::decode(data)?;
765
766 Ok(Self {
767 device,
768 quality,
769 strength,
770 channel,
771 timeslot,
772 })
773 }
774}
775
776pub type RadioStatusPacket = Cdc2CommandPacket<USER_CDC, RADIO_STATUS, ()>;
777pub type RadioStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, RADIO_STATUS, RadioStatus>;