Mk hardware
This commit is contained in:
parent
9b131b2eff
commit
38553d1ac5
@ -208,8 +208,9 @@ def readback(fname):
|
||||
if v & MK_2_OK: d.append('Mk2')
|
||||
if v & MK_3_OK: d.append('Mk3')
|
||||
if v & MK_4_OK: d.append('Mk4')
|
||||
if v & MK_5_OK: d.append('Mk5')
|
||||
if v & MK_Q1_OK: d.append('Q1')
|
||||
if v & ~(MK_1_OK | MK_2_OK | MK_3_OK | MK_4_OK | MK_Q1_OK):
|
||||
if v & ~(MK_1_OK | MK_2_OK | MK_3_OK | MK_4_OK | MK_5_OK | MK_Q1_OK):
|
||||
d.append('?other?')
|
||||
v = nv + '+'.join(d)
|
||||
elif fld == 'timestamp':
|
||||
@ -245,7 +246,7 @@ def readback(fname):
|
||||
@click.option('--pubkey-num', '-k', type=int, help='Which key # to use for signing', default=0)
|
||||
@click.option('--high_water', '-h', is_flag=True, help='Mark version as new highwater mark (no downgrades below this version)')
|
||||
@click.option('--verbose', '-v', default=False, is_flag=True, help='Show numbers related to signature')
|
||||
@click.option('--hw-compat', '-m', type=str, metavar='Mk4', help="Set HW compat field (hw_label value)")
|
||||
@click.option('--hw-compat', '-m', type=str, metavar='mk', help="Set HW compat field (hw_label value)")
|
||||
@click.option('--backdate', type=int, metavar='DAYS',
|
||||
help='Make downgrade attack test version', default=0)
|
||||
@click.option('--build_dir', '-b', default='l-port/build-COLDCARD')
|
||||
@ -278,8 +279,9 @@ def doit(keydir, outfn=None, build_dir=None, high_water=False,
|
||||
vectors = open(build_dir + '/firmware0.bin', 'rb').read()
|
||||
body = open(build_dir + '/firmware1.bin', 'rb').read()
|
||||
|
||||
if hw_compat in { 'mk4', '4'}:
|
||||
hw_compat = MK_4_OK
|
||||
if hw_compat in { 'mk4', '4', 'mk5', '5', 'mk' }:
|
||||
# Mk4 and 5 can run the same firmware, once Mk5 support was added
|
||||
hw_compat = MK_4_OK | MK_5_OK
|
||||
elif hw_compat == 'q1':
|
||||
hw_compat = MK_Q1_OK
|
||||
elif hw_compat in { 'mk3', '3'}:
|
||||
|
||||
@ -17,6 +17,14 @@ class Graphics:
|
||||
|
||||
mk4_nfc_4 = (102, 49, 13, 0, b'\x00\x7f\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xcf\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xcf\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xcf\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xcf\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x03\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x0e\x03\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\xe0\x0e\x07\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xe0\x0e\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e0\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e0\x000D\x04\x10\x00\x00\x7f\xf0\x00\xe0\x0e0\x000D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00(D\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00(D\x04\x00\x00\x00xp\x00\xff\xff\xb0\x00$G\xe4\x00\x00\x00xp\x00\xff\xff\xb0\x00$G\xe4\x00\x00\x00xp\x00\xe0\x0e0\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e0\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e0\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e?\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\x9f\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\xff\xff\x8f\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00')
|
||||
|
||||
mk5_nfc_1 = (126, 49, 16, 0, b'\x00\x7f\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xf0\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x0e\x00\xe0\x0e\x03\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\xe0\x0e\x00\xe0\x0e\x07\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xe0\x0e\x00\xe0\x0e\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\xe0\x0e\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x000D\x04\x10\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x000D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00(D\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00(D\x04\x00\x00\x00xp\x00\xff\xff\xff\xff\xfe0\x00$G\xe4\x00\x00\x00xp\x00\xff\xff\xff\xff\xfe0\x00$G\xe4\x00\x00\x00xp\x00\xe0\x0e\x00\xe0\x0e0\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e\x00\xe0\x0e0\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e\x00\xe0\x0e0\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xff\xff\xff\xff\xfe0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0\x0e?\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\xff\xff\xfe\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\xff\xff\xff\xff\xfe\x0f\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
|
||||
mk5_nfc_2 = (118, 49, 15, 0, b'\x00\x7f\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xf0\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x0e\x00\xe0\x03\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\xe0\x0e\x00\xe0\x07\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xe0\x0e\x00\xe0\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\xe0\x0e\x00\xe00\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x000D\x04\x10\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x000D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00(D\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00(D\x04\x00\x00\x00xp\x00\xff\xff\xff\xff0\x00$G\xe4\x00\x00\x00xp\x00\xff\xff\xff\xff0\x00$G\xe4\x00\x00\x00xp\x00\xe0\x0e\x00\xe00\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e\x00\xe00\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e\x00\xe00\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xff\xff\xff\xff0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe00\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00\xe0?\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\xff\xff\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\xff\xff\xff\xff\x0f\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
|
||||
mk5_nfc_3 = (110, 49, 14, 0, b'\x00\x7f\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xf0\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x0e\x00\x03\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\xe0\x0e\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xe0\x0e\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\xe0\x0e\x000\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x000D\x04\x10\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x000D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00(D\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00(D\x04\x00\x00\x00xp\x00\xff\xff\xff0\x00$G\xe4\x00\x00\x00xp\x00\xff\xff\xff0\x00$G\xe4\x00\x00\x00xp\x00\xe0\x0e\x000\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e\x000\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e\x000\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xff\xff\xff0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x000\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\xff\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\xff\xff\xff\x0f\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
|
||||
mk5_nfc_4 = (102, 49, 13, 0, b'\x00\x7f\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xf0\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x0e\x03\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\xe0\x0e\x07\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xe0\x0e\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e0\x00 G\xe3\xe0\x00\x00\x7f\xf0\x00\xe0\x0e0\x000D\x04\x10\x00\x00\x7f\xf0\x00\xe0\x0e0\x000D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00(D\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00(D\x04\x00\x00\x00xp\x00\xff\xff\xb0\x00$G\xe4\x00\x00\x00xp\x00\xff\xff\xb0\x00$G\xe4\x00\x00\x00xp\x00\xe0\x0e0\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e0\x00"D\x04\x00\x00\x00xp\x00\xe0\x0e0\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00 \xc4\x04\x00\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x04\x10\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xff\xff\xb0\x00 D\x03\xe0\x00\x00\x7f\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e0\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\xe0\x0e?\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\x9f\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\xff\xff\x8f\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00')
|
||||
|
||||
scroll = (3, 61, 1, 0, b'@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@\x00\x00@@\xe0@')
|
||||
|
||||
selected = (9, 12, 2, 0, b'\x00\x00\x00\x00\x00\x80\x01\x80\x01\x00\x03\x00\x82\x00\xc6\x00d\x00<\x00\x18\x00\x00\x00')
|
||||
|
||||
49
graphics/mono/mk5_nfc_1.txt
Normal file
49
graphics/mono/mk5_nfc_1.txt
Normal file
@ -0,0 +1,49 @@
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxx xxxx xxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n f c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxx xxx xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
49
graphics/mono/mk5_nfc_2.txt
Normal file
49
graphics/mono/mk5_nfc_2.txt
Normal file
@ -0,0 +1,49 @@
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxx xxxx xxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxx xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n f c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxx xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxx xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
49
graphics/mono/mk5_nfc_3.txt
Normal file
49
graphics/mono/mk5_nfc_3.txt
Normal file
@ -0,0 +1,49 @@
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxx xxxx xxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n n f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n n f c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
49
graphics/mono/mk5_nfc_4.txt
Normal file
49
graphics/mono/mk5_nfc_4.txt
Normal file
@ -0,0 +1,49 @@
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxx xxxx xxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxx xxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxx
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy yyyyyyyyyyy
|
||||
xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx yy n n ffffff ccccc yyyyyyyyyyy
|
||||
xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxx xxx yy nn n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy n n n f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy n n n f c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxxxxxxxxxxxxxxxx yy n n n ffffff c yyyy yyy
|
||||
xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx yy n n n f c yyyy yyy
|
||||
xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxx xxx yy n nn f c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy n n f c c yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yy n n f ccccc yyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx yy yyyyyyyyyyy
|
||||
xxx xxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
xxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
@ -2397,9 +2397,23 @@ async def microsd_2fa(*a):
|
||||
|
||||
async def keyboard_test(*a):
|
||||
# to aid keyboard testing/dev
|
||||
from ux import ux_input_text
|
||||
await ux_input_text('', max_len=128, scan_ok=True, confirm_exit=False,
|
||||
prompt='Keyboard Test', placeholder='(type whatever)')
|
||||
if version.has_qwerty:
|
||||
await ux_input_text('', max_len=128, scan_ok=True, confirm_exit=False,
|
||||
prompt='Keyboard Test', placeholder='(type whatever)')
|
||||
else:
|
||||
from ux_mk4 import ux_input_digits
|
||||
await ux_input_digits('')
|
||||
|
||||
async def quick_nfc_test(*a):
|
||||
from selftest import test_nfc
|
||||
await test_nfc()
|
||||
|
||||
async def clear_tested_flag(*a):
|
||||
# so can re-create first time power up in
|
||||
# factory case (direct to selftest)
|
||||
settings.remove_key('tested')
|
||||
settings.save()
|
||||
await reset_self()
|
||||
|
||||
#
|
||||
# Q wrappers; these will be present, but are very short on mk4
|
||||
|
||||
@ -2,9 +2,8 @@
|
||||
#
|
||||
# display.py - OLED rendering
|
||||
#
|
||||
import machine, uzlib, ckcc, utime
|
||||
import machine, uzlib, ckcc, utime, version
|
||||
from ssd1306 import SSD1306_SPI
|
||||
from version import is_devmode
|
||||
import framebuf
|
||||
from graphics_mk4 import Graphics
|
||||
from charcodes import OUT_CTRL_TITLE, OUT_CTRL_ADDRESS
|
||||
@ -35,11 +34,14 @@ class Display:
|
||||
dc_pin = Pin('PA8', Pin.OUT)
|
||||
cs_pin = Pin('PA4', Pin.OUT)
|
||||
|
||||
try:
|
||||
self.dis = SSD1306_SPI(128, 64, spi, dc_pin, reset_pin, cs_pin)
|
||||
except OSError:
|
||||
print("OLED unplugged?")
|
||||
raise
|
||||
if version.mk_num == 5:
|
||||
# Early revs (A-D) needed this pin asserted to enable +12v to OLED
|
||||
# - removed in rev E and later boards, but keep here for dev boards
|
||||
# - remove this in 2027
|
||||
vcc_en = Pin('V12EN', Pin.OUT) # aka PC1
|
||||
vcc_en(1)
|
||||
|
||||
self.dis = SSD1306_SPI(128, 64, spi, dc_pin, reset_pin, cs_pin, is_mk5=(version.mk_num==5))
|
||||
|
||||
self.last_bar_update = 0
|
||||
self.clear()
|
||||
@ -142,7 +144,7 @@ class Display:
|
||||
self.icon(128-3, 1, 'scroll')
|
||||
self.dis.fill_rect(128-2, pos, 1, bh, 1)
|
||||
|
||||
if is_devmode and not ckcc.is_simulator():
|
||||
if version.is_devmode and not ckcc.is_simulator():
|
||||
self.dis.fill_rect(128-6, 20, 5, 21, 1)
|
||||
self.text(-2, 21, 'D', font=FontTiny, invert=1)
|
||||
self.text(-2, 28, 'E', font=FontTiny, invert=1)
|
||||
@ -204,61 +206,20 @@ class Display:
|
||||
|
||||
def busy_bar(self, enable):
|
||||
# Render a continuous activity (not progress) bar in lower 8 lines of display
|
||||
# - using OLED itself to do the animation, so smooth and CPU free
|
||||
# - cannot preserve bottom 8 lines, since we have to destructively write there
|
||||
# - assumes normal horz addr mode: 0x20, 0x00
|
||||
# - speed_code=>framedelay: 0=5fr, 1=64fr, 2=128, 3=256, 4=3, 5=4, 6=25, 7=2frames
|
||||
# unused: assert 0 <= speed_code <= 7
|
||||
|
||||
setup = bytes([
|
||||
0x21, 0x00, 0x7f, # setup column address range (start, end): 0-127
|
||||
0x22, 7, 7, # setup page start/end address: page 7=last 8 lines
|
||||
])
|
||||
animate = bytes([
|
||||
0x2e, # stop animations in progress
|
||||
0x26, # scroll leftwards (stock ticker mode)
|
||||
0, # placeholder
|
||||
7, # start 'page' (vertical)
|
||||
5, # "speed_code" # scroll speed: 7=fastest, but no order to it
|
||||
7, # end 'page'
|
||||
0, 0xff, # placeholders
|
||||
0x2f # start
|
||||
])
|
||||
|
||||
cleanup = bytes([
|
||||
0x2e, # stop animation
|
||||
0x20, 0x00, # horz addr-ing mode
|
||||
0x21, 0x00, 0x7f, # setup column address range (start, end): 0-127
|
||||
0x22, 7, 7, # setup page start/end address: page 7=last 8 lines
|
||||
])
|
||||
|
||||
#
|
||||
if not enable:
|
||||
# stop animation, and redraw old (new) screen
|
||||
self.write_cmds(cleanup)
|
||||
self.dis.busy_bar(False, None)
|
||||
self.show()
|
||||
else:
|
||||
|
||||
# a pattern that repeats nicely mod 128
|
||||
# Need a pattern that repeats nicely mod 128
|
||||
# - each byte here is a vertical column, 8 pixels tall, MSB at bottom
|
||||
data = bytes(0x80 if (x%4)<2 else 0x0 for x in range(128))
|
||||
pat = bytes(0x80 if (x%4)<2 else 0x0 for x in range(128))
|
||||
|
||||
if ckcc.is_simulator():
|
||||
# just show as static pattern
|
||||
t = self.dis.buffer[:-128] + data
|
||||
self.dis.write_data(t)
|
||||
else:
|
||||
self.write_cmds(setup)
|
||||
self.dis.write_data(data)
|
||||
self.write_cmds(animate)
|
||||
|
||||
def write_cmds(self, cmds):
|
||||
for c in cmds:
|
||||
self.dis.write_cmd(c)
|
||||
self.dis.busy_bar(True, pat)
|
||||
|
||||
def set_brightness(self, val):
|
||||
# normal = 0x7f, brightness=0xff, dim=0x00 (but they are all very similar)
|
||||
self.dis.write_cmd(0x81) # Set Contrast Control
|
||||
self.dis.write_cmd(val)
|
||||
return self.dis.contrast(val)
|
||||
|
||||
def menu_draw(self, ry, msg, is_sel, is_checked, space_indicators):
|
||||
# draw a menu item, perhaps selected, checked.
|
||||
|
||||
@ -307,6 +307,8 @@ DebugFunctionsMenu = [
|
||||
# xxxxxxxxxxxxxxxx
|
||||
MenuItem("Keyboard Test", f=keyboard_test),
|
||||
MenuItem('BBQr Demo', f=debug_bbqr_test, predicate=version.has_qwerty),
|
||||
MenuItem("NFC Test", f=quick_nfc_test),
|
||||
MenuItem('Clear Tested', f=clear_tested_flag),
|
||||
MenuItem('Debug: assert', f=debug_assert),
|
||||
MenuItem('Debug: except', f=debug_except),
|
||||
MenuItem('Check: BL FW', f=check_firewall_read),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# (c) Copyright 2021 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
#
|
||||
# mk4.py - Mk4 specific code, not needed on earlier devices.
|
||||
# mk4.py - Mk4 and Mk5 specific code, not needed on earlier devices.
|
||||
#
|
||||
#
|
||||
import os, sys, pyb, ckcc, version, glob
|
||||
|
||||
@ -419,7 +419,8 @@ class NFCHandler:
|
||||
dis.text(None, -3, line2)
|
||||
else:
|
||||
from graphics_mk4 import Graphics
|
||||
frames = [getattr(Graphics, 'mk4_nfc_%d'%i) for i in range(1, 5)]
|
||||
from version import mk_num
|
||||
frames = [getattr(Graphics, 'mk%d_nfc_%d'%(mk_num, i)) for i in range(1, 5)]
|
||||
|
||||
aborted = True
|
||||
phase = -1
|
||||
|
||||
@ -171,7 +171,7 @@ async def test_secure_element():
|
||||
|
||||
dis.clear()
|
||||
|
||||
if version.has_qwerty:
|
||||
if version.has_qwerty or version.mk_num == 5:
|
||||
dis.text(0, 0, "^^-- Green? " if gg else " ^^-- Red?")
|
||||
else:
|
||||
if gg:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
#
|
||||
# ssd1306.py - MicroPython SSD1306 OLED driver, I2C and SPI interfaces
|
||||
# ssd1306.py - MicroPython SSD1306 OLED driver, with SPI interface
|
||||
#
|
||||
# Copied from ../external/micropython/drivers/display/ssd1306.py
|
||||
#
|
||||
@ -28,49 +28,81 @@ SET_VCOM_DESEL = const(0xdb)
|
||||
SET_CHARGE_PUMP = const(0x8d)
|
||||
|
||||
# Subclassing FrameBuffer provides support for graphics primitives
|
||||
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
|
||||
# see <http://docs.micropython.org/en/latest/pyboard/library/framebuf.html>
|
||||
#
|
||||
class SSD1306(framebuf.FrameBuffer):
|
||||
def __init__(self, width, height, external_vcc):
|
||||
def __init__(self, width, height, is_mk5):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.external_vcc = external_vcc
|
||||
self.is_mk5 = is_mk5
|
||||
self.pages = self.height // 8
|
||||
|
||||
#self.buffer = bytearray(self.pages * self.width)
|
||||
|
||||
self.buffer = bytearray(1024)
|
||||
assert len(self.buffer) == self.pages * self.width
|
||||
#assert len(self.buffer) == self.pages * self.width
|
||||
|
||||
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
|
||||
self.init_display()
|
||||
|
||||
def init_display(self):
|
||||
for cmd in (
|
||||
SET_DISP | 0x00, # off
|
||||
# address setting
|
||||
SET_MEM_ADDR, 0x00, # horizontal
|
||||
# resolution and layout
|
||||
SET_DISP_START_LINE | 0x00,
|
||||
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
|
||||
SET_MUX_RATIO, self.height - 1,
|
||||
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
|
||||
SET_DISP_OFFSET, 0x00,
|
||||
SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
|
||||
# timing and driving scheme
|
||||
SET_DISP_CLK_DIV, 0xF0,
|
||||
SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
|
||||
SET_VCOM_DESEL, 0x30, # 0.83*Vcc
|
||||
# display
|
||||
SET_CONTRAST, 0xff, # maximum
|
||||
SET_ENTIRE_ON, # output follows RAM contents
|
||||
SET_NORM_INV, # not inverted
|
||||
# charge pump
|
||||
SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
|
||||
SET_DISP | 0x01): # on
|
||||
self.write_cmd(cmd)
|
||||
if not self.is_mk5:
|
||||
# Mk4 and earlier
|
||||
cmds = (
|
||||
SET_DISP | 0x00, # display off
|
||||
# address setting
|
||||
SET_MEM_ADDR, 0x00, # horizontal
|
||||
# resolution and layout
|
||||
SET_DISP_START_LINE | 0x00,
|
||||
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
|
||||
SET_MUX_RATIO, self.height - 1,
|
||||
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
|
||||
SET_DISP_OFFSET, 0x00,
|
||||
SET_COM_PIN_CFG, 0x12,
|
||||
# timing and driving scheme
|
||||
SET_DISP_CLK_DIV, 0xF0,
|
||||
SET_PRECHARGE, 0xf1,
|
||||
SET_VCOM_DESEL, 0x30, # 0.83*Vcc
|
||||
# display
|
||||
SET_CONTRAST, 0xff, # maximum
|
||||
SET_ENTIRE_ON, # output follows RAM contents
|
||||
SET_NORM_INV, # not inverted
|
||||
# charge pump
|
||||
SET_CHARGE_PUMP, 0x14)
|
||||
else:
|
||||
# Mk5 has external +12v power supply, and different setup protocol
|
||||
|
||||
cmds = (
|
||||
SET_DISP | 0x00, # display off
|
||||
# address setting
|
||||
SET_MEM_ADDR, 0x00, # horizontal
|
||||
# resolution and layout
|
||||
SET_DISP_START_LINE | 0x00,
|
||||
SET_SEG_REMAP | 0x00, # column addr 0 mapped to SEG127
|
||||
SET_MUX_RATIO, self.height - 1,
|
||||
SET_COM_OUT_DIR | 0x00, # scan from COM[8] to COM[N]
|
||||
SET_DISP_OFFSET, 0x00,
|
||||
SET_COM_PIN_CFG, 0x12,
|
||||
# timing and driving scheme
|
||||
SET_DISP_CLK_DIV, 0xF0,
|
||||
SET_PRECHARGE, 0x22,
|
||||
SET_VCOM_DESEL, 0x40, # per spec sheet
|
||||
# display
|
||||
SET_CONTRAST, 0x85, # NOT maximum, because spec sheet
|
||||
SET_ENTIRE_ON, # output follows RAM contents
|
||||
SET_NORM_INV, # not inverted
|
||||
SET_CHARGE_PUMP, 0x10, # charge pump: DISABLE
|
||||
)
|
||||
|
||||
self.write_cmds(cmds)
|
||||
|
||||
self.fill(0)
|
||||
self.show()
|
||||
|
||||
self.write_cmd(SET_DISP | 0x01)
|
||||
|
||||
def write_cmds(self, cmds):
|
||||
for c in cmds:
|
||||
self.write_cmd(c)
|
||||
|
||||
def poweroff(self):
|
||||
self.write_cmd(SET_DISP | 0x00)
|
||||
|
||||
@ -78,6 +110,10 @@ class SSD1306(framebuf.FrameBuffer):
|
||||
self.write_cmd(SET_DISP | 0x01)
|
||||
|
||||
def contrast(self, contrast):
|
||||
# brightness: normal = 0x7f, brightness=0xff, dim=0x00 (but they are all very similar)
|
||||
if self.is_mk5:
|
||||
# - limit to a specific max value from OLED specs used on Mk5
|
||||
contrast = max(contrast, 0x85)
|
||||
self.write_cmd(SET_CONTRAST)
|
||||
self.write_cmd(contrast)
|
||||
|
||||
@ -85,56 +121,113 @@ class SSD1306(framebuf.FrameBuffer):
|
||||
self.write_cmd(SET_NORM_INV | (invert & 1))
|
||||
|
||||
def show(self):
|
||||
x0 = 0
|
||||
x1 = self.width - 1
|
||||
if self.width == 64:
|
||||
# displays with width of 64 pixels are shifted by 32
|
||||
x0 += 32
|
||||
x1 += 32
|
||||
self.write_cmd(SET_COL_ADDR)
|
||||
self.write_cmd(x0)
|
||||
self.write_cmd(x1)
|
||||
self.write_cmd(0)
|
||||
self.write_cmd(self.width - 1)
|
||||
|
||||
self.write_cmd(SET_PAGE_ADDR)
|
||||
self.write_cmd(0)
|
||||
self.write_cmd(self.pages - 1)
|
||||
|
||||
self.write_data(self.buffer)
|
||||
|
||||
SPI_RATE = const(40000000) # max chip can do, still slower than display limit tho
|
||||
def busy_bar(self, enable, pattern):
|
||||
# Render a continuous activity (not progress) bar in lower 8 lines of display
|
||||
# - using OLED itself to do the animation, so smooth and CPU free
|
||||
# - cannot preserve bottom 8 lines, since we have to destructively write there
|
||||
# - assumes normal horz addr mode: 0x20, 0x00
|
||||
# - speed_code=>framedelay: 0=5fr, 1=64fr, 2=128, 3=256, 4=3, 5=4, 6=25, 7=2frames
|
||||
# unused: assert 0 <= speed_code <= 7
|
||||
|
||||
setup = bytes([
|
||||
0x21, 0x00, 0x7f, # setup column address range (start, end): 0-127
|
||||
0x22, 7, 7, # setup page start/end address: page 7=last 8 lines
|
||||
])
|
||||
if not self.is_mk5:
|
||||
animate = bytes([
|
||||
0x2e, # stop animations in progress
|
||||
0x26, # scroll leftwards (stock ticker mode)
|
||||
0, # placeholder
|
||||
7, # start 'page' (vertical)
|
||||
5, # "speed_code" # scroll speed: 7=fastest, but no order to it
|
||||
7, # end 'page'
|
||||
0, 0x7f, # start/end columns
|
||||
0x2f # start
|
||||
])
|
||||
else:
|
||||
# SSD1309? doesn't implement 0x26 but has other commands
|
||||
animate = bytes([
|
||||
0x2e, # stop animations in progress
|
||||
0x29, # Vert+Right horz animation setup
|
||||
1, # A: enable horz scroll
|
||||
7, # B: start 'page' (vertical)
|
||||
5, # C: "speed_code" # scroll speed: 7=fastest, but no order to it
|
||||
7, # D: end 'page'
|
||||
1, # E: vert scrolling offset (unused)
|
||||
0, 0x7f, # F,G: start/end columns
|
||||
0xa3, # Set Vertical scroll Area
|
||||
0, 0, # A, B: # of rows in fixed vs. scroll area
|
||||
0x2f # start animating
|
||||
])
|
||||
|
||||
cleanup = bytes([
|
||||
0x2e, # stop animation
|
||||
0x20, 0x00, # horz addr-ing mode
|
||||
0x21, 0x00, 0x7f, # setup column address range (start, end): 0-127
|
||||
0x22, 7, 7, # setup page start/end address: page 7=last 8 lines
|
||||
])
|
||||
|
||||
if not enable:
|
||||
# stop animation, and redraw old (new) screen
|
||||
self.write_cmds(cleanup)
|
||||
else:
|
||||
# needs a pattern that repeats nicely mod 128
|
||||
self.write_cmds(setup)
|
||||
self.write_data(pattern)
|
||||
self.write_cmds(animate)
|
||||
|
||||
class SSD1306_SPI(SSD1306):
|
||||
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
|
||||
dc.init(dc.OUT, value=0)
|
||||
res.init(res.OUT, value=0)
|
||||
cs.init(cs.OUT, value=1)
|
||||
def __init__(self, width, height, spi, dc, res, cs, is_mk5=False):
|
||||
self.spi = spi
|
||||
self.dc = dc
|
||||
self.res = res
|
||||
self.cs = cs
|
||||
self.res(1)
|
||||
self.res = res
|
||||
|
||||
# initial states
|
||||
dc(0)
|
||||
cs(1)
|
||||
|
||||
# reset sequence
|
||||
res(1)
|
||||
time.sleep_ms(1)
|
||||
self.res(0)
|
||||
res(0)
|
||||
time.sleep_ms(10)
|
||||
self.res(1)
|
||||
super().__init__(width, height, external_vcc)
|
||||
res(1)
|
||||
|
||||
super().__init__(width, height, is_mk5)
|
||||
|
||||
def _setup_spi(self):
|
||||
# need to re-do this constantly
|
||||
# max chip can do, still slower than display limit tho
|
||||
# - 40Mhz (target) is fine for short-cabled Mk4 (actual is lower?)
|
||||
# - max spec is 10Mhz on Mk5
|
||||
rate = 40_000_000 if not self.is_mk5 else 10_000_000
|
||||
self.spi.init(baudrate=rate, polarity=0, phase=0)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
self.spi.init(baudrate=SPI_RATE, polarity=0, phase=0)
|
||||
self._setup_spi()
|
||||
self.cs(1)
|
||||
self.dc(0)
|
||||
self.cs(0)
|
||||
try:
|
||||
self.spi.write(bytearray([cmd]))
|
||||
except:
|
||||
print("SPI[cmd]: %r" % self.spi)
|
||||
self.spi.write(bytearray([cmd]))
|
||||
self.cs(1)
|
||||
|
||||
def write_data(self, buf):
|
||||
self.spi.init(baudrate=SPI_RATE, polarity=0, phase=0)
|
||||
self._setup_spi()
|
||||
self.cs(1)
|
||||
self.dc(1)
|
||||
self.cs(0)
|
||||
try:
|
||||
self.spi.write(buf)
|
||||
except:
|
||||
print("SPI[data]: %r" % self.spi)
|
||||
self.spi.write(buf)
|
||||
self.cs(1)
|
||||
|
||||
# EOF
|
||||
|
||||
@ -383,7 +383,7 @@ def check_firmware_hdr(hdr, binary_size):
|
||||
# - hdr must be a bytearray(FW_HEADER_SIZE+more)
|
||||
|
||||
from sigheader import FW_HEADER_SIZE, FW_HEADER_MAGIC, FWH_PY_FORMAT
|
||||
from sigheader import MK_1_OK, MK_2_OK, MK_3_OK, MK_4_OK, MK_Q1_OK
|
||||
from sigheader import MK_1_OK, MK_2_OK, MK_3_OK, MK_4_OK, MK_5_OK, MK_Q1_OK
|
||||
from ustruct import unpack_from
|
||||
from version import hw_label
|
||||
import callgate
|
||||
@ -412,6 +412,8 @@ def check_firmware_hdr(hdr, binary_size):
|
||||
ok = (hw_compat & MK_3_OK)
|
||||
elif hw_label == 'mk4':
|
||||
ok = (hw_compat & MK_4_OK)
|
||||
elif hw_label == 'mk5':
|
||||
ok = (hw_compat & MK_5_OK)
|
||||
elif hw_label == 'q1':
|
||||
ok = (hw_compat & MK_Q1_OK)
|
||||
|
||||
|
||||
@ -80,6 +80,7 @@ def probe_system():
|
||||
|
||||
from sigheader import RAM_BOOT_FLAGS, RBF_FACTORY_MODE
|
||||
import ckcc, callgate, machine
|
||||
from machine import Pin
|
||||
|
||||
hw_label = 'mk4'
|
||||
has_608 = True
|
||||
@ -97,7 +98,7 @@ def probe_system():
|
||||
|
||||
# detect Q1 based on pins.csv
|
||||
try:
|
||||
machine.Pin('LCD_TEAR') # only defined on Q1 build, will error otherwise
|
||||
Pin('LCD_TEAR') # only defined on Q1 build, will error otherwise
|
||||
has_qr = True
|
||||
num_sd_slots = 2
|
||||
hw_label = 'q1'
|
||||
@ -108,6 +109,15 @@ def probe_system():
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
# only defined on Mk4/5 build, will error otherwise; was open on Mk1-4, low on Mk5
|
||||
s0 = Pin('STRAP_MK5', mode=Pin.IN, pull=Pin.PULL_UP)
|
||||
if s0() == 0:
|
||||
hw_label = 'mk5'
|
||||
mk_num = 5
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Boot loader needs to tell us stuff about how we were booted, sometimes:
|
||||
# - did we just install a new version, for example (obsolete in mk4)
|
||||
# - are we running in "factory mode" with flash un-secured?
|
||||
|
||||
@ -89,3 +89,8 @@ SE2_SDA,PB14
|
||||
NFC_SCL,PB6
|
||||
NFC_SDA,PB7
|
||||
NFC_ED,PC4
|
||||
STRAP_MK5,PE0
|
||||
STRAP_S1,PE1
|
||||
STRAP_S2,PE2
|
||||
STRAP_S3,PE3
|
||||
V12EN,PC1
|
||||
|
||||
|
@ -2,20 +2,20 @@
|
||||
#
|
||||
# Build micropython for stm32 (an ARM processor). Also handles signing of resulting firmware images.
|
||||
#
|
||||
# MARK 4 with different chip and layout
|
||||
# COLDCARD Mk4 and Mk5 -- OLED display, calculator style.
|
||||
#
|
||||
|
||||
BOARD = COLDCARD_MK4
|
||||
FIRMWARE_BASE = 0x08020000
|
||||
BOOTLOADER_BASE = 0x08000000
|
||||
HW_MODEL = mk4
|
||||
PARENT_MKFILE = MK4-Makefile
|
||||
HW_MODEL = mk
|
||||
PARENT_MKFILE = MK-Makefile
|
||||
|
||||
# This is release of the bootloader that will be built into the factory.dfu
|
||||
BOOTLOADER_VERSION = 3.2.1
|
||||
BOOTLOADER_DIR = mk4-bootloader
|
||||
|
||||
LATEST_RELEASE = $(shell ls -t1 ../releases/*-mk4-*.dfu | head -1)
|
||||
LATEST_RELEASE = $(shell ls -t1 ../releases/*-mk-*.dfu ../releases/*-mk4-*.dfu | head -1)
|
||||
|
||||
# Our version for this release.
|
||||
# - caution, the bootrom will not accept version < 3.0.0
|
||||
@ -5,23 +5,23 @@
|
||||
#
|
||||
# Normally you must use:
|
||||
#
|
||||
# make -f MK4-Makefile
|
||||
# make -f MK-Makefile
|
||||
# or
|
||||
# make -f Q1-Makefile
|
||||
#
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
.DEFAULT all:
|
||||
$(MAKE) DEBUG_BUILD=1 -f Q1-Makefile $(MAKECMDGOALS)
|
||||
$(MAKE) DEBUG_BUILD=1 -f MK-Makefile $(MAKECMDGOALS)
|
||||
|
||||
clean clobber repro:
|
||||
@echo You should do either:
|
||||
@echo
|
||||
@echo " make" -f Q1-Makefile $(MAKECMDGOALS)
|
||||
@echo "-OR-"
|
||||
@echo " make" -f MK4-Makefile $(MAKECMDGOALS)
|
||||
@echo " make" -f MK-Makefile $(MAKECMDGOALS)
|
||||
|
||||
rc1 rc2 release:
|
||||
make -f Q1-Makefile $(MAKECMDGOALS) && make -f MK4-Makefile $(MAKECMDGOALS)
|
||||
make -f Q1-Makefile $(MAKECMDGOALS) && make -f MK-Makefile $(MAKECMDGOALS)
|
||||
|
||||
# EOF
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#include "gpio.h"
|
||||
#include "stm32l4xx_hal.h"
|
||||
|
||||
// PA0 - onewire bus for 608a
|
||||
// PA0 - onewire bus for 608
|
||||
#define ONEWIRE_PIN GPIO_PIN_0
|
||||
#define ONEWIRE_PORT GPIOA
|
||||
|
||||
@ -62,15 +62,20 @@ gpio_setup(void)
|
||||
|
||||
// SD active LED: PC7
|
||||
// USB active LED: PC6
|
||||
// Mk5 (disconnected & unused on Mk4):
|
||||
// PC0: early experiments, unused
|
||||
// PC1: +12v en for OLED
|
||||
// - but by rev E, neither being used, but keep support for older revs
|
||||
{ GPIO_InitTypeDef setup = {
|
||||
.Pin = GPIO_PIN_7 | GPIO_PIN_6,
|
||||
.Pin = GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_0 | GPIO_PIN_1,
|
||||
.Mode = GPIO_MODE_OUTPUT_PP,
|
||||
.Pull = GPIO_NOPULL,
|
||||
.Speed = GPIO_SPEED_FREQ_LOW,
|
||||
};
|
||||
|
||||
HAL_GPIO_Init(GPIOC, &setup);
|
||||
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7|GPIO_PIN_6, 0); // turn LEDs off
|
||||
HAL_GPIO_WritePin(GPIOC, setup.Pin, 0); // turn all off
|
||||
}
|
||||
|
||||
// SD card detect switch: PC13
|
||||
@ -83,6 +88,18 @@ gpio_setup(void)
|
||||
HAL_GPIO_Init(GPIOC, &setup);
|
||||
}
|
||||
|
||||
// Strapping pins (Mk5, but all disconnected on Mk4): PE0-3
|
||||
// - important to have the internal pull-ups enabled on these
|
||||
// - PE0: low if Mk5
|
||||
{ GPIO_InitTypeDef setup = {
|
||||
.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
|
||||
.Mode = GPIO_MODE_INPUT,
|
||||
.Pull = GPIO_PULLUP,
|
||||
.Speed = GPIO_SPEED_FREQ_LOW,
|
||||
};
|
||||
HAL_GPIO_Init(GPIOE, &setup);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// TEST CODE -- keep
|
||||
@ -125,5 +142,14 @@ gpio_setup(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
// is_mk5()
|
||||
//
|
||||
bool
|
||||
is_mk5(void)
|
||||
{
|
||||
// sample the PE0 strapping pin to know if mk4 or 5
|
||||
return !HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_0);
|
||||
}
|
||||
|
||||
|
||||
// EOF
|
||||
|
||||
@ -6,10 +6,12 @@
|
||||
// set directions, lock critical ones, etc.
|
||||
void gpio_setup(void);
|
||||
|
||||
// sample the DFU button
|
||||
inline bool dfu_button_pressed(void) { return false; }
|
||||
|
||||
#ifdef FOR_Q1_ONLY
|
||||
// kill system power; instant
|
||||
extern void turn_power_off(void);
|
||||
#endif
|
||||
|
||||
// sample the strapping pin to know if mk4 or 5
|
||||
extern bool is_mk5(void);
|
||||
|
||||
// EOF
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "delay.h"
|
||||
#include "rng.h"
|
||||
#include "console.h"
|
||||
#include "gpio.h" // for is_mk5()
|
||||
#include "stm32l4xx_hal.h"
|
||||
#include <string.h>
|
||||
|
||||
@ -14,7 +15,7 @@
|
||||
// Reset and config sequence.
|
||||
//
|
||||
// As measured! No attempt to understand them here.
|
||||
static const uint8_t reset_commands[] = {
|
||||
static const uint8_t reset_commands_mk4[] = {
|
||||
0xae, // display off
|
||||
0x20, 0x00, // horz addr-ing mode
|
||||
0x40, // ram display start line: 0
|
||||
@ -33,6 +34,28 @@ static const uint8_t reset_commands[] = {
|
||||
0xaf // display on
|
||||
};
|
||||
|
||||
// .. similar but a little different on Mk5
|
||||
static const uint8_t reset_commands_mk5[] = {
|
||||
0xae, // display off
|
||||
0xd5, 0x80, // set display clock divide ratio
|
||||
0xa8, 0x3f, // set multiplex ratio: 64
|
||||
0xd3, 0x00, // display offset (vertical shift): 0
|
||||
0x40, // ram display start line: 0
|
||||
0xad, 0x8a, // set charge pump (NEW)
|
||||
0xa0, // column addr 127 mapped to seg0 (NEW was 0xa1)
|
||||
0xc0, // remapped mode: scan from COMn to COM0 (NEW was 0xc8)
|
||||
0xda, 0x12, // seq com pin conf: alt com pin
|
||||
0x81, 0x65, // Contrast: was max, now 0x65 (NEW)
|
||||
0xd9, 0x22, // set pre-change period (NEW, was 0xf1)
|
||||
0xdb, 0x40, // Cvomh deselect level (NEW, was 0x30)
|
||||
0xa6, // normal not inverted
|
||||
|
||||
0x20, 0x00, // horz addr-ing mode
|
||||
0xa4, // display ram contents (not all on)
|
||||
//0x8d, 0x14, // enable charge pump (not in use, omitted from their sequence)
|
||||
0xaf // display on (done after VCC enabled)
|
||||
};
|
||||
|
||||
// Bytes to send before sending the 1024 bytes of pixel data.
|
||||
//
|
||||
static const uint8_t before_show[] = {
|
||||
@ -50,6 +73,9 @@ static const uint8_t before_show[] = {
|
||||
#define SPI_SCK GPIO_PIN_5
|
||||
#define SPI_MOSI GPIO_PIN_7
|
||||
|
||||
// port C, Mk5 only
|
||||
#define VCC_EN_PIN GPIO_PIN_1
|
||||
|
||||
|
||||
#ifndef DISABLE_OLED
|
||||
static SPI_HandleTypeDef spi_port;
|
||||
@ -177,7 +203,7 @@ oled_setup(void)
|
||||
HAL_GPIO_Init(GPIOA, &setup);
|
||||
|
||||
// lock the RESET pin so that St's DFU code doesn't clear screen
|
||||
// it might be trying to use it a MISO signal for SPI loading
|
||||
// it might be trying to use it as a MISO signal for SPI loading
|
||||
HAL_GPIO_LockPin(GPIOA, RESET_PIN | CS_PIN | DC_PIN);
|
||||
|
||||
// 10ms low-going pulse on reset pin
|
||||
@ -196,7 +222,14 @@ oled_setup(void)
|
||||
//SPI1->CR1 = 0x354;
|
||||
|
||||
// write a sequence to reset things
|
||||
oled_write_cmd_sequence(sizeof(reset_commands), reset_commands);
|
||||
if(is_mk5()) {
|
||||
// note: +12v is always on now, this line supports older revs
|
||||
HAL_GPIO_WritePin(GPIOC, VCC_EN_PIN, 1);
|
||||
|
||||
oled_write_cmd_sequence(sizeof(reset_commands_mk5), reset_commands_mk5);
|
||||
} else {
|
||||
oled_write_cmd_sequence(sizeof(reset_commands_mk4), reset_commands_mk4);
|
||||
}
|
||||
|
||||
rng_delay();
|
||||
}
|
||||
@ -429,13 +462,12 @@ oled_factory_busy(void)
|
||||
// Render a continuous activity (not progress) bar in lower 8 lines of display
|
||||
// - using OLED itself to do the animation, so smooth and CPU free
|
||||
// - cannot preserve bottom 8 lines, since we have to destructively write there
|
||||
//oled_spi_setup();
|
||||
|
||||
static const uint8_t setup[] = {
|
||||
0x21, 0x00, 0x7f, // setup column address range (start, end): 0-127
|
||||
0x22, 7, 7, // setup page start/end address: page 7=last 8 lines
|
||||
};
|
||||
static const uint8_t animate[] = {
|
||||
static const uint8_t animate_mk4[] = {
|
||||
0x2e, // stop animations in progress
|
||||
0x26, // scroll leftwards (stock ticker mode)
|
||||
0, // placeholder
|
||||
@ -445,6 +477,21 @@ oled_factory_busy(void)
|
||||
0, 0xff, // placeholders
|
||||
0x2f // start
|
||||
};
|
||||
// slightly different on Mk5 display
|
||||
static const uint8_t animate_mk5[] = {
|
||||
0x2e, // stop animations in progress
|
||||
0x29, // Vert+Right horz animation setup
|
||||
1, // A: enable horz scroll
|
||||
7, // B: start 'page' (vertical)
|
||||
5, // C: "speed_code" # scroll speed: 7=fastest, but no order to it
|
||||
7, // D: end 'page'
|
||||
1, // E: vert scrolling offset (unused)
|
||||
0, 0x7f, // F,G: start/end columns
|
||||
0xa3, // Set Vertical scroll Area
|
||||
0, 0, // A, B: # of rows in fixed vs. scroll area
|
||||
0x2f // start animating
|
||||
};
|
||||
|
||||
uint8_t data[128];
|
||||
|
||||
for(int x=0; x<128; x++) {
|
||||
@ -454,7 +501,11 @@ oled_factory_busy(void)
|
||||
|
||||
oled_write_cmd_sequence(sizeof(setup), setup);
|
||||
oled_write_data(sizeof(data), data);
|
||||
oled_write_cmd_sequence(sizeof(animate), animate);
|
||||
if(is_mk5()) {
|
||||
oled_write_cmd_sequence(sizeof(animate_mk5), animate_mk5);
|
||||
} else {
|
||||
oled_write_cmd_sequence(sizeof(animate_mk4), animate_mk4);
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# (c) Copyright 2021 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
#
|
||||
# Shared values and target rules for Mk4 and Q.
|
||||
# Shared values and target rules for Mk and Q platforms.
|
||||
#
|
||||
|
||||
# Define these vars to suit board
|
||||
|
||||
@ -70,8 +70,7 @@ typedef struct {
|
||||
#define MK_3_OK 0x04
|
||||
#define MK_4_OK 0x08
|
||||
#define MK_Q1_OK 0x10
|
||||
// RFU:
|
||||
#define MK_6_OK 0x20
|
||||
#define MK_5_OK 0x20
|
||||
|
||||
// (Mk1-3) There is a copy of the header at this location in RAM, copied by bootloader
|
||||
// **after** it has been verified. If you write to this memory area, you will be reset!
|
||||
|
||||
@ -54,8 +54,7 @@ MK_2_OK = 0x02
|
||||
MK_3_OK = 0x04
|
||||
MK_4_OK = 0x08
|
||||
MK_Q1_OK = 0x10
|
||||
# RFU:
|
||||
MK_6_OK = 0x20
|
||||
MK_5_OK = 0x20
|
||||
|
||||
# (Mk1-3) There is a copy of the header at this location in RAM, copied by bootloader
|
||||
# **after** it has been verified. If you write to this memory area, you will be reset!
|
||||
|
||||
@ -9,10 +9,23 @@ from ckcc_protocol.client import ColdcardDevice
|
||||
|
||||
|
||||
def _clone(source, target):
|
||||
assert source in ["Q", "Mk4"]
|
||||
assert target in ["Q", "Mk4"]
|
||||
source_sim_arg, source_is_Q = ("--q1", True) if source == "Q" else ("", False)
|
||||
target_sim_arg, target_is_Q = ("--q1", True) if target == "Q" else ("", False)
|
||||
allowed_devices = ["Q", "Mk4", "Mk5"]
|
||||
assert source in allowed_devices
|
||||
assert target in allowed_devices
|
||||
|
||||
source_is_Q = False
|
||||
source_sim_arg = ""
|
||||
if source == "Q":
|
||||
source_sim_arg, source_is_Q = "--q1", True
|
||||
elif source == "Mk4":
|
||||
source_sim_arg, source_is_Q = "--mk4", False
|
||||
|
||||
target_is_Q = False
|
||||
target_sim_arg = ""
|
||||
if target == "Q":
|
||||
target_sim_arg, target_is_Q = "--q1", True
|
||||
elif target == "Mk4":
|
||||
target_sim_arg, target_is_Q = "--mk4", False
|
||||
|
||||
# first the TARGET
|
||||
clean_sim_data() # remove all from previous
|
||||
@ -105,7 +118,7 @@ def _clone(source, target):
|
||||
sim_target.stop()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("source,target", list(itertools.product(["Q", "Mk4"], repeat=2)))
|
||||
@pytest.mark.parametrize("source,target", list(itertools.product(["Q", "Mk4", "Mk5"], repeat=2)))
|
||||
def test_clone(source, target):
|
||||
_clone(source, target)
|
||||
time.sleep(1)
|
||||
|
||||
@ -1518,19 +1518,22 @@ def is_mark3(dev_hw_label):
|
||||
def is_mark4(dev_hw_label):
|
||||
return (dev_hw_label == 'mk4')
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def is_mark5(dev_hw_label):
|
||||
return (dev_hw_label == 'mk5')
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def is_q1(dev_hw_label):
|
||||
return (dev_hw_label == 'q1')
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def is_headless(request):
|
||||
return request.config.getoption('--headless')
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def is_mark4plus(is_mark4, is_q1):
|
||||
# mark4 PLUS ... so Q1 and Mk4
|
||||
return is_mark4 or is_q1
|
||||
def is_mark4plus(is_mark4, is_q1, is_mark5):
|
||||
# mark4 PLUS ... so Q1, Mk4 and Mk5
|
||||
return is_mark4 or is_q1 or is_mark5
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def mk_num(dev_hw_label):
|
||||
@ -1544,35 +1547,29 @@ def mk_num(dev_hw_label):
|
||||
else:
|
||||
raise ValueError(v)
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def only_mk4(is_mark4):
|
||||
# NOTE: avoid this, and try to be more specific! ie. NFC vs. QR etc
|
||||
if not is_mark4:
|
||||
raise pytest.skip("Mk4 only")
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def only_q1(is_q1):
|
||||
if not is_q1:
|
||||
raise pytest.skip("Q only")
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def needs_nfc(is_mark4, is_q1):
|
||||
if is_mark4 or is_q1:
|
||||
def needs_nfc(is_mark4plus):
|
||||
if is_mark4plus:
|
||||
return
|
||||
raise pytest.skip("Needs NFC support")
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def needs_virtdisk(is_mark4, is_q1):
|
||||
def needs_virtdisk(is_mark4plus):
|
||||
# TODO/MAYBE: test if feature enabled in settings?
|
||||
if is_mark4 or is_q1:
|
||||
if is_mark4plus:
|
||||
return
|
||||
raise pytest.skip("Needs VirtDisk support")
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def only_mk4plus(mk_num):
|
||||
# Mk4 and Q1
|
||||
# Mk4, Q1 and Mk5
|
||||
if mk_num < 4:
|
||||
raise pytest.skip("Mk4/Q1 only")
|
||||
raise pytest.skip("Mk4/Mk5/Q1 only")
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def only_mk3(mk_num):
|
||||
|
||||
@ -298,7 +298,8 @@ def main():
|
||||
help="Choose how much to sleep after simulator is started")
|
||||
parser.add_argument("-m", "--module", action="append", help="Choose only n modules to run")
|
||||
parser.add_argument("--pdb", action="store_true", help="Go to debugger on failure")
|
||||
parser.add_argument("--q1", action="store_true", help="Simulate a Q instead of Mk COLDCARD")
|
||||
parser.add_argument("--q1", action="store_true", help="Simulate a Q instead of Mk5 COLDCARD")
|
||||
parser.add_argument("--mk4", action="store_true", help="Simulate a Mk4 instead of Mk5 COLDCARD")
|
||||
parser.add_argument("--psbt2", action="store_true", help="`fake_txn` produces PSBTv2")
|
||||
parser.add_argument("--ff", action="store_true", help="Run the last failures first")
|
||||
parser.add_argument("--onetime", action="store_true", default=False,
|
||||
@ -381,8 +382,11 @@ def main():
|
||||
# proper `settings.load` _ virtual disk
|
||||
sim_args = ["--set", "nfc=1", "--set", "vidsk=1"]
|
||||
|
||||
# by default Mk5 is run
|
||||
if args.q1 and '--q1' not in sim_args:
|
||||
sim_args.append('--q1')
|
||||
elif args.mk4 and '--mk4' not in sim_args:
|
||||
sim_args.append("--mk4")
|
||||
|
||||
module_args.append((test_module, sim_args, args.pytest_k, args.pdb,
|
||||
args.ff, args.psbt2, args.q1, args.headless))
|
||||
@ -416,8 +420,10 @@ def main():
|
||||
tmp_dir = "/tmp/cc-simulators"
|
||||
clean_directory(tmp_dir) # clean it
|
||||
mk4_log_dir = f"{tmp_dir}/mk4_logs"
|
||||
mk5_log_dir = f"{tmp_dir}/mk5_logs"
|
||||
q1_log_dir = f"{tmp_dir}/q1_logs"
|
||||
os.makedirs(mk4_log_dir, exist_ok=True)
|
||||
os.makedirs(mk5_log_dir, exist_ok=True)
|
||||
os.makedirs(q1_log_dir, exist_ok=True)
|
||||
|
||||
q = [] # build priority queue
|
||||
@ -455,7 +461,14 @@ def main():
|
||||
break
|
||||
sim = ColdcardSimulator(sim_args, segregate=True)
|
||||
sim.start(start_wait=0)
|
||||
ld = q1_log_dir if "--q1" in sim_args else mk4_log_dir
|
||||
|
||||
if "--q1" in sim_args:
|
||||
ld = q1_log_dir
|
||||
elif "--mk4" in sim_args:
|
||||
ld = mk4_log_dir
|
||||
else:
|
||||
ld = mk5_log_dir
|
||||
|
||||
q_chunks.append((sim, mn, mod_add, k, ld))
|
||||
|
||||
time.sleep(5)
|
||||
@ -468,7 +481,12 @@ def main():
|
||||
if k:
|
||||
cmd_list.extend(["-k", k])
|
||||
p = subprocess.Popen(cmd_list, preexec_fn=os.setsid, stdout=out_fd, stderr=out_fd)
|
||||
mark = "Q" if "q1" in log_dir else "Mk4"
|
||||
if "q1" in log_dir:
|
||||
mark = "Q"
|
||||
elif "mk5" in log_dir:
|
||||
mark = "Mk5"
|
||||
else:
|
||||
mark = "Mk4"
|
||||
procs.append((mn+mod_add, p, out_fd, sim, mark, time.time()))
|
||||
print(f'started: {mark:<6}{mn+mod_add:<30}{sim.socket.split("-")[-1].split(".")[0]:<10}')
|
||||
|
||||
|
||||
@ -91,10 +91,13 @@ def verify_msg_bip322_por(cap_story, need_keypress, press_select, press_cancel,
|
||||
[["p2pkh", None, None]] + ([["p2wpkh", None, 1000000]] * 5) + ([["p2sh-p2wpkh", None, 10000000]] * 5),
|
||||
])
|
||||
def test_bip322_por(msg, ins, bip322_txn, start_sign, end_sign, cap_story, need_keypress,
|
||||
press_select, verify_msg_bip322_por):
|
||||
press_select, verify_msg_bip322_por, sim_root_dir):
|
||||
num_ins = len(ins)
|
||||
amt = sum([i[2] or 0 for i in ins])
|
||||
psbt, msg_challenge = bip322_txn(ins, msg=msg)
|
||||
with open(f'{sim_root_dir}/debug/last-b322-por.psbt', 'wb') as f:
|
||||
f.write(psbt)
|
||||
|
||||
start_sign(psbt, finalize=True)
|
||||
|
||||
verify_msg_bip322_por(msg.decode(), way="sd")
|
||||
|
||||
@ -165,7 +165,10 @@ def test_b39p_refused(dev, press_cancel, pw='testing 123'):
|
||||
@pytest.mark.parametrize('version', range(8))
|
||||
def test_bip39_pick_words(target, version, cap_menu, pick_menu_item, cap_story,
|
||||
word_menu_entry, get_pp_sofar, reset_seed_words,
|
||||
press_select, only_mk4, go_to_passphrase):
|
||||
press_select, is_q1, go_to_passphrase):
|
||||
if is_q1:
|
||||
raise pytest.skip("not on Q")
|
||||
|
||||
# Check we can pick words
|
||||
reset_seed_words()
|
||||
|
||||
@ -192,13 +195,16 @@ def test_bip39_pick_words(target, version, cap_menu, pick_menu_item, cap_story,
|
||||
|
||||
@pytest.mark.parametrize('target', ['123', '1', '4'*32, '12'*8])
|
||||
@pytest.mark.parametrize('backspaces', [1, 0, 12])
|
||||
def test_bip39_add_nums(target, backspaces, pick_menu_item, cap_story, only_mk4,
|
||||
def test_bip39_add_nums(target, backspaces, pick_menu_item, cap_story, is_q1,
|
||||
cap_menu, word_menu_entry, get_pp_sofar, need_keypress,
|
||||
press_select, press_cancel, go_to_passphrase):
|
||||
|
||||
# Check we can pick numbers (appended)
|
||||
# - also the "clear all" menu item
|
||||
|
||||
if is_q1:
|
||||
raise pytest.skip("not on Q")
|
||||
|
||||
go_to_passphrase()
|
||||
pick_menu_item('Add Numbers')
|
||||
|
||||
|
||||
@ -22,12 +22,12 @@ from psbt import BasicPSBT
|
||||
SERVER_PUBKEY = '0231301ec4acec08c1c7d0181f4ffb8be70d693acccc86cccb8f00bf2e00fcabfd'
|
||||
|
||||
@pytest.fixture
|
||||
def goto_ccc_menu(goto_home, pick_menu_item, is_mark4):
|
||||
def goto_ccc_menu(goto_home, pick_menu_item, is_q1):
|
||||
def doit():
|
||||
goto_home()
|
||||
pick_menu_item("Advanced/Tools")
|
||||
pick_menu_item("Spending Policy")
|
||||
pick_menu_item("Co-Sign Multi." if is_mark4 else "Co-Sign Multisig (CCC)")
|
||||
pick_menu_item("Co-Sign Multisig (CCC)" if is_q1 else "Co-Sign Multi.")
|
||||
|
||||
return doit
|
||||
|
||||
|
||||
@ -55,8 +55,7 @@ goto_top_menu()
|
||||
@pytest.mark.parametrize('en_nfc', [ True, False] )
|
||||
@pytest.mark.parametrize('en_multisig', [ True, False] )
|
||||
def test_menu_contents(set_hobble, pick_menu_item, cap_menu, en_okeys, en_notes, settings_set,
|
||||
need_some_notes, is_q1, is_mark4, en_nfc, sim_exec, en_multisig,
|
||||
vdisk_disabled):
|
||||
need_some_notes, is_q1, en_nfc, sim_exec, en_multisig, vdisk_disabled):
|
||||
|
||||
# just enough to pass/fail the menu predicates!
|
||||
settings_set('seedvault', True)
|
||||
|
||||
@ -114,7 +114,10 @@ def compute_policy_hash(policy):
|
||||
return b2a_hex(sha256(json_.encode()).digest()).decode()
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def enable_hsm_commands(dev, sim_exec, only_mk4):
|
||||
def enable_hsm_commands(dev, sim_exec, is_q1):
|
||||
if is_q1:
|
||||
raise pytest.skip("Q does not have HSM support")
|
||||
|
||||
cmd = 'from glob import settings; settings.set("hsmcmd", 1)'
|
||||
sim_exec(cmd)
|
||||
yield
|
||||
|
||||
@ -134,21 +134,13 @@ def test_psbt_proxy_parsing(fn, sim_execfile, sim_exec, src_root_dir, sim_root_d
|
||||
assert oo == rb
|
||||
|
||||
@pytest.mark.unfinalized
|
||||
def test_speed_test(dev, fake_txn, is_mark3, is_mark4, start_sign, end_sign,
|
||||
press_select, press_cancel, sim_root_dir, is_q1):
|
||||
def test_speed_test(dev, fake_txn, start_sign, end_sign, press_select, press_cancel, sim_root_dir):
|
||||
# measure time to sign a larger txn
|
||||
if is_mark4 or is_q1:
|
||||
# Mk4: expect
|
||||
# 20/250 => 15.5s (or 10.0 if seed is cached)
|
||||
# 200/500 => 96.3s
|
||||
num_in = 20
|
||||
num_out = 250
|
||||
elif is_mark3:
|
||||
num_in = 20
|
||||
num_out = 250
|
||||
else:
|
||||
num_in = 9
|
||||
num_out = 100
|
||||
# Mk4: expect
|
||||
# 20/250 => 15.5s (or 10.0 if seed is cached)
|
||||
# 200/500 => 96.3s
|
||||
num_in = 20
|
||||
num_out = 250
|
||||
|
||||
psbt = fake_txn(num_in, num_out, dev.master_xpub, segwit_in=True)
|
||||
|
||||
@ -179,9 +171,7 @@ if 0:
|
||||
# see <https://bitcoin.stackexchange.com/questions/11542>
|
||||
# - how big woudl PSBT be?
|
||||
# - not a great test case because so slow.
|
||||
def test_mega_txn(fake_txn, is_mark4, start_sign, end_sign, dev):
|
||||
if not is_mark4:
|
||||
raise pytest.xfail('no way')
|
||||
def test_mega_txn(fake_txn, start_sign, end_sign, dev):
|
||||
|
||||
psbt = fake_txn(5569, 1, dev.master_xpub)
|
||||
|
||||
@ -3634,10 +3624,13 @@ def test_txn_nVersion_zero(segwit, fake_txn, start_sign, cap_story, goto_home):
|
||||
goto_home()
|
||||
|
||||
def hack(psbt):
|
||||
t = CTransaction()
|
||||
t.deserialize(BytesIO(psbt.txn))
|
||||
t.nVersion = 0
|
||||
psbt.txn = t.serialize()
|
||||
if psbt.is_v2():
|
||||
psbt.txn_version = 0
|
||||
else:
|
||||
t = CTransaction()
|
||||
t.deserialize(BytesIO(psbt.txn))
|
||||
t.nVersion = 0
|
||||
psbt.txn = t.serialize()
|
||||
|
||||
psbt = fake_txn(1, 2, segwit_in=segwit, change_outputs=[0], psbt_hacker=hack)
|
||||
start_sign(psbt)
|
||||
|
||||
@ -11,7 +11,7 @@ from ckcc.protocol import CCProtocolPacker
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def goto_sssp_menu(goto_home, pick_menu_item, is_mark4):
|
||||
def goto_sssp_menu(goto_home, pick_menu_item):
|
||||
def doit():
|
||||
goto_home()
|
||||
pick_menu_item("Advanced/Tools")
|
||||
|
||||
@ -92,18 +92,12 @@ def upgrade_by_sd(open_microsd, cap_story, pick_menu_item, goto_home, press_sele
|
||||
@pytest.mark.parametrize('mode', ['compat', 'incompat'])
|
||||
@pytest.mark.parametrize('transport', ['sd', 'usb'])
|
||||
def test_hacky_upgrade(mode, cap_story, transport, dev, sim_exec, make_firmware, upload_file,
|
||||
upgrade_by_sd, press_cancel, is_q1):
|
||||
upgrade_by_sd, press_cancel, is_q1, is_mark5):
|
||||
|
||||
if mode == 'compat':
|
||||
data = make_firmware("q1" if is_q1 else 4)
|
||||
data = make_firmware("q1" if is_q1 else (5 if is_mark5 else 4))
|
||||
elif mode == 'incompat':
|
||||
if is_q1:
|
||||
data = make_firmware(4)
|
||||
else:
|
||||
with pytest.raises(RuntimeError) as err:
|
||||
make_firmware(3)
|
||||
assert "too big for our USB upgrades" in str(err)
|
||||
return
|
||||
data = make_firmware(4 if is_q1 else "q1")
|
||||
|
||||
hdr = data[FW_HEADER_OFFSET:FW_HEADER_OFFSET+FW_HEADER_SIZE]
|
||||
|
||||
|
||||
@ -214,7 +214,7 @@ def test_virtdisk_signing(encoding, num_outs, partial, try_sign_virtdisk, fake_t
|
||||
|
||||
if 0:
|
||||
@pytest.mark.parametrize('num_outs', [ 1, 20, 250])
|
||||
def test_virtdisk_after(num_outs, fake_txn, try_sign, nfc_read, need_keypress, cap_story, only_mk4):
|
||||
def test_virtdisk_after(num_outs, fake_txn, try_sign, nfc_read, need_keypress, cap_story):
|
||||
# Read signing result (transaction) over NFC, decode it.
|
||||
psbt = fake_txn(1, num_outs)
|
||||
orig, result = try_sign(psbt, accept=True, finalize=True)
|
||||
|
||||
@ -33,6 +33,7 @@ wallet (on testnet, always with the same seed). But there are other options:
|
||||
- `--mk2` => emulate mark2 hardware (older micro, etc), default is current-gen (mark4)
|
||||
- `--mk3` => emulate mark3 hardware
|
||||
- `--mk4` => emulate mark4 hardware
|
||||
- `--mk5` => emulate mark5 hardware (default)
|
||||
- `--q1` => emulate Q1 hardware
|
||||
- `--addr` => go to the address explorer at startup
|
||||
- `--xw` => go to the wallet export submenu
|
||||
|
||||
BIN
unix/mk5-images/background.png
Executable file
BIN
unix/mk5-images/background.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
unix/mk5-images/led-green.png
Normal file
BIN
unix/mk5-images/led-green.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
BIN
unix/mk5-images/led-red.png
Normal file
BIN
unix/mk5-images/led-red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
@ -439,15 +439,6 @@ class LCDSimulator(SimulatedScreen):
|
||||
self.draw_single_led(spriterenderer, 465, 315)
|
||||
|
||||
class OLEDSimulator(SimulatedScreen):
|
||||
# top-left coord of OLED area; size is 1:1 with real pixels... 128x64 pixels
|
||||
OLED_ACTIVE = (46, 85)
|
||||
|
||||
# keypad touch buttons
|
||||
KEYPAD_LEFT = 52
|
||||
KEYPAD_TOP = 216
|
||||
KEYPAD_PITCH = 73
|
||||
|
||||
background_img = 'mk4-images/background.png'
|
||||
|
||||
def __init__(self, factory):
|
||||
self.movie = None
|
||||
@ -463,11 +454,7 @@ class OLEDSimulator(SimulatedScreen):
|
||||
|
||||
self.mv = sdl2.ext.pixels2d(self.sprite, transpose=False)
|
||||
|
||||
# for genuine/caution lights and other LED's
|
||||
self.led_red = factory.from_image("mk4-images/led-red.png")
|
||||
self.led_green = factory.from_image("mk4-images/led-green.png")
|
||||
self.led_sdcard = factory.from_image("mk4-images/led-sd.png")
|
||||
self.led_usb = factory.from_image("mk4-images/led-usb.png")
|
||||
self.load_leds(factory)
|
||||
|
||||
def new_contents(self, readable):
|
||||
# got bytes for new update.
|
||||
@ -509,13 +496,59 @@ class OLEDSimulator(SimulatedScreen):
|
||||
SD_LED = 0x2
|
||||
USB_LED = 0x4
|
||||
|
||||
spriterenderer.render(self.led_green if (active_set & GEN_LED) else self.led_red)
|
||||
spriterenderer.render(self.led_genuine if (active_set & GEN_LED) else self.led_unsafe)
|
||||
|
||||
if active_set & SD_LED:
|
||||
spriterenderer.render(self.led_sdcard)
|
||||
if active_set & USB_LED:
|
||||
spriterenderer.render(self.led_usb)
|
||||
|
||||
class Mk4OLEDSimulator(OLEDSimulator):
|
||||
# top-left coord of OLED area; size is 1:1 with real pixels... 128x64 pixels
|
||||
OLED_ACTIVE = (46, 85)
|
||||
|
||||
# keypad touch buttons
|
||||
KEYPAD_LEFT = 52
|
||||
KEYPAD_TOP = 216
|
||||
KEYPAD_PITCH = 73
|
||||
|
||||
background_img = 'mk4-images/background.png'
|
||||
|
||||
def load_leds(self, factory):
|
||||
# for genuine/caution lights and other LED's
|
||||
# - these are pre-positioned where they need to end up
|
||||
self.led_unsafe = factory.from_image("mk4-images/led-red.png")
|
||||
self.led_genuine = factory.from_image("mk4-images/led-green.png")
|
||||
self.led_sdcard = factory.from_image("mk4-images/led-sd.png")
|
||||
self.led_usb = factory.from_image("mk4-images/led-usb.png")
|
||||
|
||||
class Mk5OLEDSimulator(OLEDSimulator):
|
||||
OLED_ACTIVE = (28, 41)
|
||||
|
||||
# keypad touch buttons
|
||||
KEYPAD_LEFT = 28
|
||||
KEYPAD_TOP = 125
|
||||
KEYPAD_PITCH = 42
|
||||
|
||||
background_img = 'mk5-images/background.png'
|
||||
|
||||
def load_leds(self, factory):
|
||||
# position each carefully
|
||||
r = factory.from_image("mk5-images/led-red.png")
|
||||
g = factory.from_image("mk5-images/led-green.png")
|
||||
|
||||
self.led_unsafe = r.subsprite(r.area)
|
||||
self.led_genuine = g.subsprite(g.area)
|
||||
self.led_sdcard = g.subsprite(g.area)
|
||||
self.led_usb = g.subsprite(g.area)
|
||||
|
||||
self.led_unsafe.position = (14, -9)
|
||||
self.led_genuine.position = (-1, -9)
|
||||
|
||||
self.led_sdcard.position = (-14, 23)
|
||||
self.led_usb.position = (65, 283)
|
||||
|
||||
|
||||
def load_shared_mod(name, path):
|
||||
# load indicated file.py as a module
|
||||
# from <https://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path>
|
||||
@ -783,7 +816,15 @@ Q1 specials:
|
||||
|
||||
factory = sdl2.ext.SpriteFactory(sdl2.ext.SOFTWARE)
|
||||
|
||||
simdis = (OLEDSimulator if not is_q1 else LCDSimulator)(factory)
|
||||
if is_q1:
|
||||
simdis = LCDSimulator(factory)
|
||||
elif ('--mk4' in sys.argv):
|
||||
# retro look
|
||||
simdis = Mk4OLEDSimulator(factory)
|
||||
else:
|
||||
# default: Mk5
|
||||
simdis = Mk5OLEDSimulator(factory)
|
||||
|
||||
bg = factory.from_image(simdis.background_img)
|
||||
|
||||
window = sdl2.ext.Window("Coldcard Simulator", size=bg.size, position=(100, 100))
|
||||
@ -952,6 +993,7 @@ Q1 specials:
|
||||
if not pressed:
|
||||
numpad_tx.write(b'\0') # all up signal
|
||||
|
||||
|
||||
while running:
|
||||
events = sdl2.ext.get_events()
|
||||
for event in events:
|
||||
|
||||
@ -26,10 +26,10 @@ SET_CHARGE_PUMP = const(0x8d)
|
||||
# Subclassing FrameBuffer provides support for graphics primitives
|
||||
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
|
||||
class SSD1306(framebuf.FrameBuffer):
|
||||
def __init__(self, width, height, external_vcc):
|
||||
def __init__(self, width, height, is_mk5):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.external_vcc = external_vcc
|
||||
self.is_mk5 = is_mk5
|
||||
self.pages = self.height // 8
|
||||
self.buffer = bytearray(self.pages * self.width)
|
||||
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
|
||||
@ -73,11 +73,19 @@ class SSD1306(framebuf.FrameBuffer):
|
||||
self.write_data(self.buffer)
|
||||
|
||||
|
||||
def busy_bar(self, enable, pattern):
|
||||
# Render a continuous activity (not progress) bar in lower 8 lines of display
|
||||
if enable:
|
||||
# just show as static pattern
|
||||
t = self.buffer[:-128] + pattern
|
||||
self.write_data(t)
|
||||
|
||||
|
||||
class SSD1306_SPI(SSD1306):
|
||||
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
|
||||
def __init__(self, width, height, spi, dc, res, cs, is_mk5=False):
|
||||
import sys
|
||||
self.pipe = open(int(sys.argv[1]), 'wb')
|
||||
super().__init__(width, height, external_vcc)
|
||||
super().__init__(width, height, is_mk5)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
pass
|
||||
|
||||
@ -32,8 +32,8 @@ def get_header_value(fld_name):
|
||||
return b'\x18\x07\x11\x19S\x08\x00\x00'
|
||||
return 0
|
||||
|
||||
# default is Mk4 hardware
|
||||
hw_label = 'mk4'
|
||||
# default is Mk5 hardware
|
||||
hw_label = 'mk5'
|
||||
has_608 = True
|
||||
has_membrane = True
|
||||
supports_hsm = True
|
||||
@ -47,7 +47,7 @@ has_qwerty = False
|
||||
is_edge = False
|
||||
|
||||
if '--mk1' in sys.argv:
|
||||
# doubt this works still
|
||||
# doubt this works anymore
|
||||
hw_label = 'mk1'
|
||||
has_608 = False
|
||||
has_membrane = False
|
||||
@ -72,6 +72,9 @@ if '--mk3' in sys.argv:
|
||||
has_nfc = False
|
||||
supports_hsm = False
|
||||
|
||||
if '--mk4' in sys.argv:
|
||||
hw_label = 'mk4'
|
||||
|
||||
mk_num = int(hw_label[2:])
|
||||
|
||||
if '--q1' in sys.argv:
|
||||
@ -81,6 +84,7 @@ if '--q1' in sys.argv:
|
||||
has_battery = True
|
||||
has_qwerty = True
|
||||
supports_hsm = False
|
||||
mk_num = 4
|
||||
|
||||
from public_constants import MAX_TXN_LEN, MAX_UPLOAD_LEN
|
||||
from public_constants import MAX_TXN_LEN_MK4, MAX_UPLOAD_LEN_MK4
|
||||
|
||||
Loading…
Reference in New Issue
Block a user