use crate::{probe::WchLinkVariant, RiscvChip};
use super::*;
#[derive(Debug)]
pub struct GetProbeInfo;
impl Command for GetProbeInfo {
type Response = ProbeInfo;
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
vec![0x01]
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct ProbeInfo {
pub major_version: u8,
pub minor_version: u8,
pub variant: WchLinkVariant,
}
impl ProbeInfo {
pub fn version(&self) -> (u8, u8) {
(self.major_version, self.minor_version)
}
}
impl Response for ProbeInfo {
fn from_payload(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 3 {
return Err(crate::error::Error::InvalidPayloadLength);
}
Ok(Self {
major_version: bytes[0],
minor_version: bytes[1],
variant: if bytes.len() == 4 {
WchLinkVariant::try_from_u8(bytes[2])?
} else {
WchLinkVariant::Ch549
},
})
}
}
impl fmt::Display for ProbeInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"WCH-Link v{}.{}(v{}) ({})",
self.major_version,
self.minor_version,
self.major_version * 10 + self.minor_version,
self.variant
)
}
}
#[derive(Debug)]
pub struct AttachChip;
impl Command for AttachChip {
type Response = AttachChipResponse;
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
vec![0x02]
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct AttachChipResponse {
pub chip_family: RiscvChip,
pub riscvchip: u8,
pub chip_id: u32,
}
impl Response for AttachChipResponse {
fn from_payload(bytes: &[u8]) -> Result<Self> {
if bytes.len() != 5 {
return Err(Error::InvalidPayloadLength);
}
Ok(Self {
chip_family: RiscvChip::try_from_u8(bytes[0])?,
riscvchip: bytes[0],
chip_id: u32::from_be_bytes(bytes[1..5].try_into().unwrap()),
})
}
}
impl fmt::Display for AttachChipResponse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.chip_id == 0 {
write!(f, "{:?}", self.chip_family)
} else if let Some(chip_name) = crate::chips::chip_id_to_chip_name(self.chip_id) {
write!(
f,
"{:?} [{}] (ChipID: 0x{:08x})",
self.chip_family, chip_name, self.chip_id
)
} else {
write!(f, "{:?} (ChipID: 0x{:08x})", self.chip_family, self.chip_id)
}
}
}
#[derive(Debug)]
pub enum EraseCodeFlash {
ByPinRST(RiscvChip),
ByPowerOff(RiscvChip),
}
impl Command for EraseCodeFlash {
type Response = ();
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
match self {
EraseCodeFlash::ByPinRST(c) => vec![0x08, *c as u8],
EraseCodeFlash::ByPowerOff(c) => vec![0x0f, *c as u8],
}
}
}
#[derive(Debug)]
pub struct GetChipRomRamSplit;
impl Command for GetChipRomRamSplit {
type Response = u8;
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
vec![0x04]
}
}
#[derive(Debug)]
pub struct SetChipRomRamSplit(u8);
impl Command for SetChipRomRamSplit {
type Response = ();
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
vec![0x05, self.0]
}
}
#[derive(Debug)]
pub struct OptEnd;
impl Command for OptEnd {
type Response = ();
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
vec![0xff]
}
}
#[derive(clap::Subcommand, PartialEq, Clone, Copy, Debug)]
pub enum SetPower {
Enable3v3,
Disable3v3,
Enable5v,
Disable5v,
}
impl Command for SetPower {
type Response = ();
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
match self {
SetPower::Enable3v3 => vec![0x09],
SetPower::Disable3v3 => vec![0x0A],
SetPower::Enable5v => vec![0x0B],
SetPower::Disable5v => vec![0x0C],
}
}
}
#[derive(Debug)]
pub struct SetSdiPrintEnabled(pub bool);
impl Command for SetSdiPrintEnabled {
type Response = u8;
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
if self.0 {
vec![0xee, 0x00]
} else {
vec![0xee, 0x01]
}
}
}
#[derive(Debug)]
pub enum SetRSTPin {
Low,
High,
Floating,
}
impl Command for SetRSTPin {
type Response = ();
const COMMAND_ID: u8 = 0x0d;
fn payload(&self) -> Vec<u8> {
let subcmd = match *self {
SetRSTPin::Low => 0x13,
SetRSTPin::High => 0x14,
SetRSTPin::Floating => 0x15,
};
vec![0x0e, subcmd]
}
}