Skip to content

Commit

Permalink
Move inky_frame.py here.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gadgetoid committed Dec 3, 2024
1 parent ab62815 commit 2f1c7f2
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 3 deletions.
3 changes: 2 additions & 1 deletion boards/manifest-common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
require("aioble")

freeze("../../pimoroni-pico/micropython/modules_py", "pimoroni.py")
freeze("../../pimoroni-pico/micropython/modules_py", "boot.py")
freeze("../../pimoroni-pico/micropython/modules_py", "boot.py")
freeze("../modules", "inky_frame.py")
3 changes: 1 addition & 2 deletions boards/usermod-common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,9 @@ include(servo/micropython)
include(encoder/micropython)
include(motor/micropython)

# Still required for version.py
include(modules_py/modules_py)

copy_module(inky_frame.py)

# C++ Magic Memory
include(cppmem/micropython)

Expand Down
181 changes: 181 additions & 0 deletions modules/inky_frame.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
from pimoroni import ShiftRegister, PWMLED
from machine import Pin, I2C, RTC
from wakeup import get_shift_state, reset_shift_state
from micropython import const
import pcf85063a
import ntptime
import time

BLACK = const(0)
WHITE = const(1)

GREEN = const(2)
BLUE = const(3)
RED = const(4)
YELLOW = const(5)
ORANGE = const(6)
TAUPE = const(7)

SR_CLOCK = const(8)
SR_LATCH = const(9)
SR_OUT = const(10)

LED_A = const(11)
LED_B = const(12)
LED_C = const(13)
LED_D = const(14)
LED_E = const(15)

LED_BUSY = const(6)
LED_WIFI = const(7)

HOLD_VSYS_EN = const(2)

RTC_ALARM = const(2)
EXTERNAL_TRIGGER = const(1)
EINK_BUSY = const(0)

SHIFT_STATE = get_shift_state()

reset_shift_state()

i2c = I2C(0)
rtc = pcf85063a.PCF85063A(i2c)
i2c.writeto_mem(0x51, 0x00, b'\x00') # ensure rtc is running (this should be default?)
rtc.enable_timer_interrupt(False)

vsys = Pin(HOLD_VSYS_EN)
vsys.on()


def woken_by_rtc():
mask = (1 << RTC_ALARM)
return bool(sr.read() & mask) or bool(SHIFT_STATE & mask)


def woken_by_ext_trigger():
mask = (1 << EXTERNAL_TRIGGER)
return bool(sr.read() & mask) or bool(SHIFT_STATE & mask)


def woken_by_button():
return bool(sr.read() & 0b11111000) or bool(SHIFT_STATE & 0b11111000)


def pico_rtc_to_pcf():
# Set the PCF85063A to the time stored by Pico W's RTC
year, month, day, dow, hour, minute, second, _ = RTC().datetime()
rtc.datetime((year, month, day, hour, minute, second, dow))


def pcf_to_pico_rtc():
# Set Pico W's RTC to the time stored by the PCF85063A
t = rtc.datetime()
# BUG ERRNO 22, EINVAL, when date read from RTC is invalid for the Pico's RTC.
try:
RTC().datetime((t[0], t[1], t[2], t[6], t[3], t[4], t[5], 0))
return True
except OSError:
return False


def sleep_for(minutes):
year, month, day, hour, minute, second, dow = rtc.datetime()

# if the time is very close to the end of the minute, advance to the next minute
# this aims to fix the edge case where the board goes to sleep right as the RTC triggers, thus never waking up
if second >= 55:
minute += 1

# Can't sleep beyond a month, so clamp the sleep to a 28 day maximum
minutes = min(minutes, 40320)

# Calculate the future alarm date; first, turn the current time into seconds since epoch
sec_since_epoch = time.mktime((year, month, day, hour, minute, second, dow, 0))

# Add the required minutes to this
sec_since_epoch += minutes * 60

# And convert it back into a more useful tuple
(ayear, amonth, aday, ahour, aminute, asecond, adow, adoy) = time.localtime(sec_since_epoch)

# And now set the alarm as before, now including the day
rtc.clear_alarm_flag()
rtc.set_alarm(0, aminute, ahour, aday)
rtc.enable_alarm_interrupt(True)

turn_off()

# Simulate sleep while on USB power
while minutes > 0:
time.sleep(60)
minutes -= 1


def turn_off():
time.sleep(0.1)
vsys.off()


def set_time():
# Set both Pico W's RTC and PCF85063A to NTP time
ntptime.settime()
pico_rtc_to_pcf()


class Button:
def __init__(self, sr, idx, led, debounce=50):
self.sr = sr
self.startup_state = bool(SHIFT_STATE & (1 << idx))
self.led = PWMLED(led)
self.led.off()
self._idx = idx
self._debounce_time = debounce
self._changed = time.ticks_ms()
self._last_value = None

def led_on(self):
self.led.on()

def led_off(self):
self.led.off()

def led_brightness(self, brightness):
self.led.brightness(brightness)

def led_toggle(self):
self.led.toggle()

def read(self):
if self.startup_state:
self.startup_state = False
return True

value = self.raw()
if value != self._last_value and time.ticks_ms() - self._changed > self._debounce_time:
self._last_value = value
self._changed = time.ticks_ms()
return value
return False

def raw(self):
if self.startup_state:
self.startup_state = False
return True
return self.sr[self._idx] == 1

@property
def is_pressed(self):
return self.raw()


sr = ShiftRegister(SR_CLOCK, SR_LATCH, SR_OUT)

button_a = Button(sr, 7, LED_A)
button_b = Button(sr, 6, LED_B)
button_c = Button(sr, 5, LED_C)
button_d = Button(sr, 4, LED_D)
button_e = Button(sr, 3, LED_E)

led_busy = PWMLED(LED_BUSY)
led_wifi = PWMLED(LED_WIFI)

0 comments on commit 2f1c7f2

Please sign in to comment.