Skip to content

Commit

Permalink
adds pwm control
Browse files Browse the repository at this point in the history
  • Loading branch information
Piet Geursen committed Oct 16, 2023
1 parent 544549e commit e3653fe
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 13 deletions.
6 changes: 6 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ pub static CMD_W_CONF_A: [u8; 4] = [0x00, 0x1, 0x3D, 0x6E];

/// Precomputed write command for configuration register group B
pub static CMD_W_CONF_B: [u8; 4] = [0x00, 0x24, 0xB1, 0x9E];

/// Precomputed write command for configuration register group B
pub static CMD_W_PWM: [u8; 4] = [0x00, 0x20, 0x00, 0x00];

/// Precomputed read command for configuration register group B
pub static CMD_R_PWM: [u8; 4] = [0x00, 0x22, 0x9D, 0x56];
16 changes: 16 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
//!
use core::fmt::{Display, Formatter};

pub trait ConfigurationRegisters {
fn register_a(&self) -> [u8; 6];

fn register_b(&self) -> Option<[u8; 6]>;
}

/// Abstracted configuration of configuration register(s)
#[derive(Debug, Clone)]
pub struct Configuration {
Expand Down Expand Up @@ -333,6 +339,16 @@ impl Configuration {
}
}

impl ConfigurationRegisters for Configuration {
fn register_a(&self) -> [u8; 6] {
self.register_a
}

fn register_b(&self) -> Option<[u8; 6]> {
Some(self.register_b)
}
}

