micro:bit v1だと、メモリ不足で歯が立たない
>>> microbit.reset()
MemoryError:
MicroPython v1.9.2-34-gd64154c73 on 2017-09-01; micro:bit v1.0.1 with nRF51822
Type “help()” for more information.
>>>
>>> micropython.mem_info()
stack: 516 out of 1800
GC: total: 10048, used: 672, free: 9376
No. of 1-blocks: 18, 2-blocks: 9, max blk sz: 3, max free sz: 562
>>>
micro:bit v2では、8KBのソースが複数個ロードでき、余裕で動作する。
>>> microbit.reset()
MicroPython v1.13 on 2020-12-21; micro:bit v2.0.0-beta.3 with nRF52833
Type “help()” for more information.
>>>
>>> micropython.mem_info()
stack: 392 out of 7680
GC: total: 64512, used: 24832, free: 39680
No. of 1-blocks: 583, 2-blocks: 199, max blk sz: 189, max free sz: 1266
>>>
# MemoryDisplayライブラリ (MemoDisp.py)
# The MIT License (MIT) # # Copyright (c) 2018 ladyada for Adafruit Industries # pylint: disable=line-too-long """ `adafruit_sharpmemorydisplay` ==================================================== https://github.com/adafruit/circuitpython/releases """ from microbit import * from micropython import const # import sharp_memorydisp _SHARPMEM_BIT_WRITECMD = const(0x80) # in lsb _SHARPMEM_BIT_VCOM = const(0x40) # in lsb _SHARPMEM_BIT_CLEAR = const(0x20) # in lsb spi_clk = pin13 spi_scs = pin12 CS_ACTIVE = const(1) CS_INACTIVE = const(0) # Colors BLACK = const(0) WHITE = const(255) # Parameters to Change COLS = const(144) ROWS = const(168) COLBYTES = const(COLS // 8) TEXT_NORMAL = const(2) ROTATION = list(range(4)) _icons = [getattr(Image, x) for x in dir(Image) if hasattr(getattr(Image, x), 'get_pixel')] def reverse_bit(num): """Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as it is LSB for the SHARP, but 99% of SPI implementations are MSB only!""" result = 0 for _ in range(8): result <<= 1 result += num & 1 num >>= 1 return result class SharpMemoryDisplay(): """A driver for sharp memory displays, you can use any size but the full display must be buffered in memory!""" def __init__(self, spiP, width, height, *, baudrate=2000000, portrait=True, bottom=False): self._scs_pin = spi_scs # The SCS pin is active HIGH so we can't use bus_device. exciting! # scs_pin.switch_to_output(value=True) self._baudrate = baudrate self._portrait = portrait self._bottom = bottom self._spi = spiP self.width = width self.height = height # prealloc for when we write the display self._buf = bytearray(1) self.buffer = bytearray((width // 8) * height) # Set the vcom bit to a defined state self._vcom = True def fill(self, color, start=0, stop=0): """completely fill/clear the buffer with a color""" if color == 1: fill = WHITE else: fill = BLACK if stop == 0: bufl = len(self.buffer) else: bufl = stop*COLBYTES if not self._portrait: start = 0 bufl = len(self.buffer) elif self._bottom : bufl = (self.height - start)*COLBYTES if stop>0: start = (self.height - stop)*COLBYTES for i in range(start, bufl): self.buffer[i] = fill def clear(self): """completely fill/clear the buffer """ self._scs_pin.write_digital(CS_ACTIVE) self._buf[0] = _SHARPMEM_BIT_CLEAR self._spi.write(self._buf) self._buf[0] = 0 self._spi.write(self._buf) # we send one last 0 byte self._scs_pin.write_digital(CS_INACTIVE) def show(self, start=1, stop=0, rotate=0): portrait, bottom = ROTATION[rotate] # CS pin is inverted so we have to do this all by hand self._scs_pin.write_digital(CS_ACTIVE) # toggle the VCOM bit self._buf[0] = _SHARPMEM_BIT_WRITECMD if self._vcom: self._buf[0] |= _SHARPMEM_BIT_VCOM self._vcom = not self._vcom self._spi.write(self._buf) if (not portrait) or stop == 0: start = 1 stop = self.height stopl = self.height + 1 else: stopl = stop + 1 if portrait and bottom : stopl = (self.height - start+1) + 1 start = (self.height - stop) + 1 line_len = COLBYTES slice_from = (start-1) * line_len for line in range(start, stopl): self._buf[0] = reverse_bit(line) self._spi.write(self._buf) self._spi.write( memoryview(self.buffer[slice_from : slice_from + line_len])) slice_from += line_len self._buf[0] = 0 self._spi.write(self._buf) self._spi.write(self._buf) # we send one last 0 byte self._scs_pin.write_digital(CS_INACTIVE) def draw_line(self, x0, y0, x1, y1, color=1, rotate=0): dx = abs(x1 - x0) sx = 1 if x0 < x1 else -1 dy = -abs(y1 - y0) sy = 1 if y0 < y1 else -1 err = dx + dy while True: self.set_pixel(x0, y0, color, rotate=0) if x0 == x1 and y0 == y1: break e2 = 2 * err if e2 > dy: err += dy x0 += sx if e2 <= dx: err += dx y0 += sy def set_pixel(self, x, y, color=1, rotate=0): portrait, bottom = ROTATION[rotate] if portrait : if bottom : x = COLS - x shift = 7 - x % 8 x //= 8 offset = y if bottom : offset = ROWS - offset offset = offset * COLBYTES + x else: if not bottom : y = COLS - y shift = 7 - y % 8 y //= 8 offset = x if bottom : offset = ROWS - offset offset = offset * COLBYTES + y if offset >= len(self.buffer): return byte_b = self.buffer[offset] if color == 1: # Mask *out* a bit to set as black byte_b &= ~(0b1 << shift) if color == 0: # a bit to set as white byte_b |= (0b1 << shift) self.buffer[offset] = byte_b def draw_bin(self, filename): with open(filename, "rb") as f: f.readinto(self.buffer) spi.init(baudrate=8000000, bits=8, mode=0) # Create blank image for drawing.
# デモプログラム
# ここにコードを書いてね :-) from microbit import * from micropython import const import time import MemoDisp COLS = const(144) ROWS = const(168) COLBYTES = const(COLS // 8) # Colors BLACK = const(0) WHITE = const(255) # Parameters to Change WIDTH = 144 HEIGHT = 168 PORTRAIT = (HEIGHT > WIDTH) BOTTOMUP = True BORDER = 5 OFFSET_X = 4 OFFSET_Y = 4 TEXT_NORMAL = const(2) MemoDisp.ROTATION[0] = (PORTRAIT, BOTTOMUP) MemoDisp.ROTATION[1] = (not PORTRAIT, BOTTOMUP) MemoDisp.ROTATION[2] = (PORTRAIT, not BOTTOMUP) MemoDisp.ROTATION[3] = (not PORTRAIT, not BOTTOMUP) def char_len(char, text_size=TEXT_NORMAL): if char in b"\"*+-0123<=>ABCDEFHKLOPQSUXZ[]^bcdefghjklnopqrsxz{": return 4 * text_size if char in b"!'.:i|": return 2 * text_size if char in b" (),;I`}": return 3 * text_size return 5 * text_size def text_len(text, text_size=TEXT_NORMAL): return sum(char_len(c, text_size=text_size) + text_size for c in text) def draw_image(icon, x, y, color=1, type="T", size=TEXT_NORMAL, rotate=0): cols = 5 * size rows = 5 * size for ox in range(cols): if x + ox < 0: continue if x + ox >= WIDTH: return False for oy in range(rows): if (not icon.get_pixel(ox // size, oy // size)) and type == "T": disp.set_pixel(ox + x + OFFSET_X, oy + y + OFFSET_Y, color ^ 1, rotate=rotate) continue try: disp.set_pixel(ox + x + OFFSET_X, oy + y + OFFSET_Y, color, rotate=rotate) except IndexError: pass return True def write_text(text, x, y, color=1, text_size=TEXT_NORMAL, rotate=0): image = None for letter in text: image = None letter_width = char_len(letter, text_size=text_size) if x+letter_width >= WIDTH or ord(letter) == 13: y += text_size*5+2 x = OFFSET_X if letter != " " and (x + letter_width) >= 1: if ord(letter) > 127: image = MemoDisp._icons[ord(letter) - 128] else: try: image = Image(letter) except: pass if image is not None: if not draw_image(image, x, y, color, type="T", size=text_size, rotate=rotate): return if ord(letter) != 13: x += letter_width + text_size del image # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) disp = MemoDisp.SharpMemoryDisplay(spi, COLS, ROWS, portrait=PORTRAIT, bottom=BOTTOMUP) # Clear display. disp.fill(1) disp.show() # Draw Some Text text = "Hello World! Good morning." write_text(text, 0, 5, rotate=0) disp.draw_line(0, 5+OFFSET_Y + TEXT_NORMAL*5, text_len(text), 5+OFFSET_Y + TEXT_NORMAL*5, color=1) disp.show(5, 35) write_text(text, 0, 5, rotate=1) disp.show(5, 35, rotate=1) write_text(text, 0, 5, rotate=2) disp.show(5, 35, rotate=2) write_text(text, 0, 5, rotate=3) disp.show(5, 35, rotate=3) sleep(300) disp.show(5, 35) disp.fill(1, 5, 35) sleep(500) disp.show(5, 35) write_text("Time = ", 0, 5) start = time.ticks_ms() while not button_a.is_pressed(): past = time.ticks_diff(time.ticks_ms(), start) if past % 100 == 0: write_text(str(past // 100), TEXT_NORMAL*5*7, 5) disp.show(5, 35) if past > 800: start = time.ticks_ms() # Display image with open('Screen1.bin', "wb") as f: f.write(disp.buffer) disp.fill(0) disp.show() sleep(1000) disp.draw_bin('Screen1.bin') disp.show() # disp.clear()