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)
73                    .map_err(|e| DecodeError::new::<Self>(e.into()))?
74                    .to_string()
75            })
76        } else {
77            None
78        };
79
80        Ok(Self {
81            channel,
82            data: read,
83        })
84    }
85}
86
87pub type CompetitionControlPacket =
88    Cdc2CommandPacket<CON_CDC, CON_COMP_CTRL, CompetitionControlPayload>;
89pub type CompetitionControlReplyPacket = Cdc2ReplyPacket<CON_CDC, CON_COMP_CTRL, ()>;
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92#[repr(u8)]
93pub enum MatchMode {
94    Driver = 8,
95    Auto = 10,
96    Disabled = 11,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub struct CompetitionControlPayload {
101    pub match_mode: MatchMode,
102    /// Time in seconds that should be displayed on the controller
103    pub match_time: u32,
104}
105impl Encode for CompetitionControlPayload {
106    fn size(&self) -> usize {
107        5
108    }
109
110    fn encode(&self, data: &mut [u8]) {
111        data[0] = self.match_mode as u8;
112        self.match_time.encode(&mut data[1..]);
113    }
114}