Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions system/hardware/hardwared.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,23 @@ def touch_thread(end_event):
time.sleep(DT_HW)


def power_sample_thread(end_event):
"""5.6Hz SOM power via FG IADC direct mode."""
try:
HARDWARE.init_fast_power()
while not end_event.is_set():
try:
i_ua = HARDWARE.fast_ibat_ua()
v_mv = HARDWARE.fast_vbat_mv()
p = v_mv * i_ua / 1e9
statlog.sample("som_power_draw", p)
statlog.sample("power_draw", p)
except Exception:
pass
finally:
HARDWARE.stop_fast_power()


def hw_state_thread(end_event, hw_queue):
"""Handles non critical hardware state, and sends over queue"""
count = 0
Expand Down Expand Up @@ -472,6 +489,7 @@ def main():

if TICI:
threads.append(threading.Thread(target=touch_thread, args=(end_event,)))
threads.append(threading.Thread(target=power_sample_thread, args=(end_event,)))

for t in threads:
t.start()
Expand Down
44 changes: 44 additions & 0 deletions system/hardware/tici/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,50 @@ def get_current_power_draw(self):
def get_som_power_draw(self):
return (self.read_param_file("/sys/class/power_supply/bms/voltage_now", int) * self.read_param_file("/sys/class/power_supply/bms/current_now", int) / 1e12)

# fast power measurement: FG IADC direct mode (5.6Hz, 488uA resolution)
# PMI8998 FG normally converts IBATT every 1.47s. ALG_DIRECT_MODE triggers
# the 15-bit delta-sigma IADC on demand

def _spmi_write(self, addr, val):
regmap = '/sys/kernel/debug/regmap/spmi0-02'
with open(f'{regmap}/address', 'w') as f:
f.write(hex(addr))
with open(f'{regmap}/count', 'w') as f:
f.write('1')
with open(f'{regmap}/data', 'w') as f:
f.write(hex(val))

def _spmi_read16(self, addr):
regmap = '/sys/kernel/debug/regmap/spmi0-02'
with open(f'{regmap}/address', 'w') as f:
f.write(hex(addr))
with open(f'{regmap}/count', 'w') as f:
f.write('2')
with open(f'{regmap}/data') as f:
d = f.read().strip().split('\n')
return int(d[1].split(':')[1], 16) << 8 | int(d[0].split(':')[1], 16)

def fast_vbat_mv(self):
return self.read_param_file("/sys/class/power_supply/bms/voltage_now", int) / 1e3

def fast_ibat_ua(self):
self._spmi_write(0x41D0, 0xA5)
self._spmi_write(0x41E5, 0x12)
self._spmi_write(0x41D0, 0xA5)
self._spmi_write(0x41E5, 0x16)
time.sleep(0.170)
raw = self._spmi_read16(0x41AE)
signed = raw if raw < 0x8000 else raw - 0x10000
return signed * 488281 // 1000

def init_fast_power(self):
self._spmi_write(0x41D0, 0xA5)
self._spmi_write(0x41E5, 0x12)

def stop_fast_power(self):
self._spmi_write(0x41D0, 0xA5)
self._spmi_write(0x41E5, 0x20)

def shutdown(self):
os.system("sudo poweroff")

Expand Down
Loading