b4 key rewrite
This commit is contained in:
parent
69d2b8641b
commit
1407e0cf26
@ -12,7 +12,7 @@
|
||||
# Limitations:
|
||||
# - USB light not fully implemented, because happens at irq level on real product
|
||||
#
|
||||
import os, sys, tty, pty, termios, time, pdb, tempfile, struct
|
||||
import os, sys, tty, pty, termios, time, pdb, tempfile, struct, zlib
|
||||
import subprocess
|
||||
import sdl2.ext
|
||||
from PIL import Image, ImageSequence
|
||||
@ -72,10 +72,14 @@ class SimulatedScreen:
|
||||
self.movie.append((dt, img))
|
||||
|
||||
class LCDSimulator(SimulatedScreen):
|
||||
# Simulate the LCD found on the Q1: 320x240xBGR565
|
||||
# Simulate the LCD found on the Q1: 320x240xRGB565
|
||||
|
||||
background_img = 'q1-images/background.png'
|
||||
|
||||
TEXT_PALETTE = [0x0000, 0x0861, 0x18e3, 0x2965, 0x39e7, 0x4a69, 0x5aeb, 0x6b6d,
|
||||
0x7bef, 0x8c71, 0x9cf3, 0xad75, 0xbdf7, 0xdefb, 0xef7d, 0xffff]
|
||||
TEXT_PALETTE_INV = list(reversed(TEXT_PALETTE))
|
||||
|
||||
# where the simulated screen is, relative to fixed background
|
||||
TOPLEFT = (65, 60)
|
||||
|
||||
@ -94,13 +98,23 @@ class LCDSimulator(SimulatedScreen):
|
||||
def __init__(self, factory):
|
||||
self.movie = None
|
||||
|
||||
self.sprite = s = factory.create_software_sprite( (320,240), bpp=32)
|
||||
self.sprite = s = factory.create_software_sprite( (320,240), bpp=16)
|
||||
s.x, s.y = self.TOPLEFT
|
||||
s.depth = 100
|
||||
|
||||
self.palette = [sdl2.ext.prepare_color(code, s) for code in self.palette_colours]
|
||||
assert len(self.palette) == 16
|
||||
|
||||
# selftest
|
||||
try:
|
||||
assert sdl2.ext.prepare_color('#0f0', s) == 0x07e0, 'need RGB565 sprite (got 555?)'
|
||||
assert sdl2.ext.prepare_color('#f00', s) == 0xf800, 'need RGB565 sprite (got RGB?)'
|
||||
except:
|
||||
print('red = ' + hex(sdl2.ext.prepare_color('#f00', s)))
|
||||
print('grn = ' + hex(sdl2.ext.prepare_color('#0f0', s)))
|
||||
print('blu = ' + hex(sdl2.ext.prepare_color('#00f', s)))
|
||||
raise
|
||||
|
||||
sdl2.ext.fill(s, self.palette[0])
|
||||
|
||||
self.mv = sdl2.ext.pixels2d(self.sprite)
|
||||
@ -112,24 +126,78 @@ class LCDSimulator(SimulatedScreen):
|
||||
def new_contents(self, readable):
|
||||
# got bytes for new update. expect a header and packed pixels
|
||||
while 1:
|
||||
prefix = readable.read(8)
|
||||
prefix = readable.read(11)
|
||||
if not prefix: return
|
||||
X,Y, w, h = struct.unpack('<4H', prefix)
|
||||
mode, X,Y, w, h, count = struct.unpack('<s5H', prefix)
|
||||
mode = mode.decode('ascii')
|
||||
here = readable.read(count)
|
||||
|
||||
assert X>=0 and Y>=0
|
||||
assert X+w <= 320
|
||||
assert Y+h <= 240
|
||||
|
||||
sz = w*h
|
||||
here = readable.read(sz)
|
||||
assert len(here) == sz
|
||||
try:
|
||||
assert X>=0 and Y>=0
|
||||
assert X+w <= 320
|
||||
assert Y+h <= 240
|
||||
assert len(here) == count
|
||||
except AssertionError:
|
||||
print(f"Bad LCD update: x,y={X},{Y} w,h={w}x{h} mode={mode}")
|
||||
continue
|
||||
|
||||
pos = 0
|
||||
for y in range(Y, Y+h):
|
||||
for x in range(X, X+w):
|
||||
val = here[pos]
|
||||
pos += 1
|
||||
self.mv[x][y] = self.palette[val & 0xf]
|
||||
if mode == 'p':
|
||||
# palette lookup mode (fixed, limited; obsolete)
|
||||
assert w*h == count
|
||||
|
||||
for y in range(Y, Y+h):
|
||||
for x in range(X, X+w):
|
||||
val = here[pos]
|
||||
pos += 1
|
||||
self.mv[x][y] = self.palette[val & 0xf]
|
||||
|
||||
elif mode in 'ti':
|
||||
# palette lookup mode for text: packed 4-bit / pixel
|
||||
# cheat: palette is not repeated over link
|
||||
assert w*h == count*2, [w,h,count]
|
||||
|
||||
pal = self.TEXT_PALETTE if mode == 't' else self.TEXT_PALETTE_INV
|
||||
|
||||
unpacked = bytearray()
|
||||
for b in here:
|
||||
unpacked.append(b >> 4)
|
||||
unpacked.append(b & 0xf)
|
||||
|
||||
for y in range(Y, Y+h):
|
||||
for x in range(X, X+w):
|
||||
val = unpacked[pos]
|
||||
self.mv[x][y] = pal[val & 0xf]
|
||||
pos += 1
|
||||
|
||||
elif mode == 'z':
|
||||
# compressed RGB565 pixels
|
||||
raw = zlib.decompress(here, wbits=-12)
|
||||
assert w*h*2 == len(raw)
|
||||
for y in range(Y, Y+h):
|
||||
for x in range(X, X+w):
|
||||
#val = (raw[pos] << 8) + raw[pos+1]
|
||||
#val = raw[pos+1] + (raw[pos] << 8)
|
||||
val, = struct.unpack('<H', raw[pos:pos+2])
|
||||
self.mv[x][y] = val
|
||||
pos += 2
|
||||
|
||||
elif mode == 'r':
|
||||
# raw RGB565 pixels (not compressed, packed)
|
||||
# slow, avoid
|
||||
assert count == w * h * 2, [count, w, h]
|
||||
for y in range(Y, Y+h):
|
||||
for x in range(X, X+w):
|
||||
val, = struct.unpack('<H', here[pos:pos+2])
|
||||
self.mv[x][y] = val
|
||||
pos += 2
|
||||
|
||||
elif mode == 'f':
|
||||
# fill a region to single pixel value
|
||||
px, = struct.unpack("<H", here)
|
||||
for y in range(Y, Y+h):
|
||||
for x in range(X, X+w):
|
||||
self.mv[x][y] = px
|
||||
|
||||
if self.movie is not None:
|
||||
self.new_frame()
|
||||
@ -282,7 +350,7 @@ def scancode_remap(sc):
|
||||
|
||||
def alt_up(ch):
|
||||
# ALT+(ch) => special needs of Q1
|
||||
print(f"Alt: {ch}")
|
||||
|
||||
if ch == 'n':
|
||||
return q1_charmap.KEY_NFC
|
||||
if ch == 'q':
|
||||
@ -290,20 +358,30 @@ def alt_up(ch):
|
||||
if ch == 'l':
|
||||
return q1_charmap.KEY_LAMP
|
||||
|
||||
print(f"Alt+{ch.upper()} ignored")
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def start():
|
||||
is_q1 = ('--q1' in sys.argv)
|
||||
|
||||
print('''\nColdcard Simulator: Commands (over simulated window):
|
||||
- Control-Q to quit
|
||||
- ^Z to snapshot screen.
|
||||
- ^S/^E to start/end movie recording
|
||||
- ^N to capture NFC data (tap it)
|
||||
- ^N to capture NFC data (tap it)'''
|
||||
)
|
||||
if is_q1:
|
||||
print('''\
|
||||
Q1 specials:
|
||||
Alt-L - lamp button (but ignored because implemented lower level)
|
||||
Alt-N - NFC button
|
||||
Alt-Q - QR button
|
||||
''')
|
||||
sdl2.ext.init()
|
||||
sdl2.SDL_EnableScreenSaver()
|
||||
|
||||
is_q1 = ('--q1' in sys.argv)
|
||||
|
||||
factory = sdl2.ext.SpriteFactory(sdl2.ext.SOFTWARE)
|
||||
simdis = (OLEDSimulator if not is_q1 else LCDSimulator)(factory)
|
||||
@ -418,6 +496,7 @@ def start():
|
||||
ch = shift_up(ch)
|
||||
if event.key.keysym.mod & 0x300: # left or right ALT
|
||||
ch = alt_up(ch)
|
||||
if ch is None: continue
|
||||
except:
|
||||
# things like 'shift' by itself and anything not really ascii
|
||||
|
||||
@ -466,7 +545,7 @@ def start():
|
||||
numpad_tx.write(b'\n')
|
||||
continue
|
||||
|
||||
if event.key.keysym.mod == 0x40:
|
||||
if event.key.keysym.mod == 0x40 and event.type == sdl2.SDL_KEYUP:
|
||||
# control key releases: ignore
|
||||
continue
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user