1
0

Add scanner

This commit is contained in:
2026-02-20 21:53:52 +01:00
parent 6517709ea7
commit eece17b9db
7 changed files with 325 additions and 25 deletions

View File

@@ -1,5 +1,6 @@
from protocol import I2CPCClient, time from protocol import I2CPCClient, time
from tef_102_patch import * from tef_102_patch import *
from tef_205_patch import *
from typing import Callable, TypeVar, ParamSpec, Concatenate from typing import Callable, TypeVar, ParamSpec, Concatenate
from collections.abc import Callable as ABCCallable from collections.abc import Callable as ABCCallable
@@ -11,25 +12,27 @@ ADDRESS = 0x64
class BaseTEF668X: class BaseTEF668X:
def __init__(self, p: I2CPCClient) -> None: def __init__(self, p: I2CPCClient) -> None:
self.p = p self.p = p
p.set_baudrate(1500000) p.set_baudrate(921600)
self.p.set_clock(400_000) self.p.set_clock(100_000)
def close(self): def close(self):
self.p.set_baudrate(115200) self.p.set_baudrate(115200)
self.p.close() self.p.close()
def _reset(self): def _reset(self):
self.p.write_i2c(ADDRESS, b"\x1e\x5a\x01\x5a\x5a") self.p.write_i2c(ADDRESS, b"\x1e\x5a\x01\x5a\x5a")
def _write_firmware(self, patch: bytes | list[int], patch_lut: bytes | list[int]): def _write_firmware(self, patch: bytes | list[int], patch_lut: bytes | list[int]):
self.p.set_clock(400_000)
self.p.write_i2c(ADDRESS, b"\x1c\x00\x00") self.p.write_i2c(ADDRESS, b"\x1c\x00\x00")
self.p.write_i2c(ADDRESS, b"\x1c\x00\x74") self.p.write_i2c(ADDRESS, b"\x1c\x00\x74")
def send_patch(_patch: bytes): def send_patch(_patch: bytes):
for i in range(0, len(_patch), 24): for i in range(0, len(_patch), 64):
data = _patch[i:i+24] data = _patch[i:i+64]
if self.p.write_i2c(ADDRESS, b"\x1b" + data)[0] != 0: raise Exception if self.p.write_i2c(ADDRESS, b"\x1b" + data)[0] != 0: raise Exception
send_patch(bytes(patch)) send_patch(bytes(patch))
self.p.write_i2c(ADDRESS, b"\x1c\x00\x00") self.p.write_i2c(ADDRESS, b"\x1c\x00\x00")
self.p.write_i2c(ADDRESS, b"\x1c\x00\x75") self.p.write_i2c(ADDRESS, b"\x1c\x00\x75")
send_patch(bytes(patch_lut)) send_patch(bytes(patch_lut))
self.p.write_i2c(ADDRESS, b"\x1c\x00\x00") self.p.write_i2c(ADDRESS, b"\x1c\x00\x00")
self.p.set_clock(100_000)
def APPL_Get_Operation_Status(self): def APPL_Get_Operation_Status(self):
data = self.p.write_read_i2c(ADDRESS, b"\x40\x80\x01", 2) data = self.p.write_read_i2c(ADDRESS, b"\x40\x80\x01", 2)
@@ -55,12 +58,12 @@ class BaseTEF668X:
def APPL_Activate(self): def APPL_Activate(self):
return b"\x40\x05\x01\x00\x01", None, None return b"\x40\x05\x01\x00\x01", None, None
def init(self): def init(self, patch = tef_102_patch, patch_lut = tef_102_patch_lut, clock: int = 9216000):
self._reset() self._reset()
while self.APPL_Get_Operation_Status() != 0: time.sleep(0.01) while self.APPL_Get_Operation_Status() != 0: time.sleep(0.01)
self._write_firmware(tef_102_patch, tef_102_patch_lut) self._write_firmware(patch, patch_lut)
self.p.write_i2c(ADDRESS, b"\x14\x00\x01") self.p.write_i2c(ADDRESS, b"\x14\x00\x01")
while self.APPL_Get_Operation_Status() != 1: time.sleep(0.01) while self.APPL_Get_Operation_Status() != 1: time.sleep(0.01)
self.APPL_Set_ReferenceClock(12000000, False) if clock != 9216000: self.APPL_Set_ReferenceClock(clock, False)
self.APPL_Activate() self.APPL_Activate()
while self.APPL_Get_Operation_Status() != 2: time.sleep(0.01) while self.APPL_Get_Operation_Status() != 2: time.sleep(0.01)

View File

@@ -1,6 +1,7 @@
import serial import serial
import struct import struct
import time import time
import time
def crc8(data: bytes) -> int: def crc8(data: bytes) -> int:
crc = 0x00 crc = 0x00
@@ -15,13 +16,16 @@ class I2CPCClient:
def __init__(self, port, baudrate=115200, timeout=1): def __init__(self, port, baudrate=115200, timeout=1):
self.ser = serial.Serial(port=port, baudrate=baudrate, timeout=timeout) self.ser = serial.Serial(port=port, baudrate=baudrate, timeout=timeout)
# Gurantees resync
self.ser.write(b"~/") self.ser.write(b"~/")
self.ser.write(b"\x00"*64) self.ser.write(b"\x00"*128)
self.ser.flush() self.ser.flush()
self.ser.write(b"~/") self.ser.write(b"~/")
self.ser.flush() self.ser.flush()
while not ((d := self.ser.read_all()) and b"\xff" in d): time.sleep(0.01)
start = time.monotonic()
while not ((d := self.ser.read_all()) and b"\xff" in d):
time.sleep(0.01)
if ((time.monotonic()) - start) > 5: raise ConnectionError("Could not wake")
def _send_packet(self, payload: bytes, crc: bool = True): def _send_packet(self, payload: bytes, crc: bool = True):
if len(payload) > 127: raise ValueError("Payload too large") if len(payload) > 127: raise ValueError("Payload too large")

13
tef.py
View File

@@ -1,18 +1,19 @@
from base_tef import BaseTEF668X, ADDRESS, Concatenate, P, T, Callable from __future__ import annotations
from base_tef import BaseTEF668X, ADDRESS, Concatenate, Callable, ParamSpec
from typing import overload, TypeVar from typing import overload, TypeVar
from functools import wraps from functools import wraps
P = ParamSpec("P")
T = TypeVar("T") T = TypeVar("T")
@overload @overload
def _command_wrapper(func: Callable[Concatenate["TEF6686", P],tuple[bytes, int | None, None],],) -> Callable[Concatenate["TEF6686", P], bytes]: ... def _command_wrapper(func: Callable[Concatenate[TEF6686, P],tuple[bytes, int | None, None],],) -> Callable[Concatenate[TEF6686, P], bytes]: ...
@overload @overload
def _command_wrapper(func: Callable[Concatenate["TEF6686", P],tuple[bytes, int | None, Callable[[bytes], T]],],) -> Callable[Concatenate["TEF6686", P], T]: ... def _command_wrapper(func: Callable[Concatenate[TEF6686, P],tuple[bytes, int | None, Callable[[bytes], T]],],) -> Callable[Concatenate[TEF6686, P], T]: ...
def _command_wrapper( def _command_wrapper(func: Callable[Concatenate[TEF6686, P], tuple[bytes, int | None, Callable[[bytes], T] | None], ]) -> Callable[Concatenate[TEF6686, P], bytes | T]:
func: Callable[Concatenate["TEF6686", P], tuple[bytes, int | None, Callable[[bytes], T] | None], ]) -> Callable[Concatenate["TEF6686", P], bytes | T]:
@wraps(func) @wraps(func)
def inner(self: "TEF6686", *args: P.args, **kwargs: P.kwargs) -> bytes | T: def inner(self: TEF6686, *args: P.args, **kwargs: P.kwargs) -> bytes | T:
data, read_bytes, out_parser = func(self, *args, **kwargs) data, read_bytes, out_parser = func(self, *args, **kwargs)
if read_bytes: data = self.p.write_read_i2c(ADDRESS, data, read_bytes) if read_bytes: data = self.p.write_read_i2c(ADDRESS, data, read_bytes)

View File

