-
Notifications
You must be signed in to change notification settings - Fork 427
/
comm_sbs_bqctrl.py
3755 lines (3300 loc) · 151 KB
/
comm_sbs_bqctrl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Smart Battery System communication tool.
This tool allows to interact with chips designed based on Smart Battery Data
Specification. It also supports some extensions to that specification
implemented by Texas Instruments in their BQ series gas gauge chips.
Usage of this tool requires connection to SMBus lines (SDA,SCL,GND) of the
SBS-compatible chip. SMBus communication uses I2C as a base, so most devices
with I2C bus can be used to establish the communication.
This tool was written with intent to be used on Raspberry Pi and its I2C bus.
Using a different device will require slight modifications to the code.
You do not need the TI EV2300 programmer to use this script.
To get address of the device, you may use `i2cdetect`. Don't be scared about
the interactive messages, SBS is a well defined protocol which isn't easy to
break, especially when the chip is sealed. Probing will not accidently result
in a packet which disables the battery forever.
If the battery already has I2C master device on the bus (like uC on battery
board), try not to turn on the battery for use with this program. The SBS chip
should wake from sleep to answer on requests from this program, and if the
battery is turned on, the constant communication from internal master will
interfere with packets sent by this tool. It can also cause the battery
to enter temporary SMBus error mode. To avoid that, don't even press the
battery button while it is connected to I2C interface.
Though in case of connection issues, you may try re-running the script when
battery is on. The uC of some batteries keeps the line shorted to high state
when turned off.
Another thing to try on issues is using your bus through both SMBus API and
I2C API, using "--bus" parameter.
If the script shows "OSError: [Errno 74] Bad message", the very likely
cause is invalid I2C speed. Check how to change baud rate of your
I2C bus device. Baud rate of 100kbps should work. The EV2300 usually
uses baud rate of 66kbps, though for some chips it switches to 30kbps.
If the script shows "OSError: [Errno 121] Remote I/O error", that means
the device did not respond to a command. It's hard to say if there was no
response at all, or only to a specific part. This one may also happen when
trying to access priviliged command in sealed state. Make sure you can see
the device with 'i2cdetect'. If not, check physical connections. Make sure
that no other device interferes with the communication - it is known that
even unpowered EV2300 programmer connected to the bus can interfere with
signals on lines.
On Raspberry Pi, the "Remote I/O error" can sometimes disappear after
starting GPIO deamon with high sampling rate, ie. `sudo pigpiod -s 1`.
Constant probing of the line affects its impedance, which may sometimes
lead to such unusual effects.
There is also "OSError: [Errno 5] Input/output error" which tend to happen
interchangeably with "Remote I/O error", but only if the other side responds
to part of the message.
Finally, remember that cheap I2C devices can sometimes get into unuseable
state - make sure you reboot the Raspberry Pi, or re-connect the USB stick,
if logic signal changes are visible but I2C still refuses to detect anything.
Tested devices:
(these devices are confirmed)
BQ30z55 fw 0.36, Mavic Pro battery, 2021-02-15, mefistotelis
Devices verified with spec:
(should work, but not actually tested)
BQ30z50, BQ30z554
For other devices, only basic SBS functions are expected to work.
Using chip-specific commands on them may have undesired effects.
To make sure a command is safe, check Reference Manual of the chip
and make sure the command is defined in the same way as in spec of
one of tested devices.
"""
__version__ = "0.2.1"
__author__ = "Mefistotelis @ Original Gangsters"
__license__ = "GPL"
import re
import sys
import time
import enum
import types
import struct
import hashlib
import argparse
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
class DecoratedEnum(enum.Enum):
@classmethod
def from_name(cls, name):
for itm in cls:
if itm.name == name:
return itm
raise ValueError("{} is not a known value".format(name))
class ImprovisedCommand(types.SimpleNamespace):
def __hash__(self):
return hash(self.value)
class CHIP_TYPE(DecoratedEnum):
""" Smart Battery System chip type
"""
AUTO = 0
SBS = 1
# Texas Instruments BQ chips; lower 16 bits are DeviceType
BQGENERIC = 0x010000
BQ20z45 = 0x010450
BQ30z50 = 0x010500
BQ30z55 = 0x010550
BQ30z554 = 0x010554
BQ20z65 = 0x010650
BQ3050 = 0x013050
BQ3060 = 0x013060
BQ40z307 = 0x014307 # hw marking bq9003; custom chip for DJI
BQ40370 = 0x019db2
# supported by BatteryManagementStudio-1.3
BQ35100 = 0x010100 # hw marking bq8035;
BQ34110 = 0x010110 # hw marking bq8035;
BQ34210 = 0x010210 # hw marking bq8101;
BQ27220 = 0x010220 # hw marking bq8101;
BQ27320 = 0x010320 # hw marking bq8035;
BQ27421 = 0x010421 # hw marking bq8101; seem to also be BQ27411 ?
BQ27425 = 0x010425 # hw marking bq8036;
BQ27426 = 0x010426 # hw marking bq8101;
BQ27510 = 0x010510 # hw marking bq8035;
BQ27520 = 0x010520 # hw marking bq8035;
BQ27530 = 0x010530 # hw marking bq8035;
BQ27531 = 0x010531 # hw marking bq8035;
BQ27532 = 0x010532 # hw marking bq8035;
BQ27541 = 0x010541 # hw marking bq8034;
BQ27542 = 0x010542 # hw marking bq8034;
BQ27545 = 0x010545 # hw marking bq8035;
BQ27546 = 0x010546 # hw marking bq8034;
BQ27621 = 0x010621 # hw marking bq8101;
BQ27742 = 0x010742 # hw marking bq8037;
BQ78z100 = 0x011100 # hw marking bq9002;
BQ27z561 = 0x011561 # hw marking bq9035;
BQ78350 = 0x011e9b # hw marking bq8030;
BQ28z610 = 0x012610 # hw marking bq9002;
BQ40z50 = 0x014500 # hw marking bq9000;
BQ40z60 = 0x014600 # hw marking bq9000;
BQ40z80 = 0x014800 # hw marking bq9006; seem to also be BQ40z70 ?
BQ4050 = 0x019e34 # hw marking bq9000;
BQ769x2 = 0x017692 # hw marking bq7692; BQ76942/BQ76952
CHIP_TYPE.AUTO.__doc__ = "Automatic detection of the chip"
CHIP_TYPE.SBS.__doc__ = "Generic chip with SBS support"
CHIP_TYPE.BQGENERIC.__doc__ = "Unidentified chip from TI BQ family"
CHIP_TYPE.BQ30z55.__doc__ = "Texas Instruments BQ30z55 chip"
CHIP_TYPE.BQ20z65.__doc__ = "Texas Instruments BQ20z65 chip"
CHIP_TYPE.BQ3050.__doc__ = "Texas Instruments BQ3050 chip"
CHIP_TYPE.BQ3060.__doc__ = "Texas Instruments BQ3060 chip"
CHIP_TYPE.BQ40z307.__doc__ = "Texas Instruments BQ40z307 chip for DJI"
CHIP_TYPE.BQ40370.__doc__ = "Texas Instruments BQ40370 chip"
CHIP_TYPE.BQ35100.__doc__ = "Texas Instruments BQ35100 chip"
CHIP_TYPE.BQ34110.__doc__ = "Texas Instruments BQ34110 chip"
CHIP_TYPE.BQ34210.__doc__ = "Texas Instruments BQ34210 chip"
CHIP_TYPE.BQ27220.__doc__ = "Texas Instruments BQ27220 chip"
CHIP_TYPE.BQ27320.__doc__ = "Texas Instruments BQ27320 chip"
CHIP_TYPE.BQ27421.__doc__ = "Texas Instruments BQ27411/BQ27421 chip"
CHIP_TYPE.BQ27425.__doc__ = "Texas Instruments BQ27425 chip"
CHIP_TYPE.BQ27426.__doc__ = "Texas Instruments BQ27426 chip"
CHIP_TYPE.BQ27510.__doc__ = "Texas Instruments BQ27510 chip"
CHIP_TYPE.BQ27520.__doc__ = "Texas Instruments BQ27520 chip"
CHIP_TYPE.BQ27530.__doc__ = "Texas Instruments BQ27530 chip"
CHIP_TYPE.BQ27531.__doc__ = "Texas Instruments BQ27531 chip"
CHIP_TYPE.BQ27532.__doc__ = "Texas Instruments BQ27532 chip"
CHIP_TYPE.BQ27541.__doc__ = "Texas Instruments BQ27541 chip"
CHIP_TYPE.BQ27542.__doc__ = "Texas Instruments BQ27542 chip"
CHIP_TYPE.BQ27545.__doc__ = "Texas Instruments BQ27545 chip"
CHIP_TYPE.BQ27546.__doc__ = "Texas Instruments BQ27546 chip"
CHIP_TYPE.BQ27621.__doc__ = "Texas Instruments BQ27621 chip"
CHIP_TYPE.BQ27742.__doc__ = "Texas Instruments BQ27742 chip"
CHIP_TYPE.BQ78z100.__doc__ = "Texas Instruments BQ78z100 chip"
CHIP_TYPE.BQ27z561.__doc__ = "Texas Instruments BQ27z561 chip"
CHIP_TYPE.BQ78350.__doc__ = "Texas Instruments BQ78350 chip"
CHIP_TYPE.BQ28z610.__doc__ = "Texas Instruments BQ28z610 chip"
CHIP_TYPE.BQ40z50.__doc__ = "Texas Instruments BQ40z50 chip"
CHIP_TYPE.BQ40z60.__doc__ = "Texas Instruments BQ40z60 chip"
CHIP_TYPE.BQ40z80.__doc__ = "Texas Instruments BQ40z70/BQ40z80 chip"
CHIP_TYPE.BQ4050.__doc__ = "Texas Instruments BQ4050 chip"
CHIP_TYPE.BQ769x2.__doc__ = "Texas Instruments BQ76942/BQ76952 chip"
class SBS_COMMAND(DecoratedEnum):
""" Smart Battery Data Specification 1.1 commands list
This is a list taken directly from specification.
"""
ManufacturerAccess = 0x00
RemainingCapacityAlarm = 0x01
RemainingTimeAlarm = 0x02
BatteryMode = 0x03
AtRate = 0x04
AtRateToFull = 0x05
AtRateToEmpty = 0x06
AtRateOK = 0x07
Temperature = 0x08
Voltage = 0x09
Current = 0x0a
AverageCurrent = 0x0b
MaxError = 0x0c
RelativeStateOfCharge = 0x0d
AbsoluteStateOfCharge = 0x0e
RemainingCapacity = 0x0f
FullChargeCapacity = 0x10
RunTimeToEmpty = 0x11
AverageTimeToEmpty = 0x12
AverageTimeToFull = 0x13
ChargingCurrent = 0x14
ChargingVoltage = 0x15
BatteryStatus = 0x16
CycleCount = 0x17
DesignCapacity = 0x18
DesignVoltage = 0x19
SpecificationInfo = 0x1a
ManufactureDate = 0x1b
SerialNumber = 0x1c
ManufacturerName = 0x20
DeviceName = 0x21
DeviceChemistry = 0x22
ManufacturerData = 0x23
OptionalMfgFunction5 = 0x2f
OptionalMfgFunction4 = 0x3c
OptionalMfgFunction3 = 0x3d
OptionalMfgFunction2 = 0x3e
OptionalMfgFunction1 = 0x3f
class RAW_ADDRESS_SPACE_KIND_BQGENERIC(DecoratedEnum):
""" Address spaces used in BQ family SBS chips
"""
DataFlash = 0x00
InstructionFlash = 0x01
class MANUFACTURER_ACCESS_CMD_BQGENERIC(DecoratedEnum):
""" ManufacturerAccess sub-commands used in all BQ family SBS chips
"""
ManufacturerData = 0x00
DeviceType = 0x01
FirmwareVersion = 0x02
HardwareVersion = 0x03
class SBS_FLAG_BATTERY_MODE(DecoratedEnum):
""" Flags used in BatteryMode command
"""
INTERNAL_CHARGE_CONTROLLER = 0
PRIMARY_BATTERY_SUPPORT = 1
RESERVED2 = 2
RESERVED3 = 3
RESERVED4 = 4
RESERVED5 = 5
RESERVED6 = 6
CONDITION_FLAG = 7
CHARGE_CONTROLLER_ENABLED = 8
PRIMARY_BATTERY = 9
RESERVED10 = 10
RESERVED11 = 11
RESERVED12 = 12
ALARM_MODE = 13
CHARGER_MODE = 14
CAPACITY_MODE = 15
class SBS_FLAG_BATTERY_STATUS(DecoratedEnum):
""" Flags used in BatteryStatus command
"""
ERROR_CODE = 0
FULLY_DISCHARGED = 4
FULLY_CHARGED = 5
DISCHARGING = 6
INITIALIZED = 7
REMAINING_TIME_ALARM = 8
REMAINING_CAPACITY_ALARM = 9
RESERVED10 = 10
TERMINATE_DISCHARGE_ALARM = 11
OVERTEMPERATURE_ALARM = 12
RESERVED13 = 13
TERMINATE_CHARGE_ALARM = 14
OVER_CHARGED_ALARM = 15
class SBS_FLAG_SPECIFICATION_INFO(DecoratedEnum):
""" Flags used in SpecificationInfo command
"""
Revision = 0
Version = 4
VScale = 8
IPScale = 12
class MONITOR_GROUP(DecoratedEnum):
""" List of groups of commands/offsets.
"""
DeviceInfo = 0x00
UsageInfo = 0x01
ComputedInfo = 0x02
StatusBits = 0x03
AtRates = 0x04
BQStatusBits = 0x06
BQStatusBitsMA = 0x07
BQCellVoltages = 0x08
BQLifetimeData = 0x09
BQLifetimeDataMA = 0x0a
ImpedanceTrack = 0x0b
ImpedanceTrackMA = 0x0c
BQTurboMode = 0x0f
# Global variables, modified by chip drivers
MANUFACTURER_ACCESS_CMD_BQ_INFO = {}
MANUFACTURER_BLOCK_ACCESS_CMD_BQ_INFO = {}
SBS_BATTERY_MODE_INFO = {}
SBS_BATTERY_STATUS_INFO = {}
SBS_SPECIFICATION_INFO = {}
SBS_CMD_INFO = {}
RAW_ADDRESS_SPACE_KIND_INFO = {}
SBS_CMD_GROUPS = {}
SBS_SEALING = {}
def reset_default_driver(po):
""" Sets global variables to no chip-specific driver loaded state.
"""
global MANUFACTURER_ACCESS_CMD_BQ_INFO
MANUFACTURER_ACCESS_CMD_BQ_INFO = {
MANUFACTURER_ACCESS_CMD_BQGENERIC.ManufacturerData : {
'type' : "uint16",
'unit' : {'scale':1,'name':"hex"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Output ManufacturerData()."),
},
MANUFACTURER_ACCESS_CMD_BQGENERIC.DeviceType : {
'type' : "uint16_blk",
'unit' : {'scale':1,'name':"hex"},
'resp_location' : SBS_COMMAND.ManufacturerData,
'access_per_seal' : ("r","r","r",),
'desc' : ("IC device part number."),
},
MANUFACTURER_ACCESS_CMD_BQGENERIC.FirmwareVersion : {
'type' : "byte[13]",
'unit' : {'scale':None,'name':"hex"},
'resp_location' : SBS_COMMAND.ManufacturerData,
'access_per_seal' : ("r","r","r",),
'desc' : ("Version of the firmware within the device. Major and "
"minor version numbers."),
},
MANUFACTURER_ACCESS_CMD_BQGENERIC.HardwareVersion : {
'type' : "uint16_blk",
'unit' : {'scale':1,'name':"dec"},
'resp_location' : SBS_COMMAND.ManufacturerData,
'access_per_seal' : ("r","r","r",),
'desc' : ("The IC hardware revision."),
},
}
global MANUFACTURER_BLOCK_ACCESS_CMD_BQ_INFO
MANUFACTURER_BLOCK_ACCESS_CMD_BQ_INFO = {
}
global SBS_BATTERY_MODE_INFO
SBS_BATTERY_MODE_INFO = {
SBS_FLAG_BATTERY_MODE.INTERNAL_CHARGE_CONTROLLER : {
# Data type associated with the field
# For strings, it also contains expected length (which can be exceeeded,
# as all strings are up to 32 bytes, but this causes a second read)
'type' : "named_bitfield",
# Measurement unit in which data type is stored
'unit' : {'scale':1,'name':"boolean"},
# Amount of bits in this field
'nbits' : 1,
# Names for possible values
'value_names' : ["No support","Supported"],
# Access to the field
'access' : "r",
# Very short name of this field,
'tiny_name' : "ICC",
# Description, with first sentence making a short description,
'desc' : ("Internal Charge Controller circuit available. The ICC "
"accepts power from the battery terminals but may regulate or "
"otherwise control the current and voltage that actually reaches "
"the battery’s cells. "
"When the bit is set, the CHARGE_CONTROLLER_ENABLED bit will be "
"available for activation and control of the actual internal "
"charger."),
},
SBS_FLAG_BATTERY_MODE.PRIMARY_BATTERY_SUPPORT: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["No support","Supported"],
'access' : "r",
'tiny_name' : "PBS",
'desc' : ("Ability to act as primary or secondary battery. The "
"Primary/Secondary battery feature is used with batteries "
"containing internal discharge control mechanisms to allow "
"multiple batteries to be connected in parallel. This bit "
"indicates the presence of this internal control, while the "
"PRIMARY_BATTERY bit actually controls the on/off state of "
"this internal control."),
},
SBS_FLAG_BATTERY_MODE.RESERVED2: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.RESERVED3: {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.RESERVED4: {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.RESERVED5: {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.RESERVED6: {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.CONDITION_FLAG: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["No need","Requested"],
'access' : "r",
'tiny_name' : "CF",
'desc' : ("Battery requests a conditioning cycle. A conditioning "
"cycle may be requested because of the characteristics of the "
"battery chemistry and/or the electronics in combination with "
"the usage pattern. "
"This flag is the first signal from the Smart Battery that it "
"has limited ability to determine the present state-of-charge."),
},
SBS_FLAG_BATTERY_MODE.CHARGE_CONTROLLER_ENABLED: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Disabled","Enabled"],
'access' : "rw",
'tiny_name' : "CC",
'desc' : ("Battery pack's internal charge controller state. When "
"this bit is cleared, the internal charge controller is disabled. "
"This bit is active only when the INTERNAL_CHARGE_CONTROLLER bit "
"is set, indicating that this function is supported."),
},
SBS_FLAG_BATTERY_MODE.PRIMARY_BATTERY: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Secondary","Primary"],
'access' : "rw",
'tiny_name' : "PB",
'desc' : ("Operate as the pri/sec battery in a system. When this bit "
"is cleared, the battery operates in a secondary role. This bit "
"is active only when the PRIMARY_BATTERY_SUPPORT bit is set. The "
"optional Primary/Secondary battery feature is used with batteries "
"containing internal discharge control mechanisms to allow multiple "
"batteries to be connected in parallel."),
},
SBS_FLAG_BATTERY_MODE.RESERVED10: {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.RESERVED11: {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.RESERVED12: {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "Rsvd",
'desc' : ("Reserved by SBS spec. This field cannot be used unless "
"future version of SBS specification defines its meaning."),
},
SBS_FLAG_BATTERY_MODE.ALARM_MODE: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Tx enabled","Tx disabled"],
'access' : "rw",
'tiny_name' : "AM",
'desc' : ("Don't master the SMBus and send AlarmWarning(). "
"When set, the Smart Battery will NOT master the SMBus and "
"messages will NOT be sent to the SMBus Host and the Smart Battery "
"Charger. Automatically cleared by the Smart Battery electronics "
"every 60 seconds."),
},
SBS_FLAG_BATTERY_MODE.CHARGER_MODE: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Tx enabled","Tx disabled"],
'access' : "rw",
'tiny_name' : "ChgM",
'desc' : ("Don't send ChargingCurrent() and ChargingVoltage(). "
"When set, the Smart Battery will NOT transmit charging values to "
"the Smart Battery Charger. When cleared, the Battery will transmit "
"the ChargingCurrent() and ChargingVoltage() values to the Smart "
"Battery Charger when charging is desired."),
},
SBS_FLAG_BATTERY_MODE.CAPACITY_MODE: {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Report in mAh","Report in 10mWh"],
'access' : "rw",
'tiny_name' : "CapM",
'desc' : ("Capacity reporting unit, mA/mAh or 10mW/10mWh. After "
"changing this bit, all related values (such as AtRate()) should "
"be re-written while the new mode is active. This bit allows "
"power management systems to best match their electrical "
"characteristics with those reported by the battery. For example,"
" a switching power supply represents a constant power load, "
"whereas a linear supply is better represented by a constant "
"current model."),
},
}
global SBS_BATTERY_STATUS_INFO
SBS_BATTERY_STATUS_INFO = {
SBS_FLAG_BATTERY_STATUS.ERROR_CODE : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"dec"},
'nbits' : 4,
'value_names' : ["OK", "Busy", "Reserved Cmd", "Unsupported Cmd",
"Access Denied", "Over/Underflow", "Bad Size", "Unknown Error"],
'access' : "r",
'tiny_name' : "EC",
'desc' : ("Function error code. Error code generated by function "
"of the last command."),
},
SBS_FLAG_BATTERY_STATUS.FULLY_DISCHARGED : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Not fully","Fully"],
'access' : "r",
'tiny_name' : "FD",
'desc' : ("Battery capacity is depleted. Cleared when "
"RelativeStateOfCharge() value rises above 20% again."),
},
SBS_FLAG_BATTERY_STATUS.FULLY_CHARGED : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Not fully","Fully"],
'access' : "r",
'tiny_name' : "FC",
'desc' : ("Battery is full. Set when further charge is not required."),
},
SBS_FLAG_BATTERY_STATUS.DISCHARGING : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["No","Yes"],
'access' : "r",
'tiny_name' : "DSG",
'desc' : ("Battery is discharging. This is set by both external "
"load and self-discharge, so it does not always indicate that "
"a discharge current is present."),
},
SBS_FLAG_BATTERY_STATUS.INITIALIZED : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Correct","Recalibrate"],
'access' : "r",
'tiny_name' : "INIT",
'desc' : ("State of calibration/configuration. Battery electronics "
"are first calibrated and configured at time of manufacture. This "
"flag is set when calibration or configuration information has "
"been lost, and accuracy is significantly impaired."),
},
SBS_FLAG_BATTERY_STATUS.REMAINING_TIME_ALARM : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Inactive","Active"],
'access' : "r",
'tiny_name' : "RTA",
'desc' : ("Remaining time to depletion alarm tripped. Set when "
"value of AverageTimeToEmpty() is less than the value "
"of RemainingTimeAlarm()."),
},
SBS_FLAG_BATTERY_STATUS.REMAINING_CAPACITY_ALARM : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Inactive","Active"],
'access' : "r",
'tiny_name' : "RCA",
'desc' : ("Remaining capacity alarm tripped. Set when "
"value of RemainingCapacity() is less than the value "
"of RemainingCapacityAlarm()."),
},
SBS_FLAG_BATTERY_STATUS.RESERVED10 : {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "ResA",
'desc' : ("Purpose undefined."),
},
SBS_FLAG_BATTERY_STATUS.TERMINATE_DISCHARGE_ALARM : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Inactive","Active"],
'access' : "r",
'tiny_name' : "TDA",
'desc' : ("Battery capacity is depleted. Stop Discharge As Soon As "
"Possible."),
},
SBS_FLAG_BATTERY_STATUS.OVERTEMPERATURE_ALARM : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Inactive","Active"],
'access' : "r",
'tiny_name' : "OTA",
'desc' : ("Temperature is above pre-set limit."),
},
SBS_FLAG_BATTERY_STATUS.RESERVED13 : {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'access' : "-",
'tiny_name' : "ResD",
'desc' : ("Purpose undefined."),
},
SBS_FLAG_BATTERY_STATUS.TERMINATE_CHARGE_ALARM : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Inactive","Active"],
'access' : "r",
'tiny_name' : "TCA",
'desc' : ("Charging should be suspended. Stop Charging temporarily. "
"Charging may be re-started when conditions permit."),
},
SBS_FLAG_BATTERY_STATUS.OVER_CHARGED_ALARM : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"boolean"},
'nbits' : 1,
'value_names' : ["Inactive","Active"],
'access' : "r",
'tiny_name' : "OCA",
'desc' : ("Battery is fully charged. Stop charging."),
},
}
global SBS_SPECIFICATION_INFO
SBS_SPECIFICATION_INFO = {
SBS_FLAG_SPECIFICATION_INFO.Revision : {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"dec"},
'nbits' : 4,
'access' : "r",
'tiny_name' : "Rev",
'desc' : ("Supported SBS revision. Identifies revision of the "
"Smart Battery Specification document used to design this chip."),
},
SBS_FLAG_SPECIFICATION_INFO.Version : {
'type' : "named_bitfield",
'unit' : {'scale':1,'name':"dec"},
'nbits' : 4,
'value_names' : ["v0-none","v1.0","v1.1","v1.1+PEC","vFuture4",
"vFuture5","vFuture6","vFuture7"],
'access' : "r",
'tiny_name' : "Ver",
'desc' : ("Supported SBS version. Identifies Smart Battery "
"Specification version used to design this chip."),
},
SBS_FLAG_SPECIFICATION_INFO.VScale : {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"dec"},
'nbits' : 4,
'access' : "r",
'tiny_name' : "VSc",
'desc' : ("Voltage scaling exponent. Multiplies voltages "
"by 10 ^ VScale."),
},
SBS_FLAG_SPECIFICATION_INFO.IPScale : {
'type' : "int_bitfield",
'unit' : {'scale':1,'name':"dec"},
'nbits' : 4,
'access' : "r",
'tiny_name' : "IPSc",
'desc' : ("Current/capacity scaling exp. Multiplies currents "
"and capacities by 10 ^ IPScale."),
},
}
global SBS_CMD_INFO
SBS_CMD_INFO = {
SBS_COMMAND.ManufacturerAccess : {
# Data type associated with the function
'type' : "uint16",
# Measurement unit in which data type is stored
'unit' : {'scale':1,'name':"variable"},
# Tuple which contains all possible lists of sub-commands
# The getter algorithm should know which of these lists to use
# depending on chip model, and possibly other variables
'subcmd_infos' : (MANUFACTURER_ACCESS_CMD_BQ_INFO,),
# Access to the function in BQ seal modes: sealed, unsealed, full access;
# Access modes are defined this way in TI BQ chips, they're not part of SBS.
'access_per_seal' : ("rw","rw","rw",),
# Description, with first sentence making a short description,
'desc' : ("Optional command, is implementation specific. "
"It may be used by a battery manufacturer or silicon supplier to "
"return specific version information, internal calibration "
"information, or some other manufacturer specific function."),
# Selection of an algorithm to read/write the value of this function
'getter' : "write_word_subcommand",
},
SBS_COMMAND.RemainingCapacityAlarm : {
'type' : "uint16",
'unit0' : {'scale':1,'name':"mAh"},
'unit1' : {'scale':10,'name':"mWh"},
'access_per_seal' : ("rw","rw","rw",),
'desc' : ("Low Capacity alarm threshold value. Whenever the "
"RemainingCapacity() falls below the Low Capacity value, the "
"Smart Battery sends AlarmWarning() messages to the SMBus Host "
"with the REMAINING_CAPACITY_ALARM bit set. A Low Capacity value "
"of 0 disables this alarm. Unit depends on BatteryMode()'s "
"CAPACITY_MODE bit."),
'getter' : "unit_select_on_capacity_mode",
},
SBS_COMMAND.RemainingTimeAlarm : {
'type' : "uint16",
'unit' : {'scale':1,'name':"minutes"},
'access_per_seal' : ("rw","rw","rw",),
'desc' : ("Remaining Time alarm value. Whenever the AverageTimeToEmpty() "
"falls below the Remaining Time value, the Smart Battery sends "
"AlarmWarning() messages to the SMBus Host with the "
"REMAINING_TIME_ALARM bit set. A Remaining Time value of 0 "
"effectively disables this alarm."),
'getter' : "simple",
},
SBS_COMMAND.BatteryMode : {
'type' : "uint16",
'unit' : {'scale':1,'name':"bitfields"},
'bitfields_info' : SBS_BATTERY_MODE_INFO,
'access_per_seal' : ("rw","rw","rw",),
'desc' : ("Battery modes and capabilities. Selects the various battery "
"operational modes and reports the battery’s capabilities, modes, "
"and flags minor conditions requiring attention."),
'getter' : "simple",
},
SBS_COMMAND.AtRate : {
'type' : "int16",
'unit' : {'scale':1,'name':"mA"},
'access_per_seal' : ("rw","rw","rw",),
'desc' : ("The AtRate value used in calculations. First half of "
"a two-function call-set used to set the AtRate value used in "
"calculations made by the AtRateTimeToFull(), AtRateTimeToEmpty(), "
"and AtRateOK() functions. The AtRate value may be expressed in "
"either current (mA) or power (10mW) depending on the setting of "
"the BatteryMode()'s CAPACITY_MODE bit."),
'getter' : "simple",
},
SBS_COMMAND.AtRateToFull : {
'type' : "uint16",
'unit' : {'scale':1,'name':"minutes"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Predicted remaining time to fully charge the battery. "
"Uses the previously written AtRate value."),
'getter' : "simple",
},
SBS_COMMAND.AtRateToEmpty : {
'type' : "uint16",
'unit' : {'scale':1,'name':"minutes"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Predicted remaining operating time when discharging. "
"Uses the previously written AtRate value."),
'getter' : "simple",
},
SBS_COMMAND.AtRateOK : {
'type' : "uint16",
'unit' : {'scale':1,'name':"boolean"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Whether can deliver an additional energy for 10 sec."
"Uses the previously written AtRate value for additional energy "
"amount."),
'getter' : "simple",
},
SBS_COMMAND.Temperature : {
'type' : "uint16",
'unit' : {'scale':0.1,'name':"K"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Cell-pack's internal temperature. The actual operational "
"temperature range will be defined at a pack level by a "
"particular manufacturer. Typically it will be in the range "
"of -20 degC to +75 degC."),
'getter' : "simple",
},
SBS_COMMAND.Voltage : {
'type' : "uint16",
'unit' : {'scale':1,'name':"mV"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Cell-pack voltage. Provides power management systems "
"with an accurate battery terminal voltage. Power management "
"systems can use this voltage, along with battery current "
"information, to characterize devices they control."),
'getter' : "simple",
},
SBS_COMMAND.Current : {
'type' : "int16",
'unit' : {'scale':1,'name':"mA"},
'access_per_seal' : ("r","r","r",),
'desc' : ("The current being supplied/accepted through terminals. "
"Provides a snapshot for the power management system of the "
"current flowing into or out of the battery. This information "
"will be of particular use in power management systems because "
"they can characterize individual devices and \"tune\" their "
"operation."),
'getter' : "simple",
},
SBS_COMMAND.AverageCurrent : {
'type' : "int16",
'unit' : {'scale':1,'name':"mA"},
'access_per_seal' : ("r","r","r",),
'desc' : ("One-minute rolling average on the current flow. "
"Returns the rolling average based on the current being supplied "
"(or accepted) through the battery's terminals. This function "
"is expected to return meaningful values during the battery's "
"first minute of operation."),
'getter' : "simple",
},
SBS_COMMAND.MaxError : {
'type' : "uint16",
'unit' : {'scale':1,'name':"%"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Expected margin of error in charge calculation. "
"For example, when MaxError() returns 10% and RelativeStateOfCharge() "
"returns 50%, the Relative StateOfCharge() is actually between "
"50 and 60%. The MaxError() of a battery is expected to increase "
"until the Smart Battery identifies a condition that will give it "
"higher confidence in its own accuracy, like being fully charged. "
"The Battery can signal when MaxError() has become too high by "
"setting the CONDITION_FLAG bit in BatteryMode()."),
'getter' : "simple",
},
SBS_COMMAND.RelativeStateOfCharge : {
'type' : "uint16",
'unit' : {'scale':1,'name':"%"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Predicted remaining capacity, % of FullChargeCap()."
"Returns the predicted remaining battery capacity expressed as a "
"percentage of FullChargeCapacity(). This is is used to estimate "
"the amount of charge remaining in the battery. The problem with "
"this paradigm is that the tank size is variable."),
'getter' : "simple",
},
SBS_COMMAND.AbsoluteStateOfCharge : {
'type' : "uint16",
'unit' : {'scale':1,'name':"%"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Predicted remaining capacity, % of DesignCap(). "
"Returns the predicted remaining battery capacity expressed as a "
"percentage of DesignCapacity(). This can return values greater "
"than 100%."),
'getter' : "simple",
},
SBS_COMMAND.RemainingCapacity : {
'type' : "uint16",
'unit0' : {'scale':1,'name':"mAh"},
'unit1' : {'scale':10,'name':"mWh"},
'access_per_seal' : ("r","r","rw",),
'desc' : ("Predicted remaining battery capacity. The capacity value "
"is expressed in either current (mAh at a C/5 discharge rate) or "
"power (10mWh at a P/5 discharge rate) depending on the setting "
"of the BatteryMode()'s CAPACITY_MODE bit."),
'getter' : "unit_select_on_capacity_mode",
},
SBS_COMMAND.FullChargeCapacity : {
'type' : "uint16",
'unit0' : {'scale':1,'name':"mAh"},
'unit1' : {'scale':10,'name':"mWh"},
'access_per_seal' : ("r","r","rw",),
'desc' : ("Predicted pack capacity when it is fully charged. "
"The value is expressed in either current (mAh at a C/5 discharge "
"rate) or power (10mWh at a P/5 discharge rate) depending on the "
"setting of the BatteryMode()'s CAPACITY_MODE bit."),
'getter' : "unit_select_on_capacity_mode",
},
SBS_COMMAND.RunTimeToEmpty : {
'type' : "uint16",
'unit0' : {'scale':1,'name':"mAh"},
'unit1' : {'scale':10,'name':"mWh"},
'access_per_seal' : ("r","r","r",),
'desc' : ("Remaining battery life at the present rate of discharge. "
"The value is calculated based on either current or power, "
"depending on the setting of the BatteryMode()'s CAPACITY_MODE "
"bit. This is an important distinction because use of the wrong "
"calculation mode may result in inaccurate return values."),
'getter' : "unit_select_on_capacity_mode",
},
SBS_COMMAND.AverageTimeToEmpty : {
'type' : "uint16",
'unit' : {'scale':1,'name':"minutes"},
'access_per_seal' : ("r","r","r",),
'desc' : ("One-minute rolling average of the remaining bat life. "
"The AverageTimeToEmpty() value is calculated based on either "
"current or power depending on the setting of the BatteryMode()'s "
"CAPACITY_MODE bit."),
'getter' : "simple",
},
SBS_COMMAND.AverageTimeToFull : {
'type' : "uint16",
'unit' : {'scale':1,'name':"minutes"},
'access_per_seal' : ("r","r","r",),
'desc' : ("One minute average of the remaining time until full. "
"This function can be used by the SMBus Host's power management "
"system to aid in its policy. It may also be used to find out "
"how long the system must be left on to achieve full charge."),
'getter' : "simple",
},
SBS_COMMAND.ChargingCurrent : {
'type' : "uint16",
'unit' : {'scale':1,'name':"mA"},
'access_per_seal' : ("r","r","r",),
'desc' : ("The desired charging rate to the Battery Charger. "
"This represents the maximum current which may be provided by "
"the Smart Battery Charger to permit the Battery to reach a "
"Fully Charged state."),
'getter' : "simple",
},
SBS_COMMAND.ChargingVoltage : {
'type' : "uint16",
'unit' : {'scale':1,'name':"mV"},
'access_per_seal' : ("r","r","r",),
'desc' : ("The desired charging voltage to the Battery Charger. "
"This represents the maximum voltage which may be provided by "
"the Smart Battery Charger to permit the Smart Battery to reach "
"a Fully Charged state."),
'getter' : "simple",
},
SBS_COMMAND.BatteryStatus : {
'type' : "uint16",
'unit' : {'scale':1,'name':"bitfields"},
'bitfields_info' : SBS_BATTERY_STATUS_INFO,
'access_per_seal' : ("r","r","r",),
'desc' : ("Battery's Alarm and Status bit flags. Some of the "
"BatteryStatus() flags (REMAINING_CAPACITY_ALARM and "
"REMAINING_TIME_ALARM) are calculated based on either current "
"or power depending on the setting of the BatteryMode()'s "