Toggle Navigation
Hatchery
Eggs
Yet Another Digital Clock
__init__.py
Users
Badges
Login
Register
MCH2022 badge?
go to mch2022.badge.team
__init__.py
raw
Content
""" Thanks to yrlf for the 7-segment display code https://github.com/Ferdi265/card10-digiclk Thanks to lortas for the battery rendering code """ import os import display import utime import buttons import light_sensor import bhi160 import ujson import vibra ALARMFILE = "alarm.json" MESSAGEFILE = "messages.json" DEFAULTMESSAGECOLOR = [0, 0, 255] LONGESTMESSAGETIME = 3600 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) ] MONTH_STRING = ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] class Clock: def __init__(self): with display.open() as disp: disp.clear() disp.update() disp.backlight(0) self.display_state = 0 self.states = 2 # load alarms self.alarmsymbol = False if ALARMFILE in os.listdir("."): f = open(ALARMFILE, 'r') self.alarms = ujson.loads(f.read()) f.close() for alarm in self.alarms: alarm["minute_time"] = utime.mktime(alarm["time"]+[1, 1])//60 else: self.alarms = [] # load messages self.message = "" self.messagecol = DEFAULTMESSAGECOLOR self.lastmessage = utime.time() if MESSAGEFILE in os.listdir("."): f = open(MESSAGEFILE, 'r') self.messages = ujson.loads(f.read()) f.close() else: self.messages = [] def check_for_future_alarms(self): self.alarmsymbol = False current = utime.time() for alarm in self.alarms: if current//60 < alarm["minute_time"] < current//60+60*12: self.alarmsymbol = True def draw_alertsymb(self, disp, x, y, fgcol): disp.circ(x, y, 6, filled=False, col=fgcol) disp.line(x, y, x, y-4, col=fgcol) disp.line(x, y, x+3, y, col=fgcol) disp.line(x-7, y-6, x-2, y-10, col=fgcol) disp.line(x+7, y-6, x+2, y-10, col=fgcol) def render_battery(self, disp, v, light): if v > 3.8: c = [0, light, 0] elif v > 3.6: c = [light, light, 0] else: c = [light, 0, 0] disp.rect(140, 71, 155, 78, filled=True, col=c) disp.rect(155, 73, 157, 76, filled=True, col=c) if v < 4.0: disp.rect(151, 72, 154, 77, filled=True, col=[0, 0, 0]) if v < 3.8: disp.rect(146, 72, 151, 77, filled=True, col=[0, 0, 0]) if v < 3.6: disp.rect(141, 72, 146, 77, filled=True, col=[0, 0, 0]) def ceilDiv(self, a, b): return (a + (b - 1)) // b def tipHeight(self, w): return self.ceilDiv(w, 2) - 1 def drawTip(self, d, x, y, w, c, invert=False, swapAxes=False): h = self.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 drawSeg(self, d, x, y, w, h, c, swapAxes=False): tip_h = self.tipHeight(w) body_h = h - 2 * tip_h self.drawTip(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) self.drawTip(d, x, y + tip_h + body_h, w, c, invert=False, swapAxes=swapAxes) def drawGridSeg(self, d, x, y, w, l, c, swapAxes=False): sw = w - 2 tip_h = self.tipHeight(sw) x = x * w y = y * w l = (l - 1) * w self.drawSeg(d, x + 1, y + tip_h + 3, sw, l - 3, c, swapAxes=swapAxes) def drawGridVSeg(self, d, x, y, w, l, c): self.drawGridSeg(d, x, y, w, l, c) def drawGridHSeg(self, d, x, y, w, l, c): self.drawGridSeg(d, y, x, w, l, c, swapAxes=True) def drawGrid7Seg(self, d, x, y, w, segs, c): if segs[0]: self.drawGridHSeg(d, x, y, w, 4, c) if segs[1]: self.drawGridVSeg(d, x + 3, y, w, 4, c) if segs[2]: self.drawGridVSeg(d, x + 3, y + 3, w, 4, c) if segs[3]: self.drawGridHSeg(d, x, y + 6, w, 4, c) if segs[4]: self.drawGridVSeg(d, x, y + 3, w, 4, c) if segs[5]: self.drawGridVSeg(d, x, y, w, 4, c) if segs[6]: self.drawGridHSeg(d, x, y + 3, w, 4, c) def renderNum(self, d, num, x, c): self.drawGrid7Seg(d, x, 0, 7, DIGITS[num // 10], c) self.drawGrid7Seg(d, x + 5, 0, 7, DIGITS[num % 10], c) def renderColon(self, d, c): self.drawGridVSeg(d, 11, 2, 7, 2, c) self.drawGridVSeg(d, 11, 4, 7, 2, c) def loop(self): with display.open() as disp: while True: v = buttons.read(buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT | buttons.TOP_RIGHT) (year, month, day, hour, minute, seconds, weekday, _yday) = utime.localtime() for message in self.messages: if (weekday in message["dow"] and [hour, minute, seconds] == message["time"]): self.lastmessage = utime.time() self.message = message["message"] if "color" in message: self.messagecol = message["color"] else: self.messagecol = DEFAULTMESSAGECOLOR elif (self.lastmessage < utime.time()-LONGESTMESSAGETIME): self.message = "" if v != 0: # some button pressed light = 255 fgcol = [light]*3 # update clock disp.clear() self.renderNum(disp, hour, 1, fgcol) self.renderNum(disp, minute, 13, fgcol) self.renderColon(disp, fgcol) self.render_battery(disp, os.read_battery(), light) disp.print(str(day)+"."+MONTH_STRING[month-1], fg=fgcol, posx=0, posy=66, font=2) disp.print(self.message, posy=50, font=0, fg=self.messagecol) if self.alarmsymbol and not self.alarm: self.draw_alertsymb(disp, 150, 60, fgcol) else: self.check_for_future_alarms() disp.update() disp.backlight(100) utime.sleep(5) disp.clear() disp.update() disp.backlight(0) self.alarm = False for alarm in self.alarms: if (alarm["minute_time"] == utime.time()//60): if v != 0: alarm["minute_time"] = 0 self.check_for_future_alarms() else: disp.backlight(100) disp.print(alarm["message"], font=2, fg=[255, 0, 0], posy=30) disp.update() self.alarm = True if self.alarm: vibra.set(True) utime.sleep_ms(300) vibra.set(False) utime.sleep(1) clock = Clock() clock.loop() clock.loadalarms() print("loaded")