1use core::convert::{From, Into};
2macro_rules! commands {
3 ($ty:ident, $val:expr,$poll:expr,$doc:expr, $($trait:ident),*) => {
4 #[doc=$doc]
5 pub struct $ty {
6 cmd: u16,
7 has_poll_status: bool,
8 }
9 impl IsCmd for $ty{
10 fn as_cmd_header(&self) -> u16{
11 self.cmd
12 }
13
14 fn has_poll_status(&self) -> bool{
15 self.has_poll_status
16 }
17 }
18 $(impl $trait for $ty {})*
19 impl From<u16> for $ty {
20 fn from(value: u16) -> Self {
21 Self { cmd: value, has_poll_status: $poll}
22 }
23 }
24 impl From<$ty> for u16 {
25 fn from(value: $ty) -> Self {
26 value.cmd
27 }
28 }
29 impl Default for$ty {
30 fn default() -> Self {
31 Self { cmd: $val , has_poll_status: $poll}
32 }
33 }
34 };
35 ($ty:ident, $val:expr,$poll:expr,$doc:expr) => {
36 #[doc=$doc]
37 pub struct $ty {
38 cmd: u16,
39 has_poll_status: bool
40 }
41 impl IsCmd for $ty{
42 fn as_cmd_header(&self) -> u16{
43 self.cmd
44 }
45
46 fn has_poll_status(&self) -> bool{
47 self.has_poll_status
48 }
49 }
50 impl Default for $ty {
51 fn default () -> Self {
52 Self { cmd: $val, has_poll_status: $poll }
53 }
54 }
55 }
56}
57commands!(
58 Adcv,
59 0x260,
60 true,
61 "Start Cell Voltage ADC Conversion and Poll Status",
62 HasDCPOption,
63 HasMDOption,
64 HasCellChannelConfig
65);
66commands!(
67 Adow,
68 0x228,
69 true,
70 "Start Open Wire ADC Conversion and Poll Status",
71 HasPullUpOption,
72 HasDCPOption,
73 HasMDOption,
74 HasCellChannelConfig
75);
76commands!(
77 Cvst,
78 0x207,
79 true,
80 "Start Self Test Cell Voltage Conversion and Poll Status",
81 HasMDOption,
82 HasSTConfig
83);
84commands!(
85 Adol,
86 0x201,
87 true,
88 "Start Overlap Measurements on Cell 7 and Cell 13 (only LTC6812/13) Voltages",
89 HasMDOption,
90 HasDCPOption
91);
92commands!(
93 Adax,
94 0x460,
95 true,
96 "Start GPIOs ADC Conversion and Poll Status",
97 HasMDOption,
98 HasGpioChannelConfig
99);
100commands!(
101 Adaxd,
102 0x400,
103 true,
104 "Start GPIOs ADC Conversion with Digital Redundancy and Poll Status",
105 HasMDOption,
106 HasGpioChannelConfig
107);
108#[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
109commands!(
110 Axow,
111 0x410,
112 true,
113 "Start GPIOs Open Wire ADC Conversion and Poll Status",
114 HasMDOption,
115 HasPullUpOption,
116 HasGpioChannelConfig
117);
118commands!(
119 Axst,
120 0x407,
121 true,
122 "Start Self Test GPIOs COnversion and Poll Status",
123 HasMDOption,
124 HasSTConfig
125);
126commands!(
127 Adstat,
128 0x468,
129 true,
130 "Start Status Group ADC Conversion and Poll Status",
131 HasMDOption,
132 HasStatusChannelConfig
133);
134commands!(
135 Adstatd,
136 0x408,
137 true,
138 "Start Status Group ADC Conversion with Digital Redundancy and Poll Status",
139 HasMDOption,
140 HasStatusChannelConfig
141);
142commands!(
143 Statst,
144 0x40F,
145 true,
146 "Start Self Test Status Group Conversion and Poll Status",
147 HasMDOption,
148 HasSTConfig
149);
150commands!(
151 Adcvax,
152 0x46F,
153 true,
154 "Start Combined Cell Voltage and GPIO1, GPIO2 Conversion and Poll Status",
155 HasMDOption,
156 HasDCPOption
157);
158commands!(
159 Adcvsc,
160 0x467,
161 true,
162 "Start Combined Cell Voltage and SC Conversion and Poll Status",
163 HasMDOption,
164 HasDCPOption
165);
166commands!(Pladc, 0x714, true, "Poll ADC COnversion Status");
167commands!(Diagn, 0x715, true, "Diagnose MUX and Poll Status");
168commands!(Clrcell, 0x711, false, "Clear Cell Voltage Register Groups");
170commands!(Clraux, 0x712, false, "Clear Auxiliary Register Groups");
171commands!(Clrstat, 0x713, false, "Clear Status Register Groups");
172commands!(RdCfgA, 0x002, false, "Read Configuration Register Group A");
174commands!(RdCfgB, 0x026, false, "Read Configuration Register Group B");
175commands!(RdCvA, 0x004, false, "Read Cell Voltage Register Group A");
176commands!(RdCvB, 0x006, false, "Read Cell Voltage Register Group B");
177commands!(RdCvC, 0x008, false, "Read Cell Voltage Register Group C");
178commands!(RdCvD, 0x00A, false, "Read Cell Voltage Register Group D");
179#[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
180commands!(RdCvE, 0x009, false, "Read Cell Voltage Register Group E");
181#[cfg(feature = "ltc6813")]
182commands!(RdCvF, 0x00B, false, "Read Cell Voltage Register Group F");
183commands!(RdAuxA, 0x00C, false, "Read Auxiliary Register Group A");
184commands!(RdAuxB, 0x00E, false, "Read Auxiliary Register Group B");
185#[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
186commands!(RdAuxC, 0x00D, false, "Read Auxiliary Register Group C");
187#[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
188commands!(RdAuxD, 0x00F, false, "Read Auxiliary Register Group D");
189commands!(RdStatA, 0x010, false, "Read Status Register Group A");
190commands!(RdStatB, 0x012, false, "Read Status Register Group A");
191commands!(WrCfgA, 0x001, false, "Write Configuration Register Group A");
193commands!(WrCfgB, 0x024, false, "Write Configuration Register Group B");
194
195commands!(WrComm, 0x721, false, "Write COMM Register Group");
196commands!(RdComm, 0x722, false, "Read COMM Register Group");
197commands!(StComm, 0x723, false, "Start I2C/SPO Communication");
198
199pub enum MDSetting {
208 MD0_0 = 0b00,
209 MD0_1 = 0b01,
210 MD1_0 = 0b10,
211 MD1_1 = 0b11,
212}
213pub trait HasMDOption: Into<u16> + From<u16> {
238 #[must_use]
239 fn set_md_option(self, md_bits: MDSetting) -> Self {
240 let cmd = self.into();
241 (cmd | (md_bits as u16) << 7).into()
242 }
243}
244pub trait HasDCPOption: Into<u16> + From<u16> {
256 #[must_use]
257 fn set_dcp_option(self) -> Self {
258 let cmd: u16 = self.into();
259 (cmd | 1 << 4).into()
260 }
261}
262pub enum CellChannelConfig {
266 AllCells = 0b000,
267 Cell1_7_13 = 0b001,
268 Cell2_8_14 = 0b010,
269 Cell3_9_15 = 0b011,
270 Cell4_10_16 = 0b100,
271 Cell5_11_17 = 0b101,
272 Cell6_12_18 = 0b110,
273}
274pub trait HasCellChannelConfig: Into<u16> + From<u16> {
276 #[must_use]
278 fn set_channel_config(self, config: CellChannelConfig) -> Self {
279 let cmd = self.into();
280 (cmd | config as u16).into()
281 }
282}
283
284pub enum GpioChannelConfig {
288 AllGpios = 0b000,
289 Gpio1_6 = 0b001,
290 Gpio2_7 = 0b010,
291 Gpio3_8 = 0b011,
292 Gpio4_9 = 0b100,
293 Gpio5 = 0b101,
294 ScndRef = 0b110,
295}
296pub trait HasGpioChannelConfig: Into<u16> + From<u16> {
298 #[must_use]
300 fn set_channel_config(self, config: GpioChannelConfig) -> Self {
301 let cmd = self.into();
302 (cmd | config as u16).into()
303 }
304}
305
306pub enum StatusChannelConfig {
310 AllStatus = 0b000,
311 SumOfCells = 0b001,
312 InternalTemp = 0b010,
313 AnalogSupply = 0b011,
314 DigitalSupply = 0b100,
315}
316pub trait HasStatusChannelConfig: Into<u16> + From<u16> {
318 #[must_use]
320 fn set_channel_config(self, config: StatusChannelConfig) -> Self {
321 let cmd = self.into();
322 (cmd | config as u16).into()
323 }
324}
325pub trait HasPullUpOption: Into<u16> + From<u16> {
326 #[must_use]
330 fn set_pullup_option(self) -> Self {
331 let cmd = self.into();
332 (cmd | 1 << 6).into()
333 }
334}
335pub enum SelfTestConfig {
342 SelfTest1 = 0b01,
343 SelfTest2 = 0b10,
344}
345pub trait HasSTConfig: Into<u16> + From<u16> {
347 #[must_use]
355 fn set_st_config(self, config: SelfTestConfig) -> Self {
356 let cmd = self.into();
357 (cmd | (config as u16) << 5).into()
358 }
359}
360pub trait IsCmd {
362 fn as_cmd_header(&self) -> u16;
363 fn has_poll_status(&self) -> bool;
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369 #[test]
370 fn test_all_options() {
371 let cmd = Adow::default()
372 .set_md_option(MDSetting::MD0_1)
373 .set_dcp_option()
374 .set_channel_config(CellChannelConfig::Cell1_7_13)
375 .set_pullup_option()
376 .set_channel_config(CellChannelConfig::AllCells);
377
378 assert_eq!(cmd.cmd, 761);
379
380 let cmd = Statst::default()
381 .set_st_config(SelfTestConfig::SelfTest1)
382 .set_md_option(MDSetting::MD1_1)
383 .set_st_config(SelfTestConfig::SelfTest1);
384 assert_eq!(cmd.cmd, 1455);
385
386 let cmd = Adax::default().set_channel_config(GpioChannelConfig::AllGpios);
387 assert_eq!(cmd.cmd, 1120);
388 let cmd = Adstatd::default().set_channel_config(StatusChannelConfig::AllStatus);
389 assert_eq!(cmd.cmd, 1032);
390 }
391}