use crate::commands::McpCommand;
#[derive(Debug, Clone, Copy)]
pub struct I2cStatus {
pub communication_state: I2cCommunicationState,
pub transfer_requested_length: u16,
pub transfer_completed_length: u16,
pub internal_data_buffer_counter: u8,
pub bus_speed: I2cSpeed,
pub timeout_value: u8,
pub target_address: u16,
pub target_acknowledged_address: bool,
pub scl_line_high: bool,
pub sda_line_high: bool,
pub read_pending_value: u8,
}
#[derive(Debug, Clone, Copy)]
pub enum I2cCommunicationState {
Idle,
StartTimeout,
RepeatedStartTimeout,
WriteAddressWaitSend,
AddressTimeout,
AddressNack,
WriteDataTimeout,
WriteDataEndNoStop,
ReadDataTimeout,
StopTimeout,
Other(u8),
}
impl I2cCommunicationState {
pub fn is_idle(&self) -> bool {
matches!(self, Self::Idle)
}
}
#[doc(hidden)]
impl From<u8> for I2cCommunicationState {
fn from(value: u8) -> Self {
match value {
0x00 => Self::Idle,
0x12 => Self::StartTimeout,
0x17 => Self::RepeatedStartTimeout,
0x21 => Self::WriteAddressWaitSend,
0x23 => Self::AddressTimeout,
0x25 => Self::AddressNack,
0x44 => Self::WriteDataTimeout,
0x45 => Self::WriteDataEndNoStop,
0x52 => Self::ReadDataTimeout,
0x62 => Self::StopTimeout,
n => Self::Other(n),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum I2cCancelTransferResponse {
Done,
MarkedForCancellation,
NoTransfer,
}
#[derive(Debug, Clone, Copy)]
pub struct I2cSpeed(
u32,
);
impl I2cSpeed {
const MCP_CLOCK: u32 = 12_000_000;
const MAX_SPEED: u32 = 400_000;
const MIN_SPEED: u32 = Self::divider_to_speed(255);
const FAST_DIVIDER: u8 = Self::speed_to_divider(400_000);
const STANDARD_DIVIDER: u8 = Self::speed_to_divider(100_000);
const fn speed_to_divider(speed: u32) -> u8 {
((Self::MCP_CLOCK / speed) - 2) as u8
}
const fn divider_to_speed(divider: u8) -> u32 {
Self::MCP_CLOCK / (divider as u32 + 2)
}
pub(crate) fn to_clock_divider(self) -> u8 {
match self.0 {
400_000 => Self::FAST_DIVIDER,
100_000 => Self::STANDARD_DIVIDER,
speed => Self::speed_to_divider(speed),
}
}
pub fn fast_400k() -> Self {
Self(400_000)
}
pub fn standard_100k() -> Self {
Self(100_000)
}
pub fn new(speed: u32) -> Self {
let speed = speed.clamp(Self::MIN_SPEED, Self::MAX_SPEED);
Self(speed)
}
pub fn speed(&self) -> u32 {
self.0
}
}
#[doc(hidden)]
impl From<u8> for I2cSpeed {
fn from(divider: u8) -> Self {
Self::new(Self::divider_to_speed(divider))
}
}
pub(crate) trait I2cAddressing {
fn into_read_address(self) -> u8;
fn into_write_address(self) -> u8;
}
impl I2cAddressing for u8 {
fn into_read_address(self) -> u8 {
(self << 1) + 1
}
fn into_write_address(self) -> u8 {
self << 1
}
}
pub(crate) enum ReadType {
Normal,
RepeatedStart,
}
impl From<ReadType> for McpCommand {
fn from(value: ReadType) -> Self {
match value {
ReadType::Normal => McpCommand::I2cReadData,
ReadType::RepeatedStart => McpCommand::I2cReadDataRepeatedStart,
}
}
}
pub(crate) enum WriteType {
Normal,
RepeatedStart,
NoStop,
}
impl From<WriteType> for McpCommand {
fn from(value: WriteType) -> Self {
match value {
WriteType::Normal => McpCommand::I2cWriteData,
WriteType::RepeatedStart => McpCommand::I2cWriteDataRepeatedStart,
WriteType::NoStop => McpCommand::I2cWriteDataNoStop,
}
}
}