Skip to content

Commit

Permalink
Merge pull request #12 from fmckeogh/embassy_bentwire_changes
Browse files Browse the repository at this point in the history
  • Loading branch information
fmckeogh authored May 7, 2024
2 parents 30027aa + 5b298ed commit 58f8f32
Show file tree
Hide file tree
Showing 9 changed files with 1,182 additions and 394 deletions.
32 changes: 26 additions & 6 deletions fusb302b/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
use {
crate::{
registers::{
Control1, Control3, Mask1, MaskA, MaskB, Power, Register, Registers, Reset, Slice,
Switches0, Switches1,
Control0, Control1, Control3, Mask1, MaskA, MaskB, Power, Register, Registers, Reset,
Slice, Switches0, Switches1,
},
timeout::Timeout,
},
defmt::{debug, trace, warn},
defmt::{debug, warn},
embassy_time::{Duration, Instant},
embedded_hal_async::i2c::I2c,
usb_pd::{
header::{ControlMessageType, Header, MessageType},
message::Message,
messages::Message,
sink::{Driver as SinkDriver, DriverState},
token::Token,
CcPin,
Expand Down Expand Up @@ -126,6 +126,19 @@ impl<I2C: I2c> SinkDriver for Fusb302b<I2C> {
.set_mask_b(MaskB::default().with_m_gcrcsent(true))
.await;

self.registers
.set_control0(Control0::default().with_int_mask(false).with_host_cur(01))
.await;
self.registers
.set_control3(
Control3::default()
.with_send_hard_reset(true)
.with_auto_hardreset(true)
.with_auto_softreset(true)
.with_auto_retry(true)
.with_n_retries(3),
)
.await;
self.state = State::Measuring { cc_pin: CcPin::CC1 };
self.message = None;
self.did_change_protocol = false;
Expand Down Expand Up @@ -345,7 +358,7 @@ impl<I2C: I2c> Fusb302b<I2C> {

let message = Message::parse(Header(header), &payload[..]);

trace!("{:?}, {:x}:{:x}", message, header, payload);
debug!("{:?}, {:x}:{:x}", message, header, payload);

if self.message.replace(message).is_some() {
panic!("pending message already set");
Expand Down Expand Up @@ -383,7 +396,14 @@ impl<I2C: I2c> Fusb302b<I2C> {

// Enable automatic retries
self.registers
.set_control3(Control3::default().with_auto_retry(true).with_n_retries(3))
.set_control3(
Control3::default()
.with_send_hard_reset(true)
.with_auto_hardreset(true)
.with_auto_softreset(true)
.with_auto_retry(true)
.with_n_retries(3),
)
.await;

// Enable interrupts for CC activity and CRC_CHK
Expand Down
3 changes: 2 additions & 1 deletion pd-interceptor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use {
fusb302b::Fusb302b,
panic_probe as _,
usb_pd::{
pdo::PowerDataObject,
messages::pdo::PowerDataObject,
sink::{Event, Request, Sink},
},
};
Expand Down Expand Up @@ -132,6 +132,7 @@ fn handle_event(event: Event) -> Option<Request> {
Event::ProtocolChanged => info!("protocol changed"),
Event::PowerAccepted => info!("power accepted"),
Event::PowerRejected => info!("power rejected"),
_ => todo!(),
}

None
Expand Down
4 changes: 2 additions & 2 deletions usb-pd/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![no_std]

pub mod header;
pub mod message;
pub mod pdo;
pub mod messages;
pub mod sink;
pub mod source;
pub mod timers;
pub mod token;

#[derive(Clone, Copy, PartialEq, Eq)]
Expand Down
37 changes: 22 additions & 15 deletions usb-pd/src/message.rs → usb-pd/src/messages/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
pub mod pdo;
pub mod vdo;

use {
crate::{
header::{ControlMessageType, DataMessageType, Header, MessageType},
pdo::{
AugmentedPowerDataObject, AugmentedPowerDataObjectRaw, Battery,
EPRAdjustableVoltageSupply, FixedSupply, PowerDataObject, PowerDataObjectRaw,
SPRProgrammablePowerSupply, VDMHeader, VDMHeaderRaw, VDMHeaderStructured,
VDMHeaderUnstructured, VDMType, VariableSupply,
},
},
crate::header::{ControlMessageType, DataMessageType, Header, MessageType},
byteorder::{ByteOrder, LittleEndian},
defmt::{trace, warn, Format},
heapless::Vec,
pdo::{
AugmentedPowerDataObject, AugmentedPowerDataObjectRaw, Battery, EPRAdjustableVoltageSupply,
FixedSupply, PowerDataObject, PowerDataObjectRaw, SPRProgrammablePowerSupply,
VariableSupply,
},
vdo::{VDMHeader, VDMHeaderRaw, VDMHeaderStructured, VDMHeaderUnstructured, VDMType},
};

#[derive(Debug, Clone, Format)]
Expand All @@ -19,7 +20,7 @@ pub enum Message {
Reject,
Ready,
SourceCapabilities(Vec<PowerDataObject, 8>),
VendorDefined(VDMHeader), // TODO: Incomplete
VendorDefined((VDMHeader, Vec<u32, 7>)), // TODO: Incomplete
SoftReset,
Unknown,
}
Expand Down Expand Up @@ -57,9 +58,9 @@ impl Message {
),
MessageType::Data(DataMessageType::VendorDefined) => {
// Keep for now...
// let len = payload.len();
// let num_obj = header.num_objects();
//debug!("VENDOR: {:?}, {:?}, {:?}", len, num_obj, payload);
let len = payload.len();
let num_obj = header.num_objects();
trace!("VENDOR: {:?}, {:?}, {:x}", len, num_obj, payload);

let header = {
let raw = VDMHeaderRaw(LittleEndian::read_u32(&payload[..4]));
Expand All @@ -71,7 +72,13 @@ impl Message {
}
};

trace!("VDM RX: {:?}", header);
let data = payload[4..]
.chunks_exact(4)
.take(7)
.map(|buf| LittleEndian::read_u32(buf))
.collect::<Vec<u32, 7>>();

trace!("VDM RX: {:?} {:?}", header, data);
// trace!("HEADER: VDM:: TYPE: {:?}, VERS: {:?}", header.vdm_type(),
// header.vdm_version()); trace!("HEADER: CMD:: TYPE: {:?}, CMD:
// {:?}", header.command_type(), header.command());
Expand All @@ -83,7 +90,7 @@ impl Message {
// .map(|i| i[0])
// .collect::<Vec<u8, 8>>();

Message::VendorDefined(header)
Message::VendorDefined((header, data))
}
_ => {
warn!("unknown message type");
Expand Down
206 changes: 206 additions & 0 deletions usb-pd/src/messages/pdo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
use {
byteorder::{ByteOrder, LittleEndian},
defmt::Format,
proc_bitfield::bitfield,
};

#[derive(Clone, Copy, Debug, Format)]
pub enum PowerDataObject {
FixedSupply(FixedSupply),
Battery(Battery),
VariableSupply(VariableSupply),
AugmentedPowerDataObject(AugmentedPowerDataObject),
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct PowerDataObjectRaw(pub u32): Debug, FromRaw, IntoRaw {
pub kind: u8 @ 30..=31,
}
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct FixedSupply(pub u32): Debug, FromRaw, IntoRaw {
/// Fixed supply
pub kind: u8 @ 30..=31,
/// Dual-role power
pub dual_role_power: bool @ 29,
/// USB suspend supported
pub usb_suspend_supported: bool @ 28,
/// Unconstrained power
pub unconstrained_power: bool @ 27,
/// USB communications capable
pub usb_communications_capable: bool @ 26,
/// Dual-role data
pub dual_role_data: bool @ 25,
/// Unchunked extended messages supported
pub unchunked_extended_messages_supported: bool @ 24,
/// EPR mode capable
pub epr_mode_capable: bool @ 23,
/// Peak current
pub peak_current: u8 @ 20..=21,
/// Voltage in 50mV units
pub voltage: u16 @ 10..=19,
/// Maximum current in 10mA units
pub max_current: u16 @ 0..=9,
}
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct Battery(pub u32): Debug, FromRaw, IntoRaw {
/// Battery
pub kind: u8 @ 30..=31,
/// Maximum Voltage in 50mV units
pub max_voltage: u16 @ 20..=29,
/// Minimum Voltage in 50mV units
pub min_voltage: u16 @ 10..=19,
/// Maximum Allowable Power in 250mW units
pub max_power: u16 @ 0..=9,
}
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct VariableSupply(pub u32): Debug, FromRaw, IntoRaw {
/// Variable supply (non-battery)
pub kind: u8 @ 30..=31,
/// Maximum Voltage in 50mV units
pub max_voltage: u16 @ 20..=29,
/// Minimum Voltage in 50mV units
pub min_voltage: u16 @ 10..=19,
/// Maximum current in 10mA units
pub max_current: u16 @ 0..=9,
}
}

#[derive(Clone, Copy, Debug, Format)]
pub enum AugmentedPowerDataObject {
SPR(SPRProgrammablePowerSupply),
EPR(EPRAdjustableVoltageSupply),
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct AugmentedPowerDataObjectRaw(pub u32): Debug, FromRaw, IntoRaw {
/// Augmented power data object
pub kind: u8 @ 30..=31,
pub supply: u8 @ 28..=29,
pub power_capabilities: u32 @ 0..=27,
}
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct SPRProgrammablePowerSupply(pub u32): Debug, FromRaw, IntoRaw {
/// Augmented power data object
pub kind: u8 @ 30..=31,
/// SPR programmable power supply
pub supply: u8 @ 28..=29,
pub pps_power_limited: bool @ 27,
/// Maximum voltage in 100mV increments
pub max_voltage: u8 @ 17..=24,
/// Minimum Voltage in 100mV increments
pub min_voltage: u8 @ 8..=15,
/// Maximum Current in 50mA increments
pub maximum_current: u8 @ 0..=6,
}
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct EPRAdjustableVoltageSupply(pub u32): Debug, FromRaw, IntoRaw {
/// Augmented power data object
pub kind: u8 @ 30..=31,
/// EPR adjustable voltage supply
pub supply: u8 @ 28..=29,
pub peak_current: u8 @ 26..=27,
/// Maximum voltage in 100mV increments
pub max_voltage: u16 @ 17..=25,
/// Minimum Voltage in 100mV increments
pub min_voltage: u8 @ 8..=15,
/// PDP in 1W increments
pub maximum_current: u8 @ 0..=7,
}
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct FixedVariableRequestDataObject(pub u32): Debug, FromRaw, IntoRaw {
/// Valid range 1..=14
pub object_position: u8 @ 28..=31,
pub giveback_flag: bool @ 27,
pub capability_mismatch: bool @ 26,
pub usb_communications_capable: bool @ 25,
pub no_usb_suspend: bool @ 24,
pub unchunked_extended_messages_supported: bool @ 23,
pub epr_mode_capable: bool @ 22,
pub operating_current: u16 @ 10..=19,
pub maximum_operating_current: u16 @ 0..=9,
}
}

impl FixedVariableRequestDataObject {
pub fn to_bytes(&self, buf: &mut [u8]) {
LittleEndian::write_u32(buf, self.0);
}
}

bitfield! {
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct BatteryRequestDataObject(pub u32): FromRaw, IntoRaw {
/// Object position (0000b and 1110b…1111b are Reserved and Shall Not be used)
pub object_position: u8 @ 28..=31,
/// GiveBackFlag = 0
pub giveback_flag: bool @ 27,
/// Capability mismatch
pub capability_mismatch: bool @ 26,
/// USB communications capable
pub usb_communications_capable: bool @ 25,
/// No USB Suspend
pub no_usb_suspend: bool @ 24,
/// Unchunked extended messages supported
pub unchunked_extended_messages_supported: bool @ 23,
/// EPR mode capable
pub epr_mode_capable: bool @ 22,
/// Operating power in 250mW units
pub operating_power: u16 @ 10..=19,
/// Maximum operating power in 250mW units
pub maximum_operating_power: u16 @ 0..=9,
}
}

impl BatteryRequestDataObject {
pub fn to_bytes(&self, buf: &mut [u8]) {
LittleEndian::write_u32(buf, self.0);
}
}

bitfield!(
#[derive(Clone, Copy, PartialEq, Eq, Format)]
pub struct PPSRequestDataObject(pub u32): FromRaw, IntoRaw {
/// Object position (0000b and 1110b…1111b are Reserved and Shall Not be used)
pub object_position: u8 @ 28..=31,
/// Capability mismatch
pub capability_mismatch: bool @ 26,
/// USB communications capable
pub usb_communications_capable: bool @ 25,
/// No USB Suspend
pub no_usb_suspend: bool @ 24,
/// Unchunked extended messages supported
pub unchunked_extended_messages_supported: bool @ 23,
/// EPR mode capable
pub epr_mode_capable: bool @ 22,
/// Output voltage in 20mV units
pub output_voltage: u16 @ 9..=20,
/// Operating current in 50mA units
pub operating_current: u16 @ 0..=6,
}
);

impl PPSRequestDataObject {
pub fn to_bytes(&self, buf: &mut [u8]) {
LittleEndian::write_u32(buf, self.0);
}
}
Loading

0 comments on commit 58f8f32

Please sign in to comment.