vex_cdc/cdc2/
controller.rs

1//! Controller packets.
2
3use alloc::{
4    string::{String, ToString},
5    vec,
6};
7
8use crate::{
9    Decode, DecodeError, Encode, FixedString,
10    cdc::cmds::{CON_CDC, USER_CDC},
11    cdc2::{
12        Cdc2CommandPacket, Cdc2ReplyPacket,
13        ecmds::{CON_COMP_CTRL, USER_READ},
14    },
15};
16
17pub type UserDataPacket = Cdc2CommandPacket<USER_CDC, USER_READ, UserDataPayload>;
18pub type UserDataReplyPacket = Cdc2ReplyPacket<USER_CDC, USER_READ, UserDataReplyPayload>;
19
20#[derive(Debug, Clone, Eq, PartialEq)]
21pub struct UserDataPayload {
22    /// stdio channel is 1, other channels unknown.
23    pub channel: u8,
24
25    /// Write (stdin) bytes.
26    pub write: Option<FixedString<224>>,
27}
28impl Encode for UserDataPayload {
29    fn size(&self) -> usize {
30        2 + self.write.as_ref().map(|write| write.size()).unwrap_or(0)
31    }
32
33    fn encode(&self, data: &mut [u8]) {
34        data[0] = self.channel;
35
36        if let Some(write) = &self.write {
37            data[1] = write.size() as u8;
38            write.encode(&mut data[2..]);
39        } else {
40            data[1] = 0;
41        }
42    }
43}
44
45#[derive(Debug, Clone, Eq, PartialEq)]
46pub struct UserDataReplyPayload {
47    /// stdio channel is 1, other channels unknown.
48    pub channel: u8,
49
50    /// Bytes read from stdout.
51    pub data: Option<String>,
52}
53impl Decode for UserDataReplyPayload {
54    fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
55        let data_len = data.len().saturating_sub(5);
56        let channel = u8::decode(data)?;
57
58        let read = if data_len > 0 {
59            Some({
60                let mut utf8 = vec![];
61
62                for _ in 0..data_len {
63                    let byte = u8::decode(data)?;
64
65                    if byte == 0 {
66                        break;
67                    }
68
69                    utf8.push(byte);
70                }
71
72                core::str::from_utf8(&utf8)?.to_string()
73            })
74        } else {
75            None
76        };
77
78        Ok(Self {
79            channel,
80            data: read,
81        })
82    }
83}
84
85pub type CompetitionControlPacket =
86    Cdc2CommandPacket<CON_CDC, CON_COMP_CTRL, CompetitionControlPayload>;
87pub type CompetitionControlReplyPacket = Cdc2ReplyPacket<CON_CDC, CON_COMP_CTRL, ()>;
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90#[repr(u8)]
91pub enum MatchMode {
92    Driver = 8,
93    Auto = 10,
94    Disabled = 11,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct CompetitionControlPayload {
99    pub match_mode: MatchMode,
100    /// Time in seconds that should be displayed on the controller
101    pub match_time: u32,
102}
103impl Encode for CompetitionControlPayload {
104    fn size(&self) -> usize {
105        5
106    }
107
108    fn encode(&self, data: &mut [u8]) {
109        data[0] = self.match_mode as u8;
110        self.match_time.encode(&mut data[1..]);
111    }
112}