Rewrite to reduce memory usage and add more features
In addition to the clock scene, both the animation scene and the weather scene should now work under MicroPython on devices with 520kBytes of RAM (e.g. LoPy 1, WiPy 2) after: - combating heap fragmentation during initialization by temporarily allocating a large chunk of RAM in the beginning of main.py and freeing it after all modules have been imported and initialized - stream parsing the JSON response from the weather API - converting animations to binary and streaming them from the flash file system (additionally, older ESP8266 modules with 4MB flash have been found working under some circumstances with MicroPython 1.9.4 and an 8x8 LED matrix) - 3D parts: add diffuser grid and frame for square LED matrix displays - Arduino projects needs to be in a folder with the same name as the .ino file - config: allow multiple WiFi networks to be configured - config: add support for debug flags - config: add intensity configuration - HAL: unify serial input processing for Arduino and Pycom devices - HAL: handle UART write failures on Pycom devices - HAL: drop garbage collection from .update_display() because it takes several hundred milliseconds on 4MB devices - MCU: clear display when enabling/disabling MCU independence from host - PixelFont: move data to class attributes to reduce memory usage - PixelFont: add more characters - PixelFont: move data generation to scripts/generate-pixelfont.py - LedMatrix: support LED matrixes with strides other than 8 (e.g. as 16x16 matrices) - LedMatrix: add method to render text - LedMatrix: let consumers handle brightness themselves - AnimationScene: MicroPython does not implement bytearray.find - AnimationScene: ensure minimum on-screen time - BootScene: wifi connection and RTC sync progress for Pycom devices - ClockScene: delete unused code, switch to generic text rendering method - FireScene: classical fire effect - WeatherScene: bug fixes, switch to generic text rendering method - WeatherScene: ensure minimum on-screen time - WeatherScene: use custom JSON parsing to reduce memory usage
This commit is contained in:
113
pixelfont.py
113
pixelfont.py
@@ -1,109 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# This file provides a small 4x5 (width and height) font primarily designed to
|
||||
# present the current date and time.
|
||||
#
|
||||
# The .data property provides the bits for each character available in .alphabet.
|
||||
# For each character, the consumer must extract the bits (4x5 == 20 bits) from
|
||||
# the offset given by the the character's position in .alphabet * 20.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# font = PixelFont()
|
||||
# digit = '2' # Extract and plot the digit '2'
|
||||
#
|
||||
# start_bit = font.alphabet.find(digit) * font.width * font.height
|
||||
# font_byte = start_bit // 8
|
||||
# font_bit = start_bit % 8
|
||||
# for y in range(font.height):
|
||||
# for x in range(font.width):
|
||||
# is_lit = font.data[font_byte] & (1<<font_bit)
|
||||
# put_pixel(x, y, is_lit)
|
||||
# font_bit +=1
|
||||
# if font_bit == 8:
|
||||
# font_byte += 1
|
||||
# font_bit = 0
|
||||
#
|
||||
# To add new symbols to the font, edit the `font` variable in to_bytearray(),
|
||||
# add a new 4x5 block representing the symbol, update the .alphabet property
|
||||
# and then run this file to generate updated data for Python and C:
|
||||
#
|
||||
# $ ./pixelfont.py
|
||||
#
|
||||
# Update the variables in the constructor with the new output.
|
||||
# 4x5 pixel font
|
||||
# See scripts/generate-pixelfont.py for details
|
||||
#
|
||||
class PixelFont:
|
||||
def __init__(self):
|
||||
self.width = 4
|
||||
self.height = 5
|
||||
self.alphabet = ' %\'-./0123456789:cms'
|
||||
self.data = bytearray("\x00\x00\x50\x24\x51\x66\x00\x00\x60\x00\x00\x00\x42\x24\x11\x57\x55\x27\x23\x72\x47\x17\x77\x64\x74\x55\x47\x74\x71\x74\x17\x57\x77\x44\x44\x57\x57\x77\x75\x74\x20\x20\x20\x15\x25\x75\x57\x75\x71\x74")
|
||||
|
||||
def to_bytearray(self):
|
||||
###|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|
|
||||
font = """
|
||||
# # ## # ### # ### ### # # ### ### ### ### ### # # # ###
|
||||
# ## # # # ## # # # # # # # # # # # # # # ### #
|
||||
# ## # # # # ### ## ### ### ### # ### ### # ### ###
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
# # # # ### ### ### ### # ### ### # ### ### # # # ###
|
||||
""".strip('\n').replace('\n', '')
|
||||
###|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|123|
|
||||
|
||||
data = bytearray()
|
||||
byte = bits = 0
|
||||
num_digits = len(self.alphabet)
|
||||
for i in range(num_digits):
|
||||
pixels = bytearray()
|
||||
for row in range(self.height):
|
||||
for col in range(self.width):
|
||||
pos = row * num_digits * self.width
|
||||
pos += i * self.width + col
|
||||
is_lit = int(font[pos] != ' ')
|
||||
byte |= is_lit << bits
|
||||
bits += 1
|
||||
if bits == 8:
|
||||
data.append(byte)
|
||||
bits = byte = 0
|
||||
if bits:
|
||||
data.append(byte)
|
||||
return data
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
f = PixelFont()
|
||||
|
||||
data = f.to_bytearray()
|
||||
print('')
|
||||
print('# Computed with pixelfont.py')
|
||||
print(' self.width = {}'.format(f.width))
|
||||
print(' self.height = {}'.format(f.height))
|
||||
print(' self.alphabet = "{}"'.format(f.alphabet))
|
||||
print(' self.data = bytearray("{}")'.format("".join("\\x{:02x}".format(x) for x in data)))
|
||||
print('')
|
||||
print('/* Computed with pixelfont.py */')
|
||||
print('static int font_width = {};'.format(f.width))
|
||||
print('static int font_height = {};'.format(f.height))
|
||||
print('static char font_alphabet[] = "{}";'.format(f.alphabet))
|
||||
print('static unsigned char font_data[] = "{}";'.format("".join("\\x{:02x}".format(x) for x in data)))
|
||||
|
||||
debugstr = '12:30 1.8\'c'
|
||||
for j in range(len(debugstr)):
|
||||
digit = debugstr[j]
|
||||
i = f.alphabet.find(digit)
|
||||
if i < 0:
|
||||
print('WARN: digit {} not found in alphabet'.format(digit))
|
||||
font_byte = (i * f.height * f.width) // 8
|
||||
font_bit = (i * f.height * f.width) % 8
|
||||
for row in range(f.height):
|
||||
for col in range(f.width):
|
||||
val = 0
|
||||
if data[font_byte] & (1 << font_bit):
|
||||
val = 255
|
||||
sys.stdout.write('#' if val else ' ')
|
||||
font_bit += 1
|
||||
if font_bit == 8:
|
||||
font_byte += 1
|
||||
font_bit = 0
|
||||
sys.stdout.write('\n')
|
||||
width = 4
|
||||
height = 5
|
||||
alphabet = " %'-./0123456789:?acdefgiklmnoprstwxy"
|
||||
data = bytearray("\x00\x00\x50\x24\x51\x66\x00\x00\x60\x00\x00\x00\x42\x24\x11\x57\x55\x27\x23\x72\x47\x17\x77\x64\x74\x55\x47\x74\x71\x74\x17\x57\x77\x44\x44\x57\x57\x77\x75\x74\x20\x20\x30\x24\x20\x52\x57\x25\x15\x25\x53\x55\x73\x31\x71\x17\x13\x71\x71\x75\x27\x22\x57\x35\x55\x11\x11\x57\x77\x55\x75\x77\x75\x55\x75\x57\x17\x71\x35\x55\x17\x47\x77\x22\x22\x55\x77\x55\x25\x55\x55\x27\x02")
|
||||
|
||||
Reference in New Issue
Block a user