summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Thompson <daniel@redfelineninja.org.uk>2020-02-01 20:20:53 (GMT)
committerDaniel Thompson <daniel@redfelineninja.org.uk>2020-02-01 20:20:53 (GMT)
commite21f2a79cae0a79687061d30606599b930aa7480 (patch)
treefe8e78885d7d17af5fb8668269fa45ddf830b290
parentc7e11d60205a50e3f63344cc327be1930ff2f7d3 (diff)
wasp: simulator: Add ST7789 simulation
-rw-r--r--wasp/boards/simulator/display.py73
-rw-r--r--wasp/boards/simulator/machine.py22
-rw-r--r--wasp/boards/simulator/watch.py14
3 files changed, 102 insertions, 7 deletions
diff --git a/wasp/boards/simulator/display.py b/wasp/boards/simulator/display.py
new file mode 100644
index 0000000..dc303d9
--- /dev/null
+++ b/wasp/boards/simulator/display.py
@@ -0,0 +1,73 @@
+""" Simulated ST7789 display. """
+
+import sys
+import sdl2
+import sdl2.ext
+
+CASET = 0x2a
+RASET = 0x2b
+RAMWR = 0x2c
+
+class ST7789Sim(object):
+ def __init__(self, width=240, height=240):
+ sdl2.ext.init()
+
+ self.width = width
+ self.height = height
+
+ self.x = 0
+ self.y = 0
+ self.colclip = [0, width-1]
+ self.rowclip = [0, height-1]
+ self.cmd = 0
+
+ self.window = sdl2.ext.Window("ST7789", size=(width, height))
+ self.window.show()
+ self.windowsurface = self.window.get_surface()
+ sdl2.ext.fill(self.windowsurface, (0, 0, 0))
+
+ def write(self, data):
+ if len(data) == 1:
+ # Assume if we get a byte at a time then it is command.
+ # This is a simplification do we don't have to track
+ # the D/C pin from within the simulator.
+ self.cmd = data[0]
+
+ elif self.cmd == CASET:
+ self.colclip[0] = (data[0] << 8) + data[1]
+ self.colclip[1] = (data[2] << 8) + data[3]
+ self.x = self.colclip[0]
+
+ elif self.cmd == RASET:
+ self.rowclip[0] = (data[0] << 8) + data[1]
+ self.rowclip[1] = (data[2] << 8) + data[3]
+ self.y = self.rowclip[0]
+
+ elif self.cmd == RAMWR:
+ pixelview = sdl2.ext.PixelView(self.windowsurface)
+
+ half = False
+ for d in data:
+ if not half:
+ rgb = d << 8
+ half = True
+ continue
+ rgb |= d
+ half = False
+
+ pixel = ((rgb & 0xf800) >> 8,
+ (rgb & 0x07e0) >> 3,
+ (rgb & 0x001f) << 3)
+
+ pixelview[self.y][self.x] = pixel
+
+ self.x += 1
+ if self.x > self.rowclip[1]:
+ self.x = self.rowclip[0]
+ self.y += 1
+ if self.y > self.colclip[1]:
+ self.y = self.colclip[0]
+
+ # Forcibly release the surface to ensure it is unlocked
+ del pixelview
+ self.window.refresh()
diff --git a/wasp/boards/simulator/machine.py b/wasp/boards/simulator/machine.py
index 2c93770..3f8989f 100644
--- a/wasp/boards/simulator/machine.py
+++ b/wasp/boards/simulator/machine.py
@@ -1,3 +1,5 @@
+import display
+
class Tracer(object):
def __init__(self, *args, **kwargs):
print(f'{self.__class__.__name__}.__init__{args} {kwargs}')
@@ -14,9 +16,10 @@ class Pin(object):
IN = 'IN'
OUT = 'OUT'
- def __init__(self, id, direction, value=1):
+ def __init__(self, id, direction, value=1, quiet=False):
self._id = id
self._value = 0
+ self._quiet = quiet
def init(self, d, value):
self.value(value)
@@ -29,12 +32,16 @@ class Pin(object):
def value(self, v=None):
if v is None:
+ if not self._quiet:
+ print(f'{self._id}: read {self._value}')
return self._value
if v:
- print(self._id + ": on")
+ if not self._quiet:
+ print(self._id + ": set on")
self._value = False
else:
- print(self._id + ": off")
+ if not self._quiet:
+ print(self._id + ": set off")
self._value = True
def __call__(self, v=None):
@@ -46,9 +53,16 @@ class PWM(Tracer):
class SPI(object):
def __init__(self, id):
self._id = id
+ if id == 0:
+ self.sim = display.ST7789Sim()
+ else:
+ self.sim = None
def init(self, baudrate=1000000, polarity=0, phase=0, bits=8, sck=None, mosi=None, miso=None):
pass
def write(self, buf):
- print("Sending data: " + str(buf))
+ if self.sim:
+ self.sim.write(buf)
+ else:
+ print("Sending data: " + str(buf))
diff --git a/wasp/boards/simulator/watch.py b/wasp/boards/simulator/watch.py
index c6d695f..89faffe 100644
--- a/wasp/boards/simulator/watch.py
+++ b/wasp/boards/simulator/watch.py
@@ -9,6 +9,13 @@ from machine import SPI
from drivers.st7789 import ST7789_SPI
from drivers.vibrator import Vibrator
+class Backlight(object):
+ def __init__(self, level=1):
+ self.set(level)
+
+ def set(self, level):
+ print(f'BACKLIGHT: {level}')
+
class Display(ST7789_SPI):
def __init__(self):
spi = SPI(0)
@@ -16,11 +23,12 @@ class Display(ST7789_SPI):
spi.init(polarity=1, phase=1, baudrate=8000000)
# Configure the display
- cs = Pin("DISP_CS", Pin.OUT)
- dc = Pin("DISP_DC", Pin.OUT)
- rst = Pin("DISP_RST", Pin.OUT)
+ cs = Pin("DISP_CS", Pin.OUT, quiet=True)
+ dc = Pin("DISP_DC", Pin.OUT, quiet=True)
+ rst = Pin("DISP_RST", Pin.OUT, quiet=True)
super().__init__(240, 240, spi, cs=cs, dc=dc, res=rst)
display = Display()
+backlight = Backlight()
vibrator = Vibrator(Pin('MOTOR', Pin.OUT, value=0), active_low=True)