pub mod chunked;
pub mod extended_control;
use byteorder::{ByteOrder, LittleEndian};
use heapless::Vec;
use proc_bitfield::bitfield;
use crate::protocol_layer::message::data::sink_capabilities::SinkPowerDataObject;
use crate::protocol_layer::message::data::source_capabilities::PowerDataObject;
#[derive(Debug, Clone)]
#[non_exhaustive]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(unused)]
pub enum Extended {
SourceCapabilitiesExtended,
ExtendedControl(extended_control::ExtendedControl),
EprSourceCapabilities(Vec<PowerDataObject, 16>),
EprSinkCapabilities(Vec<SinkPowerDataObject, 7>),
Unknown,
}
impl Extended {
pub fn data_size(&self) -> u16 {
match self {
Self::SourceCapabilitiesExtended => 0,
Self::ExtendedControl(_payload) => 2,
Self::EprSourceCapabilities(pdos) => (pdos.len() * core::mem::size_of::<u32>()) as u16,
Self::EprSinkCapabilities(pdos) => (pdos.len() * core::mem::size_of::<u32>()) as u16,
Self::Unknown => 0,
}
}
pub fn to_bytes(&self, payload: &mut [u8]) -> usize {
match self {
Self::Unknown => 0,
Self::SourceCapabilitiesExtended => unimplemented!(),
Self::ExtendedControl(control) => control.to_bytes(payload),
Self::EprSourceCapabilities(pdos) => {
let mut written = 0;
for pdo in pdos {
let raw = match pdo {
PowerDataObject::FixedSupply(p) => p.0,
PowerDataObject::Battery(p) => p.0,
PowerDataObject::VariableSupply(p) => p.0,
PowerDataObject::Augmented(a) => match a {
crate::protocol_layer::message::data::source_capabilities::Augmented::Spr(p) => p.0,
crate::protocol_layer::message::data::source_capabilities::Augmented::Epr(p) => p.0,
crate::protocol_layer::message::data::source_capabilities::Augmented::Unknown(p) => *p,
},
PowerDataObject::Unknown(p) => p.0,
};
LittleEndian::write_u32(&mut payload[written..written + 4], raw);
written += 4;
}
written
}
Self::EprSinkCapabilities(pdos) => {
let mut written = 0;
for pdo in pdos {
LittleEndian::write_u32(&mut payload[written..written + 4], pdo.to_raw());
written += 4;
}
written
}
}
}
}
bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ExtendedHeader(pub u16): Debug, FromStorage, IntoStorage {
pub data_size: u16 @ 0..=8,
pub request_chunk: bool @ 10,
pub chunk_number: u8 @ 11..=14,
pub chunked: bool @ 15,
}
}
impl ExtendedHeader {
pub fn new(data_size: u16) -> Self {
Self(0).with_data_size(data_size)
}
pub fn to_bytes(self, buf: &mut [u8]) -> usize {
LittleEndian::write_u16(buf, self.0);
2
}
pub fn from_bytes(buf: &[u8]) -> Self {
assert!(buf.len() >= 2);
Self(LittleEndian::read_u16(buf))
}
}