diff options
| -rw-r--r-- | Makefile | 2 | ||||
| m--------- | bootloader | 0 | ||||
| m--------- | reloader | 0 | ||||
| -rwxr-xr-x | tools/hex2c.py | 13 | ||||
| -rw-r--r-- | wasp/apps/clock.py | 104 | ||||
| -rw-r--r-- | wasp/apps/fibonacci_clock.py | 79 | ||||
| -rw-r--r-- | wasp/apps/steps.py | 6 | ||||
| -rw-r--r-- | wasp/apps/stopwatch.py | 6 | ||||
| -rw-r--r-- | wasp/wasp.py | 2 |
9 files changed, 110 insertions, 102 deletions
@@ -46,7 +46,7 @@ bootloader: build-$(BOARD_SAFE) reloader: bootloader build-$(BOARD_SAFE) $(MAKE) -C reloader/ BOARD=$(BOARD) - mv reloader/build-$(BOARD)/reloader.zip build-$(BOARD)/ + cp reloader/build-$(BOARD)/reloader*.zip build-$(BOARD) softdevice: micropython/ports/nrf/drivers/bluetooth/download_ble_stack.sh diff --git a/bootloader b/bootloader -Subproject 477d2e07db0241d6d36ffa95740cb67eaa75a34 +Subproject 1d128f1311c084c23a662cb68263df9b187ebf9 diff --git a/reloader b/reloader -Subproject 9f55c66be8f129fd00e3eda60988b4cbeffd884 +Subproject be876ac0bb44004885ba61b8cc1992826baa9a8 diff --git a/tools/hex2c.py b/tools/hex2c.py index fa4762c..74f8431 100755 --- a/tools/hex2c.py +++ b/tools/hex2c.py @@ -20,7 +20,16 @@ def generate_c(ihex): print('};') print() - for i, segment in enumerate(ihex.segments()): + segments = [] + chunk = 32 * 1024 + for (start, end) in ihex.segments(): + while start + chunk < end: + segments.append((start, start + chunk)) + start += chunk + if start < end: + segments.append((start, end)) + + for i, segment in enumerate(segments): print(f'static const uint8_t segment{i}[] = {{', end='') for j in range(segment[0], segment[1]): @@ -30,7 +39,7 @@ def generate_c(ihex): print('\n};\n') print(f'const struct segment segments[] = {{') - for i, segment in enumerate(ihex.segments()): + for i, segment in enumerate(segments): sg = ihex.tobinarray(start=segment[0], end=segment[1]-1) crc = binascii.crc32(sg) print(f' 0x{segment[0]:08x}, 0x{segment[1]:08x}, 0x{crc:08x}, segment{i},') diff --git a/wasp/apps/clock.py b/wasp/apps/clock.py index 88ed2c7..106e712 100644 --- a/wasp/apps/clock.py +++ b/wasp/apps/clock.py @@ -13,16 +13,9 @@ import icons import fonts.clock as digits DIGITS = ( - digits.clock_0, - digits.clock_1, - digits.clock_2, - digits.clock_3, - digits.clock_4, - digits.clock_5, - digits.clock_6, - digits.clock_7, - digits.clock_8, - digits.clock_9 + digits.clock_0, digits.clock_1, digits.clock_2, digits.clock_3, + digits.clock_4, digits.clock_5, digits.clock_6, digits.clock_7, + digits.clock_8, digits.clock_9 ) MONTH = 'JanFebMarAprMayJunJulAugSepOctNovDec' @@ -38,61 +31,76 @@ class ClockApp(): NAME = 'Clock' ICON = icons.clock - def __init__(self): - self.meter = wasp.widgets.BatteryMeter() - self.notifier = wasp.widgets.NotificationBar() - def foreground(self): - """Activate the application.""" - self.on_screen = ( -1, -1, -1, -1, -1, -1 ) - self.draw() + """Activate the application. + + Configure the status bar, redraw the display and request a periodic + tick callback every second. + """ + wasp.system.bar.clock = False + self._draw(True) wasp.system.request_tick(1000) def sleep(self): + """Prepare to enter the low power mode. + + :returns: True, which tells the system manager not to automatically + switch to the default application before sleeping. + """ return True def wake(self): - self.update() + """Return from low power mode. - def tick(self, ticks): - self.update() - - def draw(self): - """Redraw the display from scratch.""" - draw = wasp.watch.drawable + Time will have changes whilst we have been asleep so we must + udpate the display (but there is no need for a full redraw because + the display RAM is preserved during a sleep. + """ + self._draw() - draw.fill() - draw.rleblit(digits.clock_colon, pos=(2*48, 80), fg=0xb5b6) - self.on_screen = ( -1, -1, -1, -1, -1, -1 ) - self.update() - self.meter.draw() + def tick(self, ticks): + """Periodic callback to update the display.""" + self._draw() - def update(self): - """Update the display (if needed). + def _draw(self, redraw=False): + """Draw or lazily update the display. - The updates are a lazy as possible and rely on an prior call to - draw() to ensure the screen is suitably prepared. + The updates are as lazy by default and avoid spending time redrawing + if the time on display has not changed. However if redraw is set to + True then a full redraw is be performed. """ - now = wasp.watch.rtc.get_localtime() - if now[3] == self.on_screen[3] and now[4] == self.on_screen[4]: - if now[5] != self.on_screen[5]: - self.meter.update() - self.notifier.update() - self.on_screen = now - return False - draw = wasp.watch.drawable + + if redraw: + now = wasp.watch.rtc.get_localtime() + + # Clear the display and draw that static parts of the watch face + draw.fill() + draw.rleblit(digits.clock_colon, pos=(2*48, 80), fg=0xb5b6) + + # Redraw the status bar + wasp.system.bar.draw() + else: + # The update is doubly lazy... we update the status bar and if + # the status bus update reports a change in the time of day + # then we compare the minute on display to make sure we + # only update the main clock once per minute. + now = wasp.system.bar.update() + if not now or self._min == now[4]: + # Skip the update + return + + # Format the month as text + month = now[1] - 1 + month = MONTH[month*3:(month+1)*3] + + # Draw the changeable parts of the watch face draw.rleblit(DIGITS[now[4] % 10], pos=(4*48, 80)) draw.rleblit(DIGITS[now[4] // 10], pos=(3*48, 80), fg=0xbdb6) draw.rleblit(DIGITS[now[3] % 10], pos=(1*48, 80)) draw.rleblit(DIGITS[now[3] // 10], pos=(0*48, 80), fg=0xbdb6) - self.on_screen = now - - month = now[1] - 1 - month = MONTH[month*3:(month+1)*3] draw.string('{} {} {}'.format(now[2], month, now[0]), 0, 180, width=240) - self.meter.update() - self.notifier.update() - return True + # Record the minute that is currently being displayed + self._min = now[4] diff --git a/wasp/apps/fibonacci_clock.py b/wasp/apps/fibonacci_clock.py index de59bc3..3718cfc 100644 --- a/wasp/apps/fibonacci_clock.py +++ b/wasp/apps/fibonacci_clock.py @@ -1,6 +1,8 @@ # SPDX-License-Identifier: LGPL-3.0-or-later # Copyright (C) 2020 Johannes Wache + """Fibonacci clock +~~~~~~~~~~~~~~~~~~ The Fibonacci sequence is a sequence of numbers created by the Italian mathematician Fibonacci in the 13th century. This is a sequence starting with @@ -22,6 +24,8 @@ result by 5 to get the actual number. import wasp import icons +COLORS = [0xffff,0xf800,0x07e0,0x001f] # White, red, green and blue +FIELDS = b'\x05\x03\x02\x01\x01' MONTH = 'JanFebMarAprMayJunJulAugSepOctNovDec' # 2-bit RLE, generated from res/fibo_icon.png, 246 bytes @@ -48,54 +52,42 @@ icon = ( class FibonacciClockApp(): """Displays the time as a Fibonacci Clock + + .. figure:: res/FiboApp.png + :width: 179 + + Screenshot of the fibonacci clock application """ NAME = 'Fibo' ICON = icon - def __init__(self): - self.meter = wasp.widgets.BatteryMeter() - self.notifier = wasp.widgets.NotificationBar() - self.fields = b'\x05\x03\x02\x01\x01' - self.color_codes = [0xffff,0xf800,0x07e0,0x001f] # White, red, green and blue - def foreground(self): """Activate the application.""" - self.on_screen = ( -1, -1, -1, -1, -1, -1 ) - self.draw() + wasp.system.bar.clock = False + self._draw(True) wasp.system.request_tick(1000) def sleep(self): return True def wake(self): - self.update() + self._draw() def tick(self, ticks): - self.update() + self._draw() - def draw(self): - """Redraw the display from scratch.""" + def _draw(self, redraw=False): + """Draw or lazily update the display.""" draw = wasp.watch.drawable - draw.fill() - self.on_screen = ( -1, -1, -1, -1, -1, -1 ) - self.update() - self.meter.draw() - - def update(self): - """Update the display (if needed). - - The updates are a lazy as possible and rely on an prior call to - draw() to ensure the screen is suitably prepared. - """ - now = wasp.watch.rtc.get_localtime() - if now[3] == self.on_screen[3] and now[4] == self.on_screen[4]: - if now[5] != self.on_screen[5]: - self.meter.update() - self.notifier.update() - self.on_screen = now - return False - draw = wasp.watch.drawable + if redraw: + now = wasp.watch.rtc.get_localtime() + draw.fill() + wasp.system.bar.draw() + else: + now = wasp.system.bar.update() + if not now or self._min == now[4]: + return #calculate colors of fields: field_colors = bytearray(5) @@ -104,27 +96,24 @@ class FibonacciClockApp(): if (hr >= 12): hr -= 12 for i in range(5): - if ((hr - self.fields[i]) >= 0): - hr -= self.fields[i] + if ((hr - FIELDS[i]) >= 0): + hr -= FIELDS[i] field_colors[i] += 1 - if ((mn - self.fields[i]) >= 0): - mn -= self.fields[i] + if ((mn - FIELDS[i]) >= 0): + mn -= FIELDS[i] field_colors[i] += 2 - draw.fill(x=71,y=60,w=23,h=23,bg=self.color_codes[field_colors[4]]) # 1 field - draw.fill(x=71,y=85,w=23,h=23,bg=self.color_codes[field_colors[3]]) # 1 field - draw.fill(x=21,y=60,w=48,h=48,bg=self.color_codes[field_colors[2]]) # 2 field - draw.fill(x=21,y=110,w=73,h=73,bg=self.color_codes[field_colors[1]]) # 3 field - draw.fill(x=96,y=60,w=123,h=123,bg=self.color_codes[field_colors[0]]) # 5 field - - self.on_screen = now + draw.fill(x=71,y=60,w=23,h=23,bg=COLORS[field_colors[4]]) # 1 field + draw.fill(x=71,y=85,w=23,h=23,bg=COLORS[field_colors[3]]) # 1 field + draw.fill(x=21,y=60,w=48,h=48,bg=COLORS[field_colors[2]]) # 2 field + draw.fill(x=21,y=110,w=73,h=73,bg=COLORS[field_colors[1]]) # 3 field + draw.fill(x=96,y=60,w=123,h=123,bg=COLORS[field_colors[0]]) # 5 field month = now[1] - 1 month = MONTH[month*3:(month+1)*3] draw.string('{} {} {}'.format(now[2], month, now[0]), 0, 202, width=240) - self.meter.update() - self.notifier.update() - return True + # Record the minute that is currently being displayed + self._min = now[4] diff --git a/wasp/apps/steps.py b/wasp/apps/steps.py index d7f16a3..cd888bd 100644 --- a/wasp/apps/steps.py +++ b/wasp/apps/steps.py @@ -42,12 +42,12 @@ class StepCounterApp(): def __init__(self): watch.accel.reset() - self._bar = wasp.widgets.StatusBar() self._count = 0 self._prev_day = -1 def foreground(self): """Activate the application.""" + wasp.system.bar.clock = True self._draw() wasp.system.request_tick(1000) @@ -62,13 +62,13 @@ class StepCounterApp(): draw.blit(feet, 12, 132-24) self._update() - self._bar.draw() + wasp.system.bar.draw() def _update(self): draw = wasp.watch.drawable # Update the status bar - now = self._bar.update() + now = wasp.system.bar.update() # Reset the step counter if we have move onto the next day if now and now[2] != self._prev_day: diff --git a/wasp/apps/stopwatch.py b/wasp/apps/stopwatch.py index 807830c..43166a6 100644 --- a/wasp/apps/stopwatch.py +++ b/wasp/apps/stopwatch.py @@ -17,12 +17,12 @@ class StopwatchApp(): ICON = icons.app def __init__(self): - self._bar = wasp.widgets.StatusBar() self._reset() self._count = 0 def foreground(self): """Activate the application.""" + wasp.system.bar.clock = True self._draw() wasp.system.request_tick(97) wasp.system.request_event(wasp.EventMask.TOUCH | @@ -111,7 +111,7 @@ class StopwatchApp(): self._last_count = -1 self._update() - self._bar.draw() + wasp.system.bar.draw() self._draw_splits() def _update(self): @@ -125,7 +125,7 @@ class StopwatchApp(): self._reset() # Update the statusbar - self._bar.update() + wasp.system.bar.update() if self._last_count != self._count: centisecs = self._count diff --git a/wasp/wasp.py b/wasp/wasp.py index 8f7e8a8..e2e728a 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -100,6 +100,8 @@ class Manager(): def __init__(self): self.app = None + self.bar = widgets.StatusBar() + self.quick_ring = [] self.launcher = LauncherApp() self.launcher_ring = [] |
