diff --git a/base_tef.py b/base_tef.py index 48bc606..ac96d46 100644 --- a/base_tef.py +++ b/base_tef.py @@ -1,5 +1,6 @@ from protocol import I2CPCClient, time from tef_102_patch import * +from tef_205_patch import * from typing import Callable, TypeVar, ParamSpec, Concatenate from collections.abc import Callable as ABCCallable @@ -11,25 +12,27 @@ ADDRESS = 0x64 class BaseTEF668X: def __init__(self, p: I2CPCClient) -> None: self.p = p - p.set_baudrate(1500000) - self.p.set_clock(400_000) + p.set_baudrate(921600) + self.p.set_clock(100_000) def close(self): self.p.set_baudrate(115200) self.p.close() def _reset(self): self.p.write_i2c(ADDRESS, b"\x1e\x5a\x01\x5a\x5a") 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\x74") def send_patch(_patch: bytes): - for i in range(0, len(_patch), 24): - data = _patch[i:i+24] + for i in range(0, len(_patch), 64): + data = _patch[i:i+64] if self.p.write_i2c(ADDRESS, b"\x1b" + data)[0] != 0: raise Exception send_patch(bytes(patch)) self.p.write_i2c(ADDRESS, b"\x1c\x00\x00") self.p.write_i2c(ADDRESS, b"\x1c\x00\x75") send_patch(bytes(patch_lut)) self.p.write_i2c(ADDRESS, b"\x1c\x00\x00") + self.p.set_clock(100_000) def APPL_Get_Operation_Status(self): data = self.p.write_read_i2c(ADDRESS, b"\x40\x80\x01", 2) @@ -55,12 +58,12 @@ class BaseTEF668X: def APPL_Activate(self): 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() 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") 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() while self.APPL_Get_Operation_Status() != 2: time.sleep(0.01) \ No newline at end of file diff --git a/protocol.py b/protocol.py index 1e6240e..eaab92f 100644 --- a/protocol.py +++ b/protocol.py @@ -1,6 +1,7 @@ import serial import struct import time +import time def crc8(data: bytes) -> int: crc = 0x00 @@ -15,13 +16,16 @@ class I2CPCClient: def __init__(self, port, baudrate=115200, timeout=1): self.ser = serial.Serial(port=port, baudrate=baudrate, timeout=timeout) - # Gurantees resync self.ser.write(b"~/") - self.ser.write(b"\x00"*64) + self.ser.write(b"\x00"*128) self.ser.flush() self.ser.write(b"~/") 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): if len(payload) > 127: raise ValueError("Payload too large") diff --git a/tef.py b/tef.py index 1b57b31..af42f86 100644 --- a/tef.py +++ b/tef.py @@ -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 functools import wraps +P = ParamSpec("P") T = TypeVar("T") @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 -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( - func: Callable[Concatenate["TEF6686", P], tuple[bytes, int | None, Callable[[bytes], T] | None], ]) -> Callable[Concatenate["TEF6686", P], bytes | T]: +def _command_wrapper(func: Callable[Concatenate[TEF6686, P], tuple[bytes, int | None, Callable[[bytes], T] | None], ]) -> Callable[Concatenate[TEF6686, P], bytes | T]: @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) if read_bytes: data = self.p.write_read_i2c(ADDRESS, data, read_bytes) diff --git a/tef_102_patch.py b/tef_102_patch.py index 8d473ef..e182a07 100644 --- a/tef_102_patch.py +++ b/tef_102_patch.py @@ -1,3 +1,5 @@ +# p2.24 + 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, 0x77, 0xD0, 0x80, 0xF0, 0x00, 0x38, 0x7B, 0xDF, 0x80, 0x80, 0xFC, 0x39, 0x0E, 0xD0, 0x80, 0xC2, 0x38, 0x20, 0x11, 0x40, 0xB7, diff --git a/tef_205_patch.py b/tef_205_patch.py new file mode 100644 index 0000000..9c9445d --- /dev/null +++ b/tef_205_patch.py @@ -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 +] \ No newline at end of file diff --git a/test.py b/test.py index 95e209a..118c37a 100644 --- a/test.py +++ b/test.py @@ -4,7 +4,7 @@ from protocol import I2CPCClient p = I2CPCClient("COM17") print(p._send_packet(bytes([4]))) tef = TEF6686(p) -tef.init() +tef.init(clock=12000000) tef.AM_Tune_To(1, 225) tef.AUDIO_Set_Mute(False) tef.AUDIO_Set_Volume(70) diff --git a/xrd.py b/xrd.py index 7879164..2f8625e 100644 --- a/xrd.py +++ b/xrd.py @@ -13,6 +13,7 @@ from protocol import I2CPCClient HOST = '0.0.0.0' PORT = 7373 PASSWORD = "test" +CLOCK = 12000000 # DP-666 SALT_LENGTH = 16 SS_UPDATE_INTERVAL = 0.125 @@ -25,15 +26,16 @@ def compute_hash(salt, password): return hashlib.sha1((salt + password).encode()).hexdigest().encode() def init_tef(): - p = I2CPCClient("COM17") + p = I2CPCClient("COM6") tef = TEF6686(p) - tef.init() + tef.init(clock=CLOCK) tef.AUDIO_Set_Mute(False) tef.AUDIO_Set_Volume(60) tef.FM_Tune_To(1, 9500) tef.FM_Set_RDS(1) tef.FM_Set_ChannelEqualizer(True) tef.FM_Set_MphSuppression(True) + tef.APPL_Set_OperationMode(True) return tef def authenticate(conn): @@ -46,7 +48,7 @@ def authenticate(conn): if not data: return False 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"" for cmd in data.splitlines(): if cmd.startswith(b"T"): @@ -67,22 +69,52 @@ def process_command(tef: TEF6686, data: bytes, state): out += f"B{int(mono)}\n".encode() elif cmd.startswith(b"D"): 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 - tef.FM_Set_Deemphasis(time) + tef.FM_Set_Deemphasis(dtime) out += f"D{deemp}\n".encode() elif cmd.startswith(b"x"): out += b"OK\n" + tef.APPL_Set_OperationMode(False) + elif cmd.startswith(b"X"): + tef.APPL_Set_OperationMode(True) elif cmd.startswith(b"W"): bw = int(cmd.decode().removeprefix("W").strip()) auto = (bw == 0) tef.FM_Set_Bandwidth(auto, 2360 if auto else (bw // 100)) state['bw'] = bw 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 -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 = stereo if stereo is not None else 1000 @@ -132,7 +164,11 @@ def run_server(): 'last_eqims': 0b11, 'forced_mono': False, 'deemp': 0, - 'bw': 0 + 'bw': 0, + 'scan_start': 87500, + 'scan_stop': 108000, + 'scan_step': 100, + 'scan_bw': 0, } try: @@ -164,9 +200,10 @@ def run_server(): try: data = conn.recv(1024) if not data: break - resp = process_command(tef, data, state) + resp = process_command(tef, data, state, conn) if resp: conn.sendall(resp) except ConnectionResetError: break + except ConnectionAbortedError: break except BlockingIOError: if ss_timer.get_time() > SS_UPDATE_INTERVAL: send_signal_status(tef, conn, state)