From 9ed2feb9b1702471abdcc7a41cbcf42dd728bd01 Mon Sep 17 00:00:00 2001 From: Erik Sommer Date: Mon, 4 Oct 2021 22:30:36 +0200 Subject: [PATCH 1/2] Make all hardware classes singletons - this removes the need of passing the objects as init values --- apps.py | 20 +++--- buttons.py | 33 +++++---- clock.py | 14 ++-- display.py | 193 ++++++++++++++++++++++++++------------------------- main.py | 22 +++--- pomodoro.py | 12 ++-- rtc.py | 3 + scheduler.py | 7 +- speaker.py | 4 ++ time_set.py | 13 ++-- util.py | 7 ++ 11 files changed, 178 insertions(+), 150 deletions(-) create mode 100644 util.py diff --git a/apps.py b/apps.py index 31f848a..ef80e34 100644 --- a/apps.py +++ b/apps.py @@ -1,3 +1,7 @@ +from buttons import Buttons +from display import Display + + class App: def __init__(self, name, label): self.name = name @@ -8,11 +12,11 @@ def __init__(self, name, label): def top_button(self, t): print("top_button not implemented for " + self.name) -class Apps: - def __init__(self, display, buttons): - self.display = display - self.buttons = buttons +class Apps: + def __init__(self, scheduler): + self.display = Display(scheduler) + self.buttons = Buttons(scheduler) self.apps = [] self.current_app = 0 self.buttons.add_callback(1, self.next, max=500) @@ -20,7 +24,7 @@ def __init__(self, display, buttons): self.buttons.add_callback(1, self.exit, min=500) def add(self, app): - if len(self.apps)==0: + if len(self.apps) == 0: app.enable() self.apps.append(app) @@ -28,12 +32,12 @@ def next(self, t): print("NEXT") if len(self.apps) == 0: return - + app = self.apps[self.current_app] if app.active and app.grab_top_button: app.top_button(t) return - + self.apps[self.current_app].disable() self.buttons.clear_callbacks(2) self.buttons.clear_callbacks(3) @@ -50,7 +54,7 @@ def previous(self, t): self.apps[self.current_app].enable() def exit(self, t): - if len(self.apps) >0: + if len(self.apps) > 0: self.apps[self.current_app].disable() self.current_app = 0 self.apps[self.current_app].enable() diff --git a/buttons.py b/buttons.py index c59221a..8ef4708 100644 --- a/buttons.py +++ b/buttons.py @@ -1,17 +1,21 @@ from machine import Pin import time -STATE_UNPRESSED=1 -STATE_PRESSED=2 +from util import singleton -class Buttons: - PINS = { +STATE_UNPRESSED = 1 +STATE_PRESSED = 2 + +PINS = { 1: 2, 2: 17, 3: 15, } - class Button: + +@singleton +class Buttons: + class Button: class Callback: def __init__(self, callback, min=0, max=-1): self.callback = callback @@ -19,7 +23,7 @@ def __init__(self, callback, min=0, max=-1): self.max = max def __init__(self, number): - self.pin = Pin(Buttons.PINS[number], Pin.IN, Pin.PULL_UP) + self.pin = Pin(PINS[number], Pin.IN, Pin.PULL_UP) self.number = number self.state = STATE_UNPRESSED self.callbacks = [] @@ -41,25 +45,25 @@ def clear_callbacks(self): def __init__(self, scheduler): self.buttons = [ - Buttons.Button(number) for number in (1,2,3) + self.Button(number) for number in (1, 2, 3) ] scheduler.schedule("button-press", 1, self.millis_callback) def add_callback(self, number, callback, min=0, max=-1): - self.buttons[number-1].add_callback(callback, min, max) + self.buttons[number - 1].add_callback(callback, min, max) def remove_callback(self, number, callback, min=0, max=-1): - self.buttons[number-1].remove_callback(callback, min, max) + self.buttons[number - 1].remove_callback(callback, min, max) def clear_callbacks(self, number): - self.buttons[number-1].clear_callbacks() + self.buttons[number - 1].clear_callbacks() def get_button(self, number): - return self.buttons[number-1] + return self.buttons[number - 1] def millis_callback(self, t): for button in self.buttons: - if len(button.callbacks)>0: + if len(button.callbacks) > 0: if button.state == STATE_UNPRESSED and button.pin.value() == 0: button.state = STATE_PRESSED button.pressed = time.ticks_ms() @@ -67,9 +71,10 @@ def millis_callback(self, t): button.state = STATE_UNPRESSED tm = time.ticks_ms() press_duration = time.ticks_diff(tm, button.pressed) - print("Button %d pressed for %dms" %(button.number, press_duration)) + print("Button %d pressed for %dms" % (button.number, press_duration)) for callback in button.callbacks: - if callback.min < press_duration and (callback.max==-1 or press_duration <= callback.max): + if callback.min < press_duration and ( + callback.max == -1 or press_duration <= callback.max): callback.callback(t) break button.pressed = None diff --git a/clock.py b/clock.py index 787aca3..b9e000d 100644 --- a/clock.py +++ b/clock.py @@ -1,13 +1,15 @@ import time from apps import App +from display import Display +from rtc import RTC + class Clock(App): - def __init__(self, scheduler, display, rtc): + def __init__(self, scheduler): App.__init__(self, "Clock", "clock") - self.display = display - self.rtc = rtc + self.display = Display(scheduler) + self.rtc = RTC() self.enabled = True - self.scheduler = scheduler scheduler.schedule("clock-second", 1000, self.secs_callback) scheduler.schedule("clock-minute", 60000, self.mins_callback) @@ -21,7 +23,7 @@ def disable(self): def secs_callback(self, t): if self.enabled: t = time.time() - if t%2==0: + if t % 2 == 0: self.display.show_char(":", pos=10) else: self.display.show_char(" :", pos=10) @@ -29,7 +31,7 @@ def secs_callback(self, t): def mins_callback(self, t): if self.enabled: self.update_time() - + def update_time(self): t = self.rtc.get_time() now = "%02d:%02d" % (t[3], t[4]) diff --git a/display.py b/display.py index bda0161..2b3c721 100644 --- a/display.py +++ b/display.py @@ -1,7 +1,9 @@ -import time from machine import Pin, Timer -import random +from util import singleton + + +@singleton class Display: def __init__(self, scheduler): self.a0 = Pin(16, Pin.OUT) @@ -14,16 +16,16 @@ def __init__(self, scheduler): self.row = 0 self.count = 0 - self.leds = [[0] * 32 for i in range(0,8)] + self.leds = [[0] * 32 for i in range(0, 8)] self.leds_changed = False self.disp_offset = 2 self.initialise_fonts() self.initialise_icons() scheduler.schedule("enable-leds", 1, self.enable_leds) - + def enable_leds(self, t): - self.count+=1 - self.row = (self.row+1)%8 + self.count += 1 + self.row = (self.row + 1) % 8 led_row = self.leds[self.row] if True: for col in range(32): @@ -33,77 +35,77 @@ def enable_leds(self, t): self.le.value(1) self.le.value(0) self.leds_changed = False - - self.a0.value(1 if self.row&0x01 else 0) - self.a1.value(1 if self.row&0x02 else 0) - self.a2.value(1 if self.row&0x04 else 0) + + self.a0.value(1 if self.row & 0x01 else 0) + self.a1.value(1 if self.row & 0x02 else 0) + self.a2.value(1 if self.row & 0x04 else 0) def clear(self, x=0, y=0, w=24, h=7): - for yy in range(y, y+h+1): - for xx in range(x, x+w+1): - self.leds[yy][xx]=0 + for yy in range(y, y + h + 1): + for xx in range(x, x + w + 1): + self.leds[yy][xx] = 0 def show_char(self, character, pos): - pos+=self.disp_offset # Plus the offset of the status indicator + pos += self.disp_offset # Plus the offset of the status indicator char = self.ziku[character] - for row in range(1,8): - byte = char.rows[row-1] + for row in range(1, 8): + byte = char.rows[row - 1] for col in range(0, char.width): - self.leds[row][pos+col] = (byte >> col) % 2 + self.leds[row][pos + col] = (byte >> col) % 2 self.leds_changed = True def show_text(self, text, pos=0): - i=0 - while i schedule.duration: schedule.callback(t) schedule.lastrun = tm - diff --git a/speaker.py b/speaker.py index 9bc64de..dad373a 100644 --- a/speaker.py +++ b/speaker.py @@ -1,6 +1,10 @@ from machine import Pin, Timer import time +from util import singleton + + +@singleton class Speaker: def __init__(self, scheduler): self.buzz = Pin(14, Pin.OUT) diff --git a/time_set.py b/time_set.py index f8d0424..5eb2621 100644 --- a/time_set.py +++ b/time_set.py @@ -1,6 +1,7 @@ -import time -import machine from apps import App +from buttons import Buttons +from display import Display +from rtc import RTC month_max = { 1: 31, # January @@ -28,13 +29,13 @@ def __init__(self, name, position, panel, index, max, length=2, offset=0): self.length = length self.offset = offset - def __init__(self, scheduler, display, buttons, rtc): + def __init__(self, scheduler): App.__init__(self, "Time Set", "timeset") - self.display = display + self.display = Display(scheduler) self.scheduler = scheduler - self.buttons = buttons - self.rtc = rtc + self.buttons = Buttons(scheduler) + self.rtc = RTC() self.grab_top_button = True self.enabled = False self.state = None diff --git a/util.py b/util.py new file mode 100644 index 0000000..856e3c9 --- /dev/null +++ b/util.py @@ -0,0 +1,7 @@ +def singleton(class_): + instances = {} + def getinstance(*args, **kwargs): + if class_ not in instances: + instances[class_] = class_(*args, **kwargs) + return instances[class_] + return getinstance \ No newline at end of file From e62df2e41b45df3a8209b7adaf108f5e9b049f73 Mon Sep 17 00:00:00 2001 From: Erik Sommer Date: Tue, 5 Oct 2021 19:59:59 +0200 Subject: [PATCH 2/2] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index efcb9c4..9e230b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Change Log +* **2021/10/05**: Unified interface for the app classes * **2021/10/02**: Add basic time-set app * **2021/10/01**: Improved 'app' functionality Top button switches between apps