impl PartialEq<Self> for Configuration {
fn eq(&self, other: &Self) -> bool {
self.register_a == other.register_a && self.register_b == other.register_b
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub mod ltc6810;
pub mod ltc6811;
pub mod ltc6812;
pub mod ltc6813;
pub mod pwm;
pub mod monitor;

pub(crate) mod commands;
Expand Down
19 changes: 14 additions & 5 deletions src/ltc6810/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::config::{Cell, DischargeTimeout, VoltageOutOfRangeError, GPIO};
use crate::config::{Cell, ConfigurationRegisters, DischargeTimeout, VoltageOutOfRangeError, GPIO};

/// Abstracted configuration of configuration register(s)
#[derive(Debug, Clone)]
Expand All @@ -7,6 +7,16 @@ pub struct Configuration {
pub(crate) register_a: [u8; 6],
}

impl ConfigurationRegisters for Configuration {
fn register_a(&self) -> [u8; 6] {
self.register_a
}

fn register_b(&self) -> Option<[u8; 6]> {
None
}
}

impl Default for Configuration {
fn default() -> Self {
Self {
Expand All @@ -29,7 +39,7 @@ impl Configuration {
GPIO::GPIO1 => self.register_a[0] &= 0b1111_0111,
GPIO::GPIO2 => self.register_a[0] &= 0b1110_1111,
GPIO::GPIO3 => self.register_a[0] &= 0b1101_1111,
_ => unimplemented!("unsupported GPIO")
_ => unimplemented!("unsupported GPIO"),
}
}

Expand All @@ -39,7 +49,7 @@ impl Configuration {
GPIO::GPIO1 => self.register_a[0] |= 0b0000_1000,
GPIO::GPIO2 => self.register_a[0] |= 0b0001_0000,
GPIO::GPIO3 => self.register_a[0] |= 0b0010_0000,
_ => unimplemented!("unsupported GPIO")
_ => unimplemented!("unsupported GPIO"),
}
}

Expand Down Expand Up @@ -114,8 +124,7 @@ impl Configuration {
Cell::Cell4 => self.register_a[4] |= 0b0000_1000,
Cell::Cell5 => self.register_a[4] |= 0b0001_0000,
Cell::Cell6 => self.register_a[4] |= 0b0010_0000,
_ => unimplemented!("Unsupported cell")

_ => unimplemented!("Unsupported cell"),
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/ltc6810/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! Device-specific types for [LTC6810](<https://www.analog.com/en/products/ltc6810-1.html>)
use crate::commands::{
CMD_R_AUX_V_REG_A, CMD_R_AUX_V_REG_B, CMD_R_CELL_V_REG_A, CMD_R_CELL_V_REG_B, CMD_R_CONF_A, CMD_R_STATUS_A,
CMD_R_STATUS_B, CMD_W_CONF_A,
CMD_R_STATUS_B, CMD_W_CONF_A, CMD_W_PWM, CMD_R_PWM,
};
use crate::monitor::{
ADCMode, ChannelIndex, ChannelType, CommandTime, DeviceTypes, GroupedRegisterIndex, NoPolling, NoWriteCommandError,
Expand All @@ -13,7 +13,9 @@ use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;

pub mod config;
pub mod pwm;
pub use config::Configuration;
pub use pwm::Pwm;

/// Cell selection for ADC conversion
///
Expand Down Expand Up @@ -57,6 +59,7 @@ pub enum Register {
StatusA,
StatusB,
Configuration,
Pwm,
}

/// All conversion channels
Expand Down Expand Up @@ -96,6 +99,9 @@ impl DeviceTypes for LTC6810 {

const REG_CONF_A: Self::Register = Register::Configuration;
const REG_CONF_B: Option<Self::Register> = None;

const REG_PWM: Self::Register = Register::Pwm;

}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6810, L>
Expand Down Expand Up @@ -132,12 +138,14 @@ impl ToFullCommand for Register {
Register::StatusA => CMD_R_STATUS_A,
Register::StatusB => CMD_R_STATUS_B,
Register::Configuration => CMD_R_CONF_A,
Register::Pwm => CMD_R_PWM,
}
}

fn to_write_command(&self) -> Result<[u8; 4], NoWriteCommandError> {
match self {
Register::Configuration => Ok(CMD_W_CONF_A),
Register::Pwm => Ok(CMD_W_PWM),
_ => Err(NoWriteCommandError {}),
}
}
Expand Down Expand Up @@ -201,6 +209,7 @@ impl GroupedRegisterIndex for Register {
Register::StatusA => 0,
Register::StatusB => 1,
Register::Configuration => 0,
Register::Pwm => 0,
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/ltc6810/pwm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::pwm::{PwmRegisters, PwmDutyCycle};

#[derive(Default)]
pub struct Pwm{
pub(crate) register_a: [u8; 6],
}

impl Pwm{
pub fn set_duty_cycle(&mut self, pwm_duty_cycle: &PwmDutyCycle) {
let duty_cycle_bits = *pwm_duty_cycle as u8;
self.register_a[0] = (duty_cycle_bits << 4) | duty_cycle_bits;
self.register_a[1] = (duty_cycle_bits << 4) | duty_cycle_bits;
self.register_a[2] = (duty_cycle_bits << 4) | duty_cycle_bits;
}
}

impl PwmRegisters for Pwm{
fn register_a(&self) -> [u8;6] {
self.register_a
}
}
8 changes: 7 additions & 1 deletion src/ltc6811.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Device-specific types for [LTC6811](<https://www.analog.com/en/products/ltc6811-1.html>)
use crate::commands::{
CMD_R_AUX_V_REG_A, CMD_R_AUX_V_REG_B, CMD_R_CELL_V_REG_A, CMD_R_CELL_V_REG_B, CMD_R_CELL_V_REG_C,
CMD_R_CELL_V_REG_D, CMD_R_CONF_A, CMD_R_CONF_B, CMD_R_STATUS_A, CMD_R_STATUS_B, CMD_W_CONF_A, CMD_W_CONF_B,
CMD_R_CELL_V_REG_D, CMD_R_CONF_A, CMD_R_CONF_B, CMD_R_STATUS_A, CMD_R_STATUS_B, CMD_W_CONF_A, CMD_W_CONF_B, CMD_R_PWM, CMD_W_PWM,
};
use crate::monitor::{
ADCMode, ChannelIndex, ChannelType, CommandTime, DeviceTypes, GroupedRegisterIndex, NoPolling, NoWriteCommandError,
Expand Down Expand Up @@ -62,6 +62,7 @@ pub enum Register {
StatusB,
ConfigurationA,
ConfigurationB,
Pwm,
}

/// All conversion channels
Expand Down Expand Up @@ -107,6 +108,8 @@ impl DeviceTypes for LTC6811 {

const REG_CONF_A: Self::Register = Register::ConfigurationA;
const REG_CONF_B: Option<Self::Register> = Some(Register::ConfigurationB);
const REG_PWM: Self::Register = Register::Pwm;

}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6811, L>
Expand Down Expand Up @@ -146,13 +149,15 @@ impl ToFullCommand for Register {
Register::StatusB => CMD_R_STATUS_B,
Register::ConfigurationA => CMD_R_CONF_A,
Register::ConfigurationB => CMD_R_CONF_B,
Register::Pwm => CMD_R_PWM,
}
}

fn to_write_command(&self) -> Result<[u8; 4], NoWriteCommandError> {
match self {
Register::ConfigurationA => Ok(CMD_W_CONF_A),
Register::ConfigurationB => Ok(CMD_W_CONF_B),
Register::Pwm => Ok(CMD_W_PWM),
_ => Err(NoWriteCommandError {}),
}
}
Expand Down Expand Up @@ -219,6 +224,7 @@ impl GroupedRegisterIndex for Register {
Register::StatusB => 1,
Register::ConfigurationA => 0,
Register::ConfigurationB => 1,
Register::Pwm => 0,
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/ltc6812.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::commands::{
CMD_R_AUX_V_REG_A, CMD_R_AUX_V_REG_B, CMD_R_AUX_V_REG_C, CMD_R_AUX_V_REG_D, CMD_R_CELL_V_REG_A, CMD_R_CELL_V_REG_B,
CMD_R_CELL_V_REG_C, CMD_R_CELL_V_REG_D, CMD_R_CELL_V_REG_E, CMD_R_CONF_A, CMD_R_CONF_B, CMD_R_STATUS_A,
CMD_R_STATUS_B, CMD_W_CONF_A, CMD_W_CONF_B,
CMD_R_STATUS_B, CMD_W_CONF_A, CMD_W_CONF_B, CMD_R_PWM, CMD_W_PWM,
};
use crate::monitor::{
ADCMode, ChannelIndex, ChannelType, CommandTime, DeviceTypes, GroupedRegisterIndex, NoPolling, NoWriteCommandError,
Expand Down Expand Up @@ -70,6 +70,7 @@ pub enum Register {
StatusB,
ConfigurationA,
ConfigurationB,
Pwm,
}

/// All conversion channels
Expand Down Expand Up @@ -122,6 +123,7 @@ impl DeviceTypes for LTC6812 {

const REG_CONF_A: Self::Register = Register::ConfigurationA;
const REG_CONF_B: Option<Self::Register> = Some(Register::ConfigurationB);
const REG_PWM: Self::Register = Register::Pwm;
}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6812, L>
Expand Down Expand Up @@ -164,13 +166,15 @@ impl ToFullCommand for Register {
Register::StatusB => CMD_R_STATUS_B,
Register::ConfigurationA => CMD_R_CONF_A,
Register::ConfigurationB => CMD_R_CONF_B,
Register::Pwm => CMD_R_PWM,
}
}

fn to_write_command(&self) -> Result<[u8; 4], NoWriteCommandError> {
match self {
Register::ConfigurationA => Ok(CMD_W_CONF_A),
Register::ConfigurationB => Ok(CMD_W_CONF_B),
Register::Pwm => Ok(CMD_W_PWM),
_ => Err(NoWriteCommandError {}),
}
}
Expand Down Expand Up @@ -241,6 +245,8 @@ impl GroupedRegisterIndex for Register {
Register::StatusB => 1,
Register::ConfigurationA => 0,
Register::ConfigurationB => 1,
Register::Pwm => 0,

}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/ltc6813.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub enum Register {
StatusB,
ConfigurationA,
ConfigurationB,
Pwm,
}

/// All conversion channels
Expand Down Expand Up @@ -125,6 +126,8 @@ impl DeviceTypes for LTC6813 {

const REG_CONF_A: Self::Register = Register::ConfigurationA;
const REG_CONF_B: Option<Self::Register> = Some(Register::ConfigurationB);

const REG_PWM: Self::Register = Register::Pwm;
}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6813, L>
Expand Down Expand Up @@ -168,13 +171,15 @@ impl ToFullCommand for Register {
Register::StatusB => CMD_R_STATUS_B,
Register::ConfigurationA => CMD_R_CONF_A,
Register::ConfigurationB => CMD_R_CONF_B,
Register::Pwm => CMD_R_PWM,
}
}

fn to_write_command(&self) -> Result<[u8; 4], NoWriteCommandError> {
match self {
Register::ConfigurationA => Ok(CMD_W_CONF_A),
Register::ConfigurationB => Ok(CMD_W_CONF_B),
Register::Pwm => Ok(CMD_W_PWM),
_ => Err(NoWriteCommandError {}),
}
}
Expand Down Expand Up @@ -247,6 +252,8 @@ impl GroupedRegisterIndex for Register {
Register::StatusB => 1,
Register::ConfigurationA => 0,
Register::ConfigurationB => 1,
Register::Pwm => 0,

}
}
}
Expand Down
31 changes: 26 additions & 5 deletions src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,10 @@
//! // Digital power supply voltage in uV => 5.12 V
//! assert_eq!(5_120_000, data[0].digital_power);
//! ````
use crate::config::Configuration;
use crate::config::ConfigurationRegisters;
use crate::monitor::Error::TransferError;
use crate::pec15::PEC15;
use crate::pwm::PwmRegisters;
use core::fmt::{Debug, Display, Formatter};
use core::marker::PhantomData;
use core::slice::Iter;
Expand Down Expand Up @@ -558,6 +559,9 @@ pub trait DeviceTypes: Send + Sync + Sized + 'static {

/// Configuration register B, None in case device type has no second configuration register
const REG_CONF_B: Option<Self::Register>;

/// Cell pwm discharge register
const REG_PWM: Self::Register;
}

/// Public LTC681X client interface
Expand Down Expand Up @@ -614,7 +618,10 @@ pub trait LTC681XClient<T: DeviceTypes, const L: usize> {
fn write_register(&mut self, register: T::Register, data: [[u8; 6]; L]) -> Result<(), Self::Error>;

/// Writes the configuration, one array item per device in daisy chain
fn write_configuration(&mut self, config: [Configuration; L]) -> Result<(), Self::Error>;
fn write_configuration<C: ConfigurationRegisters>(&mut self, config: [C; L]) -> Result<(), Self::Error>;

/// Writes the pwm dutycycles, one array item per device in daisy chain
fn write_pwm<P: PwmRegisters>(&mut self, pwm: [P; L]) -> Result<(), Self::Error>;

/// Reads and returns the conversion result (voltages) of Cell or GPIO group
/// Returns one vector for each device in daisy chain
Expand Down Expand Up @@ -792,13 +799,15 @@ where
}

/// See [LTC681XClient::read_cell_voltages](LTC681XClient#tymethod.write_configuration)
fn write_configuration(&mut self, config: [Configuration; L]) -> Result<(), Self::Error> {
fn write_configuration<C: ConfigurationRegisters>(&mut self, config: [C; L]) -> Result<(), Self::Error> {
let mut register_a = [[0x0u8; 6]; L];
let mut register_b = [[0x0u8; 6]; L];

for item in config.iter().enumerate() {
register_a[item.0] = item.1.register_a;
register_b[item.0] = item.1.register_b;
register_a[item.0] = item.1.register_a();
if let Some(reg) = item.1.register_b() {
register_b[item.0] = reg;
}
}

self.write_register(T::REG_CONF_A, register_a)?;
Expand Down Expand Up @@ -900,6 +909,18 @@ where

Ok(parameters)
}

fn write_pwm<PWM: PwmRegisters>(&mut self, pwm: [PWM; L]) -> Result<(), Self::Error> {
let mut register_a = [[0x0u8; 6]; L];

for item in pwm.iter().enumerate() {
register_a[item.0] = item.1.register_a();
}

self.write_register(T::REG_PWM, register_a)?;

Ok(())
}
}

impl<B, CS, P, T, const L: usize> LTC681X<B, CS, P, T, L>
Expand Down
Loading

0 comments on commit e3653fe

Please sign in to comment.