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:
Noah
2018-12-26 20:26:05 +00:00
parent 30903a207b
commit 3e4dd4c0bc
32 changed files with 102728 additions and 1274 deletions

View File

@@ -53,15 +53,6 @@ class WS2812:
self.spi = SPI(spi_bus, SPI.MASTER, baudrate=3200000, polarity=0, phase=1)
# turn LEDs off
self.show([])
def show(self, data):
"""
Show RGB data on LEDs. Expected data = [(R, G, B), ...] where R, G and B
are intensities of colors in range from 0 to 255. One RGB tuple for each
LED. Count of tuples may be less than count of connected LEDs.
"""
self.fill_buf(data)
self.send_buf()
def send_buf(self):
@@ -71,60 +62,33 @@ class WS2812:
disable_irq()
self.spi.write(self.buf)
enable_irq()
#gc.collect()
def update_buf(self, data, start=0):
"""
Fill a part of the buffer with RGB data.
Order of colors in buffer is changed from RGB to GRB because WS2812 LED
has GRB order of colors. Each color is represented by 4 bytes in buffer
(1 byte for each 2 bits).
Returns the index of the first unfilled LED
Note: If you find this function ugly, it's because speed optimisations
beated purity of code.
"""
buf = self.buf
buf_bytes = self.buf_bytes
intensity = self.intensity
mask = 0x03
index = start * 12
for red, green, blue in data:
# This saves 10ms for 256 leds
#red = int(red * intensity)
#green = int(green * intensity)
#blue = int(blue * intensity)
buf[index] = buf_bytes[green >> 6 & mask]
buf[index+1] = buf_bytes[green >> 4 & mask]
buf[index+2] = buf_bytes[green >> 2 & mask]
buf[index+3] = buf_bytes[green & mask]
buf[index+4] = buf_bytes[red >> 6 & mask]
buf[index+5] = buf_bytes[red >> 4 & mask]
buf[index+6] = buf_bytes[red >> 2 & mask]
buf[index+7] = buf_bytes[red & mask]
buf[index+8] = buf_bytes[blue >> 6 & mask]
buf[index+9] = buf_bytes[blue >> 4 & mask]
buf[index+10] = buf_bytes[blue >> 2 & mask]
buf[index+11] = buf_bytes[blue & mask]
index += 12
return index // 12
def fill_buf(self, data):
"""
Fill buffer with RGB data.
All LEDs after the data are turned off.
"""
end = self.update_buf(data)
# NOTE: show(), update_buf() and fill_buf() were replaced
# with these to reduce memory usage in pycomhal.py
def clear(self):
# turn off the rest of the LEDs
buf = self.buf
off = self.buf_bytes[0]
for index in range(end * 12, self.buf_length):
for index in range(self.buf_length):
buf[index] = off
index += 1
def put_pixel(self, addr, red, green, blue):
buf = self.buf
buf_bytes = self.buf_bytes
mask = 0x03
index = addr * 12
buf[index] = buf_bytes[green >> 6 & mask]
buf[index+1] = buf_bytes[green >> 4 & mask]
buf[index+2] = buf_bytes[green >> 2 & mask]
buf[index+3] = buf_bytes[green & mask]
buf[index+4] = buf_bytes[red >> 6 & mask]
buf[index+5] = buf_bytes[red >> 4 & mask]
buf[index+6] = buf_bytes[red >> 2 & mask]
buf[index+7] = buf_bytes[red & mask]
buf[index+8] = buf_bytes[blue >> 6 & mask]
buf[index+9] = buf_bytes[blue >> 4 & mask]
buf[index+10] = buf_bytes[blue >> 2 & mask]
buf[index+11] = buf_bytes[blue & mask]