use core::u8;
use alloc::{
string::{String, ToString},
vec::Vec,
};
use crate::{
Decode, DecodeError, DecodeWithLength, Encode, FixedString, Version,
cdc::cmds::USER_CDC,
cdc2::{
Cdc2CommandPacket, Cdc2ReplyPacket,
ecmds::{
DEV_STATUS, FDT_STATUS, LOG_READ, LOG_STATUS, RADIO_STATUS, SYS_C_INFO_14,
SYS_C_INFO_58, SYS_DASH_SEL, SYS_DASH_TOUCH, SYS_FLAGS, SYS_KV_LOAD, SYS_KV_SAVE,
SYS_SCREEN_CAP, SYS_STATUS, SYS_USER_PROG,
},
},
decode::DecodeErrorKind,
};
pub struct SystemFlags {
pub flags: u32,
pub byte_1: u8,
pub byte_2: u8,
pub current_program: u8,
}
impl Decode for SystemFlags {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let flags = u32::decode(data)?;
let byte_1 = u8::decode(data)?;
let byte_2 = u8::decode(data)?;
let current_program = u8::decode(data)?;
Ok(Self {
flags,
byte_1,
byte_2,
current_program,
})
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct SystemStatus {
pub reserved: u8,
pub system_version: Option<Version>,
pub cpu0_version: Version,
pub cpu1_version: Version,
pub touch_version: Version,
pub details: Option<SystemDetails>,
}
impl Decode for SystemStatus {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let reserved = u8::decode(data)?;
let system_version = match Version::decode(data)? {
Version {
major: 0,
minor: 0,
build: 0,
beta: 0,
} => None,
version => Some(version),
};
let cpu0_version = Version::decode(data)?;
let cpu1_version = Version::decode(data)?;
let touch_version = Version {
beta: u8::decode(data)?,
build: u8::decode(data)?,
minor: u8::decode(data)?,
major: u8::decode(data)?,
};
let details = match SystemDetails::decode(data) {
Ok(details) => Some(details),
Err(e) if e.kind() == DecodeErrorKind::UnexpectedEnd => None,
Err(e) => return Err(e),
};
Ok(Self {
reserved,
system_version,
cpu0_version,
cpu1_version,
touch_version,
details,
})
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct SystemDetails {
pub ssn: u32,
pub boot_flags: u32,
pub system_flags: u32,
pub golden_version: Version,
pub nxp_version: Option<Version>,
}
impl Decode for SystemDetails {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let ssn = u32::decode(data)?;
let boot_flags = u32::decode(data)?;
let system_flags = u32::decode(data)?;
let golden_version = Version::decode(data)?;
let nxp_version = match Version::decode(data) {
Ok(version) => Some(version),
Err(e) if e.kind() == DecodeErrorKind::UnexpectedEnd => None,
Err(e) => return Err(e),
};
Ok(Self {
ssn,
boot_flags,
system_flags,
golden_version,
nxp_version,
})
}
}
pub type SystemFlagsPacket = Cdc2CommandPacket<USER_CDC, SYS_FLAGS, ()>;
pub type SystemFlagsReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_FLAGS, SystemFlags>;
pub type SystemStatusPacket = Cdc2CommandPacket<USER_CDC, SYS_STATUS, ()>;
pub type SystemStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_STATUS, SystemStatus>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct LogEntry {
pub code: u8,
pub log_type: u8,
pub description: u8,
pub spare: u8,
pub time: u32,
}
impl Decode for LogEntry {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let code = u8::decode(data)?;
let log_type = u8::decode(data)?;
let description = u8::decode(data)?;
let spare = u8::decode(data)?;
let time = u32::decode(data)?;
Ok(Self {
code,
log_type,
description,
spare,
time,
})
}
}
pub type LogStatusPacket = Cdc2CommandPacket<USER_CDC, LOG_STATUS, ()>;
pub type LogStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, LOG_STATUS, LogStatusReplyPayload>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct LogStatusReplyPayload {
pub reserved_1: u8,
pub count: u32,
pub reserved_2: u32,
pub reserved_3: u32,
pub reserved_4: u32,
}
impl Decode for LogStatusReplyPayload {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let reserved = u8::decode(data)?;
let count = u32::decode(data)?;
let reserved_2 = u32::decode(data)?;
let reserved_3 = u32::decode(data)?;
let reserved_4 = u32::decode(data)?;
Ok(Self {
reserved_1: reserved,
count,
reserved_2,
reserved_3,
reserved_4,
})
}
}
pub type LogReadPacket = Cdc2CommandPacket<USER_CDC, LOG_READ, LogReadPayload>;
pub type LogReadReplyPacket = Cdc2ReplyPacket<USER_CDC, LOG_READ, LogReadReplyPayload>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct LogReadPayload {
pub offset: u32,
pub count: u32,
}
impl Encode for LogReadPayload {
fn size(&self) -> usize {
8
}
fn encode(&self, data: &mut [u8]) {
self.offset.encode(data);
self.count.encode(&mut data[4..]);
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct LogReadReplyPayload {
pub log_size: u8,
pub offset: u32,
pub count: u16,
pub entries: Vec<LogEntry>,
}
impl Decode for LogReadReplyPayload {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let log_size = u8::decode(data)?;
let offset = u32::decode(data)?;
let count = u16::decode(data)?;
let entries = Vec::decode_with_len(data, count as _)?;
Ok(Self {
log_size,
offset,
count,
entries,
})
}
}
pub type KeyValueLoadPacket = Cdc2CommandPacket<USER_CDC, SYS_KV_LOAD, FixedString<31>>;
pub type KeyValueLoadReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_KV_LOAD, FixedString<255>>;
pub type KeyValueSavePacket = Cdc2CommandPacket<USER_CDC, SYS_KV_SAVE, KeyValueSavePayload>;
pub type KeyValueSaveReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_KV_SAVE, ()>;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct KeyValueSavePayload {
pub key: FixedString<31>,
pub value: FixedString<255>,
}
impl Encode for KeyValueSavePayload {
fn size(&self) -> usize {
self.key.len() + self.value.len() + 2
}
fn encode(&self, data: &mut [u8]) {
self.key.to_string().encode(data);
self.value.to_string().encode(&mut data[(self.key.len() + 1)..]);
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Slot {
pub icon_number: u16,
pub name_length: u8,
pub name: String,
}
impl Decode for Slot {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let icon_number = u16::decode(data)?;
let name_length = u8::decode(data)?;
let name = String::decode_with_len(data, (name_length - 1) as _)?;
Ok(Self {
icon_number,
name_length,
name,
})
}
}
pub type CatalogSlot1To4InfoPacket = Cdc2CommandPacket<USER_CDC, SYS_C_INFO_14, ()>;
pub type CatalogSlot1To4InfoReplyPacket =
Cdc2CommandPacket<USER_CDC, SYS_C_INFO_14, SlotInfoPayload>;
pub type CatalogSlot5To8InfoPacket = Cdc2CommandPacket<USER_CDC, SYS_C_INFO_58, ()>;
pub type CatalogSlot5To8InfoReplyPacket =
Cdc2CommandPacket<USER_CDC, SYS_C_INFO_58, SlotInfoPayload>;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SlotInfoPayload {
pub flags: u8,
pub slots: [Slot; 4],
}
impl Decode for SlotInfoPayload {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let flags = u8::decode(data)?;
let slots = <[Slot; 4]>::decode(data)?;
Ok(Self { flags, slots })
}
}
pub type ProgramControlPacket = Cdc2CommandPacket<USER_CDC, SYS_USER_PROG, ()>;
pub type ProgramControlReplyPacket = Cdc2CommandPacket<USER_CDC, SYS_USER_PROG, ()>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[repr(u8)]
pub enum DashScreen {
Home = 0,
Battery = 1,
Led = 3,
Match = 4,
TimedRun = 5,
Wiring = 6,
Radio = 8,
Controller1 = 9,
Brain = 10,
Running = 13,
ControlsA = 14,
Drive = 15,
Devices = 16,
UserFolder = 17,
VexFolder = 18,
Settings = 19,
Config = 20,
Language = 21,
MotorReverse = 22,
Confirm = 23,
UserProgram = 24,
Off = 25,
Controller2Mapping = 26,
Config2 = 27,
Alert = 28,
Controller1Mapping = 29,
ControlsB = 30,
ControlsC = 31,
ControlsD = 32,
Multiplayer = 33,
EventLog = 34,
Motor2 = 35,
UserWiring = 40,
Clawbot = 41,
About = 42,
Language2 = 43,
Colors = 45,
SelectSignature = 46,
LogInfo = 47,
}
pub type DashTouchPacket = Cdc2CommandPacket<USER_CDC, SYS_DASH_TOUCH, DashTouchPayload>;
pub type DashTouchReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_DASH_TOUCH, ()>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct DashTouchPayload {
pub x: u16,
pub y: u16,
pub pressing: u16,
}
impl Encode for DashTouchPayload {
fn size(&self) -> usize {
6
}
fn encode(&self, data: &mut [u8]) {
self.x.encode(data);
self.y.encode(&mut data[2..]);
self.pressing.encode(&mut data[4..]);
}
}
pub type DashSelectPacket = Cdc2CommandPacket<USER_CDC, SYS_DASH_SEL, DashSelectPayload>;
pub type DashSelectReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_DASH_SEL, ()>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct DashSelectPayload {
pub screen: DashScreen,
pub port: u8,
}
impl Encode for DashSelectPayload {
fn size(&self) -> usize {
2
}
fn encode(&self, data: &mut [u8]) {
data[0] = self.screen as _;
data[1] = self.port;
}
}
pub type ScreenCapturePacket = Cdc2CommandPacket<USER_CDC, SYS_SCREEN_CAP, ScreenCapturePayload>;
pub type ScreenCaptureReplyPacket = Cdc2ReplyPacket<USER_CDC, SYS_SCREEN_CAP, ()>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct ScreenCapturePayload {
pub layer: Option<u8>,
}
impl Encode for ScreenCapturePayload {
fn size(&self) -> usize {
if self.layer.is_some() { 1 } else { 0 }
}
fn encode(&self, data: &mut [u8]) {
if let Some(layer) = self.layer {
data[0] = layer;
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u8)]
pub enum DeviceType {
NoSensor = 0,
Motor = 2,
Led = 3,
AbsEncoder = 4,
CrMotor = 5,
Imu = 6,
DistanceSensor = 7,
Radio = 8,
TetheredController = 9,
Brain = 10,
VisionSensor = 11,
AdiExpander = 12,
Res1Sensor = 13,
Battery = 14,
Res3Sensor = 15,
OpticalSensor = 16,
Magnet = 17,
GpsSensor = 20,
AicameraSensor = 26,
LightTower = 27,
ArmDevice = 28,
AiVisionSensor = 29,
Pneumatic = 30,
BumperSensor = 0x40,
GyroSensor = 0x46,
SonarSensor = 0x47,
GenericSensor = 128,
GenericSerial = 129,
UndefinedSensor = 255,
}
impl Decode for DeviceType {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let value = u8::decode(data)?;
Ok(match value {
0 => DeviceType::NoSensor,
2 => DeviceType::Motor,
3 => DeviceType::Led,
4 => DeviceType::AbsEncoder,
5 => DeviceType::CrMotor,
6 => DeviceType::Imu,
7 => DeviceType::DistanceSensor,
8 => DeviceType::Radio,
9 => DeviceType::TetheredController,
10 => DeviceType::Brain,
11 => DeviceType::VisionSensor,
12 => DeviceType::AdiExpander,
13 => DeviceType::Res1Sensor,
14 => DeviceType::Battery,
15 => DeviceType::Res3Sensor,
16 => DeviceType::OpticalSensor,
17 => DeviceType::Magnet,
20 => DeviceType::GpsSensor,
26 => DeviceType::AicameraSensor,
27 => DeviceType::LightTower,
28 => DeviceType::ArmDevice,
29 => DeviceType::AiVisionSensor,
30 => DeviceType::Pneumatic,
0x40 => DeviceType::BumperSensor,
0x46 => DeviceType::GyroSensor,
0x47 => DeviceType::SonarSensor,
128 => DeviceType::GenericSensor,
129 => DeviceType::GenericSerial,
255 => DeviceType::UndefinedSensor,
_ => {
return Err(DecodeError::new::<Self>(DecodeErrorKind::UnexpectedByte {
name: "DeviceType",
value,
expected: &[
0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 26, 27, 28,
29, 30, 64, 70, 71, 128, 129, 255,
],
}));
}
})
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct DeviceStatus {
pub port: u8,
pub device_type: DeviceType,
pub status: u8,
pub beta_version: u8,
pub version: u16,
pub boot_version: u16,
}
impl Decode for DeviceStatus {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let port = u8::decode(data)?;
let device_type = DeviceType::decode(data)?;
let status = u8::decode(data)?;
let beta_version = u8::decode(data)?;
let version = u16::decode(data)?;
let boot_version = u16::decode(data)?;
Ok(Self {
port,
device_type,
status,
beta_version,
version,
boot_version,
})
}
}
pub type DeviceStatusPacket = Cdc2CommandPacket<USER_CDC, DEV_STATUS, ()>;
pub type DeviceStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, DEV_STATUS, DeviceStatusReplyPayload>;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DeviceStatusReplyPayload {
pub count: u8,
pub devices: Vec<DeviceStatus>,
}
impl Decode for DeviceStatusReplyPayload {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let count = u8::decode(data)?;
let devices = Vec::decode_with_len(data, count as _)?;
Ok(Self { count, devices })
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FdtStatus {
pub count: u8,
pub files: Vec<Fdt>,
}
impl Decode for FdtStatus {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let count = u8::decode(data)?;
let entries = Vec::decode_with_len(data, count as _)?;
Ok(Self {
count,
files: entries,
})
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Fdt {
pub index: u8,
pub fdt_type: u8,
pub status: u8,
pub beta_version: u8,
pub version: u16,
pub boot_version: u16,
}
impl Decode for Fdt {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let index = u8::decode(data)?;
let fdt_type = u8::decode(data)?;
let status = u8::decode(data)?;
let beta_version = u8::decode(data)?;
let version = u16::decode(data)?;
let boot_version = u16::decode(data)?;
Ok(Self {
index,
fdt_type,
status,
beta_version,
version,
boot_version,
})
}
}
pub type FdtStatusPacket = Cdc2CommandPacket<USER_CDC, FDT_STATUS, ()>;
pub type FdtStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, FDT_STATUS, FdtStatus>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct RadioStatus {
pub device: u8,
pub quality: u16,
pub strength: i16,
pub channel: u8,
pub timeslot: u8,
}
impl Decode for RadioStatus {
fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
let device = u8::decode(data)?;
let quality = u16::decode(data)?;
let strength = i16::decode(data)?;
let channel = u8::decode(data)?;
let timeslot = u8::decode(data)?;
Ok(Self {
device,
quality,
strength,
channel,
timeslot,
})
}
}
pub type RadioStatusPacket = Cdc2CommandPacket<USER_CDC, RADIO_STATUS, ()>;
pub type RadioStatusReplyPacket = Cdc2ReplyPacket<USER_CDC, RADIO_STATUS, RadioStatus>;