pub const CMD_SPI_STREAM: u8 = 0xA8;
pub const CMD_I2C_STREAM: u8 = 0xAA;
pub const CMD_UIO_STREAM: u8 = 0xAB;
pub const CMD_I2C_STM_END: u8 = 0x00;
pub const CMD_GET_STATUS: u8 = 0xA1;
pub mod i2c_sub {
pub const START: u8 = 0x74;
pub const STOP: u8 = 0x75;
pub const OUT: u8 = 0x80;
pub const IN: u8 = 0xC0;
pub const SET: u8 = 0x60;
pub const END: u8 = 0x00;
}
pub const CMD_UIO_STM_OUT: u8 = 0x80;
pub const CMD_UIO_STM_DIR: u8 = 0x40;
pub const CMD_UIO_STM_END: u8 = 0x20;
pub const CMD_UIO_STM_US: u8 = 0xC0;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum SpiSpeed {
Speed208K = 0,
Speed100K = 1,
Speed400K = 2,
Speed750K = 3,
Speed1_5M = 4,
#[default]
Medium = 5,
Speed6M = 6,
Speed12M = 7,
}
impl SpiSpeed {
pub fn from_u8(value: u8) -> Self {
match value {
0 => Self::Speed208K,
1 => Self::Speed100K,
2 => Self::Speed400K,
3 => Self::Speed750K,
4 => Self::Speed1_5M,
5 => Self::Medium,
6 => Self::Speed6M,
7 => Self::Speed12M,
_ => Self::default(),
}
}
pub fn description(&self) -> &'static str {
match self {
Self::Speed208K => "~21 kHz",
Self::Speed100K => "~100 kHz",
Self::Speed400K => "~400 kHz",
Self::Speed750K => "~750 kHz",
Self::Speed1_5M => "~1.5 MHz",
Self::Medium => "~3 MHz",
Self::Speed6M => "~6 MHz",
Self::Speed12M => "~12 MHz",
}
}
}
pub mod pins {
pub const CS: u8 = 0;
pub const CLK: u8 = 1;
pub const DIN: u8 = 2;
pub const DOUT: u8 = 3;
pub const D4: u8 = 4;
pub const D5: u8 = 5;
}
pub fn build_set_mode_cmd(speed: SpiSpeed) -> Vec<u8> {
vec![
CMD_UIO_STREAM,
CMD_UIO_STM_OUT | 0x37, CMD_UIO_STM_DIR | 0x3B, CMD_UIO_STM_US | (speed as u8),
CMD_UIO_STM_END,
]
}
pub fn build_uio_out_cmd(outputs: u8) -> Vec<u8> {
vec![
CMD_UIO_STREAM,
CMD_UIO_STM_OUT | (outputs & 0x3F),
CMD_UIO_STM_END,
]
}
pub fn build_cs_cmd(active: bool) -> Vec<u8> {
let output_byte = if active {
0x36 } else {
0x37 };
vec![
CMD_UIO_STREAM,
CMD_UIO_STM_OUT | output_byte,
CMD_UIO_STM_END,
]
}
pub fn build_spi_transfer_cmd(data: &[u8]) -> Vec<u8> {
let mut cmd = Vec::with_capacity(data.len() + 1);
cmd.push(CMD_SPI_STREAM);
cmd.extend_from_slice(data);
cmd
}
pub fn build_gpio_cmd(pin: u8, level: bool, current_outputs: u8) -> Vec<u8> {
let mask = 1u8 << pin;
let new_outputs = if level {
current_outputs | mask
} else {
current_outputs & !mask
};
vec![
CMD_UIO_STREAM,
CMD_UIO_STM_OUT | (new_outputs & 0x3F),
CMD_UIO_STM_END,
]
}
pub const MAX_SPI_TRANSFER_SIZE: usize = 32;
pub const MAX_USB_BULK_SIZE: usize = 4096;
pub const MAX_SPI_STREAM_SIZE: usize = MAX_USB_BULK_SIZE - 1;
pub fn chunk_transfer(data: &[u8]) -> impl Iterator<Item = &[u8]> {
data.chunks(MAX_SPI_TRANSFER_SIZE)
}
pub fn chunk_transfer_bulk(data: &[u8]) -> impl Iterator<Item = &[u8]> {
data.chunks(MAX_SPI_STREAM_SIZE)
}
pub fn build_spi_stream_cmd(len: usize) -> Vec<u8> {
let mut cmd = Vec::with_capacity(len + 1);
cmd.push(CMD_SPI_STREAM);
cmd.resize(len + 1, 0xFF);
cmd
}