embedded_batteries/smart_battery.rs
1use bitfield_struct::bitfield;
2
3use crate::{MilliAmps, MilliAmpsSigned, MilliVolts};
4
5/// Smart Battery error.
6pub trait Error: core::fmt::Debug {
7 /// Convert error to a generic Smart Battery error kind.
8 ///
9 /// By using this method, Smart Battery errors freely defined by HAL implementations
10 /// can be converted to a set of generic Smart Battery errors upon which generic
11 /// code can act.
12 fn kind(&self) -> ErrorKind;
13}
14
15impl Error for core::convert::Infallible {
16 #[inline]
17 fn kind(&self) -> ErrorKind {
18 match *self {}
19 }
20}
21
22/// Smart Battery error kind.
23///
24/// This represents a common set of Smart Battery operation errors. HAL implementations are
25/// free to define more specific or additional error types. However, by providing
26/// a mapping to these common Smart Battery errors, generic code can still react to them.
27#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29#[non_exhaustive]
30pub enum ErrorKind {
31 /// An error occurred on the underlying peripheral supporting the sensor.
32 /// e.g. An I2C bus error occurs for an I2C enabled Smart Battery.
33 /// The original error may contain more information.
34 CommError,
35 /// An error occured and was reported by a read from the BatteryStatus (0x16) register.
36 BatteryStatus(ErrorCode),
37 /// A different error occurred. The original error may contain more information.
38 Other,
39}
40
41impl Error for ErrorKind {
42 #[inline]
43 fn kind(&self) -> ErrorKind {
44 *self
45 }
46}
47
48impl core::fmt::Display for ErrorKind {
49 #[inline]
50 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51 match self {
52 Self::CommError => write!(f, "Error communicating with Smart Battery"),
53 Self::BatteryStatus(_) => write!(
54 f,
55 "Error reported by BatteryService (0x16) register. The original error may contain more information"
56 ),
57 Self::Other => write!(
58 f,
59 "A different error occurred. The original error may contain more information"
60 ),
61 }
62 }
63}
64
65/// Smart Battery error type trait.
66///
67/// This just defines the error type, to be used by the other Smart Battery traits.
68pub trait ErrorType {
69 /// Error type.
70 type Error: Error;
71}
72
73impl<T: ErrorType + ?Sized> ErrorType for &mut T {
74 type Error = T::Error;
75}
76
77/// Depending on the value of the CapacityMode bit, the Smart Battery will use milliamps or centiwatts.
78#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80pub enum CapacityModeValue {
81 /// Unsigned Milliamp or MilliampHour representation, used when CapacityMode bit = 0.
82 MilliAmpUnsigned(u16),
83 /// Unsigned Centiwatt or CentiwattHour representation, used when CapacityMode bit = 1.
84 CentiWattUnsigned(u16),
85}
86
87/// Time is measured in minutes, where 1 minute is 1
88pub type Minutes = u16;
89
90/// Depending on the value of the CapacityMode bit, the Smart Battery will use milliamps or centiwatts.
91/// Signed to represent negative currents and capacities.
92#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
93#[cfg_attr(feature = "defmt", derive(defmt::Format))]
94pub enum CapacityModeSignedValue {
95 /// Signed Milliamp or MilliampHour representation, used when CapacityMode bit = 0.
96 MilliAmpSigned(i16),
97 /// Signed Milliamp or MilliampHour representation, used when CapacityMode bit = 1.
98 CentiWattSigned(i16),
99}
100
101/// Temperature is measured in decikelvins, where 0.1 Kelvin is 1.
102pub type DeciKelvin = u16;
103
104/// Percent, 1% is 1.
105pub type Percent = u8;
106
107/// Cycles, 1 cycle is 1.
108pub type Cycles = u16;
109
110/// Error codes that must be supported by the Smart Battery.
111#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
112#[cfg_attr(feature = "defmt", derive(defmt::Format))]
113#[repr(u8)]
114pub enum ErrorCode {
115 /// The Smart Battery processed the function code
116 /// without detecting any errors.
117 Ok = 0,
118
119 /// The Smart Battery is unable to process the function
120 /// code at this time.
121 Busy = 1,
122
123 /// The Smart Battery detected an attempt to read or
124 /// write to a function code reserved by this version of
125 /// the specification. The Smart Battery detected an
126 /// attempt to access an unsupported optional
127 /// manufacturer function code.
128 ReservedCmd = 2,
129
130 /// The Smart Battery does not support this function
131 /// code which is defined in this version of the
132 /// specification.
133 UnsupportedCmd = 3,
134
135 /// The Smart Battery detected an attempt to write to a
136 /// read only function code.
137 AccessDenied = 4,
138
139 /// The Smart Battery detected a data overflow or
140 /// under flow.
141 UnderOverFlow = 5,
142
143 /// The Smart Battery detected an attempt to write to a
144 /// function code with an incorrect size data block.
145 BadSize = 6,
146
147 /// The Smart Battery detected an unidentifiable error.
148 UnknownError = 7,
149}
150
151impl ErrorCode {
152 const fn into_bits(self) -> u8 {
153 self as _
154 }
155
156 const fn from_bits(value: u8) -> Self {
157 match value {
158 0 => Self::Ok,
159 1 => Self::Busy,
160 2 => Self::ReservedCmd,
161 3 => Self::UnsupportedCmd,
162 4 => Self::AccessDenied,
163 5 => Self::UnderOverFlow,
164 6 => Self::BadSize,
165 _ => Self::UnknownError,
166 }
167 }
168}
169
170impl From<u8> for ErrorCode {
171 fn from(value: u8) -> Self {
172 Self::from_bits(value)
173 }
174}
175
176/// Revision of SBS Spec, used in specification_info().
177#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
178#[cfg_attr(feature = "defmt", derive(defmt::Format))]
179#[repr(u8)]
180pub enum Revision {
181 /// Version 1.0 and 1.1.
182 Version1And1Dot1 = 1,
183}
184
185impl Revision {
186 const fn into_bits(self) -> u8 {
187 self as _
188 }
189
190 const fn from_bits(value: u8) -> Self {
191 match value {
192 1 => Self::Version1And1Dot1,
193 _ => unreachable!(),
194 }
195 }
196}
197
198impl TryFrom<u8> for Revision {
199 type Error = ();
200
201 fn try_from(value: u8) -> Result<Self, Self::Error> {
202 match value {
203 1 => Ok(Self::Version1And1Dot1),
204 _ => Err(()),
205 }
206 }
207}
208
209/// Version of SBS Spec, used in specification_info().
210#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
211#[cfg_attr(feature = "defmt", derive(defmt::Format))]
212#[repr(u8)]
213pub enum Version {
214 /// Reserved.
215 Reserved = 0,
216
217 /// Version 1.0.
218 Version1 = 1,
219
220 /// Version 1.1.
221 Version1Dot1 = 2,
222
223 /// Version 1.1 with optional PEC support.
224 Version1Dot1Pec = 3,
225}
226
227impl Version {
228 const fn into_bits(self) -> u8 {
229 self as _
230 }
231
232 const fn from_bits(value: u8) -> Self {
233 match value {
234 1 => Self::Version1,
235 2 => Self::Version1Dot1,
236 3 => Self::Version1Dot1Pec,
237 _ => Self::Reserved,
238 }
239 }
240}
241
242impl From<u8> for Version {
243 fn from(value: u8) -> Self {
244 Self::from_bits(value)
245 }
246}
247
248/// Return value of the manufacture_date() function (0x1b). The date is packed in the
249/// following fashion: (year-1980) * 512 + month * 32 + day.
250#[bitfield(u16, defmt = cfg(feature = "defmt"))]
251pub struct ManufactureDate {
252 /// 1 - 31 (corresponds to date).
253 #[bits(5)]
254 pub day: usize,
255
256 /// 1 - 12 (corresponds to month number).
257 #[bits(4)]
258 pub month: usize,
259
260 /// 0 - 127 (corresponds to year biased by 1980).
261 /// Add 1980 to the year to get the true year.
262 #[bits(7)]
263 pub year: usize,
264}
265
266/// Return value of the battery_mode() function (0x03). See the SBS spec for more information.
267#[bitfield(u16, defmt = cfg(feature = "defmt"))]
268pub struct BatteryModeFields {
269 /// INTERNAL_CHARGE_CONTROLLER bit set indicates that the battery pack contains its own internal
270 /// charge controller. When the bit is set, this optional function is supported and the
271 /// CHARGE_CONTROLLER_ENABLED bit will be available for activation and control of the actual
272 /// internal charger.
273 #[bits(1, access = RO)]
274 pub internal_charge_controller: bool,
275
276 /// PRIMARY_BATTERY_SUPPORT bit set indicates that the battery pack has the ability to act as either
277 /// the primary or secondary battery in a system. When the bit is set, this function is supported and the
278 /// PRIMARY_BATTERY bit will be available for activation and control of this function
279 #[bits(1, access = RO)]
280 pub primary_battery_support: bool,
281
282 #[bits(5)]
283 __: u8,
284
285 /// CONDITION_FLAG bit set indicates that the battery is requesting a conditioning cycle. A conditioning
286 /// cycle may be requested because of the characteristics of the battery chemistry and/or the electronics in
287 /// combination with the usage pattern.
288 #[bits(1, access = RO)]
289 pub condition_flag: bool,
290
291 /// CHARGE_CONTROLLER_ENABLED bit is set to enable the battery pack’s internal charge controller.
292 /// When this bit is cleared, the internal charge controller is disabled (default). This bit is active only when the
293 /// INTERNAL_CHARGE_CONTROLLER bit is set, indicating that this function is supported. The status of
294 /// a battery pack’s internal charge controller can be determined by reading this bit
295 pub charge_controller_enabled: bool,
296
297 /// PRIMARY_BATTERY bit is set to enable a battery to operate as the primary battery in a system. When
298 /// this bit is cleared, the battery operates in a secondary role (default). This bit is active only when the
299 /// PRIMARY_BATTERY_SUPPORT bit is set. The role that the battery is playing can be determined by
300 /// reading this bit.
301 pub primary_battery: bool,
302
303 #[bits(3)]
304 __: u8,
305
306 /// ALARM_MODE bit is set to disable the Smart Battery's ability to master the SMBus and send
307 /// AlarmWarning() messages to the SMBus Host and the Smart Battery Charger. When set, the Smart Battery
308 /// will NOT master the SMBus and AlarmWarning() messages will NOT be sent to the SMBus Host and the
309 /// Smart Battery Charger for a period of no more than 65 seconds and no less than 45 seconds. When
310 /// cleared (default), the Smart Battery WILL send the AlarmWarning() messages to the SMBus Host and the
311 /// Smart Battery Charger any time an alarm condition is detected. (See also Section 5.4 of the SBS spec
312 /// for a more detailed explanation of alarm conditions and operations.)
313 ///
314 /// When the ALARM_MODE bit is set, the system assumes responsibility for detecting and
315 /// responding to Smart Battery alarms by reading the BatteryStatus() to determine if any of the alarm
316 /// bit flags are set. At a minimum, this requires the system to poll the Smart Battery BatteryStatus()
317 /// every 10 seconds at all times the SMBus is active. The system is expected to take appropriate
318 /// action.
319 ///
320 /// The ALARM_MODE bit is automatically cleared by the Smart Battery electronics every 60
321 /// seconds so that any accidental activation of this mode will not be persistent. A SMBus Host which
322 /// does not want the Smart Battery to be a master on the SMBus must therefore continually set this
323 /// bit at least once per 45 seconds to keep the ALARM_MODE bit set
324 pub alarm_mode: bool,
325
326 /// CHARGER_MODE bit enables or disables the Smart Battery's transmission of ChargingCurrent() and
327 /// ChargingVoltage() messages to the Smart Battery Charger. When set, the Smart Battery will NOT transmit
328 /// ChargingCurrent() and ChargingVoltage() values to the Smart Battery Charger. When cleared, the Smart
329 /// Battery will transmit the ChargingCurrent() and ChargingVoltage() values to the Smart Battery Charger
330 /// when charging is desired. (See Section 5.3 of the SBS spec for a more detailed explanation.)
331 ///
332 /// When the CHARGER_MODE bit is set, the system assumes responsibility for safely charging the
333 /// Smart Battery. At a minimum, this requires the system to poll the Smart Battery for
334 /// ChargingVoltage() and ChargingCurrent() at the same rate the Smart Battery would normally send
335 /// these charging messages to the Smart Battery Charger (e.g. every 5 seconds to 60 seconds.)
336 /// The CHARGER_MODE bit allows a SMBus Host or Smart Battery Charger to disable the Smart
337 /// Battery's broadcast of the ChargingCurrent() and ChargingVoltage().
338 ///
339 /// The use of CHARGER_MODE does NOT affect the use of ALARM_MODE. If only
340 /// CHARGER_MODE bit is set, AlarmWarning messages relating to charging will still occur and be
341 /// broadcast the Smart Battery Charger and SMBus Host. (See ALARM_MODE bit flag definition.)
342 pub charger_mode: bool,
343
344 /// CAPACITY_MODE bit indicates if capacity information will be reported in mA/mAh or 10mW/10mWh.
345 /// When set, the capacity information will be reported in 10mW/10mWh as appropriate. When cleared, the
346 /// capacity information will be reported in mA/mAh as appropriate.
347 ///
348 /// After changing the CAPACITY_MODE bit, all related values (such as AtRate()) should be re-written while
349 /// the new mode is active. This is because changes made to the CAPACITY_MODE bit do not retroactively
350 /// affect values which may have been previously written in another mode. For example, a value written to
351 /// AtRate() while the CAPACITY_MODE bit was 0 will cause AtRate calculations to be made using the mAH
352 /// value. Changing the CAPACITY_MODE bit to 1 will not automatically cause all the AtRate calculations to
353 /// be re-calculated using the 10mWH equivalent, although this is permitted, it is not required.
354 pub capacity_mode: bool,
355}
356
357/// Return value of the battery_status() function (0x16). See the SBS spec for more information.
358#[bitfield(u16, defmt = cfg(feature = "defmt"))]
359#[derive(Eq, PartialEq, Ord, PartialOrd, Hash)]
360pub struct BatteryStatusFields {
361 /// Error codes from the Smart Battery. See ErrorCode enum fields for detailed documentation on what each
362 /// error code entails.
363 #[bits(4)]
364 pub error_code: ErrorCode,
365
366 /// FULLY_DISCHARGED bit is set when the Smart Battery determines that it has supplied all the charge it
367 /// can. Discharge should be stopped soon.
368 ///
369 /// This bit will be cleared when the RelativeStateOfCharge() is
370 /// greater than or equal to 20%. This status bit may be set prior to the
371 /// ‘TERMINATE_DISCHARGE_ALARM’ as an early or first level warning of end of battery charge.
372 pub fully_discharged: bool,
373
374 /// FULLY_CHARGED bit is set when the Smart Battery determines that has reached a full charge point.
375 ///
376 /// This bit will be cleared when the battery may want to be charged again, which is chemistry and
377 /// manufacturer specific.
378 pub fully_charged: bool,
379
380 /// DISCHARGING bit is set when the Smart Battery determines that it is not being charged.
381 /// This bit will be cleared when the battery detects that it is being charged.
382 pub discharging: bool,
383
384 /// INITIALIZED bit is SET when the Smart Battery electronics are calibrated or configured for the first time,
385 /// typically at the time of battery pack assembly or manufacture.
386 ///
387 /// It will be cleared when the battery detects that this calibration or configuration data has been lost or
388 /// altered and a significant degradation in accuracy is possible.
389 ///
390 /// The INITIALIZED status bit is the second and more serious signal from the Smart Battery that it has
391 /// perhaps lost the ability to determine the present state-of-charge. As a result other data values required by
392 /// this specification may be inaccurate.
393 ///
394 /// (The first signal from the Smart Battery is typically the CONDITION_FLAG found in the BatteryMode()
395 /// register.)
396 pub initialized: bool,
397
398 /// REMAINING_TIME_ALARM bit is set when the Smart Battery detects that the estimated remaining
399 /// time at the present discharge rate represented by the value in AverageTimeToEmpty() is less than that set by
400 /// the RemainingTimeAlarm() function.
401 ///
402 /// This bit will be cleared when either the value set by the RemainingTimeAlarm() function is lower than the
403 /// AverageTimeToEmpty() or when the AverageTimeToEmpty() is increased by charging the Smart Battery
404 /// or decreasing the discharge rate.
405 ///
406 /// (NOTE: This Alarm bit can be disabled by writing zero to the RemainingTimeAlarm() value.)
407 pub remaining_time_alarm: bool,
408
409 /// REMAINING_CAPACITY_ALARM bit is set when the Smart Battery detects that its
410 /// RemainingCapacity() is less than that set by the RemainingCapacityAlarm() function.
411 ///
412 /// This bit will be cleared when either the value set by the RemainingCapacityAlarm() function is lower than the
413 /// RemainingCapacity() or when the RemainingCapacity() is increased by charging the Smart Battery.
414 ///
415 /// (NOTE: This Alarm bit can be disabled by writing zero to the RemainingCapacityAlarm() value.)
416 pub remaining_capacity_alarm: bool,
417
418 __: bool,
419
420 /// TERMINATE_DISCHARGE_ALARM bit is set when the Smart Battery determines that it has supplied
421 /// all the charge it can at the present discharge rate. Discharge should be stopped as soon as possible.
422 ///
423 /// This bit will be cleared when the Smart Battery detects that the discharge has stopped or that the rate
424 /// has lessened.
425 /// (Note that since this is rate dependent, it may occur at a high discharge rate and disappear when the
426 /// discharge rate has slowed such that the Smart Battery can continue to be discharged at the lower rate.)
427 pub terminate_discharge_alarm: bool,
428
429 /// OVER_TEMP_ALARM bit will be set when the Smart Battery detects that its internal temperature is
430 /// greater than a preset allowable limit. When this bit is set, charging should be stopped as soon as possible.
431 /// The Smart Battery may not yet be in a Fully Charged state.
432 /// Charging is effectively ‘suspended,’ usually temporarily. Charging may resume when the Smart Battery
433 /// detects that its internal temperature is below a preset limit to allow charging again. (This limit may be a
434 /// different value than what caused the original alarm.)
435 ///
436 /// This bit is cleared when the internal temperature has dropped below an acceptable limit, which may or may
437 /// not be the original alarm threshold (although charging may not always resume at this point.)
438 pub over_temp_alarm: bool,
439
440 __: bool,
441
442 /// TERMINATE_CHARGE_ALARM bit is set when charging should be stopped but the Smart Battery may
443 /// not yet be in a Fully Charged state. Charging is effectively ‘suspended,’ usually temporarily. Charging may
444 /// resume when the Smart Battery detects that its charging parameters are back in allowable ranges and
445 /// ChargingVoltage() and ChargingCurrent() values are both returned to non-zero values.
446 ///
447 /// This bit is cleared when the Smart Battery detects that it is no longer being charged.
448 pub terminate_charge_alarm: bool,
449
450 /// OVER_CHARGED_ALARM bit is set whenever the Smart Battery detects that it is being charged
451 /// beyond a Fully Charged state. When this bit is set, charging should be completely stopped as soon as
452 /// possible. Charging further can result in permanent damage to the battery.
453 ///
454 /// This bit will be cleared when the Smart Battery detects that it is no longer being charged. Charging should
455 /// not automatically restart.
456 pub over_charged_alarm: bool,
457}
458
459/// Return value of the specification_info() function (0x1a). See the SBS spec for more information.
460#[bitfield(u16, defmt = cfg(feature = "defmt"))]
461pub struct SpecificationInfoFields {
462 /// Revision of the SBS spec supported by this Smart Battery.
463 /// See Revision enum fields for detailed documentation.
464 #[bits(4)]
465 pub revision: Revision,
466
467 /// Version of the SBS spec supported by this Smart Battery.
468 /// See Version enum fields for detailed documentation.
469 #[bits(4)]
470 pub version: Version,
471
472 /// 0 - 3 (multiplies voltages* by 10 ^ VScale).
473 #[bits(4)]
474 pub v_scale: u8,
475
476 /// 0 - 3 (multiplies currents* and capacities by 10 ^ IPScale).
477 #[bits(4)]
478 pub ip_scale: u8,
479}
480
481/// Blocking Smart Battery methods.
482pub trait SmartBattery: ErrorType {
483 /// 0x01
484 ///
485 /// Gets the Low Capacity alarm threshold value. Whenever the RemainingCapacity() falls below the
486 /// Low Capacity value, the Smart Battery sends AlarmWarning() messages to the SMBus Host with the
487 /// REMAINING_CAPACITY_ALARM bit set. A Low Capacity value of 0 disables this alarm.
488 /// (If the ALARM_MODE bit is set in BatteryMode() then the AlarmWarning() message is disabled for a set
489 /// period of time. See the BatteryMode() function for further information.)
490 ///
491 /// The Low Capacity value is set to 10% of design capacity at time of manufacture. The Low Capacity value
492 /// will remain unchanged until altered by the RemainingCapacityAlarm() function. The Low Capacity value
493 /// may be expressed in either capacity (mAh) or power (10mWh) depending on the setting of the
494 /// BatteryMode()'s CAPACITY_MODE bit (see BatteryMode()).
495 fn remaining_capacity_alarm(&mut self) -> Result<CapacityModeValue, Self::Error>;
496
497 /// 0x01
498 ///
499 /// Sets the Low Capacity alarm threshold value. Whenever the RemainingCapacity() falls below the
500 /// Low Capacity value, the Smart Battery sends AlarmWarning() messages to the SMBus Host with the
501 /// REMAINING_CAPACITY_ALARM bit set. A Low Capacity value of 0 disables this alarm.
502 /// (If the ALARM_MODE bit is set in BatteryMode() then the AlarmWarning() message is disabled for a set
503 /// period of time. See the BatteryMode() function for further information.)
504 ///
505 /// The Low Capacity value is set to 10% of design capacity at time of manufacture. The Low Capacity value
506 /// will remain unchanged until altered by the RemainingCapacityAlarm() function. The Low Capacity value
507 /// may be expressed in either capacity (mAh) or power (10mWh) depending on the setting of the
508 /// BatteryMode()'s CAPACITY_MODE bit (see BatteryMode()).
509 fn set_remaining_capacity_alarm(&mut self, capacity: CapacityModeValue) -> Result<(), Self::Error>;
510
511 /// 0x02
512 ///
513 /// Gets the Remaining Time alarm value. Whenever the AverageTimeToEmpty() falls below the
514 /// Remaining Time value, the Smart Battery sends AlarmWarning() messages to the SMBus Host with the
515 /// REMAINING_TIME_ALARM bit set. A Remaining Time value of 0 effectively disables this alarm.
516 /// (If the ALARM_MODE bit is set in BatteryMode() then the AlarmWarning() message is disabled for a set
517 /// period of time. See the BatteryMode() function for further information.)
518 ///
519 /// The Remaining Time value is set to 10 minutes at time of manufacture. The Remaining Time value will
520 /// remain unchanged until altered by the RemainingTimeAlarm() function.
521 fn remaining_time_alarm(&mut self) -> Result<Minutes, Self::Error>;
522
523 /// 0x02
524 ///
525 /// Sets the Remaining Time alarm value. Whenever the AverageTimeToEmpty() falls below the
526 /// Remaining Time value, the Smart Battery sends AlarmWarning() messages to the SMBus Host with the
527 /// REMAINING_TIME_ALARM bit set. A Remaining Time value of 0 effectively disables this alarm.
528 /// (If the ALARM_MODE bit is set in BatteryMode() then the AlarmWarning() message is disabled for a set
529 /// period of time. See the BatteryMode() function for further information.)
530 ///
531 /// The Remaining Time value is set to 10 minutes at time of manufacture. The Remaining Time value will
532 /// remain unchanged until altered by the RemainingTimeAlarm() function.
533 fn set_remaining_time_alarm(&mut self, time: Minutes) -> Result<(), Self::Error>;
534
535 /// 0x03
536 ///
537 /// This function reads the various battery operational modes and reports the battery’s capabilities, modes,
538 /// and flags minor conditions requiring attention.
539 ///
540 /// See the SBS specification for detailed documentation.
541 fn battery_mode(&mut self) -> Result<BatteryModeFields, Self::Error>;
542
543 /// 0x03
544 ///
545 /// This function sets the various battery operational modes and reports the battery’s capabilities, modes,
546 /// and flags minor conditions requiring attention. Note that not all fields are writeable.
547 ///
548 /// See the SBS specification for detailed documentation.
549 fn set_battery_mode(&mut self, flags: BatteryModeFields) -> Result<(), Self::Error>;
550
551 /// 0x04
552 ///
553 /// The AtRate() function is the first half of a two-function call-set used to set the AtRate value used in
554 /// calculations made by the AtRateTimeToFull(), AtRateTimeToEmpty(), and AtRateOK() functions.
555 ///
556 /// The AtRate value may be expressed in either current (mA) or power (10mW) depending on the setting of the
557 /// BatteryMode()'s CAPACITY_MODE bit. (Configuration of the CAPACITY_MODE bit will alter the
558 /// calculation of AtRate functions. Changing the state of CAPACITY_MODE may require a re-write to the
559 /// AtRate() function using the appropriate units.)
560 fn at_rate(&mut self) -> Result<CapacityModeSignedValue, Self::Error>;
561
562 /// 0x04
563 ///
564 /// The AtRate() function is the first half of a two-function call-set used to set the AtRate value used in
565 /// calculations made by the AtRateTimeToFull(), AtRateTimeToEmpty(), and AtRateOK() functions.
566 ///
567 /// The AtRate value may be expressed in either current (mA) or power (10mW) depending on the setting of the
568 /// BatteryMode()'s CAPACITY_MODE bit. (Configuration of the CAPACITY_MODE bit will alter the
569 /// calculation of AtRate functions. Changing the state of CAPACITY_MODE may require a re-write to the
570 /// AtRate() function using the appropriate units.)
571 fn set_at_rate(&mut self, rate: CapacityModeSignedValue) -> Result<(), Self::Error>;
572
573 /// 0x05
574 ///
575 /// Returns the predicted remaining time to fully charge the battery at the previously written AtRate value in mA.
576 ///
577 /// Note: This function is only required to return a value when the CAPACITY_MODE bit is cleared and the
578 /// AtRate() value is written in mA units. If the CAPACITY_MODE bit is set, then AtRateTimeToFull() may
579 /// return 65535 to indicate over-range and return an error code indicating overflow. Alternately, this function
580 /// may return a remaining time to full based on a 10 mW value in AtRate().
581 fn at_rate_time_to_full(&mut self) -> Result<Minutes, Self::Error>;
582
583 /// 0x06
584 ///
585 /// Returns the predicted remaining operating time if the battery is discharged at the previously written AtRate
586 /// value. (Result will depend on the setting of CAPACITY_MODE bit.)
587 fn at_rate_time_to_empty(&mut self) -> Result<Minutes, Self::Error>;
588
589 /// 0x07
590 ///
591 /// Returns a Boolean value that indicates whether or not the battery can deliver the previously written AtRate
592 /// value of additional energy for 10 seconds (Boolean). If the AtRate value is zero or positive, the
593 /// AtRateOK() function will ALWAYS return true. Result may depend on the setting of CAPACITY_MODE
594 /// bit.
595 fn at_rate_ok(&mut self) -> Result<bool, Self::Error>;
596
597 /// 0x08
598 ///
599 /// Returns the cell-pack's internal temperature (°K). The actual operational temperature range will be defined
600 /// at a pack level by a particular manufacturer.
601 fn temperature(&mut self) -> Result<DeciKelvin, Self::Error>;
602
603 /// 0x09
604 ///
605 /// Returns the cell-pack voltage (mV).
606 fn voltage(&mut self) -> Result<MilliVolts, Self::Error>;
607
608 /// 0x0A
609 ///
610 /// Returns the current being supplied (or accepted) through the battery's terminals (mA).
611 fn current(&mut self) -> Result<MilliAmpsSigned, Self::Error>;
612
613 /// 0x0B
614 ///
615 /// Returns a one-minute rolling average based on the current being supplied (or accepted) through the battery's
616 /// terminals (mA). The AverageCurrent() function is expected to return meaningful values during the battery's
617 /// first minute of operation.
618 fn average_current(&mut self) -> Result<MilliAmpsSigned, Self::Error>;
619
620 /// 0x0C
621 ///
622 /// Returns the expected margin of error (%) in the state of charge calculation. For example, when MaxError()
623 /// returns 10% and RelativeStateOfCharge() returns 50%, the Relative StateOfCharge() is actually between 50
624 /// and 60%. The MaxError() of a battery is expected to increase until the Smart Battery identifies a condition
625 /// that will give it higher confidence in its own accuracy. For example, when a Smart Battery senses that it has
626 /// been fully charged from a fully discharged state, it may use that information to reset or partially reset
627 /// MaxError(). The Smart Battery can signal when MaxError() has become too high by setting the
628 /// CONDITION_FLAG bit in BatteryMode().
629 fn max_error(&mut self) -> Result<Percent, Self::Error>;
630
631 /// 0x0D
632 ///
633 /// Returns the predicted remaining battery capacity expressed as a percentage of FullChargeCapacity() (%).
634 fn relative_state_of_charge(&mut self) -> Result<Percent, Self::Error>;
635
636 /// 0x0E
637 ///
638 /// Returns the predicted remaining battery capacity expressed as a percentage of DesignCapacity() (%).
639 ///
640 /// Note that AbsoluteStateOfCharge() can return values greater than 100%.
641 fn absolute_state_of_charge(&mut self) -> Result<Percent, Self::Error>;
642
643 /// 0x0F
644 ///
645 /// Returns the predicted remaining battery capacity. The RemainingCapacity() capacity value is expressed in
646 /// either current (mAh at a C/5 discharge rate) or power (10mWh at a P/5 discharge rate) depending on the
647 /// setting of the BatteryMode()'s CAPACITY_MODE bit.
648 fn remaining_capacity(&mut self) -> Result<CapacityModeValue, Self::Error>;
649
650 /// 0x10
651 ///
652 /// Returns the predicted pack capacity when it is fully charged. The FullChargeCapacity() value is expressed
653 /// in either current (mAh at a C/5 discharge rate) or power (10mWh at a P/5 discharge rate) depending on the
654 /// setting of the BatteryMode()'s CAPACITY_MODE bit.
655 fn full_charge_capacity(&mut self) -> Result<CapacityModeValue, Self::Error>;
656
657 /// 0x11
658 ///
659 /// Returns the predicted remaining battery life at the present rate of discharge (minutes). The
660 /// RunTimeToEmpty() value is calculated based on either current or power depending on the setting of the
661 /// BatteryMode()'s CAPACITY_MODE bit. This is an important distinction because use of the wrong
662 /// calculation mode may result in inaccurate return values.
663 ///
664 /// 65,535 indicates battery is not being discharged.
665 fn run_time_to_empty(&mut self) -> Result<Minutes, Self::Error>;
666
667 /// 0x12
668 ///
669 /// Returns a one-minute rolling average of the predicted remaining battery life (minutes). The
670 /// AverageTimeToEmpty() value is calculated based on either current or power depending on the setting of
671 /// the BatteryMode()'s CAPACITY_MODE bit. This is an important distinction because use of the wrong
672 /// calculation mode may result in inaccurate return values.
673 ///
674 /// 65,535 indicates battery is not being discharged.
675 fn average_time_to_empty(&mut self) -> Result<Minutes, Self::Error>;
676
677 /// 0x13
678 ///
679 /// Returns a one minute rolling average of the predicted remaining time until the Smart Battery reaches full
680 /// charge (minutes).
681 ///
682 /// 65,535 indicates the battery is not being charged.
683 fn average_time_to_full(&mut self) -> Result<Minutes, Self::Error>;
684
685 /// 0x14
686 ///
687 /// The ChargingCurrent() function sets the maximum current that a Smart Battery Charger may
688 /// deliver to the Smart Battery. In combination with the ChargingVoltage() function and the
689 /// battery's internal impedance, this function determines the Smart Battery Charger's desired
690 /// operating point. Together, these functions permit a Smart Battery Charger to dynamically adjust
691 /// its charging profile (current/voltage) for optimal charge.
692 ///
693 /// The Smart Battery can turn off the Smart Battery Charger by returning a value of 0 for this function.
694 /// Smart Battery Chargers may be operated as a constant voltage source above their
695 /// maximum regulated current range by returning a ChargingCurrent() value of 65535.
696 fn charging_current(&mut self) -> Result<MilliAmps, Self::Error>;
697
698 /// 0x15
699 ///
700 /// The ChargingVoltage() function sets the maximum voltage that a Smart Battery Charger may
701 /// deliver to the Smart Battery. In combination with the ChargingCurrent() function and the
702 /// battery's internal impedance, this function determines the Smart Battery Charger's desired
703 /// operating point. Together, these functions permit a Smart Battery Charger to dynamically adjust
704 /// its charging profile (current/voltage) for optimal charge.
705 ///
706 /// The Smart Battery can turn off the Smart Battery Charger by returning a value of 0 for this function.
707 /// Smart Battery Chargers may be operated as a constant current source above their
708 /// maximum regulated voltage range by returning a ChargingVoltage() value of 65535.
709 fn charging_voltage(&mut self) -> Result<MilliVolts, Self::Error>;
710
711 /// 0x16
712 ///
713 /// Returns the Smart Battery's status word which contains Alarm and Status bit flags. Some of the
714 /// BatteryStatus() flags (REMAINING_CAPACITY_ALARM and REMAINING_TIME_ALARM) are
715 /// calculated based on either current or power depending on the setting of the BatteryMode()'s
716 /// CAPACITY_MODE bit. This is important because use of the wrong calculation mode may result in an
717 /// inaccurate alarm.
718 fn battery_status(&mut self) -> Result<BatteryStatusFields, Self::Error>;
719
720 /// 0x17
721 ///
722 /// Returns the number of cycles the battery has experienced. A cycle is defined as:
723 ///
724 /// An amount of discharge approximately equal to the value of DesignCapacity.
725 fn cycle_count(&mut self) -> Result<Cycles, Self::Error>;
726
727 /// 0x18
728 ///
729 /// Returns the theoretical capacity of a new pack. The DesignCapacity() value is expressed in either current
730 /// (mAh at a C/5 discharge rate) or power (10mWh at a P/5 discharge rate) depending on the setting of the
731 /// BatteryMode()'s CAPACITY_MODE bit.
732 fn design_capacity(&mut self) -> Result<CapacityModeValue, Self::Error>;
733
734 /// 0x19
735 ///
736 /// Returns the theoretical voltage of a new pack (mV).
737 fn design_voltage(&mut self) -> Result<MilliVolts, Self::Error>;
738
739 /// 0x1A
740 ///
741 /// Returns the version number of the Smart Battery specification the battery pack supports, as well as voltage
742 /// and current and capacity scaling information in a packed unsigned integer. Power scaling is the product of
743 /// the voltage scaling times the current scaling.
744 /// These scaling functions do NOT affect ChargingCurrent() and ChargingVoltage() values.
745 /// A Smart Battery Charger cannot be assumed to know this scaling information. (However, a ‘Level 3’
746 /// or ‘Host Controlled’ Smart Battery Charger may read this value if required for specific
747 /// applications.)
748 fn specification_info(&mut self) -> Result<SpecificationInfoFields, Self::Error>;
749
750 /// 0x1B
751 ///
752 /// This function returns the date the cell pack was manufactured.
753 fn manufacture_date(&mut self) -> Result<ManufactureDate, Self::Error>;
754
755 /// 0x1C
756 ///
757 /// This function is used to return a serial number. This number when combined with the ManufacturerName(),
758 /// the DeviceName(), and the ManufactureDate() will uniquely identify the battery (unsigned int).
759 fn serial_number(&mut self) -> Result<u16, Self::Error>;
760
761 /// 0x20
762 ///
763 /// This function accepts a mutable buffer of u8s and returns it filled with a **null-terminated** character array
764 /// containing the battery's manufacturer's name. For example, "MyBattCo\0" would identify the Smart Battery's
765 /// manufacturer as MyBattCo.
766 fn manufacturer_name(&mut self, name: &mut [u8]) -> Result<(), Self::Error>;
767
768 /// 0x21
769 ///
770 /// This function accepts a mutable buffer of u8s and returns it filled with a **null-terminated** character array
771 /// that contains the battery's name. For example, a DeviceName() of "MBC101\0" would indicate that
772 /// the battery is a model MBC101.
773 fn device_name(&mut self, name: &mut [u8]) -> Result<(), Self::Error>;
774
775 /// 0x22
776 ///
777 /// This function accepts a mutable buffer of u8s and returns it filled with a **null-terminated** character array
778 /// that contains the battery's chemistry. For example, if the DeviceChemistry() function returns "NiMH\0",
779 /// the battery pack would contain nickel metal hydride cells.
780 fn device_chemistry(&mut self, chemistry: &mut [u8]) -> Result<(), Self::Error>;
781}
782
783#[macro_export]
784/// Helper macro to implement `SmartBattery` and `ErrorType` for wrapper types that just call an inner type's SmartBattery methods.
785///
786/// This macro generates implementations of both the `SmartBattery` trait and the `ErrorType` trait
787/// for a wrapper type that contains an inner type implementing `SmartBattery`. Each trait method
788/// delegates to the corresponding inner type method, automatically converting errors from the inner
789/// type to the wrapper's error type.
790///
791/// # Requirements
792///
793/// - `From<inner::Error>` must be implemented for the wrapper error type to enable error conversion
794/// - The wrapper error type must implement the `Error` trait
795///
796/// # Parameters
797///
798/// - `$wrapper`: The wrapper type that will implement `SmartBattery` and `ErrorType`
799/// - `$inner`: The field name within the wrapper that contains the inner `SmartBattery` implementation
800/// - `$error`: The error type associated with the wrapper
801///
802/// # Example
803///
804/// ```ignore
805/// struct BatteryWrapper {
806/// driver: DriverImplingSmartBattery,
807/// }
808///
809/// impl From<DriverImplingSmartBatteryError> for WrapperError {
810/// fn from(err: DriverImplingSmartBatteryError) -> Self {
811/// WrapperError::BatteryError(err)
812/// }
813/// }
814///
815/// impl_smart_battery_for_wrapper_type!(BatteryWrapper, driver, WrapperError);
816/// ```
817macro_rules! impl_smart_battery_for_wrapper_type {
818 ($wrapper:ty, $inner:ident, $error:ty) => {
819 impl embedded_batteries::smart_battery::ErrorType for $wrapper {
820 type Error = $error;
821 }
822
823 #[allow(clippy::needless_question_mark)]
824 impl embedded_batteries::smart_battery::SmartBattery for $wrapper {
825 fn remaining_capacity_alarm(
826 &mut self,
827 ) -> Result<embedded_batteries::smart_battery::CapacityModeValue, Self::Error> {
828 Ok(self.$inner.remaining_capacity_alarm()?)
829 }
830
831 fn set_remaining_capacity_alarm(
832 &mut self,
833 capacity: embedded_batteries::smart_battery::CapacityModeValue,
834 ) -> Result<(), Self::Error> {
835 Ok(self.$inner.set_remaining_capacity_alarm(capacity)?)
836 }
837
838 fn remaining_time_alarm(&mut self) -> Result<embedded_batteries::smart_battery::Minutes, Self::Error> {
839 Ok(self.$inner.remaining_time_alarm()?)
840 }
841
842 fn set_remaining_time_alarm(
843 &mut self,
844 time: embedded_batteries::smart_battery::Minutes,
845 ) -> Result<(), Self::Error> {
846 Ok(self.$inner.set_remaining_time_alarm(time)?)
847 }
848
849 fn battery_mode(&mut self) -> Result<embedded_batteries::smart_battery::BatteryModeFields, Self::Error> {
850 Ok(self.$inner.battery_mode()?)
851 }
852
853 fn set_battery_mode(
854 &mut self,
855 flags: embedded_batteries::smart_battery::BatteryModeFields,
856 ) -> Result<(), Self::Error> {
857 Ok(self.$inner.set_battery_mode(flags)?)
858 }
859
860 fn at_rate(&mut self) -> Result<embedded_batteries::smart_battery::CapacityModeSignedValue, Self::Error> {
861 Ok(self.$inner.at_rate()?)
862 }
863
864 fn set_at_rate(
865 &mut self,
866 rate: embedded_batteries::smart_battery::CapacityModeSignedValue,
867 ) -> Result<(), Self::Error> {
868 Ok(self.$inner.set_at_rate(rate)?)
869 }
870
871 fn at_rate_time_to_full(&mut self) -> Result<embedded_batteries::smart_battery::Minutes, Self::Error> {
872 Ok(self.$inner.at_rate_time_to_full()?)
873 }
874
875 fn at_rate_time_to_empty(&mut self) -> Result<embedded_batteries::smart_battery::Minutes, Self::Error> {
876 Ok(self.$inner.at_rate_time_to_empty()?)
877 }
878
879 fn at_rate_ok(&mut self) -> Result<bool, Self::Error> {
880 Ok(self.$inner.at_rate_ok()?)
881 }
882
883 fn temperature(&mut self) -> Result<embedded_batteries::smart_battery::DeciKelvin, Self::Error> {
884 Ok(self.$inner.temperature()?)
885 }
886
887 fn voltage(&mut self) -> Result<embedded_batteries::charger::MilliVolts, Self::Error> {
888 Ok(self.$inner.voltage()?)
889 }
890
891 fn current(&mut self) -> Result<embedded_batteries::smart_battery::MilliAmpsSigned, Self::Error> {
892 Ok(self.$inner.current()?)
893 }
894
895 fn average_current(&mut self) -> Result<embedded_batteries::smart_battery::MilliAmpsSigned, Self::Error> {
896 Ok(self.$inner.average_current()?)
897 }
898
899 fn max_error(&mut self) -> Result<embedded_batteries::smart_battery::Percent, Self::Error> {
900 Ok(self.$inner.max_error()?)
901 }
902
903 fn relative_state_of_charge(&mut self) -> Result<embedded_batteries::smart_battery::Percent, Self::Error> {
904 Ok(self.$inner.relative_state_of_charge()?)
905 }
906
907 fn absolute_state_of_charge(&mut self) -> Result<embedded_batteries::smart_battery::Percent, Self::Error> {
908 Ok(self.$inner.absolute_state_of_charge()?)
909 }
910
911 fn remaining_capacity(
912 &mut self,
913 ) -> Result<embedded_batteries::smart_battery::CapacityModeValue, Self::Error> {
914 Ok(self.$inner.remaining_capacity()?)
915 }
916
917 fn full_charge_capacity(
918 &mut self,
919 ) -> Result<embedded_batteries::smart_battery::CapacityModeValue, Self::Error> {
920 Ok(self.$inner.full_charge_capacity()?)
921 }
922
923 fn run_time_to_empty(&mut self) -> Result<embedded_batteries::smart_battery::Minutes, Self::Error> {
924 Ok(self.$inner.run_time_to_empty()?)
925 }
926
927 fn average_time_to_empty(&mut self) -> Result<embedded_batteries::smart_battery::Minutes, Self::Error> {
928 Ok(self.$inner.average_time_to_empty()?)
929 }
930
931 fn average_time_to_full(&mut self) -> Result<embedded_batteries::smart_battery::Minutes, Self::Error> {
932 Ok(self.$inner.average_time_to_full()?)
933 }
934
935 fn charging_current(&mut self) -> Result<embedded_batteries::charger::MilliAmps, Self::Error> {
936 Ok(self.$inner.charging_current()?)
937 }
938
939 fn charging_voltage(&mut self) -> Result<embedded_batteries::charger::MilliVolts, Self::Error> {
940 Ok(self.$inner.charging_voltage()?)
941 }
942
943 fn battery_status(
944 &mut self,
945 ) -> Result<embedded_batteries::smart_battery::BatteryStatusFields, Self::Error> {
946 Ok(self.$inner.battery_status()?)
947 }
948
949 fn cycle_count(&mut self) -> Result<embedded_batteries::smart_battery::Cycles, Self::Error> {
950 Ok(self.$inner.cycle_count()?)
951 }
952
953 fn design_capacity(&mut self) -> Result<embedded_batteries::smart_battery::CapacityModeValue, Self::Error> {
954 Ok(self.$inner.design_capacity()?)
955 }
956
957 fn design_voltage(&mut self) -> Result<embedded_batteries::charger::MilliVolts, Self::Error> {
958 Ok(self.$inner.design_voltage()?)
959 }
960
961 fn specification_info(
962 &mut self,
963 ) -> Result<embedded_batteries::smart_battery::SpecificationInfoFields, Self::Error> {
964 Ok(self.$inner.specification_info()?)
965 }
966
967 fn manufacture_date(&mut self) -> Result<embedded_batteries::smart_battery::ManufactureDate, Self::Error> {
968 Ok(self.$inner.manufacture_date()?)
969 }
970
971 fn serial_number(&mut self) -> Result<u16, Self::Error> {
972 Ok(self.$inner.serial_number()?)
973 }
974
975 fn manufacturer_name(&mut self, name: &mut [u8]) -> Result<(), Self::Error> {
976 Ok(self.$inner.manufacturer_name(name)?)
977 }
978
979 fn device_name(&mut self, name: &mut [u8]) -> Result<(), Self::Error> {
980 Ok(self.$inner.device_name(name)?)
981 }
982
983 fn device_chemistry(&mut self, chemistry: &mut [u8]) -> Result<(), Self::Error> {
984 Ok(self.$inner.device_chemistry(chemistry)?)
985 }
986 }
987 };
988}