Skip to content
Snippets Groups Projects
Commit c78dd28b authored by Ferdinand Bachmann's avatar Ferdinand Bachmann Committed by rahix
Browse files

feat(preload): Add DigiClk

parent b8803880
No related branches found
No related tags found
No related merge requests found
import os
import sys
import leds
import display
import buttons
sys.path.append("/apps/digiclk/")
import monotime as utime
import draw
DIGITS = [
(True, True, True, True, True, True, False),
(False, True, True, False, False, False, False),
(True, True, False, True, True, False, True),
(True, True, True, True, False, False, True),
(False, True, True, False, False, True, True),
(True, False, True, True, False, True, True),
(True, False, True, True, True, True, True),
(True, True, True, False, False, False, False),
(True, True, True, True, True, True, True),
(True, True, True, True, False, True, True),
]
def renderNum(d, num, x):
draw.Grid7Seg(d, x, 0, 7, DIGITS[num // 10], (255, 255, 255))
draw.Grid7Seg(d, x + 5, 0, 7, DIGITS[num % 10], (255, 255, 255))
def renderColon(d):
draw.GridVSeg(d, 11, 2, 7, 2, (255, 255, 255))
draw.GridVSeg(d, 11, 4, 7, 2, (255, 255, 255))
def renderText(d, text, blankidx=None):
bs = bytearray(text)
if blankidx != None:
bs[blankidx : blankidx + 1] = b"_"
d.print(
MODES[MODE] + " " + bs.decode(), fg=(255, 255, 255), bg=None, posx=0, posy=7 * 8
)
def renderBar(d, num):
d.rect(20, 78, 20 + num * 2, 80, col=(255, 255, 255))
def render(d):
ltime = utime.localtime()
years = ltime[0]
months = ltime[1]
days = ltime[2]
hours = ltime[3]
mins = ltime[4]
secs = ltime[5]
d.clear()
if MODE == CHANGE_YEAR:
renderNum(d, years // 100, 1)
renderNum(d, years % 100, 13)
elif MODE == CHANGE_MONTH:
renderNum(d, months, 13)
elif MODE == CHANGE_DAY:
renderNum(d, days, 13)
else:
renderNum(d, hours, 1)
renderNum(d, mins, 13)
if MODE not in (CHANGE_YEAR, CHANGE_MONTH, CHANGE_DAY) and secs % 2 == 0:
renderColon(d)
renderText(d, NAME, None)
renderBar(d, secs)
d.update()
LONG_DELAY = 400
BUTTON_UPDATE_TIME = 100
BUTTON_SEL = 1 << 0
BUTTON_SEL_LONG = 1 << 1
BUTTON_UP = 1 << 2
BUTTON_UP_LONG = 1 << 3
BUTTON_DOWN = 1 << 4
BUTTON_DOWN_LONG = 1 << 5
pressed_prev = 0
button_long_prev = {BUTTON_SEL: False, BUTTON_UP: False, BUTTON_DOWN: False}
button_times = {BUTTON_SEL: 0, BUTTON_UP: 0, BUTTON_DOWN: 0}
def checkButton(button, button_long, osbutton, pressed, t):
cur_buttons = 0
if pressed & osbutton and not pressed_prev & osbutton:
button_times[button] = t
button_long_prev[button] = False
elif pressed_prev & osbutton:
if button_times[button] + LONG_DELAY < t:
cur_buttons |= button_long
button_times[button] = t
button_long_prev[button] = True
elif not pressed & osbutton and not button_long_prev[button]:
cur_buttons |= button
return cur_buttons
def checkButtons():
global pressed_prev
t = utime.time_monotonic_ms()
pressed = buttons.read(
buttons.BOTTOM_LEFT | buttons.TOP_RIGHT | buttons.BOTTOM_RIGHT
)
cur_buttons = 0
cur_buttons |= checkButton(
BUTTON_SEL, BUTTON_SEL_LONG, buttons.BOTTOM_LEFT, pressed, t
)
cur_buttons |= checkButton(BUTTON_UP, BUTTON_UP_LONG, buttons.TOP_RIGHT, pressed, t)
cur_buttons |= checkButton(
BUTTON_DOWN, BUTTON_DOWN_LONG, buttons.BOTTOM_RIGHT, pressed, t
)
pressed_prev = pressed
return cur_buttons
def modTime(yrs, mth, day, hrs, mns, sec):
ltime = utime.localtime()
new = utime.mktime(
(
ltime[0] + yrs,
ltime[1] + mth,
ltime[2] + day,
ltime[3] + hrs,
ltime[4] + mns,
ltime[5] + sec,
None,
None,
)
)
utime.set_time(new)
def ctrl_display(bs):
global MODE, updated
updated = True
if bs & BUTTON_SEL_LONG:
MODE = CHANGE_HOURS
else:
updated = False
def ctrl_chg_hrs(bs):
global MODE, updated
updated = True
if bs & BUTTON_SEL_LONG:
MODE = DISPLAY
elif bs & BUTTON_SEL:
MODE = CHANGE_MINUTES
elif bs & BUTTON_UP_LONG:
modTime(0, 0, 0, 10, 0, 0)
elif bs & BUTTON_DOWN_LONG:
modTime(0, 0, 0, -10, 0, 0)
elif bs & BUTTON_UP:
modTime(0, 0, 0, 1, 0, 0)
elif bs & BUTTON_DOWN:
modTime(0, 0, 0, -1, 0, 0)
else:
updated = False
def ctrl_chg_mns(bs):
global MODE, updated
updated = True
if bs & BUTTON_SEL_LONG:
MODE = DISPLAY
elif bs & BUTTON_SEL:
MODE = CHANGE_SECONDS
elif bs & BUTTON_UP_LONG:
modTime(0, 0, 0, 0, 10, 0)
elif bs & BUTTON_DOWN_LONG:
modTime(0, 0, 0, 0, -10, 0)
elif bs & BUTTON_UP:
modTime(0, 0, 0, 0, 1, 0)
elif bs & BUTTON_DOWN:
modTime(0, 0, 0, 0, -1, 0)
else:
updated = False
def ctrl_chg_sec(bs):
global MODE, updated
updated = True
if bs & BUTTON_SEL_LONG:
MODE = DISPLAY
elif bs & BUTTON_SEL:
MODE = CHANGE_YEAR
elif bs & BUTTON_UP_LONG:
modTime(0, 0, 0, 0, 0, 10)
elif bs & BUTTON_DOWN_LONG:
modTime(0, 0, 0, 0, 0, -10)
elif bs & BUTTON_UP:
modTime(0, 0, 0, 0, 0, 1)
elif bs & BUTTON_DOWN:
modTime(0, 0, 0, 0, 0, -1)
else:
updated = False
def ctrl_chg_yrs(bs):
global MODE, updated
updated = True
if bs & BUTTON_SEL_LONG:
MODE = DISPLAY
elif bs & BUTTON_SEL:
MODE = CHANGE_MONTH
elif bs & BUTTON_UP_LONG:
modTime(10, 0, 0, 0, 0, 0)
elif bs & BUTTON_DOWN_LONG:
modTime(-10, 0, 0, 0, 0, 0)
elif bs & BUTTON_UP:
modTime(1, 0, 0, 0, 0, 0)
elif bs & BUTTON_DOWN:
modTime(-1, 0, 0, 0, 0, 0)
else:
updated = False
def ctrl_chg_mth(bs):
global MODE, updated
updated = True
if bs & BUTTON_SEL_LONG:
MODE = DISPLAY
elif bs & BUTTON_SEL:
MODE = CHANGE_DAY
elif bs & BUTTON_UP_LONG:
modTime(0, 6, 0, 0, 0, 0)
elif bs & BUTTON_DOWN_LONG:
modTime(0, -6, 0, 0, 0, 0)
elif bs & BUTTON_UP:
modTime(0, 1, 0, 0, 0, 0)
elif bs & BUTTON_DOWN:
modTime(0, -1, 0, 0, 0, 0)
else:
updated = False
def ctrl_chg_day(bs):
global MODE, updated
updated = True
if bs & BUTTON_SEL_LONG:
MODE = DISPLAY
elif bs & BUTTON_SEL:
MODE = CHANGE_HOURS
elif bs & BUTTON_UP_LONG:
modTime(0, 0, 10, 0, 0, 0)
elif bs & BUTTON_DOWN_LONG:
modTime(0, 0, -10, 0, 0, 0)
elif bs & BUTTON_UP:
modTime(0, 0, 1, 0, 0, 0)
elif bs & BUTTON_DOWN:
modTime(0, 0, -1, 0, 0, 0)
else:
updated = False
NAME = None
FILENAME = "nickname.txt"
def load_nickname():
global NAME
if FILENAME in os.listdir("."):
with open("nickname.txt", "rb") as f:
name = f.read().strip()
else:
name = b"no nick"
if len(name) > 7:
name = name[0:7]
else:
name = b" " * (7 - len(name)) + name
NAME = name
# MODE values
DISPLAY = 0
CHANGE_HOURS = 1
CHANGE_MINUTES = 2
CHANGE_SECONDS = 3
CHANGE_YEAR = 4
CHANGE_MONTH = 5
CHANGE_DAY = 6
MODE = DISPLAY
MODES = {
DISPLAY: "---",
CHANGE_HOURS: "HRS",
CHANGE_MINUTES: "MNS",
CHANGE_SECONDS: "SEC",
CHANGE_YEAR: "YRS",
CHANGE_MONTH: "MTH",
CHANGE_DAY: "DAY",
}
updated = False
CTRL_FNS = {
DISPLAY: ctrl_display,
CHANGE_HOURS: ctrl_chg_hrs,
CHANGE_MINUTES: ctrl_chg_mns,
CHANGE_SECONDS: ctrl_chg_sec,
CHANGE_YEAR: ctrl_chg_yrs,
CHANGE_MONTH: ctrl_chg_mth,
CHANGE_DAY: ctrl_chg_day,
}
def main():
global updated
try:
load_nickname()
with display.open() as d:
last_secs, secs = 0, 0
last_msecs, msecs = 0, 0
while True:
updated = False
bs = checkButtons()
CTRL_FNS[MODE](bs)
last_secs, secs = secs, utime.time_monotonic()
if updated or secs > last_secs:
render(d)
last_msecs, msecs = msecs, utime.time_monotonic_ms()
if msecs - last_msecs < BUTTON_UPDATE_TIME:
utime.sleep_ms(BUTTON_UPDATE_TIME - (msecs - last_msecs))
except KeyboardInterrupt:
pass
main()
def _ceilDiv(a, b):
return (a + (b - 1)) // b
def TipHeight(w):
return _ceilDiv(w, 2) - 1
def Tip(d, x, y, w, c, invert=False, swapAxes=False):
h = TipHeight(w)
for dy in range(h):
for dx in range(dy + 1, w - 1 - dy):
px = x + dx
py = y + dy if not invert else y + h - 1 - dy
if swapAxes:
px, py = py, px
d.pixel(px, py, col=c)
def Seg(d, x, y, w, h, c, swapAxes=False):
tip_h = TipHeight(w)
body_h = h - 2 * tip_h
Tip(d, x, y, w, c, invert=True, swapAxes=swapAxes)
px1, px2 = x, x + w
py1, py2 = y + tip_h, y + tip_h + body_h
if swapAxes:
px1, px2, py1, py2 = py1, py2, px1, px2
d.rect(px1, py1, px2 - 1, py2 - 1, col=c)
Tip(d, x, y + tip_h + body_h, w, c, invert=False, swapAxes=swapAxes)
def VSeg(d, x, y, w, l, c):
Seg(d, x, y, w, l, c)
def HSeg(d, x, y, w, l, c):
Seg(d, y, x, w, l, c, swapAxes=True)
def GridSeg(d, x, y, w, l, c, swapAxes=False):
sw = w - 2
tip_h = TipHeight(sw)
x = x * w
y = y * w
l = (l - 1) * w
Seg(d, x + 1, y + tip_h + 3, sw, l - 3, c, swapAxes=swapAxes)
def GridVSeg(d, x, y, w, l, c):
GridSeg(d, x, y, w, l, c)
def GridHSeg(d, x, y, w, l, c):
GridSeg(d, y, x, w, l, c, swapAxes=True)
def Grid(d, x1, y1, x2, y2, w, c):
for x in range(x1 * w, x2 * w):
for y in range(y1 * w, y2 * w):
if x % w == 0 or x % w == w - 1 or y % w == 0 or y % w == w - 1:
d.pixel(x, y, col=c)
def Grid7Seg(d, x, y, w, segs, c):
if segs[0]:
GridHSeg(d, x, y, w, 4, c)
if segs[1]:
GridVSeg(d, x + 3, y, w, 4, c)
if segs[2]:
GridVSeg(d, x + 3, y + 3, w, 4, c)
if segs[3]:
GridHSeg(d, x, y + 6, w, 4, c)
if segs[4]:
GridVSeg(d, x, y + 3, w, 4, c)
if segs[5]:
GridVSeg(d, x, y, w, 4, c)
if segs[6]:
GridHSeg(d, x, y + 3, w, 4, c)
{
"name": "DigiClk",
"description": "A Digital Clock, configurable via buttons",
"category": "wearable",
"author": "yrlf",
"revision": 1
}
import utime as _utime
_offset_ms = 0
def time_monotonic():
return _utime.time() + _offset_ms // 1000
def time_monotonic_ms():
return _utime.time_ms() + _offset_ms
def sleep(s):
return _utime.sleep(s)
def sleep_ms(ms):
return _utime.sleep_ms(ms)
def sleep_us(us):
return _utime.sleep_us(us)
def time():
return _utime.time()
def time_ms():
return _utime.time_ms()
def set_time(t):
global _offset_ms
cur_t = _utime.time_ms()
_utime.set_time(t)
new_t = _utime.time_ms()
diff = cur_t - new_t
_offset_ms += diff
def set_unix_time(t):
global _offset_ms
cur_t = _utime.time_ms()
_utime.set_unix_time(t)
new_t = _utime.time_ms()
diff = cur_t - new_t
_offset_ms += diff
def localtime(s=None):
if s != None:
return _utime.localtime(s)
else:
return _utime.localtime()
def mktime(t):
return _utime.mktime(t)
def alarm(s, cb=None):
if cb != None:
return _utime.alarm(s, cb)
else:
return _utime.alarm(s)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment