Migrate MCP and utilities to CircuitPython, including color GIF and volume fixes
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
"""CircuitPython PCF85063 Real-Time Clock (RTC) driver.
|
||||
|
||||
Synchronizes the hardware RTC with CircuitPython's native rtc.RTC() system clock.
|
||||
"""
|
||||
|
||||
import rtc
|
||||
import time
|
||||
|
||||
class PCF85063:
|
||||
ADDR = 0x51
|
||||
TIME_REG_START = 0x04
|
||||
|
||||
def __init__(self, i2c):
|
||||
self.i2c = i2c
|
||||
self._init_rtc()
|
||||
|
||||
def read_reg(self, reg, n=1):
|
||||
while not self.i2c.try_lock():
|
||||
pass
|
||||
try:
|
||||
self.i2c.writeto(self.ADDR, bytes([reg]))
|
||||
buf = bytearray(n)
|
||||
self.i2c.readfrom_into(self.ADDR, buf)
|
||||
return buf
|
||||
except Exception as e:
|
||||
print(f"RTC read failed at reg 0x{reg:02X}: {e}")
|
||||
return None
|
||||
finally:
|
||||
self.i2c.unlock()
|
||||
|
||||
def write_reg(self, reg, data):
|
||||
while not self.i2c.try_lock():
|
||||
pass
|
||||
try:
|
||||
payload = bytearray([reg])
|
||||
if isinstance(data, (bytes, bytearray, list)):
|
||||
payload.extend(data)
|
||||
else:
|
||||
payload.append(data)
|
||||
self.i2c.writeto(self.ADDR, payload)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"RTC write failed at reg 0x{reg:02X}: {e}")
|
||||
return False
|
||||
finally:
|
||||
self.i2c.unlock()
|
||||
|
||||
def _init_rtc(self):
|
||||
ctrl1 = self.read_reg(0x00, 1)
|
||||
if ctrl1 is not None and (ctrl1[0] & 0x20):
|
||||
print("RTC oscillator was stopped. Starting oscillator...")
|
||||
self.write_reg(0x00, 0x00)
|
||||
|
||||
def _dec2bcd(self, val):
|
||||
return (val // 10 << 4) | (val % 10)
|
||||
|
||||
def _bcd2dec(self, val):
|
||||
return ((val >> 4) * 10) + (val & 0x0F)
|
||||
|
||||
def get_datetime(self):
|
||||
"""Reads current time from hardware RTC.
|
||||
|
||||
Returns:
|
||||
tuple: (year, month, day, weekday, hour, minute, second) or None on error.
|
||||
"""
|
||||
data = self.read_reg(self.TIME_REG_START, 7)
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
second = self._bcd2dec(data[0] & 0x7F)
|
||||
minute = self._bcd2dec(data[1] & 0x7F)
|
||||
hour = self._bcd2dec(data[2] & 0x3F)
|
||||
day = self._bcd2dec(data[3] & 0x3F)
|
||||
weekday = data[4] & 0x07
|
||||
month = self._bcd2dec(data[5] & 0x1F)
|
||||
year = 2000 + self._bcd2dec(data[6])
|
||||
|
||||
return (year, month, day, weekday, hour, minute, second)
|
||||
|
||||
def set_datetime(self, dt):
|
||||
"""Sets the hardware RTC time.
|
||||
|
||||
Args:
|
||||
dt (tuple): (year, month, day, weekday, hour, minute, second)
|
||||
"""
|
||||
try:
|
||||
year, month, day, weekday, hour, minute, second = dt
|
||||
reg_year = year % 100
|
||||
|
||||
data = bytearray(7)
|
||||
data[0] = self._dec2bcd(second) & 0x7F
|
||||
data[1] = self._dec2bcd(minute)
|
||||
data[2] = self._dec2bcd(hour)
|
||||
data[3] = self._dec2bcd(day)
|
||||
data[4] = weekday & 0x07
|
||||
data[5] = self._dec2bcd(month)
|
||||
data[6] = self._dec2bcd(reg_year)
|
||||
|
||||
return self.write_reg(self.TIME_REG_START, data)
|
||||
except Exception as e:
|
||||
print(f"Error setting PCF85063 RTC: {e}")
|
||||
return False
|
||||
|
||||
def sync_to_system(self):
|
||||
"""Synchronizes the CircuitPython system time from the hardware RTC."""
|
||||
dt = self.get_datetime()
|
||||
if dt:
|
||||
year, month, day, weekday, hour, minute, second = dt
|
||||
r = rtc.RTC()
|
||||
r.datetime = time.struct_time((year, month, day, hour, minute, second, weekday, -1, -1))
|
||||
print(f"System clock synced to RTC: {year:04d}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}")
|
||||
return True
|
||||
return False
|
||||
|
||||
def sync_from_system(self):
|
||||
"""Synchronizes the hardware RTC time from the system clock."""
|
||||
try:
|
||||
t = time.localtime()
|
||||
dt = (t.tm_year, t.tm_mon, t.tm_mday, t.tm_wday, t.tm_hour, t.tm_min, t.tm_sec)
|
||||
success = self.set_datetime(dt)
|
||||
if success:
|
||||
print(f"RTC synced from System: {t.tm_year:04d}-{t.tm_mon:02d}-{t.tm_mday:02d} {t.tm_hour:02d}:{t.tm_min:02d}:{t.tm_sec:02d}")
|
||||
return success
|
||||
except Exception as e:
|
||||
print(f"Error syncing RTC from system: {e}")
|
||||
return False
|
||||
|
||||
def get_time_string(self):
|
||||
dt = self.get_datetime()
|
||||
if dt:
|
||||
return f"{dt[0]:04d}-{dt[1]:02d}-{dt[2]:02d} {dt[4]:02d}:{dt[5]:02d}:{dt[6]:02d}"
|
||||
return "0000-00-00 00:00:00"
|
||||
Reference in New Issue
Block a user