
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()