@@ -1,3 +1,5 @@
# p2.24
tef_102_patch = [ tef_102_patch = [
0xF0, 0x00, 0x38, 0x3B, 0xD0, 0x80, 0xF0, 0x00, 0x38, 0x43, 0xD0, 0x80, 0x43, 0xB2, 0x38, 0x46, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xC2, 0xF7, 0xF0, 0x00, 0x38, 0x3B, 0xD0, 0x80, 0xF0, 0x00, 0x38, 0x43, 0xD0, 0x80, 0x43, 0xB2, 0x38, 0x46, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xC2, 0xF7,
0xF0, 0x00, 0x38, 0x77, 0xD0, 0x80, 0xF0, 0x00, 0x38, 0x7B, 0xDF, 0x80, 0x80, 0xFC, 0x39, 0x0E, 0xD0, 0x80, 0xC2, 0x38, 0x20, 0x11, 0x40, 0xB7, 0xF0, 0x00, 0x38, 0x77, 0xD0, 0x80, 0xF0, 0x00, 0x38, 0x7B, 0xDF, 0x80, 0x80, 0xFC, 0x39, 0x0E, 0xD0, 0x80, 0xC2, 0x38, 0x20, 0x11, 0x40, 0xB7,

253
tef_205_patch.py Normal file
View File

@@ -0,0 +1,253 @@
# p5.12
tef_205_patch = [
0xF0, 0x00, 0x60, 0x40, 0xD0, 0x80, 0x20, 0x87, 0x60, 0x4C, 0xD0, 0x80, 0x90, 0x00, 0x60, 0x4E, 0xD0, 0x80, 0x22, 0x02, 0x00, 0x55, 0x60, 0x04,
0xF0, 0x00, 0x60, 0x65, 0xDF, 0x80, 0xF0, 0x00, 0x05, 0xBA, 0x60, 0x0E, 0x20, 0x90, 0x60, 0x9B, 0xD0, 0x80, 0x31, 0x40, 0x60, 0x9F, 0xD0, 0x80,
0x9E, 0xB9, 0x60, 0xAD, 0xD0, 0x80, 0xF0, 0x00, 0x60, 0xAF, 0xD0, 0x80, 0x20, 0x15, 0x60, 0xB3, 0xD2, 0x80, 0xF0, 0x00, 0x60, 0xCE, 0xD0, 0x80,
0x90, 0x01, 0x60, 0xD3, 0xD0, 0x80, 0x91, 0x01, 0x60, 0xD4, 0xD0, 0x80, 0xF0, 0x00, 0x60, 0xD5, 0xD0, 0x80, 0xA2, 0x64, 0x70, 0x00, 0xF0, 0x00,
0x31, 0xA0, 0x61, 0x06, 0xD0, 0x80, 0x40, 0x57, 0x61, 0x2B, 0xD0, 0x80, 0x22, 0x04, 0x61, 0x30, 0xD0, 0x80, 0x20, 0x13, 0x63, 0x7D, 0xD0, 0x80,
0xF0, 0x00, 0x61, 0x52, 0xD0, 0x80, 0xF0, 0x00, 0x61, 0x60, 0xD2, 0x80, 0xF0, 0x00, 0x61, 0x6C, 0xD0, 0x80, 0x4F, 0xD0, 0x61, 0x69, 0xD1, 0x80,
0x9E, 0x73, 0x61, 0xA2, 0xD0, 0x80, 0xF0, 0x00, 0x61, 0xAD, 0xD0, 0x80, 0xF0, 0x00, 0x61, 0xB5, 0xD0, 0x80, 0xF0, 0x00, 0x61, 0xCA, 0xD0, 0x80,
0x2C, 0x87, 0x61, 0xD6, 0xD0, 0x80, 0xF0, 0x00, 0x61, 0xDA, 0xD0, 0x80, 0xF0, 0x00, 0x61, 0xDD, 0xD2, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x62, 0x0D, 0xD2, 0x80, 0x57, 0xF2, 0x62, 0x0F, 0xD5, 0x80, 0xA8, 0x80, 0x70, 0x00, 0xF0, 0x00, 0x90, 0x08, 0x20, 0x55, 0xE1, 0xC0,
0xF0, 0x00, 0x62, 0x18, 0xD0, 0x80, 0xF0, 0x00, 0x62, 0x1F, 0xD2, 0x80, 0x4F, 0xA0, 0x61, 0x69, 0xD2, 0x80, 0x4F, 0xC0, 0x61, 0x69, 0xD2, 0x80,
0xF0, 0x00, 0x62, 0x32, 0xD2, 0x80, 0x9A, 0x0A, 0x62, 0x33, 0xD0, 0x80, 0x50, 0x14, 0x62, 0x3A, 0xD2, 0x80, 0xF0, 0x00, 0x62, 0x3D, 0xD0, 0x80,
0xF0, 0x00, 0x62, 0x42, 0xD0, 0x80, 0x41, 0x20, 0x14, 0xF6, 0xD2, 0x80, 0xF0, 0x00, 0x62, 0xB4, 0xD0, 0x80, 0xF0, 0x00, 0x62, 0xC4, 0xD0, 0x80,
0xF0, 0x00, 0x62, 0xCD, 0xD0, 0x80, 0xF0, 0x00, 0x62, 0xEA, 0xD0, 0x80, 0xF0, 0x00, 0x62, 0xF0, 0xD0, 0x80, 0xF0, 0x00, 0x62, 0xF2, 0xD2, 0x80,
0x40, 0x11, 0x62, 0xFC, 0xD0, 0x80, 0xF0, 0x00, 0x63, 0x0E, 0xD0, 0x80, 0xF0, 0x00, 0x63, 0x10, 0xD0, 0x80, 0x2D, 0xC5, 0x18, 0xFF, 0x60, 0x06,
0x21, 0xC6, 0x63, 0x3B, 0xD0, 0x80, 0xF0, 0x00, 0x63, 0x43, 0xD0, 0x80, 0xF0, 0x00, 0x63, 0x45, 0xD0, 0x80, 0x82, 0x09, 0x0D, 0xA4, 0x60, 0x0D,
0xF0, 0x00, 0x63, 0x57, 0xD2, 0x80, 0xF0, 0x00, 0x63, 0x57, 0xD2, 0x80, 0xF0, 0x00, 0x63, 0x56, 0xD5, 0x80, 0xF0, 0x00, 0x63, 0x7F, 0xD2, 0x80,
0x82, 0x00, 0x70, 0x00, 0xA0, 0x12, 0x82, 0x00, 0x70, 0x00, 0xA0, 0x4E, 0x82, 0x00, 0x70, 0x00, 0xA0, 0xAC, 0x82, 0x00, 0x70, 0x00, 0xA1, 0x04,
0x82, 0x00, 0x70, 0x00, 0xA1, 0xAC, 0x82, 0x00, 0x70, 0x00, 0xA3, 0x37, 0x82, 0x00, 0x70, 0x00, 0xA1, 0xE7, 0x82, 0x00, 0x70, 0x00, 0xA2, 0x0F,
0x82, 0x00, 0x70, 0x00, 0xA2, 0x26, 0x82, 0x00, 0x70, 0x00, 0xA2, 0xC8, 0x82, 0x00, 0x70, 0x00, 0xA3, 0x32, 0xF0, 0x00, 0x27, 0xAA, 0xD0, 0x80,
0xF0, 0x00, 0x01, 0xA9, 0xD5, 0x80, 0x8C, 0x79, 0x00, 0x46, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xD4, 0x09, 0xF0, 0x00, 0x00, 0x97, 0xD0, 0x80,
0x40, 0x11, 0x0E, 0x72, 0x60, 0x09, 0xD0, 0x7F, 0x70, 0x00, 0xF0, 0x00, 0xC5, 0xC9, 0x01, 0xB6, 0xD0, 0x80, 0x05, 0x44, 0x60, 0x08, 0xA3, 0x29,
0x30, 0x80, 0x05, 0x78, 0x60, 0x00, 0x06, 0x1A, 0x60, 0x08, 0xA3, 0x28, 0xF0, 0x00, 0x6F, 0x3F, 0x60, 0x00, 0x05, 0x76, 0x60, 0x08, 0xA3, 0x26,
0xF0, 0x00, 0x1C, 0x17, 0x60, 0x00, 0x05, 0x77, 0x60, 0x08, 0x83, 0x24, 0xF0, 0x00, 0x07, 0x69, 0x60, 0x08, 0xF0, 0x00, 0x05, 0x19, 0x60, 0x09,
0xF0, 0x00, 0x20, 0x00, 0xF0, 0x00, 0x26, 0x92, 0x54, 0xA3, 0x60, 0x01, 0xA2, 0x00, 0x70, 0x00, 0xF0, 0x00, 0xA2, 0x08, 0x70, 0x00, 0xF0, 0x00,
0xA2, 0x10, 0x70, 0x00, 0xF0, 0x00, 0xD8, 0x40, 0x70, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x34, 0x90, 0xF0, 0x00, 0xF0, 0x00, 0x35, 0x90, 0xF0, 0x00,
0xF0, 0x00, 0x36, 0x90, 0xD0, 0x08, 0x40, 0x15, 0x20, 0x53, 0xA3, 0x17, 0xA0, 0xE8, 0x58, 0x06, 0xA3, 0x16, 0xA0, 0x72, 0x20, 0x64, 0xF0, 0x00,
0xA8, 0x61, 0x70, 0x00, 0xF0, 0x00, 0xA1, 0x28, 0x70, 0x00, 0xF0, 0x00, 0xA0, 0xB2, 0x70, 0x00, 0xF0, 0x00, 0xA8, 0x62, 0x70, 0x00, 0xD0, 0x08,
0x05, 0x79, 0x60, 0x08, 0x83, 0x11, 0xF0, 0x00, 0x10, 0x68, 0x60, 0x01, 0xF0, 0x00, 0x60, 0x03, 0x80, 0x02, 0xF0, 0x00, 0x08, 0x34, 0x60, 0x01,
0xF8, 0x00, 0x60, 0x03, 0x80, 0x00, 0x18, 0x31, 0x60, 0x08, 0xA3, 0x0B, 0xF0, 0x00, 0x30, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x31, 0x03, 0xD0, 0x08,
0x06, 0x1A, 0x60, 0x08, 0xF0, 0x00, 0x06, 0x3B, 0x60, 0x09, 0x80, 0x00, 0xF0, 0x00, 0x0F, 0x84, 0xD2, 0x80, 0x83, 0xFF, 0x7F, 0xFF, 0x60, 0x06,
0x32, 0x90, 0x03, 0xE8, 0x60, 0x00, 0x33, 0x11, 0x07, 0x63, 0x60, 0x0A, 0x80, 0x99, 0x70, 0x00, 0xF0, 0x00, 0x8E, 0x08, 0x31, 0x22, 0xF0, 0x00,
0x90, 0xC0, 0x70, 0x00, 0x90, 0x0B, 0x83, 0x6D, 0x70, 0x00, 0xA0, 0xAF, 0x90, 0x04, 0x0F, 0xC1, 0xD2, 0x80, 0x32, 0x00, 0x03, 0xE8, 0x60, 0x00,
0x32, 0x81, 0x70, 0x00, 0xA0, 0xAC, 0x90, 0x04, 0x21, 0x20, 0xF0, 0x00, 0x31, 0x84, 0x70, 0x00, 0xA0, 0xAA, 0xF0, 0x00, 0x22, 0x87, 0xF0, 0x00,
0xB0, 0x03, 0x22, 0x06, 0xF0, 0x00, 0xB1, 0xC2, 0x31, 0x00, 0xF0, 0x00, 0xBF, 0x8A, 0x70, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x33, 0x02, 0xD0, 0x08,
0x80, 0x98, 0x70, 0x00, 0xA0, 0xA4, 0x90, 0x04, 0x31, 0x80, 0xF0, 0x00, 0x90, 0x80, 0x70, 0x00, 0xA0, 0xA2, 0x90, 0x05, 0x31, 0x00, 0xF0, 0x00,
0x90, 0x05, 0x0F, 0xC1, 0xD2, 0x80, 0xF0, 0x00, 0x32, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x32, 0x81, 0xF0, 0x00, 0xF0, 0x00, 0x33, 0x02, 0xD0, 0x08,
0xF0, 0x00, 0x1D, 0x10, 0x60, 0x09, 0x40, 0x11, 0x7F, 0xFF, 0x60, 0x02, 0x30, 0x10, 0x00, 0x82, 0x60, 0x03, 0xF0, 0x00, 0x30, 0x92, 0xF0, 0x00,
0xF0, 0x00, 0x31, 0x11, 0xF0, 0x00, 0xF0, 0x00, 0x31, 0x90, 0xF0, 0x00, 0xF0, 0x00, 0x32, 0x12, 0xF0, 0x00, 0xF0, 0x00, 0x32, 0x90, 0xF0, 0x00,
0xF0, 0x00, 0x33, 0x13, 0xF0, 0x00, 0x1D, 0x0F, 0x60, 0x08, 0xA2, 0xE4, 0xF0, 0x00, 0x70, 0x00, 0x82, 0xE2, 0x9A, 0x62, 0x1D, 0x0F, 0x60, 0x0A,
0x82, 0x92, 0x70, 0x00, 0x94, 0x01, 0x90, 0x8A, 0x00, 0x00, 0x60, 0x01, 0x30, 0x22, 0x08, 0x0C, 0xD0, 0x80, 0xF0, 0x00, 0x09, 0x44, 0xD2, 0x80,
0xF0, 0x00, 0x07, 0xFD, 0xD2, 0x80, 0xF0, 0x00, 0x08, 0x11, 0xD0, 0x80, 0xF0, 0x00, 0x18, 0x72, 0x60, 0x08, 0xF0, 0x00, 0x1D, 0x0F, 0x60, 0x09,
0xF0, 0x00, 0x2D, 0x80, 0xA2, 0xD8, 0x9A, 0x02, 0x20, 0x11, 0xF0, 0x00, 0x90, 0x8A, 0x70, 0x00, 0xD0, 0x09, 0x90, 0x41, 0x70, 0x00, 0xD0, 0x08,
0x18, 0x72, 0x60, 0x08, 0xA2, 0xD4, 0xF0, 0x00, 0x2D, 0x80, 0xA2, 0xD3, 0x98, 0x00, 0x70, 0x00, 0xF0, 0x00, 0x90, 0x08, 0x70, 0x00, 0xD0, 0x09,
0x82, 0x00, 0x70, 0x00, 0xD0, 0x08, 0x90, 0xC1, 0x08, 0xEC, 0xD1, 0x80, 0xF0, 0x00, 0x08, 0xDC, 0xD0, 0x80, 0xF0, 0x00, 0x1D, 0x0F, 0x60, 0x0A,
0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00, 0x20, 0x23, 0x70, 0x00, 0xA2, 0xCB, 0x80, 0x59, 0x09, 0x49, 0xD0, 0x80, 0x1D, 0x10, 0x60, 0x0E, 0xA2, 0xC9,
0x22, 0x61, 0x7F, 0xFF, 0x60, 0x07, 0xF0, 0x00, 0x21, 0xE0, 0xF0, 0x00, 0x82, 0x7C, 0x70, 0x00, 0xF0, 0x00, 0x90, 0x00, 0x22, 0xE4, 0xE0, 0x40,
0x90, 0x00, 0x70, 0x00, 0xD0, 0x09, 0x9F, 0x3C, 0x70, 0x00, 0x98, 0x06, 0x83, 0x24, 0x70, 0x00, 0xE1, 0x40, 0xF0, 0x00, 0x32, 0xE4, 0x94, 0x03,
0x80, 0x41, 0x70, 0x00, 0xF0, 0x00, 0x91, 0xC1, 0x40, 0x00, 0xEB, 0x40, 0xA2, 0x8A, 0x32, 0x61, 0x80, 0x04, 0xA2, 0x8A, 0x32, 0x61, 0x80, 0x03,
0x80, 0x41, 0x70, 0x00, 0xF0, 0x00, 0x82, 0x49, 0x40, 0x00, 0xEB, 0x40, 0xA2, 0x8A, 0x32, 0x61, 0x80, 0x00, 0xA2, 0xCB, 0x31, 0xE0, 0xD0, 0x08,
0x03, 0x13, 0x60, 0x06, 0x80, 0x01, 0xFC, 0xED, 0x60, 0x06, 0x80, 0x00, 0x1D, 0x10, 0x60, 0x0E, 0xA2, 0xB6, 0xF0, 0x00, 0x30, 0x66, 0xD0, 0x08,
0x03, 0x13, 0x60, 0x06, 0x80, 0x01, 0xFC, 0xED, 0x60, 0x06, 0x80, 0x00, 0x1D, 0x10, 0x60, 0x0E, 0xA2, 0xB2, 0xF0, 0x00, 0x31, 0xE6, 0xF0, 0x00,
0xF0, 0x00, 0x23, 0x66, 0xA2, 0xB0, 0xF0, 0x00, 0x32, 0xE6, 0xD0, 0x08, 0x1D, 0x0F, 0x60, 0x0B, 0xA2, 0xAE, 0xF0, 0x00, 0x20, 0x37, 0xA2, 0xAD,
0x91, 0xC7, 0x21, 0x91, 0xF0, 0x00, 0x90, 0xC3, 0x0B, 0x0B, 0xD1, 0x80, 0x82, 0x49, 0x0B, 0x14, 0xD0, 0x80, 0x31, 0x91, 0x0B, 0x14, 0xD0, 0x80,
0x31, 0x91, 0x0B, 0x14, 0xD0, 0x80, 0x1D, 0x10, 0x60, 0x0D, 0xA2, 0xA7, 0xF0, 0x00, 0x21, 0x57, 0xA2, 0xA6, 0x91, 0xC7, 0x31, 0x50, 0xF0, 0x00,
0x90, 0x00, 0x70, 0x00, 0x94, 0x02, 0xF0, 0x00, 0x70, 0x00, 0x90, 0x01, 0xF0, 0x00, 0x70, 0x00, 0xAF, 0xE9, 0xF0, 0x00, 0x7F, 0xFF, 0x60, 0x04,
0x82, 0x00, 0x20, 0x57, 0xA2, 0xA0, 0x91, 0xC7, 0x20, 0xD3, 0xA2, 0x9F, 0x80, 0xFB, 0x70, 0x00, 0x90, 0x06, 0x82, 0xE2, 0x30, 0xD3, 0x98, 0x01,
0xF0, 0x00, 0x70, 0x00, 0x98, 0x04, 0x91, 0xC7, 0x30, 0x50, 0xF0, 0x00, 0x91, 0x00, 0x70, 0x00, 0xE1, 0xC0, 0x30, 0xD0, 0x70, 0x00, 0xF0, 0x00,
0x90, 0x03, 0x70, 0x00, 0xF0, 0x00, 0xA2, 0xED, 0x70, 0x00, 0xF0, 0x00, 0xA2, 0xF6, 0x31, 0x05, 0xF0, 0x00, 0xF0, 0x00, 0x0B, 0x22, 0xD0, 0x80,
0xF0, 0x00, 0x0B, 0xFD, 0xD2, 0x80, 0xF0, 0x00, 0x70, 0x00, 0x98, 0xD9, 0xF0, 0x00, 0x70, 0x00, 0x80, 0xDB, 0xF0, 0x00, 0x2D, 0xBB, 0xD0, 0x80,
0xF0, 0x00, 0x70, 0x00, 0x81, 0x08, 0xF0, 0x00, 0x70, 0x00, 0x81, 0x0B, 0xF0, 0x00, 0x70, 0x00, 0x8F, 0x85, 0x83, 0xFF, 0x1D, 0x17, 0x60, 0x08,
0xF0, 0x00, 0x1D, 0x19, 0x60, 0x09, 0x10, 0x07, 0x00, 0x00, 0x60, 0x02, 0x10, 0x07, 0x01, 0xF4, 0x60, 0x03, 0x10, 0x12, 0x03, 0xE8, 0x60, 0x04,
0x10, 0x13, 0x00, 0x00, 0x60, 0x05, 0x10, 0x14, 0x00, 0x3C, 0x60, 0x06, 0x10, 0x15, 0x00, 0x00, 0x60, 0x07, 0x10, 0x16, 0x01, 0xF4, 0x60, 0x00,
0x10, 0x17, 0x03, 0xE8, 0x60, 0x01, 0x10, 0x10, 0x00, 0x00, 0x60, 0x00, 0x10, 0x11, 0x00, 0x3C, 0x60, 0x01, 0x10, 0x10, 0x00, 0x00, 0x60, 0x02,
0x10, 0x11, 0x00, 0x64, 0x60, 0x03, 0x10, 0x12, 0x00, 0xC8, 0x60, 0x04, 0x10, 0x13, 0x70, 0x00, 0xF0, 0x00, 0x10, 0x14, 0x70, 0x00, 0xA2, 0x7D,
0xF0, 0x00, 0x70, 0x00, 0xA0, 0x20, 0xF0, 0x00, 0x70, 0x00, 0x80, 0x25, 0xF0, 0x00, 0x1D, 0x17, 0x60, 0x06, 0xF0, 0x00, 0x0C, 0xFC, 0xD0, 0x80,
0xF0, 0x00, 0x1D, 0x17, 0x60, 0x06, 0xF0, 0x00, 0x0C, 0xFF, 0xD0, 0x80, 0x2F, 0xA0, 0x17, 0x8D, 0x60, 0x09, 0x20, 0x21, 0x1D, 0x17, 0x60, 0x06,
0xD2, 0x02, 0x00, 0x13, 0x4F, 0xF0, 0xC4, 0x8A, 0x70, 0x00, 0xF0, 0x00, 0x90, 0xC3, 0x40, 0x05, 0xF0, 0x00, 0x82, 0xD3, 0x00, 0x13, 0x90, 0x13,
0x90, 0x08, 0x70, 0x00, 0x97, 0xFD, 0xF0, 0x00, 0x2E, 0x24, 0x40, 0x15, 0x32, 0x20, 0x60, 0xEB, 0x60, 0x07, 0x32, 0xA5, 0x0C, 0xFA, 0xD2, 0x80,
0x90, 0x03, 0x0C, 0xA8, 0xD5, 0x80, 0xD0, 0x98, 0x17, 0x92, 0x60, 0x06, 0x80, 0x20, 0x0C, 0xFA, 0xD2, 0x80, 0x90, 0xC0, 0x0C, 0xCE, 0xD1, 0x80,
0xF0, 0x00, 0x0D, 0x92, 0x60, 0x09, 0xD0, 0x42, 0x17, 0x93, 0x60, 0x06, 0x20, 0x21, 0x00, 0x7F, 0x60, 0x03, 0x81, 0x96, 0x70, 0x00, 0xF0, 0x00,
0x82, 0x5B, 0x30, 0x16, 0x77, 0x0C, 0x82, 0xDB, 0x0C, 0x7F, 0xDD, 0x80, 0xC0, 0x51, 0x20, 0x19, 0xA2, 0x62, 0x20, 0x12, 0x70, 0x00, 0xF0, 0x00,
0x20, 0x98, 0x70, 0x00, 0xF0, 0x00, 0x20, 0x99, 0x0D, 0x23, 0xD2, 0x80, 0xF0, 0x00, 0x0C, 0x7F, 0xD0, 0x80, 0x21, 0xA0, 0x0E, 0xD3, 0x60, 0x01,
0x32, 0xA5, 0x0C, 0x70, 0xD0, 0x80, 0xF0, 0x00, 0x61, 0x23, 0x60, 0x00, 0x19, 0x22, 0x60, 0x08, 0x82, 0x5B, 0x9C, 0x48, 0x70, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x0D, 0x34, 0xD5, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xA1, 0xD1, 0xF0, 0x00, 0x70, 0x00, 0x80, 0xEE, 0xF0, 0x00, 0x05, 0x0C, 0x60, 0x00,
0x07, 0xE9, 0x60, 0x08, 0xA2, 0x55, 0xF0, 0x00, 0x00, 0x6B, 0x60, 0x00, 0x07, 0xE8, 0x60, 0x08, 0x82, 0x53, 0xF0, 0x00, 0x0F, 0x94, 0xD2, 0x80,
0x88, 0x00, 0x70, 0x00, 0xD0, 0x08, 0x51, 0xEC, 0x60, 0x01, 0xA2, 0x4F, 0xA0, 0x08, 0x70, 0x00, 0xF0, 0x00, 0xAB, 0xE0, 0x70, 0x00, 0xD0, 0x08,
0xF0, 0x00, 0x21, 0x83, 0xF0, 0x00, 0x91, 0x04, 0x70, 0x00, 0xF0, 0x00, 0x88, 0x24, 0x5F, 0x86, 0xEF, 0xC0, 0x82, 0x08, 0x0F, 0xF8, 0xD0, 0x80,
0xF0, 0x00, 0x0D, 0x9A, 0x60, 0x0C, 0xF0, 0x00, 0x08, 0x2E, 0x60, 0x0F, 0xF0, 0x00, 0x20, 0x48, 0x40, 0x17, 0xF0, 0x00, 0x20, 0xC9, 0x58, 0x06,
0xF0, 0x00, 0x21, 0xCA, 0xF0, 0x00, 0xF0, 0x00, 0x22, 0x4B, 0xF0, 0x00, 0xF0, 0x00, 0x20, 0x11, 0xF0, 0x00, 0xF0, 0x00, 0x20, 0x00, 0xF0, 0x00,
0xA1, 0xC8, 0x21, 0x42, 0xF0, 0x00, 0xA1, 0x82, 0x20, 0x33, 0xF0, 0x00, 0xAE, 0x88, 0x20, 0x22, 0xF0, 0x00, 0xA1, 0xD8, 0x22, 0xC4, 0xF0, 0x00,
0xA1, 0x92, 0x61, 0x34, 0x60, 0x07, 0xAF, 0x0B, 0x33, 0x40, 0xF0, 0x00, 0xF0, 0x00, 0x33, 0xC3, 0xF0, 0x00, 0xF0, 0x00, 0x30, 0x77, 0xD0, 0x08,
0x00, 0x6E, 0x60, 0x0C, 0xA2, 0x38, 0xF0, 0x00, 0x21, 0x47, 0xA2, 0x37, 0xC3, 0xC7, 0x70, 0x00, 0xD0, 0x08, 0xF0, 0x00, 0x14, 0xD7, 0xD0, 0x80,
0x44, 0xD0, 0x1D, 0x26, 0x60, 0x08, 0xF0, 0x00, 0x45, 0xF2, 0x45, 0x51, 0x30, 0x00, 0x46, 0x93, 0xF0, 0x00, 0x30, 0x81, 0x47, 0xF4, 0xF0, 0x00,
0x31, 0x02, 0x05, 0x69, 0x60, 0x01, 0x31, 0x83, 0x05, 0x42, 0x60, 0x02, 0x32, 0x04, 0x70, 0x00, 0xF0, 0x00, 0x32, 0x81, 0x70, 0x00, 0xF0, 0x00,
0x33, 0x02, 0x70, 0x00, 0x80, 0x66, 0x1D, 0x2D, 0x60, 0x08, 0x82, 0x2C, 0xF0, 0x00, 0x4F, 0xA0, 0xA0, 0x16, 0xF0, 0x00, 0x4F, 0xB0, 0xA0, 0x15,
0xF0, 0x00, 0x4F, 0xC0, 0xA0, 0x14, 0xF0, 0x00, 0x4F, 0xD0, 0xA0, 0x13, 0xF0, 0x00, 0x4F, 0xE0, 0xA0, 0x12, 0xF0, 0x00, 0x4F, 0xF0, 0xA0, 0x11,
0xF0, 0x00, 0x40, 0x20, 0xA0, 0x10, 0xF0, 0x00, 0x40, 0x40, 0xA0, 0x0F, 0xF0, 0x00, 0x40, 0x50, 0xA0, 0x0E, 0xF0, 0x00, 0x40, 0x60, 0xA0, 0x0D,
0x40, 0x00, 0x15, 0x35, 0xD2, 0x80, 0x40, 0x10, 0x15, 0x35, 0xD2, 0x80, 0x40, 0x30, 0x15, 0x35, 0xD2, 0x80, 0xF0, 0x00, 0x15, 0x2D, 0xD0, 0x80,
0x9A, 0xD9, 0x15, 0x35, 0x60, 0x01, 0x61, 0x64, 0x60, 0x01, 0xEE, 0x00, 0x9A, 0xDB, 0x70, 0x00, 0xE1, 0xC0, 0x80, 0x59, 0x70, 0x00, 0x82, 0x19,
0x1D, 0x26, 0x60, 0x09, 0x80, 0x06, 0x1D, 0x27, 0x60, 0x09, 0x80, 0x05, 0x1D, 0x28, 0x60, 0x09, 0x80, 0x04, 0x1D, 0x29, 0x60, 0x09, 0x80, 0x03,
0x1D, 0x2A, 0x60, 0x09, 0x80, 0x02, 0x1D, 0x2B, 0x60, 0x09, 0x80, 0x01, 0x1D, 0x2C, 0x60, 0x09, 0x80, 0x00, 0xF0, 0x00, 0x15, 0x4A, 0xD0, 0x80,
0x9F, 0xBA, 0x41, 0xA0, 0x40, 0xF3, 0x9F, 0xB2, 0x41, 0xA1, 0x90, 0x05, 0x9F, 0xAA, 0x70, 0x00, 0x90, 0x1A, 0x00, 0x00, 0x60, 0x02, 0x90, 0x1B,
0xF0, 0x00, 0x32, 0x20, 0xF0, 0x00, 0xF0, 0x00, 0x32, 0xA1, 0xF0, 0x00, 0xF0, 0x00, 0x34, 0x22, 0x80, 0x1D, 0xD6, 0x21, 0x1D, 0x2D, 0x60, 0x09,
0xC2, 0x59, 0x10, 0x00, 0x60, 0x03, 0x9E, 0x72, 0x41, 0xA0, 0xF0, 0x00, 0x9E, 0x6A, 0x40, 0xE0, 0xE2, 0x00, 0x9C, 0x6A, 0x41, 0x20, 0xE2, 0x00,
0xF0, 0x00, 0x20, 0x12, 0xF0, 0x00, 0x92, 0x50, 0x70, 0x00, 0xE1, 0xC0, 0x90, 0x82, 0x70, 0x00, 0xF0, 0x00, 0xC3, 0x5B, 0x41, 0xB0, 0xE2, 0x00,
0xD5, 0x22, 0x70, 0x00, 0x90, 0x06, 0x9E, 0xB3, 0x41, 0xA1, 0xF0, 0x00, 0x9E, 0xAB, 0x40, 0xE1, 0xE2, 0x00, 0x9C, 0xAB, 0x41, 0x21, 0xE2, 0x00,
0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00, 0x92, 0x91, 0x70, 0x00, 0xE1, 0xC0, 0x00, 0x01, 0x60, 0x02, 0x8F, 0xED, 0x9E, 0xB3, 0x41, 0xA1, 0xF0, 0x00,
0x9E, 0xAB, 0x41, 0x11, 0xE2, 0x00, 0x9C, 0xAB, 0x41, 0x21, 0xE2, 0x00, 0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00, 0x92, 0x91, 0x70, 0x00, 0xE1, 0xC0,
0x00, 0x0B, 0x60, 0x02, 0x8F, 0xE7, 0xF0, 0x00, 0x40, 0xD1, 0x40, 0xD0, 0x00, 0x1F, 0x60, 0x02, 0x8F, 0xE5, 0xF0, 0x00, 0x10, 0x00, 0x60, 0x03,
0xF0, 0x00, 0x41, 0xB0, 0xF0, 0x00, 0xC3, 0x5B, 0x00, 0x0A, 0x60, 0x02, 0x00, 0x00, 0x60, 0x02, 0xE6, 0x00, 0xF0, 0x00, 0x70, 0x00, 0x8F, 0xE0,
0x9F, 0xF9, 0x41, 0xA0, 0x40, 0xF3, 0xF0, 0x00, 0x41, 0xA1, 0x90, 0x01, 0x00, 0x06, 0x60, 0x02, 0x80, 0x0B, 0xC3, 0x19, 0x10, 0x00, 0x60, 0x03,
0x9E, 0x72, 0x41, 0xA0, 0xF0, 0x00, 0x9E, 0x6A, 0x40, 0xE0, 0xE2, 0x00, 0x9E, 0x62, 0x41, 0x20, 0xE2, 0x00, 0x9C, 0x6A, 0x41, 0x00, 0xE2, 0x00,
0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00, 0x92, 0x50, 0x70, 0x00, 0xE1, 0xC0, 0xC3, 0x5B, 0x70, 0x00, 0xF0, 0x00, 0x41, 0xA1, 0x00, 0x17, 0x60, 0x02,
0x00, 0x37, 0x60, 0x02, 0xE6, 0x00, 0x90, 0x01, 0x70, 0x00, 0xE0, 0xC0, 0x44, 0x03, 0x20, 0xA7, 0xA1, 0xDE, 0x91, 0xC4, 0x70, 0x00, 0xF0, 0x00,
0x41, 0xA1, 0x41, 0xA0, 0xE2, 0x40, 0xF0, 0x00, 0x15, 0x93, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0x98, 0x05, 0x9E, 0x6B, 0x70, 0x00, 0x90, 0x05,
0x9C, 0x43, 0x70, 0x00, 0x90, 0x05, 0x9C, 0x6B, 0x70, 0x00, 0x9C, 0x02, 0xF0, 0x00, 0x70, 0x00, 0x9C, 0x04, 0xF0, 0x00, 0x70, 0x00, 0x80, 0x00,
0x41, 0xA3, 0x70, 0x00, 0x80, 0x03, 0x40, 0x83, 0x70, 0x00, 0x80, 0x02, 0x41, 0x53, 0x70, 0x00, 0x80, 0x01, 0x94, 0xEB, 0x70, 0x00, 0x80, 0x00,
0x4F, 0xE0, 0x15, 0x32, 0xD0, 0x80, 0xF0, 0x00, 0x4F, 0xF0, 0xA0, 0x02, 0xD7, 0x12, 0x4F, 0xB0, 0xA0, 0x01, 0xF0, 0x00, 0x15, 0xC5, 0xD0, 0x80,
0xF0, 0x00, 0x40, 0xF3, 0xA1, 0xCC, 0xC2, 0x9B, 0x70, 0x00, 0xF0, 0x00, 0x9C, 0xEB, 0x70, 0x00, 0xF0, 0x00, 0x82, 0xDB, 0x70, 0x00, 0xE1, 0x40,
0x94, 0xEB, 0x15, 0x32, 0xD0, 0x80, 0x4F, 0xB0, 0x70, 0x00, 0xAF, 0xB3, 0x4F, 0xF0, 0x70, 0x00, 0x8F, 0xB2, 0xF0, 0x00, 0x08, 0xCC, 0x60, 0x09,
0xF0, 0x00, 0x61, 0xBD, 0x60, 0x01, 0xF0, 0x00, 0x61, 0xC0, 0x60, 0x02, 0x35, 0x91, 0x70, 0x00, 0xF0, 0x00, 0x36, 0x12, 0x08, 0x7F, 0x60, 0x00,
0x08, 0xC3, 0x60, 0x08, 0x81, 0xC1, 0xF0, 0x00, 0x16, 0x95, 0xD2, 0x80, 0x05, 0x44, 0x60, 0x03, 0xF0, 0x00, 0x0E, 0x21, 0x60, 0x09, 0x8F, 0x87,
0xF0, 0x00, 0x16, 0x9B, 0xD2, 0x80, 0xF0, 0x00, 0x24, 0xB3, 0xF0, 0x00, 0x0E, 0x21, 0x60, 0x09, 0x8F, 0x84, 0x00, 0x26, 0x60, 0x00, 0xA0, 0x05,
0x80, 0x12, 0x60, 0x03, 0xF0, 0x00, 0x0E, 0x20, 0x60, 0x09, 0x8F, 0x81, 0x00, 0x30, 0x60, 0x00, 0xA0, 0x02, 0x80, 0x03, 0x60, 0x03, 0xF0, 0x00,
0x0E, 0x20, 0x60, 0x09, 0x8F, 0x7E, 0xF0, 0x00, 0x16, 0xCB, 0xD0, 0x80, 0x0A, 0x15, 0x60, 0x08, 0xF0, 0x00, 0xF0, 0x00, 0x21, 0x5B, 0xD2, 0x80,
0xF0, 0x00, 0x1B, 0xCD, 0x60, 0x08, 0x22, 0x10, 0x70, 0x00, 0xF0, 0x00, 0x2C, 0x87, 0x70, 0x00, 0xF0, 0x00, 0x22, 0x91, 0x7F, 0xFF, 0x60, 0x06,
0x91, 0xC7, 0x2D, 0x0C, 0xF0, 0x00, 0x2E, 0x0A, 0x17, 0xCE, 0xD5, 0x80, 0xF0, 0x00, 0x33, 0x06, 0xF0, 0x00, 0xF0, 0x00, 0x33, 0x86, 0xF0, 0x00,
0xF0, 0x00, 0x34, 0x06, 0xF0, 0x00, 0x34, 0x86, 0x17, 0xCE, 0xD0, 0x80, 0xF0, 0x00, 0x32, 0x94, 0xF0, 0x00, 0x91, 0xC7, 0x70, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x17, 0xF7, 0xD5, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xD0, 0x08, 0x9E, 0xB7, 0x39, 0x12, 0xE2, 0x00, 0x83, 0x8F, 0x39, 0x12, 0xE2, 0x00,
0xF0, 0x00, 0x18, 0x8F, 0xD0, 0x80, 0x82, 0x00, 0x03, 0xE0, 0x60, 0x08, 0x0C, 0x1D, 0x60, 0x09, 0xC0, 0x10, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00,
0x33, 0x10, 0x1A, 0xA2, 0xD0, 0x80, 0x82, 0x00, 0x70, 0x00, 0xF0, 0x00, 0x09, 0x5D, 0x60, 0x08, 0xA1, 0x9A, 0xF0, 0x00, 0x34, 0x80, 0xF0, 0x00,
0xF0, 0x00, 0x34, 0x00, 0xD0, 0x08, 0x82, 0x00, 0x04, 0xA8, 0x60, 0x0A, 0xF0, 0x00, 0x06, 0x98, 0x60, 0x01, 0x09, 0xE2, 0x60, 0x08, 0xC0, 0x08,
0xF0, 0x00, 0x10, 0x21, 0xF0, 0x00, 0xF0, 0x00, 0x31, 0x80, 0xD0, 0x08, 0xF0, 0x00, 0x18, 0x93, 0xD2, 0x80, 0x08, 0x46, 0x60, 0x08, 0xA1, 0x91,
0xF0, 0x00, 0x29, 0x00, 0xA1, 0x90, 0x9E, 0x30, 0x70, 0x00, 0xF0, 0x00, 0x09, 0x97, 0x60, 0x08, 0xD4, 0x09, 0x09, 0x6E, 0x60, 0x00, 0xA1, 0x8D,
0xF0, 0x00, 0x30, 0x80, 0xD0, 0x08, 0x4F, 0xD0, 0x09, 0x7D, 0x60, 0x08, 0x4F, 0xE1, 0x40, 0x02, 0xF0, 0x00, 0x36, 0x00, 0x70, 0x00, 0xF0, 0x00,
0x33, 0x81, 0x70, 0x00, 0x80, 0x20, 0x0A, 0x66, 0x60, 0x08, 0xF0, 0x00, 0x0A, 0x87, 0x60, 0x09, 0xA0, 0x0D, 0xF0, 0x00, 0x0F, 0x84, 0xD2, 0x80,
0x83, 0xFF, 0x1D, 0x3E, 0xD0, 0x80, 0x0A, 0x6D, 0x60, 0x08, 0xF0, 0x00, 0x0A, 0x87, 0x60, 0x09, 0xA0, 0x09, 0xF0, 0x00, 0x0F, 0x84, 0xD2, 0x80,
0x31, 0x90, 0x03, 0xE8, 0x60, 0x00, 0x32, 0x11, 0x0F, 0xBE, 0xD2, 0x80, 0x90, 0x07, 0x70, 0x00, 0xF0, 0x00, 0x80, 0x98, 0x0F, 0xBE, 0xD2, 0x80,
0x8B, 0xC7, 0x70, 0x00, 0xF0, 0x00, 0x90, 0x04, 0x31, 0x87, 0x40, 0x07, 0x90, 0x80, 0x0F, 0xBE, 0xD2, 0x80, 0x31, 0x00, 0x1D, 0x67, 0xD0, 0x80,
0x58, 0x07, 0x22, 0x25, 0xF0, 0x00, 0x91, 0x04, 0x03, 0x87, 0x60, 0x00, 0x7F, 0xFC, 0x60, 0x06, 0xD0, 0x09, 0x82, 0x2A, 0x0F, 0x9C, 0xD2, 0x80,
0x80, 0xB8, 0x27, 0x14, 0xA1, 0x74, 0x81, 0x39, 0x0F, 0xE7, 0xD2, 0x80, 0xA2, 0x76, 0x20, 0x21, 0xF0, 0x00, 0xF0, 0x00, 0x20, 0xA2, 0xF0, 0x00,
0xF0, 0x00, 0x21, 0x23, 0xD0, 0x08, 0xF7, 0xCF, 0x60, 0x03, 0xF0, 0x00, 0x28, 0x00, 0x60, 0x00, 0xD0, 0x08, 0xF0, 0x00, 0x70, 0x00, 0xC0, 0x08,
0xF0, 0x00, 0x10, 0x32, 0xF0, 0x00, 0xF0, 0x00, 0x70, 0x00, 0xD0, 0x08, 0x0D, 0xA2, 0x60, 0x09, 0xA1, 0x6A, 0x20, 0x12, 0x22, 0x63, 0xD2, 0x80,
0xF0, 0x00, 0x35, 0x82, 0xD0, 0x08, 0x90, 0x82, 0x0D, 0xA2, 0x60, 0x08, 0x40, 0xA0, 0x40, 0x70, 0xE6, 0x40, 0xF0, 0x00, 0x70, 0x00, 0x81, 0x66,
0x23, 0x3E, 0x60, 0x05, 0xA1, 0x64, 0x8E, 0x2D, 0x23, 0x43, 0x60, 0x06, 0x91, 0xC1, 0x22, 0xF1, 0xD5, 0x80, 0x8F, 0x86, 0x3E, 0xE6, 0x60, 0x03,
0x91, 0xC1, 0x22, 0xF1, 0xD5, 0x80, 0x80, 0x18, 0x70, 0x00, 0xF0, 0x00, 0x91, 0xC1, 0x22, 0xF1, 0xD0, 0x80, 0x0C, 0x78, 0x60, 0x08, 0xA0, 0x01,
0x40, 0x11, 0x40, 0x94, 0x81, 0x5C, 0x90, 0x00, 0xFF, 0xEF, 0x60, 0x06, 0xF0, 0x00, 0x23, 0xB8, 0xD1, 0x80, 0x41, 0x06, 0x23, 0xB6, 0xD0, 0x80,
0x00, 0x02, 0x60, 0x03, 0x80, 0x05, 0x00, 0x04, 0x60, 0x03, 0x80, 0x04, 0x00, 0x06, 0x60, 0x03, 0x80, 0x03, 0xF0, 0x00, 0x23, 0x18, 0xD0, 0x80,
0xF0, 0x00, 0x23, 0x18, 0xD0, 0x80, 0x00, 0x10, 0x60, 0x03, 0x80, 0x00, 0xF0, 0x00, 0x20, 0x84, 0xA1, 0x52, 0xC2, 0xE3, 0x70, 0x00, 0xF0, 0x00,
0x90, 0x41, 0x23, 0x8C, 0xD1, 0x80, 0xF0, 0x00, 0x23, 0x77, 0xD0, 0x80, 0x40, 0xC0, 0x0C, 0x95, 0x60, 0x08, 0x40, 0x81, 0x0C, 0x92, 0x60, 0x09,
0xF0, 0x00, 0x30, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x30, 0x11, 0xD0, 0x08, 0x20, 0x02, 0x58, 0x01, 0x81, 0x4A, 0xD0, 0x40, 0x25, 0x21, 0xD5, 0x80,
0x40, 0xC2, 0x62, 0x36, 0x60, 0x01, 0xA0, 0x06, 0x60, 0x00, 0x81, 0x47, 0x54, 0x55, 0x60, 0x01, 0x81, 0x46, 0x55, 0x55, 0x60, 0x01, 0x81, 0x45,
0x15, 0x11, 0x60, 0x01, 0x81, 0x44, 0x00, 0x01, 0x60, 0x01, 0x81, 0x43, 0xF0, 0x00, 0x1C, 0x29, 0x60, 0x09, 0xC5, 0x04, 0x30, 0x80, 0xF0, 0x00,
0x83, 0x24, 0x3D, 0x14, 0xD0, 0x08, 0xF0, 0x00, 0x70, 0x00, 0x90, 0x02, 0xF0, 0x00, 0x40, 0x30, 0xAE, 0xC3, 0xF0, 0x00, 0x26, 0x10, 0xD0, 0x80,
0xF0, 0x00, 0x40, 0x30, 0xAE, 0xC3, 0xF0, 0x00, 0x26, 0x11, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAF, 0x0E, 0xF0, 0x00, 0x70, 0x00, 0x90, 0x08,
0xF0, 0x00, 0x00, 0x7A, 0x60, 0x08, 0x40, 0x01, 0x19, 0x32, 0x60, 0x09, 0xF0, 0x00, 0x21, 0x80, 0xF0, 0x00, 0xF0, 0x00, 0x30, 0x11, 0xF0, 0x00,
0x90, 0x00, 0x25, 0xD6, 0xD2, 0x80, 0x00, 0x00, 0x60, 0x02, 0xF0, 0x00, 0x00, 0x00, 0x60, 0x03, 0xA1, 0x2D, 0x00, 0x00, 0x60, 0x01, 0x80, 0x07,
0xF0, 0x00, 0x19, 0x30, 0x60, 0x09, 0xF0, 0x00, 0x03, 0x4E, 0x60, 0x01, 0xF0, 0x00, 0x5A, 0xCC, 0x60, 0x02, 0x10, 0x11, 0x00, 0x01, 0x60, 0x03,
0x10, 0x12, 0x70, 0x00, 0xF0, 0x00, 0x10, 0x13, 0x2C, 0xB6, 0xD2, 0x80, 0x00, 0x03, 0x60, 0x01, 0x80, 0x00, 0xF0, 0x00, 0x19, 0x34, 0x60, 0x08,
0xF0, 0x00, 0x33, 0x03, 0x60, 0x02, 0x30, 0x01, 0x10, 0x10, 0x60, 0x03, 0xF0, 0x00, 0x27, 0x25, 0xD0, 0x80, 0xF0, 0x00, 0x00, 0x00, 0x60, 0x00,
0x1C, 0x75, 0x60, 0x08, 0xA1, 0x25, 0xF0, 0x00, 0x62, 0x5B, 0x60, 0x00, 0x1C, 0x77, 0x60, 0x08, 0x81, 0x23, 0x82, 0x00, 0x29, 0x01, 0xF0, 0x00,
0xF0, 0x00, 0x3A, 0x02, 0xF0, 0x00, 0xF0, 0x00, 0x3B, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x39, 0x80, 0xF0, 0x00, 0x9E, 0x7F, 0x37, 0x01, 0x40, 0x23,
0x9E, 0x77, 0x27, 0x15, 0xD1, 0x80, 0x90, 0x47, 0x27, 0x18, 0xD1, 0x80, 0x9E, 0x6F, 0x27, 0x12, 0xD1, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xD4, 0x09,
0xF0, 0x00, 0x39, 0x03, 0xF0, 0x00, 0xF0, 0x00, 0x38, 0x83, 0xF0, 0x00, 0x40, 0x21, 0x26, 0x37, 0xD2, 0x80, 0xF0, 0x00, 0x27, 0x39, 0xD2, 0x80,
0x19, 0x64, 0x60, 0x02, 0xF0, 0x00, 0x19, 0x64, 0x60, 0x03, 0xA1, 0x0E, 0x40, 0x00, 0x27, 0x1B, 0xD0, 0x80, 0x1C, 0x67, 0x60, 0x08, 0xA1, 0x11,
0xF0, 0x00, 0x27, 0x00, 0x81, 0x10, 0xF0, 0x00, 0x01, 0x8E, 0x60, 0x00, 0x1C, 0x92, 0x60, 0x08, 0x81, 0x0F, 0x82, 0x92, 0x1C, 0xAF, 0x60, 0x0E,
0x62, 0xE8, 0x60, 0x06, 0xA0, 0x86, 0x30, 0x66, 0x1C, 0xA2, 0x60, 0x0F, 0xF0, 0x00, 0x62, 0xDD, 0x60, 0x07, 0xF0, 0x00, 0x62, 0xDF, 0x60, 0x00,
0x30, 0x77, 0x62, 0xE4, 0x60, 0x01, 0x32, 0x70, 0x1C, 0xD8, 0x60, 0x08, 0x34, 0x71, 0x62, 0x8E, 0x60, 0x00, 0xF0, 0x00, 0x62, 0x8C, 0x60, 0x01,
0x31, 0x80, 0x1C, 0xBA, 0x60, 0x09, 0x30, 0x81, 0x62, 0xC2, 0x60, 0x02, 0xF0, 0x00, 0x62, 0xBD, 0x60, 0x03, 0x33, 0x12, 0x62, 0xD9, 0x60, 0x04,
0x32, 0x93, 0x1C, 0x94, 0x60, 0x0A, 0x35, 0x94, 0x62, 0x9D, 0x60, 0x05, 0xF0, 0x00, 0x62, 0x9B, 0x60, 0x06, 0x30, 0xA5, 0x62, 0xA3, 0x60, 0x07,
0x30, 0x26, 0x1C, 0xEA, 0x60, 0x0B, 0x34, 0xA7, 0x62, 0x94, 0x60, 0x00, 0xF0, 0x00, 0x62, 0x97, 0x60, 0x01, 0x31, 0xB0, 0x62, 0x99, 0x60, 0x02,
0x32, 0x31, 0x1C, 0xD0, 0x60, 0x0C, 0x32, 0xB2, 0x62, 0xA5, 0x60, 0x03, 0xF0, 0x00, 0x62, 0xAC, 0x60, 0x04, 0x30, 0xC3, 0x62, 0xB0, 0x60, 0x05,
0x31, 0xC4, 0x62, 0xAE, 0x60, 0x06, 0x32, 0xC5, 0x70, 0x00, 0xF0, 0x00, 0x32, 0x46, 0x70, 0x00, 0x8F, 0xE2, 0xF0, 0x00, 0x28, 0x70, 0xD0, 0x80,
0x82, 0x00, 0x70, 0x00, 0xAD, 0xDF, 0xF0, 0x00, 0x29, 0x46, 0xD0, 0x80, 0xF0, 0x00, 0x31, 0xE4, 0xD2, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xA0, 0x02,
0xF0, 0x00, 0x70, 0x00, 0xA0, 0xCA, 0xF0, 0x00, 0x29, 0x61, 0xD0, 0x80, 0xF0, 0x00, 0x60, 0x6D, 0xD1, 0x80, 0xF0, 0x00, 0x70, 0x00, 0x8D, 0xDB,
0xF0, 0x00, 0x70, 0x00, 0xAD, 0xC5, 0xF0, 0x00, 0x23, 0xBD, 0xD2, 0x80, 0xF0, 0x00, 0x29, 0xB4, 0xD0, 0x80, 0xF0, 0x00, 0x23, 0xD7, 0xD2, 0x80,
0xF0, 0x00, 0x29, 0xBA, 0xD0, 0x80, 0xF0, 0x00, 0x23, 0xD5, 0xD2, 0x80, 0xF0, 0x00, 0x29, 0xBE, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAF, 0x4E,
0xF0, 0x00, 0x29, 0xE7, 0xD0, 0x80, 0x40, 0x12, 0x28, 0x76, 0xD2, 0x80, 0xF0, 0x00, 0x29, 0xF4, 0xD1, 0x80, 0x00, 0x40, 0x60, 0x00, 0xAE, 0xA4,
0x00, 0x40, 0x60, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x2C, 0x7A, 0xD7, 0x80, 0xF0, 0x00, 0x11, 0x7C, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAF, 0x3D,
0xF0, 0x00, 0x2A, 0x35, 0xD0, 0x80, 0x0C, 0xB2, 0x60, 0x0D, 0xF0, 0x00, 0xF0, 0x00, 0x28, 0x6A, 0xD2, 0x80, 0xF0, 0x00, 0x19, 0x05, 0xD2, 0x80,
0xF0, 0x00, 0x0B, 0xE9, 0xD2, 0x80, 0xF0, 0x00, 0x0B, 0xF7, 0xD2, 0x80, 0xF0, 0x00, 0x01, 0xF1, 0xD2, 0x80, 0xF0, 0x00, 0x2A, 0x7B, 0xD0, 0x80,
0xF0, 0x00, 0x23, 0xBD, 0xD2, 0x80, 0xF0, 0x00, 0x2A, 0x8A, 0xD0, 0x80, 0xF0, 0x00, 0x18, 0x7C, 0xD2, 0x80, 0xF0, 0x00, 0x2A, 0x91, 0xD0, 0x80,
0xF0, 0x00, 0x0B, 0xF8, 0xD2, 0x80, 0xF0, 0x00, 0x0B, 0xEC, 0xD2, 0x80, 0xF0, 0x00, 0x01, 0xF5, 0xD2, 0x80, 0xF0, 0x00, 0x2A, 0x9B, 0xD0, 0x80,
0x62, 0xB6, 0x60, 0x00, 0xF0, 0x00, 0x40, 0x21, 0x28, 0x89, 0xD0, 0x80, 0xF0, 0x00, 0x28, 0x92, 0xD2, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xA0, 0x43,
0x62, 0xBA, 0x60, 0x00, 0xF0, 0x00, 0x40, 0x21, 0x28, 0x89, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xA0, 0xBB, 0xF0, 0x00, 0x11, 0x7C, 0xD2, 0x80,
0x2B, 0x03, 0x60, 0x00, 0x8F, 0xCE, 0xF0, 0x00, 0x2B, 0x0D, 0xD2, 0x80, 0x62, 0xC0, 0x60, 0x00, 0xF0, 0x00, 0x40, 0x51, 0x28, 0x89, 0xD0, 0x80,
0xF0, 0x00, 0x70, 0x00, 0xAF, 0x24, 0xF0, 0x00, 0x2B, 0x14, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAE, 0x25, 0xF0, 0x00, 0x2B, 0x19, 0xD0, 0x80,
0x62, 0xC6, 0x60, 0x00, 0xF0, 0x00, 0x40, 0x21, 0x28, 0x89, 0xD0, 0x80, 0xF0, 0x00, 0x28, 0x90, 0xD2, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xA0, 0x32,
0x62, 0xCA, 0x60, 0x00, 0xF0, 0x00, 0x40, 0x21, 0x28, 0x89, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xA0, 0xAB, 0xF0, 0x00, 0x11, 0x7C, 0xD2, 0x80,
0x2B, 0x21, 0x60, 0x00, 0x8F, 0xBE, 0xF0, 0x00, 0x19, 0x1F, 0xD2, 0x80, 0x40, 0x01, 0x26, 0xEE, 0xD2, 0x80, 0x40, 0x11, 0x26, 0xF0, 0xD2, 0x80,
0x40, 0x11, 0x26, 0xF2, 0xD2, 0x80, 0xF0, 0x00, 0x0B, 0xF1, 0xD2, 0x80, 0xF0, 0x00, 0x0B, 0xEC, 0xD2, 0x80, 0xF0, 0x00, 0x0C, 0x00, 0xD2, 0x80,
0x00, 0x80, 0x60, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x2C, 0x7B, 0xD2, 0x80, 0x40, 0x11, 0x0B, 0x90, 0xD7, 0x80, 0x2B, 0x4F, 0x60, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x2B, 0x4E, 0xD0, 0x80, 0x40, 0x21, 0x0B, 0x90, 0xD2, 0x80, 0xF0, 0x00, 0x1B, 0x32, 0xD2, 0x80, 0xF0, 0x00, 0x19, 0x21, 0xD2, 0x80,
0xF0, 0x00, 0x2B, 0x58, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAF, 0x0C, 0xF0, 0x00, 0x2B, 0x7A, 0xD0, 0x80, 0x0C, 0xB2, 0x60, 0x0D, 0xF0, 0x00,
0xF0, 0x00, 0x28, 0x6A, 0xD2, 0x80, 0xF0, 0x00, 0x21, 0xA2, 0xD2, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAF, 0x2F, 0xF0, 0x00, 0x2B, 0x9D, 0xD0, 0x80,
0xF0, 0x00, 0x2B, 0xC0, 0xD2, 0x80, 0xF0, 0x00, 0x0D, 0xA3, 0x60, 0x08, 0x2B, 0xC9, 0x60, 0x00, 0xF0, 0x00, 0x20, 0x01, 0x28, 0x87, 0xD0, 0x80,
0xF0, 0x00, 0x70, 0x00, 0xAF, 0x01, 0xF0, 0x00, 0x2B, 0xE7, 0xD0, 0x80, 0xF0, 0x00, 0x28, 0x73, 0xD2, 0x80, 0x9C, 0x2F, 0x40, 0x01, 0xF0, 0x00,
0x9C, 0x0F, 0x0A, 0xA7, 0xD1, 0x80, 0x9A, 0x1F, 0x0A, 0xA7, 0xD1, 0x80, 0xF0, 0x00, 0x0A, 0xA7, 0xD1, 0x80, 0xF0, 0x00, 0x0A, 0x91, 0xD0, 0x80,
0x0C, 0xC4, 0x60, 0x08, 0xF0, 0x00, 0xF0, 0x00, 0x2C, 0x8A, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAF, 0x78, 0x90, 0x47, 0x70, 0x00, 0xF0, 0x00,
0x9E, 0x2F, 0x70, 0x00, 0xE0, 0x40, 0xF0, 0x00, 0x40, 0x31, 0xE2, 0x00, 0xF0, 0x00, 0x70, 0x00, 0xD0, 0x08, 0x90, 0x82, 0x0D, 0xA3, 0x60, 0x08,
0x40, 0x10, 0x40, 0x60, 0xE6, 0x40, 0xF0, 0x00, 0x70, 0x00, 0x80, 0x84, 0x40, 0x02, 0x40, 0x01, 0x80, 0x32, 0x40, 0x12, 0x40, 0x01, 0x80, 0x31,
0x0D, 0x15, 0x60, 0x08, 0xA0, 0x80, 0x3F, 0x01, 0x27, 0x2E, 0xD2, 0x80, 0x9E, 0x38, 0x70, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x70, 0x00, 0x94, 0x04,
0xF0, 0x00, 0x70, 0x00, 0xAD, 0xA1, 0xF0, 0x00, 0x70, 0x00, 0x90, 0x02, 0xF0, 0x00, 0x70, 0x00, 0xAD, 0xC2, 0x43, 0xE1, 0x70, 0x00, 0x80, 0x04,
0xF0, 0x00, 0x70, 0x00, 0xAD, 0xA3, 0x41, 0x31, 0x70, 0x00, 0x90, 0x02, 0xF0, 0x00, 0x70, 0x00, 0xAD, 0xC2, 0x43, 0xE1, 0x70, 0x00, 0x80, 0x00,
0xF0, 0x00, 0x63, 0x0B, 0x60, 0x02, 0x40, 0x10, 0x2D, 0x5D, 0xD2, 0x80, 0xF0, 0x00, 0x2D, 0xB2, 0xD0, 0x80, 0xF0, 0x00, 0x26, 0x41, 0xD2, 0x80,
0xF0, 0x00, 0x2F, 0xC2, 0xD2, 0x80, 0xF0, 0x00, 0x28, 0x5A, 0xD0, 0x80, 0xF0, 0x00, 0x70, 0x00, 0xAD, 0xB5, 0x40, 0x10, 0x32, 0x14, 0xD0, 0x80,
0xF0, 0x00, 0x70, 0x00, 0xAD, 0xB7, 0xF0, 0x00, 0x30, 0x1E, 0xD0, 0x80, 0xF0, 0x00, 0x0D, 0x15, 0x60, 0x08, 0xF0, 0x00, 0x17, 0x9B, 0x60, 0x00,
0xF0, 0x00, 0x17, 0x9B, 0x60, 0x01, 0x3F, 0x80, 0x0D, 0xAC, 0x60, 0x09, 0x30, 0x01, 0x56, 0xA5, 0x60, 0x02, 0xF0, 0x00, 0x5E, 0x86, 0x60, 0x03,
0x10, 0x12, 0x59, 0x89, 0x60, 0x04, 0x10, 0x13, 0x61, 0xAD, 0x60, 0x05, 0x10, 0x14, 0x5C, 0x6C, 0x60, 0x06, 0x10, 0x15, 0x64, 0xD3, 0x60, 0x07,
0x10, 0x16, 0x55, 0x2D, 0x60, 0x00, 0x10, 0x17, 0x5C, 0xEB, 0x60, 0x01, 0x10, 0x10, 0x58, 0x04, 0x60, 0x02, 0x10, 0x11, 0x60, 0x04, 0x60, 0x03,
0x10, 0x12, 0x5A, 0xDB, 0x60, 0x04, 0x10, 0x13, 0x63, 0x1D, 0x60, 0x05, 0x10, 0x14, 0x0D, 0xA4, 0x60, 0x0A, 0x10, 0x15, 0x02, 0xE1, 0x60, 0x06,
0xF0, 0x00, 0x43, 0x14, 0x60, 0x07, 0x10, 0x26, 0x04, 0x5B, 0x60, 0x00, 0x10, 0x27, 0x44, 0x95, 0x60, 0x01, 0x10, 0x20, 0x05, 0xD5, 0x60, 0x02,
0x10, 0x21, 0x46, 0x16, 0x60, 0x03, 0x10, 0x22, 0x06, 0xAE, 0x60, 0x04, 0x10, 0x23, 0x00, 0x00, 0x60, 0x05, 0x10, 0x24, 0x70, 0x00, 0xF0, 0x00,
0x10, 0x25, 0x70, 0x00, 0xD0, 0x08, 0x40, 0x05, 0x0D, 0x4F, 0x60, 0x0C, 0xF0, 0x00, 0x02, 0x09, 0x60, 0x03, 0x35, 0xC2, 0x08, 0xFB, 0x60, 0x06,
0x8F, 0x4D, 0x31, 0x40, 0xF0, 0x00, 0x8E, 0xC4, 0x20, 0x47, 0x90, 0x06, 0x81, 0x65, 0x70, 0x00, 0xF0, 0x00, 0x8F, 0x84, 0x40, 0x12, 0xF0, 0x00,
0x81, 0x65, 0x08, 0xFB, 0x60, 0x03, 0x8E, 0xA9, 0x70, 0x00, 0xF0, 0x00, 0x8E, 0xC2, 0x70, 0x00, 0xF0, 0x00, 0xC2, 0x51, 0x70, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x36, 0x41, 0xF0, 0x00, 0xF0, 0x00, 0x30, 0x45, 0xF0, 0x00, 0xF0, 0x00, 0x30, 0xC7, 0x80, 0x38, 0xD1, 0xC2, 0x35, 0x71, 0x35, 0x60,
0xD6, 0x0B, 0x1C, 0x29, 0x60, 0x0B, 0xC4, 0x9A, 0x40, 0x27, 0xF0, 0x00, 0xD2, 0x0B, 0x3D, 0xB2, 0xF0, 0x00, 0xC4, 0xF3, 0x3B, 0xB7, 0xF0, 0x00,
0x83, 0xB6, 0x3E, 0x33, 0xF0, 0x00, 0xF0, 0x00, 0x3B, 0x36, 0xF0, 0x00, 0xF0, 0x00, 0x3C, 0x36, 0xD0, 0x08, 0x82, 0x0A, 0x00, 0x61, 0x90, 0x09,
0xF0, 0x00, 0x30, 0xE3, 0xD0, 0x80, 0x17, 0xB4, 0x60, 0x08, 0xA0, 0x37, 0xF0, 0x00, 0x00, 0x02, 0xA0, 0x36, 0x90, 0x82, 0x70, 0x00, 0xF0, 0x00,
0x82, 0x8A, 0x70, 0x00, 0x90, 0x03, 0x90, 0x8A, 0x70, 0x00, 0x90, 0x01, 0xF0, 0x00, 0x70, 0x00, 0x8F, 0xFB, 0x82, 0xBF, 0x70, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x01, 0xB7, 0xD0, 0x80, 0x17, 0xAC, 0x60, 0x0E, 0xA0, 0x2F, 0x4F, 0xF6, 0x00, 0x61, 0xA0, 0x2E, 0x90, 0x41, 0x70, 0x00, 0xF0, 0x00,
0x82, 0x0A, 0x00, 0x61, 0x90, 0x04, 0x91, 0x8E, 0x70, 0x00, 0x97, 0xFD, 0x37, 0x46, 0x70, 0x00, 0xF0, 0x00, 0xD7, 0xB1, 0x17, 0xB2, 0x60, 0x00,
0xF0, 0x00, 0x30, 0xF3, 0xD0, 0x80, 0xF0, 0x00, 0x30, 0xE7, 0xD0, 0x80, 0x21, 0x40, 0x31, 0x91, 0xD0, 0x80, 0xF0, 0x00, 0x2C, 0x86, 0xD2, 0x80,
0xF0, 0x00, 0x70, 0x00, 0xD4, 0x09, 0xF0, 0x00, 0x27, 0x2E, 0xD2, 0x80, 0x90, 0x00, 0x70, 0x00, 0xD0, 0x08, 0x0D, 0x4F, 0x60, 0x0C, 0xA0, 0x21,
0x26, 0x42, 0x41, 0xD7, 0xA0, 0x20, 0x90, 0x82, 0x70, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x50, 0xD1, 0x80, 0xF0, 0x00, 0x31, 0xFE, 0xD2, 0x80,
0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00, 0x90, 0x00, 0x0D, 0xAC, 0x60, 0x08, 0x0D, 0xB2, 0x60, 0x08, 0xE6, 0x00, 0xF0, 0x00, 0x30, 0x6F, 0xD2, 0x80,
0x83, 0xFF, 0x00, 0xFF, 0x60, 0x04, 0x7F, 0xFF, 0x60, 0x02, 0xCA, 0x86, 0xF0, 0x00, 0x00, 0x01, 0xA0, 0x16, 0xA2, 0x09, 0x00, 0x80, 0x60, 0x03,
0xC2, 0x61, 0x0D, 0xB9, 0x60, 0x0B, 0x82, 0x59, 0x0D, 0xB8, 0x60, 0x0A, 0x89, 0x09, 0x70, 0x00, 0xF0, 0x00, 0x8E, 0x55, 0x70, 0x00, 0xF0, 0x00,
0xD1, 0xCB, 0x40, 0x15, 0x90, 0x02, 0x90, 0x42, 0x30, 0x33, 0xF0, 0x00, 0x91, 0xC6, 0x30, 0x27, 0xF0, 0x00, 0x91, 0xCF, 0x70, 0x00, 0xF0, 0x00,
0xC3, 0xAF, 0x01, 0xB7, 0xD2, 0x80, 0xD7, 0xF3, 0x70, 0x00, 0xF0, 0x00, 0x96, 0xEF, 0x70, 0x00, 0x8C, 0xDD, 0x40, 0x10, 0x2F, 0xB7, 0xD2, 0x80,
0xF0, 0x00, 0x2E, 0x60, 0xD2, 0x80, 0xF0, 0x00, 0x31, 0xBE, 0xD0, 0x80, 0x0D, 0x4F, 0x60, 0x08, 0xA0, 0x06, 0x2F, 0x00, 0x31, 0xF7, 0xD0, 0x80,
0x0D, 0x4F, 0x60, 0x08, 0xA0, 0x04, 0x3E, 0x82, 0x19, 0xDD, 0x60, 0x09, 0x3E, 0x03, 0x1A, 0x33, 0x60, 0x0A, 0x30, 0x12, 0x70, 0x00, 0xF0, 0x00,
0x30, 0x23, 0x70, 0x00, 0xD0, 0x08, 0xF0, 0x00, 0x70, 0x00, 0xD0, 0x08, 0xF0, 0x00, 0x33, 0x57, 0xD0, 0x80, 0xF0, 0x00, 0x33, 0x95, 0xD2, 0x80,
0xF0, 0x00, 0x63, 0x81, 0xD0, 0x80, 0xF0, 0x00, 0x17, 0x8D, 0x60, 0x08, 0xF0, 0x00, 0x40, 0x87, 0x60, 0x00, 0xF0, 0x00, 0x20, 0x2B, 0x60, 0x00,
0x10, 0x00, 0x20, 0x2C, 0x60, 0x00, 0x10, 0x00, 0x21, 0x35, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x17, 0x92, 0x60, 0x08, 0xF0, 0x00, 0xEE, 0xEE, 0x60, 0x00, 0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x17, 0x93, 0x60, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x0D, 0x92, 0x60, 0x00,
0x10, 0x00, 0x00, 0x05, 0x60, 0x00, 0x10, 0x00, 0x1D, 0x19, 0x60, 0x00, 0x10, 0x00, 0x00, 0x05, 0x60, 0x00, 0x10, 0x00, 0x1D, 0x1E, 0x60, 0x00,
0x10, 0x00, 0x00, 0x03, 0x60, 0x00, 0x10, 0x00, 0x1D, 0x23, 0x60, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x17, 0x9B, 0x60, 0x08, 0xF0, 0x00, 0x19, 0x04, 0x60, 0x00, 0xF0, 0x00, 0x00, 0x60, 0x60, 0x00, 0x10, 0x00, 0x19, 0x1C, 0x60, 0x00,
0x10, 0x00, 0x00, 0x60, 0x60, 0x00, 0x10, 0x00, 0x19, 0x1F, 0x60, 0x00, 0x10, 0x00, 0xC0, 0x5E, 0x60, 0x00, 0x10, 0x00, 0x19, 0x25, 0x60, 0x00,
0x10, 0x00, 0xC0, 0x5E, 0x60, 0x00, 0x10, 0x00, 0x1E, 0x28, 0x60, 0x00, 0x10, 0x00, 0xC0, 0x52, 0x60, 0x00, 0x10, 0x00, 0x1E, 0x2D, 0x60, 0x00,
0x10, 0x00, 0xC0, 0x52, 0x60, 0x00, 0x10, 0x00, 0x29, 0x18, 0x60, 0x00, 0x10, 0x00, 0xC0, 0x3A, 0x60, 0x00, 0x10, 0x00, 0x29, 0x18, 0x60, 0x00,
0x10, 0x00, 0x80, 0x38, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x17, 0xAC, 0x60, 0x08, 0xF0, 0x00, 0x02, 0xA8, 0x60, 0x00, 0xF0, 0x00, 0x03, 0x5C, 0x60, 0x00, 0x10, 0x00, 0x06, 0x99, 0x60, 0x00,
0x10, 0x00, 0x10, 0x3B, 0x60, 0x00, 0x10, 0x00, 0x15, 0x06, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x17, 0xB2, 0x60, 0x08, 0xF0, 0x00, 0x55, 0x04, 0x60, 0x00, 0xF0, 0x00, 0x00, 0x03, 0x60, 0x00,
0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x17, 0xB4, 0x60, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x60, 0x00,
0xF0, 0x00, 0x70, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x70, 0x00, 0xD0, 0x08
]
tef_205_patch_lut = [
0x80, 0x17, 0x80, 0x45, 0x80, 0x96, 0x81, 0x5B, 0x82, 0xD6, 0x83, 0x76, 0x88, 0x0B, 0x88, 0x10, 0x88, 0xDB, 0x89, 0x48, 0x89, 0xE9, 0x8B, 0x0A,
0x8B, 0x12, 0x8B, 0x13, 0x8B, 0x21, 0x8B, 0x26, 0x8C, 0x6F, 0x8F, 0x91, 0x8F, 0xF6, 0x94, 0xD0, 0x95, 0x20, 0x95, 0x33, 0x95, 0x6F, 0x95, 0xA8,
0x95, 0xAC, 0x95, 0xC3, 0x95, 0xE1, 0x97, 0xC9, 0x97, 0xF6, 0x98, 0x8D, 0x99, 0x00, 0x9A, 0x00, 0x9E, 0x73, 0xA0, 0x12, 0xA1, 0x03, 0xA1, 0x68,
0xA2, 0xF0, 0xA3, 0x0D, 0xA3, 0x4C, 0xA3, 0x52, 0xA3, 0xED, 0xA5, 0x20, 0xA5, 0x25, 0xA6, 0x0F, 0xA6, 0x1D, 0xA8, 0x31, 0xAB, 0x01, 0xAB, 0x1F,
0xAB, 0x4C, 0xAC, 0x76, 0xAC, 0x88, 0xAC, 0x97, 0xAD, 0xB0, 0xAD, 0xB7, 0xAD, 0xB8, 0xB0, 0x55, 0xB0, 0xC6, 0xB0, 0xE2, 0xB1, 0x01, 0xB1, 0x0B,
0xB1, 0x35, 0xB1, 0x3B, 0xB1, 0x97, 0xB3, 0x03
]

View File

@@ -4,7 +4,7 @@ from protocol import I2CPCClient
p = I2CPCClient("COM17") p = I2CPCClient("COM17")
print(p._send_packet(bytes([4]))) print(p._send_packet(bytes([4])))
tef = TEF6686(p) tef = TEF6686(p)
tef.init() tef.init(clock=12000000)
tef.AM_Tune_To(1, 225) tef.AM_Tune_To(1, 225)
tef.AUDIO_Set_Mute(False) tef.AUDIO_Set_Mute(False)
tef.AUDIO_Set_Volume(70) tef.AUDIO_Set_Volume(70)

53
xrd.py
View File

@@ -13,6 +13,7 @@ from protocol import I2CPCClient
HOST = '0.0.0.0' HOST = '0.0.0.0'
PORT = 7373 PORT = 7373
PASSWORD = "test" PASSWORD = "test"
CLOCK = 12000000 # DP-666
SALT_LENGTH = 16 SALT_LENGTH = 16
SS_UPDATE_INTERVAL = 0.125 SS_UPDATE_INTERVAL = 0.125
@@ -25,15 +26,16 @@ def compute_hash(salt, password):
return hashlib.sha1((salt + password).encode()).hexdigest().encode() return hashlib.sha1((salt + password).encode()).hexdigest().encode()
def init_tef(): def init_tef():
p = I2CPCClient("COM17") p = I2CPCClient("COM6")
tef = TEF6686(p) tef = TEF6686(p)
tef.init() tef.init(clock=CLOCK)
tef.AUDIO_Set_Mute(False) tef.AUDIO_Set_Mute(False)
tef.AUDIO_Set_Volume(60) tef.AUDIO_Set_Volume(60)
tef.FM_Tune_To(1, 9500) tef.FM_Tune_To(1, 9500)
tef.FM_Set_RDS(1) tef.FM_Set_RDS(1)
tef.FM_Set_ChannelEqualizer(True) tef.FM_Set_ChannelEqualizer(True)
tef.FM_Set_MphSuppression(True) tef.FM_Set_MphSuppression(True)
tef.APPL_Set_OperationMode(True)
return tef return tef
def authenticate(conn): def authenticate(conn):
@@ -46,7 +48,7 @@ def authenticate(conn):
if not data: return False if not data: return False
if data.strip() == expected_hash.strip(): return True if data.strip() == expected_hash.strip(): return True
def process_command(tef: TEF6686, data: bytes, state): def process_command(tef: TEF6686, data: bytes, state: dict, conn: socket.socket):
out = b"" out = b""
for cmd in data.splitlines(): for cmd in data.splitlines():
if cmd.startswith(b"T"): if cmd.startswith(b"T"):
@@ -67,22 +69,52 @@ def process_command(tef: TEF6686, data: bytes, state):
out += f"B{int(mono)}\n".encode() out += f"B{int(mono)}\n".encode()
elif cmd.startswith(b"D"): elif cmd.startswith(b"D"):
deemp = int(cmd.decode().removeprefix("D").strip()) deemp = int(cmd.decode().removeprefix("D").strip())
time = 500 if deemp == 0 else (750 if deemp == 1 else 0) dtime = 500 if deemp == 0 else (750 if deemp == 1 else 0)
state['deemp'] = deemp state['deemp'] = deemp
tef.FM_Set_Deemphasis(time) tef.FM_Set_Deemphasis(dtime)
out += f"D{deemp}\n".encode() out += f"D{deemp}\n".encode()
elif cmd.startswith(b"x"): elif cmd.startswith(b"x"):
out += b"OK\n" out += b"OK\n"
tef.APPL_Set_OperationMode(False)
elif cmd.startswith(b"X"):
tef.APPL_Set_OperationMode(True)
elif cmd.startswith(b"W"): elif cmd.startswith(b"W"):
bw = int(cmd.decode().removeprefix("W").strip()) bw = int(cmd.decode().removeprefix("W").strip())
auto = (bw == 0) auto = (bw == 0)
tef.FM_Set_Bandwidth(auto, 2360 if auto else (bw // 100)) tef.FM_Set_Bandwidth(auto, 2360 if auto else (bw // 100))
state['bw'] = bw state['bw'] = bw
out += f"W{bw}\n".encode() out += f"W{bw}\n".encode()
elif cmd.startswith(b"?"):
out += b"XRD Python driver\n"
elif cmd.startswith(b"S"):
cmd = cmd[1:]
if cmd != b"":
arg = int(cmd.decode()[1:].strip())
match cmd[0]:
case 97: state['scan_start'] = (arg + 5) // 10
case 98: state['scan_stop'] = (arg + 5) // 10
case 99: state['scan_step'] = (arg + 5) // 10
case 119: state['scan_bw'] = arg
else:
tef.FM_Set_Bandwidth((state["scan_bw"] == 0), state["scan_bw"])
conn.sendall(b"U")
for freq in range(state["scan_start"], state["scan_stop"] + state["scan_step"], state["scan_step"]):
tef.FM_Tune_To(2, freq)
time.sleep(0.0055)
conn.sendall(str(freq * 10).encode())
conn.sendall(b" = ")
_, level, *_ = tef.FM_Get_Quality_Data()
if level is None: continue
conn.sendall(str((level // 10) + 10).encode())
conn.sendall(b", ")
conn.sendall(b"\n")
tef.FM_Tune_To(1, state["last_tune"])
tef.FM_Set_Bandwidth((state["bw"] == 0), 2360 if (state["bw"] == 0) else (state["bw"] // 100))
return out return out
def send_signal_status(tef: TEF6686, conn, state): def send_signal_status(tef: TEF6686, conn: socket.socket, state):
_, _, stereo, _ = tef.FM_Get_Processing_Status() _, _, stereo, _ = tef.FM_Get_Processing_Status()
stereo = stereo if stereo is not None else 1000 stereo = stereo if stereo is not None else 1000
@@ -132,7 +164,11 @@ def run_server():
'last_eqims': 0b11, 'last_eqims': 0b11,
'forced_mono': False, 'forced_mono': False,
'deemp': 0, 'deemp': 0,
'bw': 0 'bw': 0,
'scan_start': 87500,
'scan_stop': 108000,
'scan_step': 100,
'scan_bw': 0,
} }
try: try:
@@ -164,9 +200,10 @@ def run_server():
try: try:
data = conn.recv(1024) data = conn.recv(1024)
if not data: break if not data: break
resp = process_command(tef, data, state) resp = process_command(tef, data, state, conn)
if resp: conn.sendall(resp) if resp: conn.sendall(resp)
except ConnectionResetError: break except ConnectionResetError: break
except ConnectionAbortedError: break
except BlockingIOError: except BlockingIOError:
if ss_timer.get_time() > SS_UPDATE_INTERVAL: if ss_timer.get_time() > SS_UPDATE_INTERVAL:
send_signal_status(tef, conn, state) send_signal_status(tef, conn, state)