From 3b0e00d24e2161b94df8982e25c2e8df13ae161d Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 23 Mar 2017 12:38:58 -0400 Subject: [PATCH 01/50] Added New Options Added GetUID, DumpMFU, Identify, LButton_Long and RButton_Long. --- Software/Chameleon/Device.py | 76 ++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/Software/Chameleon/Device.py b/Software/Chameleon/Device.py index 57169c7..556e985 100644 --- a/Software/Chameleon/Device.py +++ b/Software/Chameleon/Device.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import serial import serial.tools.list_ports @@ -13,15 +13,20 @@ class Device: COMMAND_DOWNLOAD = "DOWNLOAD" COMMAND_SETTING = "SETTING" COMMAND_UID = "UID" + COMMAND_GETUID = "GETUID" + COMMAND_IDENTIFY = "IDENTIFY" + COMMAND_DUMPMFU = "DUMP_MFU" COMMAND_CONFIG = "CONFIG" COMMAND_LOG_DOWNLOAD = "LOGDOWNLOAD" COMMAND_LOG_CLEAR = "LOGCLEAR" COMMAND_LOGMODE = "LOGMODE" COMMAND_LBUTTON = "LBUTTON" + COMMAND_LBUTTONLONG = "LBUTTON_LONG" COMMAND_RBUTTON = "RBUTTON" + COMMAND_RBUTTONLONG = "RBUTTON_LONG" COMMAND_GREEN_LED = "LEDGREEN" COMMAND_RED_LED = "LEDRED" - + STATUS_CODE_OK = 100 STATUS_CODE_OK_WITH_TEXT = 101 STATUS_CODE_WAITING_FOR_XMODEM = 110 @@ -49,33 +54,32 @@ class Device: SUGGEST_CHAR = "?" SET_CHAR = "=" GET_CHAR = "?" - + def __init__(self, verboseFunc = None): self.verboseFunc = verboseFunc self.serial = serial.Serial(None, 9600, timeout=5.0) self.versionString = "" self.supportedConfs = [] - + def verboseLog(self, text): if (self.verboseFunc): self.verboseFunc(text) - + def listDevices(): devices = [] for port in serial.tools.list_ports.grep("({0:04x}:{1:04x})|({0:04X}:{1:04X})".format(Chameleon.USB_VID, Chameleon.USB_PID)): devices.append(port[0]) - return devices - - def connect(self, comport): + return devices + def connect(self, comport): self.serial.port = comport try: self.serial.open() except: pass - + if (self.serial.isOpen()): # Send escape key to force clearing the Chameleon's input buffer self.serial.write(b"\x1B") @@ -94,20 +98,20 @@ class Device: return False result = self.getCmdSuggestions(self.COMMAND_CONFIG) - + if (result['statusCode'] == self.STATUS_CODE_OK_WITH_TEXT): self.supportedConfs = result['response'].split(",") else: return False else: return False - + return True - + def disconnect(self): self.verboseLog("Closing serial port") self.serial.close() - + def isConnected(self): return self.serial.isOpen() @@ -116,7 +120,7 @@ class Device: data = self.serial.read(size) self.serial.timeout = 5.0 return data - + def writeCmd(self, cmd): # Execute command cmdLine = cmd + self.LINE_ENDING @@ -130,19 +134,19 @@ class Device: return None else: self.verboseLog("Executing <{}>: {}".format(cmd, status)) - + statusCode, statusText = status.split(":") statusCode = int(statusCode) - + result = {'statusCode': statusCode, 'statusText': statusText, 'response': None} - + if (statusCode == self.STATUS_CODE_OK_WITH_TEXT): result['response'] = self.readResponse() elif (statusCode == self.STATUS_CODE_TRUE): result['response'] = True elif (statusCode == self.STATUS_CODE_FALSE): result['response'] = False - + return result def readResponse(self): @@ -150,27 +154,30 @@ class Device: response = self.serial.readline().decode('ascii').rstrip() self.verboseLog("Response: {}".format(response)) return response - + def execCmd(self, cmd, args=None): if (args is None): return self.writeCmd("{}".format(cmd)) else: return self.writeCmd("{} {}".format(cmd, args)) - + def getSetCmd(self, cmd, arg=None): # Determine if set or get mode if (arg is None): return self.writeCmd("{}{}".format(cmd, self.GET_CHAR)) else: return self.writeCmd("{}{}{}".format(cmd, self.SET_CHAR, arg)) - + + def returnCmd(self, cmd, arg=None): + return self.writeCmd("{}".format(cmd)) + def getCmdSuggestions(self, cmd): result = self.getSetCmd(cmd, self.SUGGEST_CHAR) if (result['response'] is not None): result['suggestions'] = result['response'].split(",") return result - + def cmdUploadDump(self, dataStream): if (self.execCmd(self.COMMAND_UPLOAD)['statusCode'] == self.STATUS_CODE_WAITING_FOR_XMODEM): # XMODEM started @@ -201,7 +208,7 @@ class Device: def cmdLogMode(self, newLogMode): return self.getSetCmd(self.COMMAND_LOGMODE, newLogMode) - + def cmdVersion(self): return self.getSetCmd(self.COMMAND_VERSION) @@ -211,6 +218,15 @@ class Device: def cmdUID(self, newUID = None): return self.getSetCmd(self.COMMAND_UID, newUID) + def cmdGetUID(self): + return self.returnCmd(self.COMMAND_GETUID) + + def cmdIdentify(self): + return self.returnCmd(self.COMMAND_IDENTIFY) + + def cmdDumpMFU(self): + return self.returnCmd(self.COMMAND_DUMPMFU) + def cmdConfig(self, newConfig = None): if (newConfig == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_CONFIG) @@ -223,18 +239,30 @@ class Device: else: return self.getSetCmd(self.COMMAND_LBUTTON, newAction) + def cmdLButtonLong(self, newAction = None): + if (newAction == self.SUGGEST_CHAR): + return self.getCmdSuggestions(self.COMMAND_LBUTTONLONG) + else: + return self.getSetCmd(self.COMMAND_LBUTTONLONG, newAction) + def cmdRButton(self, newAction = None): if (newAction == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_RBUTTON) else: return self.getSetCmd(self.COMMAND_RBUTTON, newAction) + def cmdRButtonLong(self, newAction = None): + if (newAction == self.SUGGEST_CHAR): + return self.getCmdSuggestions(self.COMMAND_RBUTTONLONG) + else: + return self.getSetCmd(self.COMMAND_RBUTTONLONG, newAction) + def cmdGreenLED(self, newFunction = None): if (newFunction == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_GREEN_LED) else: return self.getSetCmd(self.COMMAND_GREEN_LED, newFunction) - + def cmdRedLED(self, newFunction = None): if (newFunction == self.SUGGEST_CHAR): return self.getCmdSuggestions(self.COMMAND_RED_LED) From ce87f0a4ff3379d7bacf51cfcef18f28f54e74bb Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 23 Mar 2017 12:42:15 -0400 Subject: [PATCH 02/50] Added Options Added GetUID, DumpMFU, Identify, LButton_Long and RButton_Long. --- Software/chamtool.py | 83 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/Software/chamtool.py b/Software/chamtool.py index 6f97a96..afab402 100755 --- a/Software/chamtool.py +++ b/Software/chamtool.py @@ -11,8 +11,8 @@ import datetime def verboseLog(text): formatString = "[{}] {}" timeString = datetime.datetime.utcnow() - print(formatString.format(timeString, text), file=sys.stderr) - + print(formatString.format(timeString, text), sys.stderr) + # Command funcs def cmdInfo(chameleon, arg): return "{}".format(chameleon.cmdVersion()['response']) @@ -27,11 +27,11 @@ def cmdSetting(chameleon, arg): return "Setting has been changed to {}".format(chameleon.cmdSetting()['response']) else: return "Change setting to {} failed: {}".format(arg, result['statusText']) - return - + return + def cmdUID(chameleon, arg): result = chameleon.cmdUID(arg) - + if (arg is None): return "{}".format(result['response']) else: @@ -40,8 +40,17 @@ def cmdUID(chameleon, arg): else: return "Setting UID to {} failed: {}".format(arg, result['statusText']) +def cmdGetUID(chameleon, arg): + return "{}".format(chameleon.cmdGetUID()['response']) + +def cmdIdentify(chameleon, arg): + return "{}".format(chameleon.cmdIdentify()['response']) + +def cmdDumpMFU(chameleon, arg): + return "{}".format(chameleon.cmdDumpMFU()['response']) + def cmdConfig(chameleon, arg): - result = chameleon.cmdConfig(arg) + result = chameleon.cmdConfig(chameleon, arg) if (arg is None): return "Current configuration: {}".format(result['response']) @@ -62,7 +71,7 @@ def cmdDownload(chameleon, arg): with open(arg, 'wb') as fileHandle: bytesReceived = chameleon.cmdDownloadDump(fileHandle) return "{} Bytes successfully written to {}".format(bytesReceived, arg) - + def cmdLog(chameleon, arg): with open(arg, 'wb') as fileHandle: bytesReceived = chameleon.cmdDownloadLog(fileHandle) @@ -70,7 +79,7 @@ def cmdLog(chameleon, arg): def cmdLButton(chameleon, arg): result = chameleon.cmdLButton(arg) - + if (arg is None): return "Current left button action: {}".format(result['response']) else: @@ -81,9 +90,22 @@ def cmdLButton(chameleon, arg): else: return "Setting left button action to {} failed: {}".format(arg, result['statusText']) +def cmdLButtonLong(chameleon, arg): + result = chameleon.cmdLButtonLong(arg) + + if (arg is None): + return "Current long press left button action: {}".format(result['response']) + else: + if (arg == chameleon.SUGGEST_CHAR): + return "Possible long press left button actions: {}".format(", ".join(result['suggestions'])) + elif (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "Long press left button action has been set to {}".format(chameleon.cmdLButtonLong()['response']) + else: + return "Setting long press left button action to {} failed: {}".format(arg, result['statusText']) + def cmdRButton(chameleon, arg): result = chameleon.cmdRButton(arg) - + if (arg is None): return "Current right button action: {}".format(result['response']) else: @@ -94,9 +116,22 @@ def cmdRButton(chameleon, arg): else: return "Setting right button action to {} failed: {}".format(arg, result['statusText']) +def cmdRButtonLong(chameleon, arg): + result = chameleon.cmdRButtonLong(arg) + + if (arg is None): + return "Current long press right button action: {}".format(result['response']) + else: + if (arg == chameleon.SUGGEST_CHAR): + return "Possible long press right button actions: {}".format(", ".join(result['suggestions'])) + elif (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "Long press right button action has been set to {}".format(chameleon.cmdRButtonLong()['response']) + else: + return "Setting long press right button action to {} failed: {}".format(arg, result['statusText']) + def cmdGreenLED(chameleon, arg): result = chameleon.cmdGreenLED(arg) - + if (arg is None): return "Current green LED function: {}".format(result['response']) else: @@ -109,7 +144,7 @@ def cmdGreenLED(chameleon, arg): def cmdRedLED(chameleon, arg): result = chameleon.cmdRedLED(arg) - + if (arg is None): return "Current red LED function: {}".format(result['response']) else: @@ -119,7 +154,7 @@ def cmdRedLED(chameleon, arg): return "Red LED function has been set to {}".format(chameleon.cmdRedLED()['response']) else: return "Setting red LED function to {} failed: {}".format(arg, result['statusText']) - + # Custom class for argparse class CmdListAction(argparse.Action): def __init__(self, option_strings, dest, default=False, required=False, @@ -127,19 +162,19 @@ class CmdListAction(argparse.Action): super(CmdListAction, self).__init__( option_strings=option_strings, dest=dest, nargs=nargs, const=const, default=default, required=required, help=help, metavar=metavar, type=type, choices=choices) - + def __call__(self, parser, namespace, values, option_string=None): # Create new attribute cmdList if not exist and append command to list if not hasattr(namespace, "cmdList"): setattr(namespace, "cmdList", []) - + namespace.cmdList.append([self.dest, values]) def main(): argParser = argparse.ArgumentParser(description="Controls the Chameleon through the command line") argParser.add_argument("-v", "--verbose", dest="verbose", action="store_true", default=0, help="output verbose") argParser.add_argument("-p", "--port", dest="port", metavar="COMPORT", help="specify device's comport") - + # Add the commands using custom action that populates a list in the order the arguments are given cmdArgGroup = argParser.add_argument_group(title="Chameleon commands", description="These arguments can appear multiple times and are executed in the order they are given on the command line. " "Some of these arguments can be used with '" + Chameleon.Device.SUGGEST_CHAR + "' as parameter to get a list of suggestions.") @@ -149,13 +184,18 @@ def main(): cmdArgGroup.add_argument("-i", "--info", dest="info", action=CmdListAction, nargs=0, help="retrieve the version information") cmdArgGroup.add_argument("-s", "--setting", dest="setting", action=CmdListAction, nargs='?', type=int, choices=Chameleon.VALID_SETTINGS, help="retrieve or set the current setting") cmdArgGroup.add_argument("-U", "--uid", dest="uid", action=CmdListAction, nargs='?', help="retrieve or set the current UID") + cmdArgGroup.add_argument("-gu", "--getuid", dest="getuid", action=CmdListAction, nargs='?', help="retrieve UID of device in range") + cmdArgGroup.add_argument("-I", "--identify", dest="identify", action=CmdListAction, nargs='?', help="identify device in range") + cmdArgGroup.add_argument("-D", "--dumpmfu", dest="dumpmfu", action=CmdListAction, nargs='?', help="dump information about card in range") cmdArgGroup.add_argument("-c", "--config", dest="config", action=CmdListAction, metavar="CFGNAME", nargs='?', help="retrieve or set the current configuration") cmdArgGroup.add_argument("-lb", "--lbutton", dest="lbutton", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current left button action") + cmdArgGroup.add_argument("-lbl", "--lbuttonlong", dest="lbutton_long", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current left button long press action") cmdArgGroup.add_argument("-rb", "--rbutton", dest="rbutton", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current right button action") + cmdArgGroup.add_argument("-rbl", "--rbuttonlong", dest="rbutton_long", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current right button long press action") cmdArgGroup.add_argument("-gl", "--gled", dest="gled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current green led function") cmdArgGroup.add_argument("-rl", "--rled", dest="rled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current red led function") args = argParser.parse_args() - + if (args.verbose): verboseFunc = verboseLog else: @@ -163,7 +203,7 @@ def main(): # Instantiate device object and connect chameleon = Chameleon.Device(verboseFunc) - + if (args.port): if (chameleon.connect(args.port)): # Generate a jumptable and execute all commands in the order they are given on the command line @@ -171,11 +211,16 @@ def main(): "setting" : cmdSetting, "info" : cmdInfo, "uid" : cmdUID, + "getuid" : cmdGetUID, + "identify" : cmdIdentify, + "dumpmfu" : cmdDumpMFU, "config" : cmdConfig, "upload" : cmdUpload, "download" : cmdDownload, "log" : cmdLog, "lbutton" : cmdLButton, + "lbutton_long" : cmdLButtonLong, + "rbutton_long" : cmdRButtonLong, "rbutton" : cmdRButton, "gled" : cmdGreenLED, "rled" : cmdRedLED, @@ -197,9 +242,9 @@ def main(): print("List of potential Chameleons connected to the system:") for port in Chameleon.Device.listDevices(): print(port) - + sys.exit(0) - + if __name__ == "__main__": main() From 42ea0bf3c7529a3b97e05280dcbe3696e0773b32 Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 23 Mar 2017 16:32:58 -0400 Subject: [PATCH 03/50] Update chamtool.py --- Software/chamtool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/chamtool.py b/Software/chamtool.py index afab402..7bb9da3 100755 --- a/Software/chamtool.py +++ b/Software/chamtool.py @@ -50,7 +50,7 @@ def cmdDumpMFU(chameleon, arg): return "{}".format(chameleon.cmdDumpMFU()['response']) def cmdConfig(chameleon, arg): - result = chameleon.cmdConfig(chameleon, arg) + result = chameleon.cmdConfig(arg) if (arg is None): return "Current configuration: {}".format(result['response']) From 5b46650edded2d8119c384bbde475593b24e3598 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 26 Jun 2018 23:46:36 +0100 Subject: [PATCH 04/50] Set up framework for sniffing (cherry picked from commit 8a0b331) --- Firmware/Chameleon-Mini/Codec/Codec.h | 3 +++ .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 25 +++++++++++++++++++ .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 19 ++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c create mode 100644 Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index cf9d67d..0a74d25 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -17,6 +17,7 @@ #include "ISO14443-2A.h" #include "Reader14443-2A.h" +#include "SniffISO14443-2A.h" /* Timing definitions for ISO14443A */ #define ISO14443A_SUBCARRIER_DIVIDER 16 @@ -231,6 +232,7 @@ INLINE void CodecSetLoadmodState(bool bOnOff) { } } +// Turn on and off the codec Reader field INLINE void CodecSetReaderField(bool bOnOff) { // this is the function for turning on/off the reader field dumbly; before using this function, please consider to use CodecReaderField{Start,Stop} if (bOnOff) { @@ -244,6 +246,7 @@ INLINE void CodecSetReaderField(bool bOnOff) { // this is the function for turni } } +// Get the status of the reader field INLINE bool CodecGetReaderField(void) { return (CODEC_READER_TIMER.CTRLA == TC_CLKSEL_DIV1_gc) && (AWEXC.OUTOVEN == CODEC_READER_MASK); } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c new file mode 100644 index 0000000..9e98f0d --- /dev/null +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -0,0 +1,25 @@ +// +// Created by Zitai Chen on 05/07/2018. +// + +#include "SniffISO14443-2A.h" + +#include "Reader14443-2A.h" +#include "Codec.h" +#include "../System.h" +#include "../Application/Application.h" +#include "LEDHook.h" +#include "Terminal/Terminal.h" +#include + + +void Sniff14443ACodecInit(void){ + +} + +void Sniff14443ACodecDeInit(void) { + +} +void Sniff14443ACodecTask(void) +{ +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h new file mode 100644 index 0000000..eb0317a --- /dev/null +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -0,0 +1,19 @@ +// +// Created by 陈子泰 on 05/07/2018. +// + +#ifndef CHAMELEON_MINI_SNIFFISO14443_2A_H +#define CHAMELEON_MINI_SNIFFISO14443_2A_H + + +#include "Codec.h" +#include "Terminal/CommandLine.h" + +/* Codec Interface */ +void Sniff14443ACodecInit(void); +void Sniff14443ACodecDeInit(void); +void Sniff14443ACodecTask(void); + + + +#endif //CHAMELEON_MINI_SNIFFISO14443_2A_H From 38b7ea459a83b78578383710616c1f0686b59b5c Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 26 Jun 2018 23:56:25 +0100 Subject: [PATCH 05/50] Add some comments for better understanding (cherry picked from commit df39123) --- Firmware/Chameleon-Mini/Application/Reader14443A.c | 1 + Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 8 ++++++-- Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.c b/Firmware/Chameleon-Mini/Application/Reader14443A.c index b865df8..471dc30 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.c +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.c @@ -141,6 +141,7 @@ uint16_t addParityBits(uint8_t * Buffer, uint16_t BitCount) uint16_t removeParityBits(uint8_t * Buffer, uint16_t BitCount) { + // Short frame, no parity bit is added if (BitCount == 7) return 7; diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index e43ea61..ebf565b 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -66,8 +66,8 @@ static void StartDemod(void) { StateRegister = DEMOD_DATA_BIT; /* Configure sampling-timer free running and sync to first modulation-pause. */ - CODEC_TIMER_SAMPLING.CNT = 0; - CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; + CODEC_TIMER_SAMPLING.CNT = 0; // Reset the timer count + CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; // Set Period regisiter CODEC_TIMER_SAMPLING.CCA = 0xFFFF; /* CCA Interrupt is not active! */ CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; @@ -79,6 +79,7 @@ static void StartDemod(void) { CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0; } +// Find first pause and start sampling ISR(CODEC_DEMOD_IN_INT0_VECT) { /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start @@ -112,6 +113,7 @@ ISR(CODEC_DEMOD_IN_INT0_VECT) { CODEC_DEMOD_IN_PORT.INT0MASK = 0; } +// Sampling with timer and demod ISR(CODEC_TIMER_SAMPLING_CCA_VECT) { /* This interrupt gets called twice for every bit to sample it. */ uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; @@ -220,6 +222,7 @@ ISR(CODEC_TIMER_SAMPLING_CCA_VECT) { CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; } +// Enumulate as a card to send card responds ISR(CODEC_TIMER_LOADMOD_OVF_VECT) { /* Bit rate timer. Output a half bit on the output. */ @@ -418,6 +421,7 @@ void ISO14443ACodecTask(void) { uint16_t AnswerBitCount = ISO14443A_APP_NO_RESPONSE; if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + // For logging data LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S b/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S index f41b045..82ba110 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S @@ -15,6 +15,7 @@ #define AWEXC__OUTOVEN 0x088C #define CODEC_READER_TIMER__CTRLA 0x0800 +; For sending reader bits to cards .global TCD0_CCB_vect, Reader14443AMillerEOC TCD0_CCB_vect: push Zero ; 1 From fd57c63ba85d9f0de9c72f42e2810e218ddd9ada Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sat, 7 Jul 2018 00:16:18 +0100 Subject: [PATCH 06/50] Work in Card->Reader direction only, WIP (cherry picked from commit 9ce138c) --- .../Chameleon-Mini/Codec/Reader14443-2A.c | 198 +++++++++++++----- .../Chameleon-Mini/Codec/Reader14443-2A.h | 1 + .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 9 +- Firmware/Chameleon-Mini/Configuration.c | 6 +- Firmware/Chameleon-Mini/Makefile | 2 +- 5 files changed, 156 insertions(+), 60 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 6a70968..9192c1f 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -50,6 +50,7 @@ void Reader14443ACodecInit(void) { CodecInitCommon(); CodecSetDemodPower(true); + CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; CODEC_TIMER_SAMPLING.CCB = 0; CODEC_TIMER_SAMPLING.CCC = 0; @@ -66,9 +67,11 @@ void Reader14443ACodecInit(void) { Flags.RxDone = false; } + + void Reader14443ACodecDeInit(void) { CodecSetDemodPower(false); - CodecReaderFieldStop(); + // CodecReaderFieldStop(); CODEC_TIMER_SAMPLING.CTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = 0; @@ -94,8 +97,11 @@ INLINE void Insert1(void) *CodecBufferPtr++ = SampleRegister; } + +// End of Card-> reader communication and enter frame delay time INLINE void Reader14443A_EOC(void) { + CODEC_TIMER_LOADMOD.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; @@ -128,6 +134,7 @@ INLINE void Reader14443A_EOC(void) INLINE void BufferToSequence(void) { + uint16_t count = BitCount; if (count > BITS_PER_BYTE * CODEC_BUFFER_SIZE / 2) // todo is this correct? return; @@ -138,6 +145,7 @@ INLINE void BufferToSequence(void) uint8_t * Buffer = CodecBuffer + CODEC_BUFFER_SIZE / 2; CodecBufferPtr = CodecBuffer; + // Modified Miller Coding ISO14443-2 8.1.3 Insert1(); // SOC Insert0(); @@ -175,12 +183,14 @@ INLINE void BufferToSequence(void) if (BitCount % 8) CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); } - +// Frame Delay Time PCD to PICC ends ISR (TCD0_CCC_vect) { + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; + /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause * needs to be found. */ @@ -192,6 +202,7 @@ ISR (TCD0_CCC_vect) SampleRegister = 0x00; RxPendingSince = SystemGetSysTick(); + Flags.RxPending = true; // reset for future use @@ -202,8 +213,11 @@ ISR (TCD0_CCC_vect) PORTE.OUTTGL = PIN3_bm; } +// Reader -> card send bits finished +// Start Frame delay time PCD to PICC void Reader14443AMillerEOC(void) { + CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm | TC0_CCCIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc | TC_CCCINTLVL_HI_gc; @@ -211,21 +225,32 @@ void Reader14443AMillerEOC(void) PORTE.OUTTGL = PIN3_bm; } +// EOC of Card->Reader found ISR(CODEC_TIMER_TIMESTAMPS_CCA_VECT) // EOC found { Reader14443A_EOC(); } +// This interrupt find Card -> Reader SOC ISR(ACA_AC1_vect) // this interrupt either finds the SOC or gets triggered before { + LED_PORT.OUTSET=LED_RED; + ACA.AC1CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH0_gc; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc; + } +// Decode the Card -> Reader signal +// according to the pause and modulated period +// if the half bit duration is modulated, then add 1 to buffer +// if the half bit duration is not modulated, then add 0 to buffer ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found { + + uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL; CODEC_TIMER_TIMESTAMPS.CNT = 0; @@ -266,23 +291,72 @@ ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found return; } +static void StartDemod(void){ + LED_PORT.OUTCLR = LED_RED; + + + /* + * Prepare for Manchester decoding. + * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal + * passes a (configurable) threshold. This is realized with the event system and an analog + * comparator. + * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we + * assume there is a pause. Now we read the second timers count value and can decide how many + * bit halves had modulations since the last pause. + */ + + // Comparator ADC + /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ + ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; + + /* This timer will be used to detect the pauses between the modulation sequences. */ + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width + CODEC_TIMER_LOADMOD.CCA = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCAIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCAINTLVL_HI_gc; + + /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ + CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer + CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; + CODEC_TIMER_TIMESTAMPS.CCA = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCAIF_bm; // Clear interrupt flag + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH0MUX = EVSYS_CHMUX_ACA_CH1_gc; // on every ACA_AC1 INT + EVSYS.CH0CTRL = EVSYS_DIGFILT_1SAMPLE_gc; + + ACA.AC0CTRL = 0; + CODEC_DEMOD_IN_PORT.INTCTRL = 0; + +} void Reader14443ACodecTask(void) { - if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) - { - Reader14443A_EOC(); - BitCount = 0; - Flags.RxDone = true; - Flags.RxPending = false; - } - if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) - return; + + // Waiting for response time out +// if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) +// { +// Reader14443A_EOC(); +// BitCount = 0; +// Flags.RxDone = true; +// Flags.RxPending = false; +// } +// if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) +// return; if (!Flags.RxPending && (Flags.Start || Flags.RxDone)) { - if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) // we are in frame delay time, so we can return later - return; + +// if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) { // we are in frame delay time, so we can return later +// return; +// } + if (Flags.RxDone && BitCount > 0) // decode the raw received data { + if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { BitCount = 0; @@ -296,6 +370,8 @@ void Reader14443ACodecTask(void) bool breakflag = false; TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored + + // Manchester Code ISO14443-2 8.2.5 while (!breakflag && BitCountTmp < TotalBitCount) { uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; @@ -322,9 +398,11 @@ void Reader14443ACodecTask(void) } if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); - LEDHook(LED_CODEC_RX, LED_PULSE); LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); + + Flags.RxPending=true; } + } Flags.Start = false; Flags.RxDone = false; @@ -332,55 +410,31 @@ void Reader14443ACodecTask(void) /* Call application with received data */ BitCount = ApplicationProcess(CodecBuffer, BitCount); - if (BitCount > 0) + // Application have data to be sent + if (false)//BitCount > 0) { - /* - * Prepare for Manchester decoding. - * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal - * passes a (configurable) threshold. This is realized with the event system and an analog - * comparator. - * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we - * assume there is a pause. Now we read the second timers count value and can decide how many - * bit halves had modulations since the last pause. - */ - /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ - ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; - - /* This timer will be used to detect the pauses between the modulation sequences. */ - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.CNT = 0; - CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width - CODEC_TIMER_LOADMOD.CCA = 95; // with 27.12 MHz this is 3/4 of a half bit width - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCAIF_bm; - CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCAINTLVL_HI_gc; - - /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ - CODEC_TIMER_TIMESTAMPS.CNT = 0; - CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; - CODEC_TIMER_TIMESTAMPS.CCA = 160; - CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; - CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCAIF_bm; - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_LO_gc; - - /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH0MUX = EVSYS_CHMUX_ACA_CH1_gc; // on every ACA_AC1 INT - EVSYS.CH0CTRL = EVSYS_DIGFILT_1SAMPLE_gc; - - ACA.AC0CTRL = 0; - CODEC_DEMOD_IN_PORT.INTCTRL = 0; + StartDemod(); LEDHook(LED_CODEC_TX, LED_PULSE); LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); /* Set state and start timer for Miller encoding. */ + // Send bits to card using TCD0_CCB interrupt (See Reader14443-ISR.S) BufferToSequence(); State = STATE_MILLER_SEND; CodecBufferPtr = CodecBuffer; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_HI_gc; - _delay_loop_1(85); + _delay_loop_1(85); // Wait for sending to finish + + + }else{ // No data need to be send or in SNIFFING mode + // TODO: add another sniff flag, in case of no Application data need to be send (Non sniffing mode) + StartDemod(); + Reader14443AMillerEOC(); + + // Sniffing mode, enable sampling interrupt only } } } @@ -391,7 +445,7 @@ void Reader14443ACodecStart(void) BitCount = 0; Flags.Start = true; - CodecReaderFieldStart(); +// CodecReaderFieldStart(); } void Reader14443ACodecReset(void) @@ -400,5 +454,43 @@ void Reader14443ACodecReset(void) State = STATE_IDLE; Flags.RxDone = false; Flags.Start = false; - CodecReaderFieldStop(); + //CodecReaderFieldStop(); } + +void TestSniff14443ACodecInit(void){ + + //////////////////////////// + // Same as reader init + /* Initialize common peripherals and start listening + * for incoming data. */ + + + CodecInitCommon(); + + CodecSetDemodPower(true); + + CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; + CODEC_TIMER_SAMPLING.CCB = 0; + CODEC_TIMER_SAMPLING.CCC = 0; + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; + + CODEC_TIMER_LOADMOD.CTRLA = 0; + State = STATE_IDLE; + + BitCount = 0; + Flags.Start = false; + Flags.RxPending = false; + Flags.RxDone = false; + /////////////////////////// + + Flags.Start = true; +// Flags.RxPending = true; + + //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); + //Reader14443A_EOC(); + + +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h index e9a2c1e..a96fff2 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h @@ -15,6 +15,7 @@ void Reader14443ACodecInit(void); void Reader14443ACodecDeInit(void); void Reader14443ACodecTask(void); +void TestSniff14443ACodecInit(void); /* Application Interface */ void Reader14443ACodecStart(void); diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 9e98f0d..48f3ee8 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -13,13 +13,16 @@ #include -void Sniff14443ACodecInit(void){ +void Sniff14443ACodecInit(void) +{ } -void Sniff14443ACodecDeInit(void) { - +void Sniff14443ACodecDeInit(void) +{ + Reader14443ACodecDeInit(); } void Sniff14443ACodecTask(void) { + Reader14443ACodecTask(); } \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 72ffce1..22eaf3b 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -188,9 +188,9 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { #endif #ifdef CONFIG_ISO14443A_SNIFF_SUPPORT [CONFIG_ISO14443A_SNIFF] = { - .CodecInitFunc = ISO14443ACodecInit, - .CodecDeInitFunc = ISO14443ACodecDeInit, - .CodecTaskFunc = ISO14443ACodecTask, + .CodecInitFunc = TestSniff14443ACodecInit, + .CodecDeInitFunc = Reader14443ACodecDeInit, + .CodecTaskFunc = Reader14443ACodecTask, .ApplicationInitFunc = ApplicationInitDummy, .ApplicationResetFunc = ApplicationResetDummy, .ApplicationTaskFunc = ApplicationTaskDummy, diff --git a/Firmware/Chameleon-Mini/Makefile b/Firmware/Chameleon-Mini/Makefile index 9d3175f..5870a2b 100644 --- a/Firmware/Chameleon-Mini/Makefile +++ b/Firmware/Chameleon-Mini/Makefile @@ -92,7 +92,7 @@ TARGET = Chameleon-Mini OPTIMIZATION = s SRC += $(TARGET).c LUFADescriptors.c System.c Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c SRC += Terminal/Terminal.c Terminal/Commands.c Terminal/XModem.c Terminal/CommandLine.c -SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/Reader14443-ISR.S +SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/SniffISO14443-2A.c Codec/Reader14443-ISR.S SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) LUFA_PATH = ../LUFA From 64534c8912f956a2703a769b78be52bb14a63a21 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 8 Jul 2018 01:27:05 +0100 Subject: [PATCH 07/50] Works for one round of traffic (cherry picked from commit 800f72a) --- Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 13 +++++ .../Chameleon-Mini/Codec/Reader14443-2A.c | 50 +++++++++++++++++-- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 23 ++++++++- .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 4 +- Firmware/Chameleon-Mini/Configuration.c | 6 +-- 5 files changed, 86 insertions(+), 10 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index ebf565b..5d367ef 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -425,6 +425,18 @@ void ISO14443ACodecTask(void) { LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); + + if(SniffEnable == true){ + // TODO: Start interrupt for finding Card -> Reader direction traffic + + ISO14443ACodecDeInit(); + + TrafficSource = TRAFFIC_CARD; + TestSniff14443ACodecInit(); + return; + + } + /* Call application if we received data */ AnswerBitCount = ApplicationProcess(CodecBuffer, DemodBitCount); @@ -437,6 +449,7 @@ void ISO14443ACodecTask(void) { /* We have to generate the parity bits ourself */ ParityBufferPtr = 0; } + } if (AnswerBitCount != ISO14443A_APP_NO_RESPONSE) { diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 9192c1f..84a3a4a 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -130,6 +130,8 @@ INLINE void Reader14443A_EOC(void) CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; State = STATE_FDT; + + } INLINE void BufferToSequence(void) @@ -292,7 +294,6 @@ ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found } static void StartDemod(void){ - LED_PORT.OUTCLR = LED_RED; /* @@ -401,6 +402,17 @@ void Reader14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); Flags.RxPending=true; + + + if (SniffEnable) + { + + Reader14443ACodecDeInit(); + ISO14443ACodecInit(); + TrafficSource = TRAFFIC_CARD; + + return; + } } } @@ -431,8 +443,8 @@ void Reader14443ACodecTask(void) }else{ // No data need to be send or in SNIFFING mode // TODO: add another sniff flag, in case of no Application data need to be send (Non sniffing mode) - StartDemod(); - Reader14443AMillerEOC(); +// StartDemod(); +// Reader14443AMillerEOC(); // Sniffing mode, enable sampling interrupt only } @@ -487,10 +499,38 @@ void TestSniff14443ACodecInit(void){ /////////////////////////// Flags.Start = true; -// Flags.RxPending = true; + + StartDemod(); + + // CODEC_TIMER_SAMPLING_CCC_vect + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; + + + /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, + * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause + * needs to be found. */ + ACA.STATUS = AC_AC1IF_bm; + ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + + CodecBufferPtr = CodecBuffer; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister = 0x00; + + RxPendingSince = SystemGetSysTick(); + + Flags.RxPending = true; + + // reset for future use + CodecBufferIdx = 0; + BitCountUp = 0; + + State = STATE_IDLE; + PORTE.OUTTGL = PIN3_bm; + + //Flags.RxPending = true; //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); //Reader14443A_EOC(); - } \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 48f3ee8..6a20493 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -13,16 +13,37 @@ #include +bool SniffEnable; +enum RCTraffic TrafficSource; + void Sniff14443ACodecInit(void) { + SniffEnable = true; + TrafficSource = TRAFFIC_READER; + // Start with sniffing Reader->Card direction traffic + // Card -> Reader traffic sniffing interrupt will be enbaled + // when Reader-> Card direction sniffing finished + // See ISO14443-2A.c ISO14443ACodecTask() + ISO14443ACodecInit(); + + // Also configure Interrupt settings for Reader function +// Reader14443ACodecInit(); + } void Sniff14443ACodecDeInit(void) { + ISO14443ACodecDeInit(); Reader14443ACodecDeInit(); } void Sniff14443ACodecTask(void) { - Reader14443ACodecTask(); + if (TrafficSource == TRAFFIC_READER){ + ISO14443ACodecTask(); + } else{ + Reader14443ACodecTask(); + } +// ISO14443ACodecDeInit(); +// Reader14443ACodecTask(); } \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h index eb0317a..44d50c8 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -1,5 +1,5 @@ // -// Created by 陈子泰 on 05/07/2018. +// Created by Zitai Chen on 05/07/2018. // #ifndef CHAMELEON_MINI_SNIFFISO14443_2A_H @@ -9,6 +9,8 @@ #include "Codec.h" #include "Terminal/CommandLine.h" +extern bool SniffEnable; +extern enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; /* Codec Interface */ void Sniff14443ACodecInit(void); void Sniff14443ACodecDeInit(void); diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 22eaf3b..5fda354 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -188,9 +188,9 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { #endif #ifdef CONFIG_ISO14443A_SNIFF_SUPPORT [CONFIG_ISO14443A_SNIFF] = { - .CodecInitFunc = TestSniff14443ACodecInit, - .CodecDeInitFunc = Reader14443ACodecDeInit, - .CodecTaskFunc = Reader14443ACodecTask, + .CodecInitFunc = Sniff14443ACodecInit, + .CodecDeInitFunc = Sniff14443ACodecDeInit, + .CodecTaskFunc = Sniff14443ACodecTask, .ApplicationInitFunc = ApplicationInitDummy, .ApplicationResetFunc = ApplicationResetDummy, .ApplicationTaskFunc = ApplicationTaskDummy, From 288ae733089ebccf73fc5f0a30769daf95b6fdfe Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 9 Jul 2018 19:47:03 +0100 Subject: [PATCH 08/50] Remove repeately called function: CodecInitCommon and keep demod power on (cherry picked from commit 8eb0d58) --- Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 6 ++-- .../Chameleon-Mini/Codec/Reader14443-2A.c | 28 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index 5d367ef..b0db926 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -408,7 +408,9 @@ void ISO14443ACodecDeInit(void) CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0); - CodecSetDemodPower(false); + if (!SniffEnable) { + CodecSetDemodPower(false); + } CodecSetLoadmodState(false); } @@ -431,8 +433,8 @@ void ISO14443ACodecTask(void) { ISO14443ACodecDeInit(); - TrafficSource = TRAFFIC_CARD; TestSniff14443ACodecInit(); + TrafficSource = TRAFFIC_CARD; return; } diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 84a3a4a..9a0719c 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -70,7 +70,7 @@ void Reader14443ACodecInit(void) { void Reader14443ACodecDeInit(void) { - CodecSetDemodPower(false); +// CodecSetDemodPower(false); // CodecReaderFieldStop(); CODEC_TIMER_SAMPLING.CTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = 0; @@ -399,6 +399,9 @@ void Reader14443ACodecTask(void) } if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + +// BitCount = removeParityBits(CodecBuffer, BitCount); + LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); Flags.RxPending=true; @@ -407,9 +410,10 @@ void Reader14443ACodecTask(void) if (SniffEnable) { + LED_PORT.OUTCLR = LED_RED; Reader14443ACodecDeInit(); ISO14443ACodecInit(); - TrafficSource = TRAFFIC_CARD; + TrafficSource = TRAFFIC_READER; return; } @@ -477,9 +481,9 @@ void TestSniff14443ACodecInit(void){ * for incoming data. */ - CodecInitCommon(); +// CodecInitCommon(); - CodecSetDemodPower(true); +// CodecSetDemodPower(true); CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; CODEC_TIMER_SAMPLING.CCB = 0; @@ -493,8 +497,8 @@ void TestSniff14443ACodecInit(void){ State = STATE_IDLE; BitCount = 0; - Flags.Start = false; - Flags.RxPending = false; +// Flags.Start = false; +// Flags.RxPending = false; Flags.RxDone = false; /////////////////////////// @@ -502,9 +506,13 @@ void TestSniff14443ACodecInit(void){ StartDemod(); +// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; +// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; +// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; +// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; + PORTE.OUTTGL = PIN3_bm; + // CODEC_TIMER_SAMPLING_CCC_vect - CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, @@ -525,8 +533,8 @@ void TestSniff14443ACodecInit(void){ CodecBufferIdx = 0; BitCountUp = 0; - State = STATE_IDLE; - PORTE.OUTTGL = PIN3_bm; +// State = STATE_IDLE; +// PORTE.OUTTGL = PIN3_bm; //Flags.RxPending = true; From 43ebccbb53ee29def916c82eeda67f1865f3ff6a Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 10 Jul 2018 01:48:17 +0100 Subject: [PATCH 09/50] Remove redundancy code, disable sniff flag when deInit the siniff mode (cherry picked from commit 58df0cd) --- .../Chameleon-Mini/Codec/Reader14443-2A.c | 22 +++++++++---------- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 3 +-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 9a0719c..0e2b794 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -496,13 +496,22 @@ void TestSniff14443ACodecInit(void){ CODEC_TIMER_LOADMOD.CTRLA = 0; State = STATE_IDLE; - BitCount = 0; +// BitCount = 0; + CodecBufferPtr = CodecBuffer; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister = 0x00; + // Flags.Start = false; // Flags.RxPending = false; Flags.RxDone = false; /////////////////////////// Flags.Start = true; + // reset for future use +// CodecBufferIdx = 0; +// BitCountUp = 0; + + Flags.RxPending = true; StartDemod(); @@ -510,7 +519,7 @@ void TestSniff14443ACodecInit(void){ // CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; // CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; // CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; - PORTE.OUTTGL = PIN3_bm; +// PORTE.OUTTGL = PIN3_bm; // CODEC_TIMER_SAMPLING_CCC_vect @@ -521,17 +530,8 @@ void TestSniff14443ACodecInit(void){ ACA.STATUS = AC_AC1IF_bm; ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - CodecBufferPtr = CodecBuffer; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister = 0x00; - RxPendingSince = SystemGetSysTick(); - Flags.RxPending = true; - - // reset for future use - CodecBufferIdx = 0; - BitCountUp = 0; // State = STATE_IDLE; // PORTE.OUTTGL = PIN3_bm; diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 6a20493..6371a2e 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -28,12 +28,11 @@ void Sniff14443ACodecInit(void) // Also configure Interrupt settings for Reader function // Reader14443ACodecInit(); - - } void Sniff14443ACodecDeInit(void) { + SniffEnable = false; ISO14443ACodecDeInit(); Reader14443ACodecDeInit(); } From 4b23bc379bf10740c4ae0cb7fcf58540bc9ccec9 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 10 Jul 2018 02:16:41 +0100 Subject: [PATCH 10/50] Refactor SniffISO14443-2A code structure for further modification (cherry picked from commit cd07c68) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 6371a2e..0813e6a 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -16,6 +16,29 @@ bool SniffEnable; enum RCTraffic TrafficSource; +// Card->Reader Direction Traffic +INLINE void CardSniffInit(void) +{ + +} + +INLINE void CardSniffDeinit(void) +{ + Reader14443ACodecDeInit(); +} + +// Reader->Card Direction Traffic +INLINE void ReaderSniffInit(void) +{ + ISO14443ACodecInit(); +} + +INLINE void ReaderSniffDeInit(void) +{ + ISO14443ACodecDeInit(); +} + + void Sniff14443ACodecInit(void) { SniffEnable = true; @@ -24,7 +47,7 @@ void Sniff14443ACodecInit(void) // Card -> Reader traffic sniffing interrupt will be enbaled // when Reader-> Card direction sniffing finished // See ISO14443-2A.c ISO14443ACodecTask() - ISO14443ACodecInit(); + ReaderSniffInit(); // Also configure Interrupt settings for Reader function // Reader14443ACodecInit(); @@ -33,8 +56,9 @@ void Sniff14443ACodecInit(void) void Sniff14443ACodecDeInit(void) { SniffEnable = false; - ISO14443ACodecDeInit(); - Reader14443ACodecDeInit(); + CardSniffDeinit(); + ReaderSniffDeInit(); + } void Sniff14443ACodecTask(void) { @@ -45,4 +69,6 @@ void Sniff14443ACodecTask(void) } // ISO14443ACodecDeInit(); // Reader14443ACodecTask(); -} \ No newline at end of file +} + + From 08404604c21c951dde317ed40b165d87ee77f54c Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 10 Jul 2018 18:42:29 +0100 Subject: [PATCH 11/50] Separate Reader->Card sniffing from the ISO14443-2A code Use PORTB INT1, TCD0 CCD for sampling The card->reader sniffing of this commint may be buggy (cherry picked from commit 73b6c51) --- Firmware/Chameleon-Mini/Codec/Codec.h | 3 +- Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 19 +- .../Chameleon-Mini/Codec/Reader14443-2A.c | 3 +- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 310 +++++++++++++++++- 4 files changed, 303 insertions(+), 32 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 0a74d25..1e530bc 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -141,7 +141,8 @@ INLINE void CodecInitCommon(void) CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL0 = PORT_ISC_RISING_gc; CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL1 = PORT_ISC_FALLING_gc; CODEC_DEMOD_IN_PORT.INT0MASK = 0; - CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT0LVL_HI_gc; + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT0LVL_HI_gc | PORT_INT1LVL_HI_gc; EVSYS.CH0MUX = CODEC_DEMOD_IN_EVMUX0; EVSYS.CH1MUX = CODEC_DEMOD_IN_EVMUX1; diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index b0db926..1f9d965 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -75,7 +75,7 @@ static void StartDemod(void) { CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCAINTLVL_HI_gc; /* Start looking out for modulation pause via interrupt. */ - CODEC_DEMOD_IN_PORT.INTFLAGS = 0x03; + CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT0IF_bm; CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0; } @@ -408,9 +408,7 @@ void ISO14443ACodecDeInit(void) CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0); - if (!SniffEnable) { - CodecSetDemodPower(false); - } + CodecSetDemodPower(false); CodecSetLoadmodState(false); } @@ -427,18 +425,6 @@ void ISO14443ACodecTask(void) { LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); - - if(SniffEnable == true){ - // TODO: Start interrupt for finding Card -> Reader direction traffic - - ISO14443ACodecDeInit(); - - TestSniff14443ACodecInit(); - TrafficSource = TRAFFIC_CARD; - return; - - } - /* Call application if we received data */ AnswerBitCount = ApplicationProcess(CodecBuffer, DemodBitCount); @@ -451,7 +437,6 @@ void ISO14443ACodecTask(void) { /* We have to generate the parity bits ourself */ ParityBufferPtr = 0; } - } if (AnswerBitCount != ISO14443A_APP_NO_RESPONSE) { diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 0e2b794..cb52073 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -412,7 +412,8 @@ void Reader14443ACodecTask(void) LED_PORT.OUTCLR = LED_RED; Reader14443ACodecDeInit(); - ISO14443ACodecInit(); + Sniff14443ACodecInit(); +// ISO14443ACodecInit(); TrafficSource = TRAFFIC_READER; return; diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 0813e6a..0ab899c 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -1,5 +1,7 @@ // // Created by Zitai Chen on 05/07/2018. +// Some interrupt handling vect +// modified form ISO14443-2A.c and Reader14443-2A.c // #include "SniffISO14443-2A.h" @@ -12,14 +14,262 @@ #include "Terminal/Terminal.h" #include +/* Sampling is done using internal clock, synchronized to the field modulation. + * For that we need to convert the bit rate for the internal clock. */ +#define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) + +#define ISO14443A_MIN_BITS_PER_FRAME 7 + + +/* Define pseudo variables to use fast register access. This is useful for global vars */ +#define DataRegister Codec8Reg0 +#define StateRegister Codec8Reg1 +#define ParityRegister Codec8Reg2 +#define SampleIdxRegister Codec8Reg2 +#define SampleRegister Codec8Reg3 +#define BitSent CodecCount16Register1 +#define BitCount CodecCount16Register2 +#define CodecBufferPtr CodecPtrRegister1 +#define ParityBufferPtr CodecPtrRegister2 bool SniffEnable; enum RCTraffic TrafficSource; +static volatile struct { + volatile bool DemodFinished; +// volatile bool LoadmodFinished; +} Flags = { 0 }; + +typedef enum { + /* Demod */ + DEMOD_DATA_BIT, + DEMOD_PARITY_BIT, + LOADMOD_FDT, + +} StateType; + +///////////////////////////////////////////////// +// Reader->Card Direction Traffic +///////////////////////////////////////////////// + +void ReaderSniffInit(void) +{ + /* Initialize some global vars and start looking out for reader commands */ + Flags.DemodFinished = 0; + +// ReaderStartDemod(); + + CodecBufferPtr = CodecBuffer; + ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; + DataRegister = 0; + SampleRegister = 0; + SampleIdxRegister = 0; + BitCount = 0; + StateRegister = DEMOD_DATA_BIT; + + + /* Configure sampling-timer free running and sync to first modulation-pause. */ + CODEC_TIMER_SAMPLING.CNT = 0; // Reset the timer count + CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; // Set Period regisiter + CODEC_TIMER_SAMPLING.CCD = 0xFFFF; /* CCD Interrupt is not active! */ + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_HI_gc; + + /* Start looking out for modulation pause via interrupt. */ + CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT1IF_bm; + CODEC_DEMOD_IN_PORT.INT1MASK = CODEC_DEMOD_IN_MASK0; + +// ISO14443ACodecInit(); +} + + +// Find first pause and start sampling +ISR(PORTB_INT1_vect) { +// LED_PORT.OUTSET = LED_RED; + /* This is the first edge of the first modulation-pause after StartDemod. + * Now we have time to start + * demodulating beginning from one bit-width after this edge. */ + + /* Sampling timer has been preset to sample-rate and has automatically synced + * to THIS first modulation pause. Thus after exactly one bit-width from here, + * an OVF is generated. We want to start sampling with the next bit and use the + * XYZBUF mechanism of the xmega to automatically double the sampling rate on the + * next overflow. For this we have to temporarily deactivate the automatical alignment + * in order to catch next overflow event for updating the BUF registers. + * We want to sample the demodulated data stream in the first quarter of the half-bit + * where the pulsed miller encoded is located. */ + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES/2 - 1; /* Half bit width */ + CODEC_TIMER_SAMPLING.CCDBUF = SAMPLE_RATE_SYSTEM_CYCLES/8 - 14 - 1; /* Compensate for DIGFILT and ISR prolog */ + + /* Setup Frame Delay Timer and wire to EVSYS. Frame delay time is + * measured from last change in RF field, therefore we use + * the event channel 1 (end of modulation pause) as the restart event. + * The preliminary frame delay time chosen here is irrelevant, because + * the correct FDT gets set automatically after demodulation. */ + +// CODEC_TIMER_LOADMOD.CNT = 0; +// CODEC_TIMER_LOADMOD.PER = 0xFFFF; +//// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODEND_EVSEL; +//// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; +//// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; +//// CODEC_TIMER_LOADMOD.CTRLA = CODEC_TIMER_CARRIER_CLKSEL; +// +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = 0; + + /* Disable this interrupt */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; +} + +// Sampling with timer and demod +ISR(TCD0_CCD_vect) { + /* This interrupt gets called twice for every bit to sample it. */ + uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; + + /* Shift sampled bit into sampling register */ + SampleRegister = (SampleRegister << 1) | (!SamplePin ? 0x01 : 0x00); + + if (SampleIdxRegister) { + SampleIdxRegister = 0; + /* Analyze the sampling register after 2 samples. */ + if ((SampleRegister & 0x07) == 0x07) { + /* No carrier modulation for 3 sample points. EOC! */ + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + + /* By this time, the FDT timer is aligned to the last modulation + * edge of the reader. So we disable the auto-synchronization and + * let it count the frame delay time in the background, and generate + * an interrupt once it has reached the FDT. */ + // Do not activate loadmod +// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = 0; + +// if (SampleRegister & 0x08) { +// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV1 - 40; /* compensate for ISR prolog */ +// } else { +// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV0 - 40; /* compensate for ISR prolog */ +// } + + StateRegister = LOADMOD_FDT; + +// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; +// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_HI_gc; + + /* Determine if we did not receive a multiple of 8 bits. + * If this is the case, right-align the remaining data and + * store it into the buffer. */ + uint8_t RemainingBits = BitCount % 8; + if (RemainingBits != 0) { + uint8_t NewDataRegister = DataRegister; + + while (RemainingBits++ < 8) { + /* Pad with zeroes to right-align. */ + NewDataRegister >>= 1; + } + + /* TODO: Prevent buffer overflow */ + *CodecBufferPtr = NewDataRegister; + } + + /* Signal, that we have finished sampling */ + Flags.DemodFinished = 1; + } else { + /* Otherwise, we check the two sample bits from the bit before. */ + uint8_t BitSample = SampleRegister & 0xC; + uint8_t Bit = 0; + + if (BitSample != (0x0 << 2)) { + /* We have a valid bit. decode and process it. */ + if (BitSample & (0x1 << 2)) { + /* 01 sequence or 11 sequence -> This is a zero bit */ + Bit = 0; + } else { + /* 10 sequence -> This is a one bit */ + Bit = 1; + } + + if (StateRegister == DEMOD_DATA_BIT) { + /* This is a data bit, so shift it into the data register and + * hold a local copy of it. */ + uint8_t NewDataRegister = DataRegister >> 1; + NewDataRegister |= (Bit ? 0x80 : 0x00); + DataRegister = NewDataRegister; + + /* Update bitcount */ + uint16_t NewBitCount = ++BitCount; + if ((NewBitCount & 0x07) == 0) { + /* We have reached a byte boundary! Store the data register. */ + /* TODO: Prevent buffer overflow */ + *CodecBufferPtr++ = NewDataRegister; + + /* Store bit for determining FDT at EOC and enable parity + * handling on next bit. */ + StateRegister = DEMOD_PARITY_BIT; + } + + } else if (StateRegister == DEMOD_PARITY_BIT) { + /* This is a parity bit. Store it */ + *ParityBufferPtr++ = Bit; + StateRegister = DEMOD_DATA_BIT; + } else { + /* Should never Happen (TM) */ + } + } else { + /* 00 sequence. -> No valid data yet. This also occurs if we just started + * sampling and have sampled less than 2 bits yet. Thus ignore. */ + } + } + } else { + /* On odd sample position just sample. */ + SampleIdxRegister = ~SampleIdxRegister; + } + + /* Make sure the sampling timer gets automatically aligned to the + * modulation pauses by using the RESTART event. + * This can be understood as a "poor mans PLL" and makes sure that we are + * never too far out the bit-grid while sampling. */ + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; +} + + + + +INLINE void ReaderSniffDeInit(void) +{ + /* Gracefully shutdown codec */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + + Flags.DemodFinished = 0; + + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + + +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; + +} + + + + + +///////////////////////////////////////////////// // Card->Reader Direction Traffic +///////////////////////////////////////////////// + INLINE void CardSniffInit(void) { - + TestSniff14443ACodecInit(); } INLINE void CardSniffDeinit(void) @@ -27,22 +277,20 @@ INLINE void CardSniffDeinit(void) Reader14443ACodecDeInit(); } -// Reader->Card Direction Traffic -INLINE void ReaderSniffInit(void) -{ - ISO14443ACodecInit(); -} - -INLINE void ReaderSniffDeInit(void) -{ - ISO14443ACodecDeInit(); -} void Sniff14443ACodecInit(void) { + Flags.DemodFinished = 0; + SniffEnable = true; TrafficSource = TRAFFIC_READER; + + // Common Codec Register settings + CodecInitCommon(); + // Enable demodulator power + CodecSetDemodPower(true); + // Start with sniffing Reader->Card direction traffic // Card -> Reader traffic sniffing interrupt will be enbaled // when Reader-> Card direction sniffing finished @@ -58,12 +306,47 @@ void Sniff14443ACodecDeInit(void) SniffEnable = false; CardSniffDeinit(); ReaderSniffDeInit(); - } + + void Sniff14443ACodecTask(void) { + if (TrafficSource == TRAFFIC_READER){ - ISO14443ACodecTask(); + if (Flags.DemodFinished) { + Flags.DemodFinished = 0; + /* Reception finished. Process the received bytes */ + uint16_t DemodBitCount = BitCount; + + if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + // For logging data + LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); + LEDHook(LED_CODEC_RX, LED_PULSE); + + if(SniffEnable == true){ + // TODO: Start interrupt for finding Card -> Reader direction traffic + + ReaderSniffDeInit(); + CardSniffInit(); + +// ISO14443ACodecDeInit(); + +// TestSniff14443ACodecInit(); + TrafficSource = TRAFFIC_CARD; + return; + } + } +// +// /* No data to be processed. Disable loadmodding and start listening again */ +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = 0; + + ReaderSniffInit(); + + } + + + } else{ Reader14443ACodecTask(); } @@ -72,3 +355,4 @@ void Sniff14443ACodecTask(void) } + From c526ab3035c86cbbcb2ee583f81f62cfd4ad73ad Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 11 Jul 2018 02:36:02 +0100 Subject: [PATCH 12/50] Separate Card->Reader code, works for only one round of traffic Buggy commit. Maybe fix the event channel and reinit the timer when switching (cherry picked from commit a43869a) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 397 +++++++++++++++++- 1 file changed, 392 insertions(+), 5 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 0ab899c..d8617ef 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -20,6 +20,10 @@ #define ISO14443A_MIN_BITS_PER_FRAME 7 +// Card to reader +#define ISO14443A_PICC_TO_PCD_FDT_PRESCALER TC_CLKSEL_DIV8_gc // please change ISO14443A_PICC_TO_PCD_MIN_FDT when changing this +#define ISO14443A_RX_MINIMUM_BITCOUNT 4 + /* Define pseudo variables to use fast register access. This is useful for global vars */ #define DataRegister Codec8Reg0 @@ -32,13 +36,23 @@ #define CodecBufferPtr CodecPtrRegister1 #define ParityBufferPtr CodecPtrRegister2 + +#define BitCountUp GPIOR7 +#define CodecBufferIdx GPIOR8 + bool SniffEnable; enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; // volatile bool LoadmodFinished; + volatile bool Start; + volatile bool RxDone; + volatile bool RxPending; + } Flags = { 0 }; +static volatile uint16_t RxPendingSince; + typedef enum { /* Demod */ @@ -48,6 +62,14 @@ typedef enum { } StateType; + +static volatile enum { + STATE_IDLE, + STATE_MILLER_SEND, + STATE_MILLER_EOF, + STATE_FDT +} State; + ///////////////////////////////////////////////// // Reader->Card Direction Traffic ///////////////////////////////////////////////// @@ -267,17 +289,262 @@ INLINE void ReaderSniffDeInit(void) // Card->Reader Direction Traffic ///////////////////////////////////////////////// +INLINE void Insert0(void) +{ + SampleRegister >>= 1; + if (++BitCount % 8) + return; + *CodecBufferPtr++ = SampleRegister; +} + +INLINE void Insert1(void) +{ + SampleRegister = (SampleRegister >> 1) | 0x80; + if (++BitCount % 8) + return; + *CodecBufferPtr++ = SampleRegister; +} + +// This interrupt find Card -> Reader SOC +ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before +{ +// LED_PORT.OUTSET=LED_RED; + + ACA.AC0CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt + // enable the pause-finding timer + CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_gc; + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc; + +} +// Decode the Card -> Reader signal +// according to the pause and modulated period +// if the half bit duration is modulated, then add 1 to buffer +// if the half bit duration is not modulated, then add 0 to buffer +ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found +{ + + + uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL; + CODEC_TIMER_TIMESTAMPS.CNT = 0; + + /* This needs to be done only on the first call, + * but doing this only on a condition means wasting time, so we do it every time. */ + CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_DIV4_gc; + + switch (tmp) // decide how many half bit periods have been modulations + { + case 0 ... 48: // 32 ticks is one half of a bit period + return; + + case 49 ... 80: // 64 ticks are a full bit period + Insert1(); + Insert0(); + return; + + case 81 ... 112: // 96 ticks are 3 half bit periods + if (BitCount & 1) + { + Insert1(); + Insert1(); + Insert0(); + } else { + Insert1(); + Insert0(); + Insert0(); + } + return; + + default: // every value over 96 + 16 (tolerance) is considered to be 4 half bit periods + Insert1(); + Insert1(); + Insert0(); + Insert0(); + return; + } + return; +} +// EOC of Card->Reader found +ISR(TCD1_CCB_vect) // EOC found +{ +// Reader14443A_EOC(); + + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; + CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; + ACA.AC0CTRL &= ~AC_ENABLE_bm; + + if (BitCount & 1) + { + if (SampleRegister & 0x80) + Insert0(); + else + Insert1(); + } + + if (BitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + Flags.RxDone = true; + Flags.RxPending = false; + + // set up timer that forces the minimum frame delay time from PICC to PCD + CODEC_TIMER_LOADMOD.PER = 0xFFFF; + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLD = 0; + CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; + + State = STATE_FDT; + +} +//// End of Card-> reader communication and enter frame delay time +//void Reader14443A_EOC(void) +//{ +// +// +//} + + INLINE void CardSniffInit(void) { - TestSniff14443ACodecInit(); + + //////////////////////////// + // Same as reader init + /* Initialize common peripherals and start listening + * for incoming data. */ + + +// CodecInitCommon(); + + +// CodecSetDemodPower(true); + +// CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; +// CODEC_TIMER_SAMPLING.CCB = 0; +// CODEC_TIMER_SAMPLING.CCC = 0; + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; +// CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; + + CODEC_TIMER_LOADMOD.CTRLA = 0; + State = STATE_IDLE; + +// BitCount = 0; + CodecBufferPtr = CodecBuffer; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister = 0x00; + +// Flags.Start = false; +// Flags.RxPending = false; + Flags.RxDone = false; + /////////////////////////// + + Flags.Start = true; + // reset for future use +// CodecBufferIdx = 0; +// BitCountUp = 0; + + Flags.RxPending = true; + +// StartDemod(); + + /* + * Prepare for Manchester decoding. + * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal + * passes a (configurable) threshold. This is realized with the event system and an analog + * comparator. + * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we + * assume there is a pause. Now we read the second timers count value and can decide how many + * bit halves had modulations since the last pause. + */ + + // Comparator ADC + /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; + + /* This timer will be used to detect the pauses between the modulation sequences. */ + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width + CODEC_TIMER_LOADMOD.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc; + + /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ + CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer + CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; + CODEC_TIMER_TIMESTAMPS.CCB = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC1 INT + EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; + + CODEC_DEMOD_IN_PORT.INTCTRL = 0; + + +// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; +// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; +// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; +// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; +// PORTE.OUTTGL = PIN3_bm; + + // CODEC_TIMER_SAMPLING_CCC_vect + + + /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, + * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause + * needs to be found. */ + ACA.AC1CTRL = 0; + ACA.STATUS = AC_AC0IF_bm; + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + +// RxPendingSince = SystemGetSysTick(); + + +// State = STATE_IDLE; +// PORTE.OUTTGL = PIN3_bm; + + //Flags.RxPending = true; + + //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); + //Reader14443A_EOC(); + } INLINE void CardSniffDeinit(void) { - Reader14443ACodecDeInit(); + // CodecSetDemodPower(false); + // CodecReaderFieldStop(); + CODEC_TIMER_SAMPLING.CTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + + + + EVSYS.CH2MUX = 0; // on every ACA_AC1 INT + EVSYS.CH2CTRL = 0; + ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; + + + + Flags.RxDone = false; + Flags.RxPending = false; + Flags.Start = false; + +// Reader14443ACodecDeInit(); } +///////////////////////////////////////////////// +// Init and deInit, task, functions for this codec +///////////////////////////////////////////////// void Sniff14443ACodecInit(void) { @@ -342,13 +609,133 @@ void Sniff14443ACodecTask(void) // CODEC_TIMER_LOADMOD.INTCTRLA = 0; ReaderSniffInit(); - } + } + + else // Card->Reader Task + { + + // Waiting for response time out +// if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) +// { +// Reader14443A_EOC(); +// BitCount = 0; +// Flags.RxDone = true; +// Flags.RxPending = false; +// } +// if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) +// return; + if (!Flags.RxPending && (Flags.Start || Flags.RxDone)) + { + +// if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) { // we are in frame delay time, so we can return later +// return; +// } + + if (Flags.RxDone && BitCount > 0) // decode the raw received data + { + + if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) + { + BitCount = 0; + } else { + uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; + memcpy(TmpCodecBuffer, CodecBuffer, (BitCount + 7) / 8); + + CodecBufferPtr = CodecBuffer; + uint16_t BitCountTmp = 2, TotalBitCount = BitCount; + BitCount = 0; + + bool breakflag = false; + TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored + + // Manchester Code ISO14443-2 8.2.5 + while (!breakflag && BitCountTmp < TotalBitCount) + { + uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; + TmpCodecBuffer[BitCountTmp / 8] >>= 2; + switch (Bit) + { + case 0b10: + Insert1(); + break; + + case 0b01: + Insert0(); + break; + + case 0b00: // EOC + breakflag = true; + break; + + default: + // error, should not happen, TODO handle this + break; + } + BitCountTmp += 2; + } + if (BitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + +// BitCount = removeParityBits(CodecBuffer, BitCount); + + LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); + + Flags.RxPending=true; + + +// if (SniffEnable) +// { + +// LED_PORT.OUTCLR = LED_RED; + CardSniffDeinit(); + ReaderSniffInit(); +// Reader14443ACodecDeInit(); +// ISO14443ACodecInit(); + TrafficSource = TRAFFIC_READER; + + return; +// } + } + + } + Flags.Start = false; + Flags.RxDone = false; + + /* Call application with received data */ + BitCount = ApplicationProcess(CodecBuffer, BitCount); + + // Application have data to be sent +// if (false)//BitCount > 0) +// { + +// StartDemod(); +// +// LEDHook(LED_CODEC_TX, LED_PULSE); +// LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); +// +// /* Set state and start timer for Miller encoding. */ +// // Send bits to card using TCD0_CCB interrupt (See Reader14443-ISR.S) +// BufferToSequence(); +// State = STATE_MILLER_SEND; +// CodecBufferPtr = CodecBuffer; +// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm; +// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_HI_gc; +// _delay_loop_1(85); // Wait for sending to finish + + +// }else{ // No data need to be send or in SNIFFING mode + // TODO: add another sniff flag, in case of no Application data need to be send (Non sniffing mode) +// StartDemod(); +// Reader14443AMillerEOC(); + + // Sniffing mode, enable sampling interrupt only +// } + } +// Reader14443ACodecTask(); - } else{ - Reader14443ACodecTask(); } // ISO14443ACodecDeInit(); // Reader14443ACodecTask(); From cd321aff3d48b6244fc9204ee6722622470f4f2e Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 11 Jul 2018 10:59:43 +0100 Subject: [PATCH 13/50] Event Channel and PORTB int1 bug fix: 1. Use event CH2 for timer resetting 2. Can not sniff the second round of traffic due to the PORTB int1 was disabled in CardSniffInit(). This is reenabled in ReaderSniffInit (cherry picked from commit 24b87e2) --- Firmware/Chameleon-Mini/Codec/Codec.h | 5 +++ .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 43 +++++++++++++------ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 1e530bc..29daa91 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -146,6 +146,9 @@ INLINE void CodecInitCommon(void) EVSYS.CH0MUX = CODEC_DEMOD_IN_EVMUX0; EVSYS.CH1MUX = CODEC_DEMOD_IN_EVMUX1; + EVSYS.CH2MUX = CODEC_DEMOD_IN_EVMUX0; + + /* Configure loadmod pin configuration and use a virtual port configuration * for single instruction cycle access */ CODEC_LOADMOD_PORT.DIRSET = CODEC_LOADMOD_MASK; @@ -187,6 +190,8 @@ INLINE void CodecInitCommon(void) /* Configure Analog Comparator 1 to detect SOC */ ACA.AC1MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC1CTRL = CODEC_AC_DEMOD_SETTINGS; + + } INLINE void CodecSetSubcarrier(SubcarrierModType ModType, uint16_t Divider) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index d8617ef..22fd65e 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -76,6 +76,22 @@ static volatile enum { void ReaderSniffInit(void) { + + // Common Codec Register settings +// CodecInitCommon(); + + + // Configure interrupt for demod + // This was disabled in CardSniffInit() + CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; + + + // Enable demodulator power +// CodecSetDemodPower(true); + + + TrafficSource = TRAFFIC_READER; + /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; @@ -408,6 +424,7 @@ ISR(TCD1_CCB_vect) // EOC found INLINE void CardSniffInit(void) { + TrafficSource = TRAFFIC_CARD; //////////////////////////// // Same as reader init @@ -530,6 +547,7 @@ INLINE void CardSniffDeinit(void) EVSYS.CH2MUX = 0; // on every ACA_AC1 INT EVSYS.CH2CTRL = 0; + ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; @@ -548,10 +566,9 @@ INLINE void CardSniffDeinit(void) void Sniff14443ACodecInit(void) { - Flags.DemodFinished = 0; +// Flags.DemodFinished = 0; - SniffEnable = true; - TrafficSource = TRAFFIC_READER; +// SniffEnable = true; // Common Codec Register settings CodecInitCommon(); @@ -570,9 +587,10 @@ void Sniff14443ACodecInit(void) void Sniff14443ACodecDeInit(void) { - SniffEnable = false; +// SniffEnable = false; CardSniffDeinit(); ReaderSniffDeInit(); + CodecSetDemodPower(false); } @@ -590,18 +608,17 @@ void Sniff14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); - if(SniffEnable == true){ - // TODO: Start interrupt for finding Card -> Reader direction traffic +// if(SniffEnable == true){ + // TODO: Start interrupt for finding Card -> Reader direction traffic - ReaderSniffDeInit(); - CardSniffInit(); + ReaderSniffDeInit(); + CardSniffInit(); // ISO14443ACodecDeInit(); // TestSniff14443ACodecInit(); - TrafficSource = TRAFFIC_CARD; - return; - } + return; +// } } // // /* No data to be processed. Disable loadmodding and start listening again */ @@ -691,10 +708,12 @@ void Sniff14443ACodecTask(void) // LED_PORT.OUTCLR = LED_RED; CardSniffDeinit(); +// TrafficSource = TRAFFIC_READER; ReaderSniffInit(); +// Sniff14443ACodecInit(); +// ReaderSniffInit(); // Reader14443ACodecDeInit(); // ISO14443ACodecInit(); - TrafficSource = TRAFFIC_READER; return; // } From 686691f30ce7675236c0ffb86c4ed9e27d89b90a Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 02:01:53 +0100 Subject: [PATCH 14/50] Remove experimental code in Reader14443-2A.c, make sniffing code independent form Reader14443-2A.c and ISO14443-2A.c (cherry picked from commit 16f4fb1) --- Firmware/Chameleon-Mini/Codec/Codec.h | 2 - .../Chameleon-Mini/Codec/Reader14443-2A.c | 233 ++++-------------- .../Chameleon-Mini/Codec/Reader14443-2A.h | 1 - .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 1 - 4 files changed, 53 insertions(+), 184 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 29daa91..34b8e34 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -190,8 +190,6 @@ INLINE void CodecInitCommon(void) /* Configure Analog Comparator 1 to detect SOC */ ACA.AC1MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC1CTRL = CODEC_AC_DEMOD_SETTINGS; - - } INLINE void CodecSetSubcarrier(SubcarrierModType ModType, uint16_t Divider) diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index cb52073..d9cabbe 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -50,7 +50,6 @@ void Reader14443ACodecInit(void) { CodecInitCommon(); CodecSetDemodPower(true); - CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; CODEC_TIMER_SAMPLING.CCB = 0; CODEC_TIMER_SAMPLING.CCC = 0; @@ -67,11 +66,9 @@ void Reader14443ACodecInit(void) { Flags.RxDone = false; } - - void Reader14443ACodecDeInit(void) { -// CodecSetDemodPower(false); - // CodecReaderFieldStop(); + CodecSetDemodPower(false); + CodecReaderFieldStop(); CODEC_TIMER_SAMPLING.CTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = 0; @@ -101,7 +98,6 @@ INLINE void Insert1(void) // End of Card-> reader communication and enter frame delay time INLINE void Reader14443A_EOC(void) { - CODEC_TIMER_LOADMOD.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; @@ -130,13 +126,10 @@ INLINE void Reader14443A_EOC(void) CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; State = STATE_FDT; - - } INLINE void BufferToSequence(void) { - uint16_t count = BitCount; if (count > BITS_PER_BYTE * CODEC_BUFFER_SIZE / 2) // todo is this correct? return; @@ -188,11 +181,9 @@ INLINE void BufferToSequence(void) // Frame Delay Time PCD to PICC ends ISR (TCD0_CCC_vect) { - CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; - /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause * needs to be found. */ @@ -204,7 +195,6 @@ ISR (TCD0_CCC_vect) SampleRegister = 0x00; RxPendingSince = SystemGetSysTick(); - Flags.RxPending = true; // reset for future use @@ -219,7 +209,6 @@ ISR (TCD0_CCC_vect) // Start Frame delay time PCD to PICC void Reader14443AMillerEOC(void) { - CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm | TC0_CCCIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc | TC_CCCINTLVL_HI_gc; @@ -236,13 +225,10 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCA_VECT) // EOC found // This interrupt find Card -> Reader SOC ISR(ACA_AC1_vect) // this interrupt either finds the SOC or gets triggered before { - LED_PORT.OUTSET=LED_RED; - ACA.AC1CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH0_gc; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc; - } // Decode the Card -> Reader signal @@ -251,8 +237,6 @@ ISR(ACA_AC1_vect) // this interrupt either finds the SOC or gets triggered befor // if the half bit duration is not modulated, then add 0 to buffer ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found { - - uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL; CODEC_TIMER_TIMESTAMPS.CNT = 0; @@ -293,71 +277,23 @@ ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found return; } -static void StartDemod(void){ - - - /* - * Prepare for Manchester decoding. - * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal - * passes a (configurable) threshold. This is realized with the event system and an analog - * comparator. - * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we - * assume there is a pause. Now we read the second timers count value and can decide how many - * bit halves had modulations since the last pause. - */ - - // Comparator ADC - /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ - ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; - - /* This timer will be used to detect the pauses between the modulation sequences. */ - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.CNT = 0; - CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width - CODEC_TIMER_LOADMOD.CCA = 95; // with 27.12 MHz this is 3/4 of a half bit width - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCAIF_bm; - CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCAINTLVL_HI_gc; - - /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ - CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer - CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; - CODEC_TIMER_TIMESTAMPS.CCA = 160; - CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; - CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCAIF_bm; // Clear interrupt flag - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_LO_gc; - - /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH0MUX = EVSYS_CHMUX_ACA_CH1_gc; // on every ACA_AC1 INT - EVSYS.CH0CTRL = EVSYS_DIGFILT_1SAMPLE_gc; - - ACA.AC0CTRL = 0; - CODEC_DEMOD_IN_PORT.INTCTRL = 0; - -} void Reader14443ACodecTask(void) { - - // Waiting for response time out -// if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) -// { -// Reader14443A_EOC(); -// BitCount = 0; -// Flags.RxDone = true; -// Flags.RxPending = false; -// } -// if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) -// return; + if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) + { + Reader14443A_EOC(); + BitCount = 0; + Flags.RxDone = true; + Flags.RxPending = false; + } + if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) + return; if (!Flags.RxPending && (Flags.Start || Flags.RxDone)) { - -// if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) { // we are in frame delay time, so we can return later -// return; -// } - + if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) // we are in frame delay time, so we can return later + return; if (Flags.RxDone && BitCount > 0) // decode the raw received data { - if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { BitCount = 0; @@ -399,27 +335,9 @@ void Reader14443ACodecTask(void) } if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); - -// BitCount = removeParityBits(CodecBuffer, BitCount); - + LEDHook(LED_CODEC_RX, LED_PULSE); LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); - - Flags.RxPending=true; - - - if (SniffEnable) - { - - LED_PORT.OUTCLR = LED_RED; - Reader14443ACodecDeInit(); - Sniff14443ACodecInit(); -// ISO14443ACodecInit(); - TrafficSource = TRAFFIC_READER; - - return; - } } - } Flags.Start = false; Flags.RxDone = false; @@ -427,11 +345,44 @@ void Reader14443ACodecTask(void) /* Call application with received data */ BitCount = ApplicationProcess(CodecBuffer, BitCount); - // Application have data to be sent - if (false)//BitCount > 0) + if (BitCount > 0) { + /* + * Prepare for Manchester decoding. + * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal + * passes a (configurable) threshold. This is realized with the event system and an analog + * comparator. + * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we + * assume there is a pause. Now we read the second timers count value and can decide how many + * bit halves had modulations since the last pause. + */ - StartDemod(); + /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ + ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; + + /* This timer will be used to detect the pauses between the modulation sequences. */ + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width + CODEC_TIMER_LOADMOD.CCA = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCAIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCAINTLVL_HI_gc; + + /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ + CODEC_TIMER_TIMESTAMPS.CNT = 0; + CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; + CODEC_TIMER_TIMESTAMPS.CCA = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCAIF_bm; + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH0MUX = EVSYS_CHMUX_ACA_CH1_gc; // on every ACA_AC1 INT + EVSYS.CH0CTRL = EVSYS_DIGFILT_1SAMPLE_gc; + + ACA.AC0CTRL = 0; + CODEC_DEMOD_IN_PORT.INTCTRL = 0; LEDHook(LED_CODEC_TX, LED_PULSE); LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); @@ -443,15 +394,7 @@ void Reader14443ACodecTask(void) CodecBufferPtr = CodecBuffer; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_HI_gc; - _delay_loop_1(85); // Wait for sending to finish - - - }else{ // No data need to be send or in SNIFFING mode - // TODO: add another sniff flag, in case of no Application data need to be send (Non sniffing mode) -// StartDemod(); -// Reader14443AMillerEOC(); - - // Sniffing mode, enable sampling interrupt only + _delay_loop_1(85); } } } @@ -462,7 +405,7 @@ void Reader14443ACodecStart(void) BitCount = 0; Flags.Start = true; -// CodecReaderFieldStart(); + CodecReaderFieldStart(); } void Reader14443ACodecReset(void) @@ -471,75 +414,5 @@ void Reader14443ACodecReset(void) State = STATE_IDLE; Flags.RxDone = false; Flags.Start = false; - //CodecReaderFieldStop(); + CodecReaderFieldStop(); } - -void TestSniff14443ACodecInit(void){ - - //////////////////////////// - // Same as reader init - /* Initialize common peripherals and start listening - * for incoming data. */ - - -// CodecInitCommon(); - -// CodecSetDemodPower(true); - - CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; - CODEC_TIMER_SAMPLING.CCB = 0; - CODEC_TIMER_SAMPLING.CCC = 0; - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; - - CODEC_TIMER_LOADMOD.CTRLA = 0; - State = STATE_IDLE; - -// BitCount = 0; - CodecBufferPtr = CodecBuffer; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister = 0x00; - -// Flags.Start = false; -// Flags.RxPending = false; - Flags.RxDone = false; - /////////////////////////// - - Flags.Start = true; - // reset for future use -// CodecBufferIdx = 0; -// BitCountUp = 0; - - Flags.RxPending = true; - - StartDemod(); - -// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; -// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; -// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; -// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; -// PORTE.OUTTGL = PIN3_bm; - - // CODEC_TIMER_SAMPLING_CCC_vect - - - /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, - * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause - * needs to be found. */ - ACA.STATUS = AC_AC1IF_bm; - ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - - RxPendingSince = SystemGetSysTick(); - - -// State = STATE_IDLE; -// PORTE.OUTTGL = PIN3_bm; - - //Flags.RxPending = true; - - //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); - //Reader14443A_EOC(); - -} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h index a96fff2..e9a2c1e 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h @@ -15,7 +15,6 @@ void Reader14443ACodecInit(void); void Reader14443ACodecDeInit(void); void Reader14443ACodecTask(void); -void TestSniff14443ACodecInit(void); /* Application Interface */ void Reader14443ACodecStart(void); diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 22fd65e..23b04d1 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -40,7 +40,6 @@ #define BitCountUp GPIOR7 #define CodecBufferIdx GPIOR8 -bool SniffEnable; enum RCTraffic TrafficSource; static volatile struct { From 56d5525beb5a0a690d9520846093d918ae232dcd Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 02:11:03 +0100 Subject: [PATCH 15/50] Remove redundancy comments in SniffISO14443-2A.c (cherry picked from commit b95dfda) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 174 +----------------- 1 file changed, 7 insertions(+), 167 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 23b04d1..dd1e573 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -4,6 +4,7 @@ // modified form ISO14443-2A.c and Reader14443-2A.c // +// TODO: implement pending since to automatically reset the sniffing after a period of no traffic #include "SniffISO14443-2A.h" #include "Reader14443-2A.h" @@ -76,26 +77,15 @@ static volatile enum { void ReaderSniffInit(void) { - // Common Codec Register settings -// CodecInitCommon(); - - // Configure interrupt for demod // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; - - // Enable demodulator power -// CodecSetDemodPower(true); - - TrafficSource = TRAFFIC_READER; /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; -// ReaderStartDemod(); - CodecBufferPtr = CodecBuffer; ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; DataRegister = 0; @@ -124,7 +114,6 @@ void ReaderSniffInit(void) // Find first pause and start sampling ISR(PORTB_INT1_vect) { -// LED_PORT.OUTSET = LED_RED; /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start * demodulating beginning from one bit-width after this edge. */ @@ -141,22 +130,6 @@ ISR(PORTB_INT1_vect) { CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES/2 - 1; /* Half bit width */ CODEC_TIMER_SAMPLING.CCDBUF = SAMPLE_RATE_SYSTEM_CYCLES/8 - 14 - 1; /* Compensate for DIGFILT and ISR prolog */ - /* Setup Frame Delay Timer and wire to EVSYS. Frame delay time is - * measured from last change in RF field, therefore we use - * the event channel 1 (end of modulation pause) as the restart event. - * The preliminary frame delay time chosen here is irrelevant, because - * the correct FDT gets set automatically after demodulation. */ - -// CODEC_TIMER_LOADMOD.CNT = 0; -// CODEC_TIMER_LOADMOD.PER = 0xFFFF; -//// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODEND_EVSEL; -//// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; -//// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; -//// CODEC_TIMER_LOADMOD.CTRLA = CODEC_TIMER_CARRIER_CLKSEL; -// -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = 0; - /* Disable this interrupt */ CODEC_DEMOD_IN_PORT.INT1MASK = 0; } @@ -177,26 +150,10 @@ ISR(TCD0_CCD_vect) { CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - /* By this time, the FDT timer is aligned to the last modulation - * edge of the reader. So we disable the auto-synchronization and - * let it count the frame delay time in the background, and generate - * an interrupt once it has reached the FDT. */ - // Do not activate loadmod -// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = 0; - -// if (SampleRegister & 0x08) { -// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV1 - 40; /* compensate for ISR prolog */ -// } else { -// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV0 - 40; /* compensate for ISR prolog */ -// } + // FDT timer (CODEC_TIMER_LOADMOD) is diabled StateRegister = LOADMOD_FDT; -// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; -// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_HI_gc; - /* Determine if we did not receive a multiple of 8 bits. * If this is the case, right-align the remaining data and * store it into the buffer. */ @@ -287,19 +244,10 @@ INLINE void ReaderSniffDeInit(void) CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - - -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; - } - - ///////////////////////////////////////////////// // Card->Reader Direction Traffic ///////////////////////////////////////////////// @@ -337,8 +285,6 @@ ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered befor // if the half bit duration is not modulated, then add 0 to buffer ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found { - - uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL; CODEC_TIMER_TIMESTAMPS.CNT = 0; @@ -376,13 +322,10 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found Insert0(); return; } - return; } // EOC of Card->Reader found ISR(TCD1_CCB_vect) // EOC found { -// Reader14443A_EOC(); - CODEC_TIMER_LOADMOD.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; @@ -413,50 +356,29 @@ ISR(TCD1_CCB_vect) // EOC found State = STATE_FDT; } -//// End of Card-> reader communication and enter frame delay time -//void Reader14443A_EOC(void) -//{ -// -// -//} INLINE void CardSniffInit(void) { TrafficSource = TRAFFIC_CARD; - //////////////////////////// - // Same as reader init /* Initialize common peripherals and start listening - * for incoming data. */ + * for incoming data. */ -// CodecInitCommon(); - - -// CodecSetDemodPower(true); - -// CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; -// CODEC_TIMER_SAMPLING.CCB = 0; -// CODEC_TIMER_SAMPLING.CCC = 0; + // No need to implement FDT, timer disabled CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTCTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; -// CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; CODEC_TIMER_LOADMOD.CTRLA = 0; State = STATE_IDLE; -// BitCount = 0; CodecBufferPtr = CodecBuffer; // use GPIOR for faster access BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly SampleRegister = 0x00; -// Flags.Start = false; -// Flags.RxPending = false; Flags.RxDone = false; - /////////////////////////// - Flags.Start = true; // reset for future use // CodecBufferIdx = 0; @@ -464,8 +386,6 @@ INLINE void CardSniffInit(void) Flags.RxPending = true; -// StartDemod(); - /* * Prepare for Manchester decoding. * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal @@ -503,16 +423,6 @@ INLINE void CardSniffInit(void) CODEC_DEMOD_IN_PORT.INTCTRL = 0; - -// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; -// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; -// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; -// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; -// PORTE.OUTTGL = PIN3_bm; - - // CODEC_TIMER_SAMPLING_CCC_vect - - /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause * needs to be found. */ @@ -521,16 +431,6 @@ INLINE void CardSniffInit(void) ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; // RxPendingSince = SystemGetSysTick(); - - -// State = STATE_IDLE; -// PORTE.OUTTGL = PIN3_bm; - - //Flags.RxPending = true; - - //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); - //Reader14443A_EOC(); - } INLINE void CardSniffDeinit(void) @@ -565,23 +465,14 @@ INLINE void CardSniffDeinit(void) void Sniff14443ACodecInit(void) { -// Flags.DemodFinished = 0; - -// SniffEnable = true; - // Common Codec Register settings CodecInitCommon(); // Enable demodulator power CodecSetDemodPower(true); // Start with sniffing Reader->Card direction traffic - // Card -> Reader traffic sniffing interrupt will be enbaled - // when Reader-> Card direction sniffing finished - // See ISO14443-2A.c ISO14443ACodecTask() ReaderSniffInit(); - // Also configure Interrupt settings for Reader function -// Reader14443ACodecInit(); } void Sniff14443ACodecDeInit(void) @@ -607,24 +498,13 @@ void Sniff14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); -// if(SniffEnable == true){ - // TODO: Start interrupt for finding Card -> Reader direction traffic - ReaderSniffDeInit(); CardSniffInit(); -// ISO14443ACodecDeInit(); - -// TestSniff14443ACodecInit(); return; -// } } -// -// /* No data to be processed. Disable loadmodding and start listening again */ -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = 0; - - ReaderSniffInit(); + // Get nothing, Start sniff again + ReaderSniffInit(); } @@ -701,21 +581,11 @@ void Sniff14443ACodecTask(void) Flags.RxPending=true; - -// if (SniffEnable) -// { - -// LED_PORT.OUTCLR = LED_RED; + // Disable card sniffing and enable reader sniffing CardSniffDeinit(); -// TrafficSource = TRAFFIC_READER; ReaderSniffInit(); -// Sniff14443ACodecInit(); -// ReaderSniffInit(); -// Reader14443ACodecDeInit(); -// ISO14443ACodecInit(); return; -// } } } @@ -725,38 +595,8 @@ void Sniff14443ACodecTask(void) /* Call application with received data */ BitCount = ApplicationProcess(CodecBuffer, BitCount); - // Application have data to be sent -// if (false)//BitCount > 0) -// { - -// StartDemod(); -// -// LEDHook(LED_CODEC_TX, LED_PULSE); -// LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); -// -// /* Set state and start timer for Miller encoding. */ -// // Send bits to card using TCD0_CCB interrupt (See Reader14443-ISR.S) -// BufferToSequence(); -// State = STATE_MILLER_SEND; -// CodecBufferPtr = CodecBuffer; -// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm; -// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_HI_gc; -// _delay_loop_1(85); // Wait for sending to finish - - -// }else{ // No data need to be send or in SNIFFING mode - // TODO: add another sniff flag, in case of no Application data need to be send (Non sniffing mode) -// StartDemod(); -// Reader14443AMillerEOC(); - - // Sniffing mode, enable sampling interrupt only -// } } -// Reader14443ACodecTask(); - } -// ISO14443ACodecDeInit(); -// Reader14443ACodecTask(); } From 2fa4a94fb9cd09372921cf9d062e4d83522ec841 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 13:45:46 +0100 Subject: [PATCH 16/50] name Interrupt vectors (cherry picked from commit 8d15036) --- Firmware/Chameleon-Mini/Codec/Codec.h | 5 +++++ Firmware/Chameleon-Mini/Codec/Reader14443-2A.c | 2 +- Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c | 6 +++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 34b8e34..09dee73 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -39,6 +39,7 @@ #define CODEC_DEMOD_IN_EVMUX0 EVSYS_CHMUX_PORTB_PIN1_gc #define CODEC_DEMOD_IN_EVMUX1 EVSYS_CHMUX_PORTB_PIN2_gc #define CODEC_DEMOD_IN_INT0_VECT PORTB_INT0_vect +#define CODEC_DEMOD_IN_INT1_VECT PORTB_INT1_vect #define CODEC_LOADMOD_PORT PORTC #define CODEC_LOADMOD_MASK PIN6_bm #define CODEC_CARRIER_IN_PORT PORTC @@ -58,6 +59,8 @@ #define CODEC_TIMER_SAMPLING TCD0 #define CODEC_TIMER_SAMPLING_CCA_VECT TCD0_CCA_vect #define CODEC_TIMER_SAMPLING_CCB_VECT TCD0_CCB_vect +#define CODEC_TIMER_SAMPLING_CCC_VECT TCD0_CCC_vect +#define CODEC_TIMER_SAMPLING_CCD_VECT TCD0_CCD_vect #define CODEC_TIMER_LOADMOD TCE0 #define CODEC_TIMER_LOADMOD_OVF_VECT TCE0_OVF_vect #define CODEC_TIMER_LOADMOD_CCA_VECT TCE0_CCA_vect @@ -81,6 +84,8 @@ #define CODEC_THRESHOLD_CALIBRATE_STEPS 16 #define CODEC_TIMER_TIMESTAMPS TCD1 #define CODEC_TIMER_TIMESTAMPS_CCA_VECT TCD1_CCA_vect +#define CODEC_TIMER_TIMESTAMPS_CCB_VECT TCD1_CCB_vect + #define CODEC_BUFFER_SIZE 256 diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index d9cabbe..1bea53b 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -179,7 +179,7 @@ INLINE void BufferToSequence(void) CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); } // Frame Delay Time PCD to PICC ends -ISR (TCD0_CCC_vect) +ISR (CODEC_TIMER_SAMPLING_CCC_VECT) { CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index dd1e573..b7200a9 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -113,7 +113,7 @@ void ReaderSniffInit(void) // Find first pause and start sampling -ISR(PORTB_INT1_vect) { +ISR(CODEC_DEMOD_IN_INT1_VECT) { /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start * demodulating beginning from one bit-width after this edge. */ @@ -135,7 +135,7 @@ ISR(PORTB_INT1_vect) { } // Sampling with timer and demod -ISR(TCD0_CCD_vect) { +ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* This interrupt gets called twice for every bit to sample it. */ uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; @@ -324,7 +324,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found } } // EOC of Card->Reader found -ISR(TCD1_CCB_vect) // EOC found +ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found { CODEC_TIMER_LOADMOD.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; From 6f020e492fc3002420e4f7aa021a1dd134e6dfa3 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 17:30:06 +0100 Subject: [PATCH 17/50] Remove unused flags Add timeout for resetting to Reader->Card sniffing when no data get from Card->Reader sniffing (cherry picked from commit 6e88ae7) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 104 ++++++++---------- 1 file changed, 43 insertions(+), 61 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index b7200a9..a6883f6 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -45,11 +45,7 @@ enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; -// volatile bool LoadmodFinished; - volatile bool Start; volatile bool RxDone; - volatile bool RxPending; - } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -77,6 +73,7 @@ static volatile enum { void ReaderSniffInit(void) { + LED_PORT.OUTCLR = LED_RED; // Configure interrupt for demod // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; @@ -172,7 +169,8 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; - } else { + } + else { /* Otherwise, we check the two sample bits from the bit before. */ uint8_t BitSample = SampleRegister & 0xC; uint8_t Bit = 0; @@ -182,7 +180,8 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { if (BitSample & (0x1 << 2)) { /* 01 sequence or 11 sequence -> This is a zero bit */ Bit = 0; - } else { + } + else { /* 10 sequence -> This is a one bit */ Bit = 1; } @@ -206,19 +205,23 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { StateRegister = DEMOD_PARITY_BIT; } - } else if (StateRegister == DEMOD_PARITY_BIT) { + } + else if (StateRegister == DEMOD_PARITY_BIT) { /* This is a parity bit. Store it */ *ParityBufferPtr++ = Bit; StateRegister = DEMOD_DATA_BIT; - } else { + } + else { /* Should never Happen (TM) */ } - } else { + } + else { /* 00 sequence. -> No valid data yet. This also occurs if we just started * sampling and have sampled less than 2 bits yet. Thus ignore. */ } } - } else { + } + else { /* On odd sample position just sample. */ SampleIdxRegister = ~SampleIdxRegister; } @@ -271,8 +274,6 @@ INLINE void Insert1(void) // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { -// LED_PORT.OUTSET=LED_RED; - ACA.AC0CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_gc; @@ -303,8 +304,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found return; case 81 ... 112: // 96 ticks are 3 half bit periods - if (BitCount & 1) - { + if (BitCount & 1) { Insert1(); Insert1(); Insert0(); @@ -332,8 +332,7 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; ACA.AC0CTRL &= ~AC_ENABLE_bm; - if (BitCount & 1) - { + if (BitCount & 1) { if (SampleRegister & 0x80) Insert0(); else @@ -343,7 +342,6 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); Flags.RxDone = true; - Flags.RxPending = false; // set up timer that forces the minimum frame delay time from PICC to PCD CODEC_TIMER_LOADMOD.PER = 0xFFFF; @@ -379,13 +377,10 @@ INLINE void CardSniffInit(void) SampleRegister = 0x00; Flags.RxDone = false; - Flags.Start = true; // reset for future use // CodecBufferIdx = 0; // BitCountUp = 0; - Flags.RxPending = true; - /* * Prepare for Manchester decoding. * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal @@ -418,7 +413,7 @@ INLINE void CardSniffInit(void) CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC1 INT + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; CODEC_DEMOD_IN_PORT.INTCTRL = 0; @@ -430,13 +425,12 @@ INLINE void CardSniffInit(void) ACA.STATUS = AC_AC0IF_bm; ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; -// RxPendingSince = SystemGetSysTick(); + RxPendingSince = SystemGetSysTick(); } INLINE void CardSniffDeinit(void) { - // CodecSetDemodPower(false); - // CodecReaderFieldStop(); + CODEC_TIMER_SAMPLING.CTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = 0; @@ -444,18 +438,14 @@ INLINE void CardSniffDeinit(void) - EVSYS.CH2MUX = 0; // on every ACA_AC1 INT + EVSYS.CH2MUX = 0; // on every ACA_AC0 INT EVSYS.CH2CTRL = 0; ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - - Flags.RxDone = false; - Flags.RxPending = false; - Flags.Start = false; - -// Reader14443ACodecDeInit(); +// Flags.RxPending = false; +// Flags.Start = false; } @@ -486,8 +476,8 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { - - if (TrafficSource == TRAFFIC_READER){ + // Reader->Card Task + if (TrafficSource == TRAFFIC_READER) { if (Flags.DemodFinished) { Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ @@ -506,26 +496,14 @@ void Sniff14443ACodecTask(void) // Get nothing, Start sniff again ReaderSniffInit(); } - - } - - else // Card->Reader Task + // Card->Reader Task + else { - - // Waiting for response time out -// if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) -// { -// Reader14443A_EOC(); -// BitCount = 0; -// Flags.RxDone = true; -// Flags.RxPending = false; -// } // if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) // return; - if (!Flags.RxPending && (Flags.Start || Flags.RxDone)) - { - + // Receive finished + if (Flags.RxDone) { // if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) { // we are in frame delay time, so we can return later // return; // } @@ -533,10 +511,10 @@ void Sniff14443ACodecTask(void) if (Flags.RxDone && BitCount > 0) // decode the raw received data { - if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) - { + if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { BitCount = 0; - } else { + } + else { uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; memcpy(TmpCodecBuffer, CodecBuffer, (BitCount + 7) / 8); @@ -548,12 +526,10 @@ void Sniff14443ACodecTask(void) TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored // Manchester Code ISO14443-2 8.2.5 - while (!breakflag && BitCountTmp < TotalBitCount) - { + while (!breakflag && BitCountTmp < TotalBitCount) { uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; TmpCodecBuffer[BitCountTmp / 8] >>= 2; - switch (Bit) - { + switch (Bit) { case 0b10: Insert1(); break; @@ -579,22 +555,28 @@ void Sniff14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); - Flags.RxPending=true; - // Disable card sniffing and enable reader sniffing CardSniffDeinit(); ReaderSniffInit(); return; } - } - Flags.Start = false; Flags.RxDone = false; /* Call application with received data */ BitCount = ApplicationProcess(CodecBuffer, BitCount); - + } + else // Receive not finished yet, Continue waiting + { + // If Waiting for response time out + // Reset to reader sniffing + if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) ) { + Flags.RxDone = true; + // Disable card sniffing and enable reader sniffing + CardSniffDeinit(); + ReaderSniffInit(); + } } } } From cb49799de1d1d06fa93be590c74049603cadf6f6 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sat, 14 Jul 2018 18:52:48 +0100 Subject: [PATCH 18/50] Fix bug: ACA interrupt start after the card->Reader traffic start, so sometimes get not complete trace Another buffer used for store card->reader traffic is added, so that card->reader traffic sniffing can start right after the reader->Card trafic sniffing finished. (cherry picked from commit e074fcc) --- Firmware/Chameleon-Mini/Codec/Codec.c | 2 +- Firmware/Chameleon-Mini/Codec/Codec.h | 3 + .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 283 ++++++++++-------- 3 files changed, 162 insertions(+), 126 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.c b/Firmware/Chameleon-Mini/Codec/Codec.c index 56f2774..adfb60d 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.c +++ b/Firmware/Chameleon-Mini/Codec/Codec.c @@ -23,7 +23,7 @@ static volatile struct { } ReaderFieldFlags = { false }; uint8_t CodecBuffer[CODEC_BUFFER_SIZE]; - +uint8_t CodecBuffer2[CODEC_BUFFER_SIZE]; // the following three functions prevent sending data directly after turning on the reader field void CodecReaderFieldStart(void) // DO NOT CALL THIS FUNCTION INSIDE APPLICATION! { diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 09dee73..cdc82cd 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -99,6 +99,8 @@ #define CodecCount16Register2 (*((volatile uint16_t*) &GPIOR6)) /* GPIOR4 & GPIOR5 */ #define CodecPtrRegister1 (*((volatile uint8_t**) &GPIOR8)) #define CodecPtrRegister2 (*((volatile uint8_t**) &GPIORA)) +#define CodecPtrRegister3 (*((volatile uint8_t**) &GPIORC)) + extern uint16_t Reader_FWT; @@ -110,6 +112,7 @@ typedef enum { } SubcarrierModType; extern uint8_t CodecBuffer[CODEC_BUFFER_SIZE]; +extern uint8_t CodecBuffer2[CODEC_BUFFER_SIZE]; INLINE void CodecInit(void) { ActiveConfiguration.CodecInitFunc(); diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index a6883f6..ddd4146 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -30,16 +30,20 @@ #define DataRegister Codec8Reg0 #define StateRegister Codec8Reg1 #define ParityRegister Codec8Reg2 -#define SampleIdxRegister Codec8Reg2 + +#define SampleIdxRegister GPIO4 #define SampleRegister Codec8Reg3 -#define BitSent CodecCount16Register1 +#define SampleRegister2 GPIO5 +//#define BitSent CodecCount16Register1 #define BitCount CodecCount16Register2 #define CodecBufferPtr CodecPtrRegister1 #define ParityBufferPtr CodecPtrRegister2 +#define CodecBufferPtr2 CodecPtrRegister3 -#define BitCountUp GPIOR7 -#define CodecBufferIdx GPIOR8 + +//#define BitCountUp GPIOR7 +//#define CodecBufferIdx GPIOR8 enum RCTraffic TrafficSource; @@ -65,12 +69,12 @@ static volatile enum { STATE_MILLER_EOF, STATE_FDT } State; - +uint16_t DemodBitCount; ///////////////////////////////////////////////// // Reader->Card Direction Traffic ///////////////////////////////////////////////// -void ReaderSniffInit(void) +INLINE void ReaderSniffInit(void) { LED_PORT.OUTCLR = LED_RED; @@ -78,8 +82,6 @@ void ReaderSniffInit(void) // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; - TrafficSource = TRAFFIC_READER; - /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; @@ -107,6 +109,116 @@ void ReaderSniffInit(void) // ISO14443ACodecInit(); } +INLINE void ReaderSniffDeInit(void) +{ + /* Gracefully shutdown codec */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + + Flags.DemodFinished = 0; + + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; +} + +INLINE void CardSniffInit(void) +{ + /* Initialize common peripherals and start listening + * for incoming data. */ + + + // No need to implement FDT, timer disabled + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; + + CODEC_TIMER_LOADMOD.CTRLA = 0; + State = STATE_IDLE; + + CodecBufferPtr2 = CodecBuffer2; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister2 = 0x00; + + Flags.RxDone = false; + // reset for future use +// CodecBufferIdx = 0; +// BitCountUp = 0; + + /* + * Prepare for Manchester decoding. + * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal + * passes a (configurable) threshold. This is realized with the event system and an analog + * comparator. + * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we + * assume there is a pause. Now we read the second timers count value and can decide how many + * bit halves had modulations since the last pause. + */ + + // Comparator ADC + /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; + + /* This timer will be used to detect the pauses between the modulation sequences. */ + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width + CODEC_TIMER_LOADMOD.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc; + + /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ + CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer + CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; + CODEC_TIMER_TIMESTAMPS.CCB = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT + EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; + + CODEC_DEMOD_IN_PORT.INTCTRL = 0; + + /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, + * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause + * needs to be found. */ + ACA.AC1CTRL = 0; + ACA.STATUS = AC_AC0IF_bm; + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + + RxPendingSince = SystemGetSysTick(); + PORTE.OUTSET = PIN3_bm; + + +} + +INLINE void CardSniffDeinit(void) +{ + PORTE.OUTCLR = PIN3_bm; + + + CODEC_TIMER_SAMPLING.CTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + + + + EVSYS.CH2MUX = 0; // on every ACA_AC0 INT + EVSYS.CH2CTRL = 0; + ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; + ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; + + Flags.RxDone = false; +// Flags.RxPending = false; +// Flags.Start = false; + + +} + // Find first pause and start sampling @@ -169,6 +281,23 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; + DemodBitCount = BitCount; + + /* Gracefully shutdown codec */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + +// Flags.DemodFinished = 0; + + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + + +// ReaderSniffDeInit(); + CardSniffInit(); + return; + } else { /* Otherwise, we check the two sample bits from the bit before. */ @@ -236,18 +365,7 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { -INLINE void ReaderSniffDeInit(void) -{ - /* Gracefully shutdown codec */ - CODEC_DEMOD_IN_PORT.INT1MASK = 0; - Flags.DemodFinished = 0; - - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; - CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; -} @@ -257,18 +375,18 @@ INLINE void ReaderSniffDeInit(void) INLINE void Insert0(void) { - SampleRegister >>= 1; + SampleRegister2 >>= 1; if (++BitCount % 8) return; - *CodecBufferPtr++ = SampleRegister; + *CodecBufferPtr2++ = SampleRegister2; } INLINE void Insert1(void) { - SampleRegister = (SampleRegister >> 1) | 0x80; + SampleRegister2 = (SampleRegister2 >> 1) | 0x80; if (++BitCount % 8) return; - *CodecBufferPtr++ = SampleRegister; + *CodecBufferPtr2++ = SampleRegister2; } // This interrupt find Card -> Reader SOC @@ -333,14 +451,14 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found ACA.AC0CTRL &= ~AC_ENABLE_bm; if (BitCount & 1) { - if (SampleRegister & 0x80) + if (SampleRegister2 & 0x80) Insert0(); else Insert1(); } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); Flags.RxDone = true; // set up timer that forces the minimum frame delay time from PICC to PCD @@ -356,97 +474,6 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found } -INLINE void CardSniffInit(void) -{ - TrafficSource = TRAFFIC_CARD; - - /* Initialize common peripherals and start listening - * for incoming data. */ - - - // No need to implement FDT, timer disabled - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; - - CODEC_TIMER_LOADMOD.CTRLA = 0; - State = STATE_IDLE; - - CodecBufferPtr = CodecBuffer; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister = 0x00; - - Flags.RxDone = false; - // reset for future use -// CodecBufferIdx = 0; -// BitCountUp = 0; - - /* - * Prepare for Manchester decoding. - * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal - * passes a (configurable) threshold. This is realized with the event system and an analog - * comparator. - * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we - * assume there is a pause. Now we read the second timers count value and can decide how many - * bit halves had modulations since the last pause. - */ - - // Comparator ADC - /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ - ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; - - /* This timer will be used to detect the pauses between the modulation sequences. */ - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.CNT = 0; - CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width - CODEC_TIMER_LOADMOD.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; - CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc; - - /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ - CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer - CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; - CODEC_TIMER_TIMESTAMPS.CCB = 160; - CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; - CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; - - /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT - EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; - - CODEC_DEMOD_IN_PORT.INTCTRL = 0; - - /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, - * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause - * needs to be found. */ - ACA.AC1CTRL = 0; - ACA.STATUS = AC_AC0IF_bm; - ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - - RxPendingSince = SystemGetSysTick(); -} - -INLINE void CardSniffDeinit(void) -{ - - CODEC_TIMER_SAMPLING.CTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - - - - EVSYS.CH2MUX = 0; // on every ACA_AC0 INT - EVSYS.CH2CTRL = 0; - ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; - ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - - Flags.RxDone = false; -// Flags.RxPending = false; -// Flags.Start = false; -} ///////////////////////////////////////////////// @@ -455,12 +482,14 @@ INLINE void CardSniffDeinit(void) void Sniff14443ACodecInit(void) { + PORTE.DIRSET= PIN3_bm; // Common Codec Register settings CodecInitCommon(); // Enable demodulator power CodecSetDemodPower(true); // Start with sniffing Reader->Card direction traffic + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); } @@ -476,24 +505,25 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { + // Reader->Card Task if (TrafficSource == TRAFFIC_READER) { if (Flags.DemodFinished) { Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ - uint16_t DemodBitCount = BitCount; +// uint16_t DemodBitCount = BitCount; if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { // For logging data LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); - ReaderSniffDeInit(); - CardSniffInit(); + TrafficSource = TRAFFIC_CARD; return; } // Get nothing, Start sniff again + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); } } @@ -503,7 +533,7 @@ void Sniff14443ACodecTask(void) // if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) // return; // Receive finished - if (Flags.RxDone) { + if (Flags.RxDone ) { // if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) { // we are in frame delay time, so we can return later // return; // } @@ -516,9 +546,9 @@ void Sniff14443ACodecTask(void) } else { uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer, (BitCount + 7) / 8); + memcpy(TmpCodecBuffer, CodecBuffer2, (BitCount + 7) / 8); - CodecBufferPtr = CodecBuffer; + CodecBufferPtr2 = CodecBuffer2; uint16_t BitCountTmp = 2, TotalBitCount = BitCount; BitCount = 0; @@ -549,14 +579,15 @@ void Sniff14443ACodecTask(void) BitCountTmp += 2; } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); // BitCount = removeParityBits(CodecBuffer, BitCount); - LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); + LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); return; @@ -565,7 +596,7 @@ void Sniff14443ACodecTask(void) Flags.RxDone = false; /* Call application with received data */ - BitCount = ApplicationProcess(CodecBuffer, BitCount); + BitCount = ApplicationProcess(CodecBuffer2, BitCount); } else // Receive not finished yet, Continue waiting { @@ -575,10 +606,12 @@ void Sniff14443ACodecTask(void) Flags.RxDone = true; // Disable card sniffing and enable reader sniffing CardSniffDeinit(); + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); } } } + } From bf41815dbd042f65f3c1ffe610e1e499802c4135 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 16 Jul 2018 17:35:57 +0100 Subject: [PATCH 19/50] Sniffing Code Optimization Remove code related to FDT in sniffing mode Remove some redundant variables (cherry picked from commit 7254eb2) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 320 +++++++----------- .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 1 - 2 files changed, 125 insertions(+), 196 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index ddd4146..ca3ab4b 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -1,10 +1,10 @@ // // Created by Zitai Chen on 05/07/2018. -// Some interrupt handling vect -// modified form ISO14443-2A.c and Reader14443-2A.c +// Sniffing Function of ISO14443-2A cards +// Wors in both direction: PCD->PICC, PICC->PCD, +// modified from ISO14443-2A.c and Reader14443-2A.c // -// TODO: implement pending since to automatically reset the sniffing after a period of no traffic #include "SniffISO14443-2A.h" #include "Reader14443-2A.h" @@ -17,34 +17,27 @@ /* Sampling is done using internal clock, synchronized to the field modulation. * For that we need to convert the bit rate for the internal clock. */ -#define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) - +#define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) #define ISO14443A_MIN_BITS_PER_FRAME 7 // Card to reader #define ISO14443A_PICC_TO_PCD_FDT_PRESCALER TC_CLKSEL_DIV8_gc // please change ISO14443A_PICC_TO_PCD_MIN_FDT when changing this -#define ISO14443A_RX_MINIMUM_BITCOUNT 4 - +#define ISO14443A_RX_MINIMUM_BITCOUNT 4 /* Define pseudo variables to use fast register access. This is useful for global vars */ #define DataRegister Codec8Reg0 #define StateRegister Codec8Reg1 #define ParityRegister Codec8Reg2 -#define SampleIdxRegister GPIO4 -#define SampleRegister Codec8Reg3 -#define SampleRegister2 GPIO5 -//#define BitSent CodecCount16Register1 +#define SampleIdxRegister Codec8Reg3 +#define ReaderSampleR GPIOR4 +#define CardSampleR GPIOR5 #define BitCount CodecCount16Register2 -#define CodecBufferPtr CodecPtrRegister1 +#define ReaderBufferPtr CodecPtrRegister1 #define ParityBufferPtr CodecPtrRegister2 -#define CodecBufferPtr2 CodecPtrRegister3 +#define CardBufferPtr CodecPtrRegister3 - -//#define BitCountUp GPIOR7 -//#define CodecBufferIdx GPIOR8 - enum RCTraffic TrafficSource; static volatile struct { @@ -53,23 +46,16 @@ static volatile struct { } Flags = { 0 }; static volatile uint16_t RxPendingSince; - typedef enum { - /* Demod */ - DEMOD_DATA_BIT, + DEMOD_DATA_BIT, /* Demod */ DEMOD_PARITY_BIT, - LOADMOD_FDT, - } StateType; - -static volatile enum { - STATE_IDLE, - STATE_MILLER_SEND, - STATE_MILLER_EOF, - STATE_FDT -} State; uint16_t DemodBitCount; + +INLINE void CardSniffInit(void); +INLINE void CardSniffDeinit(void); + ///////////////////////////////////////////////// // Reader->Card Direction Traffic ///////////////////////////////////////////////// @@ -79,16 +65,15 @@ INLINE void ReaderSniffInit(void) LED_PORT.OUTCLR = LED_RED; // Configure interrupt for demod - // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; - CodecBufferPtr = CodecBuffer; + ReaderBufferPtr = CodecBuffer; ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; DataRegister = 0; - SampleRegister = 0; + ReaderSampleR = 0; SampleIdxRegister = 0; BitCount = 0; StateRegister = DEMOD_DATA_BIT; @@ -106,13 +91,12 @@ INLINE void ReaderSniffInit(void) /* Start looking out for modulation pause via interrupt. */ CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT1IF_bm; CODEC_DEMOD_IN_PORT.INT1MASK = CODEC_DEMOD_IN_MASK0; - -// ISO14443ACodecInit(); } INLINE void ReaderSniffDeInit(void) { /* Gracefully shutdown codec */ CODEC_DEMOD_IN_PORT.INT1MASK = 0; + CODEC_DEMOD_IN_PORT.INTCTRL = 0; Flags.DemodFinished = 0; @@ -122,104 +106,6 @@ INLINE void ReaderSniffDeInit(void) CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; } -INLINE void CardSniffInit(void) -{ - /* Initialize common peripherals and start listening - * for incoming data. */ - - - // No need to implement FDT, timer disabled - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; - - CODEC_TIMER_LOADMOD.CTRLA = 0; - State = STATE_IDLE; - - CodecBufferPtr2 = CodecBuffer2; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister2 = 0x00; - - Flags.RxDone = false; - // reset for future use -// CodecBufferIdx = 0; -// BitCountUp = 0; - - /* - * Prepare for Manchester decoding. - * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal - * passes a (configurable) threshold. This is realized with the event system and an analog - * comparator. - * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we - * assume there is a pause. Now we read the second timers count value and can decide how many - * bit halves had modulations since the last pause. - */ - - // Comparator ADC - /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ - ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; - - /* This timer will be used to detect the pauses between the modulation sequences. */ - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.CNT = 0; - CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width - CODEC_TIMER_LOADMOD.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; - CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc; - - /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ - CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer - CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; - CODEC_TIMER_TIMESTAMPS.CCB = 160; - CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; - CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; - - /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT - EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; - - CODEC_DEMOD_IN_PORT.INTCTRL = 0; - - /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, - * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause - * needs to be found. */ - ACA.AC1CTRL = 0; - ACA.STATUS = AC_AC0IF_bm; - ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - - RxPendingSince = SystemGetSysTick(); - PORTE.OUTSET = PIN3_bm; - - -} - -INLINE void CardSniffDeinit(void) -{ - PORTE.OUTCLR = PIN3_bm; - - - CODEC_TIMER_SAMPLING.CTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - - - - EVSYS.CH2MUX = 0; // on every ACA_AC0 INT - EVSYS.CH2CTRL = 0; - ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; - ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - - Flags.RxDone = false; -// Flags.RxPending = false; -// Flags.Start = false; - - -} - - // Find first pause and start sampling ISR(CODEC_DEMOD_IN_INT1_VECT) { @@ -249,19 +135,23 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; /* Shift sampled bit into sampling register */ - SampleRegister = (SampleRegister << 1) | (!SamplePin ? 0x01 : 0x00); + ReaderSampleR = (ReaderSampleR << 1) | (!SamplePin ? 0x01 : 0x00); if (SampleIdxRegister) { SampleIdxRegister = 0; /* Analyze the sampling register after 2 samples. */ - if ((SampleRegister & 0x07) == 0x07) { + if ((ReaderSampleR & 0x07) == 0x07) { /* No carrier modulation for 3 sample points. EOC! */ + + // Shutdown the Reader->Card Sniffing, + // disable the sampling timer + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - - // FDT timer (CODEC_TIMER_LOADMOD) is diabled - - StateRegister = LOADMOD_FDT; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_DEMOD_IN_PORT.INTCTRL = 0; // Disable CODEC_DEMOD_IN_PORT interrupt + // CTRLD already disabled in CODEC_DEMOD_IN_INT1_VECT, + // so no need to disable it again it here /* Determine if we did not receive a multiple of 8 bits. * If this is the case, right-align the remaining data and @@ -276,32 +166,22 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { } /* TODO: Prevent buffer overflow */ - *CodecBufferPtr = NewDataRegister; + *ReaderBufferPtr = NewDataRegister; } /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; DemodBitCount = BitCount; - /* Gracefully shutdown codec */ - CODEC_DEMOD_IN_PORT.INT1MASK = 0; - -// Flags.DemodFinished = 0; - - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; - CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - - -// ReaderSniffDeInit(); + // Start Card->Reader Sniffing without waiting for the complete of CodecTask + // Otherwise some bit will not be captured CardSniffInit(); return; } else { /* Otherwise, we check the two sample bits from the bit before. */ - uint8_t BitSample = SampleRegister & 0xC; + uint8_t BitSample = ReaderSampleR & 0xC; uint8_t Bit = 0; if (BitSample != (0x0 << 2)) { @@ -327,7 +207,7 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { if ((NewBitCount & 0x07) == 0) { /* We have reached a byte boundary! Store the data register. */ /* TODO: Prevent buffer overflow */ - *CodecBufferPtr++ = NewDataRegister; + *ReaderBufferPtr++ = NewDataRegister; /* Store bit for determining FDT at EOC and enable parity * handling on next bit. */ @@ -362,31 +242,102 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; } - - - - - - - ///////////////////////////////////////////////// // Card->Reader Direction Traffic ///////////////////////////////////////////////// +INLINE void CardSniffInit(void) +{ + /* Initialize common peripherals and start listening + * for incoming data. */ + + CardBufferPtr = CodecBuffer2; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + CardSampleR = 0x00; + + Flags.RxDone = false; + + /* + * Prepare for Manchester decoding. + * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal + * passes a (configurable) threshold. This is realized with the event system and an analog + * comparator. + * Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we + * assume there is a pause. Now we read the second timers count value and can decide how many + * bit halves had modulations since the last pause. + */ + + // Comparator ADC + /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; + + /* This timer will be used to detect the pauses between the modulation sequences. */ + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width + CODEC_TIMER_LOADMOD.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc; + + /* This timer will be used to find out how many bit halfs since the last pause have been passed. */ + CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer + CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF; + CODEC_TIMER_TIMESTAMPS.CCB = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT + EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; + + /* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer, + * or it is triggered before the SOC, which mostly isn't bad at all, since the first pause + * needs to be found. */ + ACA.AC1CTRL = 0; + ACA.STATUS = AC_AC0IF_bm; + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + + RxPendingSince = SystemGetSysTick(); + PORTE.OUTSET = PIN3_bm; + + +} + +INLINE void CardSniffDeinit(void) +{ + PORTE.OUTCLR = PIN3_bm; + + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + + // Disable event system CH2 + EVSYS.CH2MUX = 0; + EVSYS.CH2CTRL = 0; + // Reset ACA AC0 to default setting + ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; + ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; + + Flags.RxDone = false; +} + + + INLINE void Insert0(void) { - SampleRegister2 >>= 1; + CardSampleR >>= 1; if (++BitCount % 8) return; - *CodecBufferPtr2++ = SampleRegister2; + *CardBufferPtr++ = CardSampleR; } INLINE void Insert1(void) { - SampleRegister2 = (SampleRegister2 >> 1) | 0x80; + CardSampleR = (CardSampleR >> 1) | 0x80; if (++BitCount % 8) return; - *CodecBufferPtr2++ = SampleRegister2; + *CardBufferPtr++ = CardSampleR; } // This interrupt find Card -> Reader SOC @@ -444,38 +395,28 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found // EOC of Card->Reader found ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found { - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + // Disable LOADMOD Timer + CODEC_TIMER_LOADMOD.INTCTRLB = 0; // Disable Interrupt + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; // Disable Clock + CODEC_TIMER_LOADMOD.CTRLD = 0; // Disable connection to event channel + CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; ACA.AC0CTRL &= ~AC_ENABLE_bm; if (BitCount & 1) { - if (SampleRegister2 & 0x80) + if (CardSampleR & 0x80) Insert0(); else Insert1(); } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); Flags.RxDone = true; - // set up timer that forces the minimum frame delay time from PICC to PCD - CODEC_TIMER_LOADMOD.PER = 0xFFFF; - CODEC_TIMER_LOADMOD.CNT = 0; - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLD = 0; - CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; - - State = STATE_FDT; - } - - - ///////////////////////////////////////////////// // Init and deInit, task, functions for this codec ///////////////////////////////////////////////// @@ -505,13 +446,11 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { - // Reader->Card Task if (TrafficSource == TRAFFIC_READER) { if (Flags.DemodFinished) { Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ -// uint16_t DemodBitCount = BitCount; if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { // For logging data @@ -530,14 +469,8 @@ void Sniff14443ACodecTask(void) // Card->Reader Task else { -// if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) -// return; // Receive finished - if (Flags.RxDone ) { -// if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) { // we are in frame delay time, so we can return later -// return; -// } - + if (Flags.RxDone) { if (Flags.RxDone && BitCount > 0) // decode the raw received data { @@ -548,7 +481,7 @@ void Sniff14443ACodecTask(void) uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; memcpy(TmpCodecBuffer, CodecBuffer2, (BitCount + 7) / 8); - CodecBufferPtr2 = CodecBuffer2; + CardBufferPtr = CodecBuffer2; uint16_t BitCountTmp = 2, TotalBitCount = BitCount; BitCount = 0; @@ -579,7 +512,7 @@ void Sniff14443ACodecTask(void) BitCountTmp += 2; } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); // BitCount = removeParityBits(CodecBuffer, BitCount); @@ -613,6 +546,3 @@ void Sniff14443ACodecTask(void) } } - - - diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h index 44d50c8..b8616b0 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -9,7 +9,6 @@ #include "Codec.h" #include "Terminal/CommandLine.h" -extern bool SniffEnable; extern enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; /* Codec Interface */ void Sniff14443ACodecInit(void); From 2a3b5c51ef2871bf5cb2af93ae6bca5f1f4abce2 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 16 Jul 2018 18:27:16 +0100 Subject: [PATCH 20/50] Add new log type for sniffing log (cherry picked from commit e63396e) --- Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c | 6 +++--- Firmware/Chameleon-Mini/Log.h | 8 ++++++++ Software/Chameleon/Log.py | 6 ++++++ Software/chamlog.py | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index ca3ab4b..6d4b996 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -454,7 +454,7 @@ void Sniff14443ACodecTask(void) if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { // For logging data - LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); TrafficSource = TRAFFIC_CARD; @@ -515,8 +515,8 @@ void Sniff14443ACodecTask(void) CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); // BitCount = removeParityBits(CodecBuffer, BitCount); - - LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); + LEDHook(LED_CODEC_RX, LED_PULSE); + LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); diff --git a/Firmware/Chameleon-Mini/Log.h b/Firmware/Chameleon-Mini/Log.h index ce0bbfd..3fd3a31 100644 --- a/Firmware/Chameleon-Mini/Log.h +++ b/Firmware/Chameleon-Mini/Log.h @@ -23,6 +23,14 @@ typedef enum { LOG_INFO_CODEC_RX_DATA_W_PARITY = 0x42, ///< Currently active codec received data. LOG_INFO_CODEC_TX_DATA_W_PARITY = 0x43, ///< Currently active codec sent data. + LOG_INFO_CODEC_SNI_READER_DATA = 0x44, //< Sniffing codec receive data from reader + LOG_INFO_CODEC_SNI_READER_DATA_W_PARITY = 0x45, //< Sniffing codec receive data from reader + + LOG_INFO_CODEC_SNI_CARD_DATA = 0x46, //< Sniffing codec receive data from card + LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY = 0x47, //< Sniffing codec receive data from card + + + /* App */ LOG_INFO_APP_CMD_READ = 0x80, ///< Application processed read command. LOG_INFO_APP_CMD_WRITE = 0x81, ///< Application processed write command. diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index bcf7a24..0614e1b 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -25,6 +25,12 @@ eventTypes = { 0x42: { 'name': 'CODEC RX W/PARITY', 'decoder': binaryDecoder }, 0x43: { 'name': 'CODEC TX W/PARITY', 'decoder': binaryDecoder }, + 0x44: { 'name': 'CODEC RX SNI READER', 'decoder': binaryDecoder }, + 0x45: { 'name': 'CODEC RX SNI READER W/PARITY', 'decoder': binaryDecoder }, + 0x46: { 'name': 'CODEC RX SNI CARD', 'decoder': binaryDecoder }, + 0x47: { 'name': 'CODEC RX SNI CARD W/PARITY', 'decoder': binaryDecoder }, + + 0x80: { 'name': 'APP READ', 'decoder': binaryDecoder }, 0x81: { 'name': 'APP WRITE', 'decoder': binaryDecoder }, 0x84: { 'name': 'APP INC', 'decoder': binaryDecoder }, diff --git a/Software/chamlog.py b/Software/chamlog.py index e73d503..76dd87e 100755 --- a/Software/chamlog.py +++ b/Software/chamlog.py @@ -19,7 +19,7 @@ def verboseLog(text): def formatText(log): formatString = '{timestamp:0>5d} ms <{deltaTimestamp:>+6d} ms>:' - formatString += '{eventName:<16} ({dataLength:<3} bytes) [{data}]\n' + formatString += '{eventName:<28} ({dataLength:<3} bytes)\t[{data}]\n' text = '' for logEntry in log: From 14a6bc3c74e2eda48ec327fe7ab98bf997507e01 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 17 Jul 2018 05:01:35 +0100 Subject: [PATCH 21/50] Fix bug, card traffic is not right when using logmode=memory Print log after a round finished Otherwise it will take too much cpu cycles then the card traffic sniffing may not start in time (cherry picked from commit 48c89f5) --- Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 6d4b996..feb110c 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -43,6 +43,7 @@ enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; volatile bool RxDone; + } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -453,12 +454,9 @@ void Sniff14443ACodecTask(void) /* Reception finished. Process the received bytes */ if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { - // For logging data - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); TrafficSource = TRAFFIC_CARD; - return; } // Get nothing, Start sniff again @@ -516,6 +514,10 @@ void Sniff14443ACodecTask(void) // BitCount = removeParityBits(CodecBuffer, BitCount); LEDHook(LED_CODEC_RX, LED_PULSE); + // Print log after a round finished + // Otherwise it will take too much cpu cycles + // then the card traffic sniffing may not start in time + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); // Disable card sniffing and enable reader sniffing @@ -537,6 +539,10 @@ void Sniff14443ACodecTask(void) // Reset to reader sniffing if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) ) { Flags.RxDone = true; + + // If Card sniffing started but no data get + // Then the codec must have sniffed some reader raffic + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); TrafficSource = TRAFFIC_READER; From 7af4cc5ee138fafb34fa643255f1f0ccbeaee5ae Mon Sep 17 00:00:00 2001 From: chenzitai Date: Thu, 19 Jul 2018 14:08:57 +0100 Subject: [PATCH 22/50] Longer reader pending timeout according to ISO-14443-4 5.5 (cherry picked from commit 4347afc) --- Firmware/Chameleon-Mini/Codec/Codec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index cdc82cd..3833f1b 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -25,7 +25,7 @@ #define ISO14443A_BIT_RATE_CYCLES 128 #define ISO14443A_FRAME_DELAY_PREV1 1236 #define ISO14443A_FRAME_DELAY_PREV0 1172 -#define ISO14443A_RX_PENDING_TIMEOUT 1 // ms +#define ISO14443A_RX_PENDING_TIMEOUT 4 // ms /* Peripheral definitions */ #define CODEC_DEMOD_POWER_PORT PORTB From 396cc21be196782e2bed8263118668c5718486b8 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 22 Jul 2018 00:08:11 +0100 Subject: [PATCH 23/50] Start reader sniffing right after card sniffing finished. This fix the bug that the sniffing get wrong data when the time gap between card signal and reader signal is too small (cherry picked from commit 573cb49) --- Firmware/Chameleon-Mini/Codec/Codec.h | 2 +- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 120 ++++++++++++------ 2 files changed, 85 insertions(+), 37 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 3833f1b..23e39e9 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -96,7 +96,7 @@ #define Codec8Reg2 GPIOR2 #define Codec8Reg3 GPIOR3 #define CodecCount16Register1 (*((volatile uint16_t*) &GPIOR4)) /* GPIOR4 & GPIOR5 */ -#define CodecCount16Register2 (*((volatile uint16_t*) &GPIOR6)) /* GPIOR4 & GPIOR5 */ +#define CodecCount16Register2 (*((volatile uint16_t*) &GPIOR6)) /* GPIOR6 & GPIOR7 */ #define CodecPtrRegister1 (*((volatile uint8_t**) &GPIOR8)) #define CodecPtrRegister2 (*((volatile uint8_t**) &GPIORA)) #define CodecPtrRegister3 (*((volatile uint8_t**) &GPIORC)) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index feb110c..2bb6e2d 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -43,6 +43,7 @@ enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; volatile bool RxDone; + volatile bool CardStarted; // If card have send the first bit } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -52,7 +53,8 @@ typedef enum { DEMOD_PARITY_BIT, } StateType; -uint16_t DemodBitCount; +uint16_t ReaderBitCount; +uint16_t CardBitCount; INLINE void CardSniffInit(void); INLINE void CardSniffDeinit(void); @@ -63,8 +65,8 @@ INLINE void CardSniffDeinit(void); INLINE void ReaderSniffInit(void) { +// PORTE.OUTSET = PIN3_bm; - LED_PORT.OUTCLR = LED_RED; // Configure interrupt for demod CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; @@ -95,6 +97,8 @@ INLINE void ReaderSniffInit(void) } INLINE void ReaderSniffDeInit(void) { +// PORTE.OUTCLR = PIN3_bm; + /* Gracefully shutdown codec */ CODEC_DEMOD_IN_PORT.INT1MASK = 0; CODEC_DEMOD_IN_PORT.INTCTRL = 0; @@ -147,6 +151,8 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { // Shutdown the Reader->Card Sniffing, // disable the sampling timer + PORTE.OUTSET = PIN3_bm; + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; @@ -172,11 +178,18 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; - DemodBitCount = BitCount; + ReaderBitCount = BitCount; + // If we are have got data // Start Card->Reader Sniffing without waiting for the complete of CodecTask // Otherwise some bit will not be captured - CardSniffInit(); + if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + CardSniffInit(); + } else{ + ReaderSniffInit(); + } + PORTE.OUTCLR = PIN3_bm; + return; } @@ -249,6 +262,10 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { INLINE void CardSniffInit(void) { + LED_PORT.OUTSET = LED_RED; + PORTE.OUTSET = PIN2_bm; + + /* Initialize common peripherals and start listening * for incoming data. */ @@ -268,6 +285,8 @@ INLINE void CardSniffInit(void) * bit halves had modulations since the last pause. */ + DACB.CH0DATA = GlobalSettings.ActiveSettingPtr->ReaderThreshold; // real threshold voltage can be calculated with ch0data * Vref / 0xFFF + // Comparator ADC /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; @@ -301,14 +320,16 @@ INLINE void CardSniffInit(void) ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; RxPendingSince = SystemGetSysTick(); - PORTE.OUTSET = PIN3_bm; + Flags.CardStarted = false; } INLINE void CardSniffDeinit(void) { - PORTE.OUTCLR = PIN3_bm; + PORTE.OUTCLR = PIN2_bm; + LED_PORT.OUTCLR = LED_RED; + CODEC_TIMER_LOADMOD.CTRLA = 0; CODEC_TIMER_LOADMOD.INTCTRLB = 0; @@ -320,7 +341,8 @@ INLINE void CardSniffDeinit(void) ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - Flags.RxDone = false; +// Flags.RxDone = false; +// Flags.CardStarted = false; } @@ -341,6 +363,22 @@ INLINE void Insert1(void) *CardBufferPtr++ = CardSampleR; } +INLINE void TaskInsert0(void) +{ + CardSampleR >>= 1; + if (++CardBitCount % 8) + return; + *CardBufferPtr++ = CardSampleR; +} + +INLINE void TaskInsert1(void) +{ + CardSampleR = (CardSampleR >> 1) | 0x80; + if (++CardBitCount % 8) + return; + *CardBufferPtr++ = CardSampleR; +} + // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { @@ -348,7 +386,7 @@ ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered befor // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_gc; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc; - + Flags.CardStarted = true; } // Decode the Card -> Reader signal // according to the pause and modulated period @@ -414,7 +452,13 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); + + CardBitCount = BitCount; Flags.RxDone = true; + Flags.CardStarted = false; + + CardSniffDeinit(); + ReaderSniffInit(); } @@ -424,7 +468,7 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found void Sniff14443ACodecInit(void) { - PORTE.DIRSET= PIN3_bm; + PORTE.DIRSET= PIN3_bm | PIN2_bm; // Common Codec Register settings CodecInitCommon(); // Enable demodulator power @@ -433,6 +477,7 @@ void Sniff14443ACodecInit(void) // Start with sniffing Reader->Card direction traffic TrafficSource = TRAFFIC_READER; ReaderSniffInit(); + Flags.RxDone = false; } @@ -453,15 +498,15 @@ void Sniff14443ACodecTask(void) Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ - if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { - LEDHook(LED_CODEC_RX, LED_PULSE); + if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { +// LEDHook(LED_CODEC_RX, LED_PULSE); TrafficSource = TRAFFIC_CARD; return; } // Get nothing, Start sniff again TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); +// ReaderSniffInit(); } } // Card->Reader Task @@ -469,19 +514,19 @@ void Sniff14443ACodecTask(void) { // Receive finished if (Flags.RxDone) { - if (Flags.RxDone && BitCount > 0) // decode the raw received data + if (Flags.RxDone && CardBitCount > 0) // decode the raw received data { - if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { - BitCount = 0; + if (CardBitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { + CardBitCount = 0; } else { uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer2, (BitCount + 7) / 8); + memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); CardBufferPtr = CodecBuffer2; - uint16_t BitCountTmp = 2, TotalBitCount = BitCount; - BitCount = 0; + uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; + CardBitCount = 0; bool breakflag = false; TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored @@ -492,11 +537,11 @@ void Sniff14443ACodecTask(void) TmpCodecBuffer[BitCountTmp / 8] >>= 2; switch (Bit) { case 0b10: - Insert1(); + TaskInsert1(); break; case 0b01: - Insert0(); + TaskInsert0(); break; case 0b00: // EOC @@ -509,40 +554,43 @@ void Sniff14443ACodecTask(void) } BitCountTmp += 2; } - if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); + if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); -// BitCount = removeParityBits(CodecBuffer, BitCount); - LEDHook(LED_CODEC_RX, LED_PULSE); +// BitCount = removeParityBits(CodecBuffer, CardBitCount); +// LEDHook(LED_CODEC_RX, LED_PULSE); // Print log after a round finished // Otherwise it will take too much cpu cycles // then the card traffic sniffing may not start in time - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); - LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); + LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); - // Disable card sniffing and enable reader sniffing - CardSniffDeinit(); - TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); - - return; +// return; } } + + // Once Rx Finished, Switch to Reader sniffing, + // No matter if getting data or not +// CardSniffDeinit(); + // Disable card sniffing and enable reader sniffing + TrafficSource = TRAFFIC_READER; +// ReaderSniffInit(); + Flags.RxDone = false; /* Call application with received data */ - BitCount = ApplicationProcess(CodecBuffer2, BitCount); + CardBitCount = ApplicationProcess(CodecBuffer2, CardBitCount); } else // Receive not finished yet, Continue waiting { // If Waiting for response time out // Reset to reader sniffing - if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) ) { - Flags.RxDone = true; + if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT) && !Flags.CardStarted) { + Flags.RxDone = false; // If Card sniffing started but no data get // Then the codec must have sniffed some reader raffic - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); TrafficSource = TRAFFIC_READER; From 59d8e1739dc41604945f40be167e6eb2eebeecd3 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 23 Jul 2018 16:29:04 +0100 Subject: [PATCH 24/50] Refactor state and flags in SniffISO14443-2A.c (cherry picked from commit f3dd397) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 194 +++++++----------- 1 file changed, 79 insertions(+), 115 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 2bb6e2d..2a20cf7 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -41,9 +41,11 @@ enum RCTraffic TrafficSource; static volatile struct { - volatile bool DemodFinished; - volatile bool RxDone; - volatile bool CardStarted; // If card have send the first bit + volatile bool ReaderDataAvaliable; + volatile bool CardDataAvaliable; +// volatile bool DemodFinished; +// volatile bool RxDone; +// volatile bool CardStarted; // If card have send the first bit } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -51,10 +53,13 @@ static volatile uint16_t RxPendingSince; typedef enum { DEMOD_DATA_BIT, /* Demod */ DEMOD_PARITY_BIT, + PCD_PICC_FDT, + PICC_FRAME, + } StateType; -uint16_t ReaderBitCount; -uint16_t CardBitCount; +static volatile uint16_t ReaderBitCount; +static volatile uint16_t CardBitCount; INLINE void CardSniffInit(void); INLINE void CardSniffDeinit(void); @@ -71,7 +76,6 @@ INLINE void ReaderSniffInit(void) CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; /* Initialize some global vars and start looking out for reader commands */ - Flags.DemodFinished = 0; ReaderBufferPtr = CodecBuffer; ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; @@ -103,8 +107,6 @@ INLINE void ReaderSniffDeInit(void) CODEC_DEMOD_IN_PORT.INT1MASK = 0; CODEC_DEMOD_IN_PORT.INTCTRL = 0; - Flags.DemodFinished = 0; - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; @@ -114,6 +116,8 @@ INLINE void ReaderSniffDeInit(void) // Find first pause and start sampling ISR(CODEC_DEMOD_IN_INT1_VECT) { + PORTE.OUTSET = PIN2_bm; + /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start * demodulating beginning from one bit-width after this edge. */ @@ -150,8 +154,9 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { // Shutdown the Reader->Card Sniffing, // disable the sampling timer + PORTE.OUTCLR = PIN2_bm; + - PORTE.OUTSET = PIN3_bm; CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; @@ -177,18 +182,17 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { } /* Signal, that we have finished sampling */ - Flags.DemodFinished = 1; ReaderBitCount = BitCount; // If we are have got data // Start Card->Reader Sniffing without waiting for the complete of CodecTask // Otherwise some bit will not be captured if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + Flags.ReaderDataAvaliable = true; CardSniffInit(); } else{ ReaderSniffInit(); } - PORTE.OUTCLR = PIN3_bm; return; @@ -231,7 +235,7 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { } else if (StateRegister == DEMOD_PARITY_BIT) { /* This is a parity bit. Store it */ - *ParityBufferPtr++ = Bit; +// *ParityBufferPtr++ = Bit; StateRegister = DEMOD_DATA_BIT; } else { @@ -263,7 +267,6 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { INLINE void CardSniffInit(void) { LED_PORT.OUTSET = LED_RED; - PORTE.OUTSET = PIN2_bm; /* Initialize common peripherals and start listening @@ -273,7 +276,6 @@ INLINE void CardSniffInit(void) BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly CardSampleR = 0x00; - Flags.RxDone = false; /* * Prepare for Manchester decoding. @@ -306,7 +308,8 @@ INLINE void CardSniffInit(void) CODEC_TIMER_TIMESTAMPS.CCB = 160; CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; +// CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_HI_gc; /* Use the event system for resetting the pause-detecting timer. */ EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT @@ -320,14 +323,13 @@ INLINE void CardSniffInit(void) ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; RxPendingSince = SystemGetSysTick(); - Flags.CardStarted = false; + StateRegister = PCD_PICC_FDT; } INLINE void CardSniffDeinit(void) { - PORTE.OUTCLR = PIN2_bm; LED_PORT.OUTCLR = LED_RED; @@ -341,8 +343,6 @@ INLINE void CardSniffDeinit(void) ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; -// Flags.RxDone = false; -// Flags.CardStarted = false; } @@ -382,11 +382,12 @@ INLINE void TaskInsert1(void) // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { + ACA.AC0CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_gc; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc; - Flags.CardStarted = true; + StateRegister = PICC_FRAME; } // Decode the Card -> Reader signal // according to the pause and modulated period @@ -407,6 +408,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found return; case 49 ... 80: // 64 ticks are a full bit period + // Insert 0 Insert1(); Insert0(); return; @@ -434,6 +436,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found // EOC of Card->Reader found ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found { + // Disable LOADMOD Timer CODEC_TIMER_LOADMOD.INTCTRLB = 0; // Disable Interrupt CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; // Disable Clock @@ -450,12 +453,14 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found Insert1(); } + if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); CardBitCount = BitCount; - Flags.RxDone = true; - Flags.CardStarted = false; + if (BitCount >= ISO14443A_RX_MINIMUM_BITCOUNT * 2) { + Flags.CardDataAvaliable = true; + } CardSniffDeinit(); ReaderSniffInit(); @@ -468,6 +473,7 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found void Sniff14443ACodecInit(void) { + PORTE.DIRSET= PIN3_bm | PIN2_bm; // Common Codec Register settings CodecInitCommon(); @@ -477,7 +483,8 @@ void Sniff14443ACodecInit(void) // Start with sniffing Reader->Card direction traffic TrafficSource = TRAFFIC_READER; ReaderSniffInit(); - Flags.RxDone = false; + Flags.ReaderDataAvaliable = false; + Flags.CardDataAvaliable = false; } @@ -492,111 +499,68 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { - // Reader->Card Task - if (TrafficSource == TRAFFIC_READER) { - if (Flags.DemodFinished) { - Flags.DemodFinished = 0; - /* Reception finished. Process the received bytes */ - - if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { -// LEDHook(LED_CODEC_RX, LED_PULSE); - - TrafficSource = TRAFFIC_CARD; - return; - } - // Get nothing, Start sniff again - TrafficSource = TRAFFIC_READER; -// ReaderSniffInit(); - } + PORTE.OUTSET = PIN3_bm; + if(Flags.ReaderDataAvaliable){ + Flags.ReaderDataAvaliable = false; + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); + ReaderBitCount = 0; } - // Card->Reader Task - else - { - // Receive finished - if (Flags.RxDone) { - if (Flags.RxDone && CardBitCount > 0) // decode the raw received data - { - if (CardBitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { - CardBitCount = 0; - } - else { - uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); + if (Flags.CardDataAvaliable){ + Flags.CardDataAvaliable = false; - CardBufferPtr = CodecBuffer2; - uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; - CardBitCount = 0; + uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; + memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); - bool breakflag = false; - TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored + CardBufferPtr = CodecBuffer2; + uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; + CardBitCount = 0; - // Manchester Code ISO14443-2 8.2.5 - while (!breakflag && BitCountTmp < TotalBitCount) { - uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; - TmpCodecBuffer[BitCountTmp / 8] >>= 2; - switch (Bit) { - case 0b10: - TaskInsert1(); - break; + bool breakflag = false; + TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored - case 0b01: - TaskInsert0(); - break; + // Manchester Code ISO14443-2 8.2.5 + while (!breakflag && BitCountTmp < TotalBitCount) { + uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; + TmpCodecBuffer[BitCountTmp / 8] >>= 2; + switch (Bit) { + case 0b10: + TaskInsert1(); + break; - case 0b00: // EOC - breakflag = true; - break; + case 0b01: + TaskInsert0(); + break; - default: - // error, should not happen, TODO handle this - break; - } - BitCountTmp += 2; - } - if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); + case 0b00: // EOC + breakflag = true; + break; + + default: + // error, should not happen, TODO handle this + break; + } + BitCountTmp += 2; + } + if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); // BitCount = removeParityBits(CodecBuffer, CardBitCount); // LEDHook(LED_CODEC_RX, LED_PULSE); - // Print log after a round finished - // Otherwise it will take too much cpu cycles - // then the card traffic sniffing may not start in time - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); + // Print log after a round finished + // Otherwise it will take too much cpu cycles + // then the card traffic sniffing may not start in time + LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); // return; - } - } - - // Once Rx Finished, Switch to Reader sniffing, - // No matter if getting data or not -// CardSniffDeinit(); - // Disable card sniffing and enable reader sniffing - TrafficSource = TRAFFIC_READER; -// ReaderSniffInit(); - - Flags.RxDone = false; - - /* Call application with received data */ - CardBitCount = ApplicationProcess(CodecBuffer2, CardBitCount); - } - else // Receive not finished yet, Continue waiting - { - // If Waiting for response time out - // Reset to reader sniffing - if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT) && !Flags.CardStarted) { - Flags.RxDone = false; - - // If Card sniffing started but no data get - // Then the codec must have sniffed some reader raffic - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - // Disable card sniffing and enable reader sniffing - CardSniffDeinit(); - TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); - } - } } + + if(StateRegister == PCD_PICC_FDT && (SYSTICK_DIFF(RxPendingSince) > Reader_FWT)){ + CardSniffDeinit(); + ReaderSniffInit(); + } + PORTE.OUTCLR = PIN3_bm; + + } From 14e17381533e89cb599f8b42f588856d1c18c8cb Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 24 Jul 2018 00:43:06 +0100 Subject: [PATCH 25/50] Optimise the Card->Reader Manchester decoder in Sniffing to make it faster It now decode and sample in the same time, so the decode half bit sampling to Manchester in the CodecTask can be removed. This optimisation may also fix the bug that the CodecTask not finished after start of Reader->Card Sampling and make the reader->Card sampling not in perfect timing and cause the Reader ->Card Sniffed data to be wrong. Trace from oscilloscope for the Problem: ReaderSniffing Enable __________ _________ __| |____________________| |_________ CardSniffing Enable _____________ _______ ________________| |______________| Task __ ___---- _|__|__|__|___| |__|__|__|__|__|_| |__|__|__|__| "-" indicate the problem (cherry picked from commit a246b98) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 149 ++++++++---------- 1 file changed, 63 insertions(+), 86 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 2a20cf7..2552a8d 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -37,15 +37,9 @@ #define ParityBufferPtr CodecPtrRegister2 #define CardBufferPtr CodecPtrRegister3 - -enum RCTraffic TrafficSource; - static volatile struct { volatile bool ReaderDataAvaliable; volatile bool CardDataAvaliable; -// volatile bool DemodFinished; -// volatile bool RxDone; -// volatile bool CardStarted; // If card have send the first bit } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -60,6 +54,7 @@ typedef enum { static volatile uint16_t ReaderBitCount; static volatile uint16_t CardBitCount; +static volatile uint16_t rawBitCount; INLINE void CardSniffInit(void); INLINE void CardSniffDeinit(void); @@ -273,7 +268,8 @@ INLINE void CardSniffInit(void) * for incoming data. */ CardBufferPtr = CodecBuffer2; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + rawBitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + BitCount = 0; CardSampleR = 0x00; @@ -363,22 +359,6 @@ INLINE void Insert1(void) *CardBufferPtr++ = CardSampleR; } -INLINE void TaskInsert0(void) -{ - CardSampleR >>= 1; - if (++CardBitCount % 8) - return; - *CardBufferPtr++ = CardSampleR; -} - -INLINE void TaskInsert1(void) -{ - CardSampleR = (CardSampleR >> 1) | 0x80; - if (++CardBitCount % 8) - return; - *CardBufferPtr++ = CardSampleR; -} - // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { @@ -402,34 +382,68 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found * but doing this only on a condition means wasting time, so we do it every time. */ CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_DIV4_gc; + // Remember, LSB is send first + // If current raw bit count is odd, then the previous raw bit must be 0 switch (tmp) // decide how many half bit periods have been modulations { case 0 ... 48: // 32 ticks is one half of a bit period return; case 49 ... 80: // 64 ticks are a full bit period - // Insert 0 - Insert1(); - Insert0(); + // Got 01 + if(rawBitCount & 1){ + // 01 + 0 -> 0 10 + // 10 -> 1, last 0 is ignored + if(rawBitCount > 1) { + // Ignore SOC + Insert1(); + } + } else{ + // Current sampled bit count is even, decode directly + // 01 -> 0 + Insert0(); + } + rawBitCount += 2; return; case 81 ... 112: // 96 ticks are 3 half bit periods - if (BitCount & 1) { - Insert1(); - Insert1(); + if (rawBitCount & 1) { + // Current sampled bit count is odd + // Got 011 + // 011 + 0 -> 01 10 -> 01 + if(rawBitCount > 1) { + // Ignore SOC + Insert1(); + } Insert0(); } else { - Insert1(); - Insert0(); + // Even bit count + // Got 001 + // 001 -> 0 01, The last 0 is ignored + // 01 -> 0 Insert0(); } + rawBitCount += 3; + return; default: // every value over 96 + 16 (tolerance) is considered to be 4 half bit periods - Insert1(); - Insert1(); - Insert0(); - Insert0(); + // Got 00 11 + if(rawBitCount & 1){ + // 00 11 + 0 -> 0 01 10 + // 01 -> 0, 10 -> 1, Ignore last 0 + if(rawBitCount > 1) { + // Ignore SOC + Insert1(); + } + Insert0(); + } else { + // Should not happen + // If modulation is correct, + // there should not be a full bit period modulation in even bit count + } + rawBitCount += 4; + return; } } @@ -446,19 +460,21 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; ACA.AC0CTRL &= ~AC_ENABLE_bm; - if (BitCount & 1) { - if (CardSampleR & 0x80) - Insert0(); - else - Insert1(); + // If finished in odd sample count + // There must been an incomplete decoded bit + // Since only EOC is no modulation in full bit period, and previous raw bit must be 0 + // so the last not modulated bit must be 1 + if (rawBitCount & 1) { + // The previous raw bit must be 0 + // 1 + 0 -> 10 -> 1 + Insert1(); } - if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); CardBitCount = BitCount; - if (BitCount >= ISO14443A_RX_MINIMUM_BITCOUNT * 2) { + if (BitCount >= ISO14443A_RX_MINIMUM_BITCOUNT) { Flags.CardDataAvaliable = true; } @@ -481,11 +497,10 @@ void Sniff14443ACodecInit(void) CodecSetDemodPower(true); // Start with sniffing Reader->Card direction traffic - TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); Flags.ReaderDataAvaliable = false; Flags.CardDataAvaliable = false; + ReaderSniffInit(); } void Sniff14443ACodecDeInit(void) @@ -503,56 +518,18 @@ void Sniff14443ACodecTask(void) if(Flags.ReaderDataAvaliable){ Flags.ReaderDataAvaliable = false; LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - ReaderBitCount = 0; +// ReaderBitCount = 0; } + if (Flags.CardDataAvaliable){ Flags.CardDataAvaliable = false; - uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); +// CardBitCount = removeParityBits(CodecBuffer2,CardBitCount ); +// LEDHook(LED_CODEC_RX, LED_PULSE); - CardBufferPtr = CodecBuffer2; - uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; - CardBitCount = 0; - - bool breakflag = false; - TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored - - // Manchester Code ISO14443-2 8.2.5 - while (!breakflag && BitCountTmp < TotalBitCount) { - uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; - TmpCodecBuffer[BitCountTmp / 8] >>= 2; - switch (Bit) { - case 0b10: - TaskInsert1(); - break; - - case 0b01: - TaskInsert0(); - break; - - case 0b00: // EOC - breakflag = true; - break; - - default: - // error, should not happen, TODO handle this - break; - } - BitCountTmp += 2; - } - if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); - -// BitCount = removeParityBits(CodecBuffer, CardBitCount); -// LEDHook(LED_CODEC_RX, LED_PULSE); - // Print log after a round finished - // Otherwise it will take too much cpu cycles - // then the card traffic sniffing may not start in time LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); -// return; } From 823602c721ca859a2671ac38c149ae8eb0d1884f Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 25 Jul 2018 17:40:46 +0100 Subject: [PATCH 26/50] Add Framework for autocalibrate of Sniffing Mode (cherry picked from commit c8606be) --- .../Chameleon-Mini/Application/Application.h | 1 + .../Chameleon-Mini/Application/Sniff14443A.c | 48 +++++++++++++++++++ .../Chameleon-Mini/Application/Sniff14443A.h | 24 ++++++++++ .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 13 ++--- Firmware/Chameleon-Mini/Configuration.c | 10 ++-- Firmware/Chameleon-Mini/Makefile | 2 +- Firmware/Chameleon-Mini/Terminal/Commands.c | 28 ++++++++--- 7 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 Firmware/Chameleon-Mini/Application/Sniff14443A.c create mode 100644 Firmware/Chameleon-Mini/Application/Sniff14443A.h diff --git a/Firmware/Chameleon-Mini/Application/Application.h b/Firmware/Chameleon-Mini/Application/Application.h index 0b94960..1002d31 100644 --- a/Firmware/Chameleon-Mini/Application/Application.h +++ b/Firmware/Chameleon-Mini/Application/Application.h @@ -16,6 +16,7 @@ #include "MifareUltralight.h" #include "MifareClassic.h" #include "Reader14443A.h" +#include "Sniff14443A.h" /* Function wrappers */ INLINE void ApplicationInit(void) { diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c new file mode 100644 index 0000000..68512a7 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -0,0 +1,48 @@ +// +// Created by Zitai Chen on 25/07/2018. +// Application layer for sniffing +// Currently only support Autocalibrate +// + +#include +#include +#include "Sniff14443A.h" +Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; + +extern bool checkParityBits(uint8_t * Buffer, uint16_t BitCount); + static enum { + STATE_IDLE, + STATE_READER_DATA, + STATE_CARD_DATA +} SniffState = STATE_IDLE; + +void Sniff14443AAppInit(void){ + SniffState = STATE_IDLE; +} + +void Sniff14443AAppReset(void){ + SniffState = STATE_IDLE; + Sniff14443CurrentCommand = Sniff14443_Do_Nothing; +} +// Currently APPTask and AppTick is not being used +void Sniff14443AAppTask(void){/* Empty */} +void Sniff14443AAppTick(void){/* Empty */} + +void Sniff14443AAppTimeout(void){ + Sniff14443AAppReset(); +} + +uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ + switch (Sniff14443CurrentCommand){ + case Sniff14443_Do_Nothing: + return 0; + case Sniff14443_Autocalibrate: + // If received Reader WUPA + if(Buffer[0] == 0x26 || Buffer[0] == 0x54){ + LED_PORT.OUTSET = LED_RED; + } + break; + default: + return 0; + } +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.h b/Firmware/Chameleon-Mini/Application/Sniff14443A.h new file mode 100644 index 0000000..60f1c85 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.h @@ -0,0 +1,24 @@ +// +// Created by Zitai Chen on 25/07/2018. +// + +#ifndef CHAMELEON_MINI_SNIFF14443A_H +#define CHAMELEON_MINI_SNIFF14443A_H + +#include + +void Sniff14443AAppInit(void); +void Sniff14443AAppReset(void); +void Sniff14443AAppTask(void); +void Sniff14443AAppTick(void); +void Sniff14443AAppTimeout(void); + +uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount); + +typedef enum { + Sniff14443_Do_Nothing, + Sniff14443_Autocalibrate, +} Sniff14443Command; + +#endif //CHAMELEON_MINI_SNIFF14443A_H + diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 2552a8d..fb2a51a 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -261,8 +261,6 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { INLINE void CardSniffInit(void) { - LED_PORT.OUTSET = LED_RED; - /* Initialize common peripherals and start listening * for incoming data. */ @@ -326,8 +324,6 @@ INLINE void CardSniffInit(void) INLINE void CardSniffDeinit(void) { - LED_PORT.OUTCLR = LED_RED; - CODEC_TIMER_LOADMOD.CTRLA = 0; CODEC_TIMER_LOADMOD.INTCTRLB = 0; @@ -518,18 +514,17 @@ void Sniff14443ACodecTask(void) if(Flags.ReaderDataAvaliable){ Flags.ReaderDataAvaliable = false; LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); -// ReaderBitCount = 0; + ApplicationProcess(CodecBuffer, (ReaderBitCount+7)/8); + LEDHook(LED_CODEC_RX, LED_PULSE); } if (Flags.CardDataAvaliable){ Flags.CardDataAvaliable = false; - // CardBitCount = removeParityBits(CodecBuffer2,CardBitCount ); -// LEDHook(LED_CODEC_RX, LED_PULSE); - LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); - + LEDHook(LED_CODEC_RX, LED_PULSE); + ApplicationProcess(CodecBuffer2, (CardBitCount+7)/8); } diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 5fda354..1fffdd0 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -191,11 +191,11 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .CodecInitFunc = Sniff14443ACodecInit, .CodecDeInitFunc = Sniff14443ACodecDeInit, .CodecTaskFunc = Sniff14443ACodecTask, - .ApplicationInitFunc = ApplicationInitDummy, - .ApplicationResetFunc = ApplicationResetDummy, - .ApplicationTaskFunc = ApplicationTaskDummy, - .ApplicationTickFunc = ApplicationTickDummy, - .ApplicationProcessFunc = ApplicationProcessDummy, + .ApplicationInitFunc = Sniff14443AAppInit, + .ApplicationResetFunc = Sniff14443AAppReset, + .ApplicationTaskFunc = Sniff14443AAppTask, + .ApplicationTickFunc = Sniff14443AAppTick, + .ApplicationProcessFunc = Sniff14443AAppProcess, .ApplicationGetUidFunc = ApplicationGetUidDummy, .ApplicationSetUidFunc = ApplicationSetUidDummy, .UidSize = 0, diff --git a/Firmware/Chameleon-Mini/Makefile b/Firmware/Chameleon-Mini/Makefile index 5870a2b..3824633 100644 --- a/Firmware/Chameleon-Mini/Makefile +++ b/Firmware/Chameleon-Mini/Makefile @@ -93,7 +93,7 @@ OPTIMIZATION = s SRC += $(TARGET).c LUFADescriptors.c System.c Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c SRC += Terminal/Terminal.c Terminal/Commands.c Terminal/XModem.c Terminal/CommandLine.c SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/SniffISO14443-2A.c Codec/Reader14443-ISR.S -SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c +SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c Application/Sniff14443A.c SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) LUFA_PATH = ../LUFA CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -DFLASH_DATA_ADDR=$(FLASH_DATA_ADDR) -DFLASH_DATA_SIZE=$(FLASH_DATA_SIZE) -DSPM_HELPER_ADDR=$(SPM_HELPER_ADDR) -DBUILD_DATE=$(BUILD_DATE) -DCOMMIT_ID=\"$(COMMIT_ID)\" $(SETTINGS) diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index d4b26e9..c6307a8 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -2,6 +2,7 @@ #include "Commands.h" #include #include +#include #include "XModem.h" #include "../Settings.h" #include "../Chameleon-Mini.h" @@ -16,6 +17,7 @@ #include "../Codec/Codec.h" extern Reader14443Command Reader14443CurrentCommand; +extern Sniff14443Command Sniff14443CurrentCommand; extern const PROGMEM CommandEntryType CommandTable[]; @@ -629,15 +631,27 @@ CommandStatusIdType CommandGetField(char* OutMessage) CommandStatusIdType CommandExecAutocalibrate(char* OutMessage) { - if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER) + if (GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_ISO14443A_READER){ + ApplicationReset(); + + Reader14443CurrentCommand = Reader14443_Autocalibrate; + Reader14443AAppInit(); + Reader14443ACodecStart(); + CommandLinePendingTaskTimeout = &Reader14443AAppTimeout; + return TIMEOUT_COMMAND; + } + else if (GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_ISO14443A_SNIFF){ + ApplicationReset(); + + Sniff14443CurrentCommand = Sniff14443_Autocalibrate; + Sniff14443AAppInit(); + CommandLinePendingTaskTimeout = &Sniff14443AAppTimeout; + return TIMEOUT_COMMAND; + } + else { return COMMAND_ERR_INVALID_USAGE_ID; - ApplicationReset(); + } - Reader14443CurrentCommand = Reader14443_Autocalibrate; - Reader14443AAppInit(); - Reader14443ACodecStart(); - CommandLinePendingTaskTimeout = &Reader14443AAppTimeout; - return TIMEOUT_COMMAND; } CommandStatusIdType CommandExecClone(char *OutMessage) From 9c37cf758bd520d779e187229ceab35301a2dbf3 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Thu, 26 Jul 2018 02:28:03 +0100 Subject: [PATCH 27/50] Trace the Reader and card status in sniffing mode This will prepare for the autocalibrate of threshold If card selection fully detected, then the threshold is good, Otherwise it is not good. (cherry picked from commit f5c8485) --- .../Chameleon-Mini/Application/Sniff14443A.c | 127 ++++++++++++++++-- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 12 +- .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 2 +- 3 files changed, 129 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c index 68512a7..e652834 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff14443A.c +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -7,22 +7,31 @@ #include #include #include "Sniff14443A.h" -Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; - +#include "Codec/SniffISO14443-2A.h" extern bool checkParityBits(uint8_t * Buffer, uint16_t BitCount); - static enum { + +Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; +bool selected = false; +static enum { STATE_IDLE, - STATE_READER_DATA, - STATE_CARD_DATA + STATE_REQA, + STATE_ATQA, + STATE_ANTICOLLI, + STATE_SELECT, + STATE_UID, + STATE_SAK, } SniffState = STATE_IDLE; + void Sniff14443AAppInit(void){ - SniffState = STATE_IDLE; + SniffState = STATE_REQA; + selected = false; } void Sniff14443AAppReset(void){ SniffState = STATE_IDLE; Sniff14443CurrentCommand = Sniff14443_Do_Nothing; + selected = false; } // Currently APPTask and AppTick is not being used void Sniff14443AAppTask(void){/* Empty */} @@ -32,16 +41,116 @@ void Sniff14443AAppTimeout(void){ Sniff14443AAppReset(); } +void reset2REQA(void){ + SniffState = STATE_REQA; + LED_PORT.OUTCLR = LED_RED; + selected = false; + // TODO: Mark the current threshold as fail and continue + +} uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ switch (Sniff14443CurrentCommand){ case Sniff14443_Do_Nothing: return 0; case Sniff14443_Autocalibrate: - // If received Reader WUPA - if(Buffer[0] == 0x26 || Buffer[0] == 0x54){ - LED_PORT.OUTSET = LED_RED; + switch (SniffState){ + case STATE_REQA: + // If received Reader REQA or WUPA + if (TrafficSource == TRAFFIC_READER && + (Buffer[0] == 0x26 || Buffer[0] == 0x54)) + { + SniffState = STATE_ATQA; + } else { + // Stay in this state, do noting + } + break; + case STATE_ATQA: + // ATQA: P RRRR XXXX P XXRX XXXX + if (TrafficSource == TRAFFIC_CARD && + BitCount == 2*9 && + (Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0 + (Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0 + (Buffer[2] & 0x01) == 0x00 && + checkParityBits(Buffer, BitCount)) + { + // Assume this is a good ATQA + SniffState = STATE_ANTICOLLI; + } else { + // If not ATQA, but REQA, then stay on this state, + // Reset to REQA, save the counter and reset the counter + if (TrafficSource == TRAFFIC_READER && + (Buffer[0] == 0x26 || Buffer[0] == 0x54)) { + } else { + // If not ATQA and not REQA then reset to REQA + reset2REQA(); + } + } + break; + case STATE_ANTICOLLI: + LED_PORT.OUTSET = LED_RED; + // SEL: 93/95/97 + if(TrafficSource == TRAFFIC_READER && + BitCount == 2*8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01) + { + SniffState = STATE_UID; + } else{ + reset2REQA(); + } + break; + case STATE_UID: + if(TrafficSource == TRAFFIC_CARD && + BitCount == 5*9 && + checkParityBits(Buffer, BitCount)) + { + SniffState = STATE_SELECT; + } else { + reset2REQA(); + } + break; + case STATE_SELECT: + + // SELECT: 9 bytes, SEL = 93/95/97, NVB=70 + if (TrafficSource == TRAFFIC_READER && + BitCount == 9*8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01 && + Buffer[1] == 0x70) + { + SniffState = STATE_SAK; + } else{ + // Not valid, reset + reset2REQA(); + } + break; + case STATE_SAK: + // SAK: 1Byte SAK + CRC + if(TrafficSource == TRAFFIC_CARD && + BitCount == 3*9 && + checkParityBits(Buffer, BitCount)) + { + if((Buffer[0] & 0x04) == 0x00){ + // UID complete, success SELECTED, + // TODO: Mark the current threshold as success and continue + // reset + SniffState = STATE_REQA; + selected = true; + LED_PORT.OUTCLR = LED_RED; + + } else { + // UID not complete, goto ANTICOLLI + SniffState = STATE_ANTICOLLI; + } + } else{ + reset2REQA(); + } + break; + default: + break; } break; + default: return 0; } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index fb2a51a..b58cc16 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -513,18 +513,26 @@ void Sniff14443ACodecTask(void) PORTE.OUTSET = PIN3_bm; if(Flags.ReaderDataAvaliable){ Flags.ReaderDataAvaliable = false; + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - ApplicationProcess(CodecBuffer, (ReaderBitCount+7)/8); + // Let the Application layer know where this data comes from LEDHook(LED_CODEC_RX, LED_PULSE); + + TrafficSource = TRAFFIC_READER; + ApplicationProcess(CodecBuffer, ReaderBitCount); } if (Flags.CardDataAvaliable){ Flags.CardDataAvaliable = false; + // CardBitCount = removeParityBits(CodecBuffer2,CardBitCount ); LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); LEDHook(LED_CODEC_RX, LED_PULSE); - ApplicationProcess(CodecBuffer2, (CardBitCount+7)/8); + + // Let the Application layer know where this data comes from + TrafficSource = TRAFFIC_CARD; + ApplicationProcess(CodecBuffer2, CardBitCount); } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h index b8616b0..0e22d46 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -9,7 +9,7 @@ #include "Codec.h" #include "Terminal/CommandLine.h" -extern enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; +enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; /* Codec Interface */ void Sniff14443ACodecInit(void); void Sniff14443ACodecDeInit(void); From 86d47110a97f18ebbffd3ac8d7ed79e1ce3bacc1 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 27 Jul 2018 01:46:12 +0100 Subject: [PATCH 28/50] Basic auto calibrate for sniffing mode. Started from the smallest threshold and when the first good threshold is obtained, stop. May also need to extend the TIMEOUT to make this work. Need the reader reading all the timing when sniffing in order to auto calibrate (cherry picked from commit 2c3d5f5) --- .../Chameleon-Mini/Application/Sniff14443A.c | 102 ++++++++++-------- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 2 - 2 files changed, 57 insertions(+), 47 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c index e652834..59f3ed7 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff14443A.c +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -11,7 +11,7 @@ extern bool checkParityBits(uint8_t * Buffer, uint16_t BitCount); Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; -bool selected = false; +//bool selected = false; static enum { STATE_IDLE, STATE_REQA, @@ -22,16 +22,21 @@ static enum { STATE_SAK, } SniffState = STATE_IDLE; +static uint16_t tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN; +static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) / + CODEC_THRESHOLD_CALIBRATE_STEPS] = {0}; void Sniff14443AAppInit(void){ SniffState = STATE_REQA; - selected = false; + + tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN; + CodecThresholdSet(tmp_th); } void Sniff14443AAppReset(void){ SniffState = STATE_IDLE; + Sniff14443CurrentCommand = Sniff14443_Do_Nothing; - selected = false; } // Currently APPTask and AppTick is not being used void Sniff14443AAppTask(void){/* Empty */} @@ -41,24 +46,31 @@ void Sniff14443AAppTimeout(void){ Sniff14443AAppReset(); } -void reset2REQA(void){ +INLINE void reset2REQA(void){ SniffState = STATE_REQA; LED_PORT.OUTCLR = LED_RED; - selected = false; - // TODO: Mark the current threshold as fail and continue + // Mark the current threshold as fail and continue + if(tmp_th < CODEC_THRESHOLD_CALIBRATE_MAX){ + Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = 0; + tmp_th = CodecThresholdIncrement(); + } else{ + // mark finish + } } uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ switch (Sniff14443CurrentCommand){ - case Sniff14443_Do_Nothing: + case Sniff14443_Do_Nothing: { return 0; - case Sniff14443_Autocalibrate: - switch (SniffState){ + } + case Sniff14443_Autocalibrate: { + + switch (SniffState) { case STATE_REQA: + LED_PORT.OUTCLR = LED_RED; // If received Reader REQA or WUPA if (TrafficSource == TRAFFIC_READER && - (Buffer[0] == 0x26 || Buffer[0] == 0x54)) - { + (Buffer[0] == 0x26 || Buffer[0] == 0x52)) { SniffState = STATE_ATQA; } else { // Stay in this state, do noting @@ -67,19 +79,18 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ case STATE_ATQA: // ATQA: P RRRR XXXX P XXRX XXXX if (TrafficSource == TRAFFIC_CARD && - BitCount == 2*9 && - (Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0 - (Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0 - (Buffer[2] & 0x01) == 0x00 && - checkParityBits(Buffer, BitCount)) - { + BitCount == 2 * 9 && + (Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0 + (Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0 + (Buffer[2] & 0x01) == 0x00 && + checkParityBits(Buffer, BitCount)) { // Assume this is a good ATQA SniffState = STATE_ANTICOLLI; } else { // If not ATQA, but REQA, then stay on this state, // Reset to REQA, save the counter and reset the counter if (TrafficSource == TRAFFIC_READER && - (Buffer[0] == 0x26 || Buffer[0] == 0x54)) { + (Buffer[0] == 0x26 || Buffer[0] == 0x52)) { } else { // If not ATQA and not REQA then reset to REQA reset2REQA(); @@ -87,23 +98,21 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ } break; case STATE_ANTICOLLI: - LED_PORT.OUTSET = LED_RED; // SEL: 93/95/97 - if(TrafficSource == TRAFFIC_READER && - BitCount == 2*8 && - (Buffer[0] & 0xf0) == 0x90 && - (Buffer[0] & 0x09) == 0x01) - { + if (TrafficSource == TRAFFIC_READER && + BitCount == 2 * 8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01) { SniffState = STATE_UID; - } else{ + + } else { reset2REQA(); } break; case STATE_UID: - if(TrafficSource == TRAFFIC_CARD && - BitCount == 5*9 && - checkParityBits(Buffer, BitCount)) - { + if (TrafficSource == TRAFFIC_CARD && + BitCount == 5 * 9 && + checkParityBits(Buffer, BitCount)) { SniffState = STATE_SELECT; } else { reset2REQA(); @@ -113,36 +122,39 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ // SELECT: 9 bytes, SEL = 93/95/97, NVB=70 if (TrafficSource == TRAFFIC_READER && - BitCount == 9*8 && - (Buffer[0] & 0xf0) == 0x90 && - (Buffer[0] & 0x09) == 0x01 && - Buffer[1] == 0x70) - { + BitCount == 9 * 8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01 && + Buffer[1] == 0x70) { SniffState = STATE_SAK; - } else{ + } else { // Not valid, reset reset2REQA(); } break; case STATE_SAK: // SAK: 1Byte SAK + CRC - if(TrafficSource == TRAFFIC_CARD && - BitCount == 3*9 && - checkParityBits(Buffer, BitCount)) - { - if((Buffer[0] & 0x04) == 0x00){ + if (TrafficSource == TRAFFIC_CARD && + BitCount == 3 * 9 && + checkParityBits(Buffer, BitCount)) { + if ((Buffer[0] & 0x04) == 0x00) { // UID complete, success SELECTED, - // TODO: Mark the current threshold as success and continue + // Mark the current threshold as ok and finish // reset SniffState = STATE_REQA; - selected = true; - LED_PORT.OUTCLR = LED_RED; + LED_PORT.OUTSET = LED_RED; + Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] += 1; + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL); + char tmpBuf[10]; + snprintf(tmpBuf, 10, "%4" PRIu16 ": ", tmp_th); + TerminalSendString(tmpBuf); + Sniff14443AAppReset(); } else { // UID not complete, goto ANTICOLLI SniffState = STATE_ANTICOLLI; } - } else{ + } else { reset2REQA(); } break; @@ -150,7 +162,7 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ break; } break; - + } default: return 0; } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index b58cc16..628eead 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -281,8 +281,6 @@ INLINE void CardSniffInit(void) * bit halves had modulations since the last pause. */ - DACB.CH0DATA = GlobalSettings.ActiveSettingPtr->ReaderThreshold; // real threshold voltage can be calculated with ch0data * Vref / 0xFFF - // Comparator ADC /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; From daf51f28d77936d7a24c2d3a5eafd8786689443f Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 27 Jul 2018 17:12:53 +0100 Subject: [PATCH 29/50] Continue threshold searching from the last searched value or the current configured value (cherry picked from commit f3aa7b2) --- Firmware/Chameleon-Mini/Application/Sniff14443A.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c index 59f3ed7..bea898c 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff14443A.c +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -28,9 +28,8 @@ static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIB void Sniff14443AAppInit(void){ SniffState = STATE_REQA; - - tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN; - CodecThresholdSet(tmp_th); + // Get current threshold and continue searching from here + tmp_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; } void Sniff14443AAppReset(void){ @@ -56,6 +55,7 @@ INLINE void reset2REQA(void){ tmp_th = CodecThresholdIncrement(); } else{ // mark finish + CommandLinePendingTaskFinished(COMMAND_INFO_FALSE, NULL); } } uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ @@ -145,10 +145,14 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ LED_PORT.OUTSET = LED_RED; Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] += 1; CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL); + // Send this threshold to terminal char tmpBuf[10]; snprintf(tmpBuf, 10, "%4" PRIu16 ": ", tmp_th); TerminalSendString(tmpBuf); + // Save value to EEPROM + SETTING_UPDATE(GlobalSettings.ActiveSettingPtr->ReaderThreshold); + Sniff14443AAppReset(); } else { // UID not complete, goto ANTICOLLI From eea78c8f5661faddaa55a9fda1500ccb541535a9 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 17 Jul 2018 15:43:09 +0100 Subject: [PATCH 30/50] Decode sniffing data with parityBit in Python Software If parity bit check failed, ! is appended to the data and raw data is diaplayed Currently Software layer parity bit check and removal is only enabled in sniffing mode (cherry picked from commit 2cfd54a) --- Software/Chameleon/Log.py | 47 +++++++++++++++++++++++++++++++++++++++ Software/chamlog.py | 1 + 2 files changed, 48 insertions(+) diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index bcf7a24..168704c 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -2,6 +2,40 @@ import struct import binascii +import math + +def checkParityBit(data): + byteCount = len(data) + # Short frame, no parityBit + if (byteCount == 1): + return (True, data) + + # 9 bit is a group, validate bit count is calculated below + bitCount = int((byteCount*8)/9) * 9 + parsedData = bytearray(int(bitCount/9)) + + oneCounter = 0 # Counter for count ones in a byte + for i in range(0, bitCount): + # Get bit i in data + byteIndex = math.floor(i/8) + bitIndex = i % 8 + bit = (data[byteIndex] >> bitIndex) & 0x01 + + # Check parityBit + # Current bit is parityBit + if(i % 9 == 8): + # Even number of ones in current byte + if(oneCounter % 2 and bit == 1): + return (False, data) + # Odd number of ones in current byte + elif((not oneCounter % 2) and bit == 0): + return (False, data) + oneCounter = 0 + # Current bit is normal bit + else: + oneCounter += bit + parsedData[int(i/9)] |= bit << (i%9) + return (True, parsedData) def noDecoder(data): return "" @@ -12,6 +46,13 @@ def textDecoder(data): def binaryDecoder(data): return binascii.hexlify(data).decode() +def binaryParityDecoder(data): + isValid, checkedData = checkParityBit(data) + if(isValid): + return binascii.hexlify(checkedData).decode() + else: + return binascii.hexlify(checkedData).decode()+"!" + eventTypes = { 0x00: { 'name': 'EMPTY', 'decoder': noDecoder }, 0x10: { 'name': 'GENERIC', 'decoder': textDecoder }, @@ -25,6 +66,12 @@ eventTypes = { 0x42: { 'name': 'CODEC RX W/PARITY', 'decoder': binaryDecoder }, 0x43: { 'name': 'CODEC TX W/PARITY', 'decoder': binaryDecoder }, + 0x44: { 'name': 'CODEC RX SNI READER', 'decoder': binaryDecoder }, + 0x45: { 'name': 'CODEC RX SNI READER W/PARITY', 'decoder': binaryParityDecoder }, + 0x46: { 'name': 'CODEC RX SNI CARD', 'decoder': binaryDecoder }, + 0x47: { 'name': 'CODEC RX SNI CARD W/PARITY', 'decoder': binaryParityDecoder }, + + 0x80: { 'name': 'APP READ', 'decoder': binaryDecoder }, 0x81: { 'name': 'APP WRITE', 'decoder': binaryDecoder }, 0x84: { 'name': 'APP INC', 'decoder': binaryDecoder }, diff --git a/Software/chamlog.py b/Software/chamlog.py index e73d503..f644379 100755 --- a/Software/chamlog.py +++ b/Software/chamlog.py @@ -58,6 +58,7 @@ def main(): else: verboseFunc = None + print("\nNote: If parityBit check failed, '!' is appended to the decoded data and raw data with parity bit is displayed.\n") if (args.live): # Live logging mode if (args.port is not None): From 74010123cde6c99bcaeac64b5ab8b83a657f0c5c Mon Sep 17 00:00:00 2001 From: chenzitai Date: Thu, 19 Jul 2018 13:49:35 +0100 Subject: [PATCH 31/50] Add basic ISO14443 log data parser for Reader side traffic Can parse: SELECT, HALE, RATS, PPS, DESELECT (cherry picked from commit aa46598) --- Software/Chameleon/ISO14443.py | 87 ++++++++++++++++++++++++++++++++++ Software/Chameleon/Log.py | 12 ++++- Software/chamlog.py | 8 ++-- 3 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 Software/Chameleon/ISO14443.py diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py new file mode 100644 index 0000000..a04d253 --- /dev/null +++ b/Software/Chameleon/ISO14443.py @@ -0,0 +1,87 @@ +import binascii + +ReaderTrafficTypes = { + "SEL":{ + 0x93: "SEL_CL1 ", + 0x95: "SEL_CL2 ", + 0x97: "SEL_CL3 ", + }, + # 1 byte commands + "SHORTFRAME": { + 0x26: "REQA", + 0x52: "WUPA", + 0x35: "Optional Timeslot Method", + # 40 - 4F Proprietary + # 78 - 7F proprietary + # Other RFU + }, + "FSDI":{ + 0x0: "FSD:16 ", + 0x1: "FSD:24 ", + 0x2: "FSD:32 ", + 0x3: "FSD:40 ", + 0x4: "FSD:48 ", + 0x5: "FSD:64 ", + 0x6: "FSD:96 ", + 0x7: "FSD:128 ", + 0x8: "FSD:256 " + }, +} + +CardTrafficTypes = { + +} +def parseReader(data): + byteCount = len(data) + note = "" + + # short frame commands + if (byteCount == 1 and data[0] in ReaderTrafficTypes["SHORTFRAME"]): + note += ReaderTrafficTypes["SHORTFRAME"][data[0]] + + # ANTICOLLISION command + elif (byteCount<9 and byteCount > 1 and data[0] in ReaderTrafficTypes["SEL"] and data[1] & 0x88 == 0 ): + note += "ATCOLI - " + note += ReaderTrafficTypes["SEL"][data[0]] + # note += "UID_CLn:" + binascii.hexlify(data[2:7]).decode() + " " + # note += str((data[1] >> 4) & 0x0f) + "bytes + " + str(data[1] & 0x0f) + "bits " + + # SELECT Command + elif (byteCount== 9 and data[0] in ReaderTrafficTypes["SEL"] and data[1] == 0x70): + note += "SELECT - " + note += ReaderTrafficTypes["SEL"][data[0]] + note += "UID_CLn:" + binascii.hexlify(data[2:7]).decode() + " " + # note += "7bytes + 0bits " + # note += "CRC_A:"+data[8] + # HALT Command + elif (byteCount == 4 and data[0] == 0x50 and data[1] == 0x00): + note += "HALT" + # RATS + elif (byteCount == 4 and data[0] == 0xe0 and ((data[1] & 0x0f) < 15) and ((data[1] & 0xf0 >> 8) in ReaderTrafficTypes["FSDI"])): + note += "RATS - " + note += ReaderTrafficTypes["FSDI"][data[1]>>8] + note += "CID:" + str(data[1]&0x0f) + " " + # PPS Protocol and parameter selection request + # PSS0 only + elif (byteCount == 4 and (data[0]&0xf0 == 0xd0) and (data[1] == 0x01)): + note += "PSS0 - " + note += "CID:"+str(data[1]&0x0f) + " " + # PSS0+1 + elif (byteCount == 5 and (data[0]&0xf0 == 0xd0) and (data[1] == 0x11) and (data[2]&0xf0 == 0x00)): + note += "PSS0+1 - " + note += "CID:"+str(data[1]&0x0f) + " " + note += "DSI:"+str(pow(2,(data[2]>>2)&0x03)) + " " + note += "DRI:"+str(pow(2,data[2]&0x03)) + " " + # BLOCK S-block PCB DESELECT + # Without CID + elif (byteCount == 3 and data[0] == 0xc2): + note += "DESEL" + # With CID + elif (byteCount == 4 and data[0] == 0xca and data[1]&0x30 == 0x00): + note += "DESEL - " + note += "CID:"+ str(data[1]&0x0f) + " " + + return note + +def parseCard(data): + pass \ No newline at end of file diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index 168704c..61d2098 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -3,6 +3,7 @@ import struct import binascii import math +import Chameleon.ISO14443 as iso14443_3 def checkParityBit(data): byteCount = len(data) @@ -96,7 +97,7 @@ eventTypes = { TIMESTAMP_MAX = 65536 eventTypes = { i : ({'name': 'UNKNOWN', 'decoder': binaryDecoder} if i not in eventTypes.keys() else eventTypes[i]) for i in range(256) } -def parseBinary(binaryStream): +def parseBinary(binaryStream, decode=False): log = [] # Completely read file contents and process them byte by byte @@ -135,13 +136,20 @@ def parseBinary(binaryStream): if (deltaTimestamp < 0): deltaTimestamp += TIMESTAMP_MAX; + note = "" + # If we need to decode the data + if (decode): + # Decode the data from Reader + if(event == 0x44 or event == 0x45): + note = iso14443_3.parseReader(binascii.a2b_hex(logData)) # Create log entry as dict and append it to event list logEntry = { 'eventName': eventTypes[event]['name'], 'dataLength': dataLength, 'timestamp': timestamp, 'deltaTimestamp': deltaTimestamp, - 'data': logData + 'data': logData, + 'note': note } log.append(logEntry) diff --git a/Software/chamlog.py b/Software/chamlog.py index f644379..da4281a 100755 --- a/Software/chamlog.py +++ b/Software/chamlog.py @@ -19,10 +19,11 @@ def verboseLog(text): def formatText(log): formatString = '{timestamp:0>5d} ms <{deltaTimestamp:>+6d} ms>:' - formatString += '{eventName:<16} ({dataLength:<3} bytes) [{data}]\n' + formatString += '{eventName:<28} ({dataLength:<3} bytes)\t[{data:<20}]\t{note}\n' text = '' for logEntry in log: + text += formatString.format(**logEntry) return text @@ -46,6 +47,7 @@ def main(): argParser.add_argument("-t", "--type", choices=outputTypes.keys(), default='text', help="specifies output type") + argParser.add_argument("-d", "--decode", dest="decode", action='store_true', default=False) argParser.add_argument("-l", "--live", dest="live", action='store_true', help="Use live logging capabilities of Chameleon") argParser.add_argument("-c", "--clear", dest="clear", action='store_true', help="Clear Chameleon's log memory when using -p") argParser.add_argument("-m", "--mode", dest="mode", metavar="LOGMODE", help="Additionally set Chameleon's log mode after reading it's memory") @@ -69,7 +71,7 @@ def main(): while True: stream = io.BytesIO(chameleon.read()) - log = Chameleon.Log.parseBinary(stream) + log = Chameleon.Log.parseBinary(stream, args.decode) if (len(log) > 0): print(outputTypes[args.type](log)) @@ -95,7 +97,7 @@ def main(): sys.exit(2) # Parse actual logfile - log = Chameleon.Log.parseBinary(handle) + log = Chameleon.Log.parseBinary(handle, args.decode) # Print to console using chosen output type print(outputTypes[args.type](log)) From 7cc3793033f135858926c121b24bee476f26d0e9 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 22 Jul 2018 00:09:10 +0100 Subject: [PATCH 32/50] Add commands for setting threshold and upgrade (cherry picked from commit d43975e) --- Software/Chameleon/Device.py | 14 +++++++++++++- Software/chamtool.py | 21 ++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Software/Chameleon/Device.py b/Software/Chameleon/Device.py index 57169c7..1852cf0 100644 --- a/Software/Chameleon/Device.py +++ b/Software/Chameleon/Device.py @@ -21,7 +21,10 @@ class Device: COMMAND_RBUTTON = "RBUTTON" COMMAND_GREEN_LED = "LEDGREEN" COMMAND_RED_LED = "LEDRED" - + COMMAND_THRESHOLD = "THRESHOLD" + COMMAND_UPGRADE = "upgrade" + + STATUS_CODE_OK = 100 STATUS_CODE_OK_WITH_TEXT = 101 STATUS_CODE_WAITING_FOR_XMODEM = 110 @@ -240,3 +243,12 @@ class Device: return self.getCmdSuggestions(self.COMMAND_RED_LED) else: return self.getSetCmd(self.COMMAND_RED_LED, newFunction) + + def cmdThreshold(self, value): + if(value == self.SUGGEST_CHAR): + return self.getCmdSuggestions(self.COMMAND_THRESHOLD) + else: + return self.getSetCmd(self.COMMAND_THRESHOLD, value) + + def cmdUpgrade(self): + return self.execCmd(self.COMMAND_UPGRADE) \ No newline at end of file diff --git a/Software/chamtool.py b/Software/chamtool.py index 6f97a96..0e964ee 100755 --- a/Software/chamtool.py +++ b/Software/chamtool.py @@ -119,7 +119,21 @@ def cmdRedLED(chameleon, arg): return "Red LED function has been set to {}".format(chameleon.cmdRedLED()['response']) else: return "Setting red LED function to {} failed: {}".format(arg, result['statusText']) - + +def cmdThreshold(chameleon, arg): + result = chameleon.cmdThreshold(arg) + + if (arg is None): + return "Current threshold is: {}".format(result['response']) + else: + if (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "Threshold have been set to {}".format(arg) + else: + return "Setting threshold faled: {}".format(arg, result['statusText']) + +def cmdUpgrade(chameleon, arg): + result = chameleon.cmdUpgrade() + return "" # Custom class for argparse class CmdListAction(argparse.Action): def __init__(self, option_strings, dest, default=False, required=False, @@ -154,6 +168,9 @@ def main(): cmdArgGroup.add_argument("-rb", "--rbutton", dest="rbutton", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current right button action") cmdArgGroup.add_argument("-gl", "--gled", dest="gled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current green led function") cmdArgGroup.add_argument("-rl", "--rled", dest="rled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current red led function") + cmdArgGroup.add_argument("-th", "--threshold", dest="threshold", action=CmdListAction, nargs='?', help="retrieve or set the threshold") + cmdArgGroup.add_argument("-ug", "--upgrade", dest="upgrade", action=CmdListAction, nargs=0, help="set the micro Controller to upgrade mode") + args = argParser.parse_args() if (args.verbose): @@ -179,6 +196,8 @@ def main(): "rbutton" : cmdRButton, "gled" : cmdGreenLED, "rled" : cmdRedLED, + "threshold" : cmdThreshold, + "upgrade" : cmdUpgrade, } if hasattr(args, "cmdList"): From c145976f3fcadcd185caeb46e3b938b177f18bcf Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 25 Jul 2018 00:51:40 +0100 Subject: [PATCH 33/50] Add CRC_A check function for Decode Reader SELECT and RATS command (cherry picked from commit 4eec449) --- Software/Chameleon/ISO14443.py | 29 ++++++++++++++++++++++++++++- Software/requirements.txt | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index a04d253..4956232 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -1,4 +1,10 @@ import binascii +import crcmod + +# Parameters for CRC_A +CRC_INIT = 0x6363 +POLY = 0x11021 +CRC_A_func = crcmod.mkCrcFun(POLY, initCrc=CRC_INIT, xorOut=0) ReaderTrafficTypes = { "SEL":{ @@ -31,6 +37,22 @@ ReaderTrafficTypes = { CardTrafficTypes = { } + +def CRC_A(data): + return CRC_A_func(data) + +def CRC_A_check(data): + datalen = len(data) + # Short frame or no space for CRC skip check + if(datalen < 4 ): + return + + crc = CRC_A(bytearray(data[0:datalen-2])).to_bytes(2,'little') + if (data[datalen-2:datalen] == crc): + return True + else: + return False + def parseReader(data): byteCount = len(data) note = "" @@ -51,8 +73,11 @@ def parseReader(data): note += "SELECT - " note += ReaderTrafficTypes["SEL"][data[0]] note += "UID_CLn:" + binascii.hexlify(data[2:7]).decode() + " " + # Check CRC for SELECT + if(not CRC_A_check(data)): + note+=" WRONG CRC " # note += "7bytes + 0bits " - # note += "CRC_A:"+data[8] + # note += "CRC_A:"+data[7:9] # HALT Command elif (byteCount == 4 and data[0] == 0x50 and data[1] == 0x00): note += "HALT" @@ -61,6 +86,8 @@ def parseReader(data): note += "RATS - " note += ReaderTrafficTypes["FSDI"][data[1]>>8] note += "CID:" + str(data[1]&0x0f) + " " + if(not CRC_A_check(data)): + note+=" WRONG CRC " # PPS Protocol and parameter selection request # PSS0 only elif (byteCount == 4 and (data[0]&0xf0 == 0xd0) and (data[1] == 0x01)): diff --git a/Software/requirements.txt b/Software/requirements.txt index f6c1a1f..5900a94 100644 --- a/Software/requirements.txt +++ b/Software/requirements.txt @@ -1 +1,2 @@ pyserial +crcmod \ No newline at end of file From 686cbf011e8f42f21297f7d9c7b148fe1c03ac8a Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sat, 28 Jul 2018 01:28:55 +0100 Subject: [PATCH 34/50] Add decode functions for card response in anti collision phase (cherry picked from commit b4ca798) --- Software/Chameleon/ISO14443.py | 36 +++++++++++++++++++++++++++++----- Software/Chameleon/Log.py | 2 ++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index 4956232..e5242b8 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -32,10 +32,15 @@ ReaderTrafficTypes = { 0x7: "FSD:128 ", 0x8: "FSD:256 " }, + } CardTrafficTypes = { - + "SAK":{ + 0x04: "UID NOT Complete ", + 0x20: "UID complete, PICC compliant with 14443-4 ", + 0x00: "UID complete, PICC NOT compliant with 14443-4" + } } def CRC_A(data): @@ -43,9 +48,9 @@ def CRC_A(data): def CRC_A_check(data): datalen = len(data) - # Short frame or no space for CRC skip check - if(datalen < 4 ): - return + # Short frame/SAK or no space for CRC skip check + if(datalen < 3 ): + return True crc = CRC_A(bytearray(data[0:datalen-2])).to_bytes(2,'little') if (data[datalen-2:datalen] == crc): @@ -70,9 +75,10 @@ def parseReader(data): # SELECT Command elif (byteCount== 9 and data[0] in ReaderTrafficTypes["SEL"] and data[1] == 0x70): + # TODO: distinguish CT+uid012+BCC and uid0123+BCC note += "SELECT - " note += ReaderTrafficTypes["SEL"][data[0]] - note += "UID_CLn:" + binascii.hexlify(data[2:7]).decode() + " " + note += "UID_CLn:" + binascii.hexlify(data[2:6]).decode() + " " # Check CRC for SELECT if(not CRC_A_check(data)): note+=" WRONG CRC " @@ -111,4 +117,24 @@ def parseReader(data): return note def parseCard(data): + + byteCount = len(data) + note = "" + + # ATQA: RRRR XXXX XXRX XXXX + if(byteCount == 2 and (data[0] & 0x20 == 0x00) and (data[1] & 0xf0 == 0x00)): + note += "ATQA - " + note += binascii.hexlify(data).decode() + # SAK + elif (byteCount == 3 and (data[0] & (~0x24)) == 0x00): + note += "SAK - " + note += CardTrafficTypes["SAK"][(data[2] & 0x24)] + if not CRC_A_check(data): + note += " WRONG CRC " + # UID + elif (byteCount == 5 and (data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4] ): + note += "UID Resp - CLn " + + return note + pass \ No newline at end of file diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index 61d2098..aa0d7a9 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -142,6 +142,8 @@ def parseBinary(binaryStream, decode=False): # Decode the data from Reader if(event == 0x44 or event == 0x45): note = iso14443_3.parseReader(binascii.a2b_hex(logData)) + elif (event == 0x46 or event == 0x47): + note = iso14443_3.parseCard(binascii.a2b_hex(logData)) # Create log entry as dict and append it to event list logEntry = { 'eventName': eventTypes[event]['name'], From 56b17302dff67f1bafd666ddcb26676162b06b32 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 29 Jul 2018 15:38:07 +0100 Subject: [PATCH 35/50] Add decoding ATS in sniffing mode (cherry picked from commit 1ef1af2) --- Software/Chameleon/ISO14443.py | 133 ++++++++++++++++++++++++++------- Software/Chameleon/Log.py | 5 +- 2 files changed, 110 insertions(+), 28 deletions(-) diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index e5242b8..94c60fa 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -1,11 +1,19 @@ import binascii import crcmod - +from enum import Enum # Parameters for CRC_A CRC_INIT = 0x6363 POLY = 0x11021 CRC_A_func = crcmod.mkCrcFun(POLY, initCrc=CRC_INIT, xorOut=0) + +class ReaderCMD(Enum): + NONE = 0 + RATS = 1 + PPS = 2 + +readerCMD = ReaderCMD.NONE + ReaderTrafficTypes = { "SEL":{ 0x93: "SEL_CL1 ", @@ -38,8 +46,20 @@ ReaderTrafficTypes = { CardTrafficTypes = { "SAK":{ 0x04: "UID NOT Complete ", + 0x24: "UID NOT Complete, PICC compliant with 14443-4", 0x20: "UID complete, PICC compliant with 14443-4 ", 0x00: "UID complete, PICC NOT compliant with 14443-4" + }, + "FSCI": { + 0x0: "FSCC:16 ", + 0x1: "FSC:24 ", + 0x2: "FSC:32 ", + 0x3: "FSC:40 ", + 0x4: "FSC:48 ", + 0x5: "FSC:64 ", + 0x6: "FSC:96 ", + 0x7: "FSC:128 ", + 0x8: "FSC:256 " } } @@ -58,66 +78,77 @@ def CRC_A_check(data): else: return False -def parseReader(data): +def parseReader_3(data): byteCount = len(data) note = "" # short frame commands if (byteCount == 1 and data[0] in ReaderTrafficTypes["SHORTFRAME"]): - note += ReaderTrafficTypes["SHORTFRAME"][data[0]] + note += ReaderTrafficTypes["SHORTFRAME"][data[0]] # ANTICOLLISION command - elif (byteCount<9 and byteCount > 1 and data[0] in ReaderTrafficTypes["SEL"] and data[1] & 0x88 == 0 ): + elif (byteCount < 9 and byteCount > 1 and data[0] in ReaderTrafficTypes["SEL"] and data[1] & 0x88 == 0): note += "ATCOLI - " note += ReaderTrafficTypes["SEL"][data[0]] # note += "UID_CLn:" + binascii.hexlify(data[2:7]).decode() + " " # note += str((data[1] >> 4) & 0x0f) + "bytes + " + str(data[1] & 0x0f) + "bits " # SELECT Command - elif (byteCount== 9 and data[0] in ReaderTrafficTypes["SEL"] and data[1] == 0x70): + elif (byteCount == 9 and data[0] in ReaderTrafficTypes["SEL"] and data[1] == 0x70): # TODO: distinguish CT+uid012+BCC and uid0123+BCC note += "SELECT - " note += ReaderTrafficTypes["SEL"][data[0]] note += "UID_CLn:" + binascii.hexlify(data[2:6]).decode() + " " # Check CRC for SELECT - if(not CRC_A_check(data)): - note+=" WRONG CRC " + if (not CRC_A_check(data)): + note += " WRONG CRC " # note += "7bytes + 0bits " # note += "CRC_A:"+data[7:9] # HALT Command elif (byteCount == 4 and data[0] == 0x50 and data[1] == 0x00): note += "HALT" + + return note + +def parseReader_4(data): + byteCount = len(data) + note = "" + # RATS - elif (byteCount == 4 and data[0] == 0xe0 and ((data[1] & 0x0f) < 15) and ((data[1] & 0xf0 >> 8) in ReaderTrafficTypes["FSDI"])): + if (byteCount == 4 and data[0] == 0xe0 and ((data[1] & 0x0f) < 15) and ( + (data[1] & 0xf0 >> 8) in ReaderTrafficTypes["FSDI"])): note += "RATS - " - note += ReaderTrafficTypes["FSDI"][data[1]>>8] - note += "CID:" + str(data[1]&0x0f) + " " - if(not CRC_A_check(data)): - note+=" WRONG CRC " + note += ReaderTrafficTypes["FSDI"][data[1] >> 8] + note += "CID:" + str(data[1] & 0x0f) + " " + if (not CRC_A_check(data)): + note += " WRONG CRC " + else: + readerCMD = ReaderCMD.RATS + # PPS Protocol and parameter selection request # PSS0 only - elif (byteCount == 4 and (data[0]&0xf0 == 0xd0) and (data[1] == 0x01)): + elif (byteCount == 4 and (data[0] & 0xf0 == 0xd0) and (data[1] == 0x01)): note += "PSS0 - " - note += "CID:"+str(data[1]&0x0f) + " " + note += "CID:" + str(data[1] & 0x0f) + " " + readerCMD = ReaderCMD.PPS # PSS0+1 - elif (byteCount == 5 and (data[0]&0xf0 == 0xd0) and (data[1] == 0x11) and (data[2]&0xf0 == 0x00)): + elif (byteCount == 5 and (data[0] & 0xf0 == 0xd0) and (data[1] == 0x11) and (data[2] & 0xf0 == 0x00)): note += "PSS0+1 - " - note += "CID:"+str(data[1]&0x0f) + " " - note += "DSI:"+str(pow(2,(data[2]>>2)&0x03)) + " " - note += "DRI:"+str(pow(2,data[2]&0x03)) + " " - # BLOCK S-block PCB DESELECT + note += "CID:" + str(data[1] & 0x0f) + " " + note += "DSI:" + str(pow(2, (data[2] >> 2) & 0x03)) + " " + note += "DRI:" + str(pow(2, data[2] & 0x03)) + " " + # BLOCK S-block PCB DESELECT # Without CID elif (byteCount == 3 and data[0] == 0xc2): note += "DESEL" # With CID - elif (byteCount == 4 and data[0] == 0xca and data[1]&0x30 == 0x00): + elif (byteCount == 4 and data[0] == 0xca and data[1] & 0x30 == 0x00): note += "DESEL - " - note += "CID:"+ str(data[1]&0x0f) + " " - + note += "CID:" + str(data[1] & 0x0f) + " " + return note -def parseCard(data): - +def parseCard_3(data): byteCount = len(data) note = "" @@ -126,7 +157,7 @@ def parseCard(data): note += "ATQA - " note += binascii.hexlify(data).decode() # SAK - elif (byteCount == 3 and (data[0] & (~0x24)) == 0x00): + elif (byteCount == 3 and ((data[0] & (0x24)) in CardTrafficTypes["SAK"])): note += "SAK - " note += CardTrafficTypes["SAK"][(data[2] & 0x24)] if not CRC_A_check(data): @@ -137,4 +168,54 @@ def parseCard(data): return note - pass \ No newline at end of file +def parseCard_4(data): + byteCount = len(data) + note = "" + + # ATS + # TL + T0 + TA + TB + TC + T1 ... + CRC + # TL: length without CRC + # ATS without data + if(byteCount == 3 and data[0] == (byteCount-2)): + note += "ATS - NO DATA" + # ATS with data mush have T0, T0 b8=0 + elif (byteCount > 3 and data[0] == (byteCount-2) + and data[1] & 0x80 == 0x00 + and data[1] & 0x0f in CardTrafficTypes["FSCI"]): + # Decode T0 + hasTA = data[1] & 0x10 + hasTB = data[1] & 0x20 + hasTC = data[1] & 0x40 + note += CardTrafficTypes["FSCI"][data[1] & 0x0f] + + # Which byte to decode next + byteNext = 2 # T0 Decoded, next is TA/TB/TC + # TA b4=0 + if (hasTA and data[byteNext] & 0x08 == 0x00): + note += "TA:" + hex(data[byteNext]) + " " + byteNext += 1 + + if (hasTB): + note += "TB:" + hex(data[byteNext]) + " " + byteNext += 1 + + # TC b3-8=0 + if (hasTC and data[byteNext] & 0xFC == 0x00): + note += "TC:" + hex(data[byteNext]) + " " + byteNext += 1 + + # TODO: decode historical bytes + + # Check CRC_A + if not CRC_A_check(data): + note += " WRONG CRC " + + elif (): + pass + return note + +def parseReader(data): + return parseReader_3(data) + parseReader_4(data) + +def parseCard(data): + return parseCard_3(data) + parseCard_4(data) diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index aa0d7a9..c10fd5f 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -137,13 +137,14 @@ def parseBinary(binaryStream, decode=False): deltaTimestamp += TIMESTAMP_MAX; note = "" - # If we need to decode the data - if (decode): + # If we need to decode the data and paritybit check success + if (decode and logData[-1] != '!'): # Decode the data from Reader if(event == 0x44 or event == 0x45): note = iso14443_3.parseReader(binascii.a2b_hex(logData)) elif (event == 0x46 or event == 0x47): note = iso14443_3.parseCard(binascii.a2b_hex(logData)) + # Create log entry as dict and append it to event list logEntry = { 'eventName': eventTypes[event]['name'], From 13e87a0b65e4310ae68dde5e344984e63e91d581 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 30 Jul 2018 04:40:21 +0100 Subject: [PATCH 36/50] Decode Basic I-Block and MF DESFire Ev1 APP Data in SniffingMode EV1: AuthAES, Select APP, GetAPPIDs, ReadData and decode I-Block (cherry picked from commit 5a14e1b) --- Software/Chameleon/ISO14443.py | 108 ++++++++++++++++++++++++++---- Software/Chameleon/MFDESFire.py | 113 ++++++++++++++++++++++++++++++++ Software/Chameleon/utils.py | 5 ++ 3 files changed, 214 insertions(+), 12 deletions(-) create mode 100644 Software/Chameleon/MFDESFire.py create mode 100644 Software/Chameleon/utils.py diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index 94c60fa..04fd6f6 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -1,6 +1,10 @@ import binascii import crcmod from enum import Enum + +from Chameleon.MFDESFire import MFDESFireDecode +from Chameleon.utils import TrafficSource + # Parameters for CRC_A CRC_INIT = 0x6363 POLY = 0x11021 @@ -12,6 +16,76 @@ class ReaderCMD(Enum): RATS = 1 PPS = 2 + + +class BlockData: + @staticmethod + def isBlockData(byteCount, data): + if(byteCount >= 3 and (data[0]& 0xE6) in ReaderTrafficTypes["PCB"]): + return True + else: + return False + + def __init__(self, byteCount, data, source): + self.byteCount = byteCount + self.data = data + self.PCB = data[0] + self.type = ReaderTrafficTypes["PCB"][self.PCB & 0xE6] + self.CID = None + self.NAD = None + self.INF = None + self.source = source + self.CRCChecked = CRC_A_check(data) + self.CardApplicationDecoder = MFDESFireDecode + + if self.CRCChecked: + + hasCID = self.PCB & 0x08 # PCB b4 indicate CID + hasNAD = 0 + + if (self.type == "IBlock"): + hasNAD = self.PCB & 0x04 # IBlock PCB b2 indicate NAD + + byteNext = 1 + # CID + if (hasCID): + self.CID = self.data[byteNext] + byteNext += 1 + + # NAD + if (hasNAD): + self.NAD = self.data[byteNext] + byteNext += 1 + + # INF field not empty + if(byteNext < byteCount -2): + self.INF = self.data[byteNext: byteCount-2] + + + def decode(self): + note = "" + # Prologue + # PCB + note += self.type + " " + + # CID + if (self.CID != None): + note += "CID:" + hex(self.CID) + " " + + # NAD + if (self.NAD != None): + note += "NAD:" + hex(self.NAD) + " " + + # INF + if (self.INF != None): + note += self.CardApplicationDecoder(self.INF, self.source) + # EDC CRC check + if not self.CRCChecked: + note += " WRONG CRC " + + + return note + readerCMD = ReaderCMD.NONE ReaderTrafficTypes = { @@ -40,7 +114,16 @@ ReaderTrafficTypes = { 0x7: "FSD:128 ", 0x8: "FSD:256 " }, - + "PCB":{ + # IBlock 000X XX1X + 0x02: "IBlock", # 000X X01X + 0x08: "IBlock", # 000X X11X + # RBlock 101X X01X + 0xA2: "RBlock", # 101X X01X + # SBlock 11XX X010 + 0xC2: "SBlock", # 110X X010 + 0xE2: "SBlock" # 111X X010 + } } CardTrafficTypes = { @@ -119,7 +202,7 @@ def parseReader_4(data): (data[1] & 0xf0 >> 8) in ReaderTrafficTypes["FSDI"])): note += "RATS - " note += ReaderTrafficTypes["FSDI"][data[1] >> 8] - note += "CID:" + str(data[1] & 0x0f) + " " + note += "CID:" + hex(data[1] & 0x0f) + " " if (not CRC_A_check(data)): note += " WRONG CRC " else: @@ -137,14 +220,12 @@ def parseReader_4(data): note += "CID:" + str(data[1] & 0x0f) + " " note += "DSI:" + str(pow(2, (data[2] >> 2) & 0x03)) + " " note += "DRI:" + str(pow(2, data[2] & 0x03)) + " " - # BLOCK S-block PCB DESELECT - # Without CID - elif (byteCount == 3 and data[0] == 0xc2): - note += "DESEL" - # With CID - elif (byteCount == 4 and data[0] == 0xca and data[1] & 0x30 == 0x00): - note += "DESEL - " - note += "CID:" + str(data[1] & 0x0f) + " " + + # Half-duplex block transmission + # PCB bit mask: 0b11100110 + elif (BlockData.isBlockData(byteCount, data)): + blockData = BlockData(byteCount,data, TrafficSource.Reader) + note = blockData.decode() return note @@ -209,9 +290,12 @@ def parseCard_4(data): # Check CRC_A if not CRC_A_check(data): note += " WRONG CRC " + # Application Data + elif (BlockData.isBlockData(byteCount, data)): + blockData = BlockData(byteCount,data, TrafficSource.Card) + note = blockData.decode() + - elif (): - pass return note def parseReader(data): diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py new file mode 100644 index 0000000..9e94556 --- /dev/null +++ b/Software/Chameleon/MFDESFire.py @@ -0,0 +1,113 @@ +from Chameleon.utils import TrafficSource +from binascii import hexlify + +lastCMD = 0x00 + +StatusCode = { + 0x00 : "OPERATION_OK", + 0x0C : "NO_CHANGES", + 0x0E : "ERR_OUT_OF_EEPROM", + 0x1C : "ILLEGAL_CMD_CODE", + 0x1E : "ERR_INTEGRITY", + 0x40 : "NO_SUCH_KEY", + 0x7E : "ERR_LENGTH", + 0x9D : "PERMISSION_DENIED", + 0x9E : "ERR_PARAMETER", + 0xA0 : "APP_NOT_FOUND", + 0xA1 : "ERR_APP_INTEGRITY", + 0xAE : "ERR_AUTH", + 0xAF : "ADDITIONAL_FRAME", + 0xBE : "ERR_BOUNDARY", + 0xC1 : "ERR_PICC_INTEGRITY", + 0xCA : "CMD_ABORTED", + 0xCD : "ERR_PICC_DISABLED", + 0xCE : "ERR_COUNT", + 0xDE : "ERR_DUPLICATE", + 0xEE : "ERR_EEPROM", + 0xF0 : "FILE_NOT_FOUND", + 0xF1 : "ERR_FILE_INTEGRITY" +} + + +def decodeSelectAPP(data): + if len(data) == 4: + return "AID: 0x"+ hexlify(data[1:4]).decode() + else: + return "Decode Fail" + +def decodeGetAPPID(data): + if len(data) == 1: + return "" + else: + return "Decode Fail" + +def decodeRespGetAPPID (data): + note = "APPIDs: |" + dataLen = len(data) + + for i in range (0,int((dataLen-1)/3)): + note += "0x"+hexlify(data[3*i: 3*(i+1)]).decode()+"|" + + return note + + +def decodeAuthAES(data): + if len(data) == 2: + return "KeyNo:"+hex(data[1]) + else: + return "Decode Fail" + +def decodeRespAuthAES(data): + return "" + + +def decodeReadData(data): + if len(data) == 8: + fileNo = data[1] + offSet = data[2:5] + length = data[5:8] + return "FileNo:"+hex(fileNo) + " OffSet:0x"+hexlify(offSet).decode() + " len:0x"+hexlify(length).decode() + else: + return "Decode Fail" + +def decodeRespReadData(data): + return "Data:0x"+hexlify(data[1:]).decode() + +def decodeAdiFrame(data): + return "" + +def decodeRespAdiFrame(data): + return "" + +def decodeDummy(data): + return "" + +MFDESFireCMDTypes = { + 0x5A : {"name": "SelectApp ", "CMDdecoder":decodeSelectAPP, "RespDecoder": decodeDummy}, + 0x6A : {"name": "GetAPPID ", "CMDdecoder":decodeGetAPPID, "RespDecoder": decodeRespGetAPPID}, + 0xAA : {"name": "AuthAES ", "CMDdecoder":decodeAuthAES, "RespDecoder": decodeRespAuthAES}, + 0xBD : {"name": "ReadData ", "CMDdecoder":decodeReadData, "RespDecoder": decodeRespReadData}, + 0xAF : {"name": "AdditionalFrame", "CMDdecoder":decodeAdiFrame, "RespDecoder": decodeRespAdiFrame} +} + + +def MFDESFireDecode(data, source): + note = "" + global lastCMD + if (source == TrafficSource.Reader): + cmd = data[0] + if cmd in MFDESFireCMDTypes : + lastCMD = cmd + note += "CMD:" + MFDESFireCMDTypes[cmd]["name"] + note += MFDESFireCMDTypes[cmd]["CMDdecoder"](data) + + elif (source == TrafficSource.Card): + status = data[0] + # Decode status code + if status in StatusCode: + note += StatusCode[status] + " " + # If status Ok, decode data + if status == 0x00 and lastCMD in MFDESFireCMDTypes: + note += MFDESFireCMDTypes[lastCMD]["RespDecoder"](data) + + return note \ No newline at end of file diff --git a/Software/Chameleon/utils.py b/Software/Chameleon/utils.py new file mode 100644 index 0000000..af4a5ab --- /dev/null +++ b/Software/Chameleon/utils.py @@ -0,0 +1,5 @@ +from enum import Enum + +class TrafficSource(Enum): + Reader = 0 + Card = 1 From 9bfcb942dccfcd062ee20537c8981aa53cea543f Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 30 Jul 2018 16:34:53 +0100 Subject: [PATCH 37/50] Add Color to Note (cherry picked from commit 2ef5769) --- Software/chamlog.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Software/chamlog.py b/Software/chamlog.py index da4281a..5bece7a 100755 --- a/Software/chamlog.py +++ b/Software/chamlog.py @@ -19,11 +19,12 @@ def verboseLog(text): def formatText(log): formatString = '{timestamp:0>5d} ms <{deltaTimestamp:>+6d} ms>:' - formatString += '{eventName:<28} ({dataLength:<3} bytes)\t[{data:<20}]\t{note}\n' - text = '' - - for logEntry in log: + formatString += '{eventName:<28} ({dataLength:<3} bytes) [{data:<20}] ' \ + '\033[94m {note} \x1b[0m \n' + text = '' + + for logEntry in log: text += formatString.format(**logEntry) return text From 0e26656eb4fc78dc904911f0420a72cd59173403 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 31 Jul 2018 04:02:32 +0100 Subject: [PATCH 38/50] Full implement decoding security related CMD in MFDESFire Sniffing (cherry picked from commit 210fd9f) --- Software/Chameleon/MFDESFire.py | 135 +++++++++++++++++++++++++++----- 1 file changed, 117 insertions(+), 18 deletions(-) diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py index 9e94556..6f64ebb 100644 --- a/Software/Chameleon/MFDESFire.py +++ b/Software/Chameleon/MFDESFire.py @@ -2,7 +2,7 @@ from Chameleon.utils import TrafficSource from binascii import hexlify lastCMD = 0x00 - +strFail = "Decode Fail" StatusCode = { 0x00 : "OPERATION_OK", 0x0C : "NO_CHANGES", @@ -33,13 +33,14 @@ def decodeSelectAPP(data): if len(data) == 4: return "AID: 0x"+ hexlify(data[1:4]).decode() else: - return "Decode Fail" + return strFail +# Get APP ID CMD def decodeGetAPPID(data): if len(data) == 1: return "" else: - return "Decode Fail" + return strFail def decodeRespGetAPPID (data): note = "APPIDs: |" @@ -49,18 +50,89 @@ def decodeRespGetAPPID (data): note += "0x"+hexlify(data[3*i: 3*(i+1)]).decode()+"|" return note - - +############################## +# Security Related Commands +############################## +# Authenticate AES CMD def decodeAuthAES(data): if len(data) == 2: return "KeyNo:"+hex(data[1]) else: - return "Decode Fail" + return strFail def decodeRespAuthAES(data): - return "" + if len(data) == 17: + return "ekNo(RndB):0x" + hexlify(data[1:]).decode() + else: + return strFail +def decodeAuthAESAF (data): + if len(data) == 33: + return "ekNo(RndA+RndB'):0x" + hexlify(data[1:]).decode() + else: + return strFail +def decodeCardAuthAESAF (data): + if len(data) == 17: + return "ekNo(RndA'):0x" + hexlify(data[1:]).decode() + else: + return strFail + +# Authenticate 3DES CMD +def decodeAuth3DES(data): + if len(data) == 2: + return "KeyNo:"+hex(data[1]) + else: + return strFail + +def decodeRespAuth3DES(data): + if len(data) == 9: + return "ekNo(RndB):0x" + hexlify(data[1:]).decode() + else: + return strFail + +def decodeAuth3DESAF(data): + if len(data) == 17: + return "dkNo(RndA+RndB'):0x" + hexlify(data[1:]).decode() + else: + return strFail + +def decodeCardAuth3DESAF (data): + if len(data) == 9: + return "ekNo(RndA'):0x" + hexlify(data[1:]).decode() + else: + return strFail + +# ChangeKeySettings CMD +def decodeChangeKeySettings(data): + if len(data) == 9: + return "KeySettings:0x" + hexlify(data[1:]).decode() + else: + return strFail +# GetKeySettings CMD +def decodeRespGetKeySettings(data): + if len(data) == 3: + return "KeySettings:" + hex(data[1]) + " MaxNoKeys:" + hex(data[2]) + else: + return strFail + +# ChangeKey CMD +def decodeChangeKey(data): + if len(data) == 26: + return "KeyNo:" + hex(data[1]) + " decipheredKeyData:0x"+hexlify(data[2:]).decode() + else: + return strFail + +# GetKeyVersion CMD +def decodeGetKeyVersion(data): + if len(data) == 2: + return "KeyNo:" + hex(data[1]) + else: + return strFail +def decodeRespGetKeyVersion(data): + return "KeyVersion" + hex(data[1]) if len(data) == 2 else strFail + +# Read Data def decodeReadData(data): if len(data) == 8: fileNo = data[1] @@ -68,28 +140,43 @@ def decodeReadData(data): length = data[5:8] return "FileNo:"+hex(fileNo) + " OffSet:0x"+hexlify(offSet).decode() + " len:0x"+hexlify(length).decode() else: - return "Decode Fail" + return strFail def decodeRespReadData(data): - return "Data:0x"+hexlify(data[1:]).decode() + return "Data:0x"+hexlify(data[1:]).decode() if len(data) >1 else strFail def decodeAdiFrame(data): - return "" + return "Data:0x"+hexlify(data[1:]).decode() if len(data) >1 else strFail def decodeRespAdiFrame(data): - return "" + return "Data:0x"+hexlify(data[1:]).decode() if len(data) >1 else strFail def decodeDummy(data): return "" + + MFDESFireCMDTypes = { 0x5A : {"name": "SelectApp ", "CMDdecoder":decodeSelectAPP, "RespDecoder": decodeDummy}, 0x6A : {"name": "GetAPPID ", "CMDdecoder":decodeGetAPPID, "RespDecoder": decodeRespGetAPPID}, - 0xAA : {"name": "AuthAES ", "CMDdecoder":decodeAuthAES, "RespDecoder": decodeRespAuthAES}, 0xBD : {"name": "ReadData ", "CMDdecoder":decodeReadData, "RespDecoder": decodeRespReadData}, - 0xAF : {"name": "AdditionalFrame", "CMDdecoder":decodeAdiFrame, "RespDecoder": decodeRespAdiFrame} + 0xAF : {"name": "AdditionalFrame ", "CMDdecoder":decodeAdiFrame, "RespDecoder": decodeRespAdiFrame}, + # Security Related CMD + 0xAA : {"name": "AuthAES ", "CMDdecoder": decodeAuthAES, "RespDecoder": decodeRespAuthAES}, + 0x0A : {"name": "Auth3DES", "CMDdecoder": decodeAuth3DES, "RespDecoder": decodeRespAuth3DES}, + 0x54 : {"name": "ChangeKeySettings ","CMDdecoder":decodeChangeKeySettings,"respDecoder": decodeDummy}, + 0x45 : {"name": "GetKeySettings ", "CMDdecoder":decodeDummy, "RespDecoder": decodeRespGetKeySettings}, + 0xC4 : {"name": "ChangeKey ", "CMDdecoder":decodeChangeKey, "RespDecoder": decodeDummy}, + 0x64 : {"name": "GetKeyVersion ", "CMDdecoder":decodeGetKeyVersion, "RespDecoder": decodeRespGetKeyVersion} + } +# Commands need to use additional frame +MFDESFireAFCMD = { + 0xAA : {"name": "AuthAES", "AFReaderDecoder":decodeAuthAESAF, "AFCardDecoder": decodeCardAuthAESAF}, + 0x0A : {"name": "Auth3DES", "AFReaderDecoder":decodeAuth3DESAF, "AFCardDecoder": decodeCardAuth3DESAF}, + +} def MFDESFireDecode(data, source): note = "" @@ -97,9 +184,17 @@ def MFDESFireDecode(data, source): if (source == TrafficSource.Reader): cmd = data[0] if cmd in MFDESFireCMDTypes : - lastCMD = cmd - note += "CMD:" + MFDESFireCMDTypes[cmd]["name"] - note += MFDESFireCMDTypes[cmd]["CMDdecoder"](data) + # If current frame is Additional Frame + # And the previous cmd need Additional Frame + if lastCMD in MFDESFireAFCMD and cmd == 0xAF: + note += "CMD:AdditionalFrame " + note += MFDESFireAFCMD[lastCMD]["AFReaderDecoder"](data) + # Current command not need Additional Frame + # or last cmd doesn't need AF + else: + lastCMD = cmd + note += "CMD:" + MFDESFireCMDTypes[cmd]["name"] + note += MFDESFireCMDTypes[cmd]["CMDdecoder"](data) elif (source == TrafficSource.Card): status = data[0] @@ -107,7 +202,11 @@ def MFDESFireDecode(data, source): if status in StatusCode: note += StatusCode[status] + " " # If status Ok, decode data - if status == 0x00 and lastCMD in MFDESFireCMDTypes: - note += MFDESFireCMDTypes[lastCMD]["RespDecoder"](data) + if (status == 0x00 or status == 0xAF) and lastCMD in MFDESFireCMDTypes: + # If last cmd need additional frame and this is the last frame + if status == 0x00 and lastCMD in MFDESFireAFCMD: + note += MFDESFireAFCMD[lastCMD]["AFCardDecoder"](data) + else: + note += MFDESFireCMDTypes[lastCMD]["RespDecoder"](data) return note \ No newline at end of file From abff0402f6bc1e89bb690d316e5e4b8d5cfda0cf Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 31 Jul 2018 04:25:52 +0100 Subject: [PATCH 39/50] Full implement decoding half-Duplex Data Trans Protocol in iso14443-4 (Show PCB Block infos) (cherry picked from commit 9f469be) --- Software/Chameleon/ISO14443.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index 04fd6f6..1ee4596 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -68,6 +68,28 @@ class BlockData: # PCB note += self.type + " " + # Block number + if ((self.type == "IBlock" or self.type == "RBlock") and self.PCB & 0x01): + note += "BlkNo:1 " + + # Chaining? + if (self.type == "IBlock" and self.PCB & 0x10): + note += "Chaining " + + # ACK/NAK? for R-Block + if (self.type == "RBlock"): + if (self.PCB & 0x10): + note += "NAK " + else: + note += "ACK " + + # DESEL/WTX for SBlock + if (self.type == "SBlock"): + if (self.PCB & 0x30 == 0x00): + note += "DESEL " + elif (self.PCB & 0x30 == 0x30): + note += "WTX" + # CID if (self.CID != None): note += "CID:" + hex(self.CID) + " " From 89b29415aaf969ef4c6f415d70ff755d3f65d5ad Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 31 Jul 2018 16:27:10 +0100 Subject: [PATCH 40/50] Fix bug: parsing SAK and ATS wrong because of non-stateful (cherry picked from commit 32b2e88) --- Software/Chameleon/ISO14443.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index 1ee4596..e574819 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -13,10 +13,13 @@ CRC_A_func = crcmod.mkCrcFun(POLY, initCrc=CRC_INIT, xorOut=0) class ReaderCMD(Enum): NONE = 0 - RATS = 1 - PPS = 2 + SELECT = 1 + RATS = 2 + PPS = 3 +readerCMD = ReaderCMD.NONE + class BlockData: @staticmethod @@ -108,7 +111,6 @@ class BlockData: return note -readerCMD = ReaderCMD.NONE ReaderTrafficTypes = { "SEL":{ @@ -156,7 +158,7 @@ CardTrafficTypes = { 0x00: "UID complete, PICC NOT compliant with 14443-4" }, "FSCI": { - 0x0: "FSCC:16 ", + 0x0: "FSC:16 ", 0x1: "FSC:24 ", 0x2: "FSC:32 ", 0x3: "FSC:40 ", @@ -184,6 +186,7 @@ def CRC_A_check(data): return False def parseReader_3(data): + global readerCMD byteCount = len(data) note = "" @@ -201,6 +204,7 @@ def parseReader_3(data): # SELECT Command elif (byteCount == 9 and data[0] in ReaderTrafficTypes["SEL"] and data[1] == 0x70): # TODO: distinguish CT+uid012+BCC and uid0123+BCC + readerCMD = ReaderCMD.SELECT note += "SELECT - " note += ReaderTrafficTypes["SEL"][data[0]] note += "UID_CLn:" + binascii.hexlify(data[2:6]).decode() + " " @@ -216,6 +220,7 @@ def parseReader_3(data): return note def parseReader_4(data): + global readerCMD byteCount = len(data) note = "" @@ -260,7 +265,7 @@ def parseCard_3(data): note += "ATQA - " note += binascii.hexlify(data).decode() # SAK - elif (byteCount == 3 and ((data[0] & (0x24)) in CardTrafficTypes["SAK"])): + elif (byteCount == 3 and readerCMD == ReaderCMD.SELECT and ((data[0] & (0x24)) in CardTrafficTypes["SAK"])): note += "SAK - " note += CardTrafficTypes["SAK"][(data[2] & 0x24)] if not CRC_A_check(data): @@ -272,6 +277,7 @@ def parseCard_3(data): return note def parseCard_4(data): + global readerCMD byteCount = len(data) note = "" @@ -279,12 +285,13 @@ def parseCard_4(data): # TL + T0 + TA + TB + TC + T1 ... + CRC # TL: length without CRC # ATS without data - if(byteCount == 3 and data[0] == (byteCount-2)): + if(byteCount == 3 and readerCMD == ReaderCMD.RATS and data[0] == (byteCount-2)): note += "ATS - NO DATA" # ATS with data mush have T0, T0 b8=0 - elif (byteCount > 3 and data[0] == (byteCount-2) + elif (byteCount > 3 and readerCMD == ReaderCMD.RATS and data[0] == (byteCount-2) and data[1] & 0x80 == 0x00 and data[1] & 0x0f in CardTrafficTypes["FSCI"]): + note += "ATS - " # Decode T0 hasTA = data[1] & 0x10 hasTB = data[1] & 0x20 @@ -317,6 +324,7 @@ def parseCard_4(data): blockData = BlockData(byteCount,data, TrafficSource.Card) note = blockData.decode() + readerCMD = ReaderCMD.NONE return note From f57207d2f19ab6b86b7288f9c7d34fc43d78e1a4 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 31 Jul 2018 17:07:03 +0100 Subject: [PATCH 41/50] Finish decoding PICC level commands of MFDESFire (cherry picked from commit 84f636a) --- Software/Chameleon/MFDESFire.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py index 6f64ebb..e30e4a2 100644 --- a/Software/Chameleon/MFDESFire.py +++ b/Software/Chameleon/MFDESFire.py @@ -27,11 +27,26 @@ StatusCode = { 0xF0 : "FILE_NOT_FOUND", 0xF1 : "ERR_FILE_INTEGRITY" } +# Create APP CMD +def decodeCreateAPP(data): + note = "" + if len(data) == 6: + note += "AID:0x"+hexlify(data[1:4]).decode() + " " + note += "KeySett:"+hex(data[4]) + " " + note += "NumOfKeys:"+hex(data[5]) + " " + else: + note += strFail + return note +def decodeDelAPP(data): + if len(data) == 4: + return "AID:0x"+hexlify(data[1:]).decode() + else: + return strFail def decodeSelectAPP(data): if len(data) == 4: - return "AID: 0x"+ hexlify(data[1:4]).decode() + return "AID:0x"+ hexlify(data[1:4]).decode() else: return strFail @@ -157,17 +172,25 @@ def decodeDummy(data): MFDESFireCMDTypes = { + # PICC Level Commands, GetVersion not decoded, please refer to datasheet for the meaning of resp + 0xCA : {"name": "CreateApp", "CMDdecoder":decodeCreateAPP, "RespDecoder": decodeDummy}, + 0xDA : {"name": "DelApp", "CMDdecoder":decodeDelAPP, "RespDecoder": decodeDummy}, 0x5A : {"name": "SelectApp ", "CMDdecoder":decodeSelectAPP, "RespDecoder": decodeDummy}, 0x6A : {"name": "GetAPPID ", "CMDdecoder":decodeGetAPPID, "RespDecoder": decodeRespGetAPPID}, + 0xFC : {"name": "FormatPICC", "CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, + 0x60 : {"name": "GetVersion", "CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, + # Data Manipulation Commands 0xBD : {"name": "ReadData ", "CMDdecoder":decodeReadData, "RespDecoder": decodeRespReadData}, - 0xAF : {"name": "AdditionalFrame ", "CMDdecoder":decodeAdiFrame, "RespDecoder": decodeRespAdiFrame}, # Security Related CMD 0xAA : {"name": "AuthAES ", "CMDdecoder": decodeAuthAES, "RespDecoder": decodeRespAuthAES}, 0x0A : {"name": "Auth3DES", "CMDdecoder": decodeAuth3DES, "RespDecoder": decodeRespAuth3DES}, 0x54 : {"name": "ChangeKeySettings ","CMDdecoder":decodeChangeKeySettings,"respDecoder": decodeDummy}, 0x45 : {"name": "GetKeySettings ", "CMDdecoder":decodeDummy, "RespDecoder": decodeRespGetKeySettings}, 0xC4 : {"name": "ChangeKey ", "CMDdecoder":decodeChangeKey, "RespDecoder": decodeDummy}, - 0x64 : {"name": "GetKeyVersion ", "CMDdecoder":decodeGetKeyVersion, "RespDecoder": decodeRespGetKeyVersion} + 0x64 : {"name": "GetKeyVersion ", "CMDdecoder":decodeGetKeyVersion, "RespDecoder": decodeRespGetKeyVersion}, + + # Additional Frame + 0xAF: {"name": "AdditionalFrame ", "CMDdecoder": decodeAdiFrame, "RespDecoder": decodeRespAdiFrame}, } From f2d78eeb2572893273978470b69f16292a2e770d Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 1 Aug 2018 18:04:50 +0100 Subject: [PATCH 42/50] Finish decoding Data Manipulation Commands commands of MFDESFire (cherry picked from commit 502d951) --- Software/Chameleon/MFDESFire.py | 71 +++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py index e30e4a2..96307d8 100644 --- a/Software/Chameleon/MFDESFire.py +++ b/Software/Chameleon/MFDESFire.py @@ -27,6 +27,9 @@ StatusCode = { 0xF0 : "FILE_NOT_FOUND", 0xF1 : "ERR_FILE_INTEGRITY" } +######################### +# PICC Level Commands +######################### # Create APP CMD def decodeCreateAPP(data): note = "" @@ -147,8 +150,11 @@ def decodeGetKeyVersion(data): def decodeRespGetKeyVersion(data): return "KeyVersion" + hex(data[1]) if len(data) == 2 else strFail +############################## +# Data Manipulation Commands +############################## # Read Data -def decodeReadData(data): +def decodeFileNoOffsetLen(data): if len(data) == 8: fileNo = data[1] offSet = data[2:5] @@ -156,8 +162,32 @@ def decodeReadData(data): return "FileNo:"+hex(fileNo) + " OffSet:0x"+hexlify(offSet).decode() + " len:0x"+hexlify(length).decode() else: return strFail +# Write Data +def decodeFileNoOffsetLenData(data): + if len(data) > 8: + fileNo = data[1] + offSet = data[2:5] + length = data[5:8] + dataWrite = data[8:] + return "FileNo:"+hex(fileNo) + " OffSet:0x"+hexlify(offSet).decode() + " len:0x"+hexlify(length).decode() + \ + " Data:0x" + hexlify(dataWrite).decode() + else: + return strFail -def decodeRespReadData(data): +# Get Value +def decodeFileNo(data): + if len(data) == 2: + return "FileNo:"+hex(data[1]) + else: + return strFail +# Credit +def decodeFileNoData(data): + if len(data) >2: + return "FileNo:" + hex(data[1]) + " Data:0x" + hexlify(data[2:]).decode() + else: + return strFail + +def decodeData(data): return "Data:0x"+hexlify(data[1:]).decode() if len(data) >1 else strFail def decodeAdiFrame(data): @@ -173,31 +203,46 @@ def decodeDummy(data): MFDESFireCMDTypes = { # PICC Level Commands, GetVersion not decoded, please refer to datasheet for the meaning of resp - 0xCA : {"name": "CreateApp", "CMDdecoder":decodeCreateAPP, "RespDecoder": decodeDummy}, - 0xDA : {"name": "DelApp", "CMDdecoder":decodeDelAPP, "RespDecoder": decodeDummy}, + 0xCA : {"name": "CreateApp ", "CMDdecoder":decodeCreateAPP, "RespDecoder": decodeDummy}, + 0xDA : {"name": "DelApp ", "CMDdecoder":decodeDelAPP, "RespDecoder": decodeDummy}, 0x5A : {"name": "SelectApp ", "CMDdecoder":decodeSelectAPP, "RespDecoder": decodeDummy}, 0x6A : {"name": "GetAPPID ", "CMDdecoder":decodeGetAPPID, "RespDecoder": decodeRespGetAPPID}, - 0xFC : {"name": "FormatPICC", "CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, - 0x60 : {"name": "GetVersion", "CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, + 0xFC : {"name": "FormatPICC ", "CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, + 0x60 : {"name": "GetVersion ", "CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, # Data Manipulation Commands - 0xBD : {"name": "ReadData ", "CMDdecoder":decodeReadData, "RespDecoder": decodeRespReadData}, + 0xBD : {"name": "ReadData ", "CMDdecoder":decodeFileNoOffsetLen, "RespDecoder": decodeData}, + 0x3D : {"name": "WriteData ", "CMDdecoder":decodeFileNoOffsetLenData, "RespDecoder": decodeDummy}, + 0x6C : {"name": "GetValue ", "CMDdecoder":decodeFileNo, "RespDecoder": decodeData}, + 0x0C : {"name": "Credit ", "CMDdecoder":decodeFileNoData, "RespDecoder": decodeDummy}, + 0xDC : {"name": "Debit ", "CMDdecoder":decodeFileNoData, "RespDecoder": decodeDummy}, + 0x1C : {"name": "LimitedCredit ", "CMDdecoder":decodeFileNoData, "RespDecoder": decodeDummy}, + 0x3B : {"name": "WriteRecord ", "CMDdecoder":decodeFileNoOffsetLenData, "RespDecoder": decodeDummy}, + 0xBB : {"name": "ReadRecord ", "CMDdecoder":decodeFileNoOffsetLen, "RespDecoder": decodeData}, + 0xEB : {"name": "ClearRecordFile ", "CMDdecoder":decodeFileNo, "RespDecoder": decodeDummy}, + 0xC7 : {"name": "CommitTransaction ","CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, + 0xA7 : {"name": "AbortTransaction ","CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, # Security Related CMD - 0xAA : {"name": "AuthAES ", "CMDdecoder": decodeAuthAES, "RespDecoder": decodeRespAuthAES}, - 0x0A : {"name": "Auth3DES", "CMDdecoder": decodeAuth3DES, "RespDecoder": decodeRespAuth3DES}, - 0x54 : {"name": "ChangeKeySettings ","CMDdecoder":decodeChangeKeySettings,"respDecoder": decodeDummy}, + 0xAA : {"name": "AuthAES ", "CMDdecoder": decodeAuthAES, "RespDecoder": decodeRespAuthAES}, + 0x0A : {"name": "Auth3DES ", "CMDdecoder": decodeAuth3DES, "RespDecoder": decodeRespAuth3DES}, + 0x54 : {"name": "ChangeKeySettings ","CMDdecoder":decodeChangeKeySettings,"RespDecoder": decodeDummy}, 0x45 : {"name": "GetKeySettings ", "CMDdecoder":decodeDummy, "RespDecoder": decodeRespGetKeySettings}, 0xC4 : {"name": "ChangeKey ", "CMDdecoder":decodeChangeKey, "RespDecoder": decodeDummy}, 0x64 : {"name": "GetKeyVersion ", "CMDdecoder":decodeGetKeyVersion, "RespDecoder": decodeRespGetKeyVersion}, # Additional Frame - 0xAF: {"name": "AdditionalFrame ", "CMDdecoder": decodeAdiFrame, "RespDecoder": decodeRespAdiFrame}, + 0xAF: {"name": "AdditionalFrame ", "CMDdecoder": decodeAdiFrame, "RespDecoder": decodeRespAdiFrame}, } # Commands need to use additional frame MFDESFireAFCMD = { - 0xAA : {"name": "AuthAES", "AFReaderDecoder":decodeAuthAESAF, "AFCardDecoder": decodeCardAuthAESAF}, - 0x0A : {"name": "Auth3DES", "AFReaderDecoder":decodeAuth3DESAF, "AFCardDecoder": decodeCardAuth3DESAF}, + 0xAA : {"name": "AuthAES ", "AFReaderDecoder":decodeAuthAESAF, "AFCardDecoder": decodeCardAuthAESAF}, + 0x0A : {"name": "Auth3DES ", "AFReaderDecoder":decodeAuth3DESAF, "AFCardDecoder": decodeCardAuth3DESAF}, + + 0x3D : {"name": "WriteData ", "AFReaderDecoder":decodeData, "AFCardDecoder": decodeDummy}, + 0xBB : {"name": "ReadRecord ", "AFReaderDecoder":decodeDummy, "AFCardDecoder": decodeData}, + + 0x3B: {"name": "WriteRecord ", "AFReaderDecoder": decodeData, "AFCardDecoder": decodeDummy} } From bc75cb982f843c9c4b85d9a940e66e1483519cd5 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Thu, 2 Aug 2018 01:15:17 +0100 Subject: [PATCH 43/50] Finish decoding # Application Level Commands commands of MFDESFire (cherry picked from commit c0e0607) --- Software/Chameleon/ISO14443.py | 3 -- Software/Chameleon/MFDESFire.py | 95 ++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index e574819..3306485 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -203,7 +203,6 @@ def parseReader_3(data): # SELECT Command elif (byteCount == 9 and data[0] in ReaderTrafficTypes["SEL"] and data[1] == 0x70): - # TODO: distinguish CT+uid012+BCC and uid0123+BCC readerCMD = ReaderCMD.SELECT note += "SELECT - " note += ReaderTrafficTypes["SEL"][data[0]] @@ -314,8 +313,6 @@ def parseCard_4(data): note += "TC:" + hex(data[byteNext]) + " " byteNext += 1 - # TODO: decode historical bytes - # Check CRC_A if not CRC_A_check(data): note += " WRONG CRC " diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py index 96307d8..f66eee6 100644 --- a/Software/Chameleon/MFDESFire.py +++ b/Software/Chameleon/MFDESFire.py @@ -190,6 +190,84 @@ def decodeFileNoData(data): def decodeData(data): return "Data:0x"+hexlify(data[1:]).decode() if len(data) >1 else strFail +########################### +# Application Level Commands +########################### +def decodeRespGetFileIDs(data): + if len(data) == 4: + return "FIDs:0x"+hexlify(data[1:]).decode() + else: + return strFail + +def decodeRespGetFileSettings(data): + lenData = len(data) + note = "" + if lenData >5: + note += "FileType:"+hex(data[1])+" ComSett:"+hex(data[2]) + "AccessRight:0x"+hexlify(data[3:5]).decode() + " " + if lenData == 8: + note += "FileSize:0x"+hexlify(data[5:]).decode() + elif lenData == 18: + note += "LowLimit:0x"+hexlify(data[5:9]).decode() + " " + note += "UpLimit:0x" + hexlify(data[9:13]).decode() + " " + note += "LimitedCreditVal:0x"+hexlify(data[13:17]).decode() + " " + note += "LimitedCreditEn:" + hex(data[17]) + elif lenData == 14: + note += "RecordSize:0x"+ hexlify(data[5:8]).decode() + " " + note += "MaxNumRecords:0x"+hexlify(data[8:11]).decode() + " " + note += "CurrentNumRecords:0x"+hexlify(data[11:]).decode() + return note + else: + return strFail + +def decodeFNComSetAccessRightsFileSize(data): + if len(data) == 8: + note = "FileNo:" + hex(data[1]) + " ComSet:" + hex(data[2]) + "AccessRight:0x" + hexlify( + data[3:5]).decode() + " " + note += "FileSize:0x" + hexlify(data[5:]).decode() + return note + else: + return strFail + +def decodeChangeFileSettings(data): + lenData = len(data) + note ="" + if lenData > 2: + note += "FileNo:"+hex(data[1]) + " " + if lenData == 5: + note += "ComSet:"+hex(data[2]) + " " + note += "AccessRights:0x"+hexlify(data[3:]).decode() + elif lenData == 10: + note += "NewSettings:0x"+hexlify(data[2:]).decode() + return note + else: + return strFail + +def decodeCreateValueFile(data): + if len(data) == 18: + note = "FileNo:"+hex(data[1])+" ComSet:"+hex(data[2]) + "AccessRight:0x"+hexlify(data[3:5]).decode() + " " + note += "LowLimit:0x"+hexlify(data[5:9]).decode() + " " + note += "UpLimit:0x" + hexlify(data[9:13]).decode() + " " + note += "Val:0x"+hexlify(data[13:17]).decode() + " " + note += "LimitedCreditEn:" + hex(data[17]) + return note + else: + return strFail + +def decodeCreateRecordFile(data): + if len(data) == 11: + note = "FileNo:"+hex(data[1])+" ComSet:"+hex(data[2]) + "AccessRight:0x"+hexlify(data[3:5]).decode() + " " + note += "RecordSize:0x"+hexlify(data[5:8]).decode()+" " + note += "MaxNumRecords:0x"+hexlify(data[8:]).decode() + return note + else: + return strFail + +def decodeDelFile(data): + if len(data) == 2: + return "FileNo:"+hex(data[1]) + else: + return strFail + def decodeAdiFrame(data): return "Data:0x"+hexlify(data[1:]).decode() if len(data) >1 else strFail @@ -201,7 +279,20 @@ def decodeDummy(data): + + MFDESFireCMDTypes = { + # Application Level Commands + 0x6F : {"name": "GetFileIDs", "CMDdecoder":decodeDummy, "RespDecoder": decodeRespGetFileIDs}, + 0xF5 : {"name": "GetFileSettings", "CMDdecoder":decodeFileNo, "RespDecoder": decodeRespGetFileSettings}, + 0x5F : {"name": "ChangeFileSettings", "CMDdecoder":decodeChangeFileSettings, "RespDecoder": decodeDummy}, + 0xCD : {"name": "CreateStdDataFile", "CMDdecoder":decodeFNComSetAccessRightsFileSize,"RespDecoder": decodeDummy}, + 0xCB : {"name": "CreateBackupDataFile", "CMDdecoder":decodeFNComSetAccessRightsFileSize,"RespDecoder": decodeDummy}, + 0xCC : {"name": "CreateValueFile", "CMDdecoder":decodeCreateValueFile, "RespDecoder": decodeDummy}, + 0xC1 : {"name": "CreateLinearRecordFile","CMDdecoder":decodeCreateRecordFile, "RespDecoder": decodeDummy}, + 0xC0 : {"name": "CreateCyclicRecordFile","CMDdecoder":decodeCreateRecordFile, "RespDecoder": decodeDummy}, + 0xDF: {"name": "DelFile", "CMDdecoder":decodeDelFile, "RespDecoder": decodeDummy}, + # PICC Level Commands, GetVersion not decoded, please refer to datasheet for the meaning of resp 0xCA : {"name": "CreateApp ", "CMDdecoder":decodeCreateAPP, "RespDecoder": decodeDummy}, 0xDA : {"name": "DelApp ", "CMDdecoder":decodeDelAPP, "RespDecoder": decodeDummy}, @@ -222,8 +313,8 @@ MFDESFireCMDTypes = { 0xC7 : {"name": "CommitTransaction ","CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, 0xA7 : {"name": "AbortTransaction ","CMDdecoder":decodeDummy, "RespDecoder": decodeDummy}, # Security Related CMD - 0xAA : {"name": "AuthAES ", "CMDdecoder": decodeAuthAES, "RespDecoder": decodeRespAuthAES}, - 0x0A : {"name": "Auth3DES ", "CMDdecoder": decodeAuth3DES, "RespDecoder": decodeRespAuth3DES}, + 0xAA : {"name": "AuthAES ", "CMDdecoder": decodeAuthAES, "RespDecoder": decodeRespAuthAES}, + 0x0A : {"name": "Auth3DES ", "CMDdecoder": decodeAuth3DES, "RespDecoder": decodeRespAuth3DES}, 0x54 : {"name": "ChangeKeySettings ","CMDdecoder":decodeChangeKeySettings,"RespDecoder": decodeDummy}, 0x45 : {"name": "GetKeySettings ", "CMDdecoder":decodeDummy, "RespDecoder": decodeRespGetKeySettings}, 0xC4 : {"name": "ChangeKey ", "CMDdecoder":decodeChangeKey, "RespDecoder": decodeDummy}, From 1d2847cdec3adbddef4ae995fdd831a59021bb72 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 3 Aug 2018 18:32:01 +0100 Subject: [PATCH 44/50] Add decoder selection parameter -d MFDESFire/None for different cards (cherry picked from commit 93635d9) --- Software/Chameleon/ISO14443.py | 31 +++++++++++++++++++++---------- Software/Chameleon/Log.py | 8 ++++---- Software/chamlog.py | 3 ++- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Software/Chameleon/ISO14443.py b/Software/Chameleon/ISO14443.py index 3306485..55565e9 100644 --- a/Software/Chameleon/ISO14443.py +++ b/Software/Chameleon/ISO14443.py @@ -20,6 +20,16 @@ class ReaderCMD(Enum): readerCMD = ReaderCMD.NONE +# Map card types string to decoder +def DummyCardDecoder(data, source): + return "" + +CardTypesMap = { + "None": {"ApplicationDecoder": DummyCardDecoder}, + "MFDESFire": {"ApplicationDecoder": MFDESFireDecode}, + +} + class BlockData: @staticmethod @@ -29,7 +39,8 @@ class BlockData: else: return False - def __init__(self, byteCount, data, source): + + def __init__(self, byteCount, data, source, Cardtype): self.byteCount = byteCount self.data = data self.PCB = data[0] @@ -39,7 +50,7 @@ class BlockData: self.INF = None self.source = source self.CRCChecked = CRC_A_check(data) - self.CardApplicationDecoder = MFDESFireDecode + self.CardApplicationDecoder = CardTypesMap[Cardtype]["ApplicationDecoder"] if self.CRCChecked: @@ -218,7 +229,7 @@ def parseReader_3(data): return note -def parseReader_4(data): +def parseReader_4(data, Cardtype): global readerCMD byteCount = len(data) note = "" @@ -250,7 +261,7 @@ def parseReader_4(data): # Half-duplex block transmission # PCB bit mask: 0b11100110 elif (BlockData.isBlockData(byteCount, data)): - blockData = BlockData(byteCount,data, TrafficSource.Reader) + blockData = BlockData(byteCount,data, TrafficSource.Reader, Cardtype) note = blockData.decode() return note @@ -275,7 +286,7 @@ def parseCard_3(data): return note -def parseCard_4(data): +def parseCard_4(data, Cardtype): global readerCMD byteCount = len(data) note = "" @@ -318,15 +329,15 @@ def parseCard_4(data): note += " WRONG CRC " # Application Data elif (BlockData.isBlockData(byteCount, data)): - blockData = BlockData(byteCount,data, TrafficSource.Card) + blockData = BlockData(byteCount,data, TrafficSource.Card, Cardtype) note = blockData.decode() readerCMD = ReaderCMD.NONE return note -def parseReader(data): - return parseReader_3(data) + parseReader_4(data) +def parseReader(data, Cardtype): + return parseReader_3(data) + parseReader_4(data, Cardtype) -def parseCard(data): - return parseCard_3(data) + parseCard_4(data) +def parseCard(data, Cardtype): + return parseCard_3(data) + parseCard_4(data, Cardtype) diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index c10fd5f..da32bc8 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -97,7 +97,7 @@ eventTypes = { TIMESTAMP_MAX = 65536 eventTypes = { i : ({'name': 'UNKNOWN', 'decoder': binaryDecoder} if i not in eventTypes.keys() else eventTypes[i]) for i in range(256) } -def parseBinary(binaryStream, decode=False): +def parseBinary(binaryStream, decoder=None): log = [] # Completely read file contents and process them byte by byte @@ -138,12 +138,12 @@ def parseBinary(binaryStream, decode=False): note = "" # If we need to decode the data and paritybit check success - if (decode and logData[-1] != '!'): + if (decoder!=None and logData[-1] != '!'): # Decode the data from Reader if(event == 0x44 or event == 0x45): - note = iso14443_3.parseReader(binascii.a2b_hex(logData)) + note = iso14443_3.parseReader(binascii.a2b_hex(logData), decoder) elif (event == 0x46 or event == 0x47): - note = iso14443_3.parseCard(binascii.a2b_hex(logData)) + note = iso14443_3.parseCard(binascii.a2b_hex(logData), decoder) # Create log entry as dict and append it to event list logEntry = { diff --git a/Software/chamlog.py b/Software/chamlog.py index 5bece7a..d12e3d3 100755 --- a/Software/chamlog.py +++ b/Software/chamlog.py @@ -11,6 +11,7 @@ import json import Chameleon import io import datetime +from Chameleon.ISO14443 import CardTypesMap def verboseLog(text): formatString = "[{}] {}" @@ -48,7 +49,7 @@ def main(): argParser.add_argument("-t", "--type", choices=outputTypes.keys(), default='text', help="specifies output type") - argParser.add_argument("-d", "--decode", dest="decode", action='store_true', default=False) + argParser.add_argument("-d", "--decode", dest="decode", choices=CardTypesMap.keys(), default=None, help="Decode the sniffed traffic and application data with a decoder") argParser.add_argument("-l", "--live", dest="live", action='store_true', help="Use live logging capabilities of Chameleon") argParser.add_argument("-c", "--clear", dest="clear", action='store_true', help="Clear Chameleon's log memory when using -p") argParser.add_argument("-m", "--mode", dest="mode", metavar="LOGMODE", help="Additionally set Chameleon's log mode after reading it's memory") From 336a32d1e7aa3528497a4ff74d713605f262750f Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 3 Aug 2018 18:42:31 +0100 Subject: [PATCH 45/50] Add a parameter for setting logmode in chamtool (cherry picked from commit 4fb21fa) --- Software/chamtool.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Software/chamtool.py b/Software/chamtool.py index 0e964ee..8d7febc 100755 --- a/Software/chamtool.py +++ b/Software/chamtool.py @@ -68,6 +68,17 @@ def cmdLog(chameleon, arg): bytesReceived = chameleon.cmdDownloadLog(fileHandle) return "{} Bytes successfully written to {}".format(bytesReceived, arg) +def cmdLogMode(chameleon, arg): + result = chameleon.cmdLogMode(arg) + + if (arg is None): + return "Current logmode is: {}".format(result['response']) + else: + if (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "logmode have been set to {}".format(arg) + else: + return "Setting logmode failed: {}".format(arg, result['statusText']) + def cmdLButton(chameleon, arg): result = chameleon.cmdLButton(arg) @@ -129,7 +140,7 @@ def cmdThreshold(chameleon, arg): if (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): return "Threshold have been set to {}".format(arg) else: - return "Setting threshold faled: {}".format(arg, result['statusText']) + return "Setting threshold failed: {}".format(arg, result['statusText']) def cmdUpgrade(chameleon, arg): result = chameleon.cmdUpgrade() @@ -164,6 +175,7 @@ def main(): cmdArgGroup.add_argument("-s", "--setting", dest="setting", action=CmdListAction, nargs='?', type=int, choices=Chameleon.VALID_SETTINGS, help="retrieve or set the current setting") cmdArgGroup.add_argument("-U", "--uid", dest="uid", action=CmdListAction, nargs='?', help="retrieve or set the current UID") cmdArgGroup.add_argument("-c", "--config", dest="config", action=CmdListAction, metavar="CFGNAME", nargs='?', help="retrieve or set the current configuration") + cmdArgGroup.add_argument("-lm", "--logmode", dest="logmode", action=CmdListAction, metavar="LOGMODE", nargs='?', help="retrieve or set the current log mode") cmdArgGroup.add_argument("-lb", "--lbutton", dest="lbutton", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current left button action") cmdArgGroup.add_argument("-rb", "--rbutton", dest="rbutton", action=CmdListAction, metavar="ACTION", nargs='?', help="retrieve or set the current right button action") cmdArgGroup.add_argument("-gl", "--gled", dest="gled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current green led function") @@ -192,6 +204,7 @@ def main(): "upload" : cmdUpload, "download" : cmdDownload, "log" : cmdLog, + "logmode" : cmdLogMode, "lbutton" : cmdLButton, "rbutton" : cmdRButton, "gled" : cmdGreenLED, From 070ed1556b990ff9101c95959ffd5dbb8f0cba3f Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 5 Aug 2018 03:04:45 +0100 Subject: [PATCH 46/50] Fix bug(lengthCheck,decodeAPPIDs) (cherry picked from commit d6ea321) --- Software/Chameleon/Log.py | 2 +- Software/Chameleon/MFDESFire.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index da32bc8..524ecab 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -138,7 +138,7 @@ def parseBinary(binaryStream, decoder=None): note = "" # If we need to decode the data and paritybit check success - if (decoder!=None and logData[-1] != '!'): + if (decoder!=None and len(logData) >0 and logData[-1] != '!'): # Decode the data from Reader if(event == 0x44 or event == 0x45): note = iso14443_3.parseReader(binascii.a2b_hex(logData), decoder) diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py index f66eee6..8237970 100644 --- a/Software/Chameleon/MFDESFire.py +++ b/Software/Chameleon/MFDESFire.py @@ -65,7 +65,7 @@ def decodeRespGetAPPID (data): dataLen = len(data) for i in range (0,int((dataLen-1)/3)): - note += "0x"+hexlify(data[3*i: 3*(i+1)]).decode()+"|" + note += "0x"+hexlify(data[1+3*i: 1+3*(i+1)]).decode()+"|" return note ############################## @@ -368,4 +368,4 @@ def MFDESFireDecode(data, source): else: note += MFDESFireCMDTypes[lastCMD]["RespDecoder"](data) - return note \ No newline at end of file + return note From 9e89f1935301c8eb28e20e55acc2bf05f15f414c Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 5 Aug 2018 03:22:26 +0100 Subject: [PATCH 47/50] Fix bug: number of returnd FileIDs (cherry picked from commit e1761af) --- Software/Chameleon/MFDESFire.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py index 8237970..41186c5 100644 --- a/Software/Chameleon/MFDESFire.py +++ b/Software/Chameleon/MFDESFire.py @@ -194,7 +194,7 @@ def decodeData(data): # Application Level Commands ########################### def decodeRespGetFileIDs(data): - if len(data) == 4: + if len(data) > 0: return "FIDs:0x"+hexlify(data[1:]).decode() else: return strFail From 2be9b9e76ea01d357683d86fbd5965cfebb62ab5 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 8 Aug 2018 23:32:14 +0100 Subject: [PATCH 48/50] Fix chamtool: upgrade command gives exception (cherry picked from commit 592b851) --- Software/Chameleon/Device.py | 5 ++++- Software/chamtool.py | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Software/Chameleon/Device.py b/Software/Chameleon/Device.py index 1852cf0..bfe2267 100644 --- a/Software/Chameleon/Device.py +++ b/Software/Chameleon/Device.py @@ -251,4 +251,7 @@ class Device: return self.getSetCmd(self.COMMAND_THRESHOLD, value) def cmdUpgrade(self): - return self.execCmd(self.COMMAND_UPGRADE) \ No newline at end of file + # Execute command + cmdLine = self.COMMAND_UPGRADE + self.LINE_ENDING + self.serial.write(cmdLine.encode('ascii')) + return 0 diff --git a/Software/chamtool.py b/Software/chamtool.py index 8d7febc..aff659c 100755 --- a/Software/chamtool.py +++ b/Software/chamtool.py @@ -143,8 +143,10 @@ def cmdThreshold(chameleon, arg): return "Setting threshold failed: {}".format(arg, result['statusText']) def cmdUpgrade(chameleon, arg): - result = chameleon.cmdUpgrade() - return "" + if(chameleon.cmdUpgrade() == 0): + print ("Device changed into Upgrade Mode") + exit(0) + # Custom class for argparse class CmdListAction(argparse.Action): def __init__(self, option_strings, dest, default=False, required=False, From 2af62ab8f8ed2c29e8cb2cce029a25dfbaffe3e4 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 19 Aug 2018 15:32:59 +0100 Subject: [PATCH 49/50] Add decode additional frame for readdata command --- Software/Chameleon/MFDESFire.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Software/Chameleon/MFDESFire.py b/Software/Chameleon/MFDESFire.py index 41186c5..07577ef 100644 --- a/Software/Chameleon/MFDESFire.py +++ b/Software/Chameleon/MFDESFire.py @@ -327,6 +327,7 @@ MFDESFireCMDTypes = { # Commands need to use additional frame MFDESFireAFCMD = { + 0xBD : {"name": "ReadData ", "AFReaderDecoder": decodeDummy, "AFCardDecoder": decodeData}, 0xAA : {"name": "AuthAES ", "AFReaderDecoder":decodeAuthAESAF, "AFCardDecoder": decodeCardAuthAESAF}, 0x0A : {"name": "Auth3DES ", "AFReaderDecoder":decodeAuth3DESAF, "AFCardDecoder": decodeCardAuth3DESAF}, From e8500b5db7539ea05cb113dfc9941db6f7f8826e Mon Sep 17 00:00:00 2001 From: Georg Date: Wed, 12 Sep 2018 14:55:36 +0200 Subject: [PATCH 50/50] added LATEST firmware --- .../Chameleon-Mini/Latest/Chameleon-Mini.eep | 2 +- .../Chameleon-Mini/Latest/Chameleon-Mini.hex | 5658 +++++++++-------- 2 files changed, 2927 insertions(+), 2733 deletions(-) diff --git a/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.eep b/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.eep index a43b2b0..9b80dbb 100644 --- a/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.eep +++ b/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.eep @@ -1,4 +1,4 @@ -:100000000000B32E0606080800000401320090012B +:100000000000402F0606080800000401320090019D :1000100006060808000004013200900106060808E0 :1000200000000401320090010606080800000401E7 :100030003200900106060808000004013200900119 diff --git a/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.hex b/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.hex index d24c39d..05d727f 100644 --- a/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.hex +++ b/Firmware/Chameleon-Mini/Latest/Chameleon-Mini.hex @@ -1,25 +1,25 @@ :100000000C94AB0B0C94D00B0C94D00B0C94D00B29 :100010000C94D00B0C94D00B0C94D00B0C94D00BF4 -:100020000C94D00B0C94D00B0C94420D0C94D00B70 +:100020000C94D00B0C94D00B0C94470D0C94D00B6B :100030000C94D00B0C94D00B0C94D00B0C94D00BD4 :100040000C94D00B0C94D00B0C94D00B0C94D00BC4 :100050000C94D00B0C94D00B0C94D00B0C94D00BB4 :100060000C94D00B0C94D00B0C94D00B0C94D00BA4 :100070000C94D00B0C94D00B0C94D00B0C94D00B94 -:100080000C94D00B0C94D00B0C9417240C94D00B24 +:100080000C94D00B0C94D00B0C942B240C94992C26 :100090000C94D00B0C94D00B0C94D00B0C94D00B74 :1000A0000C94D00B0C94D00B0C94D00B0C94D00B64 -:1000B0000C94D00B0C94D00B0C94D00B0C94E62425 -:1000C0000C94D00B0C9460280C94D00B0C94D00B97 +:1000B0000C94D00B0C94D00B0C94D00B0C94FA2411 +:1000C0000C94D00B0C947E280C94072E0C94D00B1F :1000D0000C94D00B0C94D00B0C94D00B0C94D00B34 :1000E0000C94D00B0C94D00B0C94D00B0C94D00B24 :1000F0000C94D00B0C94D00B0C94D00B0C94D00B14 :100100000C94D00B0C94D00B0C94D00B0C94D00B03 -:100110000C94D00B0C943B280C94D00B0C94D00B6B +:100110000C94E02D0C9459280C94D00B0C94D00B1B :100120000C94D00B0C94D00B0C94D00B0C94D00BE3 -:100130000C94D00B0C94D00B0C94D00B0C944F243B -:100140000C94090C0C9456270C94D00B0C94D00BE7 -:100150000C94D00B0C94B2270C94D00B0C94D00BB5 +:100130000C94D00B0C94D00B0C94D00B0C94632427 +:100140000C94090C0C9474270C94C52C0C94D00BB3 +:100150000C94D00B0C94D0270C94D82E0C94D00B6C :100160000C94D00B0C94D00B0C94D00B0C94D00BA3 :100170000C94D00B0C94D00B0C94D00B0C94D00B93 :100180000C94D00B0C94D00B0C94D00B0C94D00B83 @@ -29,7 +29,7 @@ :1001C0000C94D00B0C94D00B0C94D00B0C94D00B43 :1001D0000C94D00B0C94D00B0C94D00B0C94D00B33 :1001E0000C94D00B0C94D00B0C94D00B0C94D00B23 -:1001F0000C94D00B0C941B530C94D00B6364696E5D +:1001F0000C94D00B0C942D590C94D00B6364696E45 :100200006F70737578585B001E03430068006100CF :100210006D0065006C0065006F006E002D004D00E4 :1002200069006E00690000002A034B006100730042 @@ -40,22 +40,22 @@ :100270002402060524060001070582030800FF0981 :10028000040100020A00000007050402100005072F :100290000583021000051201100102000008D016AB -:1002A000B20401000102DC01F20DF30DF40DF50DB5 -:1002B000F60DF70DEC0DED0DF10DF00D0000000148 -:1002C000A72517263626C62CE22CE62CEC0DE72CAB -:1002D0000530183040000700A72517263626DA2CEF -:1002E000E22CE62CEC0DE72C05301830500007000E -:1002F000A72517263626DE2CE22CE62CEC0DE72C63 -:1003000005301830A4000700A725172636265830D8 -:1003100094309830EC0D99307A3796370004040009 -:10032000A72517263626673094309830EC0D993083 -:100330007A37963700040700A72517263626763029 -:1003400094309830EC0D99307A37963700100400CD -:10035000A72517263626853094309830EC0D993035 -:100360007A37963700100700A72517263626F50D91 -:10037000F60DF70DEC0DED0DF10DF00D0000000187 -:10038000C7264427FC287146744681468246214987 -:10039000F10DF00D00000000004E4F4E4500000032 +:1002A000B20401000102DC01F70DF80DF90DFA0DA1 +:1002B000FB0DFC0DF10DF20DF60DF50D000000012A +:1002C000BB2530264F268431A031A431F10DA53154 +:1002D000C334D63440000700BB2530264F26983162 +:1002E000A031A431F10DA531C334D634500007003C +:1002F000BB2530264F269C31A031A431F10DA5310C +:10030000C334D634A4000700BB2530264F2616354B +:1003100052355635F10D5735383C543C0004040035 +:10032000BB2530264F26253552355635F10D57352C +:10033000383C543C00040700BB2530264F2634359A +:1003400052355635F10D5735383C543C00100400F9 +:10035000BB2530264F26433552355635F10D5735DE +:10036000383C543C00100700922F4B306C30EA525E +:10037000F852FD52FE520053F60DF50D000000013B +:10038000E02662271A292F4B324B3F4B404BDF4D63 +:10039000F60DF50D00000000004E4F4E4500000028 :1003A000000000000000000000000000000000004D :1003B000000000000000000000014D465F554C5455 :1003C00052414C4947485400000000000000000022 @@ -186,8 +186,8 @@ :100B900070733A2F2F6769746875622E636F6D2FBB :100BA000656D7365632F4368616D656C656F6E4D30 :100BB000696E6920636F6D6D69742025530031384B -:100BC000303232380031353131313500352E342E66 -:100BD000300037616238643362000D0A000D0A008C +:100BC000303931320031353131313500352E342E66 +:100BD000300031303134346631000D0A000D0A0026 :100BE0000D0A000D0A000D0A000D0A0064313030B4 :100BF0003A4F4B0000000000000000000000000021 :100C0000000000000000000000000000006531301E @@ -208,64 +208,64 @@ :100CF00000000000CB3230333A54494D454F555433 :100D000000000000000000000000000000000000E3 :100D1000000000000056455253494F4E00000000AD -:100D20000000000000000000000000E119434F4EE9 +:100D20000000000000000000000000E619434F4EE4 :100D300046494700000000000000000000000000DD -:100D400000091A031A554944000000000000000081 -:100D50000000000000000000006A1A2B1A524541F2 +:100D4000000E1A081A554944000000000000000077 +:100D50000000000000000000006F1A301A524541E8 :100D6000444F4E4C590000000000000000000000FD -:100D700000C81ABC1A55504C4F41440000000000F6 -:100D80000000000000F51A000000000000444F576A -:100D90004E4C4F41440000000000000000FA1A00D1 +:100D700000CD1AC11A55504C4F41440000000000EC +:100D80000000000000FA1A000000000000444F5765 +:100D90004E4C4F41440000000000000000FF1A00CC :100DA00000000000005245534554000000000000C0 -:100DB0000000000000FF1A0000000000005550472E -:100DC000524144450000000000000000000A1B00E2 +:100DB0000000000000041B00000000000055504728 +:100DC000524144450000000000000000000F1B00DD :100DD00000000000004D454D53495A4500000000F9 -:100DE0000000000000000000000000151B554944F1 +:100DE00000000000000000000000001A1B554944EC :100DF00053495A45000000000000000000000000B8 -:100E00000000002D1B52425554544F4E000000006C -:100E10000000000000000000004A1B431B52425526 +:100E0000000000321B52425554544F4E0000000067 +:100E10000000000000000000004F1B481B5242551C :100E200054544F4E5F4C4F4E4700000000000000EE -:100E300000661B5F1B4C425554544F4E000000008F -:100E4000000000000000000000821B7B1B4C42558C +:100E3000006B1B641B4C425554544F4E0000000085 +:100E4000000000000000000000871B801B4C425582 :100E500054544F4E5F4C4F4E4700000000000000BE -:100E6000009E1B971B4C4544475245454E000000D1 -:100E7000000000000000000000BA1BB31B4C4544FA +:100E600000A31B9C1B4C4544475245454E000000C7 +:100E7000000000000000000000BF1BB81B4C4544F0 :100E80005245440000000000000000000000000087 -:100E900000D61BCF1B4C4F474D4F44450000000070 -:100EA000000000000000000000F01BEB1B4C4F474F +:100E900000DB1BD41B4C4F474D4F44450000000066 +:100EA000000000000000000000F51BF01B4C4F4745 :100EB0004D454D0000000000000000000000000053 -:100EC000000000051C4C4F47444F574E4C4F4144C7 -:100ED00000000000002A1C0000000000004C4F47EA -:100EE00053544F524500000000000000002F1C002A +:100EC0000000000A1C4C4F47444F574E4C4F4144C2 +:100ED00000000000002F1C0000000000004C4F47E5 +:100EE00053544F52450000000000000000341C0025 :100EF00000000000004C4F47434C454152000000A9 -:100F00000000000000321C000000000000534554A7 +:100F00000000000000371C000000000000534554A2 :100F100054494E470000000000000000000000009F -:100F2000003A1C351C434C454152000000000000B3 -:100F30000000000000421C00000000000053544F5D -:100F400052450000000000000000000000461C00A8 +:100F2000003F1C3A1C434C454152000000000000A9 +:100F30000000000000471C00000000000053544F58 +:100F4000524500000000000000000000004B1C00A3 :100F50000000000000524543414C4C0000000000DE -:100F600000000000004A1C0000000000004348414F +:100F600000000000004F1C0000000000004348414A :100F70005247494E470000000000000000000000FA -:100F80000000004E1C48454C5000000000000000CE -:100F90000000000000561C000000000000525353E7 +:100F8000000000531C48454C5000000000000000C9 +:100F900000000000005B1C000000000000525353E2 :100FA00049000000000000000000000000000000F8 -:100FB000000000921C5359535449434B0000000059 -:100FC0000000000000000000000000C51C53454E5A -:100FD000445F524157000000000000000000006B19 +:100FB000000000971C5359535449434B0000000054 +:100FC0000000000000000000000000CA1C53454E55 +:100FD000445F524157000000000000000000007014 :100FE0001D0000000053454E4400000000000000BA -:100FF00000000000000000E11C0000000047455414 -:1010000055494400000000000000000000271E00B9 +:100FF00000000000000000E61C000000004745540F +:10100000554944000000000000000000002C1E00B4 :10101000000000000044554D505F4D465500000053 -:1010200000000000000A1E000000000000494445C6 -:101030004E544946590000000000000000441E00C4 +:1010200000000000000F1E000000000000494445C1 +:101030004E544946590000000000000000491E00BF :10104000000000000054494D454F55540000000079 -:10105000000000000000000000811E611E54485284 +:10105000000000000000000000861E661E5448527A :101060004553484F4C4400000000000000000000C1 -:1010700000EE1ED41E4155544F43414C494252414B -:101080005445000000811F00000000000046494553 +:1010700000F31ED91E4155544F43414C4942524141 +:101080005445000000861F0000000000004649454E :101090004C440000000000000000000000000000C0 -:1010A00000431F6D1F434C4F4E45000000000000E1 -:1010B00000000000009E1F00000000000000000073 +:1010A00000481F721F434C4F4E45000000000000D7 +:1010B0000000000000B21F0000000000000000005F :1010C0000000000000000000000000000000000020 :1010D000000000000053414B3A09005549443A09C9 :1010E00000415451413A09005468657265206973A2 @@ -373,10 +373,10 @@ :101740000000000000000000000000000000000099 :1017500000000000000011241FBECFEFCDBFDFE36B :10176000DEBF00E00CBF18BE19BE1ABE1BBE14E2DD -:10177000A0E0B0E2E6E8FAEB00E00BBF02C00790A1 -:101780000D92A235B107D9F71BBE25E3A2E5B4E25D -:1017900001C01D92A03AB207E1F77ED00C94415DE2 -:1017A00068C13BB78BBFFB01879196913BBF089502 +:10177000A0E0B0E2EAEAF6EC00E00BBF02C007909E +:101780000D92AA35B107D9F71BBE27E3AAE5B4E24B +:1017900001C01D92AD32B207E1F77ED00C945363C5 +:1017A0006DC13BB78BBFFB01879196913BBF0895FD :1017B0003BB78BBFCB0142E20D94F00F3BB70B015F :1017C00043E20D94F00F3BB78BBFCB0145E20D9484 :1017D000F00F3BB746E208C02091CF0127FDFCCFB8 @@ -388,2671 +388,2865 @@ :1018300035B124B1569578F400928C0800920008D6 :1018400006E10A95F1F700C001E00093000803E00B :1018500000938C0804C00AE10A95F1F700002150BA -:10186000304019F40E94A0270CC04F5F477011F45C +:10186000304019F40E94BE270CC04F5F477011F43E :10187000519102C000C000C00AE00A95F1F700C013 :10188000D9CFFF91EF910F910FBF5F914F913F9192 -:101890002F910F910F9018950ED10E9406170E945C -:1018A000A217A8D21092520684E08093420682E6E4 +:101890002F910F910F90189513D10E940B170E9452 +:1018A000A717ADD21092520684E08093420682E6DA :1018B00080938601C1E0C0932606C093210686E08E -:1018C00080932206C093310602E000933206109204 -:1018D0002A0613E01093290689E5809380018AE5A2 -:1018E0008093810180E48093410680934606909125 -:1018F000B200907F9093B2009091B200926090936A -:10190000B20090E390934106909346068093500670 -:10191000C0934606009345061093410683E18093E9 -:10192000010821E030E02093260830932708209317 -:1019300028083093290810928C0880938008109210 -:10194000230310922103D8E0D093220381E18093F6 -:101950002003E091B12EF091B22E82859385809381 -:101960003803909339038CE380938203D0938003F0 -:1019700080938303D093810366D10E944419B7D129 -:1019800017D7C09300021092010200930202109335 -:101990000402C0932002D09321020E94991517D10E -:1019A000D2E0C1E18091030481FF25C08091010450 -:1019B00080FDFCCFD09303040E94A617AED10E94F5 -:1019C0007719FED60E940117E091A22EF091A32E66 -:1019D00019950E948C220E94E318E091B12EF0919B -:1019E000B22E8781813011F4C0935B2C86818130C7 -:1019F00011F4C0935A2C0E9448199CD7E091A02E54 -:101A0000F091A12E1995E0919A2EF0919B2E1995A7 -:101A1000C9CF292F33272230310559F02330310522 -:101A200069F021303105E9F482E190E026E932E005 -:101A30001CC08EE390E028E532E017C09927813082 -:101A4000910549F028F0029761F4E8E0F2E005C062 -:101A5000E4E5F2E002C0E8E2F2E0849190E09F0168 -:101A600004C080E090E020E030E0FA012083318380 -:101A700008951F920F920FB60F92112408B60F927D -:101A800018BEFFCF1F920F920FB60F92112408B607 -:101A90000F9218BE8F939F938EB19FB180589F4F26 -:101AA0008EB99FB99F918F910F9008BE0F900FBE76 -:101AB0000F901F9018958091780083FF0AC088E0EE -:101AC0008093780088ED84BF81E0809380000D943E -:101AD000FE008BEC809352008091500088608093D0 -:101AE00050008091510083FFFCCF82EC8093550021 -:101AF000809150008061809350008091510084FF5C -:101B0000FCCF88ED84BF84E0809340001EB81FB8EE -:101B100081E0809343002FE730E020930A04309364 -:101B20000B0420930C0430930D04809300048093E5 -:101B3000020480E880930001089588ED84BF81E06D -:101B400080937900089588ED84BF8BE180938000B5 -:101B500008958091500082608093500080915100E0 -:101B600081FFFCCF82E08093CA01EDE1F0E0E491D7 -:101B7000E0936200ECE1F0E0E491E0936300109206 -:101B8000CA0180E8809365008BEB809366008091AA -:101B90005600897F80935600809156008460809320 -:101BA0005600809160008160809360000895E0E4B9 -:101BB000F0E084818E7F8483E0E6F0E080818E7F98 -:101BC0008083E0E5F0E080818D7F8083089587E069 -:101BD0008093A20078940895089580E090E008959D -:101BE000089508950895089508950895089508950D -:101BF0000F931F93CF93C82F06E91EE2D8011296C8 -:101C0000ED91FC91139719950E94C422E091B12E99 -:101C1000F091B22EC583B8E1CB9FB0011124685575 -:101C20007D4F48E150E0C8010E940456D801ED9173 -:101C3000FC911995D8011696ED91FC911797CF91CB -:101C40001F910F91199448E150E068EA72E086E92B -:101C50009EE20E940456E091B12EF091B22E858151 -:101C6000C7CF0F931F93E091B12EF091B22E8B014D -:101C70009C0145816AE088E993E00E947F181F91EA -:101C80000F910895FF920F931F93CF93DF931F92AD -:101C9000CDB7DEB78C019E012F5F3F4FAC016AE0EC -:101CA00088E993E00E949718F82E882389F08981AB -:101CB0009FDFF80140E08191882319F04F5F4F3199 -:101CC000D1F7E091AE2EF091AF2EB80181E11995D8 -:101CD0008F2D0F90DF91CF911F910F91FF9008955D -:101CE0009B01AC016AE088E993E00C94BE1808956A -:101CF0000C94F65508950F931F93CF938C01C62F24 -:101D0000CC2339F00E94F655F80181938F01C15020 -:101D1000F7CFCF911F910F9108950E94F6550E9421 -:101D2000F6550E94F6550C94F655CF93DF93EC01CF -:101D300061507109DA01420F531FFC01CF018C1B66 -:101D40009D0BA417B50721F41082DF91CF91089560 -:101D500062307105C8F39D91392F32953F703A304A -:101D600010F4305D01C0395C30839F709A3010F4FC -:101D7000905D01C0995C9183329662507109DECF0B -:101D8000CF93DF93EC01DA0120E030E05C91552342 -:101D900051F111969C911197992339F12617370724 -:101DA00011F180ED850F8A3020F08FEB850F8630A2 -:101DB000E0F480ED890F8A3020F04FEB490F463078 -:101DC000A0F4E52FF0E0513408F0F797E295E07FBA -:101DD000913410F4982F01C097539E2B99932F5F45 -:101DE0003F4F1296D3CFC90102C080E090E0DF914F -:101DF000CF910895E0E6F6E080E1858382E0868376 -:101E000088E085838AE18183E0EAF9E0168217821F -:101E100080EC858388E18483E0E0F1E0128A8BE640 -:101E2000838B148A158A20EA208F99E0918F128E75 -:101E3000148E158E168E84E0808B12A23CE633A39E -:101E400014A215A210A611A612A624A795A716A63D -:101E500080A308954115510509F449C020E120935C -:101E6000660623E02093A0092091A10927FFFCCF5B -:101E70002091A0097093A0092091A10927FFFCCF10 -:101E80002091A0096093A0092091A10927FFFCCF10 -:101E90002091A00921E02093120180931C019093CE -:101EA0001D0140931401509315011092220182E507 -:101EB00094E2809328019093290140932401509348 -:101EC000250180911001806880931001809120018C -:101ED0008068809320018091100187FDFCCF80E312 -:101EE000809311018093210180E18093650608951C -:101EF0004115510509F469C020E12093660626E0EA -:101F00002093A0092091A10927FFFCCF2091A009CF -:101F100020E120936506000000002093660622E081 -:101F20002093A0092091A10927FFFCCF2091A009AF -:101F30007093A0092091A10927FFFCCF2091A0094F -:101F40006093A0092091A10927FFFCCF2091A0094F -:101F50001092120122E534E220931C0130931D01FE -:101F6000409314015093150120E1209322018093A6 -:101F700028019093290140932401509325018091D9 -:101F80001001806880931001809120018068809307 -:101F900020018091100187FDFCCF80E38093110127 -:101FA0008093210180E180936506E091B12EF0914C -:101FB000B22E8781863019F481E180935B2C868173 -:101FC000863019F481E180935A2C0895CF92DF92E4 -:101FD000EF92FF92CF93DF93C090B02ED12CE12CE3 -:101FE000F12C8DE0CC0CDD1CEE1CFF1C8A95D1F78A -:101FF000C114D10481E0E806F10408F04EC080E18C -:102000008093660686E08093A0098091A10987FFEE -:10201000FCCF8091A00980E180936506000000005C -:102020008093660682E08093A0098091A10987FFD2 -:10203000FCCF8091A0091092A0098091A10987FF8F -:10204000FCCF8091A0091092A0098091A10987FF7F -:10205000FCCF8FEFE81AF80A8091A009C0E0D0E128 -:10206000C701B6019EDB8093A0098091A10987FF7B -:10207000FCCF8091A0099093A0098091A10987FFCE -:10208000FCCF8091A00982E0C80ED11CE11CF11C9C -:10209000219731F780E1809365068091010480FDEE -:1020A000FCCF82E080930304DF91CF91FF90EF900B -:1020B000DF90CF900895CF92DF92EF92FF92CF936F -:1020C000DF93C090B02ED12CE12CF12C8DE0CC0C04 -:1020D000DD1CEE1CFF1C8A95D1F7C114D10481E0F0 -:1020E000E806F10438F0DF91CF91FF90EF90DF9098 -:1020F000CF906CCF8FEFE81AF80AC1E2D0E02197B9 -:1021000091F36ADBC701B60153DB66DB8FEFD81AA8 -:10211000E80AF80AF4CFCF92DF92EF92FF920F9382 -:102120001F93CF93DF93C090B02ED12CE12CF12CD4 -:102130008DE0CC0CDD1CEE1CFF1C8A95D1F7C11480 -:10214000D10481E0E806F10408F04FC080E18093FB -:10215000660683E08093A0098091A10987FFFCCFE8 -:102160008091A0091092A0098091A10987FFFCCF5E -:102170008091A0091092A0098091A10987FFFCCF4E -:102180008FEFE81AF80A8091A00901E210E00150EF -:10219000110941F121DB1DDB1FDBC0E0D0E0109213 -:1021A000A0098091A10987FFFCCF6091A00970E090 -:1021B0001092A0098091A10987FFFCCF8091A0090E -:1021C000782BCE01FBDA08DB2296C11581E0D80717 -:1021D00031F7C701B601F7DAFFDA8FEFD81AE80A4C -:1021E000F80AD5CF80E180936506E091B12EF09199 -:1021F000B22E8781863019F490E190935B2C968102 -:10220000963049F420E120935A2C853059F483E12B -:1022100080935B2C02C08530D1F3953019F483E1B3 -:1022200080935A2C8091010480FDFCCF82E0809342 -:102230000304DF91CF911F910F91FF90EF90DF90FA -:10224000CF900895CF92DF92EF92FF920F931F935A -:102250004115E0E25E076105710508F06BC0690198 -:10226000E12CF12C00E010E220E030E0041B150B23 -:10227000260B370BC016D106E206F30610F49701C1 -:10228000860120E12093660626E02093A009209194 -:10229000A10927FFFCCF2091A00920E1209365062A -:1022A000000000002093660622E02093A009209100 -:1022B000A10927FFFCCF2091A0095093A0092091EC -:1022C000A10927FFFCCF2091A0094093A0092091EC -:1022D000A10927FFFCCF2091A0091092120122E54D -:1022E00034E220931C0130931D01009314011093DC -:1022F000150120E120932201809328019093290168 -:10230000009324011093250180911001806880932F -:10231000100180912001806880932001809110013C -:1023200087FDFCCF80E3809311018093210180E140 -:102330008093650681E01F910F91FF90EF90DF90F1 -:10234000CF900895CF92DF92EF92FF920F931F9359 -:102350004115E0E25E076105710508F05DC06901A5 -:10236000E12CF12C00E010E220E030E0041B150B22 -:10237000260B370BC016D106E206F30610F49701C0 -:10238000860120E12093660623E02093A009209196 -:10239000A10927FFFCCF2091A0095093A00920910B -:1023A000A10927FFFCCF2091A0094093A00920910B -:1023B000A10927FFFCCF2091A00921E02093120161 -:1023C00080931C0190931D0100931401109315013B -:1023D0001092220182E594E28093280190932901D2 -:1023E000009324011093250180911001806880934F -:1023F000100180912001806880932001809110015C -:1024000087FDFCCF80E3809311018093210180E15F -:102410008093650681E001C080E01F910F91FF90DD -:10242000EF90DF90CF9008958091CF0187FDFCCF92 -:102430000895FADF8091CF0181FF0BC086E380937E -:10244000CA01EBECF1E021E030E088ED90E084BFE0 -:1024500020830895EF92FF920F931F93CF93DF9302 -:10246000EC017B018A011092C201DEDFD701CE01AF -:10247000800F911F26E048ED50E061E070E0EBEC4A -:10248000F1E0C817D90779F0C093C0013D2F3F7123 -:102490003093C1012093CA0144BF60833091C401CD -:1024A0003D932196EECFC801DF91CF911F910F91FF -:1024B000FF90EF9008953F924F925F926F927F92BC -:1024C0008F929F92AF92BF92CF92DF92EF92FF9244 -:1024D0000F931F93CF93DF938B01542E652E282FDC -:1024E0002F71722EEC01C21BD109A3DF9DDF83E3A4 -:1024F0008093CA011092C1011092C2017801052D8A -:10250000162D85E3482E98EDC92ED12C882483946E -:10251000912C3BECA32EBB24B39443E3342E011542 -:10252000110501F17092C001F70181917F01809343 -:10253000C4010150110921F07394F0E27F12EFCF32 -:10254000C093C0018D2F8F718093C1014092CA0149 -:10255000C601F50184BF8082A09666DF3092CA0171 -:10256000712CDDCF852D962DDF91CF911F910F918D -:10257000FF90EF90DF90CF90BF90AF909F908F90A3 -:102580007F906F905F904F903F9008951F93CF93EF -:10259000DF93CDB7DEB7A097CDBFDEBF863009F49D -:1025A000EAC0D0F4833009F46AC028F4813059F1CC -:1025B0008230C9F1F6C0843009F486C0853009F054 -:1025C000F0C0E091A62EF091A72ECE0101961995AC -:1025D0008091AC2E41E0A4C0893009F4D0C040F411 -:1025E000873009F4CAC0883009F0DBC0EFDCD9C0FD -:1025F0008A3009F4D5C08B3009F0D3C08EEA93E25B -:102600000E94C221CEC010E08091AC2E181708F0B5 -:102610009FC06EDBE1E0F0E0EC0FFD1FE10FF11D6C -:1026200080831F5FF1CF11E08091AC2E873009F0DD -:1026300010E0E091A62EF091A72ECE0101961995FB -:102640004091AC2E31E0141708F082C03323A9F07A -:10265000812F90E0E1E0F0E0EC0FFD1FE80FF91FA3 -:10266000208131E02F3F09F030E0E1E0F0E0EC0FB5 -:10267000FD1FE80FF91F2F5F20831F5FE4CFE0915C -:10268000A62EF091A72ECE01019619958091AC2E21 -:1026900041E0815008F45CC04423D9F3282F30E096 -:1026A000E1E0F0E0EC0FFD1FE20FF31F908141E04D -:1026B0009F3F09F040E0E1E0F0E0EC0FFD1FE20F8A -:1026C000F31F9F5F9083E5CF11E08091AC2E8730A0 -:1026D00009F010E0E091A62EF091A72ECE01019610 -:1026E00019954091AC2E31E0141790F53323A1F0E9 -:1026F000812F90E0E1E0F0E0EC0FFD1FE80FF91F03 -:10270000208131E0211130E0E1E0F0E0EC0FFD1F2D -:10271000E80FF91F215020831F5FE6CF411103C04E -:102720008150E0F715C0282F30E0E1E0F0E0EC0F39 -:10273000FD1FE20FF31F908141E0911140E0E1E0C5 -:10274000F0E0EC0FFD1FE20FF31F91509083E8CFF4 -:10275000E091A82EF091A92ECE0101961995E09155 -:10276000AE2EF091AF2E4091AC2EBE016F5F7F4F29 -:1027700083E1199516C0B0D314C0CDDC12C080918E -:102780000008813021F490918C08933009F080E0AA -:1027900080FD03C00E944E2304C00E94742301C028 -:1027A000AAD2A096CDBFDEBFDF91CF911F91089531 -:1027B000E0E0F6E080E6828388E1868B858B0895F1 -:1027C000CF93C0910806C095C6FF12C080915424D3 -:1027D0008A3050F08A30E1F4E091B12EF091B22EBF -:1027E0008181D4DE809154248F5F8093542410C063 -:1027F0008C2F807669F48091542481508A3030F493 -:10280000E091B12EF091B22E8081C0DE109254245E -:10281000C5FF12C0809153248A3050F08A30D9F419 -:10282000E091B12EF091B22E8381B0DE80915324DD -:102830008F5F809353240FC0C07669F48091532436 -:1028400081508A3030F4E091B12EF091B22E828125 -:102850009DDE10925324CF9108959B01AC016CE052 -:1028600082EE96E08BC4E82FF0E0E055F14D88E071 -:10287000638381503C968111FBCF08950F931F9382 -:102880009B01E091B12EF091B22EE80FF11D8A016B -:1028900040816CE082EE96E032D41F910F91089552 -:1028A0000F931F93CF93DF931F92CDB7DEB7082FFF -:1028B000AB019E012F5F3F4F6CE082EE96E037D474 -:1028C000182F882319F06981802FCDDF812F0F9079 -:1028D000DF91CF911F910F9108950895EF92FF928C -:1028E0000F931F93CF937B01C42F0EB11FB1209183 -:1028F000080430910904022B132B682F83E090E227 -:102900000E9406546C2F83E090E20E940654612FCF -:1029100083E090E20E940654602F83E090E20E94E0 -:1029200006546C2F70E0C701CF911F910F91FF905B -:10293000EF90A4C408953F924F925F926F927F925E -:102940008F929F92AF92BF92CF92DF92EF92FF92BF -:102950000F931F93CF93DF937C01E901C090002078 -:10296000D0900120960122503843C901A0E0B0E088 -:10297000481759076A077B0708F05FC0E2E0CE1AE4 -:10298000E0E4DE0A2A013B014C0E5D1E611C711C55 -:10299000481659066A067B0648F0241B350B8E0143 -:1029A000021B130BE9013324339403C000E010E051 -:1029B000312C4601A12CB12C481559056A057B051F -:1029C00010F5CA018E5F9F4B2A013B014C0E5D1E24 -:1029D000611C711C481459046A047B0428F4AE017C -:1029E000BC01C70137DA18C0C41AD50AA601BC0158 -:1029F000C70130DAAE014C195D096AE574E2C7011E -:102A00008C0D9D1D07C04C195D09BA01665A7B4D9E -:102A1000AE01C7010E943256332041F00C0F1D1F3A -:102A2000F701E00FF11FCE0DDF1D02C081E006C0EF -:102A3000EC17FD07D9F31292FBCF80E0DF91CF9125 -:102A40001F910F91FF90EF90DF90CF90BF90AF90CC -:102A50009F908F907F906F905F904F903F900895E0 -:102A6000209156243091572480E098E0821B930BEC -:102A7000EAE5F4E29F012A5534422817390710F499 -:102A80001192F8CF8AE594E28093582490935924C8 -:102A900080E098E0809356249093572482E090E45D -:102AA000809300209093012042E050E060E070E4C9 -:102AB00080E090E21DDAE091B12EF091B22E878194 -:102AC0008A3019F480E180935B2C86818A3019F476 -:102AD00080E180935A2C0895809156249091572438 -:102AE00090582091002030910120821B930B089573 -:102AF000E0EBFEE287833C969FE2E031F907D1F7F5 -:102B0000813049F018F0823059F008951092552420 -:102B10008DE694E109C08093552484EF95E104C0CB -:102B2000109255248EE694E18093AE2E9093AF2EB2 -:102B300008950F931F93CF93DF931F92CDB7DEB706 -:102B4000E091B12EF091B22E8481D2DF8AE594E239 -:102B5000809358249093592400E018E00093562461 -:102B60001093572441E050E0BE016F5F7F4F80E03B -:102B700090E070DCE0915824F0915924DF01C80105 -:102B80001D920197E9F78981882341F042E050E0E6 -:102B900060E070E480E090E25DD917C082E090E4EC -:102BA000809300209093012042E050E060E070E4C8 -:102BB00080E090E29DD981E0898341E050E0BE0150 -:102BC0006F5F7F4F80E090E076DCE091AE2EF09179 -:102BD000AF2E40E060E070E08FEF19950F90DF912D -:102BE000CF911F910F9108950F931F93CF93DF9370 -:102BF000CEB1DFB1A0910804B09109042091562410 -:102C000030915724E42FF0E08F010C5F1F4F201705 -:102C1000310758F1CA2BDB2B245031092E1B3F0BF7 -:102C20002093562430935724A0915824B0915924CE -:102C30008C9311964C9311971296DC931297CD01B9 -:102C4000049680935824909359241396CC93DB01D7 -:102C5000EC01415018F02D912993FBCFE80FF91F9B -:102C6000E0935824F093592412C080E041DFE091B2 -:102C7000B12EF091B22E87818A3019F481E18093D0 -:102C80005B2C86818A3019F481E180935A2CDF9184 -:102C9000CF911F910F9108951F93CF93DF931F92B0 -:102CA000CDB7DEB79E012F5F3F4FAC0163E08EE6EC -:102CB00098E03DD2182F882311F0898119DF812FE8 -:102CC0000F90DF91CF911F9108950F931F93E09183 -:102CD000B12EF091B22E8B019C01448163E08EE60F -:102CE00098E00DD21F910F9108959B01AC0163E014 -:102CF0008EE698E043C20F931F93CF93DF938091AA -:102D0000562490915724811528E0920708F074C04A -:102D10006091002070910120C0E0D0E8C61BD70B65 -:102D200000E018E0A801481B590BC417D50758F15B -:102D30008AE594E2DDD82091562430915724809181 -:102D4000002090910120985F821B930B80930020BC -:102D500090930120021B130BEAE5F4E2CF018A55A0 -:102D600094428017910710F41192F8CF8AE594E20B -:102D7000809358249093592480E098E080935624BF -:102D8000909357242EC02097B9F1AE018AE594E2C2 -:102D9000AFD8A8014C1B5D0BBE01665A7B4D8AE57E -:102DA00094E20E943B5680915824909159248C1BA8 -:102DB0009D0B809358249093592480915624909190 -:102DC00057248C0F9D1F80935624909357248091F5 -:102DD000002090910120C80FD91FC0930020D093EC -:102DE000012042E050E060E070E480E090E2DF919A -:102DF000CF911F910F917CC8DF91CF911F910F91BF -:102E0000089580915524811176CF089543E650E0CE -:102E100060EB7EE281E090E01DCB43E650E060EBAA -:102E20007EE281E090E047CB0F931F93CF93DF9337 -:102E3000CFEFC80FC83008F047C0D82F0E94C42277 -:102E40008091B02EC81779F166D9C093B02E8CE06E -:102E5000C89F90011124C9018D54914D8093B12ECA -:102E60009093B22EF901E055F14D80850E94F80D46 -:102E7000E091B12EF091B22E84813ADEA7D801E024 -:102E800010E0005B1E426091B02EC8018055914D4C -:102E90000E94D35C6091B12E7091B22EC8018F5404 -:102EA000914D0E94DC5C8FE18D0FE091B12EF0918D -:102EB000B22E9781943011F480935B2C96819430DC -:102EC00029F480935A2C02C080E001C081E0DF9198 -:102ED000CF911F910F9108958091B02E99E04CE011 -:102EE000915099F0282F30E02F5F3F4F2770332704 -:102EF000822F429FF001439FF00D1124E055F14DC8 -:102F00002085222369F38F5F8FCF0895FC01909174 -:102F1000B02E9F5C908311820895CF93FC01218194 -:102F200021110DC0BC01C081E091AE2EF091AF2EF9 -:102F300041E082E1199580ED8C0FCF9175CF80E053 -:102F4000CF91089588E180930106089580915A2CCD -:102F5000823191F030F48031B9F050F48823A9F136 -:102F600032C0833169F090EE980F983088F02BC012 -:102F700088E08093050627C088E08093070623C079 -:102F80008091040683FF12C088E0809306061BC070 -:102F900090915C2C9F5F913019F090935C2C15C040 -:102FA00010925C2C9091040693FD04C088E08093FD -:102FB00005060BC098E090930606803221F0815000 -:102FC00080935A2C02C010925A2C80915B2C823133 -:102FD00091F030F48031C1F050F48823A9F132C06F -:102FE000833169F090EE980F983088F02BC080E123 -:102FF0008093050627C080E18093070623C0809157 -:10300000040684FF12C080E1809306061BC09091E5 -:103010005D2C9F5F913019F090935D2C0895109274 -:103020005D2C9091040694FD04C080E18093050618 -:10303000089590E190930606803221F081508093AC -:103040005B2C089510925B2C08959B01AC016BE002 -:1030500081ED98E093C0E0EBFEE298E0282F20712C -:103060008870211162878111618791503C9691117E -:10307000F8CF222329F090E19093060610925B2C62 -:10308000882329F088E08093060610925A2C089530 -:103090000F931F939B018A01803131F4E091B12E8F -:1030A000F091B22E478107C0883049F4E091B12EEB -:1030B000F091B22E46816BE081ED98E020D01F9117 -:1030C0000F9108950F931F93CF93DF931F92CDB766 -:1030D000DEB7082FAB019E012F5F3F4F6BE081ED04 -:1030E00098E025D0182F882319F06981802FB3DF4D -:1030F000812F0F90DF91CF911F910F9108950F9322 -:103100001F93FC01662379F094916150941309C0D8 -:10311000BF016F5F7F4FA801C9010E94165681E071 -:1031200003C0B196EFCF80E01F910F910895CF9229 -:10313000DF92EF92FF921F93CF93DF93EC017A011E -:103140006901162F112389F0BE016F5F7F4FC70100 -:103150000E940D561150892B31F4FE01C491F601E5 -:10316000C08381E003C0A196EDCF80E0DF91CF91D5 -:103170001F91FF90EF90DF90CF900895CF9301962D -:10318000CCE26623D1F0FC01DA01AD017491772322 -:1031900041F021153105A9F07D9331962150310977 -:1031A000F4CF623038F02115310559F0FD01C083AC -:1031B0004F5F5F4F61508196E4CF232B11F0FA01EE -:1031C0001082CF9108958091200280688093200220 -:1031D0008091230280FFFCCF81E080932302A091A5 -:1031E0001002B0911102AE5BB109B7FF02C0A0E0BE -:1031F000B0E020E038EB4BE050E00E949055E091C9 -:10320000B12EF091B22E843F9140A8F4878187308F -:1032100019F480E180935B2C8681873019F480E17A -:1032200080935A2C8091AC2E882389F0E0919E2EB9 -:10323000F0919F2E19948781873019F481E1809352 -:103240005B2C8681873019F481E180935A2C089594 -:10325000BC0183E090E20C94B853CF93DF93FC0160 -:103260006491EC012196662331F083E090E20E94A4 -:103270000654CE01F4CFDF91CF910895AB01BC018C -:1032800083E090E20C94E25380E28093620608951A -:10329000CF93DF9380915E2C823031F583E090E212 -:1032A0000E946F540E944D4F83E090E20E948B5425 -:1032B000EC0197FD19C0E091B12EF091B22E8781FB -:1032C000833019F483E180935B2C8681833019F479 -:1032D00083E180935A2C8C2F79D6811105C08C2FD5 -:1032E000DF91CF910C94E221DF91CF9108958091ED -:1032F0005E2C813079F028F08230C9F0833011F1F2 -:103300002EC08091680685FF31C08FE08093022037 -:1033100081E015C0809102208150809302208111AC -:1033200025C00E94A90D0E94E55282E008C080914C -:10333000680685FD18C08FE08093022083E08093AB -:103340005E2C0DC08091022081508093022081115B -:103350000DC00E94AA520E94D70D10925E2C80913F -:103360005E2C823019F481D70C948C220895E09160 -:10337000B12EF091B22E8781823019F481E18093D1 -:103380005B2C8681823019F481E180935A2C089558 -:10339000E091B12EF091B22E8781823019F480E154 -:1033A00080935B2C8681823019F480E180935A2CC3 -:1033B000089583E090E20C94935383E090E20C94A0 -:1033C000DE5422ED3BE03F932F932CEC3BE03F9308 -:1033D0002F9325EC3BE03F932F932EEB3BE03F9365 -:1033E0002F932EE13BE03F932F9322E02F931F92E8 -:1033F0009F938F930E949B568DB79EB70E968DBF5D -:103400009EBF85E6089560E072E00E94310E85E679 -:103410000895FB0120812F3349F42181211106C039 -:1034200060E072E00E94700E85E60895CB010E9474 -:10343000420E882371F0E091B12EF091B22ECF01AF -:103440008B5A9E4265818F5F9F4F0E94D35C84E6BA -:1034500008958AEC0895EF92FF920F931F93CF93F4 -:10346000DF93CDB7DEB7A097CDBFDEBF7C01009163 -:10347000AC2E10E00115110591F486E19BE09F93BD -:103480008F9382E08F931F92FF92EF920E949B5640 -:103490000F900F900F900F900F900F9010C0E09131 -:1034A000A62EF091A72ECE01019619959801AE0196 -:1034B0004F5F5F4F60E072E0C7010E94950E85E6A6 -:1034C000A096CDBFDEBFDF91CF911F910F91FF90EE -:1034D000EF900895DF92EF92FF920F931F93CF9397 -:1034E000DF93CDB7DEB7A097CDBFDEBF7B010091E4 -:1034F000AC2E10E06FE07BE0C7010E940D56892BD7 -:1035000029F5D12CED2CF12CE016F10658F40E948F -:10351000780EE1E0F0E0EC0FFD1FEE0DFF1D808363 -:10352000D394F0CFE091A82EF091A92ECE01019670 -:103530001995E091AE2EF091AF2E4091AC2EBE01C8 -:103540006F5F7F4F83E1199584E60BC0A70160E2AE -:1035500070E0CE0101960E94C00E0817190711F302 -:103560008AECA096CDBFDEBFDF91CF911F910F9166 -:10357000FF90EF90DF900895FC018091AD2E88239D -:1035800011F081E301C080E38083118285E6089514 -:10359000FB012181211127C02081213321F481E009 -:1035A0008093AD2E04C0203321F41092AD2E84E61A -:1035B00008952F33C1F41F9220E32F931F9221E32C -:1035C0002F9329E03BE03F932F9322E02F931F920C -:1035D0009F938F930E949B568DB79EB70A968DBF7F -:1035E0009EBF85E608958AEC089582E291E1BDD4FC -:1035F0008EE6089582EA91E1D3D48EE60895E0EC58 -:10360000F4E081818E7F81830E94AA520E949D0DE9 -:1036100084E60895E0ECF4E081818E7F81830E944E -:10362000AA520E94A30D84E60895E6E9FEE22589E8 -:103630002F9324892F9326E03BE03F932F9322E0A2 -:103640002F931F929F938F930E949B568DB79EB787 -:1036500008968DBF9EBF85E608952091AC2E1F92DF -:103660002F9323E03BE03F932F9322E02F931F9271 -:103670009F938F930E949B568DB79EB708968DBFE0 -:103680009EBF85E6089540E052E0BC0180E0F6D898 -:1036900085E60895FB0120812F3341F4218121111A -:1036A00005C060E072E0D9D885E6089580E0F8D8DA -:1036B000882319F0B2DB84E608958AEC089540E08F -:1036C00052E0BC0181E0DAD885E60895FB01208153 -:1036D0002F3341F42181211105C060E072E0BDD893 -:1036E00085E6089581E0DCD8882319F096DB84E62E -:1036F00008958AEC089540E052E0BC0182E0BED813 -:1037000085E60895FB0120812F3341F421812111A9 -:1037100005C060E072E0A1D885E6089582E0C0D8D7 -:10372000882319F07ADB84E608958AEC089540E056 -:1037300052E0BC0183E0A2D885E60895FB01208118 -:103740002F3341F42181211105C060E072E085D85A -:1037500085E6089583E0A4D8882319F05EDB84E62B -:1037600008958AEC089540E052E0BC0180E190DCCD -:1037700085E60895FB0120812F3341F42181211139 -:1037800005C060E072E061DC85E6089580E19ADCC6 -:10379000882319F042DB84E608958AEC089540E01E -:1037A00052E0BC0188E074DC85E60895FB012081CD -:1037B0002F3341F42181211105C060E072E045DC26 -:1037C00085E6089588E07EDC882319F026DB84E610 -:1037D00008958AEC089560E072E077DA85E608954E -:1037E000FB0120812F3341F42181211105C060E0CC -:1037F00072E07BDA85E60895CB014EDA882319F072 -:103800000CDB84E608958AEC0895CF93DF93EC01F6 -:1038100063D9813028E0920718F09C01385002C02B -:1038200020E030E03F932F939F938F9383EE9AE0B5 -:103830009F938F9382E08F931F92DF93CF930E9489 -:103840009B568DB79EB70A968DBF9EBF85E6DF91CA -:10385000CF9108958BE994E1A3D38EE608954BDAD6 -:1038600084E60895FDD884E6089560E072E04EDBBA -:1038700085E60895CB0151DB811102C08AEC0895E1 -:1038800084E608950E945B1084E608950E948B10E0 -:1038900084E608950E94E60F84E608958091680604 -:1038A00080FD02C089E7089588E70895DF92EF92CE -:1038B000FF920F931F93CF93DF93EC010FEF11E073 -:1038C00085E1E82E8DE0F82E9CE2D92EB70185EC3B -:1038D00093E20E940D56892BD1F001151105B9F024 -:1038E000DE01F7012491ED012196C8010197222301 -:1038F00041F00130110529F02C93DE0131968C0145 -:10390000F1CFDC928C0188E1E80EF11CDFCF21972A -:10391000188285E6DF91CF911F910F91FF90EF9074 -:10392000DF900895FC01809120028068809320023E -:103930008091230280FFFCCF81E080932302A0913D -:103940001002B0911102AE5BB109B7FF02C0A0E056 -:10395000B0E020E038EB4BE050E00E949055AA2701 -:10396000BB279F938F938CED9AE09F938F9382E078 -:103970008F931F92FF93EF930E949B568DB79EB734 -:1039800008968DBF9EBF85E608954EB15FB1209128 -:10399000080430910904242B352B3F932F9326EDF7 -:1039A0003AE03F932F9322E02F931F929F938F93A0 -:1039B0000E949B568DB79EB708968DBF9EBF85E629 -:1039C00008950F931F93CF93DF931F921F92CDB74C -:1039D000DEB78B01E091B12EF091B22E8581893056 -:1039E00009F06FC0E0919E2EF0919F2E199581E015 -:1039F0008093B82C60E270E0C8010E945356009793 -:103A0000F9F4F80101900020E9F73197E01BF10B80 -:103A1000E0FD59C0F695E795E130F10539F487E00E -:103A200090E08093942E9093952E37C053E0EE0F44 -:103A3000FF1F5A95E1F7E093942EF093952E2DC039 -:103A400098012C5F3F4F82179307E9F5A80162E0C8 -:103A500070E0CE0101960E94C00E898190E0982FFF -:103A600088272A81820F911D8093942E9093952E02 -:103A70000B5F1F4FF80101900020E9F73197E01B21 -:103A8000F10BE0FD20C0F695E79533E0EE0FFF1F48 -:103A90003A95E1F7E817F907B0F06091942E70912C -:103AA000952E695F7F4F83E0769567958A95E1F75C -:103AB000A80184E99DE20E94C00E0E94072C8FEFAE -:103AC00003C089EC01C08AEC0F900F90DF91CF9179 -:103AD0001F910F910895EF92FF920F931F93CF9331 -:103AE000DF931F921F92CDB7DEB78B01E091B12E0D -:103AF000F091B22E8581893009F080C0E0919E2E30 -:103B0000F0919F2E199582E08093B82C60E270E0CE -:103B1000C8010E9453567C01892B31F5F8010190B0 -:103B20000020E9F73197E01BF10BE0FD69C0F69545 -:103B3000E795E130F10539F487E090E08093942E29 -:103B40009093952E47C053E0EE0FFF1F5A95E1F773 -:103B5000CF0169E070E00E947C55E81BF90BE0930F -:103B6000942EF093952E36C0C8010496E816F906F7 -:103B700009F046C0A80162E070E0CE0101960E9403 -:103B8000C00E898190E0982F88272A81820F911D8D -:103B90008093942E9093952E8730910529F09C0167 -:103BA00027703327232B61F587010F5F1F4FF80123 -:103BB00001900020E9F73197E01BF10BE0FD20C0F8 -:103BC000F695E79533E0EE0FFF1F3A95E1F7E8171A -:103BD000F907B0F06091942E7091952E695F7F4F38 -:103BE00083E0769567958A95E1F7A80184E99DE2DF -:103BF0000E94C00E0E94072C8FEF03C089EC01C009 -:103C00008AEC0F900F90DF91CF911F910F91FF9051 -:103C1000EF900895E091B12EF091B22E8581893018 -:103C2000A1F4E0919E2EF0919F2E199585E080934E -:103C3000B82C0E9471460E94072C8BE796E4809373 -:103C40006D2C90936E2C8FEF089589EC0895E09180 -:103C5000B12EF091B22E85818930A1F4E0919E2E93 -:103C6000F0919F2E199583E08093B82C0E947146A5 -:103C70000E94072C8BE796E480936D2C90936E2C1A -:103C80008FEF089589EC0895E091B12EF091B22E56 -:103C900085818930A1F4E0919E2EF0919F2E199597 -:103CA00086E08093B82C0E9471460E94072C8BE717 -:103CB00096E480936D2C90936E2C8FEF089589EC91 -:103CC0000895E091B12EF091B22E4085518564E6C1 -:103CD000649F9001659F300D11243F932F9320ED39 -:103CE0003AE03F932F9322E02F931F929F938F935D -:103CF0000E949B568DB79EB708968DBF9EBF85E6E6 -:103D00000895CF93DF931F921F92CDB7DEB7FB01CB -:103D100020812F33B1F42181211113C02EE93AE023 -:103D20003F932F9322E02F931F929F938F930E9494 -:103D30009B560F900F900F900F900F900F9085E66D -:103D40002EC089E592E089839A83CE0101969F93E4 -:103D50008F938AE99AE09F938F937F936F930E944A -:103D6000D1560F900F900F900F900F900F90892BBE -:103D7000A9F069817A816935F2E07F0778F4E091F2 -:103D8000B12EF091B22E60877187CF01885A9E4282 -:103D90008F5F9F4F0E94DC5C84E601C08AEC0F902D -:103DA0000F90DF91CF910895E091B12EF091B22E56 -:103DB00023852F9322852F9327E93AE03F932F9372 -:103DC00022E02F931F929F938F930E949B568DB753 -:103DD0009EB708968DBF9EBF85E60895CF93DF936B -:103DE0001F921F92CDB7DEB7FB0120812F33B1F4B4 -:103DF0002181211113C02FE02F932FEF2F9326E461 -:103E00003AE03F932F9322E02F931F929F938F933B -:103E10000E949B56CDBFDEBF85E630C019821A8254 -:103E2000CE0101969F938F9382E49AE09F938F93A4 -:103E30007F936F930E94D1560F900F900F900F9029 -:103E40000F900F90892BC9F069817A81611590E1FB -:103E5000790798F46093380370933903E091B12E99 -:103E6000F091B22E62877387CF01865A9E428F5F90 -:103E70009F4F0E94DC5C84E601C08AEC0F900F909B -:103E8000DF91CF910895FB0120812F33D9F4218157 -:103E9000211121C01F9220E32F931F9221E32F9322 -:103EA0002CE33AE03F932F9322E02F931F929F93AE -:103EB0008F930E949B568DB79EB70A968DBF9EBF6B -:103EC00085E60895213311F4E9D303C0203319F4B2 -:103ED0000BD484E608958AEC0895FC0180910008D3 -:103EE000813029F480918C0891E0833009F090E0D2 -:103EF00090FF02C081E301C080E38083118285E6E8 -:103F00000895E091B12EF091B22E85818930A1F40F -:103F1000E0919E2EF0919F2E199584E08093B82C0D -:103F20000E9471460E94072C8BE796E480936D2CCB -:103F300090936E2C8FEF089589EC089589E00E948C -:103F4000F80DE0919E2EF0919F2E199587E08093B9 -:103F5000B82C0E9471460E94072C8BE796E4809350 -:103F60006D2C90936E2C8FEF089521E020936C2C94 -:103F700020936B2C2CE32093692C25E030E02093D8 -:103F8000672C3093682C1092612C1092622C109246 -:103F9000632C1092642C80935F2C9093602C089576 -:103FA00027E020936C2C2CE231E02093672C309397 -:103FB000682C1092612C1092622C1092632C10923B -:103FC000642C80935F2C9093602C0895CF939091F4 -:103FD0006C2C953009F441C030F4933019F130F570 -:103FE000913068F43EC1973009F4AAC008F44AC081 -:103FF000983009F4ACC0993009F495C032C18130D1 -:1040000031F41092652C1092662C83E023C084302A -:1040100011F466E084C0883109F485C08B3109F061 -:1040200084C081C080936A2C84E014C090E04091E9 -:104030006A2C2FEF30E0241B31098217930721F4FB -:1040400085E008C0891779F165E183E090E20E947C -:10405000065482E080936C2C68C02091652C3091CE -:10406000662CA9014F5F5F4F4093652C5093662CDF -:10407000F901ED5EF04D80834038510509F055C0DF -:1040800086E0E8CF20916A2C90916B2C29134FC0C9 -:10409000E3E1FFE223E93FE290E02E173F0791F2D0 -:1040A0004191940FFACF4091612C5091622C609114 -:1040B000632C7091642CE0915F2CF091602C20E8CF -:1040C00030E083E19FE21995C82F882311F1809198 -:1040D0006B2C8F5F80936B2C8091612C9091622C64 -:1040E000A091632CB091642C80589F4FAF4FBF4F6D -:1040F0008093612C9093622CA093632CB093642CDA -:1041000066E083E090E20E94065482E080936C2C8B -:10411000A9C068E183E090E20E94065468E183E070 -:1041200090E20E94065410926C2CC1E09BC030E0DB -:10413000892F90E001972817390781F766E085CF2E -:10414000853119F410926B2C08C08B3161F38831E2 -:1041500009F45FCF863009F05AC080916B2C8F5FD5 -:1041600080936B2C4091612C5091622C6091632C58 -:104170007091642CE0915F2CF091602C20E830E08D -:1041800083E19FE21995C82F8823D1F161E083E094 -:1041900090E20E94065460916B2C83E090E20E94B2 -:1041A000065460916B2C609583E090E20E94065467 -:1041B00060E870E083E19FE261D8E3E1FFE260E064 -:1041C0008FE2E339F80719F08191680FF9CF83E0A6 -:1041D00090E20E9406548091612C9091622CA091F3 -:1041E000632CB091642C80589F4FAF4FBF4F80938A -:1041F000612C9093622CA093632CB093642C32C0FA -:1042000064E083E090E20E94065489E023CF853188 -:1042100009F08BCF61E083E090E20E940654609148 -:104220006B2C83E090E20E94065460916B2C6095A9 -:1042300083E090E20E94065460E870E083E19FE230 -:104240001DD8E3E1FFE283E99FE260E08E179F075C -:1042500019F02191620FFACF83E090E20E94065498 -:1042600064CFC0E08C2FCF91089580916C2C813069 -:1042700019F0873029F108958091672C9091682C6E -:104280009C01215031092093672C3093682C892B95 -:1042900031F58091692C9FEF980F9093692C8823BA -:1042A00031F065E183E090E20E94065402C0109272 -:1042B0006C2C85E090E08093672C9093682C089597 -:1042C0008091672C9091682C9C012150310920939A -:1042D000672C3093682C892B11F410926C2C089564 -:1042E000ECEEFBE020E030E09491981309C041E24D -:1042F000429FC001439F900D11248351944F089514 -:104300002F5F3F4FB1962930310571F780E090E083 -:104310000895262FBA012F3311F4469607C02D3386 -:1043200011F4449611C021110CC04096FC01259156 -:1043300034912115310521F183E19FE2F9011995AD -:104340000DC02032E9F44296FC01259134912115EB -:104350003105B1F083E19FE2F90119958F3F89F4AE -:1043600091E09093712C4EB15FB12091080430918F -:104370000904242B352B20936F2C3093702C089537 -:1043800089EC08950F931F93CF93DF938C01C5E1C0 -:10439000DDE0BE01C8010E940D56892B49F440E0C2 -:1043A00050E060E0CE01DF91CF911F910F91B1CF2E -:1043B000689680E1C53DD80761F7DF91CF911F91E5 -:1043C0000F910895EF92FF921F93CF93DF93982F51 -:1043D0009F7D91549A3160F090ED980F9A3040F0A3 -:1043E0008F3531F0982F9D7F9D3311F08032D1F4BD -:1043F0009FE9980F9A3108F480522091722C3091E5 -:10440000732C2F3F91E0390708F07FC0A9014F5F5F -:104410005F4F4093722C5093732CF901ED5EF04D79 -:10442000808373C08D3009F040C0E091722CF09110 -:10443000732CED5EF04D10821092722C1092732C42 -:104440008091712C811161C08091132F982F9F7DD5 -:1044500009F440C08D7F8D33E9F1E3E1FFE27F0194 -:104460001191112331F01F3321F01D3311F010325F -:10447000B1F7F7011082C5E1DDE0BE0183E19FE203 -:104480000E940D56892B59F41092132FA7014F5FEC -:104490005F4F612FCE013DDF8F3FB9F124C0689699 -:1044A000F0E1C53DDF0749F715C0883061F4809120 -:1044B000722C9091732C009741F101978093722C8C -:1044C0009093732C22C08B3101F51092722C1092B4 -:1044D000732C1BC088EC04DF0E942D1989EE9BE031 -:1044E0000E942D1912C0FCDE0E942D1989EE9BE05E -:1044F0000E942D198091132F882339F083E19FE2C8 -:104500000E94281986EE9BE0EBCF81E0DF91CF91EE -:104510001F91FF90EF9008958091712C882399F15D -:10452000E091B12EF091B22E208531852115310513 -:1045300051F14EB15FB18091080490910904842B30 -:10454000952B40916F2C5091702C841B950B64E639 -:1045500070E00E947C5562177307A8F01092712CCE -:104560008BECBEDE0E942D1983EE9BE00E942D197C -:10457000E0916D2CF0916E2C309729F019951092E6 -:104580006D2C10926E2C08958091712C8823A9F0C7 -:104590001092712C8BECA4DE0E942D1983EE9BE00F -:1045A0000E942D19E0916D2CF0916E2C309729F01E -:1045B000199510926D2C10926E2C0895CF93DF9365 -:1045C0009091712C9923A9F0EB011092712C88DE47 -:1045D0000E942D1980EE9BE00E942D19209749F032 -:1045E000CE010E9428198DED9BE0DF91CF910C94B4 -:1045F0002D19DF91CF910895EF92FF920F931F93A2 -:10460000CF937C019B01613081E0780710F020E0BE -:1046100031E08B01021B130BA70160E072E083E124 -:104620009FE20E94950E83E19FE20E942819C1E05B -:10463000013081E01807A8F01A954C2F50E0542F54 -:1046400044274E0D5F1D20E032E060E072E083E120 -:104650009FE20E94950E83E19FE20E942819CF5F9E -:10466000E7CF0115110589F04C2F50E0542F442756 -:104670004E0D5F1D980160E072E083E19FE20E94B1 -:10468000950E83E19FE20E9428198AED9BE0CF916D -:104690001F910F91FF90EF900C942D1980910008BD -:1046A000813021F490918C08933009F080E080FDF6 -:1046B0001AC08091762C811116C081E08093000889 -:1046C00093E090938C088093742C1092752C2EB1EB -:1046D0003FB18091080490910904822B932B809321 -:1046E0007B2C90937C2C089510928C0810920008DB -:1046F000E4E7FCE21082118208959091742C9923D2 -:10470000F1F08091752C811115C02091742C222319 -:10471000B9F04EB15FB12091080430910904242B07 -:10472000352B40917B2C50917C2C241B350B26344F -:10473000310530F081E08093752C892F089581E058 -:104740000895CF93C091762CCC23C1F02EB13FB108 -:104750008091080490910904822B932B2091792C4D -:1047600030917A2C821B930B2091772C3091782CEE -:104770008217930718F01092762C90DF8C2FCF9130 -:104780000895E091B12EF091B22E828793878093A5 -:104790003803909339030895E091B12EF091B22E31 -:1047A0008285938540968287938780933803909380 -:1047B0003903828593850895E091B12EF091B22E50 -:1047C00080E991E08287938780933803909339033F -:1047D0000895A0E2B6E081E015968C93159723E149 -:1047E00031E328B939B923E931E32AB93BB910B823 -:1047F00013B812B816B817B811B8E0E0F9E010A273 -:1048000011A22FEF30E026A337A32FEF3FEF20A711 -:1048100031A7808388E8838380E1848783E087836E -:104820001C968C931C9782E01A968C9308951F9285 -:104830000F920FB60F92112408B60F9218BE0BB646 -:104840000F921BBE8F939F93EF93FF93E0E0F9E0ED -:1048500013828FE790E086AB97AB81E190E080AF69 -:1048600091AFE0E0FAE010A211A28FEF9FEF86A3D4 -:1048700097A389E88383168281E084878EE0808312 -:1048800010922A06FF91EF919F918F910F900BBE8E -:104890000F9008BE0F900FBE0F901F9018951F929B -:1048A0000F920FB60F92112408B60F9218BE0BB6D6 -:1048B0000F921BBE2F933F938F939F93EF93FF9382 -:1048C0002091280693B1267081E009F080E0990FCD -:1048D000892B83B982B1882309F463C012B883B1EC -:1048E0008770873059F51092000980E180930C0998 -:1048F0001092030A1B9B03C08CEA94E002C08CE672 -:1049000094E08093260A9093270A82E081B981E09F -:1049100080930C0A83E08093060A86B197B1877072 -:1049200049F090B18F5F893011F09695FBCFE8B1D7 -:10493000F9B1908381E080937D2C36C083B1982FAC -:104940009C7091F1847091B191111CC020B1269599 -:10495000882311F080E001C080E8282B20B986B1BF -:1049600097B1019686B997B987709927892BE1F499 -:10497000E8B1F9B1CF01019688B999B9208381E0F6 -:1049800081B912C091B1913079F4EAB1FBB19F01C4 -:104990002F5F3F4F2AB93BB9811190E0908311B846 -:1049A00003C082B1809582B988E880930309FF91A2 -:1049B000EF919F918F913F912F910F900BBE0F9090 -:1049C00008BE0F900FBE0F901F9018951F920F9268 -:1049D0000FB60F92112408B60F9218BE0BB60F92A5 -:1049E0001BBE2F933F938F939F93EF93FF9381B1C0 -:1049F000823008F49DC081B18D3008F099C0E1B1DA -:104A0000F0E0EE0FFF1FEC5DFF4D0190F081E02D17 -:104A100019948FE790E08093260A9093270A88C024 -:104A20008E9A8EE0809340088FE390E08093260A70 -:104A30009093270A85E06FC08E9886E081B98FEF4A -:104A400082B914B815B8E8B1F9B1808180B970C0E5 -:104A5000009B05C08E9A82B1809582B901C08E9864 -:104A600087E059C0009B02C08E9801C08E9A80B129 -:104A7000869580B984B195B1019684B995B984B110 -:104A800095B187709927892B11F488E044C024B12F -:104A900035B186B197B128173907B1F52BC0EAB106 -:104AA000FBB1309711F0808101C082B1882311F0F1 -:104AB0008E9A01C08E9889E02EC0EAB1FBB1309782 -:104AC00051F08081882311F08E9801C08E9A319622 -:104AD000EAB9FBB908C082B1882311F08E9801C0F1 -:104AE0008E9A8FEF82B924B135B186B197B128176C -:104AF000390711F48AE00FC0E8B1F9B1CF0101968E -:104B000088B999B9818180B986E005C08E988BE01B -:104B100002C08E988CE081B90BC01092000A1092EE -:104B2000060A109240081092410881E080937E2C82 -:104B3000FF91EF919F918F913F912F910F900BBE1D -:104B40000F9008BE0F900FBE0F901F901895CF9337 -:104B5000DF93EDE7FCE210821182E0E4F6E0128AD6 -:104B600084E08283C0E8D1E082E68E83A0E2B6E0F2 -:104B700081E016968C93169711968C93119796E078 -:104B800012969C93129751968C93519742E05296AD -:104B90004C9352971A961C921A9733E019963C93AD -:104BA00099E598839AE5998390E491839683A0EBA5 -:104BB000B0E012962C911297207F12962C931297A8 -:104BC00012962C911297226012962C9320E3218347 -:104BD0002683908B868345833183E0E0F8E083E190 -:104BE000818321E030E026A337A320A731A7E0E8A6 -:104BF000F8E014868083E0E2F3E01382118288E01B -:104C0000828391E19083A091B12EB091B22E1A9639 -:104C10002D913C911B97208F318FE0E8F3E09CE3CE -:104C20009283808393838183DF91CF91D2CDA0E261 -:104C3000B6E01A961C921A97EDE7FCE210821182F8 -:104C4000E0E0F9E010821382178280E18487E0E0DF -:104C5000FAE010821382168281E08487E0E4F8E0B3 -:104C60001082118216968C938E980895CF93DF93BD -:104C700080917D2C882309F47EC010927D2CC6B1D2 -:104C8000D7B1C730D10508F471C0AE01495F5F4F9D -:104C900093E0569547959A95E1F7E091AE2EF09105 -:104CA000AF2E63E171E380E41995E091B12EF091AC -:104CB000B22E8781883019F483E180935B2C868142 -:104CC000883019F483E180935A2CE091A42EF0915E -:104CD000A52EBE0183E191E31995EC0194FF06C076 -:104CE000DF7E83E991E38AB99BB902C01AB81BB889 -:104CF0002097E1F1AE01495F5F4F83E056954795FC -:104D00008A95E1F7E091AE2EF091AF2E63E171E369 -:104D100081E41995E091B12EF091B22E878189300E -:104D200019F483E180935B2C8681893019F483E147 -:104D300080935A2CC6B9D7B983E191E388B999B960 -:104D400010926008109261088FE090E080936608EE -:104D50009093670888E090E080936A0890936B08CE -:104D600083E28093410883E081B905C01092000A74 -:104D70001092060A2EDD80917E2C882329F0109255 -:104D80007E2CDF91CF9125CDDF91CF910895CF93E8 -:104D9000DF93E0E4F6E0128A84E08283C0E8D1E0A9 -:104DA00082E68E83A0E2B6E081E016968C93169799 -:104DB00011968C93119796E012969C9312975196A8 -:104DC0008C93519742E052964C9352971A961C92AC -:104DD0001A9733E019963C93199799E598839AE5C9 -:104DE000998390E491839683C0EBD0E02A81207F61 -:104DF0002A832A8122602A8320E321832683908BC1 -:104E0000868345833183E0E0F8E093E1918321E0FC -:104E100030E026A337A320A731A7E0E8F8E0148606 -:104E20009083E0E2F3E01382118298E0928321E123 -:104E30002083C091B12ED091B22E2A853B85208F40 -:104E4000318FE0E8F3E02CE3228390832383918386 -:104E500015968C93E0E0F9E02FEF30E026A337A31E -:104E600012A613A614A615A6108216821782808396 -:104E70001092000A10927F2CE2E8FCE2108212826B -:104E80001182DF91CF91089581E0809326062CDC7A -:104E9000E0E0F9E010821782E0E0FAE01082178289 -:104EA000E2E8FCE211821282108208951F920F92B2 -:104EB0000FB60F92112408B60F9218BE0BB60F92C0 -:104EC0001BBE2F933F938F939F93EF93FF93E0E04D -:104ED000F9E080E484871782E0E8F3E082E08783EA -:104EE00089EB818383E191E38AB99BB981E090E00A -:104EF00084B995B916B82EB13FB18091080490914C -:104F00000904822B932B8093802C9093812C81E039 -:104F10008093842C18B817B810927F2C88E0809367 -:104F20008706FF91EF919F918F913F912F910F9065 -:104F30000BBE0F9008BE0F900FBE0F901F901895DC -:104F4000E0E0F9E08FEF94E086A397A380E6848702 -:104F500080E387838FEF90E086AB97AB88E0809308 -:104F6000870608951F920F920FB60F92112408B66C -:104F70000F9218BE0BB60F921BBE2F933F934F9309 -:104F80005F938F939F93EF93FF931092070A109272 -:104F9000000A1092470910924009809181038E7F88 -:104FA0008093810384B195B180FF1AC0379B03C001 -:104FB00086B1869503C086B18695806886B984B12E -:104FC00095B1019684B995B987709927892B41F4D9 -:104FD000EAB1FBB1CF0101968AB99BB986B1808352 -:104FE00084B195B187709927892BC9F0E4B1F5B1E7 -:104FF00086B144B155B193E0F695E7959A95E1F7FE -:10500000ED5EFE4C90E04770552728E030E0241B11 -:10501000350B02C0959587952A95E2F7808381E04C -:105020008093832C1092842C8FEF9FEF8093260A1D -:105030009093270A1092200A1092210A1092060AD1 -:105040001092070A1092030A84E08093000A83E01A -:1050500080937F2CFF91EF919F918F915F914F9162 -:105060003F912F910F900BBE0F9008BE0F900FBE77 -:105070000F901F9018951F920F920FB60F92112448 -:1050800008B60F9218BE0BB60F921BBE8F93EF930C -:10509000FF93E0E8F3E081818F7C8183E0E0FAE038 -:1050A00088E8838381E08083FF91EF918F910F9057 -:1050B0000BBE0F9008BE0F900FBE0F901F9018955B -:1050C0001F920F920FB60F92112408B60F9218BEBE -:1050D0000BB60F921BBE8F939F93EF93FF9380911C -:1050E0006009109260091092610993E09093400961 -:1050F000813520F4813308F472C01BC08137E8F495 -:1051000084B195B180FF2EC086B18695806886B93E -:1051100084B195B1019684B995B987709927892B87 -:1051200041F4EAB1FBB1CF0101968AB99BB986B1CE -:10513000808386B1869580682CC086B1869580680C -:1051400086B984B195B1019684B995B987709927CC -:10515000892B41F4EAB1FBB1CF0101968AB99BB921 -:1051600086B1808386B18695806886B984B195B111 -:10517000019684B995B987709927892B41F4EAB1D2 -:10518000FBB1CF0101968AB99BB986B1808386B104 -:10519000869586B984B195B1019684B995B9877021 -:1051A0009927892B41F4EAB1FBB1CF0101968AB965 -:1051B0009BB986B1808386B1869586B984B195B155 -:1051C000019684B995B987709927892B41F4EAB182 -:1051D000FBB1CF0101968AB99BB986B18083FF915B -:1051E000EF919F918F910F900BBE0F9008BE0F9083 -:1051F0000FBE0F901F9018950F931F93CF93DF93BF -:10520000CDB7DEB7DA95CDBFDEBF8091842C882381 -:1052100009F483C04EB15FB18091080490910904F4 -:105220002091802C3091812C842B952B821B930B09 -:1052300020911E2030911F202F5F3F4F28173907E4 -:1052400008F06BC01092070A1092000A10924709EA -:1052500010924009809181038E7F8093810384B1F5 -:1052600095B180FF1AC0379B03C086B1869503C0F5 -:1052700086B18695806886B984B195B1019684B966 -:1052800095B987709927892B41F4EAB1FBB1CF0119 -:1052900001968AB99BB986B1808384B195B1877034 -:1052A0009927892BC9F0E4B1F5B186B144B155B164 -:1052B00013E0F695E7951A95E1F7ED5EFE4C90E068 -:1052C0004770552728E030E0241B350B02C0959528 -:1052D00087952A95E2F7808381E08093832C109252 -:1052E000842C2FEF3FEF2093260A3093270A109249 -:1052F000200A1092210A1092060A1092070A1092B0 -:10530000030A94E09093000A93E090937F2C14B8E2 -:1053100015B88093832C1092842C13DA81116FC2FC -:10532000ECD9882309F46BC28091842C811167C267 -:105330008091822C811105C08091832C882309F4EF -:105340005EC280917F2C833041F48091200A90913D -:10535000210A8532914008F452C28091832C88231F -:1053600009F4A2C084B195B1892B09F49DC084B120 -:1053700095B1089718F414B815B896C044B155B152 -:10538000495F5F4FB3E056954795BA95E1F763E102 -:1053900071E3CE0101960E94325683E191E38AB90E -:1053A0009BB944B155B114B815B8898186958695D5 -:1053B000898322E030E024173507B0F5F901A3E036 -:1053C000F695E795AA95E1F781E090E08C0F9D1F97 -:1053D000E80FF91F8081982F96959695908383709A -:1053E000813049F030F08230D1F486B18695806802 -:1053F00004C081E015C086B1869586B984B195B1A7 -:10540000019684B995B987709927892B41F4EAB13F -:10541000FBB1CF0101968AB99BB986B1808380E048 -:105420002E5F3F4F882339F284B195B18770992759 -:10543000892BC9F0E4B1F5B186B144B155B173E03F -:10544000F695E7957A95E1F7ED5EFE4C90E04770B2 -:10545000552728E030E0241B350B02C09595879531 -:105460002A95E2F78083E091B12EF091B22E8781E8 -:10547000883019F483E180935B2C8681883019F49D -:1054800083E180935A2C44B155B1495F5F4F63E08B -:10549000569547956A95E1F7E091AE2EF091AF2EC3 -:1054A00063E171E382E419951092822C1092832CAF -:1054B00064B175B1E091A42EF091A52E83E191E342 -:1054C000199584B995B984B195B1892B09F497C11F -:1054D00089E8809381031092000A1092200A1092AA -:1054E000210A2FEF3FEF2093260A3093270A8FE5FA -:1054F00090E08093280A9093290A1092060A80E18E -:1055000080930C0A93E09093070A1092600910921E -:105510006109209366093093670920EA30E02093FF -:105520006809309369091092460980934C0981E01B -:105530008093470981E18093800110928801109245 -:10554000800310922906E091B12EF091B22E87814E -:10555000893019F483E180935B2C8681893019F4BA -:1055600083E180935A2C44B155B1495F5F4F33E0DA -:10557000569547953A95E1F7E091AE2EF091AF2E12 -:1055800063E171E383E4199504B115B1013094E04E -:10559000190708F024C114B815B8A801495F5F4F76 -:1055A00023E0569547952A95E1F763E171E383E996 -:1055B00091E30E94325683E191E38AB99BB986B1A7 -:1055C0008695806886B984B195B1019684B995B9FC -:1055D00087709927892B39F484E191E38AB99BB9C3 -:1055E00086B18093133186B1869586B984B195B121 -:1055F000019684B995B987709927892B41F4EAB14E -:10560000FBB1CF0101968AB99BB986B1808380E056 -:1056100041E050E0E3E9F1E30417150708F495C011 -:10562000908190FF2BC086B1869586B984B195B1E3 -:10563000019684B995B987709927892B41F4AAB14D -:10564000BBB1CD0101968AB99BB986B18C9386B165 -:105650008695806886B984B195B1019684B995B96B -:1056600087709927892B09F063C0AAB1BBB1CD011E -:1056700001968AB99BB986B18C935AC0882351F19F -:1056800086B1869586B984B195B1019684B995B9EC -:1056900087709927892B41F4AAB1BBB1CD0101963E -:1056A0008AB99BB986B18C9386B1869586B984B147 -:1056B00095B1019684B995B987709927892B41F4E2 -:1056C000AAB1BBB1CD0101968AB99BB986B18C93C1 -:1056D00080E02FC096B19695906896B924B135B107 -:1056E0002F5F3F4F24B935B927703327232B49F457 -:1056F000AAB1BBB19D012F5F3F4F2AB93BB996B10B -:105700009C9396B1969596B924B135B12F5F3F4FD2 -:1057100024B935B927703327232BD1F6AAB1BBB1F1 -:105720009D012F5F3F4F2AB93BB996B19C9301C0B1 -:1057300081E09081969590839A0127703327232BDF -:1057400009F431964F5F5F4F67CF811129C086B151 -:105750008695806886B984B195B1019684B995B96A -:1057600087709927892B41F4EAB1FBB1CF010196EB -:105770008AB99BB986B1808386B1869586B984B192 -:1057800095B1019684B995B987709927892B41F411 -:10579000EAB1FBB1CF0101968AB99BB986B180838A -:1057A00084B195B187709927892BC9F0E4B1F5B11F -:1057B00086B144B155B193E0F695E7959A95E1F736 -:1057C000ED5EFE4C90E04770552728E030E0241B4A -:1057D000350B02C0959587952A95E2F7808381E085 -:1057E00080937F2C83E191E38AB99BB980E2809317 -:1057F0000C098CE08093070985E58A95F1F7D3952C -:10580000CDBFDEBFDF91CF911F910F91089514B8E6 -:1058100015B881E08093822C0C944E231092070AD5 -:105820001092000A1092470910924009809181035A -:105830008E7F8093810384B195B180FF1AC0379B1E -:1058400003C086B1869503C086B18695806886B907 -:1058500084B195B1019684B995B987709927892B40 -:1058600041F4EAB1FBB1CF0101968AB99BB986B187 -:10587000808384B195B187709927892BC9F0E4B1F1 -:10588000F5B186B144B155B193E0F695E7959A9597 -:10589000E1F7ED5EFE4C90E04770552728E030E0E0 -:1058A000241B350B02C0959587952A95E2F78083D6 -:1058B00081E08093832C1092842C8FEF9FEF809354 -:1058C000260A9093270A1092200A1092210A109219 -:1058D000060A1092070A1092030A84E08093000AD5 -:1058E00083E080937F2C10927F2C1092832C109257 -:1058F000822C0C947423982F80918D2C882359F03E -:105900008091872C811108C081E02091862C92170C -:1059100018F080E0089581E00895FF920F931F939F -:10592000CF93DF931F92CDB7DEB700918A2C000F83 -:10593000000F0051FF24F394F0928D2C10E0B80179 -:105940006D5F7F4F41E050E086E89CE20E942A0FA5 -:10595000B8016C5F7F4F41E050E0CE0101960E949C -:105960002A0F8981881F8827881F8093852CF092B1 -:105970008C2C10928B2C1092872C1092892C0F90CB -:10598000DF91CF911F910F91FF90089510928D2C70 -:1059900080E180938A2C8FEF8093862C1092852C47 -:1059A00081E080938C2C10928B2C1092872C10927B -:1059B000892C089584E180938A2CAFCF89E280936B -:1059C0008A2CABCF81E080938C2C089508958F9220 -:1059D0009F92AF92BF92CF92DF92EF92FF920F937E -:1059E0001F93CF93DF9300D01F92CDB7DEB78C010A -:1059F000FC01808190918C2C9230E1F028F0933062 -:105A000011F1943051F14EC0292F2095217020932F -:105A10008B2C992311F0863219F0823509F042C09F -:105A200084E4F8018083118282E080938C2C80E1F1 -:105A300090E0DBC290918B2C911102C08632B1F0C4 -:105A4000823599F513C090918B2C911102C086324A -:105A500069F0823509F05BC009C090918B2C9111DF -:105A600002C0863219F0823509F0F3C084E4F801EF -:105A70008083118281E0892713C08091892C811154 -:105A8000FCC0F8018081803509F476C108F006C1B8 -:105A9000803309F409C190918D2C911174C181E07A -:105AA00080938C2C80E090E0A0C28339C1F71982EA -:105AB0001A821B821C8288E8898343E050E060E000 -:105AC00070E0CE0102960E942A0FF8018181803297 -:105AD00009F4ABC0803709F047C0F8019281898191 -:105AE0009813B2C093818A819813AEC094818B8140 -:105AF0009813AAC095818C819813A6C084E08083F6 -:105B000061E070E0C8010E94BF3783E029C0853999 -:105B100031F644E050E064E070E0CE0101960E946E -:105B20002A0FF8018181803209F47FC08037E1F4C7 -:105B3000F80192818981981387C093818A81981393 -:105B400083C094818B8198137FC095818C81981339 -:105B50007BC0108261E070E0C8010E94BF3784E022 -:105B600080938C2C38E171C0E82EE294AFE0EA22F9 -:105B7000EA94EA948F70F82E88E090E08F199109EA -:105B80002FEF30E0690102C0D594C7948A95E2F7FF -:105B9000F5E0EF1629F024E0E2122AC0FF20E1F040 -:105BA00044E050E0B8016E5F7F4FCE0101960E9445 -:105BB0002556892B61F499818A8189279B818927C0 -:105BC0009C818927F801968189278C2171F1F4E065 -:105BD000EF120EC0F11038C044E050E0B8016E5F23 -:105BE0007F4FCE0101960E942556892BF1F02CC0E3 -:105BF00023E02E1548F1F12CA701B8016E5F7F4F0D -:105C0000CE0101960E942556892BF1F4D801AE0DE4 -:105C1000BF1DE1E0F0E0EC0FFD1FEE0DFF1D129641 -:105C20009C9180818927C82279F43981F8013083D9 -:105C30002A8121839B8192838C81838323279227CE -:105C40008927848338E201C030E020E0832F922F3F -:105C5000CCC1695F7F4F83E0769567958A95E1F7C0 -:105C60006330710508F41BCF62507109C8010E94AE -:105C7000EA37811102CF81E092C11092892C809184 -:105C8000AD2E81118BC16091882CF4E06F9FB00123 -:105C9000112444E050E0C80102967EC1803A09F424 -:105CA00055C0823AC1F1F7CEF801F18080918D2C78 -:105CB000882359F08091852C882339F08091872C96 -:105CC000811103C0E090862C02C0E0908A2CFE1463 -:105CD00010F0F80131C1C12CD12CF4E0FF9EB001CD -:105CE000112444E050E0C8018C0D9D1D0E942A0F34 -:105CF000F394EF1001C0F12C24E0C20ED11C80E11E -:105D0000C816D10451F760E170E0C8010E94BF37A6 -:105D100080E990E06AC1F801F180F1E0FF15C8F672 -:105D200080918A2CF816A8F68F2DE5DD882309F4DA -:105D3000C2C0C80102962091AD2E21112FC1F4E0FE -:105D4000FF9EB001112444E050E026C1F801F1802B -:105D5000F1E0FF1508F0BDCF80918A2CF81608F00D -:105D6000B8CF8F2DC8DD882309F4A5C0F092882C08 -:105D700081E08093892C12C1F80181818111A9CF22 -:105D800010928C2C8FCE8C3309F40EC148F48933D9 -:105D900009F4A6C08A3391F18B3109F080CE6AC034 -:105DA0008B3409F40FC138F48E3309F078CE8DEBC3 -:105DB000F801808314C1803621F0853A09F4ABC024 -:105DC0006ECEF801108284E0818383E0828381E0DB -:105DD00083838483158280918A2C843111F08EE034 -:105DE00001C08BE0F801868383E0878368E070E080 -:105DF000C8010E94BF3780E590E0F7C0F801D1806C -:105E0000E280ED1408F465CF80918A2CD81608F052 -:105E100060CFE81608F05DCF8091852C882351F083 -:105E20008D2D69DD882309F446C08E2D64DD88231D -:105E300009F441C0F12C6D2D70E0E61AF70AFFEF6E -:105E4000EF1AFF0AEE0CFF1CEE0CFF1C660F771F0B -:105E5000660F771FA701C8010E942A0FB701C8016A -:105E60000E94BF37C7010296F3E0880F991FFA9589 -:105E7000E1F7BBC060918A2C660F660F6051E62E79 -:105E8000F12CB701685F7F4F44E050E0CE010196EE -:105E90000E942A0F9981F801818198130CC09A8180 -:105EA0008281981308C09B818381981304C09C81D0 -:105EB0008481981711F086E072C081E08093872C6E -:105EC000B701645F7F4F42E050E0C8010E942A0F93 -:105ED00062E070E0C8010E94BF3780E290E085C0B8 -:105EE000F8016181633008F0F4CE80918A2C70E073 -:105EF000680F711D660F771F660F771F43E050E034 -:105F0000C8010E942A0F63E070E0C8010E94BF37F9 -:105F100088E290E06AC0F8012181E22EF12C9E2DEA -:105F20008827856A092E000CAA0BBB0B32814C0115 -:105F30005D01A32A233010F0108233C080918A2C97 -:105F4000B701680F711D660F771F660F771F44E05A -:105F500050E0CE0101960E942A0F89819A81AB817F -:105F6000BC81880D991DAA1DBB1D89839A83AB83B3 -:105F7000BC830097A105B14010F084E010C080916F -:105F80008A2CB701680F711D660F771F660F771F88 -:105F900044E050E0CE0101960E94780F8AE0F801BB -:105FA000808384E090E021C040E250E06AEC70E041 -:105FB000C8010E944C5660E270E0C801E0D780E161 -:105FC00091E013C060918A2C660F660F605170E0FB -:105FD0006B5F7F4F41E050E0C8010E942A0F61E0F3 -:105FE00070E0C801CCD788E190E02496CDBFDEBF39 -:105FF000DF91CF911F910F91FF90EF90DF90CF90A5 -:10600000BF90AF909F908F900895CF93DF93EC0156 -:1060100043E050E060E070E00E942A0F44E050E06E -:1060200064E070E0CE010396DF91CF910C942A0FCB -:106030000F931F93CF93DF931F921F92CDB7DEB7BD -:106040008C01FC0190818181892798E889279281C0 -:1060500089278A83938184818927958189279681DD -:106060008927898343E050E060E070E0C8010E9426 -:10607000780F41E050E063E070E0CE0102960E94AC -:10608000780F44E050E064E070E0C80103960E949D -:10609000780F41E050E068E070E0CE0101960E9488 -:1060A000780F0F900F90DF91CF911F910F9108956E -:1060B00081E08093B12C84E090E08093902C9093C9 -:1060C000912C88E080938F2C10928E2C089581E083 -:1060D0008093B12C84E490E08093902C9093912C49 -:1060E00088E080938F2C10928E2C089581E080930D -:1060F000B12C82E090E08093902C9093912C88E1D9 -:1061000080938F2C10928E2C089581E08093B12C77 -:1061100082E490E08093902C9093912C88E180937E -:106120008F2C10928E2C089581E08093B12C0895CD -:1061300008958F929F92AF92BF92CF92DF92EF928B -:10614000FF920F931F93CF93DF93CDB7DEB7629784 -:10615000CDBFDEBF8C015B018091B12C6730710532 -:1061600001F5F8019081882311F0963211F09235F3 -:10617000C1F421E0811120E020938E2C882311F0BE -:10618000963211F0923559F49091902C8091912C87 -:10619000F801908381838FEF8093922C37C0A12CDC -:1061A000B12C853009F497C050F48230A1F1C8F0C9 -:1061B000833009F468C0843009F481C0ACC58830EC -:1061C00009F41CC138F4863009F491C0873009F411 -:1061D000CAC0A1C5893009F441C38D3008F463C336 -:1061E0009AC5982F9095917090938E2CF80190817C -:1061F000882311F0963219F0923509F006C4909177 -:10620000902C8091912CF8019083818384E080937D -:10621000B12C80E181C5F8018081982F9D7F913458 -:1062200019F48AE080835AC38033C1F462E070E0DD -:10623000C801D0D6882309F494C0F8016181F0E147 -:106240006F9FB001112440E150E0C8010E942A0F65 -:1062500060E170E0C80193D680E95EC5803A79F4C8 -:1062600062E070E0C801B6D6882309F47AC0F8016C -:1062700081818093A82C83E08093B12CD2CF80358C -:1062800009F049C54AC060E170E0C801A3D688237F -:1062900089F08091AD2E81110BC06091A82CF0E1A6 -:1062A0006F9FB001112440E150E0C8010E94780FB7 -:1062B0008AE001C081E0F801808382E00DC3909103 -:1062C0008E2CF8018081911102C08632D1F0823586 -:1062D00009F0A3C316C090918E2CF8018081911112 -:1062E00002C0863271F0823509F045C40AC090912F -:1062F0008E2CF8018081911102C0863211F0823516 -:1063000051F42091902C8091912CF801208381836D -:1063100081E0892777C38035C9F4F801818188231A -:1063200019F0F8011082DAC262E070E0C80152D6BA -:106330008823B9F0E091AE2EF091AF2E40E060E0FE -:1063400070E081E919951092B12CE5C490EA980F9C -:10635000923008F0B4C462E070E0C8013BD681110D -:10636000DDC481E04FC2C8010E94733D64E0780142 -:10637000F4E0EF0EF11CC7010E948F40E091AE2EB9 -:10638000F091AF2E44E0B70180EA1995F8019481AD -:106390008091A92C981329C095818091AA2C9813DB -:1063A00024C096818091AB2C98131FC09781809157 -:1063B000AC2C98131AC08091AD2C80838091AE2CA8 -:1063C00081838091AF2C82838091B02C838364E0A1 -:1063D000C8010E94A842E091AE2EF091AF2E44E099 -:1063E000B80181EA199588E004C2E091AE2EF091DF -:1063F000AF2E44E069EA7CE280EC2DC2F801808196 -:10640000803551F48181811107C08281873521F463 -:1064100083818D3C09F405C264E0C8010E948F406D -:10642000F8018081803309F0BDC062E070E0C801EE -:10643000D1D5882309F4A7C0F801618167FD04C0A4 -:10644000862F8370833029F0862F8F708F3009F06C -:106450007FC06093A82C8091932C9091942C3091C4 -:10646000952C282F22952095492F4227407F09F00F -:106470003FC023272F70E1F5929590959327907F49 -:10648000B9F5262F67FD02C0237003C02F7009F0F5 -:1064900023E08095432F42954F702223B1F090E086 -:1064A000022E02C0959587950A94E2F7E32FF0E05B -:1064B000022E02C0F595E7950A94E2F73E2F50E0D0 -:1064C00002C0559547952A95E2F740FBCC24C0F8C9 -:1064D000D12CF601EE0FFF1FEE0FFF1F30FBEE2455 -:1064E000E0F8F12CEE0CFF1CEE298170E82B01C0C6 -:1064F000E7E0F0E08091A72CEE0FFF1FE25CFF4D7C -:10650000E80FF11D8081F8019801205F3F4F119243 -:106510002E173F07E1F79091962CF801918782FFA3 -:1065200009C09091932C96839091942C978390918D -:10653000952C908784FF15C06360F0E16F9FB001D8 -:106540001124665F7F4F46E050E0C8010A9607C0FD -:1065500080E1689FB001112440E150E0C8010E9431 -:106560002A0F60E170E0C8010AD5E091AE2EF091EB -:10657000AF2E42E1B80180E8199562E1C8010E949E -:10658000A84280E939C10E949A3F91E08927F80129 -:106590008083E091AE2EF091AF2E44E0B80181EC03 -:1065A00019959CC1803A61F462E070E0C80112D58F -:1065B0008823D9F1F80181818093A82C89E00DC04E -:1065C000803C89F462E070E0C80104D5882369F159 -:1065D000F80181818093A82C8BE08093B12C0E94DC -:1065E0009A3F9AE00EC1813C91F462E070E0C801EC -:1065F000F1D48823D1F0F80181818093A82CFAE0AE -:10660000FF2EF092B12C0E949A3F8F25FBC0823C56 -:1066100099F462E070E0C801DDD4882331F0F8011C -:1066200081818093A82C8CE0D8CFE091AE2EF091A0 -:10663000AF2E44E0B80121C0803B11F562E070E06C -:10664000C801C8D4E091AE2EF091AF2E44E0B8015D -:10665000882399F086E819958091AD2E8111BFCFDE -:10666000F8016181F0E16F9FB001112440E150E039 -:1066700087E99CE20E94780FB2CF81EC1995BEC0E9 -:1066800090EA980F923008F0BFC062E070E0C80155 -:10669000A1D4882309F4B2C0F8018081803621F0AA -:1066A000EAE3CE2ED12C03C070E3C72ED12CF80123 -:1066B000818187FF0CC0807FF0E18F9F70011124E2 -:1066C00080ECC80ED11C66EFA62EB12C08C08C7FC2 -:1066D00090E1899F7001112456E3A52EB12CE09121 -:1066E000AE2EF091AF2E42E0B80180E91995F80185 -:1066F000808181708093A72CC70144E0969587958F -:106700004A95E1F78093A82C9091922C981769F004 -:10671000B5016E0D7F1D44E050E083E99CE20E94CC -:106720002A0F8091A82C8093922C68E0CE010196CC -:106730000E947B0E8091AC2E44E050E0873019F42B -:1067400063E070E002C060E070E0CE010F960E944E -:106750002A0FB6016E0D7F1D46E050E0CE0109966E -:106760000E942A0F89818093A92C8A818093AA2C68 -:106770008B818093AB2C8C818093AC2C60E489EA74 -:106780009CE20E94C2448091A92C8093AD2C809100 -:10679000AA2C8093AE2C8091AB2C8093AF2C80914F -:1067A000AC2C8093B02C60E28DEA9CE20E94C24443 -:1067B00020E0AE014F5F5F4FBE01615F7F4FCE01B2 -:1067C0000996E6D68981F80180838A8181838B814D -:1067D00082838C818383E058FF4F8D818083319643 -:1067E0008E81808331968F818083319688858083E6 -:1067F00087E08093B12C80E290E16CC30E949A3FC5 -:1068000091E08927F8010ECD8035B9F4F801818136 -:10681000811187CD62E070E0C801DCD3882309F4E0 -:10682000A0CD1092B12CE091AE2EF091AF2E40E0B1 -:1068300060E070E081E919956EC2A501495F5F4F84 -:1068400033E0569547953A95E1F7E091AE2EF091F9 -:10685000AF2EB80182E9199581E0D4C062E1C80188 -:106860000E948F4060E170E0C801B4D3E091AE2E89 -:10687000F091AF2E882329F142E1B80181E8199502 -:106880008091AD2E81110BC06091A82CF0E16F9F1B -:10689000B001112440E150E0C8010E94780F0E942D -:1068A0009A3F9AE015C066E0C8010E948F4064E0FC -:1068B00070E0C8018FD3811113C0E091AE2EF0912A -:1068C000AF2E44E0B80181EC19950E949A3F91E007 -:1068D0008927F801808388E08093B12C84E01CC272 -:1068E0006091A82CF0E16F9FB001112440E150E0CD -:1068F00087E99CE20E942A0F9091972C80919B2C13 -:1069000080959813E3C280919F2C9813DFC29091D9 -:10691000982C80919C2C80959813D8C28091A02CA3 -:106920009813D4C29091992C80919D2C80959813A6 -:10693000CDC28091A12C9813C9C290919A2C8091BC -:106940009E2C80959813C2C28091A22C9813BEC22F -:106950009091A32C8091A42C80959813B7C280911C -:10696000A52C9813B3C28091A62C80959813AEC223 -:10697000C090972CD090982CE090992CF0909A2C65 -:10698000F80180809180A280B3808091B12C8B30FF -:1069900009F081C2E091AE2EF091AF2E46E0B80131 -:1069A00085E81995C818D908EA08FB08C092972C01 -:1069B00033272F2D1E2D0D2D0093982CA701662710 -:1069C00077274093992C8F2D9927AA27BB2780934F -:1069D0009A2CEC2DE095E0939B2CE02FE095E09332 -:1069E0009C2CE42FE095E0939D2CE82FE095E0931C -:1069F0009E2CC0929F2C0093A02C4093A12C80939E -:106A0000A22C88E08093B12C86C1903409F083C118 -:106A100082E08093B12C8AE0F5CE833909F093CCE3 -:106A20008091AC2E873009F0A1C043E050E060E0D7 -:106A300070E0CE0102960E942A0F88E88983F8014F -:106A40009181903219F0903761F024C0F801808371 -:106A50003A8131832B8122839C8193832327822750 -:106A60002AC1F8018281883809F055C193818A8151 -:106A7000981351C194818B8198134DC195818C815C -:106A8000981349C184E0808361E070E0C80177D247 -:106A900085E09FC0E92EE294EFE0EE22EA94EA94CA -:106AA0009F70F92E88E090E08F1991092FEF30E068 -:106AB000690102C0D594C7948A95E2F7F5E0EF1614 -:106AC00029F084E0E8122AC0FF20E1F044E050E021 -:106AD000B8016E5F7F4FCE0101960E942556892B2B -:106AE00061F49A818B81892798E889279C8189277D -:106AF000F801968189278C2189F1F4E0EF120EC00C -:106B0000F11009C144E050E0B8016E5F7F4FCE0143 -:106B100001960E942556892B09F1FDC083E08E1550 -:106B200008F4F9C0F12CA701B8016E5F7F4FCE01C8 -:106B300001960E942556892B09F0EDC0D801AE0DB3 -:106B4000BF1DE1E0F0E0EC0FFD1FEE0DFF1D129602 -:106B50009C9180818927C82209F0DDC098E8F8015E -:106B600090833A8131832B812283A1C044E050E09D -:106B700060E070E007C0853909F0E5CB44E050E003 -:106B800063E070E0CE0101960E942A0FF801818136 -:106B9000803209F485C0803701F5F801928189813E -:106BA0009813B9C093818A819813B5C094818B8161 -:106BB0009813B1C095818C819813ADC080918F2CB2 -:106BC000808361E070E0C801DAD18FEF8093922C6E -:106BD00086E08093B12C88E19FC0E82EE2947FE0AC -:106BE000E722EA94EA948F70F82E88E090E08F19FB -:106BF00091092FEF30E0690102C0D594C7948A95BE -:106C0000E2F7F5E0EF1629F084E0E8122AC0FF2051 -:106C1000E1F044E050E0B8016E5F7F4FCE01019695 -:106C20000E942556892B61F499818A8189279B814D -:106C300089279C818927F801968189278C2181F1F8 -:106C4000F4E0EF120EC0F11066C044E050E0B8016D -:106C50006E5F7F4FCE0101960E942556892B01F170 -:106C60005AC083E08E1508F456C0F12CA701B80174 -:106C70006E5F7F4FCE0101960E942556892B09F049 -:106C80004AC0D801AE0DBF1DE1E0F0E0EC0FFD1FE2 -:106C9000EE0DFF1D12969C9180818927C822D9F59F -:106CA0003981F80130832A8121839B8192838C81F1 -:106CB0008383232792278927848388E22DC0823CFF -:106CC00009F0CBC0F8018181803E09F0CFC08281FC -:106CD000843B09F0CBC046E050E06AEA74E0CE01A4 -:106CE00001960E942A0F89818B3409F03ACB8A8160 -:106CF000893709F036CB8B818B3109F032CB8C810F -:106D00008A3E09F02ECB8D818B3709F02ACB8E81FC -:106D10008C3C09F026CB80E090E0DCC0F80180815B -:106D2000803621F06AE3C62ED12C03C050E3C52E75 -:106D3000D12CF801818187FF0CC0807FF0E18F9F0B -:106D40007001112480ECC80ED11C46EFA42EB12C8A -:106D500008C08C7F90E1899F7001112436E3A32E37 -:106D6000B12CE091AE2EF091AF2E42E0B80180E957 -:106D70001995F801808181708093A72CC70124E0C8 -:106D8000969587952A95E1F78093A82CB5016E0D0D -:106D90007F1D44E050E083E99CE20E942A0F80912D -:106DA000A82C8093922C68E0CE0101960E947B0E65 -:106DB0008091AC2E44E050E0873019F463E070E03D -:106DC00002C060E070E0CE010F960E942A0FB6016B -:106DD0006E0D7F1D46E050E0CE0109960E942A0FFD -:106DE00089818093A92C8A818093AA2C8B8180939E -:106DF000AB2C8C818093AC2C60E489EA9CE20E94ED -:106E0000C2448091A92C8093AD2C8091AA2C8093B0 -:106E1000AE2C8091AB2C8093AF2C8091AC2C8093C6 -:106E2000B02C60E28DEA9CE20E94C24487E080932D -:106E3000B12C8981F80180838A8181838B8182834F -:106E40008C818383AE014F5F5F4FBE01615F7F4FD7 -:106E5000CE010996F0D080E25FCF982F9F779033D4 -:106E600029F0803A19F0805C833078F481E08093D7 -:106E7000B12C84E0F8018083E091AE2EF091AF2E2A -:106E800040E060E070E082EC8BCBE091AE2EF091C0 -:106E9000AF2E40E0DECC8A3069F4E091AE2EF09166 -:106EA000AF2E46E0B80184E81995C80CD91CEA1C3D -:106EB000FB1C7CCD8C3009F079CDE091AE2EF091A9 -:106EC000AF2E46E0B80187E8199570CD0E949A3F31 -:106ED00096E0FECC6296CDBFDEBFDF91CF911F91D1 -:106EE0000F91FF90EF90DF90CF90BF90AF909F9069 -:106EF0008F900895CF93DF932091AC2E273071F4BB -:106F0000EC0143E050E060E070E00E942A0F44E0B2 -:106F100050E063E070E0CE01039604C044E050E02E -:106F200060E070E0DF91CF910C942A0FCF93DF9354 -:106F30001F92CDB7DEB72091AC2E273029F447E061 -:106F400050E060E070E015C0FC0130812181232712 -:106F50003281232733812327298344E050E060E0F6 -:106F600070E00E94780F41E050E064E070E0CE01F4 -:106F700001960E94780F0F90DF91CF91089520E441 -:106F80002093D00026EC2093D5002093D40021E05C -:106F90002093D000DC01680F791FA617B70741F0D6 -:106FA000ED91F0E0EE51FA4FE491E093D300F5CF8C -:106FB000E091D500F0E0EE51FA4FE491EC93E091CE -:106FC000D400F0E0EE51FA4FE4911196EC93109258 -:106FD000D000089520E42093D00026EC2093D50023 -:106FE0002093D40021E02093D000DC01680F791FAA -:106FF000A617B70741F0ED91F0E0EE51FA4FE4919A -:10700000E093D300F5CFE091D500F0E0EE51FA4FD8 -:10701000E4918C918E130AC0E091D400F0E0EE511F -:10702000FA4FE49181E011969C919E1380E01092BA -:10703000D000817008958F929F92BF92CF92DF927D -:10704000EF92FF920F931F93CF93DF93DC018C910C -:10705000D12C30E08695D794869537958695D79430 -:10706000869537958695D794869537958695D79446 -:107070008695379511968C9111978695D79486951C -:1070800037958695D794869537958695D794869526 -:1070900037958695D7948695379512968C91129749 -:1070A000F0E010E08695F795869517958695F7950B -:1070B000869517958695F795869517958695F795F4 -:1070C0008695179513968C9113978695F7958695C7 -:1070D00017958695F795869517958695F7958695D4 -:1070E00017958695F7958695179514968C91149714 -:1070F00090E020E0869597958695279586959795BB -:107100008695279586959795869527958695979543 -:10711000869527951596EC91E6959795E695279592 -:10712000E6959795E6952795E6959795E6952795A3 -:10713000E6959795E69527954B01DA014C5F5F4FF1 -:107140000C91E401B9904E01B026C32FD0E0BE01EE -:1071500062557F4D7B01612F70E062557E4DE701E6 -:10716000F880EB0188816F2D682BE22EF12CE7016E -:10717000C255DD4D8881682B70E062577F4DEB0171 -:1071800088818695E7956F2F60718D2D817E6827A8 -:10719000892F80726827832F84796827812F8377CE -:1071A0006827822F8A736827F62EF2946F25762F30 -:1071B000769576956727FB2CF6266695F6267D2D27 -:1071C0006F2F892FF694879567957795B694C72E7C -:1071D000D12CE601C255DF4D6E01E62EF12CE70100 -:1071E000C255DE4D7E01E601F881E7019881EF2E60 -:1071F000E92AC82ED12CE601C255DD4D9881E92A35 -:10720000F12CE701C257DF4D98819695E795F12F54 -:10721000F071932F917EEF2EE926922F9072E9263E -:10722000972F9479E926962F9377E926982F9A73CA -:10723000E926FE2CF294EF24CE2CC694C694EC24BE -:10724000FB2CFE24E694FE24F6942795179537959B -:10725000B694C32ED12CE601C255DF4D6E01E12E4E -:10726000F12CE701C255DE4D7E01E601F881E70110 -:107270009881EF2EE92AC22ED12CE601C255DD4DB0 -:107280009881E92AF12CE701C257DF4D9881969544 -:10729000E795F62FF071972F917EEF2EE926982F24 -:1072A0009072E926932F9479E926912F9377E92616 -:1072B000922F9A73E926FE2CF294EF24CE2CC694DA -:1072C000C694EC24FB2CFE24E694FE24F82FF694BE -:1072D000F79567957795B694872F90E0EC01C255A6 -:1072E000DF4D862F90E082559E4DF880EC0188811D -:1072F0008F29EF2EF12CE701C255DD4D9881892BA6 -:1073000090E082579F4DEC0188818695E795912FFB -:107310009071832F817EE92EE826822F8072E826E5 -:10732000872F8479E826862F8377E8268F2F8A7324 -:10733000E826FE2CF294EF24CE2CC694C694EC24BE -:10734000FB2CFE24E694FE24F6942795179537959A -:10735000B694832F90E0EC01C255DF4D812F90E071 -:1073600082559E4DF880EC0188818F29E22EF12C08 -:10737000E701C255DD4D9881892B90E082579F4DE2 -:10738000EC0188818695E795962F9071872F817EF5 -:10739000F92EF8268F2F8072F826832F8479F8260D -:1073A000812F8377F826822F8A73F8269F2D929556 -:1073B000F926EF2CE694E694FE249B2D9F25F69467 -:1073C0009F258F2F9695879567957795B694C72EAD -:1073D000D12CE601C255DF4D6E01E62EF12CE701FE -:1073E000C255DE4D7E01E601F881E7019881EF2E5E -:1073F000E92AC82ED12CE601C255DD4D9881E92A33 -:10740000F12CE701C257DF4D98819695E795F12F52 -:10741000F071932F917EF927922F9072F927972F71 -:107420009479F927962F9377F927982F9A73F9274C -:107430009F2F9295F927FF2EF694F694FF259B2D0A -:107440009F27F6959F279695279517953795B6947C -:10745000C32ED12CE601C255DF4D6E01E12EF12C79 -:10746000E701C255DE4D7E01E601F881E701988112 -:10747000EF2EE92AC22ED12CE601C255DD4D9881AE -:10748000E92AF12CE701C257DF4D98819695E795DF -:10749000F62FF071972F917E9F27F82FF0729F277C -:1074A000F32FF4799F27F12FF3779F27F22FFA73A9 -:1074B0009F27F92FF2959F27F92FF695F6959F278D -:1074C000FB2DF9279695F927982F8F2F869597955D -:1074D00067957795D72EF62F672F70E0EB01C25591 -:1074E000DF4D6F2F70E062557E4DF880EB01888193 -:1074F0006F2D682BE92EF12CE701C255DD4D8881F7 -:10750000682B70E062577F4DEB0188818695E79587 -:10751000632F617E812F80718627622F607286279C -:107520006D2D647986276F2F63778627692F6A739D -:107530008627682F62958627682F66956695862729 -:10754000B694B8268695B826812FB6942795879548 -:107550003795182F0E270D934A175B0709F0F0CDCA -:10756000D092B22CF093B32C9093B42C3093B52CD2 -:107570008093B62C2093B72CDF91CF911F910F9160 -:10758000FF90EF90DF90CF90BF909F908F900895E5 -:107590008F929F92AF92BF92CF92DF92EF92FF9223 -:1075A0000F931F93CF93DF93FC01C62FF42EB52FBB -:1075B0008081A0E050E0869557958695A7958695A1 -:1075C00057958695A795869557958695A7958695FF -:1075D00057958695A7958181869557958695A79508 -:1075E000869557958695A795869557958695A795DF -:1075F000869557958695A795828130E040E08695DF -:1076000047958695379586954795869537958695BE -:1076100047958695379586954795869537958381C5 -:10762000869547958695379586954795869537959E -:10763000869547958695379586954795869537958E -:10764000648190E080E0669587956695979566954C -:1076500087956695979566958795669597956695AE -:10766000879566959795B5806B2D669587956695F8 -:10767000979566958795669597956695879566958E -:1076800097956695879566959795B62EEA2FF0E0C3 -:10769000E255FF4D032F10E002551E4DD081F80139 -:1076A0006081D62B092F10E002551D4DF801608135 -:1076B000ED2FE62BF0E0E257FF4DC0800C2F172F87 -:1076C000CF2DDB2F7E01F4E0EF0EF11C7881F80165 -:1076D000B1918F01B7276B2DC6946795F42FF07188 -:1076E000E52FE17EFE27E82FE072FE27EA2FE479FE -:1076F000FE27E32FE377FE27E92FEA73FE27EF2F1C -:10770000E295FE27DF2ED694D694FD25EB2FEF27AA -:10771000F695EF2720FDEC25E6958795479557953B -:10772000B695C52ED12CF601E255FF4D6F01A42E62 -:10773000B12CF501E255FE4D5F01F601D080F50157 -:10774000C080DC28E82FF0E0E255FD4DF081ED2D02 -:10775000EF2BF0E0E257FF4DC080C6946795F32F02 -:10776000F071EA2FE17EFE27E92FE072FE27E52F78 -:10777000E479FE27E42FE377FE27E82FEA73FE275C -:10778000EF2FE295FE27DF2ED694D694FD25EB2F22 -:10779000EF27F695EF27DA2E20FDEC25E695979555 -:1077A0003795D794CB2EC694AD2DB0E0A255BF4DE2 -:1077B000E32FF0E0E255FE4DAC91E081EA2BA92FDA -:1077C000B0E0A255BD4DFC91EF2BF0E0E257FF4D2C -:1077D000B081B6956795F42FF071E52FE17EFE2715 -:1077E000E82FE072FE27ED2DE479FE27E32FE37703 -:1077F000FE27E92FEA73FE27EF2FE295FE27AF2F32 -:10780000A695A695FA27EC2DEF27F695EF2720FDF4 -:10781000EB27E695879547955795C694A52FB0E039 -:10782000A255BF4DE42FF0E0E255FE4DAC91E08152 -:10783000EA2BA82FB0E0A255BD4DFC91EF2BF0E054 -:10784000E257FF4DB081B6956795F32FF071ED2D9E -:10785000E17EFE27E92FE072FE27E52FE479FE277F -:10786000E42FE377FE27E82FEA73FE27EF2FE29558 -:10787000FE27AF2FA695A695FA27EC2DEF27F695B4 -:10788000EF2720FDEB27E69597953795D794C6947B -:10789000AD2DB0E0A255BF4DE32FF0E0E255FE4D17 -:1078A000AC91E081EA2BA92FB0E0A255BD4DFC912F -:1078B000EF2BF0E0E257FF4DB081B6956795F42FBE -:1078C000F071E52FE17EFE27E82FE072FE27ED2D17 -:1078D000E479FE27E32FE377FE27E92FEA73FE27FB -:1078E000EF2FE295FE27AF2FA695A695FA27EC2D50 -:1078F000EF27F695EF2720FDEB27E695879547952F -:107900005795C694A52FB0E0A255BF4DE42FF0E0E7 -:10791000E255FE4DAC91E081EA2BA82FB0E0A255D4 -:10792000BD4DFC91EF2BF0E0E257FF4DB081B695D5 -:107930006795F32FF071ED2DE17EFE27E92FE072C0 -:10794000FE27E52FE479FE27E42FE377FE27E82FD3 -:10795000EA73FE27EF2FE295FE27AF2FA695A69597 -:10796000FA27EC2DEF27F695EF2720FDEB27E6957C -:1079700097953795D794C694ED2DF0E0E255FF4DDD -:10798000A32FB0E0A255BE4DF081EC91EF2BA92FB3 -:10799000B0E0A255BD4DFC91EF2BF0E0E257FF4D5A -:1079A000B081B6956795F42FF071E52FE17EFE2743 -:1079B000E82FE072FE27ED2DE479FE27E32FE37731 -:1079C000FE27E92FEA73FE27EF2FE295FE27AF2F60 -:1079D000A695A695FA27EC2DEF27F695EF2720FD23 -:1079E000EB27E695879547955795A52FB0E0A255CB -:1079F000BF4DE42FF0E0E255FE4DAC91E081EA2B63 -:107A0000A82FB0E0A255BD4DFC91EF2BF0E0E2575E -:107A1000FF4DF081F6956795B62EED2DE17E632F33 -:107A200060716E27E92FE0726E27E52FE4796E27EB -:107A3000E42FE3776E27E82FEA736E27E62FE295AF -:107A40006E27E62FE695E6956E27C694C6266695C0 -:107A5000C62620FDCF26C69497953795D794AD2D91 -:107A6000CD2CD12CF601E255FF4D6F01832E912CC8 -:107A7000F401E255FE4D4F01F601B081F401608141 -:107A8000B62BC92ED12CF601E255FD4D6081EB2FAE -:107A9000E62BF0E0E257FF4DC080E72FF0E0EE511B -:107AA000FB4FE491EC25EC837B257993EC16FD06E6 -:107AB00009F00CCE5093B22C4093B32C8093B42C8D -:107AC000A093B52C3093B62C9093B72CDF91CF9127 -:107AD0001F910F91FF90EF90DF90CF90BF90AF90EC -:107AE0009F908F900895BF92CF92DF92EF92FF9276 -:107AF0000F931F93CF93DF93A091B22C5091B32C8F -:107B00001091B42C4091B52C3091B62C2091B72C0B -:107B1000FC01BC016C5F7F4F0191952F90718A2F02 -:107B2000817E9827812F80729827842F84799827C7 -:107B3000832F83779827822F8A739827892F82959E -:107B40009827892F869586959827C42ED12CE601F3 -:107B5000C255DF4D6E01E32EF12CE701C255DE4D1B -:107B60007E01E601B881E7018881B82BE22EF12C75 -:107B7000E701C255DD4D8881CB2FC82BD0E0C2571D -:107B8000DF4DB881B027B92796959B270695812FA1 -:107B9000969587955795A795B32FB071942F917EA1 -:107BA000B927922F9072B9279A2F9479B927952FD8 -:107BB0009377B927982F9A73B9279B2F9295B92756 -:107BC0009B2F96959695B927CA2ED12CE601C255C2 -:107BD000DF4D6E01E52EF12CE701C255DE4D7E0131 -:107BE000E6011881E7019881192BE82EF12CE701B5 -:107BF000C255DD4D9881C12FC92BD0E0C257DF4D52 -:107C0000988190279B27B695B927B02EB694922FCE -:107C1000B695979537954795B52FB0712A2F217E48 -:107C2000B227282F2072B227242F2479B227232F9E -:107C30002377B227292F2A73B2272B2F2295B22719 -:107C40002B2F26952695B227C42FD0E08E01025502 -:107C50001F4D6801C32FD0E08E0102551E4D7801E3 -:107C6000E6010881E7012881022BE92EF12CE701CA -:107C7000C255DD4D2881022B10E002571F4DE8014F -:107C80002881C22FCB25CB27B695BC272B2D269537 -:107C9000B69587955795A795C32FC071B42FB17E20 -:107CA000BC27C92FC072BC27CA2FC479BC27C52FD7 -:107CB000C377BC27C82FCA73BC27CB2FC295BC275C -:107CC000CB2FC695C695BC27CA2FD0E0C255DF4D35 -:107CD000052F10E002551E4DF880E8011881F12AA9 -:107CE000082F10E002551D4DE8011881CF2DC12B42 -:107CF000D0E0C257DF4DC881C227CB27B695BC273D -:107D00002695B695979537954795C52FC071BA2F8B -:107D1000B17EBC27C82FC072BC27C42FC479BC2732 -:107D2000C32FC377BC27C92FCA73BC27CB2FC295DB -:107D3000BC27CB2FC695C695BC27C42FD0E0C25513 -:107D4000DF4D032F10E002551E4DF880E801188129 -:107D5000F12A092F10E002551D4DE8011881CF2DA1 -:107D6000C12BD0E0C257DF4DC881C227CB27B695C3 -:107D7000BC272695B69587955795A795D32FD07193 -:107D8000B42FB17EDB27B92FB072DB27BA2FB479BD -:107D9000DB27B52FB377DB27B82FBA73DB27BD2FCF -:107DA000B295DB271D2F169516951D27CA2ED12CAF -:107DB000E601C255DF4D6E01E52EF12CE701C255FB -:107DC000DE4D7E01E6010881E701B8810B2BE82E2C -:107DD000F12CE701C255DD4DB881C02FCB2BD0E08F -:107DE000C257DF4DB881B227B127D12FD695DB27F7 -:107DF000B22EB694D695979537954795D52FD071D5 -:107E00002A2F217ED227282F2072D227242F2479AF -:107E1000D227232F2377D227292F2A73D2272D2F3A -:107E20002295D2272D2F26952695BD2FB227C42F18 -:107E3000D0E08E0102551F4D6801C32FD0E08E01A6 -:107E400002551E4D7801E6010881E7012881022BC9 -:107E5000E92EF12CE701C255DD4D2881022B10E0FF -:107E600002571F4DE80118811B251B27DB2FD695D4 -:107E7000D127D69587955795A795182F242F217E22 -:107E8000832F80712827892F807228278A2F847951 -:107E90002827852F83772827812F8A732827B22FB9 -:107EA000B2952B27B22FB695B6952B27EA2EF12C3B -:107EB000E701C255DF4D7E01C52ED12CE601C2552A -:107EC000DE4D6E01E701E880E6018881E82AC12ED7 -:107ED000D12CE601C255DD4D8881E82AF12CE7015D -:107EE000C257DF4DB6948881CB2DC827C22726956F -:107EF000B22FBC272B2F2695979537954795292F7D -:107F00006E177F0709F008CEA093B22C5093B32CC4 -:107F10001093B42C4093B52C3093B62C9093B72C7F -:107F2000DF91CF911F910F91FF90EF90DF90CF9055 -:107F3000BF900895CF93DF93E2EBFCE2A0817181C3 -:107F40006281338124819581472F40718A2F817E00 -:107F50008427462F40728427432F44798427422F59 -:107F600043778427492F4A738427482F42958427D3 -:107F7000482F469546958427482F46958427869511 -:107F800067957795A795C32FD0E0C255DF4D422F57 -:107F900050E042555E4DB881EA018881B82B492FE7 -:107FA00050E042555D4DEA018881CB2FC82BD0E0CF -:107FB000C25BDF4D88818695522F5071432F417EE1 -:107FC0004527592F507245275A2F54794527572F47 -:107FD00053774527562F5A734527542F52954527D7 -:107FE000542F569556954527542F56954527469517 -:107FF000979527953795CA2FD0E0C255DF4D472F6B -:1080000050E042555E4DB881EA014881B42B462FBD -:1080100050E042555D4DEA014881CB2FC42BD0E0A2 -:10802000C25BDF4D4881842B8695572F50714A2FB4 -:10803000417E4527562F50724527532F54794527A7 -:10804000522F53774527592F5A734527542F52954E -:108050004527542F569556954527542F5695452715 -:10806000469567957795A795C32FD0E0C255DF4D0C -:10807000422F50E042555E4DB881EA014881B42B51 -:10808000492F50E042555D4DEA014881CB2FC42B6A -:10809000D0E0C25BDF4D4881842B8695CA2FD0E0AB -:1080A000C255DF4D472F50E042555E4DB881EA0181 -:1080B0004881B42B462F50E042555D4DEA0148817E -:1080C000CB2FC42BD0E0C25BDF4D4881842B532FD4 -:1080D000517E422F40714527592F507245275A2F04 -:1080E00054794527572F53774527562F5A734527DD -:1080F000542F52954527542F569556954527542F62 -:10810000569545274695979527953795A083718372 -:108110006283338324839583DF91CF910895BF9247 -:10812000CF92DF92EF92FF920F931F93CF93DF9343 -:108130005091B22CC091B32CB090B42C4091B52C7E -:108140003091B62C2091B72CFC01615008F4EAC1A3 -:108150009C2F9071852F817E98278B2D8072982778 -:10816000842F84799827832F83779827822F8A7387 -:108170009827892F82959827792F76957695972736 -:10818000892F86959827AC2F8B2D96958795A79547 -:108190005795C42FD0E0C255DF4D032F10E0025594 -:1081A0001E4D7881E8019881792B022F10E002554D -:1081B0001D4DE8019881C72FC92BD0E0C259DF4D72 -:1081C00018811695732F7071942F917E9727722FB7 -:1081D00070729727752F747997277A2F737797275F -:1081E000782F7A739727792F72959727792F76951D -:1081F00076959727792F76957927922F272F269591 -:10820000979537954795C52ED12CE601C255DF4D80 -:108210006E01EA2EF12CE701C255DE4D7E01E6012A -:108220007881E7012881722BE82EF12CE701C255F5 -:10823000DD4D2881C72FC22BD0E0C259DF4D2881E8 -:10824000122B16957A2F7071252F217E2727782FD4 -:1082500070722727742F74792727732F7377272736 -:10826000792F7A732727722F72952727722F769589 -:1082700076952727722F76952727BA2F26958795EB -:10828000B7955795C42ED12CE601C255DF4D6E012E -:10829000E32EF12CE701C255DE4D7E01E601788127 -:1082A000E7012881722BE92EF12CE701C255DD4D43 -:1082B0002881C72FC22BD0E0C259DF4DA881A12B46 -:1082C000A695732F7071242F217E2727792F707226 -:1082D0002727752F747927277B2F73772727782FE8 -:1082E0007A732727722F72952727722F76957695A6 -:1082F0002727722F76957227232F372F369597953C -:1083000027954795C52FD0E0C255DF4D0B2F10E0C4 -:1083100002551E4D7881E8013881732B082F10E03B -:1083200002551D4DE8013881C72FC32BD0E0C2593B -:10833000DF4DD881AD2BA6957B2F7071352F317E07 -:108340003727782F70723727742F74793727722F59 -:1083500073773727792F7A733727732F72953727DB -:10836000732F769576953727732F76953727369521 -:108370008795B7955795C42FD0E0C255DF4D022F92 -:1083800010E002551E4D7881E8013881732B092FCA -:1083900010E002551D4DE8013881C72FC32BD0E0F6 -:1083A000C259DF4DD881AD2BA695722F7071342F35 -:1083B000317E7327392F30727327352F3479732725 -:1083C0003B2F33777327382F3A737327372F329524 -:1083D0007327372F369536957327372F36957327A2 -:1083E000342F7695979527953795C52FD0E0C255B0 -:1083F000DF4D0B2F10E002551E4D7881E8014881BA -:10840000742B082F10E002551D4DE8014881C72F3D -:10841000C42BD0E0C259DF4DD881DA2BD6957B2F03 -:108420007071452F417E7427482F40727427432F67 -:1084300044797427422F43777427492F4A7374274E -:10844000472F42957427A72FA695A6957A27472FE1 -:10845000469574274B2F7695879547955795C42F4A -:10846000B82EA32FB0E08D0102551F4D6801A22F39 -:10847000B0E08D0102551E4D7801D6010C91D70157 -:108480008C91082BE92EF12CD701A255BD4D8C9172 -:10849000082B10E002591F4DD8018C91D82BD6958E -:1084A000732F717E822F80717827892F80727827B1 -:1084B000852F84797827842F837778278B2D8A736B -:1084C0007827872F82957827A72FA695A6957A27B4 -:1084D000872F86957827432F322F272F269597951C -:1084E00037954795292F852F90E082559F4D0C2F6A -:1084F00010E002551E4DDC019C91D8018C91892B16 -:108500000B2D10E002551D4DD8019C91892B90E058 -:1085100082599F4DDC019C918D2F892B9081892759 -:10852000819313CE5093B22CC093B32CB092B42C41 -:108530004093B52C3093B62C2093B72CDF91CF917C -:108540001F910F91FF90EF90DF90CF90BF90089513 -:10855000EF92FF920F931F93CF93DF937091B22C02 -:108560005091B32C2091B42C4091B52C3091B62C65 -:10857000C091B72CE42FF0E0E255FF4DA32FB0E0FF -:10858000A255BE4DF081EC91EF2BAC2FB0E0A2557F -:10859000BD4DFC91EF2BF0E0E257FF4D1081DC0167 -:1085A000D0E0615008F4DBC11695D795952F9071F6 -:1085B000872F817E8927922F90728927942F947913 -:1085C0008927932F937789279C2F9A738927982F30 -:1085D00092958927E82FE695E6958E27982F969510 -:1085E00089278695279557957795D695932F9071DE -:1085F000842F817E89279C2F90728927972F9479C9 -:108600008927952F93778927922F9A738927982FF7 -:1086100092958927E82FE695E6958E27982F9695CF -:1086200089279C2F8695979537954795E72FF0E0FA -:10863000E255FF4D052F10E002551E4DC081F80197 -:108640008081C82B022F10E002551D4DF80180815A -:10865000EC2FE82BF0E0E259FF4D8081D82BD69526 -:10866000E52FE071872F817E8E27E22FE0728E2723 -:10867000E42FE4798E27E32FE3778E27E92FEA733F -:108680008E27E82FE2958E27E82FE695E6958E2730 -:10869000E82FE6958E278695279557957795E42FB1 -:1086A000F0E0E255FF4D032F10E002551E4DC08152 -:1086B000F8018081C82B092F10E002551D4DF801EB -:1086C0008081EC2FE82BF0E0E259FF4D8081D82B20 -:1086D000D695E32FE071842F817E8E27E92FE072FB -:1086E0008E27E72FE4798E27E52FE3778E27E22F79 -:1086F000EA738E27E82FE2958E27E82FE695E69518 -:108700008E27E82FE6958E2786959795379547957E -:10871000E72FF0E0E255FF4D052F10E002551E4D0A -:10872000C081F8018081C82B022F10E002551D4D39 -:10873000F8018081EC2FE82BF0E0E259FF4D8081B9 -:10874000D82BD695E52FE071872F817E8E27E22FDB -:10875000E0728E27E42FE4798E27E32FE3778E27CC -:10876000E92FEA738E27E82FE2958E27E82FE6950A -:10877000E6958E27E82FE6958E27869527955795BF -:108780007795E42FF0E0E255FF4D032F10E00255FE -:108790001E4DC081F8018081C82B092F10E00255C1 -:1087A0001D4DF8018081EC2FE82BF0E0E259FF4DE0 -:1087B0008081D82BD695E32FE071842F817E8E2780 -:1087C000E92FE0728E27E72FE4798E27E52FE377F4 -:1087D0008E27E22FEA738E27E82FE2958E27E82F67 -:1087E000E695E6958E27E82FE6958E278695979550 -:1087F00037954795E72FF0E0E255FF4D052F10E044 -:1088000002551E4DC081F8018081C82B022F10E057 -:1088100002551D4DF8018081EC2FE82BF0E0E25964 -:10882000FF4D8081D82BD695E52FE071872F817E73 -:108830008E27E22FE0728E27E42FE4798E27E32F34 -:10884000E3778E27E92FEA738E27E82FE2958E27AC -:10885000E82FE695E6958E27E82FE6958E278695F4 -:10886000279557957795E42FF0E0E255FF4D032FBC -:1088700010E002551E4DC081F8018081C82B092FE0 -:1088800010E002551D4DF8018081EC2FE82BF0E03F -:10889000E259FF4D8081D82BD695E72FF0E0E255C5 -:1088A000FF4D052F10E002551E4DC081F80180815B -:1088B000C82B022F10E002551D4DF8018081EC2FCE -:1088C000E82BF0E0E259FF4D8081D82BE42FE17EC8 -:1088D000832F8071E827892F8072E827872F84797A -:1088E000E827852F8377E827822F8A73E8278E2F42 -:1088F0008295E8278E2F86958695E8278E2F869578 -:10890000E827E695979537954795C92FE42FF0E02E -:10891000E255FF4D832F90E082559E4D1081FC0162 -:108920008081182B8C2F90E082559D4DFC01808119 -:10893000E12FE82BF0E0E257FF4D10818C91E82FFA -:10894000F0E0EE51FB4FE4917D01F0E8EF0EF11CF9 -:108950009E2F9127F70190838D278D9322CE7093C0 -:10896000B22C5093B32C2093B42C4093B52C30935D -:10897000B62CC093B72CDF91CF911F910F91FF9030 -:10898000EF9008950F931F93FC01862F4081518132 -:10899000628173818B0122273327803208F471C0F2 -:1089A000D80123E0B695A7952A95E1F70A271B275A -:1089B00098013695279536952795BBE0769567956E -:1089C00057954795BA95D1F70227132720E030E055 -:1089D00095E1000F111F221F331F9A95D1F7402BED -:1089E000512B622B732B8B0122273327D80133E0C5 -:1089F000B695A7953A95E1F70A271B279801369572 -:108A0000279536952795BBE07695679557954795B9 -:108A1000BA95D1F70227132720E030E095E1000F47 -:108A2000111F221F331F9A95D1F7402B512B622B18 -:108A3000732B8B0122273327D80133E0B695A795F6 -:108A40003A95E1F70A271B27980136952795369521 -:108A50002795BAE07695679557954795BA95D1F7DA -:108A60000227132720E030E096E1000F111F221F9C -:108A7000331F9A95D1F7402B512B622B732B8052C9 -:108A800089CF40835183028373831F910F9108958F -:108A9000AF92BF92CF92DF92EF92FF920F931F930C -:108AA000CF93DF936730710509F451C09B012770A4 -:108AB0003327232B09F04EC05B016C01EB0183E0EF -:108AC000D695C7958A95E1F77B0196E0F694E794F1 -:108AD0009A95E1F7EC0EFD1EEC0CFD1C8E01015089 -:108AE00011090C0D1D1DA701401B510B60E070E02A -:108AF000C80101960E944C560C151D0520F1D801A5 -:108B0000EC91F0E0EE51FB4F2491D701CD010A1713 -:108B10001B0768F4FC018081982F990F8E91881FA4 -:108B20008827881F892B11968C931197EFCF119668 -:108B30008C9111978E7FE22FE170E82B1196EC93C8 -:108B400001501109D9CFC5018C0F9D1F04C087E0CA -:108B500090E001C0CB01DF91CF911F910F91FF9069 -:108B6000EF90DF90CF90BF90AF900895CF93DF93B9 -:108B7000EC0182EC888361E070E0CE010E94BF3797 -:108B80008AE08093922D1092932D68E170E0CE01DF -:108B9000DF91CF917DCFEF92FF920F931F93CF93F1 -:108BA000DF93EC01CB0167307105E1F169E070E022 -:108BB0000E947C55DE0180E090E008E010E086171E -:108BC000970751F1FC0133E0F695E7953A95E1F707 -:108BD000E80FF91FAC0147705527EC0FFD1F2081EE -:108BE00030E0042E02C0359527950A94E2F72C93C5 -:108BF0004115510571F0E181F0E07801E41AF50AC0 -:108C0000A7017F0102C0EE0CFF1C4A95E2F72E2956 -:108C10002C9301961196D3CF23E0880F991F2A95A4 -:108C2000E1F702C087E090E0DF91CF911F910F91B3 -:108C3000FF90EF900895EF92FF920F931F93CF93C1 -:108C4000DF939C01CB016730710509F440C069E0F6 -:108C500070E00E947C5580E090E048E050E086178C -:108C60009707A9F1DC01E3E0B695A795EA95E1F74E -:108C7000A80FB91FEC01C770DD27A20FB31FEC913D -:108C8000F0E00C2E02C0F595E7950A94E2F72097E4 -:108C900059F011960C9111977A01EC1AFD0A01C056 -:108CA000000FEA94EAF7E02BF0E0EE51FB4FE4917D -:108CB0001196AC91B0E002C0B595A795CA95E2F7C0 -:108CC000ED01CE27FE01E0FD04C00196C8CF81E092 -:108CD00001C080E0DF91CF911F910F91FF90EF9045 -:108CE00008951092922D08951092922D1092B82C02 -:108CF0001092932D0895F8DF0E940E2C1092922D61 -:108D0000089508950895DC0123E633E66150E8F004 -:108D10004D91942F922780E1989FA001112449271B -:108D2000E42FF0E0232F332742954F70C9018427A9 -:108D3000AC013E2F22272427352743E0EE0FFF1FEB -:108D40004A95E1F72E273F27E1CFC9010895EF9219 -:108D5000FF921F93CF93DF93EC017B018091932DC2 -:108D6000882339F08091922D823008F0DBC0109278 -:108D7000932DE114F10461F0B701CE015CDF88238B -:108D800009F4D3C0B701CE0106DF7C0181E001C048 -:108D900082E01091922D163090F4133070F512305D -:108DA000A8F484E090E080931E2090931F2082E539 -:108DB000888382E08093922D87E090E0C7C01930CD -:108DC00008F467C01A3009F496C0ACC090E1E91607 -:108DD000F10411F480FD03C01092922D92C088819D -:108DE00099818093842D9093852D83E9888380E2F7 -:108DF000898383E08093922D6AC080FFEDCF88E263 -:108E0000E816F10448F32881898182279A8189270D -:108E10009B8189279C818913DFCFA12FB0E0139715 -:108E2000CD01880F991FA80FB91FA957B24D283837 -:108E300021F483E0FE01319602C084E0FE0101903E -:108E40000D928A95E1F745E050E0BE01CE01029611 -:108E50000E943B56133021F0143021F485E903C001 -:108E600083E901C087E9888380E7898367E070E050 -:108E7000CE010E94BF378091922D8D5F8093922DFD -:108E800068E470E0CE01DF91CF911F91FF90EF90E9 -:108E9000FFCD80FFA1CF98E1E916F10409F09CCF46 -:108EA00063E0CE0130DF009709F096CF288122FFE2 -:108EB00011C0183079F0163011F485E901C087E946 -:108EC000888380E289832EEF210F2093922D60E129 -:108ED00070E0D8CF21E02093932D212F30E0265051 -:108EE0003109322F330F230F2C5F2093912D2881CE -:108EF0002093862D2BC0982F927031F081E08093C3 -:108F0000922D0E94072C0EC080FF05C063E0CE01A9 -:108F1000FADE892B99F3CE01DF91CF911F91FF905B -:108F2000EF9024CE80E090E011C0A701495F5F4F31 -:108F300083E0569547958A95E1F7E091AE2EF09142 -:108F4000AF2EBE0181EC199580E023CFDF91CF9148 -:108F50001F91FF90EF9008959F92AF92BF92CF9292 -:108F6000DF92EF92FF920F931F93CF93DF93CDB7D2 -:108F7000DEB7C756D109CDBFDEBF8C017B01FB0137 -:108F800060817181E4DED090932DDD2009F445C12C -:108F90008091922D9AEF980F933008F057C0F80106 -:108FA00080818072C82E1092742D5DE4A52E51E14F -:108FB000B52E912C47E650E0B501CE0101960E94F6 -:108FC00004568B81882349F029813A818091842D30 -:108FD0009091852D28173907B9F48D81882329F0C0 -:108FE0009C818091862D98130FC08F89882311F062 -:108FF000CC2051F0E091742D81E08E0F8093742D80 -:10900000F0E0EB58F24D90829394F7E6AF0EB11C6E -:109010008FE09812CFCFC1100DC08091922D9AEFA2 -:10902000980F943008F0AEC02091742DE5E7FDE272 -:1090300080E08FC080EEF801808380E8818362E069 -:1090400070E0C8010E94BF3789E095C0893029F7D8 -:10905000F70160817181C801EEDDF70160817181E6 -:10906000811115C0CB01089667E070E00E947C5525 -:10907000462FE091AE2EF091AF2EB80181EC1995FC -:10908000C80174DDF70180839183D12CC9C0C80168 -:1090900082DDF70180839183F8016081262F30E023 -:1090A00043E0969587954A95E1F702972817390787 -:1090B00039F76E5FC80127DE892B11F7C12C97E6BF -:1090C000992E5801FFEFAF1ABF0A8091742DC81670 -:1090D00008F0A3CFEC2DF0E0EB58F24D6081969EA6 -:1090E000B0011124635B7E4E47E650E0CE0101964D -:1090F0000E9404568F89882349F14E8950E0F80177 -:10910000808190E001974817590741F02091742D14 -:10911000422F50E0415051093C2D08C0B501CE010D -:1091200006960E942556892B89F710C0832F90E060 -:10913000841795073CF4FC01EB58F24D8181808344 -:109140003F5FF4CF21502093742DCA94C394BDCFB8 -:109150008F5F821709F464C0919194509230C0F7E8 -:1091600082E0F801808380E6818362E070E0C801DC -:109170000E94BF378BE08093922D60E270E0C801BF -:1091800087DC80CF8B3009F04BC0F70160817181A3 -:109190006115710509F43EC0C8014DDDD82EF701F7 -:1091A00060817181811113C0CB01089667E070E086 -:1091B0000E947C55462FE091AE2EF091AF2EB80163 -:1091C00081EC19951092742DC801D0DC26C0C8011D -:1091D000E2DCF70180839183BC0183E0769567959B -:1091E0008A95E1F7C8018FDD892B19F01092742D53 -:1091F00047CFF8018581882331F0813059F480937D -:10920000742D85E004C081E08093742D84E0809308 -:10921000752D06C01092742D03C0F70180839183D1 -:109220008D2DC959DF4FCDBFDEBFDF91CF911F918B -:109230000F91FF90EF90DF90CF90BF90AF909F90F5 -:1092400008955F926F927F928F929F92AF92BF929A -:10925000CF92DF92EF92FF920F931F93CF93DF9302 -:10926000CDB7DEB7C254D240CDBFDEBF7C01CF5BED -:10927000DD4F68837983C154D2408091B82C84300B -:1092800009F48BC140F4823009F4D6C008F060C103 -:10929000813051F08CC4863009F41EC308F446C2F4 -:1092A000873009F4C8C383C40091942E1091952E81 -:1092B00001151105C1F0A801495F5F4F63E05695A4 -:1092C00047956A95E1F764E97DE2C7010E9432564D -:1092D0006091942E7091952EC701DADB1092942E36 -:1092E0001092952E21C2CF5BDD4F68817981C154E8 -:1092F000D2406115710509F4C7C0C7019CDCD82EA6 -:10930000CF5BDD4F68817981C154D240C70143DC16 -:10931000CF5BDD4F88839983C154D2409C01295F84 -:109320003F4FC901880F991F53E0969587955A952D -:10933000E1F706968138910578F064EB73E2CE018F -:1093400001960E945E561092B82CBE016F5F7F4F4F -:1093500085E60E94DE226BC4B3E036952795BA9568 -:10936000E1F7A70160E870E0CE0101960E94950E3A -:109370007C01CF5BDD4F8881C154D240CE5BDD4F95 -:109380009881C254D240CF5FDD4F9883C150D24004 -:10939000CE5FDD4F8883C250D24083EC93E29F932F -:1093A0008F9380E8A82EB12CC5018E199F099F9339 -:1093B0008F9381E090E08C0F9D1F8E0D9F1D9F93DA -:1093C0008F930E946556E80EF91EB5016E197F094C -:1093D00022E030E0AE014F5F5D4F81E090E08C0F06 -:1093E0009D1F8E0D9F1D0E94950E8E0D9F1D0F902F -:1093F0000F900F900F900F900F909501281B390B35 -:1094000041E050E04C0F5D1F840F951FD11003C049 -:1094100046EC53E202C045ED53E25F934F933F9316 -:109420002F939F938F930E9465560F900F900F90EC -:109430000F900F900F9087CF0091942E1091952E42 -:1094400001151105C1F0A801495F5F4FA3E05695D2 -:109450004795AA95E1F764E97DE2C7010E9432567B -:109460009091942E8091952E1092942E1092952E7C -:10947000092F182FDCC3CF5BDD4F28813981C15400 -:10948000D2402115310551F488E0E9E4F4E2DE012F -:10949000119601900D928A95E1F755CF295F3F4FC4 -:1094A000E3E036952795EA95E1F7A70160E870E0DB -:1094B000CE0101960E94950E7C01CF5BDD4F888125 -:1094C000C154D240CE5BDD4F9881C254D240CF5FB1 -:1094D000DD4F9883C150D240CE5FDD4F8883C250AC -:1094E000D24083EC93E29F938F93F0E8CF2ED12C60 -:1094F000C6018E199F099F938F9381E090E08C0F96 -:109500009D1F8E0D9F1D9F938F930E9465568E0DFC -:109510009F1DB601681B790B22E030E0AE014F5F62 -:109520005D4FA1E0B0E0AC0FBD1F8A0F9B1F0E94F2 -:10953000950E1092B82CBE016F5F7F4F85E60E949A -:10954000DE220F900F900F900F900F900F906FC32F -:10955000CF5BDD4F68817981C154D240C701F7DB11 -:109560002091932D222309F425C32091912D30E0E1 -:1095700047E85DE264E170E0CE0101960E94950E3D -:10958000BE016F5F7F4F85E60E94DE221092932D11 -:109590001092B82C0E9474230AC38091732D8111FC -:1095A00008C080E890E00E94C12381E08093732D81 -:1095B0007BC0813009F07AC08091922D823008F012 -:1095C00075C08091722D8F5F8093722D803109F06C -:1095D0006DC00E94CC238C019350409768F0011518 -:1095E000B8E01B0708F460C0E0E1F0E020E030E004 -:1095F000A12CB12C60E040C0AAEFBCE240E050E0FA -:1096000020E030E080E090E0E0E0F0E060E07D919C -:10961000703149F44732510509F405C361110EC098 -:10962000FA0161E00BC0662349F0BA016E1B7F0BA3 -:109630006817790710F09F01CB0160E04F5F5F4F23 -:109640004832510521F78430910508F03BC22CC007 -:10965000D601ED906D01F12CEE16FF06B0F461110C -:1096600019C04F5F5F4F4837510591F7009709F0D8 -:1096700029C2319709F426C27AEFC72E7CE2D72E91 -:1096800040E050E080E090E0E3CF6111EACF5A0182 -:1096900061E0E7CFBA016A197B096817790710F012 -:1096A0009501CB0160E0DDCF1092722DCF5BDD4FD5 -:1096B00068817981C154D240C70149DB2091932D43 -:1096C000222309F477C2E091B12EF091B22E0284E8 -:1096D000F385E02DE058F10954E0F695E7955A95A9 -:1096E000E1F7E650F34D80818F5F80838091722D8A -:1096F000803121F40E94CC231092722D1092922D71 -:109700000E94072C80E5F7018083118262E070E0FF -:10971000C7010E94BF3781E08093922D1092932D54 -:1097200060E270E0C701B4D98C0181C2CF5BDD4F2C -:1097300068817981C154D240C70109DB2091932D02 -:10974000222309F437C2D090F92CDD2009F445C05A -:10975000CF5BDD4F08811981C154D240011511053D -:1097600049F41092F92C1092932D1092922D0E9490 -:10977000072C5DC2023A110538F0B801C7015BDA67 -:1097800001E08027082F02C001E010E0CF5BDD4F31 -:1097900068817981C154D240C701FDD9CF5BDD4FCB -:1097A00088839983C154D24000FD05C062E1C7019E -:1097B000AADA892B29F0ACEFAD0DA093F92C2AC0C1 -:1097C000F4E0DF9ED0011124A755B34D80E1F701ED -:1097D00001900D928A95E1F71DC042E050E062E8E9 -:1097E00072E1CE0101960E940456E5E8F2E1E491AF -:1097F0002091842D3091852D89819A8128173907F0 -:1098000021F48091862DE81729F01092922D0E9464 -:10981000072CCDC18091F92C803109F04DC01092F8 -:10982000932D1092F92C1092B82C20E130E049EBE6 -:109830005CE267E870E0CE0101960E94950E63EC51 -:1098400073E2CE0181960E945E5620E130E049EC41 -:109850005CE265E670E0CE0183960E94950E63ECB3 -:1098600073E2CE018D5B9F4F0E945E5620E130E097 -:1098700049ED5CE263E470E0CE018B5B9F4F0E9498 -:10988000950E63EC73E2CE018B599F4F0E945E569A -:1098900020E130E049EE5CE261E270E0CE018959FE -:1098A0009F4F0E94950E0E947423BE016F5F7F4FF1 -:1098B00085E60E94DE227BC190E3D7019C9311963E -:1098C0008C9362E070E0C7010E94BF378091F92C51 -:1098D0008C5F8093F92C24CFBE016F5B7D4FC70155 -:1098E0003BDB882309F4E7C08091742D811103C00C -:1098F0006BEE73E227C08130A1F0912C80E090E004 -:1099000000E010E027E6822E7E01BFEFEB1ABDEFEC -:10991000FB0A3EEFC32E33E2D32EA12C42E0B42E3D -:1099200040C06091752DE7E66E9FB00111246C5820 -:109930007E4E40E450E0CE0101960E940456BE01E6 -:109940006F5F7F4F85E60E94DE2255C00130F2E056 -:109950001F0760F5E92DF0E0EB58F24D6081869E1F -:10996000B00111246C587E4E40E450E0C7010E94C3 -:109970000456FF92EF92DF92CF92C501801B910BAC -:109980009F938F9381E090E08C0F9D1F800F911F1C -:109990009F938F930E946556080F191F9394CDBF14 -:1099A000DEBF2091742D921688F204C0081B190B9B -:1099B000F12C06C0013032E01307C0F7FF24F39406 -:1099C000EDEFFFEFEC0FFD1FE00FF11F8EE2808344 -:1099D000EEEFFFEFEC0FFD1FE00FF11F1082BE0155 -:1099E0006F5F7F4F85E60E94DE22F11004C088EE93 -:1099F00090E10E942D1981EE90E10E942D1962E004 -:109A000070E084E89DE20E94FC228BED90E10E94D0 -:109A10002D196091912D70E087E89DE20E94FC2253 -:109A200085ED90E10E942D1961E070E086E89DE2ED -:109A30000E94FC2237C0BE016F5B7D4FC7018CDAEC -:109A40008823C9F18091742D813039F58091752D6D -:109A5000833009F4BDC028F4813059F0823099F088 -:109A6000DFC08A3031F008F4DBC08D50823058F00E -:109A7000D7C08091912D843009F4ACC0873009F0B3 -:109A8000CFC015E0AAC08091912D843009F4A4C004 -:109A9000873009F0C5C017E0A0C065E074E285E634 -:109AA0000E94DE221092B82C1092742D0E94742312 -:109AB0001092932D7CC0CF5BDD4F08811981C1547A -:109AC000D240B5C01092732D009709F475C09695D9 -:109AD0008795285F3F4F820F931F54E0880F991F8F -:109AE0005A95E1F70E94C123E091B12EF091B22E78 -:109AF00062857385CF01865A9E428F5F9F4F0E9479 -:109B0000DC5C60E070E085E60E94DE220115184012 -:109B100008F455C0B8E7AB2EB12C0AEF1CE260E8A0 -:109B2000E62EF12C71EE672E73E2772EEAE05E2EC0 -:109B3000FE0131966F01F7EE8F2EF3E29F2EFF921A -:109B4000EF927F926F921F925F92DF92CF920E946C -:109B50006556C6010E942819D8018C91CDBFDEBF81 -:109B6000882389F11F928F939F928F921F925F9209 -:109B7000DF92CF920E946556C6010E942819CDBF80 -:109B8000DEBF8AE491E10E942D19D8011D928D015A -:109B9000B0E1EB0EF11CC8018A5F9C428A159B055F -:109BA00070F21092932D1092B82C0E940E2C00E0AF -:109BB00010E03DC08C013BC00E94DC2395CFA8E2A1 -:109BC000AA2EB12CAACF6DE283E090E21FD6D9CFA6 -:109BD00011E003C014E001C016E06BE274E285E618 -:109BE0000E94DE22812F0E94F80DE0919E2EF091BE -:109BF0009F2E1995E091A82EF091A92E87E89DE25D -:109C00001995E091AE2EF091AF2E4091AC2E67E801 -:109C10007DE283E119950E948B100E940D1742CFBF -:109C200066E374E23CCF662309F40DCDFECCC80197 -:109C3000CE5BDD4FCDBFDEBFDF91CF911F910F9186 -:109C4000FF90EF90DF90CF90BF90AF909F908F905C -:109C50007F906F905F9008950F931F93CF93DF9342 -:109C6000CDB7DEB7EA97CDBFDEBF08E112E395D2EC -:109C7000F80181938F01F2E300321F07C1F70E94C0 -:109C8000DD1906D3882309F4FAC080911832909127 -:109C90001932953009F46FC030F4913069F168F0F1 -:109CA000933051F1ECC0983009F4C2C0993009F4F6 -:109CB000C8C0963009F0E3C072C0803891F0823895 -:109CC00009F0DDC080911C328F7087D2E091223282 -:109CD000F0912332118112FB112710F980E07DD21F -:109CE00006C0109114328091153281111260EAD2AF -:109CF000812F63D280E0A1C0282F2D7F09F0BFC043 -:109D0000882319F0823061F0BAC080911A32813014 -:109D100009F0B5C0933009F080E08093153227C078 -:109D200080911A32811123C0E0911C321E2F1F70C6 -:109D300009F4A5C0812F51D280911932833011F4DA -:109D4000EDD215C0E0912232F091233281818B7FD8 -:109D5000818324E8129FF0011124EA59FD4C1082FE -:109D6000E0912232F091233280818E7F808380E0E7 -:109D700034D2A8D264C0811182C010911A321F77E8 -:109D8000A1D28FD35FD28823E9F31093C3041111BA -:109D900002C082E001C083E08093173270C0805817 -:109DA000823008F06CC080911A3290911B328C3D49 -:109DB000E3E09E0761F583E08A838AE389834FB7F6 -:109DC000F894DE01139620E038E052E05093CA0187 -:109DD000E32FF0E0E4911092CA0120FF03C0E29566 -:109DE000EF703F5FEF708E2F90E0EA3010F0C79673 -:109DF00001C0C0968D939D932F5F2C3139F74FBFD3 -:109E000061D26AE370E0CE010196A5D00FC0AE0129 -:109E10004F5F5F4F60911C320E94090D8C01892BAE -:109E200071F150D2B80189819A8111D1A7D127C08F -:109E3000803829F547D280911332BFD186D131D3F2 -:109E40001EC081111CC080911A3290911B3299273B -:109E50000297ACF437D280911A328093133221D317 -:109E600080911332811106C08091C304811102C018 -:109E700081E001C084E0809317320E94D91908D292 -:109E8000882311F01FD24AD2EA96CDBFDEBFDF9100 -:109E9000CF911F910F9108950895CF93809117321C -:109EA000882351F0C091243280E097D1F1D1811103 -:109EB000D3DE8C2FCF9191C1CF910895CF92DF92B5 -:109EC000EF92FF920F931F93CF93DF93EC018B01DF -:109ED0007A01FDD2811136C0E114F10439F0F701A5 -:109EE00080819181081B190BC80FD91FC12CD12C5F -:109EF0000115110531F18091203290912132FC0140 -:109F0000EF5BFF4F208131978081281790F01DD1A2 -:109F1000C4DFE114F10449F0F70180819181C80E9A -:109F2000D91EC082D18285E00DC0D1D2882301F331 -:109F300009C0899142D101501109FFEFCF1ADF0A00 -:109F4000D7CF80E0DF91CF911F910F91FF90EF90DD -:109F5000DF90CF900895DF92EF92FF920F931F93BF -:109F6000CF93DF93D82FC92F8B0180912432806843 -:109F700034D180911E3290911F328017910728F0C2 -:109F80000115110519F4E1D001C08C01ED2EFC2E54 -:109F9000D12C0115110509F440C0809117328111AF -:109FA00002C082E04CC0853011F483E048C070D11B -:109FB000882311F081E043C051D181113CC042D1CE -:109FC000882339F3209124328091203290912132DC -:109FD000FC0127FF05C0EF5BFF4FC081D0E013C03D -:109FE000E05CFF4FC08131968081D0E0C81BD10971 -:109FF0000AC0C830D10550F4F70181917F01DDD04E -:10A000000150110921960115110599F7DD24D3940A -:10A01000289709F0D12C99D0BCCFD110BECF0BC05E -:10A0200080911732882309F4BCCF853009F4BDCF65 -:10A030002FD18111BFCF12D1882391F380E0DF911E -:10A04000CF911F910F91FF90EF90DF900895DF92D5 -:10A05000EF92FF920F931F93CF93DF93D82FC92FC7 -:10A060008B01809124328068B8D080911E3290910B -:10A070001F328017910728F00115110519F465D0DA -:10A0800001C08C01ED2EFC2ED12C0115110509F417 -:10A0900042C080911732811102C082E04EC08530EB -:10A0A00011F483E04AC0F4D0882311F081E045C068 -:10A0B000D5D081113EC0C6D0882339F320912432F7 -:10A0C0008091203290912132FC0127FF05C0EF5B87 -:10A0D000FF4FC081D0E015C0E05CFF4FC0813196DA -:10A0E0008081D0E0C81BD1090CC0C830D10560F414 -:10A0F000F701849162D0FFEFEF1AFF0A01501109B6 -:10A1000021960115110589F7DD24D394289709F0CC -:10A11000D12C1BD0BACFD110BCCF0BC0809117323D -:10A12000882309F4BACF853009F4BBCFB1D08111AF -:10A13000BDCF94D0882391F380E0DF91CF911F9120 -:10A140000F91FF90EF90DF900895E0912232F0910F -:10A150002332A0912032B0912132AF5BBF4F8C915E -:10A1600090E08283938380818D798083E091203297 -:10A17000F0912132EF5BFF4F10820895E09122327F -:10A18000F091233280818D798083E0912032F091AB -:10A190002132EF5BFF4F1082089580912032909121 -:10A1A0002132FC01EF5BFF4F208131E0320F308321 -:10A1B000FC01E20FF11D8081089520912032309141 -:10A1C0002132F901EF5BFF4F908141E0490F40835D -:10A1D000F901E90FF11D8083089580932432482FFF -:10A1E0004F7050E06091C6047091C7049A0194E0EA -:10A1F000220F331F9A95E1F7E4E887FF11C0E49F2F -:10A20000C001E59F900D112489599D4C8093203207 -:10A2100090932132C90108969B01280F391F0DC068 -:10A22000E49FC001E59F900D11248B5D9D4C8093B0 -:10A23000203290932132260F371F20932232309301 -:10A2400023320895809124328068C7DFE091223262 -:10A25000F091233280818695817008958091243217 -:10A260008F77BBDFA0912232B09123328C9185FF92 -:10A270000DC0E0912032F091213212968D919C9187 -:10A280001397E05CFF4F808381E0089580E008959C -:10A29000809124328F77A1DFA0912232B0912332B6 -:10A2A0008C9184FF0DC0E0912032F0912132129602 -:10A2B0008D919C911397E05CFF4F808381E008951E -:10A2C00080E00895809124328F7787DFE0912232F9 -:10A2D000F091233280818D788083E0912232F09159 -:10A2E0002332808181608083E0912032F09121329D -:10A2F000EF5BFF4F10828091243280686EDFE09127 -:10A300002232F0912332808181608083E09120327B -:10A31000F0912132EF5BFF4F10820895E0912232DD -:10A32000F0912332818184608183E0912232F09127 -:10A3300023328181807C803459F48091243280588A -:10A340004CDFE0912232F09123328181846081835D -:10A3500008951F93CF93DF93C82F162FD42F3DDF7F -:10A36000E0912232F09123321182E0912232F09179 -:10A3700023328C2F881F8827881F880F8083E091C5 -:10A380002232F09123321183E0912232F091233274 -:10A39000128213822091203230912132248335831E -:10A3A000CC0FCC0BCD23F901E05CFF4FC08331967D -:10A3B000108281E0DF91CF911F910895CF92DF92BB -:10A3C000EF92FF920F931F93CF93DF93C62E8C01D2 -:10A3D000D12CDC1409F43FC0F801D081D11104C0A4 -:10A3E000D3940B5F1F4FF5CFF801E180F28093818A -:10A3F0008481823010F488E001C088E128E030E0F8 -:10A40000C0E02E153F0520F4CF5F220F331FF9CF98 -:10A41000C82B8D2F8F70863010F080E01DC0CF7E4E -:10A42000F1E4EF16F104C8F7992321F0913021F4FB -:10A43000C06C0AC0C06403C0C068911105C04E2D35 -:10A440006C2F80E88D0F85DF4E2D6C2F8D2F81DFD7 -:10A450008111C6CFE2CF81E0DF91CF911F910F91A3 -:10A46000FF90EF90DF90CF90089580E090E0E09132 -:10A47000C604F091C7049C0144E0220F331F4A95A3 -:10A48000E1F7E20FF31F11864091C6045091C70413 -:10A49000FA01E20FF31F118201968630910539F718 -:10A4A00008958091183287FF0DC0D8DE811105C054 -:10A4B000809117328111F9CF09C060CE8091173297 -:10A4C000882321F0BFDE8823C9F33FCE08950F9380 -:10A4D0001F93CF93E091C604F091C704E05AFF4F59 -:10A4E00000811181C4E68091243287FF0AC0AADE70 -:10A4F000811105C080911732811105C022C080E012 -:10A5000025C0ACDEF5CF8530F1F0E0912232F0913C -:10A510002332818182FD19C0E091C604F091C70405 -:10A52000E05AFF4F808191810817190711F48C01BF -:10A53000DACF2FEF2C0FCC2311F0C22FF8CF84E00D -:10A5400005C082E003C083E001C081E0CF911F918C -:10A550000F91089563D069D0E0ECF4E081818E7FA3 -:10A56000818380818F778083109216320895CF93F4 -:10A57000DF93E0E4F0E014828481836084834ED032 -:10A5800054D0C0ECD4E088818F778883888180683C -:10A590008883109217321092133210921532109253 -:10A5A000143288818064888348E068E480E8D1DEE2 -:10A5B00048E068E480E0CDDE888580648887898112 -:10A5C00081608983DF91CF910895CF93DF933FB767 -:10A5D000F894C0ECD1E022E02A87EAE1F0E0E491CF -:10A5E000A0ECB4E0DA96EC93DA97EBE1F0E0E491DA -:10A5F000DB96EC93DB971A868EE395E38E7F1696B7 -:10A600008D939C93179785E18C9318962C933FBF5D -:10A6100081E080931632DF91CF91A9CFE0ECF4E096 -:10A6200080858370808711860895E0ECF4E08FEFD9 -:10A630008287848708951F920F920FB60F9211247C -:10A6400008B60F9218BE09B60F9219BE0BB60F923C -:10A650001BBE2F933F934F935F936F937F938F9383 -:10A660009F93AF93BF93EF93FF938091CA0487FFAB -:10A6700008C08091C80487FF04C080E88093CA04A2 -:10A680000BDC8091CA0486FF07C080E48093CA0473 -:10A69000109217320E94C8198091CA0485FF14C015 -:10A6A00080E28093CA0480911332882311F084E001 -:10A6B00007C08091C304811102C081E001C083E022 -:10A6C000809317320E94B7198091CA0484FF14C086 -:10A6D00080E18093CA0482E0809317321092133293 -:10A6E0001092C304C2DE48E068E480E832DE48E04D -:10A6F00068E480E02EDED0DBFF91EF91BF91AF9157 -:10A700009F918F917F916F915F914F913F912F9189 -:10A710000F900BBE0F9009BE0F9008BE0F900FBE9A -:10A720000F901F901895CF93DF93EC01FC0170966A -:10A730008BE0DF011D928A95E9F782E08C8389879F -:10A7400083E08E8761E0CE01019638DE882361F0D8 -:10A7500061E0CE01069632DE882331F061E0CE0161 -:10A760000B96DF91CF912ACE80E0DF91CF910895B3 -:10A770000F931F93CF93DF93209117322430E1F48E -:10A78000FC010489158926893789012B022B032BAB -:10A7900099F0EB01818121DDFE0101900020E9F7B4 -:10A7A0003197BF016C1B7D0B40E050E0CE01DF9183 -:10A7B000CF911F910F9182CB82E0DF91CF911F91BA -:10A7C0000F9108950F931F93CF93DF93209117322A -:10A7D0002430B1F4FC010489158926893789012BBD -:10A7E000022B032B69F08A01EB018181F6DC40E04A -:10A7F00050E0B801CE01DF91CF911F910F915ECB58 -:10A8000082E0DF91CF911F910F9108950F931F93D5 -:10A81000CF9320911732243009F5FC010489158962 -:10A8200026893789012B022B032BC1F0C62F81818A -:10A83000D4DC8091203290912132FC01EF5BFF4FFC -:10A84000208131978081281720F48C2FB6DC80E09E -:10A8500006C07BDC3CDE8823C1F301C082E0CF91DF -:10A860001F910F910895CF93DF93209117322430D9 -:10A8700091F5FC014489558966897789452B462BDA -:10A88000472B49F18181A9DC80912432209120322B -:10A8900030912132F90187FF05C0EF5BFF4F8081C6 -:10A8A00090E008C0E05CFF4F80813196408190E0ED -:10A8B000841B9109892B69F0F901EF5BFF4FD0816F -:10A8C0003197C08142DCDC1720F001DE811104C029 -:10A8D0003CDC80E001C082E0DF91CF910895CF930E -:10A8E000DF9320911732243099F4FC014489558973 -:10A8F00066897789452B462B472B51F0EC018181E6 -:10A900006CDCA0DC882321F0CE01DF91CF91ABCFAE -:10A91000DF91CF910895CF93DF93209117322430A8 -:10A9200019F08FEF9FEF46C0FC0144895589668975 -:10A930007789452B462B472BA1F386814EDC8EDC95 -:10A94000882379F380912432209120323091213272 -:10A95000F90187FF05C0EF5BFF4F808190E008C0E1 -:10A96000E05CFF4F80813196208190E0821B91094D -:10A97000892B21F012DCC82FD0E002C0CFEFDFEF2F -:10A98000209124328091203290912132FC0127FFC6 -:10A9900005C0EF5BFF4F208130E008C0E05CFF4F57 -:10A9A00020813196808130E0281B3109232B09F466 -:10A9B000E5DBCE01DF91CF9108950895FF920F93CB -:10A9C0001F93CF93DF93EC0163DC882309F48EC0DF -:10A9D000888190E020911C3230911D322817390770 -:10A9E00009F084C080911932813259F018F4803214 -:10A9F00049F17CC0823209F457C0833209F467C040 -:10AA000075C080911832813A09F070C05BDC1ADCA5 -:10AA10008823E9F38C89FD880E891F89CEDB8F2D71 -:10AA2000CCDB802FCADB812FC8DB888DC6DB898D0C -:10AA3000C4DB8A8DC2DB89DBDF91CF911F910F913F -:10AA4000FF902FCD80911832813209F04FC03ADC4F -:10AA500005DC811105C0809117328111F9CF46C004 -:10AA60009CDBF82E9ADB182F98DB082F96DB402F03 -:10AA700050E060E070E0BA0155274427782B4F2959 -:10AA8000512B4C8B5D8B6E8B7F8B87DB888F85DBAF -:10AA9000898F83DB8A8F72DB04DDCE01DF91CF915A -:10AAA0001F910F91FF9089CF809118328132F1F47C -:10AAB00009DCF7DC80911A3290911B32888B998BDC -:10AAC000CE01DF91CF911F910F91FF9076CF8091B2 -:10AAD0001832813259F4F6DBE4DC60911A32CE018F -:10AAE000DF91CF911F910F91FF9067CFDF91CF91B1 -:10AAF0001F910F91FF900895AA1BBB1B51E107C046 -:10AB0000AA1FBB1FA617B70710F0A61BB70B881FFD -:10AB1000991F5A95A9F780959095BC01CD0108958C -:10AB2000B7FF04C003D0821B930B089509D0A59FE3 -:10AB3000900DB49F900DA49F800D911D1124089538 -:10AB4000A29FB001B39FC001A39F700D811D11246E -:10AB5000911DB29F700D811D1124911D08958F923A -:10AB60009F92AF92BF92CF92DF92EF92FF92CF93DC -:10AB7000DF93EC01688179818A819B816115710580 -:10AB80008105910521F464E279ED8BE597E02DE1F3 -:10AB900033EF41E050E037D749015A019B01AC0146 -:10ABA000A7EAB1E4C3DF6B017C01ACEEB4EFA50111 -:10ABB0009401B8DFDC01CB018C0D9D1DAE1DBF1DC6 -:10ABC000B7FF03C00197A109B04888839983AA837E -:10ABD000BB839F77DF91CF91FF90EF90DF90CF9075 -:10ABE000BF90AF909F908F900895B9CF80E290E290 -:10ABF000B6CFA0E0B0E08093202090932120A093D6 -:10AC00002220B09323200895FB01DC0102C00590AF -:10AC10000D9241505040D8F70895FB01DC018D9111 -:10AC2000059080190110D9F3990B0895FB01DC01FF -:10AC30004150504048F005900D920020C9F701C0E6 -:10AC40001D9241505040E0F70895FB01DC0104C023 -:10AC50008D910190801921F441505040C8F7881B14 -:10AC6000990B0895FB01DC0102C001900D92415047 -:10AC70005040D8F708956817790768F4FB01DC01A4 -:10AC8000E40FF51FA40FB51F02C002900E924150B1 -:10AC90005040D8F70895E6CFDC0101C06D934150D4 -:10ACA0005040E0F70895FC018191861721F0882338 -:10ACB000D9F7992708953197CF010895FB01DC0159 -:10ACC00001900D920020E1F708950F931F93CF9309 -:10ACD000DF93CDB7DEB72E97CDBFDEBF0E891F89BC -:10ACE000888D998D26E02C8309831A8397FF02C0F3 -:10ACF00080E090E801978D839E83AE01445E5F4FB4 -:10AD00006A8D7B8DCE01019667D04D815E8157FDA6 -:10AD10000AC02F813885421753070CF49A01F801B5 -:10AD2000E20FF31F10822E96CDBFDEBFDF91CF91D1 -:10AD30001F910F9108950F931F93CF93DF93CDB77A -:10AD4000DEB72E97CDBFDEBF0E891F89888D998D06 -:10AD50002EE02C8309831A8397FF02C080E090E8DD -:10AD600001978D839E83AE01445E5F4F6A8D7B8D1C -:10AD7000CE01019631D04D815E8157FD0AC02F81F1 -:10AD80003885421753070CF49A01F801E20FF31FBC -:10AD900010822E96CDBFDEBFDF91CF911F910F9114 -:10ADA0000895CF93DF93CDB7DEB72E97CDBFDEBF2B -:10ADB0008DE08C838C899D8989839A83AE01485E5E -:10ADC0005F4F6E897F89CE010196A9D32E96CDBFA4 -:10ADD000DEBFDF91CF9108952F923F924F925F9205 -:10ADE0006F927F928F929F92AF92BF92CF92DF929B -:10ADF000EF92FF920F931F93CF93DF93CDB7DEB700 -:10AE00002B97CDBFDEBF6C017B018A01FC0116824E -:10AE10001782838181FFBFC1CE0101963C01F601FB -:10AE20009381F70193FD859193FF81917F018823A1 -:10AE300009F4ADC1853239F493FD859193FF819179 -:10AE40007F01853221F4B60190E0E7D4E8CF912C60 -:10AE5000212C312CFFE1F315D8F08B3279F038F446 -:10AE6000803279F08332A1F4232D20611DC08D3210 -:10AE700061F0803369F4232D216016C0832D826038 -:10AE8000382EE32DE4603E2E2AC0F32DF8601DC05D -:10AE900037FC2DC020ED280F2A3040F08E32B9F457 -:10AEA00036FC75C1232D2064322E19C036FE06C033 -:10AEB0008AE0989E200D1124922E11C0EAE02E9E69 -:10AEC000200D1124222EF32DF0623F2E08C08C3667 -:10AED00021F4832D8068382E02C0883641F4F701B2 -:10AEE00093FD859193FF81917F018111B3CF982FBD -:10AEF0009F7D9554933028F40C5F1F4F9FE39983F7 -:10AF00000DC0833631F0833771F0833509F055C0B9 -:10AF100020C0F801808189830E5F1F4F88248394AD -:10AF2000912C530112C02801F2E04F0E511CF80180 -:10AF3000A080B18036FE03C0692D70E002C06FEFC3 -:10AF40007FEFC50121D44C018201F32DFF773F2E05 -:10AF500015C0280122E0420E511CF801A080B180EA -:10AF600036FE03C0692D70E002C06FEF7FEFC501B0 -:10AF700000D44C01F32DF0683F2E820133FC19C040 -:10AF8000822D90E088169906A0F4B60180E290E048 -:10AF900044D42A94F5CFF50137FC859137FE819191 -:10AFA0005F01B60190E039D421102A9421E0821A81 -:10AFB00091088114910479F7E1C0843611F0893643 -:10AFC00039F5F80137FE07C0608171818281938174 -:10AFD0000C5F1F4F08C060817181072E000C880B29 -:10AFE000990B0E5F1F4FF32DFF763F2E97FF09C081 -:10AFF00090958095709561957F4F8F4F9F4FF0682A -:10B000003F2E2AE030E0A3015DD4882E861844C08C -:10B01000853731F4232D2F7EB22E2AE030E025C073 -:10B02000932D997FB92E8F36C1F018F4883579F0B9 -:10B03000AEC0803719F0883721F0A9C0E92FE06150 -:10B04000BE2EB4FE0DC0FB2DF460BF2E09C034FE31 -:10B050000AC0292F2660B22E06C028E030E005C0C5 -:10B0600020E130E002C020E132E0F801B7FE07C085 -:10B0700060817181828193810C5F1F4F06C0608166 -:10B08000718180E090E00E5F1F4FA3011BD4882EDA -:10B090008618FB2DFF773F2E36FE0DC0232D2E7F09 -:10B0A000A22E891458F434FE0BC032FC09C0832D43 -:10B0B0008E7EA82E05C0B82CA32C03C0B82C01C0CE -:10B0C000B92CA4FE0FC0FE01E80DF11D8081803374 -:10B0D00021F49A2D997EA92E09C0A2FE06C0B39430 -:10B0E000B39404C08A2D867809F0B394A3FC10C0F1 -:10B0F000A0FE06C0B21480F4280C922C9B180DC040 -:10B10000B21458F4B60180E290E087D3B394F8CF3C -:10B11000B21418F42B1802C0982C212CA4FE0FC0D6 -:10B12000B60180E390E079D3A2FE16C0A1FC03C073 -:10B1300088E790E002C088E590E0B6010CC08A2D57 -:10B14000867851F0A1FE02C08BE201C080E2A7FC2C -:10B150008DE2B60190E061D3891430F4B60180E34A -:10B1600090E05BD39A94F8CF8A94F301E80DF11D37 -:10B170008081B60190E051D38110F6CF222009F4EE -:10B180004ECEB60180E290E048D32A94F7CFF60184 -:10B190008681978102C08FEF9FEF2B96CDBFDEBFD8 -:10B1A000DF91CF911F910F91FF90EF90DF90CF90A3 -:10B1B000BF90AF909F908F907F906F905F904F90D7 -:10B1C0003F902F90089520FD09C0FC0123FD05C08C -:10B1D00022FF02C07383628351834083089544FD3C -:10B1E00017C046FD17C0AB01BC01DA01FB01AA0F75 -:10B1F000BB1FEE1FFF1F1094D1F74A0F5B1F6E1F7E -:10B200007F1FCB01BA01660F771F881F991F09C0E6 -:10B2100033E001C034E0660F771F881F991F31505B -:10B22000D1F7620F711D811D911D08950F931F931A -:10B23000CF93DF938C01C801B2D2EC0197FD06C019 -:10B2400085D2892BC1F7B801CE0123D3CE01DF917E -:10B25000CF911F910F9108958F929F92AF92BF92BD -:10B26000EF92FF920F931F93CF93DF938C01D62F12 -:10B270007A01B22E94D29C0133272B32310531F062 -:10B280002D32310559F48B2D8068B82ED15011F430 -:10B2900080E061C0C80183D297FDFACFCB2DCD7F6E -:10B2A0002B2D2073F9F48033E9F4AA24AA94AD0E6F -:10B2B00009F43EC0C80173D297FD3AC09C012F7DAE -:10B2C00033272835310541F4C264D25089F1C801D1 -:10B2D00066D297FF07C02CC0B6FE02C0C26001C094 -:10B2E000C261DA2D812C912C540120ED280F2830D9 -:10B2F00078F0C4FF03C0B801CCD217C02A3040F0A8 -:10B30000C6FFF9CF2F7D3FEE320F3630A0F7275022 -:10B310004C2FC501B40163DF4B015C01C260D15009 -:10B3200051F0C8013CD297FFE0CFC1FD04C0B0CFBF -:10B33000812C912C5401C7FF08C0B094A094909424 -:10B340008094811C911CA11CB11C2C2FB501A4015F -:10B35000C70139DF81E0DF91CF911F910F91FF90FD -:10B36000EF90BF90AF909F908F9008955F926F92F3 -:10B370007F928F929F92AF92BF92CF92DF92EF9285 -:10B38000FF920F931F93CF93DF93CDB7DEB7A097B4 -:10B39000CDBFDEBF5C01962E7A01F9018E010F5FF1 -:10B3A0001F4F680180E2D8011D928A95E9F7D50107 -:10B3B00013968C9080E090E0612C712C30E061E07D -:10B3C00070E083FC259183FE21918F01522E211183 -:10B3D00003C080E090E090C02E3511F4009751F149 -:10B3E000432F50E0481759073CF42D3559F12D32C1 -:10B3F00019F4772009F103C0772009F468C0452DBE -:10B40000469546954695D601A40FB11D452D47702A -:10B410008B0102C0000F111F4A95E2F7A8015C9151 -:10B42000452B4C93651459F0561410F45394E7CF00 -:10B430005A94E5CF31E004C07724739401C0712C95 -:10B440000196BFCF772019F08E8180628E833111F3 -:10B4500003C08824839417C0F6019E012F5D3F4FDF -:10B460008081809581932E173F07D1F7F2CFE114A9 -:10B47000F10429F0D7018C93F70131967F019A945A -:10B48000812C9920E9F0C5018AD197FD17C0FC01F4 -:10B49000FF2723E0F595E7952A95E1F7EC0DFD1DD3 -:10B4A000208130E0AC014770552702C035952795C3 -:10B4B0004A95E2F720FDDBCFB501EBD1811089CFB2 -:10B4C000E114F10411F0D7011C92C80115C0422FFC -:10B4D000469546954695D601A40FB11D422F47705B -:10B4E0008B0102C0000F111F4A95E2F7A8015C9181 -:10B4F000452B4C93622EA4CFA096CDBFDEBFDF912B -:10B50000CF911F910F91FF90EF90DF90CF90BF9060 -:10B51000AF909F908F907F906F905F9008955F9213 -:10B520006F927F928F929F92AF92BF92CF92DF9253 -:10B53000EF92FF920F931F93CF93DF936C01EB0178 -:10B540005A01FC0116821782512CF601E380FE019C -:10B55000E3FC8591E3FE8191182FEF01882309F424 -:10B56000E0C090E0F3D0892B19F0C6015FDEEDCF8B -:10B57000153241F4FE01E3FC1591E3FE1191EF0158 -:10B58000153271F4C6010BD197FDC9C0412F50E0AF -:10B590009C01332724173507C1F2B6017AD1C1C007 -:10B5A0001A3239F4E3FC1591E3FE1191EF0101E049 -:10B5B00001C000E0F12C20ED210F2A3078F4026068 -:10B5C0006F2D70E080E090E040E209DEF62EFE0193 -:10B5D000E3FC1591E3FE1191EF01EDCF01FF03C0F4 -:10B5E000F11003C09EC0FF24FA94183619F01C36DF -:10B5F00051F010C0FE01E3FC1591E3FE1191EF0143 -:10B60000183641F408600460FE01E3FC1591E3FE86 -:10B610001191EF01112309F484C0612F70E08CEFC8 -:10B6200091E09CD0892B09F47CC000FD07C0F50196 -:10B6300080809180C50102965C0102C0812C912C12 -:10B640001E3649F4F6014681578160E070E0202FF4 -:10B65000C401B9DD7ACF1336A1F401FD02C0FF2485 -:10B66000F394C6019CD097FD5AC08114910429F02F -:10B67000F4018083C40101964C01FA94F110F1CFDA -:10B680004AC01B3551F49E01A4016F2DC6016EDE28 -:10B69000EC01892B09F03FC039C0C601C7DD97FD19 -:10B6A0003EC01F3649F128F4143621F1193639F11C -:10B6B00025C0133771F01537E9F020C081149104CB -:10B6C00029F0F4016082C40101964C01FA94FF2034 -:10B6D00059F0C60164D03C0197FD06C037D0892BD4 -:10B6E00069F3B601C301D5D081149104A1F0F4012E -:10B6F000108211C0006203C0006101C00064202FED -:10B70000A4016F2DC601A8DD811105C0F60183815A -:10B71000807329F406C000FD18CF539416CF55202E -:10B7200019F0852D90E002C08FEF9FEFDF91CF9150 -:10B730001F910F91FF90EF90DF90CF90BF90AF904F -:10B740009F908F907F906F905F900895911118C196 -:10B75000803219F089508550D0F70895FC0105908A -:10B76000061621F00020D9F7C00108953197CF01C6 -:10B770000895FC010590615070400110D8F7809544 -:10B7800090958E0F9F1F0895FC01615070400190AD -:10B790000110D8F7809590958E0F9F1F0895CF9335 -:10B7A000DF93EC012B8120FF33C026FF0AC02F7BE3 -:10B7B0002B838E819F8101968E839F838A8190E067 -:10B7C00029C022FF0FC0E881F9818081082E000C7A -:10B7D000990B009719F420622B831AC03196E883E5 -:10B7E000F9830EC0EA85FB85199597FF09C02B8167 -:10B7F000019611F080E201C080E1822B8B8308C0AA -:10B800002E813F812F5F3F4F2E833F83992702C0B8 -:10B810008FEF9FEFDF91CF9108950F931F93CF93F9 -:10B82000DF93FB01238121FD03C08FEF9FEF2CC02D -:10B8300022FF16C046815781248135814217530764 -:10B8400044F4A081B1819D012F5F3F4F208331835C -:10B850008C93268137812F5F3F4F2683378314C017 -:10B860008B01EC01FB010084F185E02D1995892BFA -:10B87000E1F6D80116968D919C9117970196169630 -:10B880008D939C931797CE01DF91CF911F910F91CC -:10B890000895FB01238120FF12C026FD10C08F3FB9 -:10B8A0003FEF930761F082832F7D206423832681FD -:10B8B00037812150310926833783992708958FEFE7 -:10B8C0009FEF0895FA01AA27283051F1203181F124 -:10B8D000E8946F936E7F6E5F7F4F8F4F9F4FAF4F98 -:10B8E000B1E03ED0B4E03CD0670F781F891F9A1FAB -:10B8F000A11D680F791F8A1F911DA11D6A0F711D5F -:10B90000811D911DA11D20D009F468943F912AE06A -:10B91000269F11243019305D3193DEF6CF01089552 -:10B92000462F4770405D4193B3E00FD0C9F7F6CF83 -:10B93000462F4F70405D4A3318F0495D31FD40524B -:10B94000419302D0A9F7EACFB4E0A69597958795E1 -:10B9500077956795BA95C9F70097610571050895C0 -:10B960009B01AC010A2E069457954795379527956C -:10B97000BA95C9F7620F731F841F951FA01D089504 -:10B9800099278827089503D0808199270895E0ECAE -:10B99000F1E0378537FDFDCF348538603487FC0111 -:10B9A000E050F04F0895262FF2DF0080021611F0CC -:10B9B00008D00197019708950196272FF5DFF3CF5F -:10B9C000262FE0ECF1E0378537FDFDCF3485377F5A -:10B9D0003487378531FF09C036E3328738ED34BF0D -:10B9E00031E03387378537FDFDCF33E332878083FE -:10B9F00091831282248325E3228728ED31E024BF3E -:10BA0000338701960895052E97FB16F400940FD006 -:10BA100057FD05D014D007FC02D046F408C050955D -:10BA20004095309521953F4F4F4F5F4F089590952A -:10BA30008095709561957F4F8F4F9F4F0895A1E23C -:10BA40001A2EAA1BBB1BFD010DC0AA1FBB1FEE1F98 -:10BA5000FF1FA217B307E407F50720F0A21BB30BE3 -:10BA6000E40BF50B661F771F881F991F1A9469F75F -:10BA700060957095809590959B01AC01BD01CF01BB -:06BA80000895F894FFCFC9 -:10BA860002400F008310000001041000000182082C -:10BA9600000001000000000000000000000001009E -:10BAA60001000000000000000925102510251C25B6 -:10BAB600282532254F255D25862589258D253E009D -:10BAC6000426140004043E00042E040C040400089A -:10BAD6000008000000000000000800080808080828 -:10BAE6000800080008000000080800080808008090 -:10BAF60000800000000000000080008080808080C0 -:10BB0600800080008000000080800080808000012E -:10BB16000001000000000000000100010101010118 -:10BB26000100010001000000010100010101000007 -:10BB360000000000000000000000000000000101FD -:10BB460001010101010101010101010101010101DF -:10BB560001010101010101010101010101010101CF -:10BB660001010101010101010101010101010000C1 -:10BB760000000000000000000000000000000000BF -:10BB860000000000000000000000000000000000AF -:10BB9600000000000000000000000000000001019D -:10BBA6000101010101010101010101010101000081 -:10BBB600000000000000000000000000000000007F -:10BBC600000000000000000000000000000001016D -:10BBD6000101010101010101010101010101000051 -:10BBE600000000000000000000000000000001014D -:10BBF600010101010101010101010101010101012F -:10BC06000101010101010101010101010101000020 -:10BC1600000000000000000000000000000001011C -:10BC26000101010101010101010101010101000000 -:10BC360000020200000200020202020000020000EE -:10BC460000020200000200020202020000020000DE -:10BC560000020200000200020202020000020404C6 -:10BC6600040606040406040606060604040604047E -:10BC76000406060404060406060606040406000076 -:10BC8600000202000002000202020200000200009E -:10BC96000002020000020002020202000002040486 -:10BCA6000406060404060406060606040406000046 -:10BCB6000002020000020002020202000002040466 -:10BCC600040606040406040606060604040604041E -:10BCD600040606040406040606060604040604040E -:10BCE60004060604040604060606060404060404FE -:10BCF60004060604040604060606060404060000F6 -:10BD0600000202000002000202020200000200001D -:10BD16000002020000020002020202000002040405 -:10BD260004060604040604060606060404060008BD -:10BD360008080000000800000800080800080008BD -:10BD460008080000000800000800080800080008AD -:10BD5600080800000008000008000808000810187D -:10BD6600181810101018101018101818101810188D -:10BD7600181810101018101018101818101800089D -:10BD8600080800000008000008000808000800086D -:10BD9600080800000008000008000808000810183D -:10BDA600181810101018101018101818101800086D -:10BDB600080800000008000008000808000810181D -:10BDC600181810101018101018101818101810182D -:10BDD600181810101018101018101818101810181D -:10BDE600181810101018101018101818101810180D -:10BDF600181810101018101018101818101800081D -:10BE060008080000000800000800080800080008EC -:10BE160008080000000800000800080800081018BC -:10BE26001818101010181010181018181018434C65 -:10BE36004F4E4500546F6F206D616E7920646174BA -:10BE4600612E000D0A000D0A5041524954592045F1 -:10BE560052524F52000D0A504152495459204F4BED -:10BE6600002534753A200025337500556E6B6E6FCC -:10BE7600776E206361726420747970652E00257375 -:10BE8600206F7220004D756C7469706C6520706F40 -:10BE960073736962696C69746965732C206E6F745B -:10BEA60020636C6F6E61626C652100436C6F6E651A -:10BEB60064204F4B2100436C6F6E6520756E737561 -:10BEC60070706F7274656421004E4F204441544176 -:02BED60000006A +:1018C00080932206C093310612E0109332061092E4 +:1018D0002A0610922B068FE08093290689E58093D3 +:1018E00080019AE5909381018093820180E4809346 +:1018F0004106809346069091B200907F9093B2008B +:101900009091B20092609093B20090E39093410660 +:101910009093460680935006C09346061093450662 +:1019200003E00093410683E18093010821E030E069 +:1019300020932608309327082093280830932908FD +:1019400010928C0880938008109223031092210338 +:10195000D8E0D093220381E180932003E0913E2FD1 +:10196000F0913F2F828593858093380390933903BC +:101970008CE380938203D093800380938303D0937E +:10198000810366D10E944919B7D117D7C0930002CD +:10199000109201021093020200930402C0932002ED +:1019A000D09321020E949E1517D1D2E0C1E180910F +:1019B000030481FF25C08091010480FDFCCFD093FA +:1019C00003040E94AB17AED10E947C19FED60E9480 +:1019D0000617E0912F2FF091302F19950E94A02229 +:1019E0000E94E818E0913E2FF0913F2F87818130CF +:1019F00011F4C093632C8681813011F4C093622C62 +:101A00000E944D199CD7E0912D2FF0912E2F199502 +:101A1000E091272FF091282F1995C9CF292F33272F +:101A20002230310559F02330310569F0213031057C +:101A3000E9F482E190E026E932E01CC08EE390E018 +:101A400028E532E017C099278130910549F028F048 +:101A5000029761F4E8E0F2E005C0E4E5F2E002C0DC +:101A6000E8E2F2E0849190E09F0104C080E090E021 +:101A700020E030E0FA012083318308951F920F9215 +:101A80000FB60F92112408B60F9218BEFFCF1F9207 +:101A90000F920FB60F92112408B60F9218BE8F93B3 +:101AA0009F938EB19FB180589F4F8EB99FB99F91E0 +:101AB0008F910F9008BE0F900FBE0F901F9018953A +:101AC0008091780083FF0AC088E08093780088EDD9 +:101AD00084BF81E0809380000D94FE008BEC8093A6 +:101AE0005200809150008860809350008091510096 +:101AF00083FFFCCF82EC8093550080915000806181 +:101B0000809350008091510084FFFCCF88ED84BF0A +:101B100084E0809340001EB81FB881E080934300AA +:101B20002FE730E020930A0430930B0420930C0439 +:101B300030930D04809300048093020480E8809326 +:101B40000001089588ED84BF81E0809379000895B5 +:101B500088ED84BF8BE180938000089580915000D0 +:101B60008260809350008091510081FFFCCF82E021 +:101B70008093CA01EDE1F0E0E491E0936200ECE1D2 +:101B8000F0E0E491E09363001092CA0180E8809352 +:101B900065008BEB8093660080915600897F80936F +:101BA00056008091560084608093560080916000BA +:101BB0008160809360000895E0E4F0E084818E7F8E +:101BC0008483E0E6F0E080818E7F8083E0E5F0E0D2 +:101BD00080818D7F8083089587E08093A200789430 +:101BE0000895089580E090E0089508950895089577 +:101BF000089508950895089508950F931F93CF931E +:101C0000C82F03E21FE2D8011296ED91FC911397C1 +:101C100019950E94D822E0913E2FF0913F2FC58365 +:101C2000B8E1CB9FB001112468557D4F48E150E0E9 +:101C3000C8010E94165CD801ED91FC911995D8015C +:101C40001696ED91FC911797CF911F910F911994D2 +:101C500048E150E068EA72E083E29FE20E94165C8D +:101C6000E0913E2FF0913F2F8581C7CF0F931F93B7 +:101C7000E0913E2FF0913F2F8B019C0145816AE05E +:101C800088E993E00E9484181F910F910895FF92B4 +:101C90000F931F93CF93DF931F92CDB7DEB78C01C5 +:101CA0009E012F5F3F4FAC016AE088E993E00E94FC +:101CB0009C18F82E882389F089819FDFF80140E085 +:101CC0008191882319F04F5F4F31D1F7E0913B2F7D +:101CD000F0913C2FB80181E119958F2D0F90DF9184 +:101CE000CF911F910F91FF9008959B01AC016AE085 +:101CF00088E993E00C94C31808950C94085C089547 +:101D00000F931F93CF938C01C62FCC2339F00E94E1 +:101D1000085CF80181938F01C150F7CFCF911F91DB +:101D20000F9108950E94085C0E94085C0E94085C64 +:101D30000C94085CCF93DF93EC0161507109DA01D8 +:101D4000420F531FFC01CF018C1B9D0BA417B5073D +:101D500021F41082DF91CF91089562307105C8F3AC +:101D60009D91392F32953F703A3010F4305D01C0AB +:101D7000395C30839F709A3010F4905D01C0995C9B +:101D80009183329662507109DECFCF93DF93EC01DD +:101D9000DA0120E030E05C91552351F111969C91DD +:101DA0001197992339F12617370711F180ED850F27 +:101DB0008A3020F08FEB850F8630E0F480ED890FBC +:101DC0008A3020F04FEB490F4630A0F4E52FF0E0C9 +:101DD000513408F0F797E295E07F913410F4982F92 +:101DE00001C097539E2B99932F5F3F4F1296D3CFED +:101DF000C90102C080E090E0DF91CF910895E0E654 +:101E0000F6E080E1858382E0868388E085838AE14D +:101E10008183E0EAF9E01682178280EC858388E10D +:101E20008483E0E0F1E0128A8BE6838B148A158AC2 +:101E300020EA208F99E0918F128E148E158E168EC7 +:101E400084E0808B12A23CE633A314A215A210A654 +:101E500011A612A624A795A716A680A3089541153A +:101E6000510509F449C020E12093660623E0209340 +:101E7000A0092091A10927FFFCCF2091A009709310 +:101E8000A0092091A10927FFFCCF2091A009609310 +:101E9000A0092091A10927FFFCCF2091A00921E0F2 +:101EA0002093120180931C0190931D014093140113 +:101EB00050931501109222018AE594E28093280143 +:101EC00090932901409324015093250180911001A2 +:101ED00080688093100180912001806880932001A8 +:101EE0008091100187FDFCCF80E3809311018093E6 +:101EF000210180E18093650608954115510509F49B +:101F000069C020E12093660626E02093A009209175 +:101F1000A10927FFFCCF2091A00920E120936506AD +:101F2000000000002093660622E02093A009209183 +:101F3000A10927FFFCCF2091A0097093A00920914F +:101F4000A10927FFFCCF2091A0096093A00920914F +:101F5000A10927FFFCCF2091A009109212012AE5C8 +:101F600034E220931C0130931D01409314015093DF +:101F7000150120E1209322018093280190932901EB +:101F80004093240150932501809110018068809333 +:101F900010018091200180688093200180911001C0 +:101FA00087FDFCCF80E3809311018093210180E1C4 +:101FB00080936506E0913E2FF0913F2F8781863018 +:101FC00019F481E18093632C8681863019F481E1D4 +:101FD0008093622C0895CF92DF92EF92FF92CF937D +:101FE000DF93C0903D2FD12CE12CF12C8DE0CC0C57 +:101FF000DD1CEE1CFF1C8A95D1F7C114D10481E0D1 +:10200000E806F10408F04EC080E18093660686E0A1 +:102010008093A0098091A10987FFFCCF8091A0093E +:1020200080E180936506000000008093660682E0F0 +:102030008093A0098091A10987FFFCCF8091A0091E +:102040001092A0098091A10987FFFCCF8091A0097F +:102050001092A0098091A10987FFFCCF8FEFE81AA9 +:10206000F80A8091A009C0E0D0E1C701B60199DB70 +:102070008093A0098091A10987FFFCCF8091A009DE +:102080009093A0098091A10987FFFCCF8091A009BE +:1020900082E0C80ED11CE11CF11C219731F780E1D0 +:1020A000809365068091010480FDFCCF82E08093DF +:1020B0000304DF91CF91FF90EF90DF90CF900895D0 +:1020C000CF92DF92EF92FF92CF93DF93C0903D2F9C +:1020D000D12CE12CF12C8DE0CC0CDD1CEE1CFF1C76 +:1020E0008A95D1F7C114D10481E0E806F10438F0F3 +:1020F000DF91CF91FF90EF90DF90CF906CCF8FEF7B +:10210000E81AF80AC1E2D0E0219791F365DBC70134 +:10211000B6014EDB61DB8FEFD81AE80AF80AF4CF7C +:10212000CF92DF92EF92FF920F931F93CF93DF93A3 +:10213000C0903D2FD12CE12CF12C8DE0CC0CDD1C7E +:10214000EE1CFF1C8A95D1F7C114D10481E0E8068A +:10215000F10408F04FC080E18093660683E080932D +:10216000A0098091A10987FFFCCF8091A00910925E +:10217000A0098091A10987FFFCCF8091A00910924E +:10218000A0098091A10987FFFCCF8FEFE81AF80A18 +:102190008091A00901E210E00150110941F11CDB1E +:1021A00018DB1ADBC0E0D0E01092A0098091A109F1 +:1021B00087FFFCCF6091A00970E01092A009809188 +:1021C000A10987FFFCCF8091A009782BCE01F6DA18 +:1021D00003DB2296C11581E0D80731F7C701B601AC +:1021E000F2DAFADA8FEFD81AE80AF80AD5CF80E1E6 +:1021F00080936506E0913E2FF0913F2F87818630D6 +:1022000019F490E19093632C9681963049F420E183 +:102210002093622C853059F483E18093632C02C0B3 +:102220008530D1F3953019F483E18093622C80914D +:10223000010480FDFCCF82E080930304DF91CF9105 +:102240001F910F91FF90EF90DF90CF900895CF9264 +:10225000DF92EF92FF920F931F934115E0E25E072A +:102260006105710508F06BC06901E12CF12C00E0FB +:1022700010E220E030E0041B150B260B370BC016D4 +:10228000D106E206F30610F49701860120E12093BF +:10229000660626E02093A0092091A10927FFFCCF24 +:1022A0002091A00920E12093650600000000209302 +:1022B000660622E02093A0092091A10927FFFCCF08 +:1022C0002091A0095093A0092091A10927FFFCCFDC +:1022D0002091A0094093A0092091A10927FFFCCFDC +:1022E0002091A009109212012AE534E220931C01EA +:1022F00030931D01009314011093150120E12093E8 +:1023000022018093280190932901009324011093C6 +:102310002501809110018068809310018091200137 +:102320008068809320018091100187FDFCCF80E3BD +:10233000809311018093210180E18093650681E003 +:102340001F910F91FF90EF90DF90CF900895CF9263 +:10235000DF92EF92FF920F931F934115E0E25E0729 +:102360006105710508F05DC06901E12CF12C00E008 +:1023700010E220E030E0041B150B260B370BC016D3 +:10238000D106E206F30610F49701860120E12093BE +:10239000660623E02093A0092091A10927FFFCCF26 +:1023A0002091A0095093A0092091A10927FFFCCFFB +:1023B0002091A0094093A0092091A10927FFFCCFFB +:1023C0002091A00921E02093120180931C01909399 +:1023D0001D010093140110931501109222018AE54A +:1023E00094E2809328019093290100932401109393 +:1023F0002501809110018068809310018091200157 +:102400008068809320018091100187FDFCCF80E3DC +:10241000809311018093210180E18093650681E022 +:1024200001C080E01F910F91FF90EF90DF90CF905F +:1024300008958091CF0187FDFCCF0895FADF809148 +:10244000CF0181FF0BC086E38093CA01EBECF1E082 +:1024500021E030E088ED90E084BF20830895EF9282 +:10246000FF920F931F93CF93DF93EC017B018A01BF +:102470001092C201DEDFD701CE01800F911F26E04E +:1024800048ED50E061E070E0EBECF1E0C817D907EF +:1024900079F0C093C0013D2F3F713093C10120936B +:1024A000CA0144BF60833091C4013D932196EECFB1 +:1024B000C801DF91CF911F910F91FF90EF90089588 +:1024C0003F924F925F926F927F928F929F92AF92C4 +:1024D000BF92CF92DF92EF92FF920F931F93CF9311 +:1024E000DF938B01542E652E282F2F71722EEC0155 +:1024F000C21BD109A3DF9DDF83E38093CA01109241 +:10250000C1011092C2017801052D162D85E3482ED8 +:1025100098EDC92ED12C88248394912C3BECA32ECA +:10252000BB24B39443E3342E0115110501F17092DD +:10253000C001F70181917F018093C401015011090D +:1025400021F07394F0E27F12EFCFC093C0018D2F82 +:102550008F718093C1014092CA01C601F50184BF09 +:102560008082A09666DF3092CA01712CDDCF852D66 +:10257000962DDF91CF911F910F91FF90EF90DF90FB +:10258000CF90BF90AF909F908F907F906F905F9013 +:102590004F903F9008951F93CF93DF93CDB7DEB751 +:1025A000A097CDBFDEBF863009F4EAC0D0F48330F7 +:1025B00009F46AC028F4813059F18230C9F1F6C0BB +:1025C000843009F486C0853009F0F0C0E091332FE3 +:1025D000F091342FCE01019619958091392F41E069 +:1025E000A4C0893009F4D0C040F4873009F4CAC0CF +:1025F000883009F0DBC0EFDCD9C08A3009F4D5C0DF +:102600008B3009F0D3C080EB93E20E94D621CEC07C +:1026100010E08091392F181708F09FC06EDBE1E0C1 +:10262000F0E0EC0FFD1FE10FF11D80831F5FF1CF84 +:1026300011E08091392F873009F010E0E091332FBD +:10264000F091342FCE01019619954091392F31E048 +:10265000141708F082C03323A9F0812F90E0E1E045 +:10266000F0E0EC0FFD1FE80FF91F208131E02F3F54 +:1026700009F030E0E1E0F0E0EC0FFD1FE80FF91F9A +:102680002F5F20831F5FE4CFE091332FF091342F31 +:10269000CE01019619958091392F41E0815008F4BF +:1026A0005CC04423D9F3282F30E0E1E0F0E0EC0FE8 +:1026B000FD1FE20FF31F908141E09F3F09F040E0D2 +:1026C000E1E0F0E0EC0FFD1FE20FF31F9F5F90834E +:1026D000E5CF11E08091392F873009F010E0E091CB +:1026E000332FF091342FCE01019619954091392F57 +:1026F00031E0141790F53323A1F0812F90E0E1E051 +:10270000F0E0EC0FFD1FE80FF91F208131E02111EF +:1027100030E0E1E0F0E0EC0FFD1FE80FF91F215081 +:1027200020831F5FE6CF411103C08150E0F715C041 +:10273000282F30E0E1E0F0E0EC0FFD1FE20FF31F87 +:10274000908141E0911140E0E1E0F0E0EC0FFD1FED +:10275000E20FF31F91509083E8CFE091352FF09175 +:10276000362FCE0101961995E0913B2FF0913C2F29 +:102770004091392FBE016F5F7F4F83E1199516C0DD +:10278000B0D314C0CDDC12C080910008813021F498 +:1027900090918C08933009F080E080FD03C00E9486 +:1027A000622304C00E94882301C0AAD2A096CDBF94 +:1027B000DEBFDF91CF911F910895E0E0F6E080E663 +:1027C000828388E1868B858B0895CF93C09108061C +:1027D000C095C6FF12C080915C248A3050F08A30C8 +:1027E000E1F4E0913E2FF0913F2F8181D4DE809182 +:1027F0005C248F5F80935C2410C08C2F807669F4FA +:1028000080915C2481508A3030F4E0913E2FF09129 +:102810003F2F8081C0DE10925C24C5FF12C08091E2 +:102820005B248A3050F08A30D9F4E0913E2FF09149 +:102830003F2F8381B0DE80915B248F5F80935B2488 +:102840000FC0C07669F480915B2481508A3030F4E7 +:10285000E0913E2FF0913F2F82819DDE10925B240C +:10286000CF9108959B01AC016CE082EE96E08BC4A1 +:10287000E82FF0E0E35CF04D88E0638381503C9604 +:102880008111FBCF08950F931F939B01E0913E2F81 +:10289000F0913F2FE80FF11D8A0140816CE082EE3C +:1028A00096E032D41F910F9108950F931F93CF9309 +:1028B000DF931F92CDB7DEB7082FAB019E012F5FCC +:1028C0003F4F6CE082EE96E037D4182F882319F042 +:1028D0006981802FCDDF812F0F90DF91CF911F91E4 +:1028E0000F9108950895EF92FF920F931F93CF9346 +:1028F0007B01C42F0EB11FB120910804309109044F +:10290000022B132B682F83E090E20E94185A6C2F41 +:1029100083E090E20E94185A612F83E090E20E94C7 +:10292000185A602F83E090E20E94185A6C2F70E0D2 +:10293000C701CF911F910F91FF90EF90A4C408950C +:102940003F924F925F926F927F928F929F92AF923F +:10295000BF92CF92DF92EF92FF920F931F93CF938C +:10296000DF937C01E901C0900020D0900120960106 +:1029700022503843C901A0E0B0E0481759076A0760 +:102980007B0708F05FC0E2E0CE1AE0E4DE0A2A012D +:102990003B014C0E5D1E611C711C481659066A06EF +:1029A0007B0648F0241B350B8E01021B130BE9013B +:1029B0003324339403C000E010E0312C4601A12CF5 +:1029C000B12C481559056A057B0510F5CA018E5FC3 +:1029D0009F4B2A013B014C0E5D1E611C711C48146B +:1029E00059046A047B0428F4AE01BC01C70137DA3C +:1029F00018C0C41AD50AA601BC01C70130DAAE015D +:102A00004C195D0962E674E2C7018C0D9D1D07C07B +:102A10004C195D09BA016E597B4DAE01C7010E9488 +:102A2000445C332041F00C0F1D1FF701E00FF11F34 +:102A3000CE0DDF1D02C081E006C0EC17FD07D9F303 +:102A40001292FBCF80E0DF91CF911F910F91FF9009 +:102A5000EF90DF90CF90BF90AF909F908F907F903E +:102A60006F905F904F903F90089520915E24309139 +:102A70005F2480E098E0821B930BE2E6F4E29F0182 +:102A8000225634422817390710F41192F8CF82E603 +:102A900094E2809360249093612480E098E0809396 +:102AA0005E2490935F2482E090E4809300209093D2 +:102AB000012042E050E060E070E480E090E21DDA46 +:102AC000E0913E2FF0913F2F87818A3019F480E109 +:102AD0008093632C86818A3019F480E18093622C84 +:102AE000089580915E2490915F2490582091002059 +:102AF00030910120821B930B0895EDE3FFE2878361 +:102B00003C969FE2ED39F907D1F7813049F018F092 +:102B1000823059F0089510925D2482E794E109C053 +:102B200080935D2489EF95E104C010925D2483E7D2 +:102B300094E180933B2F90933C2F08950F931F9324 +:102B4000CF93DF931F92CDB7DEB7E0913E2FF09188 +:102B50003F2F8481D2DF82E694E2809360249093B9 +:102B6000612400E018E000935E2410935F2441E0AC +:102B700050E0BE016F5F7F4F80E090E070DCE0913D +:102B80006024F0916124DF01C8011D920197E9F7EB +:102B90008981882341F042E050E060E070E480E009 +:102BA00090E25DD917C082E090E48093002090937A +:102BB000012042E050E060E070E480E090E29DD9C6 +:102BC00081E0898341E050E0BE016F5F7F4F80E08C +:102BD00090E076DCE0913B2FF0913C2F40E060E00C +:102BE00070E08FEF19950F90DF91CF911F910F91AA +:102BF00008950F931F93CF93DF93CEB1DFB1A091D0 +:102C00000804B091090420915E2430915F24E42FE0 +:102C1000F0E08F010C5F1F4F2017310758F1CA2BCE +:102C2000DB2B245031092E1B3F0B20935E24309365 +:102C30005F24A0916024B09161248C9311964C93F1 +:102C400011971296DC931297CD010496809360241D +:102C5000909361241396CC93DB01EC01415018F062 +:102C60002D912993FBCFE80FF91FE0936024F09397 +:102C7000612412C080E041DFE0913E2FF0913F2FB0 +:102C800087818A3019F481E18093632C86818A30B0 +:102C900019F481E18093622CDF91CF911F910F9104 +:102CA00008951F93CF93DF931F92CDB7DEB79E0198 +:102CB0002F5F3F4FAC0163E08EE698E03DD2182FC6 +:102CC000882311F0898119DF812F0F90DF91CF9137 +:102CD0001F9108950F931F93E0913E2FF0913F2F86 +:102CE0008B019C01448163E08EE698E00DD21F9138 +:102CF0000F9108959B01AC0163E08EE698E043C21A +:102D00000F931F93CF93DF9380915E2490915F2464 +:102D1000811528E0920708F074C06091002070913E +:102D20000120C0E0D0E8C61BD70B00E018E0A801E6 +:102D3000481B590BC417D50758F182E694E2DDD839 +:102D400020915E2430915F24809100209091012099 +:102D5000985F821B930B8093002090930120021BAD +:102D6000130BE2E6F4E2CF018256944280179107FA +:102D700010F41192F8CF82E694E28093602490934D +:102D8000612480E098E080935E2490935F242EC0BD +:102D90002097B9F1AE0182E694E2AFD8A8014C1BAE +:102DA0005D0BBE016E597B4D82E694E20E944D5C44 +:102DB00080916024909161248C1B9D0B80936024F2 +:102DC0009093612480915E2490915F248C0F9D1FCD +:102DD00080935E2490935F24809100209091012045 +:102DE000C80FD91FC0930020D093012042E050E0CB +:102DF00060E070E480E090E2DF91CF911F910F914D +:102E00007CC8DF91CF911F910F91089580915D242F +:102E1000811176CF089543E650E06DE37FE281E0D3 +:102E200090E01DCB43E650E06DE37FE281E090E06F +:102E300047CB0F931F93CF93DF93CFEFC80FC830CB +:102E400008F047C0D82F0E94D82280913D2FC81784 +:102E500079F166D9C0933D2F8CE0C89F9001112471 +:102E6000C901805C904D80933E2F90933F2FF901D4 +:102E7000E35CF04D80850E94FD0DE0913E2FF091C6 +:102E80003F2F84813ADEA7D801E010E00D531F42A6 +:102E900060913D2FC801835C904D0E94E562609176 +:102EA0003E2F70913F2FC801825C904D0E94EE62D0 +:102EB0008FE18D0FE0913E2FF0913F2F978194305D +:102EC00011F48093632C9681943029F48093622CC2 +:102ED00002C080E001C081E0DF91CF911F910F918E +:102EE000089580913D2F99E04CE0915099F0282F62 +:102EF00030E02F5F3F4F27703327822F429FF00132 +:102F0000439FF00D1124E35CF04D2085222369F3EB +:102F10008F5F8FCF0895FC0190913D2F9F5C908330 +:102F200011820895CF93FC01218121110DC0BC01B4 +:102F3000C081E0913B2FF0913C2F41E082E1199557 +:102F400080ED8C0FCF9175CF80E0CF91089588E10F +:102F50008093010608958091622C823191F030F4C3 +:102F60008031B9F050F48823A9F132C0833169F07F +:102F700090EE980F983088F02BC088E0809305067B +:102F800027C088E08093070623C08091040683FF52 +:102F900012C088E0809306061BC09091642C9F5F4E +:102FA000913019F09093642C15C01092642C90917C +:102FB000040693FD04C088E0809305060BC098E0EA +:102FC00090930606803221F081508093622C02C0DB +:102FD0001092622C8091632C823191F030F4803118 +:102FE000C1F050F48823A9F132C0833169F090EE2A +:102FF000980F983088F02BC080E18093050627C099 +:1030000080E18093070623C08091040684FF12C0EC +:1030100080E1809306061BC09091652C9F5F9130E4 +:1030200019F09093652C08951092652C90910406E8 +:1030300094FD04C080E180930506089590E190938B +:103040000606803221F081508093632C08951092FF +:10305000632C08959B01AC016BE081ED98E093C077 +:10306000EDE3FFE298E0282F20718870211162873C +:103070008111618791503C969111F8CF222329F05C +:1030800090E1909306061092632C882329F088E043 +:10309000809306061092622C08950F931F939B0154 +:1030A0008A01803131F4E0913E2FF0913F2F47812A +:1030B00007C0883049F4E0913E2FF0913F2F4681C0 +:1030C0006BE081ED98E020D01F910F9108950F9350 +:1030D0001F93CF93DF931F92CDB7DEB7082FAB01BD +:1030E0009E012F5F3F4F6BE081ED98E025D0182FB8 +:1030F000882319F06981802FB3DF812F0F90DF9132 +:10310000CF911F910F9108950F931F93FC01662398 +:1031100079F094916150941309C0BF016F5F7F4FA4 +:10312000A801C9010E94285C81E003C0B196EFCFDD +:1031300080E01F910F910895CF92DF92EF92FF925E +:103140001F93CF93DF93EC017A016901162F1123AE +:1031500089F0BE016F5F7F4FC7010E941F5C115055 +:10316000892B31F4FE01C491F601C08381E003C0D4 +:10317000A196EDCF80E0DF91CF911F91FF90EF906E +:10318000DF90CF900895CF930196CCE26623D1F0E3 +:10319000FC01DA01AD017491772341F0211531056D +:1031A000A9F07D93319621503109F4CF623038F087 +:1031B0002115310559F0FD01C0834F5F5F4F61500C +:1031C0008196E4CF232B11F0FA011082CF9108955C +:1031D000809120028068809320028091230280FFEA +:1031E000FCCF81E080932302A0911002B0911102E4 +:1031F000AE5BB109B7FF02C0A0E0B0E020E038EB61 +:103200004BE050E00E94A25BE0913E2FF0913F2FF7 +:10321000843F9140A8F48781873019F480E180933E +:10322000632C8681873019F480E18093622C809131 +:10323000392F882389F0E0912B2FF0912C2F1994AE +:103240008781873019F481E18093632C86818730F0 +:1032500019F481E18093622C0895BC0183E090E22F +:103260000C94CA59CF93DF93FC016491EC01219631 +:10327000662331F083E090E20E94185ACE01F4CF29 +:10328000DF91CF910895AB01BC0183E090E20C94F3 +:10329000F45980E2809362060895CF93DF93809182 +:1032A000662C823031F583E090E20E94815A0E94C0 +:1032B0005F5583E090E20E949D5AEC0197FD19C092 +:1032C000E0913E2FF0913F2F8781833019F483E105 +:1032D0008093632C8681833019F483E18093622C80 +:1032E0008C2F88D6811105C08C2FDF91CF910C9443 +:1032F000F621DF91CF9108958091662C813079F08D +:1033000028F08230C9F0833011F12EC08091680618 +:1033100085FF31C08FE08093022081E015C080914D +:103320000220815080930220811125C00E94AE0DA1 +:103330000E94F75882E008C08091680685FD18C099 +:103340008FE08093022083E08093662C0DC08091F3 +:10335000022081508093022081110DC00E94BC5830 +:103360000E94DC0D1092662C8091662C823019F43C +:1033700090D70C94A0220895E0913E2FF0913F2F1A +:103380008781823019F481E18093632C86818230B9 +:1033900019F481E18093622C0895E0913E2FF09121 +:1033A0003F2F8781823019F480E18093632C8681DE +:1033B000823019F480E18093622C089583E090E2DA +:1033C0000C94A55983E090E20C94F05A22ED3BE076 +:1033D0003F932F932CEC3BE03F932F9325EC3BE066 +:1033E0003F932F932EEB3BE03F932F932EE13BE057 +:1033F0003F932F9322E02F931F929F938F930E94CE +:10340000AD5C8DB79EB70E968DBF9EBF85E60895C5 +:1034100060E072E00E94360E85E60895FB0120818F +:103420002F3349F42181211106C060E072E00E942F +:10343000750E85E60895CB010E94470E882371F032 +:10344000E0913E2FF0913F2FCF0188539F4265813D +:103450008F5F9F4F0E94E56284E608958AEC08958D +:10346000EF92FF920F931F93CF93DF93CDB7DEB709 +:10347000A097CDBFDEBF7C010091392F10E0011570 +:10348000110591F486E19BE09F938F9382E08F93E7 +:103490001F92FF92EF920E94AD5C0F900F900F90E1 +:1034A0000F900F900F9010C0E091332FF091342FB8 +:1034B000CE01019619959801AE014F5F5F4F60E014 +:1034C00072E0C7010E949A0E85E6A096CDBFDEBFCE +:1034D000DF91CF911F910F91FF90EF900895DF92B0 +:1034E000EF92FF920F931F93CF93DF93CDB7DEB789 +:1034F000A097CDBFDEBF7B010091392F10E06FE0B8 +:103500007BE0C7010E941F5C892B29F5D12CED2C93 +:10351000F12CE016F10658F40E947D0EE1E0F0E097 +:10352000EC0FFD1FEE0DFF1D8083D394F0CFE091D3 +:10353000352FF091362FCE0101961995E0913B2F52 +:10354000F0913C2F4091392FBE016F5F7F4F83E197 +:10355000199584E60BC0A70160E270E0CE010196E8 +:103560000E94C50E0817190711F38AECA096CDBF6B +:10357000DEBFDF91CF911F910F91FF90EF90DF9011 +:103580000895FC0180913A2F882311F081E301C056 +:1035900080E38083118285E60895FB01218121115A +:1035A00027C02081213321F481E080933A2F04C089 +:1035B000203321F410923A2F84E608952F33C1F47A +:1035C0001F9220E32F931F9221E32F9329E03BE0EA +:1035D0003F932F9322E02F931F929F938F930E94EC +:1035E000AD5C8DB79EB70A968DBF9EBF85E60895E8 +:1035F0008AEC089587E291E1CCD48EE6089587EABB +:1036000091E1E2D48EE60895E0ECF4E081818E7FD2 +:1036100081830E94BC580E94A20D84E60895E0ECCC +:10362000F4E081818E7F81830E94BC580E94A80DA6 +:1036300084E60895E3E2FFE225892F9324892F93FE +:1036400026E03BE03F932F9322E02F931F929F931E +:103650008F930E94AD5C8DB79EB708968DBF9EBFBD +:1036600085E608952091392F1F922F9323E03BE0A8 +:103670003F932F9322E02F931F929F938F930E944B +:10368000AD5C8DB79EB708968DBF9EBF85E6089549 +:1036900040E052E0BC0180E0F6D885E60895FB01E9 +:1036A00020812F3341F42181211105C060E072E0B7 +:1036B000D9D885E6089580E0F8D8882319F0B2DBE0 +:1036C00084E608958AEC089540E052E0BC0181E070 +:1036D000DAD885E60895FB0120812F3341F421815A +:1036E000211105C060E072E0BDD885E6089581E053 +:1036F000DCD8882319F096DB84E608958AEC0895D7 +:1037000040E052E0BC0182E0BED885E60895FB01AE +:1037100020812F3341F42181211105C060E072E046 +:10372000A1D885E6089582E0C0D8882319F07ADB15 +:1037300084E608958AEC089540E052E0BC0183E0FD +:10374000A2D885E60895FB0120812F3341F4218121 +:10375000211105C060E072E085D885E6089583E018 +:10376000A4D8882319F05EDB84E608958AEC0895D6 +:1037700040E052E0BC0180E190DC85E60895FB0169 +:1037800020812F3341F42181211105C060E072E0D6 +:1037900061DC85E6089580E19ADC882319F042DB3C +:1037A00084E608958AEC089540E052E0BC0188E088 +:1037B00074DC85E60895FB0120812F3341F42181DB +:1037C000211105C060E072E045DC85E6089588E0DF +:1037D0007EDC882319F026DB84E608958AEC0895C0 +:1037E00060E072E077DA85E60895FB0120812F33EF +:1037F00041F42181211105C060E072E07BDA85E6A9 +:103800000895CB014EDA882319F00CDB84E6089585 +:103810008AEC0895CF93DF93EC0163D9813028E0DF +:10382000920718F09C01385002C020E030E03F932E +:103830002F939F938F9383EE9AE09F938F9382E0D1 +:103840008F931F92DF93CF930E94AD5C8DB79EB78D +:103850000A968DBF9EBF85E6DF91CF91089580EADD +:1038600094E1B2D38EE608954BDA84E60895FDD84C +:1038700084E6089560E072E04EDB85E60895CB01B2 +:1038800051DB811102C08AEC089584E608950E94FC +:10389000601084E608950E94901084E608950E94C6 +:1038A000EB0F84E608958091680680FD02C089E7E9 +:1038B000089588E70895DF92EF92FF920F931F9388 +:1038C000CF93DF93EC010FEF11E085E1E82E8DE05F +:1038D000F82E9CE2D92EB70187EC93E20E941F5C80 +:1038E000892BD1F001151105B9F0DE01F701249102 +:1038F000ED012196C8010197222341F00130110505 +:1039000029F02C93DE0131968C01F1CFDC928C01F1 +:1039100088E1E80EF11CDFCF2197188285E6DF9160 +:10392000CF911F910F91FF90EF90DF900895FC01D0 +:10393000809120028068809320028091230280FF82 +:10394000FCCF81E080932302A0911002B09111027C +:10395000AE5BB109B7FF02C0A0E0B0E020E038EBF9 +:103960004BE050E00E94A25BAA27BB279F938F9356 +:103970008CED9AE09F938F9382E08F931F92FF9339 +:10398000EF930E94AD5C8DB79EB708968DBF9EBF2A +:1039900085E608954EB15FB1209108043091090485 +:1039A000242B352B3F932F9326ED3AE03F932F9313 +:1039B00022E02F931F929F938F930E94AD5C8DB74F +:1039C0009EB708968DBF9EBF85E608950F931F93FF +:1039D000CF93DF931F921F92CDB7DEB78B01E0919B +:1039E0003E2FF0913F2F8581893009F06FC0E09123 +:1039F0002B2FF0912C2F199581E08093CA2C60E237 +:103A000070E0C8010E94655C0097F9F4F80101902C +:103A10000020E9F73197E01BF10BE0FD59C0F69566 +:103A2000E795E130F10539F487E090E08093212FAC +:103A30009093222F37C053E0EE0FFF1F5A95E1F706 +:103A4000E093212FF093222F2DC098012C5F3F4F40 +:103A500082179307E9F5A80162E070E0CE010196B4 +:103A60000E94C50E898190E0982F88272A81820FB5 +:103A7000911D8093212F9093222F0B5F1F4FF801F0 +:103A800001900020E9F73197E01BF10BE0FD20C029 +:103A9000F695E79533E0EE0FFF1F3A95E1F7E8174B +:103AA000F907B0F06091212F7091222F695F7F4F4D +:103AB00083E0769567958A95E1F7A80181E29EE219 +:103AC0000E94C50E0E94252C8FEF03C089EC01C017 +:103AD0008AEC0F900F90DF91CF911F910F91089575 +:103AE000EF92FF920F931F93CF93DF931F921F923A +:103AF000CDB7DEB78B01E0913E2FF0913F2F85814E +:103B0000893009F080C0E0912B2FF0912C2F19956E +:103B100082E08093CA2C60E270E0C8010E94655C7C +:103B20007C01892B31F5F80101900020E9F73197EC +:103B3000E01BF10BE0FD69C0F695E795E130F1057A +:103B400039F487E090E08093212F9093222F47C093 +:103B500053E0EE0FFF1F5A95E1F7CF0169E070E0E7 +:103B60000E948E5BE81BF90BE093212FF093222F2C +:103B700036C0C8010496E816F90609F046C0A80147 +:103B800062E070E0CE0101960E94C50E898190E04E +:103B9000982F88272A81820F911D8093212F90933F +:103BA000222F8730910529F09C0127703327232B82 +:103BB00061F587010F5F1F4FF80101900020E9F7C1 +:103BC0003197E01BF10BE0FD20C0F695E79533E05F +:103BD000EE0FFF1F3A95E1F7E817F907B0F0609193 +:103BE000212F7091222F695F7F4F83E07695679533 +:103BF0008A95E1F7A80181E29EE20E94C50E0E942B +:103C0000252C8FEF03C089EC01C08AEC0F900F9038 +:103C1000DF91CF911F910F91FF90EF900895E09168 +:103C20003E2FF0913F2F85818930A1F4E0912B2F19 +:103C3000F0912C2F199585E08093CA2C0E942F4B70 +:103C40000E94252C89E39BE48093752C9093762C1D +:103C50008FEF089589EC0895E0913E2FF0913F2F6A +:103C600085818930A1F4E0912B2FF0912C2F1995AB +:103C700083E08093CA2C0E942F4B0E94252C89E35D +:103C80009BE48093752C9093762C8FEF089589ECAC +:103C90000895E0913E2FF0913F2F85818930A1F466 +:103CA000E0912B2FF0912C2F199586E08093CA2C50 +:103CB0000E942F4B0E94252C89E39BE48093752C56 +:103CC0009093762C8FEF089589EC0895E0913E2F24 +:103CD000F0913F2F4085518564E6649F9001659F78 +:103CE000300D11243F932F9320ED3AE03F932F9313 +:103CF00022E02F931F929F938F930E94AD5C8DB70C +:103D00009EB708968DBF9EBF85E60895CF93DF933B +:103D10001F921F92CDB7DEB7FB0120812F33B1F484 +:103D20002181211113C02EE93AE03F932F9322E025 +:103D30002F931F929F938F930E94AD5C0F900F90D3 +:103D40000F900F900F900F9085E62EC089E592E0BE +:103D500089839A83CE0101969F938F938AE99AE093 +:103D60009F938F937F936F930E94E35C0F900F90CC +:103D70000F900F900F900F90892BA9F069817A8195 +:103D80006935F2E07F0778F4E0913E2FF0913F2F04 +:103D900060877187CF0185539F428F5F9F4F0E943D +:103DA000EE6284E601C08AEC0F900F90DF91CF9114 +:103DB0000895E0913E2FF0913F2F23852F93228588 +:103DC0002F9327E93AE03F932F9322E02F931F92FE +:103DD0009F938F930E94AD5C8DB79EB708968DBF61 +:103DE0009EBF85E60895CF93DF931F921F92CDB7B4 +:103DF000DEB7FB0120812F33B1F42181211113C0E3 +:103E00002FE02F932FEF2F9326E43AE03F932F9349 +:103E100022E02F931F929F938F930E94AD5CCDBFA2 +:103E2000DEBF85E630C019821A82CE0101969F93CB +:103E30008F9382E49AE09F938F937F936F930E9476 +:103E4000E35C0F900F900F900F900F900F90892BC5 +:103E5000C9F069817A81611590E1790798F46093DE +:103E6000380370933903E0913E2FF0913F2F628722 +:103E70007387CF0183539F428F5F9F4F0E94EE62F3 +:103E800084E601C08AEC0F900F90DF91CF910895E6 +:103E9000FB0120812F33D9F42181211121C01F92F0 +:103EA00020E32F931F9221E32F932CE33AE03F93DB +:103EB0002F9322E02F931F929F938F930E94AD5CCC +:103EC0008DB79EB70A968DBF9EBF85E608952133B4 +:103ED00011F4F8D303C0203319F41AD484E60895FA +:103EE0008AEC0895FC0180910008813029F48091CA +:103EF0008C0891E0833009F090E090FF02C081E3EC +:103F000001C080E38083118285E60895E0913E2F11 +:103F1000F0913F2F8581893079F4E0912B2FF0913A +:103F20002C2F199584E08093CA2C0E942F4B0E945D +:103F3000252C89E39BE40EC0883091F4E0912B2F6F +:103F4000F0912C2F199581E08093A62D0E94EA52C2 +:103F50008FEF92E58093752C9093762C8FEF0895D8 +:103F600089EC089589E00E94FD0DE0912B2FF091DE +:103F70002C2F199587E08093CA2C0E942F4B0E940A +:103F8000252C89E39BE48093752C9093762C8FEFFE +:103F9000089521E02093742C2093732C2CE320931C +:103FA000712C25E030E020936F2C3093702C109210 +:103FB000692C10926A2C10926B2C10926C2C8093AE +:103FC000672C9093682C089527E02093742C2CE2A2 +:103FD00031E020936F2C3093702C1092692C10924A +:103FE0006A2C10926B2C10926C2C8093672C9093FF +:103FF000682C0895CF939091742C953009F441C0AA +:1040000030F4933019F130F5913068F43EC19730B7 +:1040100009F4AAC008F44AC0983009F4ACC0993039 +:1040200009F495C032C1813031F410926D2C109298 +:104030006E2C83E023C0843011F466E084C08831A4 +:1040400009F485C08B3109F084C081C08093722C43 +:1040500084E014C090E04091722C2FEF30E0241BDC +:1040600031098217930721F485E008C0891779F197 +:1040700065E183E090E20E94185A82E08093742CFC +:1040800068C020916D2C30916E2CA9014F5F5F4F5D +:1040900040936D2C50936E2CF901E056F04D8083C7 +:1040A0004038510509F055C086E0E8CF2091722CC8 +:1040B0009091732C29134FC0E0EAFFE220E230E335 +:1040C00090E02E173F0791F24191940FFACF409163 +:1040D000692C50916A2C60916B2C70916C2CE09142 +:1040E000672CF091682C20E830E080EA9FE2199577 +:1040F000C82F882311F18091732C8F5F8093732CCC +:104100008091692C90916A2CA0916B2CB0916C2CB1 +:1041100080589F4FAF4FBF4F8093692C90936A2C6C +:10412000A0936B2CB0936C2C66E083E090E20E942D +:10413000185A82E08093742CA9C068E183E090E271 +:104140000E94185A68E183E090E20E94185A109287 +:10415000742CC1E09BC030E0892F90E001972817B4 +:10416000390781F766E085CF853119F41092732CF9 +:1041700008C08B3161F3883109F45FCF863009F0D4 +:104180005AC08091732C8F5F8093732C4091692C5F +:1041900050916A2C60916B2C70916C2CE091672C83 +:1041A000F091682C20E830E080EA9FE21995C82F52 +:1041B0008823D1F161E083E090E20E94185A609177 +:1041C000732C83E090E20E94185A6091732C6095E2 +:1041D00083E090E20E94185A60E870E080EA9FE273 +:1041E00052D8E0EAFFE260E080E3E032F80719F03D +:1041F0008191680FF9CF83E090E20E94185A809174 +:10420000692C90916A2CA0916B2CB0916C2C8058E9 +:104210009F4FAF4FBF4F8093692C90936A2CA09310 +:104220006B2CB0936C2C32C064E083E090E20E946F +:10423000185A89E023CF853109F08BCF61E083E004 +:1042400090E20E94185A6091732C83E090E20E94E1 +:10425000185A6091732C609583E090E20E94185A7E +:1042600060E870E080EA9FE20ED8E0EAFFE280E2D8 +:1042700090E360E08E179F0719F02191620FFACF4B +:1042800083E090E20E94185A64CFC0E08C2FCF9157 +:1042900008958091742C813019F0873029F10895A8 +:1042A00080916F2C9091702C9C01215031092093AA +:1042B0006F2C3093702C892B31F58091712C9FEFEE +:1042C000980F9093712C882331F065E183E090E2A0 +:1042D0000E94185A02C01092742C85E090E08093DE +:1042E0006F2C9093702C089580916F2C9091702C6E +:1042F0009C012150310920936F2C3093702C892B15 +:1043000011F41092742C0895ECEEFBE020E030E004 +:104310009491981309C041E2429FC001439F900DC0 +:1043200011248351944F08952F5F3F4FB196293048 +:10433000310571F780E090E00895262FBA012F3300 +:1043400011F4469607C02D3311F4449611C0211183 +:104350000CC04096FC01259134912115310521F1C5 +:1043600080EA9FE2F90119950DC02032E9F44296E6 +:10437000FC012591349121153105B1F080EA9FE2CD +:10438000F90119958F3F89F491E09093792C4EB102 +:104390005FB12091080430910904242B352B209320 +:1043A000772C3093782C089589EC08950F931F9300 +:1043B000CF93DF938C01C5E1DDE0BE01C8010E940F +:1043C0001F5C892B49F440E050E060E0CE01DF91B2 +:1043D000CF911F910F91B1CF689680E1C53DD8076D +:1043E00061F7DF91CF911F910F910895EF92FF92A6 +:1043F0001F93CF93DF93982F9F7D91549A3160F054 +:1044000090ED980F9A3040F08F3531F0982F9D7FC6 +:104410009D3311F08032D1F49FE9980F9A3108F45E +:10442000805220917A2C30917B2C2F3F91E03907DC +:1044300008F07FC0A9014F5F5F4F40937A2C5093E3 +:104440007B2CF901E056F04D808373C08D3009F06C +:1044500040C0E0917A2CF0917B2CE056F04D108218 +:1044600010927A2C10927B2C8091792C811161C052 +:104470008091A02F982F9F7D09F440C08D7F8D33B0 +:10448000E9F1E0EAFFE27F011191112331F01F33DE +:1044900021F01D3311F01032B1F7F7011082C5E1A0 +:1044A000DDE0BE0180EA9FE20E941F5C892B59F487 +:1044B0001092A02FA7014F5F5F4F612FCE013DDF0C +:1044C0008F3FB9F124C06896F0E1C53DDF0749F799 +:1044D00015C0883061F480917A2C90917B2C0097E4 +:1044E00041F1019780937A2C90937B2C22C08B31E1 +:1044F00001F510927A2C10927B2C1BC088EC04DF03 +:104500000E94321989EE9BE00E94321912C0FCDE33 +:104510000E94321989EE9BE00E9432198091A02FEF +:10452000882339F080EA9FE20E942D1986EE9BE0F5 +:10453000EBCF81E0DF91CF911F91FF90EF90089535 +:104540008091792C882399F1E0913E2FF0913F2FB3 +:10455000208531852115310551F14EB15FB1809132 +:10456000080490910904842B952B4091772C50914D +:10457000782C841B950B64E670E00E948E5B6217BA +:104580007307A8F01092792C8BECBEDE0E943219D2 +:1045900083EE9BE00E943219E091752CF091762C0D +:1045A000309729F019951092752C1092762C089559 +:1045B0008091792C8823A9F01092792C8BECA4DEC1 +:1045C0000E94321983EE9BE00E943219E091752C13 +:1045D000F091762C309729F019951092752C109245 +:1045E000762C0895CF93DF939091792C9923A9F09D +:1045F000EB011092792C88DE0E94321980EE9BE04C +:104600000E943219209749F0CE010E942D198DED9C +:104610009BE0DF91CF910C943219DF91CF910895F7 +:10462000EF92FF920F931F93CF937C019B01613018 +:1046300081E0780710F020E031E08B01021B130BC2 +:10464000A70160E072E080EA9FE20E949A0E80EA91 +:104650009FE20E942D19C1E0013081E01807A8F007 +:104660001A954C2F50E0542F44274E0D5F1D20E02B +:1046700032E060E072E080EA9FE20E949A0E80EAF7 +:104680009FE20E942D19CF5FE7CF0115110589F038 +:104690004C2F50E0542F44274E0D5F1D980160E0D1 +:1046A00072E080EA9FE20E949A0E80EA9FE20E94F6 +:1046B0002D198AED9BE0CF911F910F91FF90EF9004 +:1046C0000C94321980910008813021F490918C086B +:1046D000933009F080E080FD1AC080917E2C81111A +:1046E00016C081E08093000893E090938C0880933B +:1046F0007C2C10927D2C2EB13FB1809108049091BA +:104700000904822B932B8093832C9093842C0895FF +:1047100010928C0810920008ECE7FCE210821182E3 +:10472000089590917C2C9923F1F080917D2C81113A +:1047300015C020917C2C2223B9F04EB15FB120919D +:10474000080430910904242B352B4091832C50917F +:10475000842C241B350B2634310530F081E0809306 +:104760007D2C892F089581E00895CF93C0917E2CF0 +:10477000CC23C1F02EB13FB180910804909109047F +:10478000822B932B2091812C3091822C821B930BB6 +:1047900020917F2C3091802C8217930718F0109273 +:1047A0007E2C90DF8C2FCF910895E0913E2FF091D9 +:1047B0003F2F82879387809338039093390308951E +:1047C000E0913E2FF0913F2F82859385409682871E +:1047D0009387809338039093390382859385089556 +:1047E000E0913E2FF0913F2F80E991E082879387FF +:1047F00080933803909339030895A0E2B6E081E0F6 +:1048000015968C93159720EA31E328B939B920E23F +:1048100032E32AB93BB910B813B812B816B817B8B2 +:1048200011B8E0E0F9E010A211A22FEF30E026A3CA +:1048300037A32FEF3FEF20A731A7808398E893831A +:1048400090E1948793E097831C968C931C9782E069 +:104850001A968C9308951F920F920FB60F921124FF +:1048600008B60F9218BE0BB60F921BBE8F939F9384 +:10487000EF93FF93E0E0F9E013828FE790E086ABDF +:1048800097AB81E190E080AF91AFE0E0FAE010A259 +:1048900011A28FEF9FEF86A397A389E883831682E7 +:1048A00081E084878EE0808310922A06FF91EF9149 +:1048B0009F918F910F900BBE0F9008BE0F900FBE6F +:1048C0000F901F9018951F920F920FB60F92112400 +:1048D00008B60F9218BE0BB60F921BBE2F933F93D4 +:1048E0008F939F93EF93FF932091280693B12670A7 +:1048F00081E009F080E0990F892B83B982B1882388 +:1049000009F463C012B883B18770873059F51092EB +:10491000000980E180930C091092030A1B9B03C0DD +:104920008CEA94E002C08CE694E08093260A90938F +:10493000270A82E081B981E080930C0A83E08093AA +:10494000060A86B197B1877049F090B18F5F8930C0 +:1049500011F09695FBCFE8B1F9B1908381E0809397 +:10496000852C36C083B1982F9C7091F1847091B1E1 +:1049700091111CC020B12695882311F080E001C060 +:1049800080E8282B20B986B197B1019686B997B9EE +:1049900087709927892BE1F4E8B1F9B1CF0101962D +:1049A00088B999B9208381E081B912C091B1913061 +:1049B00079F4EAB1FBB19F012F5F3F4F2AB93BB9B0 +:1049C000811190E0908311B803C082B1809582B9C3 +:1049D00088E880930309FF91EF919F918F913F9118 +:1049E0002F910F900BBE0F9008BE0F900FBE0F902F +:1049F0001F9018951F920F920FB60F92112408B6B0 +:104A00000F9218BE0BB60F921BBE2F933F938F933E +:104A10009F93EF93FF9381B1823008F49DC081B1E1 +:104A20008D3008F099C0E1B1F0E0EE0FFF1FEA5DB4 +:104A3000FF4D0190F081E02D19948FE790E0809375 +:104A4000260A9093270A88C08E9A8EE080934008A9 +:104A50008FE390E08093260A9093270A85E06FC049 +:104A60008E9886E081B98FEF82B914B815B8E8B195 +:104A7000F9B1808180B970C0009B05C08E9A82B167 +:104A8000809582B901C08E9887E059C0009B02C012 +:104A90008E9801C08E9A80B1869580B984B195B107 +:104AA000019684B995B984B195B187709927892BFE +:104AB00011F488E044C024B135B186B197B128170C +:104AC0003907B1F52BC0EAB1FBB1309711F0808105 +:104AD00001C082B1882311F08E9A01C08E9889E0BE +:104AE0002EC0EAB1FBB1309751F08081882311F0DC +:104AF0008E9801C08E9A3196EAB9FBB908C082B18E +:104B0000882311F08E9801C08E9A8FEF82B924B15C +:104B100035B186B197B12817390711F48AE00FC073 +:104B2000E8B1F9B1CF01019688B999B9818180B90D +:104B300086E005C08E988BE002C08E988CE081B92B +:104B40000BC01092000A1092060A109240081092B0 +:104B5000410881E08093862CFF91EF919F918F9186 +:104B60003F912F910F900BBE0F9008BE0F900FBE7C +:104B70000F901F901895CF93DF93E5E8FCE2108229 +:104B80001182E0E4F6E0128A84E08283C0E8D1E09A +:104B900082E68E83A0E2B6E081E016968C931697AB +:104BA00011968C93119796E012969C9312975196BA +:104BB0008C93519732E052963C9352971A961C92DE +:104BC0001A971B961C921B979FE019969C9399E548 +:104BD00098832AE529839A8390E491839683A0EBB6 +:104BE000B0E012962C911297207F12962C93129778 +:104BF00012962C911297226012962C9320E3218317 +:104C00002683908B8683358383E08183E0E0F8E020 +:104C100083E1818321E030E026A337A320A731A7D9 +:104C2000E0E8F8E014868083E0E2F3E0138211828A +:104C300088E0828391E19083A0913E2FB0913F2F35 +:104C40001A962D913C911B97208F318FE0E8F3E06D +:104C50009CE39283808393838183DF91CF91CDCD39 +:104C6000A0E2B6E01A961C921A97E5E8FCE21082E0 +:104C70001182E0E0F9E010821382178280E18487DC +:104C8000E0E0FAE010821382168281E08487E0E49B +:104C9000F8E01082118216968C938E980895CF9327 +:104CA000DF938091852C882309F47EC01092852C97 +:104CB000C6B1D7B1C730D10508F471C0AE01495FA4 +:104CC0005F4F93E0569547959A95E1F7E0913B2F1A +:104CD000F0913C2F60EA71E380E41995E0913E2F5A +:104CE000F0913F2F8781883019F483E18093632C02 +:104CF0008681883019F483E18093622CE091312F12 +:104D0000F091322FBE0180EA91E31995EC0194FFF6 +:104D100006C0DF7E80E292E38AB99BB902C01AB86E +:104D20001BB82097E1F1AE01495F5F4F83E05695D4 +:104D300047958A95E1F7E0913B2FF0913C2F60EA8F +:104D400071E381E41995E0913E2FF0913F2F878127 +:104D5000893019F483E18093632C8681893019F4BA +:104D600083E18093622CC6B9D7B980EA91E388B910 +:104D700099B910926008109261088FE090E08093DA +:104D800066089093670888E090E080936A089093A3 +:104D90006B0883E28093410883E081B905C01092DB +:104DA000000A1092060A29DD8091862C882329F0BA +:104DB0001092862CDF91CF9120CDDF91CF91089575 +:104DC000CF93DF93E0E4F6E0128A84E08283C0E8C8 +:104DD000D1E082E68E83A0E2B6E081E016968C9365 +:104DE000169711968C93119796E012969C931297B2 +:104DF00051968C93519732E052963C9352971A9663 +:104E00001C921A971B961C921B979FE019969C93D5 +:104E1000199799E598832AE529839A8390E49183E9 +:104E20009683C0EBD0E02A81207F2A832A812260EA +:104E30002A8320E321832683908B8683358393E026 +:104E40009183E0E0F8E093E1918321E030E026A354 +:104E500037A320A731A7E0E8F8E014869083E0E2CA +:104E6000F3E01382118298E0928321E12083C091C4 +:104E70003E2FD0913F2F2A853B85208F318FE0E850 +:104E8000F3E02CE3228390832383918315968C9304 +:104E9000E0E0F9E02FEF30E026A337A312A613A637 +:104EA00014A615A610821682178280831092000A1B +:104EB0001092872CEAE8FCE2108212821182DF91C4 +:104EC000CF91089581E08093260622DCE0E0F9E0AE +:104ED00010821782E0E0FAE010821782EAE8FCE232 +:104EE00011821282108208951F920F920FB60F92B4 +:104EF000112408B60F9218BE0BB60F921BBE2F934B +:104F00003F938F939F93EF93FF93E0E0F9E080E46A +:104F100084871782E0E8F3E082E0878389EB81836E +:104F200080EA91E38AB99BB981E090E084B995B9B0 +:104F300016B82EB13FB18091080490910904822BDC +:104F4000932B8093882C9093892C81E080938C2CD8 +:104F500018B817B81092872C88E080938706FF91C5 +:104F6000EF919F918F913F912F910F900BBE0F90DA +:104F700008BE0F900FBE0F901F901895E0E0F9E06B +:104F80008FEF94E086A397A380E6848780E38783EE +:104F90008FEF90E086AB97AB88E08093870608950B +:104FA0001F920F920FB60F92112408B60F9218BEDF +:104FB0000BB60F921BBE2F933F934F935F938F932C +:104FC0009F93EF93FF931092070A1092000A10929A +:104FD000470910924009809181038E7F809381035D +:104FE00084B195B180FF1AC0379B03C086B1869506 +:104FF00003C086B18695806886B984B195B1019663 +:1050000084B995B987709927892B41F4EAB1FBB12E +:10501000CF0101968AB99BB986B1808384B195B1DD +:1050200087709927892BC9F0E4B1F5B186B144B1F5 +:1050300055B193E0F695E7959A95E1F7E056FE4C69 +:1050400090E04770552728E030E0241B350B02C064 +:10505000959587952A95E2F7808381E080938B2C44 +:1050600010928C2C8FEF9FEF8093260A9093270A43 +:105070001092200A1092210A1092060A1092070A32 +:105080001092030A84E08093000A83E08093872CC7 +:10509000FF91EF919F918F915F914F913F912F9150 +:1050A0000F900BBE0F9008BE0F900FBE0F901F9079 +:1050B00018951F920F920FB60F92112408B60F92F7 +:1050C00018BE0BB60F921BBE8F93EF93FF93E0E8D1 +:1050D000F3E081818F7C8183E0E0FAE088E88383DC +:1050E00081E08083FF91EF918F910F900BBE0F9025 +:1050F00008BE0F900FBE0F901F9018951F920F9231 +:105100000FB60F92112408B60F9218BE0BB60F926D +:105110001BBE8F939F93EF93FF9380916009109232 +:1051200060091092610993E090934009813520F461 +:10513000813308F472C01BC08137E8F484B195B1A3 +:1051400080FF2EC086B18695806886B984B195B1FE +:10515000019684B995B987709927892B41F4EAB1F2 +:10516000FBB1CF0101968AB99BB986B1808386B124 +:10517000869580682CC086B18695806886B984B192 +:1051800095B1019684B995B987709927892B41F417 +:10519000EAB1FBB1CF0101968AB99BB986B1808390 +:1051A00086B18695806886B984B195B1019684B937 +:1051B00095B987709927892B41F4EAB1FBB1CF01EA +:1051C00001968AB99BB986B1808386B1869586B9E6 +:1051D00084B195B1019684B995B987709927892BC7 +:1051E00041F4EAB1FBB1CF0101968AB99BB986B10E +:1051F000808386B1869586B984B195B1019684B9CC +:1052000095B987709927892B41F4EAB1FBB1CF0199 +:1052100001968AB99BB986B18083FF91EF919F91E6 +:105220008F910F900BBE0F9008BE0F900FBE0F9086 +:105230001F9018950F931F93CF93DF93CDB7DEB7D1 +:10524000DA95CDBFDEBF80918C2C882309F483C012 +:105250004EB15FB180910804909109042091882C8F +:105260003091892C842B952B821B930B20911E202F +:1052700030911F202F5F3F4F2817390708F06BC070 +:105280001092070A1092000A1092470910924009E2 +:10529000809181038E7F8093810384B195B180FFDB +:1052A0001AC0379B03C086B1869503C086B1869528 +:1052B000806886B984B195B1019684B995B9877033 +:1052C0009927892B41F4EAB1FBB1CF0101968AB944 +:1052D0009BB986B1808384B195B187709927892B5A +:1052E000C9F0E4B1F5B186B144B155B113E0F6951A +:1052F000E7951A95E1F7E056FE4C90E04770552788 +:1053000028E030E0241B350B02C0959587952A953F +:10531000E2F7808381E080938B2C10928C2C2FEF0E +:105320003FEF2093260A3093270A1092200A10920A +:10533000210A1092060A1092070A1092030A94E0BA +:105340009093000A93E09093872C14B815B880933B +:105350008B2C10928C2C09DA81116FC2E2D9882330 +:1053600009F46BC280918C2C811167C280918A2CC8 +:10537000811105C080918B2C882309F45EC2809135 +:10538000872C833041F48091200A9091210A853244 +:10539000914008F452C280918B2C882309F4A2C05A +:1053A00084B195B1892B09F49DC084B195B108975A +:1053B00018F414B815B896C044B155B1495F5F4FA1 +:1053C000B3E056954795BA95E1F760EA71E3CE01EF +:1053D00001960E94445C80EA91E38AB99BB944B18A +:1053E00055B114B815B8898186958695898322E0D0 +:1053F00030E024173507B0F5F901A3E0F695E795FD +:10540000AA95E1F781E090E08C0F9D1FE80FF91F4E +:105410008081982F9695969590838370813049F07E +:1054200030F08230D1F486B18695806804C081E086 +:1054300015C086B1869586B984B195B1019684B9B7 +:1054400095B987709927892B41F4EAB1FBB1CF0157 +:1054500001968AB99BB986B1808380E02E5F3F4F69 +:10546000882339F284B195B187709927892BC9F0C7 +:10547000E4B1F5B186B144B155B173E0F695E79565 +:105480007A95E1F7E056FE4C90E04770552728E00A +:1054900030E0241B350B02C0959587952A95E2F7DD +:1054A0008083E0913E2FF0913F2F8781883019F45F +:1054B00083E18093632C8681883019F483E18093A3 +:1054C000622C44B155B1495F5F4F63E056954795F3 +:1054D0006A95E1F7E0913B2FF0913C2F60EA71E390 +:1054E00082E4199510928A2C10928B2C64B175B1BC +:1054F000E091312FF091322F80EA91E3199584B930 +:1055000095B984B195B1892B09F497C189E8809345 +:1055100081031092000A1092200A1092210A2FEFA4 +:105520003FEF2093260A3093270A8FE590E080937F +:10553000280A9093290A1092060A80E180930C0AA7 +:1055400093E09093070A10926009109261092093EA +:1055500066093093670920EA30E0209368093093A8 +:1055600069091092460980934C0981E080934709AC +:1055700081E1809380011092880110928003109243 +:105580002906E0913E2FF0913F2F8781893019F451 +:1055900083E18093632C8681893019F483E18093C1 +:1055A000622C44B155B1495F5F4F33E05695479542 +:1055B0003A95E1F7E0913B2FF0913C2F60EA71E3DF +:1055C00083E4199504B115B1013094E0190708F08E +:1055D00024C114B815B8A801495F5F4F23E0569560 +:1055E00047952A95E1F760EA71E380E292E30E9431 +:1055F000445C80EA91E38AB99BB986B1869580685C +:1056000086B984B195B1019684B995B98770992707 +:10561000892B39F481EA91E38AB99BB986B18093E9 +:10562000A03186B1869586B984B195B1019684B9C9 +:1056300095B987709927892B41F4EAB1FBB1CF0165 +:1056400001968AB99BB986B1808380E041E050E041 +:10565000E0E2F2E30417150708F495C0908190FF8B +:105660002BC086B1869586B984B195B1019684B96F +:1056700095B987709927892B41F4AAB1BBB1CD01A7 +:1056800001968AB99BB986B18C9386B1869580685C +:1056900086B984B195B1019684B995B98770992777 +:1056A000892B09F063C0AAB1BBB1CD0101968AB9BB +:1056B0009BB986B18C935AC0882351F186B18695E7 +:1056C00086B984B195B1019684B995B98770992747 +:1056D000892B41F4AAB1BBB1CD0101968AB99BB91E +:1056E00086B18C9386B1869586B984B195B10196C1 +:1056F00084B995B987709927892B41F4AAB1BBB1B8 +:10570000CD0101968AB99BB986B18C9380E02FC0F8 +:1057100096B19695906896B924B135B12F5F3F4FF9 +:1057200024B935B927703327232B49F4AAB1BBB16B +:105730009D012F5F3F4F2AB93BB996B19C9396B11B +:10574000969596B924B135B12F5F3F4F24B935B93D +:1057500027703327232BD1F6AAB1BBB19D012F5F50 +:105760003F4F2AB93BB996B19C9301C081E090812B +:10577000969590839A0127703327232B09F431964D +:105780004F5F5F4F67CF811129C086B186958068D2 +:1057900086B984B195B1019684B995B98770992776 +:1057A000892B41F4EAB1FBB1CF0101968AB99BB9CB +:1057B00086B1808386B1869586B984B195B101960C +:1057C00084B995B987709927892B41F4EAB1FBB167 +:1057D000CF0101968AB99BB986B1808384B195B116 +:1057E00087709927892BC9F0E4B1F5B186B144B12E +:1057F00055B193E0F695E7959A95E1F7E056FE4CA2 +:1058000090E04770552728E030E0241B350B02C09C +:10581000959587952A95E2F7808381E08093872C80 +:1058200080EA91E38AB99BB980E280930C098CE00D +:105830008093070985E58A95F1F7D395CDBFDEBF43 +:10584000DF91CF911F910F91089514B815B881E0A1 +:1058500080938A2C0C9462231092070A1092000AFB +:105860001092470910924009809181038E7F8093A6 +:10587000810384B195B180FF1AC0379B03C086B104 +:10588000869503C086B18695806886B984B195B146 +:10589000019684B995B987709927892B41F4EAB1AB +:1058A000FBB1CF0101968AB99BB986B1808384B1DF +:1058B00095B187709927892BC9F0E4B1F5B186B10C +:1058C00044B155B193E0F695E7959A95E1F7E05626 +:1058D000FE4C90E04770552728E030E0241B350B44 +:1058E00002C0959587952A95E2F7808381E08093A1 +:1058F0008B2C10928C2C8FEF9FEF8093260A909325 +:10590000270A1092200A1092210A1092060A109279 +:10591000070A1092030A84E08093000A83E08093D0 +:10592000872C1092872C10928B2C10928A2C0C941E +:1059300088231F920F920FB60F92112408B60F9270 +:1059400018BE0BB60F921BBE8F939F93EF93FF93DE +:1059500084E080938506E0E0F9E013828FE790E031 +:1059600086AB97AB81E190E086AF97AF10922B06A4 +:10597000FF91EF919F918F910F900BBE0F9008BEFA +:105980000F900FBE0F901F9018951F920F920FB699 +:105990000F92112408B60F9218BE0BB60F921BBEC1 +:1059A0002F933F934F935F938F939F93EF93FF9327 +:1059B0002091280694B1267081E009F080E0990FCB +:1059C000892B84B983B1882309F4E3C013B884B167 +:1059D0008770873009F0B5C084E080938606109206 +:1059E000000980E880930C0910920709109229069B +:1059F00086B197B1877049F090B18F5F893011F00F +:105A00009695FBCFE8B1F9B1908386B197B18093B9 +:105A1000912C9093922C8091912C9091922C07979D +:105A200008F45CC081E08093952C20EA32E32CB925 +:105A30003DB921E030E020938D2C30938E2C16B8A8 +:105A400017B815B899E8909380031092000A109245 +:105A5000200A1092210A4FEF5FEF4093260A5093DD +:105A6000270A2FE530E020932A0A30932B0A109260 +:105A7000060A20E220930C0A9CE09093070A1092F9 +:105A8000600910926109409366095093670940EAE2 +:105A900050E040936A0950936B0910924609209395 +:105AA0004C099093470990E19093820110928A01EA +:105AB000109281038093870389EB809380032EB13A +:105AC0003FB18091080490910904822B932B80931D +:105AD000932C9093942C82E081B961C08CE08093E8 +:105AE000290680EA91E388B999B980E292E38AB9FC +:105AF0009BB910B814B813B816B817B811B81092EB +:105B00002009109221098FEF90E08093260990934D +:105B100027098FEF9FEF80932E0990932F0981E043 +:105B20008093000988E88093030980E880930C093A +:105B300080EC8093070982E080932C0680932B06EB +:105B40002EC084B1982F9C7039F191B191111CC075 +:105B500020B1269582FF02C080E001C080E8282B9A +:105B600020B986B197B1019686B997B98770992700 +:105B7000892B91F4E8B1F9B1CF01019688B999B9AF +:105B8000208381E081B908C081B1813029F411B846 +:105B900003C083B1809583B988E880930309FF919E +:105BA000EF919F918F915F914F913F912F910F9026 +:105BB0000BBE0F9008BE0F900FBE0F901F90189550 +:105BC0001F920F920FB60F92112408B60F9218BEB3 +:105BD0000BB60F921BBE8F93EF93FF93E0E8F3E0B9 +:105BE00080818F7C8083E0E0FAE08AE8838381E033 +:105BF000808383E081B9FF91EF918F910F900BBE6D +:105C00000F9008BE0F900FBE0F901F9018951F9217 +:105C10000F920FB60F92112408B60F9218BE0BB652 +:105C20000F921BBE8F939F93EF93FF938091600918 +:105C3000109260091092610993E0909340098135B8 +:105C400020F4813308F4A7C003C0813758F165C040 +:105C500080918D2C90918E2C80FF0AC080918D2C8C +:105C600090918E2C0297C0F085B18695806802C015 +:105C700085B1869585B986B197B1019686B997B9F0 +:105C800087709927892B41F4ECB1FDB1CF010196C2 +:105C90008CB99DB985B1808380918D2C90918E2C8B +:105CA000029675C080918D2C90918E2C80FF1BC028 +:105CB00080918D2C90918E2C0297A8F085B18695BD +:105CC000806885B986B197B1019686B997B9877012 +:105CD0009927892B41F4ECB1FDB1CF0101968CB924 +:105CE0009DB985B1808385B1869585B986B197B117 +:105CF000019686B997B987709927892B41F4ECB141 +:105D0000FDB1CF0101968CB99DB985B18083809199 +:105D10008D2C90918E2C03963AC080918D2C909171 +:105D20008E2C80FF2FC080918D2C90918E2C02970D +:105D3000A8F085B18695806885B986B197B101963E +:105D400086B997B987709927892B41F4ECB1FDB1D9 +:105D5000CF0101968CB99DB985B1808385B18695B7 +:105D600085B986B197B1019686B997B98770992799 +:105D7000892B41F4ECB1FDB1CF0101968CB99DB9ED +:105D800085B1808380918D2C90918E2C0496809388 +:105D90008D2C90938E2CFF91EF919F918F910F906E +:105DA0000BBE0F9008BE0F900FBE0F901F9018955E +:105DB0001F920F920FB60F92112408B60F9218BEC1 +:105DC0000BB60F921BBE2F933F934F935F938F930E +:105DD0009F93EF93FF931092070A1092000A10927C +:105DE000030A1092470910924009809180038E7F28 +:105DF0008093800380918D2C90918E2C80FF15C014 +:105E000085B18695806885B986B197B1019686B9C6 +:105E100097B987709927892B41F4ECB1FDB1CF0177 +:105E200001968CB99DB985B1808386B197B1877091 +:105E30009927892BC9F0E6B1F7B185B146B157B1C1 +:105E400093E0F695E7959A95E1F7E056FD4C90E0E2 +:105E50004770552728E030E0241B350B02C095958C +:105E600087952A95E2F7808386B197B180938F2C2E +:105E70009093902C86B197B1049718F081E08093AD +:105E8000962C1092000A1092070A1092820110922A +:105E90008A018CE38093820388E0809380038CE006 +:105EA0008093290680EA91E388B999B980E292E368 +:105EB0008AB99BB910B814B813B816B817B811B886 +:105EC00010922009109221098FEF90E0809326090B +:105ED000909327098FEF9FEF80932E0990932F09BE +:105EE00081E08093000988E88093030980E880932B +:105EF0000C0980EC8093070982E080932C06809344 +:105F00002B06FF91EF919F918F915F914F913F9160 +:105F10002F910F900BBE0F9008BE0F900FBE0F90E9 +:105F20001F901895CF93DF934CE040938106A0E437 +:105F3000B6E052961C92529784E012968C93129778 +:105F4000C0E8D1E082E68E83E0E2F6E081E086837D +:105F5000818396E09283818B92E0928B12861386E6 +:105F60002FE0218729E528833AE539832A8320E435 +:105F700011962C93119716962C931697C0EBD0E0A0 +:105F80003A81307F3A833A8132603A8330E3119626 +:105F90003C93119716963C93169750962C935097D6 +:105FA00016968C93169715969C93159723E0119649 +:105FB0002C93A0E0B8E023E111962C93119761E0B7 +:105FC00070E096966D937C93979798966D937C93DB +:105FD0009997A0E8B8E01C961C921C972C93A0E21D +:105FE000B3E013961C92139711961C92119728E018 +:105FF00012962C93129731E13C93C0913E2FD09191 +:106000003F2F6A857B8558966D937C935997A0E8BE +:10601000B3E03CE312963C9312972C9313963C9377 +:10602000139711962C938583A5E9BCE21C921196D7 +:106030001C92418720EA31E328B939B920E232E3E2 +:106040002AB93BB910B814B813B816B817B811B8B4 +:10605000A0E0B9E090961D921C9291972FEF30E04E +:1060600096962D933C9397972FEF3FEF9E962D9307 +:106070003C939F978C9388E813968C93139780E8B2 +:106080001C968C931C9780EC17968C93948793871F +:10609000DF91CF910895E0E0FAE010821782E0E806 +:1060A000F1E012821286E0E8F3E08CE3828388E07C +:1060B0008083A0E2B6E01B961C921B9719961C9257 +:1060C0001997E0E0F9E010821382178280E8848754 +:1060D00081E016968C93089588E0809385068091E0 +:1060E000952C882391F11092952C4091912C5091F0 +:1060F000922C495F5F4F93E0569547959A95E1F74B +:10610000E0913B2FF0913C2F60EA71E384E4199514 +:10611000E0913E2FF0913F2F8781883019F483E181 +:106120008093632C8681883019F483E18093622CFC +:106130001092202E6091912C7091922CE091312F31 +:10614000F091322F80EA91E319958091962C882363 +:1061500099F11092962C40918F2C5091902C495F80 +:106160005F4F83E0569547958A95E1F7E0913B2F85 +:10617000F0913C2F60EA72E387E41995E0913E2F9D +:10618000F0913F2F8781883019F483E18093632C4D +:106190008681883019F483E18093622C81E08093BA +:1061A000202E60918F2C7091902CE091312FF091E6 +:1061B000322F80EA92E3199521B1223009F055C0BF +:1061C0006EB17FB180910804909109044091932CA5 +:1061D0005091942C862B972B841B950B40911E205D +:1061E00050911F204817590708F03FC01092000A2D +:1061F0001092070A1092820110928A018CE3809318 +:10620000820388E0809380038CE08093290680EAF3 +:1062100091E388B999B980E292E38AB99BB910B841 +:1062200014B813B816B817B811B810922009109204 +:1062300021098FEF90E080932609909327098FEF33 +:106240009FEF80932E0990932F0981E0809300099E +:1062500088E88093030980E880930C0980EC8093A0 +:10626000070920932C0620932B0688E0809386064E +:106270000895982F80919F2C882359F08091992C14 +:10628000811108C081E02091982C921718F080E0CD +:10629000089581E00895FF920F931F93CF93DF93AA +:1062A0001F92CDB7DEB700919C2C000F000F00515C +:1062B000FF24F394F0929F2C10E0B8016D5F7F4FA4 +:1062C00041E050E088E99CE20E942F0FB8016C5F2A +:1062D0007F4F41E050E0CE0101960E942F0F89814F +:1062E000881F8827881F8093972CF0929E2C1092ED +:1062F0009D2C1092992C10929B2C0F90DF91CF9196 +:106300001F910F91FF90089510929F2C80E1809330 +:106310009C2C8FEF8093982C1092972C81E0809387 +:106320009E2C10929D2C1092992C10929B2C0895CB +:1063300084E180939C2CAFCF89E280939C2CABCFDF +:1063400081E080939E2C089508958F929F92AF9242 +:10635000BF92CF92DF92EF92FF920F931F93CF9352 +:10636000DF9300D01F92CDB7DEB78C01FC01808196 +:1063700090919E2C9230E1F028F0933011F19430FE +:1063800051F14EC0292F2095217020939D2C9923E7 +:1063900011F0863219F0823509F042C084E4F80128 +:1063A0008083118282E080939E2C80E190E0DBC2AA +:1063B00090919D2C911102C08632B1F0823599F5F1 +:1063C00013C090919D2C911102C0863269F08235E4 +:1063D00009F05BC009C090919D2C911102C08632DA +:1063E00019F0823509F0F3C084E4F801808311824A +:1063F00081E0892713C080919B2C8111FCC0F8019A +:106400008081803509F476C108F006C1803309F433 +:1064100009C190919F2C911174C181E080939E2CB1 +:1064200080E090E0A0C28339C1F719821A821B82F2 +:106430001C8288E8898343E050E060E070E0CE0190 +:1064400002960E942F0FF8018181803209F4ABC0BF +:10645000803709F047C0F801928189819813B2C052 +:1064600093818A819813AEC094818B819813AAC0BE +:1064700095818C819813A6C084E0808361E070E0F0 +:10648000C8010E947D3C83E029C0853931F644E093 +:1064900050E064E070E0CE0101960E942F0FF801F9 +:1064A0008181803209F47FC08037E1F4F801928164 +:1064B0008981981387C093818A81981383C09481BE +:1064C0008B8198137FC095818C8198137BC010823B +:1064D00061E070E0C8010E947D3C84E080939E2CC6 +:1064E00038E171C0E82EE294AFE0EA22EA94EA943F +:1064F0008F70F82E88E090E08F1991092FEF30E02F +:10650000690102C0D594C7948A95E2F7F5E0EF16C9 +:1065100029F024E0E2122AC0FF20E1F044E050E03C +:10652000B8016E5F7F4FCE0101960E94375C892BC8 +:1065300061F499818A8189279B8189279C81892798 +:10654000F801968189278C2171F1F4E0EF120EC0D9 +:10655000F11038C044E050E0B8016E5F7F4FCE01CB +:1065600001960E94375C892BF1F02CC023E02E1598 +:1065700048F1F12CA701B8016E5F7F4FCE01019663 +:106580000E94375C892BF1F4D801AE0DBF1DE1E00C +:10659000F0E0EC0FFD1FEE0DFF1D12969C91808127 +:1065A0008927C82279F43981F80130832A8121832F +:1065B0009B8192838C8183832327922789278483DD +:1065C00038E201C030E020E0832F922FCCC1695F18 +:1065D0007F4F83E0769567958A95E1F76330710583 +:1065E00008F41BCF62507109C8010E94A83C8111B8 +:1065F00002CF81E092C110929B2C80913A2F8111A1 +:106600008BC160919A2CF4E06F9FB001112444E09B +:1066100050E0C80102967EC1803A09F455C0823A22 +:10662000C1F1F7CEF801F18080919F2C882359F0B9 +:106630008091972C882339F08091992C811103C087 +:10664000E090982C02C0E0909C2CFE1410F0F80111 +:1066500031C1C12CD12CF4E0FF9EB001112444E0E3 +:1066600050E0C8018C0D9D1D0E942F0FF394EF1078 +:1066700001C0F12C24E0C20ED11C80E1C816D10467 +:1066800051F760E170E0C8010E947D3C80E990E034 +:106690006AC1F801F180F1E0FF15C8F680919C2CE9 +:1066A000F816A8F68F2DE5DD882309F4C2C0C801CD +:1066B000029620913A2F21112FC1F4E0FF9EB001E4 +:1066C000112444E050E026C1F801F180F1E0FF150B +:1066D00008F0BDCF80919C2CF81608F0B8CF8F2D14 +:1066E000C8DD882309F4A5C0F0929A2C81E080933C +:1066F0009B2C12C1F80181818111A9CF10929E2C8F +:106700008FCE8C3309F40EC148F4893309F4A6C046 +:106710008A3391F18B3109F080CE6AC08B3409F451 +:106720000FC138F48E3309F078CE8DEBF8018083F9 +:1067300014C1803621F0853A09F4ABC06ECEF80161 +:10674000108284E0818383E0828381E08383848379 +:10675000158280919C2C843111F08EE001C08BE079 +:10676000F801868383E0878368E070E0C8010E94B7 +:106770007D3C80E590E0F7C0F801D180E280ED1427 +:1067800008F465CF80919C2CD81608F060CFE816ED +:1067900008F05DCF8091972C882351F08D2D69DD15 +:1067A000882309F446C08E2D64DD882309F441C096 +:1067B000F12C6D2D70E0E61AF70AFFEFEF1AFF0AD1 +:1067C000EE0CFF1CEE0CFF1C660F771F660F771F89 +:1067D000A701C8010E942F0FB701C8010E947D3C8C +:1067E000C7010296F3E0880F991FFA95E1F7BBC045 +:1067F00060919C2C660F660F6051E62EF12CB7015C +:10680000685F7F4F44E050E0CE0101960E942F0F59 +:106810009981F801818198130CC09A818281981323 +:1068200008C09B818381981304C09C818481981740 +:1068300011F086E072C081E08093992CB701645F0B +:106840007F4F42E050E0C8010E942F0F62E070E0ED +:10685000C8010E947D3C80E290E085C0F801618122 +:10686000633008F0F4CE80919C2C70E0680F711DAD +:10687000660F771F660F771F43E050E0C8010E9444 +:106880002F0F63E070E0C8010E947D3C88E290E039 +:106890006AC0F8012181E22EF12C9E2D8827856A9D +:1068A000092E000CAA0BBB0B32814C015D01A32AFF +:1068B000233010F0108233C080919C2CB701680FF8 +:1068C000711D660F771F660F771F44E050E0CE0101 +:1068D00001960E942F0F89819A81AB81BC81880D1E +:1068E000991DAA1DBB1D89839A83AB83BC83009726 +:1068F000A105B14010F084E010C080919C2CB7013C +:10690000680F711D660F771F660F771F44E050E018 +:10691000CE0101960E947D0F8AE0F801808384E019 +:1069200090E021C040E250E06AEC70E0C8010E94B3 +:106930005E5C60E270E0C801E0D780E191E013C0E6 +:1069400060919C2C660F660F605170E06B5F7F4F0B +:1069500041E050E0C8010E942F0F61E070E0C801E3 +:10696000CCD788E190E02496CDBFDEBFDF91CF91F8 +:106970001F910F91FF90EF90DF90CF90BF90AF905D +:106980009F908F900895CF93DF93EC0143E050E008 +:1069900060E070E00E942F0F44E050E064E070E09F +:1069A000CE010396DF91CF910C942F0F0F931F937D +:1069B000CF93DF931F921F92CDB7DEB78C01FC01FE +:1069C00090818181892798E88927928189278A8304 +:1069D0009381848189279581892796818927898355 +:1069E00043E050E060E070E0C8010E947D0F41E0AC +:1069F00050E063E070E0CE0102960E947D0F44E01B +:106A000050E064E070E0C80103960E947D0F41E011 +:106A100050E068E070E0CE0101960E947D0F0F907B +:106A20000F90DF91CF911F910F91089581E0809396 +:106A3000C32C84E090E08093A22C9093A32C88E058 +:106A40008093A12C1092A02C089581E08093C32CF8 +:106A500084E490E08093A22C9093A32C88E0809310 +:106A6000A12C1092A02C089581E08093C32C82E089 +:106A700090E08093A22C9093A32C88E18093A12C8A +:106A80001092A02C089581E08093C32C82E490E0C2 +:106A90008093A22C9093A32C88E18093A12C109238 +:106AA000A02C089581E08093C32C089508958F92BF +:106AB0009F92AF92BF92CF92DF92EF92FF920F938D +:106AC0001F93CF93DF93CDB7DEB76297CDBFDEBF05 +:106AD0008C015B018091C32C6730710501F5F801D1 +:106AE0009081882311F0963211F09235C1F421E0A3 +:106AF000811120E02093A02C882311F0963211F010 +:106B0000923559F49091A22C8091A32CF801908396 +:106B100081838FEF8093A42C37C0A12CB12C8530BA +:106B200009F497C050F48230A1F1C8F0833009F421 +:106B300068C0843009F481C0ACC5883009F41CC138 +:106B400038F4863009F491C0873009F4CAC0A1C571 +:106B5000893009F441C38D3008F463C39AC5982F76 +:106B6000909591709093A02CF8019081882311F05A +:106B7000963219F0923509F006C49091A22C8091BA +:106B8000A32CF8019083818384E08093C32C80E15F +:106B900081C5F8018081982F9D7F913419F48AE096 +:106BA00080835AC38033C1F462E070E0C801D0D65C +:106BB000882309F494C0F8016181F0E16F9FB0016E +:106BC000112440E150E0C8010E942F0F60E170E005 +:106BD000C80193D680E95EC5803A79F462E070E03E +:106BE000C801B6D6882309F47AC0F8018181809360 +:106BF000BA2C83E08093C32CD2CF803509F049C5ED +:106C00004AC060E170E0C801A3D6882389F0809172 +:106C10003A2F81110BC06091BA2CF0E16F9FB00147 +:106C2000112440E150E0C8010E947D0F8AE001C0BC +:106C300081E0F801808382E00DC39091A02CF801DF +:106C40008081911102C08632D1F0823509F0A3C350 +:106C500016C09091A02CF8018081911102C086325B +:106C600071F0823509F045C40AC09091A02CF8015A +:106C70008081911102C0863211F0823551F4209149 +:106C8000A22C8091A32CF8012083818381E08927A5 +:106C900077C38035C9F4F8018181882319F0F801A0 +:106CA0001082DAC262E070E0C80152D68823B9F0DF +:106CB000E0913B2FF0913C2F40E060E070E081E9F3 +:106CC00019951092C32CE5C490EA980F923008F001 +:106CD000B4C462E070E0C8013BD68111DDC481E03C +:106CE0004FC2C8010E94314264E07801F4E0EF0E27 +:106CF000F11CC7010E944D45E0913B2FF0913C2FC4 +:106D000044E0B70180EA1995F80194818091BB2C89 +:106D1000981329C095818091BC2C981324C096812A +:106D20008091BD2C98131FC097818091BE2C981321 +:106D30001AC08091BF2C80838091C02C8183809168 +:106D4000C12C82838091C22C838364E0C8010E949D +:106D50006647E0913B2FF0913C2F44E0B80181EA77 +:106D6000199588E004C2E0913B2FF0913C2F44E05C +:106D70006BEB7CE280EC2DC2F8018081803551F410 +:106D80008181811107C08281873521F483818D3C07 +:106D900009F405C264E0C8010E944D45F8018081F4 +:106DA000803309F0BDC062E070E0C801D1D588230E +:106DB00009F4A7C0F801618167FD04C0862F8370C4 +:106DC000833029F0862F8F708F3009F07FC0609359 +:106DD000BA2C8091A52C9091A62C3091A72C282F0D +:106DE00022952095492F4227407F09F03FC0232755 +:106DF0002F70E1F5929590959327907FB9F5262F06 +:106E000067FD02C0237003C02F7009F023E0809556 +:106E1000432F42954F702223B1F090E0022E02C022 +:106E2000959587950A94E2F7E32FF0E0022E02C0D1 +:106E3000F595E7950A94E2F73E2F50E002C055958C +:106E400047952A95E2F740FBCC24C0F8D12CF601F7 +:106E5000EE0FFF1FEE0FFF1F30FBEE24E0F8F12CCA +:106E6000EE0CFF1CEE298170E82B01C0E7E0F0E09A +:106E70008091B92CEE0FFF1FE05CFF4DE80FF11D74 +:106E80008081F8019801205F3F4F11922E173F0734 +:106E9000E1F79091A82CF801918782FF09C09091A9 +:106EA000A52C96839091A62C97839091A72C9087E0 +:106EB00084FF15C06360F0E16F9FB0011124665F2D +:106EC0007F4F46E050E0C8010A9607C080E1689F06 +:106ED000B001112440E150E0C8010E942F0F60E191 +:106EE00070E0C8010AD5E0913B2FF0913C2F42E1C0 +:106EF000B80180E8199562E1C8010E94664780E9FF +:106F000039C10E94584491E08927F8018083E091BB +:106F10003B2FF0913C2F44E0B80181EC19959CC1C6 +:106F2000803A61F462E070E0C80112D58823D9F19B +:106F3000F80181818093BA2C89E00DC0803C89F4EE +:106F400062E070E0C80104D5882369F1F80181810D +:106F50008093BA2C8BE08093C32C0E9458449AE013 +:106F60000EC1813C91F462E070E0C801F1D4882345 +:106F7000D1F0F80181818093BA2CFAE0FF2EF092D3 +:106F8000C32C0E9458448F25FBC0823C99F462E0D8 +:106F900070E0C801DDD4882331F0F801818180934D +:106FA000BA2C8CE0D8CFE0913B2FF0913C2F44E0FD +:106FB000B80121C0803B11F562E070E0C801C8D47F +:106FC000E0913B2FF0913C2F44E0B801882399F0E9 +:106FD00086E8199580913A2F8111BFCFF801618120 +:106FE000F0E16F9FB001112440E150E089EA9CE29A +:106FF0000E947D0FB2CF81EC1995BEC090EA980F28 +:10700000923008F0BFC062E070E0C801A1D48823CC +:1070100009F4B2C0F8018081803621F0EAE3CE2E77 +:10702000D12C03C070E3C72ED12CF801818187FFDA +:107030000CC0807FF0E18F9F7001112480ECC80E9E +:10704000D11C66EFA62EB12C08C08C7F90E1899FE1 +:107050007001112456E3A52EB12CE0913B2FF09145 +:107060003C2F42E0B80180E91995F80180818170D8 +:107070008093B92CC70144E0969587954A95E1F72E +:107080008093BA2C9091A42C981769F0B5016E0DDD +:107090007F1D44E050E085EA9CE20E942F0F809122 +:1070A000BA2C8093A42C68E0CE0101960E94800E39 +:1070B0008091392F44E050E0873019F463E070E0AC +:1070C00002C060E070E0CE010F960E942F0FB60163 +:1070D0006E0D7F1D46E050E0CE0109960E942F0FF5 +:1070E00089818093BB2C8A818093BC2C8B81809377 +:1070F000BD2C8C818093BE2C60E48BEB9CE20E94C3 +:1071000080498091BB2C8093BF2C8091BC2C8093B4 +:10711000C02C8091BD2C8093C12C8091BE2C80937B +:10712000C22C60E28FEB9CE20E94804920E0AE011D +:107130004F5F5F4FBE01615F7F4FCE010996E6D67C +:107140008981F80180838A8181838B8182838C810C +:107150008383E058FF4F8D81808331968E818083B9 +:1071600031968F81808331968885808387E08093F4 +:10717000C32C80E290E16CC30E94584491E08927BF +:10718000F8010ECD8035B9F4F8018181811187CDE8 +:1071900062E070E0C801DCD3882309F4A0CD10922E +:1071A000C32CE0913B2FF0913C2F40E060E070E079 +:1071B00081E919956EC2A501495F5F4F33E056958D +:1071C00047953A95E1F7E0913B2FF0913C2FB801BC +:1071D00082E9199581E0D4C062E1C8010E944D4561 +:1071E00060E170E0C801B4D3E0913B2FF0913C2FF7 +:1071F000882329F142E1B80181E8199580913A2F5D +:1072000081110BC06091BA2CF0E16F9FB001112485 +:1072100040E150E0C8010E947D0F0E9458449AE06E +:1072200015C066E0C8010E944D4564E070E0C801E9 +:107230008FD3811113C0E0913B2FF0913C2F44E09C +:10724000B80181EC19950E94584491E08927F80112 +:10725000808388E08093C32C84E01CC26091BA2CA8 +:10726000F0E16F9FB001112440E150E089EA9CE217 +:107270000E942F0F9091A92C8091AD2C809598138E +:10728000E3C28091B12C9813DFC29091AA2C809117 +:10729000AE2C80959813D8C28091B22C9813D4C28A +:1072A0009091AB2C8091AF2C80959813CDC280919A +:1072B000B32C9813C9C29091AC2C8091B02C8095BE +:1072C0009813C2C28091B42C9813BEC29091B52C71 +:1072D0008091B62C80959813B7C28091B72C9813E3 +:1072E000B3C28091B82C80959813AEC2C090A92CDF +:1072F000D090AA2CE090AB2CF090AC2CF8018080C0 +:107300009180A280B3808091C32C8B3009F081C220 +:10731000E0913B2FF0913C2F46E0B80185E81995AC +:10732000C818D908EA08FB08C092A92C33272F2DCA +:107330001E2D0D2D0093AA2CA701662777274093B9 +:10734000AB2C8F2D9927AA27BB278093AC2CEC2D33 +:10735000E095E093AD2CE02FE095E093AE2CE42F88 +:10736000E095E093AF2CE82FE095E093B02CC0922D +:10737000B12C0093B22C4093B32C8093B42C88E0B2 +:107380008093C32C86C1903409F083C182E080933E +:10739000C32C8AE0F5CE833909F093CC8091392F44 +:1073A000873009F0A1C043E050E060E070E0CE011A +:1073B00002960E942F0F88E88983F801918190320C +:1073C00019F0903761F024C0F80180833A8131834D +:1073D0002B8122839C819383232782272AC1F80152 +:1073E0008281883809F055C193818A81981351C1EF +:1073F00094818B8198134DC195818C81981349C1DB +:1074000084E0808361E070E0C80177D285E09FC0AE +:10741000E92EE294EFE0EE22EA94EA949F70F92ECE +:1074200088E090E08F1991092FEF30E0690102C0E8 +:10743000D594C7948A95E2F7F5E0EF1629F084E039 +:10744000E8122AC0FF20E1F044E050E0B8016E5F8E +:107450007F4FCE0101960E94375C892B61F49A819F +:107460008B81892798E889279C818927F801968153 +:1074700089278C2189F1F4E0EF120EC0F11009C1C7 +:1074800044E050E0B8016E5F7F4FCE0101960E944C +:10749000375C892B09F1FDC083E08E1508F4F9C033 +:1074A000F12CA701B8016E5F7F4FCE0101960E94BB +:1074B000375C892B09F0EDC0D801AE0DBF1DE1E0AE +:1074C000F0E0EC0FFD1FEE0DFF1D12969C918081E8 +:1074D0008927C82209F0DDC098E8F80190833A8135 +:1074E00031832B812283A1C044E050E060E070E052 +:1074F00007C0853909F0E5CB44E050E063E070E077 +:10750000CE0101960E942F0FF8018181803209F48B +:1075100085C0803701F5F801928189819813B9C03F +:1075200093818A819813B5C094818B819813B1C0DF +:1075300095818C819813ADC08091A12C808361E0EE +:1075400070E0C801DAD18FEF8093A42C86E080939D +:10755000C32C88E19FC0E82EE2947FE0E722EA9402 +:10756000EA948F70F82E88E090E08F1991092FEF40 +:1075700030E0690102C0D594C7948A95E2F7F5E03E +:10758000EF1629F084E0E8122AC0FF20E1F044E081 +:1075900050E0B8016E5F7F4FCE0101960E94375CCC +:1075A000892B61F499818A8189279B8189279C8114 +:1075B0008927F801968189278C2181F1F4E0EF1267 +:1075C0000EC0F11066C044E050E0B8016E5F7F4F1E +:1075D000CE0101960E94375C892B01F15AC083E0ED +:1075E0008E1508F456C0F12CA701B8016E5F7F4FCD +:1075F000CE0101960E94375C892B09F04AC0D80160 +:10760000AE0DBF1DE1E0F0E0EC0FFD1FEE0DFF1D24 +:1076100012969C9180818927C822D9F53981F80179 +:1076200030832A8121839B8192838C8183832327CA +:1076300092278927848388E22DC0823C09F0CBC041 +:10764000F8018181803E09F0CFC08281843B09F03E +:10765000CBC046E050E06AEA74E0CE0101960E9499 +:107660002F0F89818B3409F03ACB8A81893709F051 +:1076700036CB8B818B3109F032CB8C818A3E09F07D +:107680002ECB8D818B3709F02ACB8E818C3C09F073 +:1076900026CB80E090E0DCC0F8018081803621F0CC +:1076A0006AE3C62ED12C03C050E3C52ED12CF801BD +:1076B000818187FF0CC0807FF0E18F9F70011124D2 +:1076C00080ECC80ED11C46EFA42EB12C08C08C7FD4 +:1076D00090E1899F7001112436E3A32EB12CE09133 +:1076E0003B2FF0913C2F42E0B80180E91995F80159 +:1076F000808181708093B92CC70124E0969587958D +:107700002A95E1F78093BA2CB5016E0D7F1D44E0F8 +:1077100050E085EA9CE20E942F0F8091BA2C809362 +:10772000A42C68E0CE0101960E94800E8091392F32 +:1077300044E050E0873019F463E070E002C060E09C +:1077400070E0CE010F960E942F0FB6016E0D7F1DC7 +:1077500046E050E0CE0109960E942F0F8981809368 +:10776000BB2C8A818093BC2C8B818093BD2C8C8117 +:107770008093BE2C60E48BEB9CE20E948049809158 +:10778000BB2C8093BF2C8091BC2C8093C02C80910B +:10779000BD2C8093C12C8091BE2C8093C22C60E2C2 +:1077A0008FEB9CE20E94804987E08093C32C898103 +:1077B000F80180838A8181838B8182838C8183839A +:1077C000AE014F5F5F4FBE01615F7F4FCE010996F3 +:1077D000F0D080E25FCF982F9F77903329F0803AE6 +:1077E00019F0805C833078F481E08093C32C84E0CE +:1077F000F8018083E0913B2FF0913C2F40E060E066 +:1078000070E082EC8BCBE0913B2FF0913C2F40E07D +:10781000DECC8A3069F4E0913B2FF0913C2F46E0BA +:10782000B80184E81995C80CD91CEA1CFB1C7CCD56 +:107830008C3009F079CDE0913B2FF0913C2F46E060 +:10784000B80187E8199570CD0E94584496E0FECCA7 +:107850006296CDBFDEBFDF91CF911F910F91FF9058 +:10786000EF90DF90CF90BF90AF909F908F90089552 +:10787000CF93DF932091392F273071F4EC0143E04F +:1078800050E060E070E00E942F0F44E050E063E0C1 +:1078900070E0CE01039604C044E050E060E070E088 +:1078A000DF91CF910C942F0FCF93DF931F92CDB721 +:1078B000DEB72091392F273029F447E050E060E00F +:1078C00070E015C0FC0130812181232732812327FC +:1078D00033812327298344E050E060E070E00E9478 +:1078E0007D0F41E050E064E070E0CE0101960E941F +:1078F0007D0F0F90DF91CF91089520E42093D00069 +:1079000026EC2093D5002093D40021E02093D000D2 +:10791000DC01680F791FA617B70741F0ED91F0E081 +:10792000EE51FA4FE491E093D300F5CFE091D5000A +:10793000F0E0EE51FA4FE491EC93E091D400F0E0E6 +:10794000EE51FA4FE4911196EC931092D000089505 +:1079500020E42093D00026EC2093D5002093D4007F +:1079600021E02093D000DC01680F791FA617B7072C +:1079700041F0ED91F0E0EE51FA4FE491E093D30045 +:10798000F5CFE091D500F0E0EE51FA4FE4918C9103 +:107990008E130AC0E091D400F0E0EE51FA4FE4916A +:1079A00081E011969C919E1380E01092D00081702E +:1079B00008958F929F92BF92CF92DF92EF92FF92A3 +:1079C0000F931F93CF93DF93DC018C91D12C30E088 +:1079D0008695D794869537958695D79486953795CD +:1079E0008695D794869537958695D79486953795BD +:1079F00011968C9111978695D79486953795869593 +:107A0000D794869537958695D7948695379586959C +:107A1000D7948695379512968C911297F0E010E0E6 +:107A20008695F795869517958695F795869517957A +:107A30008695F795869517958695F795869517956A +:107A400013968C9113978695F7958695179586953D +:107A5000F795869517958695F7958695179586954A +:107A6000F7958695179514968C91149790E020E0E1 +:107A700086959795869527958695979586952795CA +:107A800086959795869527958695979586952795BA +:107A90001596EC91E6959795E6952795E695979539 +:107AA000E6952795E6959795E6952795E69597951A +:107AB000E69527954B01DA014C5F5F4F0C91E4018D +:107AC000B9904E01B026C32FD0E0BE0160557F4D66 +:107AD0007B01612F70E060557E4DE701F880EB017E +:107AE00088816F2D682BE22EF12CE701C055DD4D0A +:107AF0008881682B70E060577F4DEB018881869507 +:107B0000E7956F2F60718D2D817E6827892F807298 +:107B10006827832F84796827812F83776827822FAE +:107B20008A736827F62EF2946F25762F76957695D0 +:107B30006727FB2CF6266695F6267D2D6F2F892F5D +:107B4000F694879567957795B694C72ED12CE60164 +:107B5000C055DF4D6E01E62EF12CE701C055DE4D1C +:107B60007E01E601F881E7019881EF2EE92AC82E0F +:107B7000D12CE601C055DD4D9881E92AF12CE701B1 +:107B8000C057DF4D98819695E795F12FF071932FAF +:107B9000917EEF2EE926922F9072E926972F947905 +:107BA000E926962F9377E926982F9A73E926FE2CDB +:107BB000F294EF24CE2CC694C694EC24FB2CFE2425 +:107BC000E694FE24F694279517953795B694C32E20 +:107BD000D12CE601C055DF4D6E01E12EF12CE701FD +:107BE000C055DE4D7E01E601F881E7019881EF2E58 +:107BF000E92AC22ED12CE601C055DD4D9881E92A33 +:107C0000F12CE701C057DF4D98819695E795F62F47 +:107C1000F071972F917EEF2EE926982F9072E9262A +:107C2000932F9479E926912F9377E926922F9A73CF +:107C3000E926FE2CF294EF24CE2CC694C694EC24B4 +:107C4000FB2CFE24E694FE24F82FF694F795679516 +:107C50007795B694872F90E0EC01C055DF4D862FC5 +:107C600090E080559E4DF880EC0188818F29EF2EA1 +:107C7000F12CE701C055DD4D9881892B90E08057AC +:107C80009F4DEC0188818695E795912F9071832F08 +:107C9000817EE92EE826822F8072E826872F84795C +:107CA000E826862F8377E8268F2F8A73E826FE2C16 +:107CB000F294EF24CE2CC694C694EC24FB2CFE2424 +:107CC000E694FE24F694279517953795B694832F5E +:107CD00090E0EC01C055DF4D812F90E080559E4D26 +:107CE000F880EC0188818F29E22EF12CE701C05544 +:107CF000DD4D9881892B90E080579F4DEC01888164 +:107D00008695E795962F9071872F817EF92EF8261C +:107D10008F2F8072F826832F8479F826812F83771E +:107D2000F826822F8A73F8269F2D9295F926EF2C3C +:107D3000E694E694FE249B2D9F25F6949F258F2F95 +:107D40009695879567957795B694C72ED12CE601C1 +:107D5000C055DF4D6E01E62EF12CE701C055DE4D1A +:107D60007E01E601F881E7019881EF2EE92AC82E0D +:107D7000D12CE601C055DD4D9881E92AF12CE701AF +:107D8000C057DF4D98819695E795F12FF071932FAD +:107D9000917EF927922F9072F927972F9479F927DE +:107DA000962F9377F927982F9A73F9279F2F9295FB +:107DB000F927FF2EF694F694FF259B2D9F27F69525 +:107DC0009F279695279517953795B694C32ED12C56 +:107DD000E601C055DF4D6E01E12EF12CE701C055E3 +:107DE000DE4D7E01E601F881E7019881EF2EE92A58 +:107DF000C22ED12CE601C055DD4D9881E92AF12C27 +:107E0000E701C057DF4D98819695E795F62FF07101 +:107E1000972F917E9F27F82FF0729F27F32FF479E9 +:107E20009F27F12FF3779F27F22FFA739F27F92FC0 +:107E3000F2959F27F92FF695F6959F27FB2DF927A9 +:107E40009695F927982F8F2F869597956795779513 +:107E5000D72EF62F672F70E0EB01C055DF4D6F2F47 +:107E600070E060557E4DF880EB0188816F2D682BA6 +:107E7000E92EF12CE701C055DD4D8881682B70E0BB +:107E800060577F4DEB0188818695E795632F617E72 +:107E9000812F80718627622F607286276D2D64790D +:107EA00086276F2F63778627692F6A738627682F47 +:107EB00062958627682F669566958627B694B826BC +:107EC0008695B826812FB694279587953795182FD4 +:107ED0000E270D934A175B0709F0F0CDD092C42C02 +:107EE000F093C52C9093C62C3093C72C8093C82C4C +:107EF0002093C92CDF91CF911F910F91FF90EF90AC +:107F0000DF90CF90BF909F908F9008958F929F9217 +:107F1000AF92BF92CF92DF92EF92FF920F931F9397 +:107F2000CF93DF93FC01C62FF42EB52F8081A0E004 +:107F300050E0869557958695A79586955795869591 +:107F4000A795869557958695A79586955795869575 +:107F5000A7958181869557958695A795869557957E +:107F60008695A795869557958695A7958695579555 +:107F70008695A795828130E040E086954795869565 +:107F80003795869547958695379586954795869535 +:107F9000379586954795869537958381869547953C +:107FA0008695379586954795869537958695479515 +:107FB000869537958695479586953795648190E0A7 +:107FC00080E0669587956695979566958795669501 +:107FD0009795669587956695979566958795669525 +:107FE0009795B5806B2D669587956695979566955F +:107FF0008795669597956695879566959795669505 +:10800000879566959795B62EEA2FF0E0E055FF4DDF +:10801000032F10E000551E4DD081F8016081D62B52 +:10802000092F10E000551D4DF8016081ED2FE62B62 +:10803000F0E0E057FF4DC0800C2F172FCF2DDB2F26 +:108040007E01F4E0EF0EF11C7881F801B1918F010F +:10805000B7276B2DC6946795F42FF071E52FE17E5D +:10806000FE27E82FE072FE27EA2FE479FE27E32FB0 +:10807000E377FE27E92FEA73FE27EF2FE295FE272D +:10808000DF2ED694D694FD25EB2FEF27F695EF271C +:1080900020FDEC25E695879547955795B695C52E15 +:1080A000D12CF601E055FF4D6F01A42EB12CF50146 +:1080B000E055FE4D5F01F601D080F501C080DC285F +:1080C000E82FF0E0E055FD4DF081ED2DEF2BF0E0D5 +:1080D000E057FF4DC080C6946795F32FF071EA2FEB +:1080E000E17EFE27E92FE072FE27E52FE479FE27E7 +:1080F000E42FE377FE27E82FEA73FE27EF2FE295C0 +:10810000FE27DF2ED694D694FD25EB2FEF27F6958C +:10811000EF27DA2E20FDEC25E69597953795D79435 +:10812000CB2EC694AD2DB0E0A055BF4DE32FF0E0AF +:10813000E055FE4DAC91E081EA2BA92FB0E0A055AF +:10814000BD4DFC91EF2BF0E0E057FF4DB081B695AF +:108150006795F42FF071E52FE17EFE27E82FE0729E +:10816000FE27ED2DE479FE27E32FE377FE27E92FA5 +:10817000EA73FE27EF2FE295FE27AF2FA695A6956F +:10818000FA27EC2DEF27F695EF2720FDEB27E69554 +:10819000879547955795C694A52FB0E0A055BF4D3C +:1081A000E42FF0E0E055FE4DAC91E081EA2BA82FE2 +:1081B000B0E0A055BD4DFC91EF2BF0E0E057FF4D36 +:1081C000B081B6956795F32FF071ED2DE17EFE2716 +:1081D000E92FE072FE27E52FE479FE27E42FE3770D +:1081E000FE27E82FEA73FE27EF2FE295FE27AF2F39 +:1081F000A695A695FA27EC2DEF27F695EF2720FDFB +:10820000EB27E69597953795D794C694AD2DB0E0BA +:10821000A055BF4DE32FF0E0E055FE4DAC91E0815D +:10822000EA2BA92FB0E0A055BD4DFC91EF2BF0E05B +:10823000E057FF4DB081B6956795F42FF071E52FAB +:10824000E17EFE27E82FE072FE27ED2DE479FE2780 +:10825000E32FE377FE27E92FEA73FE27EF2FE2955E +:10826000FE27AF2FA695A695FA27EC2DEF27F695BA +:10827000EF2720FDEB27E695879547955795C69400 +:10828000A52FB0E0A055BF4DE42FF0E0E055FE4D26 +:10829000AC91E081EA2BA82FB0E0A055BD4DFC9138 +:1082A000EF2BF0E0E057FF4DB081B6956795F32FC7 +:1082B000F071ED2DE17EFE27E92FE072FE27E52F1C +:1082C000E479FE27E42FE377FE27E82FEA73FE2701 +:1082D000EF2FE295FE27AF2FA695A695FA27EC2D56 +:1082E000EF27F695EF2720FDEB27E6959795379535 +:1082F000D794C694ED2DF0E0E055FF4DA32FB0E0EC +:10830000A055BE4DF081EC91EF2BA92FB0E0A05508 +:10831000BD4DFC91EF2BF0E0E057FF4DB081B695DD +:108320006795F42FF071E52FE17EFE27E82FE072CC +:10833000FE27ED2DE479FE27E32FE377FE27E92FD3 +:10834000EA73FE27EF2FE295FE27AF2FA695A6959D +:10835000FA27EC2DEF27F695EF2720FDEB27E69582 +:10836000879547955795A52FB0E0A055BF4DE42FB1 +:10837000F0E0E055FE4DAC91E081EA2BA82FB0E093 +:10838000A055BD4DFC91EF2BF0E0E057FF4DF08183 +:10839000F6956795B62EED2DE17E632F60716E2701 +:1083A000E92FE0726E27E52FE4796E27E42FE3775B +:1083B0006E27E82FEA736E27E62FE2956E27E62FE9 +:1083C000E695E6956E27C694C6266695C62620FDD8 +:1083D000CF26C69497953795D794AD2DCD2CD12C1B +:1083E000F601E055FF4D6F01832E912CF401E0550D +:1083F000FE4D4F01F601B081F4016081B62BC92E0C +:10840000D12CF601E055FD4D6081EB2FE62BF0E01D +:10841000E057FF4DC080E72FF0E0EE51FB4FE491B5 +:10842000EC25EC837B257993EC16FD0609F00CCE48 +:108430005093C42C4093C52C8093C62CA093C72C7A +:108440003093C82C9093C92CDF91CF911F910F913D +:10845000FF90EF90DF90CF90BF90AF909F908F9064 +:108460000895BF92CF92DF92EF92FF920F931F93E6 +:10847000CF93DF93A091C42C5091C52C1091C62CA2 +:108480004091C72C3091C82C2091C92CFC01BC0113 +:108490006C5F7F4F0191952F90718A2F817E982775 +:1084A000812F80729827842F84799827832F837750 +:1084B0009827822F8A739827892F82959827892F4A +:1084C000869586959827C42ED12CE601C055DF4DA0 +:1084D0006E01E32EF12CE701C055DE4D7E01E60171 +:1084E000B881E7018881B82BE22EF12CE701C05555 +:1084F000DD4D8881CB2FC82BD0E0C057DF4DB88130 +:10850000B027B92796959B270695812F9695879535 +:108510005795A795B32FB071942F917EB927922FBD +:108520009072B9279A2F9479B927952F9377B92705 +:10853000982F9A73B9279B2F9295B9279B2F9695C1 +:108540009695B927CA2ED12CE601C055DF4D6E0194 +:10855000E52EF12CE701C055DE4D7E01E6011881C4 +:10856000E7019881192BE82EF12CE701C055DD4D6C +:108570009881C12FC92BD0E0C057DF4D988190273B +:108580009B27B695B927B02EB694922FB69597959E +:1085900037954795B52FB0712A2F217EB227282F06 +:1085A0002072B227242F2479B227232F2377B227D2 +:1085B000292F2A73B2272B2F2295B2272B2F2695EE +:1085C0002695B227C42FD0E08E0100551F4D6801BB +:1085D000C32FD0E08E0100551E4D7801E6010881C1 +:1085E000E7012881022BE92EF12CE701C055DD4D72 +:1085F0002881022B10E000571F4DE8012881C22F6F +:10860000CB25CB27B695BC272B2D2695B6958795E0 +:108610005795A795C32FC071B42FB17EBC27C92F22 +:10862000C072BC27CA2FC479BC27C52FC377BC270B +:10863000C82FCA73BC27CB2FC295BC27CB2FC6959A +:10864000C695BC27CA2FD0E0C055DF4D052F10E0DE +:1086500000551E4DF880E8011881F12A082F10E01E +:1086600000551D4DE8011881CF2DC12BD0E0C0571A +:10867000DF4DC881C227CB27B695BC272695B69576 +:10868000979537954795C52FC071BA2FB17EBC27F6 +:10869000C82FC072BC27C42FC479BC27C32FC3778F +:1086A000BC27C92FCA73BC27CB2FC295BC27CB2FA1 +:1086B000C695C695BC27C42FD0E0C055DF4D032F0B +:1086C00010E000551E4DF880E8011881F12A092FAD +:1086D00010E000551D4DE8011881CF2DC12BD0E0D1 +:1086E000C057DF4DC881C227CB27B695BC2726953A +:1086F000B69587955795A795D32FD071B42FB17E96 +:10870000DB27B92FB072DB27BA2FB479DB27B52F5F +:10871000B377DB27B82FBA73DB27BD2FB295DB27E2 +:108720001D2F169516951D27CA2ED12CE601C05572 +:10873000DF4D6E01E52EF12CE701C055DE4D7E01C7 +:10874000E6010881E701B8810B2BE82EF12CE70147 +:10875000C055DD4DB881C02FCB2BD0E0C057DF4DC9 +:10876000B881B227B127D12FD695DB27B22EB69488 +:10877000D695979537954795D52FD0712A2F217E7D +:10878000D227282F2072D227242F2479D227232FD3 +:108790002377D227292F2A73D2272D2F2295D2274C +:1087A0002D2F26952695BD2FB227C42FD0E08E0100 +:1087B00000551F4D6801C32FD0E08E0100551E4D9E +:1087C0007801E6010881E7012881022BE92EF12CCE +:1087D000E701C055DD4D2881022B10E000571F4DE9 +:1087E000E80118811B251B27DB2FD695D127D695AD +:1087F00087955795A795182F242F217E832F807159 +:108800002827892F807228278A2F84792827852F67 +:1088100083772827812F8A732827B22FB2952B2799 +:10882000B22FB695B6952B27EA2EF12CE701C0554D +:10883000DF4D7E01C52ED12CE601C055DE4D6E0107 +:10884000E701E880E6018881E82AC12ED12CE60103 +:10885000C055DD4D8881E82AF12CE701C057DF4D76 +:10886000B6948881CB2DC827C2272695B22FBC2766 +:108870002B2F2695979537954795292F6E177F07AC +:1088800009F008CEA093C42C5093C52C1093C62C8D +:108890004093C72C3093C82C9093C92CDF91CF9173 +:1088A0001F910F91FF90EF90DF90CF90BF900895B0 +:1088B000CF93DF93E4ECFCE2A0817181628133818C +:1088C00024819581472F40718A2F817E8427462FEE +:1088D00040728427432F44798427422F437784278B +:1088E000492F4A738427482F42958427482F46955D +:1088F00046958427482F46958427869567957795D2 +:10890000A795C32FD0E0C055DF4D422F50E0405512 +:108910005E4DB881EA018881B82B492F50E040555F +:108920005D4DEA018881CB2FC82BD0E0C05BDF4DC5 +:1089300088818695522F5071432F417E4527592FAC +:10894000507245275A2F54794527572F537745277B +:10895000562F5A734527542F52954527542F569515 +:1089600056954527542F5695452746959795279513 +:108970003795CA2FD0E0C055DF4D472F50E0405506 +:108980005E4DB881EA014881B42B462F50E0405536 +:108990005D4DEA014881CB2FC42BD0E0C05BDF4D99 +:1089A0004881842B8695572F50714A2F417E452749 +:1089B000562F50724527532F54794527522F5377FE +:1089C0004527592F5A734527542F52954527542F21 +:1089D000569556954527542F5695452746956795A4 +:1089E0007795A795C32FD0E0C055DF4D422F50E0BB +:1089F00040555E4DB881EA014881B42B492F50E0C3 +:108A000040555D4DEA014881CB2FC42BD0E0C05BBF +:108A1000DF4D4881842B8695CA2FD0E0C055DF4DAD +:108A2000472F50E040555E4DB881EA014881B42B94 +:108A3000462F50E040555D4DEA014881CB2FC42BB5 +:108A4000D0E0C05BDF4D4881842B532F517E422FF5 +:108A500040714527592F507245275A2F5479452781 +:108A6000572F53774527562F5A734527542F529522 +:108A70004527542F569556954527542F56954527EB +:108A80004695979527953795A083718362833383A5 +:108A900024839583DF91CF910895BF92CF92DF9287 +:108AA000EF92FF920F931F93CF93DF935091C42CBB +:108AB000C091C52CB090C62C4091C72C3091C82CC9 +:108AC0002091C92CFC01615008F4EAC19C2F9071DF +:108AD000852F817E98278B2D80729827842F84790B +:108AE0009827832F83779827822F8A739827892F37 +:108AF00082959827792F769576959727892F869551 +:108B00009827AC2F8B2D96958795A7955795C42FB1 +:108B1000D0E0C055DF4D032F10E000551E4D788189 +:108B2000E8019881792B022F10E000551D4DE801D6 +:108B30009881C72FC92BD0E0C059DF4D18811695F9 +:108B4000732F7071942F917E9727722F70729727D1 +:108B5000752F747997277A2F73779727782F7A73E1 +:108B60009727792F72959727792F7695769597275E +:108B7000792F76957927922F272F269597953795D8 +:108B80004795C52ED12CE601C055DF4D6E01EA2E6A +:108B9000F12CE701C055DE4D7E01E6017881E70149 +:108BA0002881722BE82EF12CE701C055DD4D28817C +:108BB000C72FC22BD0E0C059DF4D2881122B16954C +:108BC0007A2F7071252F217E2727782F7072272703 +:108BD000742F74792727732F73772727792F7A7348 +:108BE0002727722F72952727722F7695769527273C +:108BF000722F76952727BA2F26958795B795579583 +:108C0000C42ED12CE601C055DF4D6E01E32EF12CB0 +:108C1000E701C055DE4D7E01E6017881E70128813C +:108C2000722BE92EF12CE701C055DD4D2881C72FAD +:108C3000C22BD0E0C059DF4DA881A12BA695732F80 +:108C40007071242F217E2727792F70722727752F87 +:108C5000747927277B2F73772727782F7A73272715 +:108C6000722F72952727722F769576952727722F68 +:108C700076957227232F372F369597952795479509 +:108C8000C52FD0E0C055DF4D0B2F10E000551E4D15 +:108C90007881E8013881732B082F10E000551D4DB5 +:108CA000E8013881C72FC32BD0E0C059DF4DD881F0 +:108CB000AD2BA6957B2F7071352F317E3727782FFE +:108CC00070723727742F74793727722F737737278D +:108CD000792F7A733727732F72953727732F7695ED +:108CE00076953727732F7695372736958795B795DD +:108CF0005795C42FD0E0C055DF4D022F10E000552E +:108D00001E4D7881E8013881732B092F10E0005542 +:108D10001D4DE8013881C72FC32BD0E0C059DF4D6E +:108D2000D881AD2BA695722F7071342F317E7327A9 +:108D3000392F30727327352F347973273B2F3377D0 +:108D40007327382F3A737327372F32957327372FAE +:108D5000369536957327372F36957327342F7695AA +:108D6000979527953795C52FD0E0C055DF4D0B2F30 +:108D700010E000551E4D7881E8014881742B082FC2 +:108D800010E000551D4DE8014881C72FC42BD0E0ED +:108D9000C059DF4DD881DA2BD6957B2F7071452FC6 +:108DA000417E7427482F40727427432F44797427DB +:108DB000422F43777427492F4A737427472F4295D0 +:108DC0007427A72FA695A6957A27472F469574272F +:108DD0004B2F7695879547955795C42FB82EA32F7F +:108DE000B0E08D0100551F4D6801A22FB0E08D014C +:108DF00000551E4D7801D6010C91D7018C91082B9E +:108E0000E92EF12CD701A055BD4D8C91082B10E017 +:108E100000591F4DD8018C91D82BD695732F717E98 +:108E2000822F80717827892F80727827852F847907 +:108E30007827842F837778278B2D8A737827872F3D +:108E400082957827A72FA695A6957A27872F8695AE +:108E50007827432F322F272F2695979537954795BB +:108E6000292F852F90E080559F4D0C2F10E0005545 +:108E70001E4DDC019C91D8018C91892B0B2D10E0AB +:108E800000551D4DD8019C91892B90E080599F4D34 +:108E9000DC019C918D2F892B90818927819313CEA2 +:108EA0005093C42CC093C52CB092C62C4093C72CB1 +:108EB0003093C82C2093C92CDF91CF911F910F9133 +:108EC000FF90EF90DF90CF90BF900895EF92FF92C8 +:108ED0000F931F93CF93DF937091C42C5091C52CA7 +:108EE0002091C62C4091C72C3091C82CC091C92C20 +:108EF000E42FF0E0E055FF4DA32FB0E0A055BE4DAC +:108F0000F081EC91EF2BAC2FB0E0A055BD4DFC9162 +:108F1000EF2BF0E0E057FF4D1081DC01D0E0615015 +:108F200008F4DBC11695D795952F9071872F817E18 +:108F30008927922F90728927942F94798927932FCC +:108F4000937789279C2F9A738927982F9295892741 +:108F5000E82FE695E6958E27982F96958927869592 +:108F6000279557957795D695932F9071842F817E6D +:108F700089279C2F90728927972F94798927952F7D +:108F800093778927922F9A738927982F929589270B +:108F9000E82FE695E6958E27982F969589279C2FA2 +:108FA0008695979537954795E72FF0E0E055FF4D6B +:108FB000052F10E000551E4DC081F8018081C82B9F +:108FC000022F10E000551D4DF8018081EC2FE82B99 +:108FD000F0E0E059FF4D8081D82BD695E52FE07168 +:108FE000872F817E8E27E22FE0728E27E42FE4798F +:108FF0008E27E32FE3778E27E92FEA738E27E82F5A +:10900000E2958E27E82FE695E6958E27E82FE695E0 +:109010008E278695279557957795E42FF0E0E055B4 +:10902000FF4D032F10E000551E4DC081F8018081D7 +:10903000C82B092F10E000551D4DF8018081EC2F41 +:10904000E82BF0E0E059FF4D8081D82BD695E32F37 +:10905000E071842F817E8E27E92FE0728E27E72F23 +:10906000E4798E27E52FE3778E27E22FEA738E27A8 +:10907000E82FE2958E27E82FE695E6958E27E82FD4 +:10908000E6958E278695979537954795E72FF0E0DB +:10909000E055FF4D052F10E000551E4DC081F80131 +:1090A0008081C82B022F10E000551D4DF8018081F2 +:1090B000EC2FE82BF0E0E059FF4D8081D82BD695BE +:1090C000E52FE071872F817E8E27E22FE0728E27B9 +:1090D000E42FE4798E27E32FE3778E27E92FEA73D5 +:1090E0008E27E82FE2958E27E82FE695E6958E27C6 +:1090F000E82FE6958E278695279557957795E42F47 +:10910000F0E0E055FF4D032F10E000551E4DC081EB +:10911000F8018081C82B092F10E000551D4DF80182 +:109120008081EC2FE82BF0E0E059FF4D8081D82BB7 +:10913000D695E32FE071842F817E8E27E92FE07290 +:109140008E27E72FE4798E27E52FE3778E27E22F0E +:10915000EA738E27E82FE2958E27E82FE695E695AD +:109160008E27E82FE6958E27869597953795479514 +:10917000E72FF0E0E055FF4D052F10E000551E4DA4 +:10918000C081F8018081C82B022F10E000551D4DD1 +:10919000F8018081EC2FE82BF0E0E059FF4D808151 +:1091A000D82BD695E52FE071872F817E8E27E22F71 +:1091B000E0728E27E42FE4798E27E32FE3778E2762 +:1091C000E92FEA738E27E82FE2958E27E82FE695A0 +:1091D000E6958E27E82FE6958E2786952795579555 +:1091E0007795E42FF0E0E055FF4D032F10E0005598 +:1091F0001E4DC081F8018081C82B092F10E0005559 +:109200001D4DF8018081EC2FE82BF0E0E059FF4D77 +:109210008081D82BD695E72FF0E0E055FF4D052F44 +:1092200010E000551E4DC081F8018081C82B022F2F +:1092300010E000551D4DF8018081EC2FE82BF0E087 +:10924000E059FF4D8081D82BE42FE17E832F807180 +:10925000E827892F8072E827872F8479E827852FD0 +:109260008377E827822F8A73E8278E2F8295E82755 +:109270008E2F86958695E8278E2F8695E827E6958A +:10928000979537954795C92FE42FF0E0E055FF4DAE +:10929000832F90E080559E4D1081FC018081182B1A +:1092A0008C2F90E080559D4DFC018081E12FE82BB3 +:1092B000F0E0E057FF4D10818C91E82FF0E0EE5187 +:1092C000FB4FE4917D01F0E8EF0EF11C9E2F9127FA +:1092D000F70190838D278D9322CE7093C42C5093E9 +:1092E000C52C2093C62C4093C72C3093C82CC09318 +:1092F000C92CDF91CF911F910F91FF90EF900895AE +:109300000F931F93FC01862F4081518162817381ED +:109310008B0122273327803208F471C0D80123E063 +:10932000B695A7952A95E1F70A271B279801369548 +:10933000279536952795BBE0769567955795479580 +:10934000BA95D1F70227132720E030E095E1000F0E +:10935000111F221F331F9A95D1F7402B512B622BDF +:10936000732B8B0122273327D80133E0B695A795BD +:109370003A95E1F70A271B279801369527953695E8 +:109380002795BBE07695679557954795BA95D1F7A0 +:109390000227132720E030E095E1000F111F221F64 +:1093A000331F9A95D1F7402B512B622B732B8B01D6 +:1093B00022273327D80133E0B695A7953A95E1F7F0 +:1093C0000A271B2798013695279536952795BAE0E9 +:1093D0007695679557954795BA95D1F70227132744 +:1093E00020E030E096E1000F111F221F331F9A95F5 +:1093F000D1F7402B512B622B732B805289CF4083A6 +:109400005183028373831F910F910895AF92BF928E +:10941000CF92DF92EF92FF920F931F93CF93DF9340 +:109420006730710509F451C09B0127703327232B46 +:1094300009F04EC05B016C01EB0183E0D695C79546 +:109440008A95E1F77B0196E0F694E7949A95E1F727 +:10945000EC0EFD1EEC0CFD1C8E01015011090C0DD3 +:109460001D1DA701401B510B60E070E0C801019673 +:109470000E945E5C0C151D0520F1D801EC91F0E016 +:10948000EE51FB4F2491D701CD010A171B0768F459 +:10949000FC018081982F990F8E91881F8827881F43 +:1094A000892B11968C931197EFCF11968C91119770 +:1094B0008E7FE22FE170E82B1196EC930150110999 +:1094C000D9CFC5018C0F9D1F04C087E090E001C07B +:1094D000CB01DF91CF911F910F91FF90EF90DF9023 +:1094E000CF90BF90AF900895CF93DF93EC0182ECC3 +:1094F000888361E070E0CE010E947D3C8AE0809329 +:10950000A42D1092A52D68E170E0CE01DF91CF91DE +:109510007DCFEF92FF920F931F93CF93DF93EC01D8 +:10952000CB0167307105E1F169E070E00E948E5B6C +:10953000DE0180E090E008E010E08617970751F127 +:10954000FC0133E0F695E7953A95E1F7E80FF91F4E +:10955000AC0147705527EC0FFD1F208130E0042E31 +:1095600002C0359527950A94E2F72C9341155105D1 +:1095700071F0E181F0E07801E41AF50AA7017F01BA +:1095800002C0EE0CFF1C4A95E2F72E292C9301969F +:109590001196D3CF23E0880F991F2A95E1F702C0D7 +:1095A00087E090E0DF91CF911F910F91FF90EF90B6 +:1095B0000895EF92FF920F931F93CF93DF939C0137 +:1095C000CB016730710509F440C069E070E00E948A +:1095D0008E5B80E090E048E050E086179707A9F1A5 +:1095E000DC01E3E0B695A795EA95E1F7A80FB91F6E +:1095F000EC01C770DD27A20FB31FEC91F0E00C2E39 +:1096000002C0F595E7950A94E2F7209759F0119674 +:109610000C9111977A01EC1AFD0A01C0000FEA942F +:10962000EAF7E02BF0E0EE51FB4FE4911196AC919C +:10963000B0E002C0B595A795CA95E2F7ED01CE2737 +:10964000FE01E0FD04C00196C8CF81E001C080E0CA +:10965000DF91CF911F910F91FF90EF90089510929D +:10966000A42D08951092A42D1092CA2C1092A52D0D +:109670000895F8DF0E942C2C1092A42D08950895CF +:109680000895DC0123E633E66150E8F04D91942F14 +:10969000922780E1989FA00111244927E42FF0E050 +:1096A000232F332742954F70C9018427AC013E2FE9 +:1096B00022272427352743E0EE0FFF1F4A95E1F7C5 +:1096C0002E273F27E1CFC9010895EF92FF921F9304 +:1096D000CF93DF93EC017B018091A52D882339F096 +:1096E0008091A42D823008F0DBC01092A52DE114EA +:1096F000F10461F0B701CE015CDF882309F4D3C027 +:10970000B701CE0106DF7C0181E001C082E010914B +:10971000A42D163090F4133070F51230A8F484E0C4 +:1097200090E080931E2090931F2082E5888382E042 +:109730008093A42D87E090E0C7C0193008F467C07B +:109740001A3009F496C0ACC090E1E916F10411F4A6 +:1097500080FD03C01092A42D92C0888199818093CE +:10976000962D9093972D83E9888380E2898383E007 +:109770008093A42D6AC080FFEDCF88E2E816F10443 +:1097800048F32881898182279A8189279B818927AB +:109790009C818913DFCFA12FB0E01397CD01880FF3 +:1097A000991FA80FB91FA756B24D283821F483E09E +:1097B000FE01319602C084E0FE0101900D928A956F +:1097C000E1F745E050E0BE01CE0102960E944D5CFB +:1097D000133021F0143021F485E903C083E901C07E +:1097E00087E9888380E7898367E070E0CE010E9483 +:1097F0007D3C8091A42D8D5F8093A42D68E470E062 +:10980000CE01DF91CF911F91FF90EF90FFCD80FFB0 +:10981000A1CF98E1E916F10409F09CCF63E0CE01F5 +:1098200030DF009709F096CF288122FF11C0183051 +:1098300079F0163011F485E901C087E9888380E268 +:1098400089832EEF210F2093A42D60E170E0D8CF03 +:1098500021E02093A52D212F30E026503109322F11 +:10986000330F230F2C5F2093A32D28812093982D55 +:109870002BC0982F927031F081E08093A42D0E942C +:10988000252C0EC080FF05C063E0CE01FADE892BD7 +:1098900099F3CE01DF91CF911F91FF90EF9024CEED +:1098A00080E090E011C0A701495F5F4F83E05695CB +:1098B00047958A95E1F7E0913B2FF0913C2FBE014F +:1098C00081EC199580E023CFDF91CF911F91FF901C +:1098D000EF9008959F92AF92BF92CF92DF92EF9256 +:1098E000FF920F931F93CF93DF93CDB7DEB7C75689 +:1098F000D109CDBFDEBF8C017B01FB01608171818D +:10990000E4DED090A52DDD2009F445C18091A42D81 +:109910009AEF980F933008F057C0F8018081807259 +:10992000C82E1092862D5DE4A52E51E1B52E912C06 +:1099300047E650E0B501CE0101960E94165C8B818E +:10994000882349F029813A818091962D9091972D15 +:1099500028173907B9F48D81882329F09C818091DB +:10996000982D98130FC08F89882311F0CC2051F0C7 +:10997000E091862D81E08E0F8093862DF0E0E957EF +:10998000F24D90829394F7E6AF0EB11C8FE09812DF +:10999000CFCFC1100DC08091A42D9AEF980F9430B5 +:1099A00008F0AEC02091862DE7E8FDE280E08FC090 +:1099B00080EEF801808380E8818362E070E0C80176 +:1099C0000E947D3C89E095C0893029F7F7016081CC +:1099D0007181C801EEDDF70160817181811115C0CF +:1099E000CB01089667E070E00E948E5B462FE09105 +:1099F0003B2FF0913C2FB80181EC1995C80174DD23 +:109A0000F70180839183D12CC9C0C80182DDF701A1 +:109A100080839183F8016081262F30E043E09695A2 +:109A200087954A95E1F702972817390739F76E5F4E +:109A3000C80127DE892B11F7C12C97E6992E580112 +:109A4000FFEFAF1ABF0A8091862DC81608F0A3CF8A +:109A5000EC2DF0E0E957F24D6081969EB0011124A3 +:109A6000635B7E4E47E650E0CE0101960E94165C95 +:109A70008F89882349F14E8950E0F801808190E078 +:109A800001974817590741F02091862D422F50E049 +:109A9000415051093C2D08C0B501CE0106960E94E7 +:109AA000375C892B89F710C0832F90E084179507C6 +:109AB0003CF4FC01E957F24D818180833F5FF4CF94 +:109AC00021502093862DCA94C394BDCF8F5F8217F7 +:109AD00009F464C0919194509230C0F782E0F8018B +:109AE000808380E6818362E070E0C8010E947D3C53 +:109AF0008BE08093A42D60E270E0C80187DC80CF0A +:109B00008B3009F04BC0F7016081718161157105DF +:109B100009F43EC0C8014DDDD82EF7016081718186 +:109B2000811113C0CB01089667E070E00E948E5B44 +:109B3000462FE0913B2FF0913C2FB80181EC199515 +:109B40001092862DC801D0DC26C0C801E2DCF701E6 +:109B500080839183BC0183E0769567958A95E1F7D0 +:109B6000C8018FDD892B19F01092862D47CFF8019F +:109B70008581882331F0813059F48093862D85E0EA +:109B800004C081E08093862D84E08093872D06C0F9 +:109B90001092862D03C0F701808391838D2DC959C2 +:109BA000DF4FCDBFDEBFDF91CF911F910F91FF90AF +:109BB000EF90DF90CF90BF90AF909F9008955F920D +:109BC0006F927F928F929F92AF92BF92CF92DF92CD +:109BD000EF92FF920F931F93CF93DF93CDB7DEB732 +:109BE000C254D240CDBFDEBF7C01CF5BDD4F688366 +:109BF0007983C154D2408091CA2C843009F48BC13E +:109C000040F4823009F4D6C008F060C1813051F0D0 +:109C10008CC4863009F41EC308F446C2873009F4A8 +:109C2000C8C383C40091212F1091222F0115110563 +:109C3000C1F0A801495F5F4F63E0569547956A956B +:109C4000E1F761E27EE2C7010E94445C6091212F4E +:109C50007091222FC701DADB1092212F1092222F50 +:109C600021C2CF5BDD4F68817981C154D24061153B +:109C7000710509F4C7C0C7019CDCD82ECF5BDD4F4E +:109C800068817981C154D240C70143DCCF5BDD4F8D +:109C900088839983C154D2409C01295F3F4FC901F9 +:109CA000880F991F53E0969587955A95E1F7069688 +:109CB0008138910578F066EB73E2CE0101960E943F +:109CC000705C1092CA2CBE016F5F7F4F85E60E94C8 +:109CD000F2226BC4B3E036952795BA95E1F7A70158 +:109CE00060E870E0CE0101960E949A0E7C01CF5B85 +:109CF000DD4F8881C154D240CE5BDD4F9881C25484 +:109D0000D240CF5FDD4F9883C150D240CE5FDD4F50 +:109D10008883C250D24085EC93E29F938F9380E872 +:109D2000A82EB12CC5018E199F099F938F9381E0B6 +:109D300090E08C0F9D1F8E0D9F1D9F938F930E940F +:109D4000775CE80EF91EB5016E197F0922E030E05C +:109D5000AE014F5F5D4F81E090E08C0F9D1F8E0D37 +:109D60009F1D0E949A0E8E0D9F1D0F900F900F90B9 +:109D70000F900F900F909501281B390B41E050E098 +:109D80004C0F5D1F840F951FD11003C048EC53E2A8 +:109D900002C047ED53E25F934F933F932F939F93FE +:109DA0008F930E94775C0F900F900F900F900F9001 +:109DB0000F9087CF0091212F1091222F01151105AF +:109DC000C1F0A801495F5F4FA3E056954795AA955A +:109DD000E1F761E27EE2C7010E94445C9091212F8D +:109DE0008091222F1092212F1092222F092F182FAD +:109DF000DCC3CF5BDD4F28813981C154D2402115AE +:109E0000310551F488E0EBE4F4E2DE0111960190B3 +:109E10000D928A95E1F755CF295F3F4FE3E03695E4 +:109E20002795EA95E1F7A70160E870E0CE01019679 +:109E30000E949A0E7C01CF5BDD4F8881C154D240D5 +:109E4000CE5BDD4F9881C254D240CF5FDD4F988307 +:109E5000C150D240CE5FDD4F8883C250D24085ECE6 +:109E600093E29F938F93F0E8CF2ED12CC6018E19E9 +:109E70009F099F938F9381E090E08C0F9D1F8E0D23 +:109E80009F1D9F938F930E94775C8E0D9F1DB6013F +:109E9000681B790B22E030E0AE014F5F5D4FA1E01F +:109EA000B0E0AC0FBD1F8A0F9B1F0E949A0E10924C +:109EB000CA2CBE016F5F7F4F85E60E94F2220F9091 +:109EC0000F900F900F900F900F906FC3CF5BDD4FEF +:109ED00068817981C154D240C701F7DB2091A52D5B +:109EE000222309F425C32091A32D30E049E95DE246 +:109EF00064E170E0CE0101960E949A0EBE016F5F90 +:109F00007F4F85E60E94F2221092A52D1092CA2C56 +:109F10000E9488230AC38091852D811108C080E8A2 +:109F200090E00E94D52381E08093852D7BC0813015 +:109F300009F07AC08091A42D823008F075C080911C +:109F4000842D8F5F8093842D803109F06DC00E9435 +:109F5000E0238C019350409768F00115B8E01B078F +:109F600008F460C0E0E1F0E020E030E0A12CB12C8A +:109F700060E040C0ACE0BDE240E050E020E030E016 +:109F800080E090E0E0E0F0E060E07D91703149F445 +:109F90004732510509F405C361110EC0FA0161E0B1 +:109FA0000BC0662349F0BA016E1B7F0B6817790757 +:109FB00010F09F01CB0160E04F5F5F4F48325105C9 +:109FC00021F78430910508F03BC22CC0D601ED90FA +:109FD0006D01F12CEE16FF06B0F4611119C04F5F50 +:109FE0005F4F4837510591F7009709F029C2319723 +:109FF00009F426C27CE0C72E7DE2D72E40E050E077 +:10A0000080E090E0E3CF6111EACF5A0161E0E7CF51 +:10A01000BA016A197B096817790710F09501CB011D +:10A0200060E0DDCF1092842DCF5BDD4F68817981B8 +:10A03000C154D240C70149DB2091A52D222309F448 +:10A0400077C2E0913E2FF0913F2F0284F385E02DFF +:10A05000E058F10954E0F695E7955A95E1F7E45F89 +:10A06000F24D80818F5F80838091842D803121F437 +:10A070000E94E0231092842D1092A42D0E94252C82 +:10A0800080E5F7018083118262E070E0C7010E94E1 +:10A090007D3C81E08093A42D1092A52D60E270E0BC +:10A0A000C701B4D98C0181C2CF5BDD4F6881798152 +:10A0B000C154D240C70109DB2091A52D222309F408 +:10A0C00037C2D0900B2DDD2009F445C0CF5BDD4FAA +:10A0D00008811981C154D2400115110549F410922B +:10A0E0000B2D1092A52D1092A42D0E94252C5DC23F +:10A0F000023A110538F0B801C7015BDA01E08027A8 +:10A10000082F02C001E010E0CF5BDD4F688179814C +:10A11000C154D240C701FDD9CF5BDD4F88839983FD +:10A12000C154D24000FD05C062E1C701AADA892B03 +:10A1300029F0ACEFAD0DA0930B2D2AC0F4E0DF9E0B +:10A14000D0011124A554B34D80E1F70101900D9287 +:10A150008A95E1F71DC042E050E062E872E1CE016D +:10A1600001960E94165CE5E8F2E1E4912091962DBB +:10A170003091972D89819A812817390721F4809190 +:10A18000982DE81729F01092A42D0E94252CCDC1FE +:10A1900080910B2D803109F04DC01092A52D1092A9 +:10A1A0000B2D1092CA2C20E130E04BEC5CE267E80A +:10A1B00070E0CE0101960E949A0E65EC73E2CE012A +:10A1C00081960E94705C20E130E04BED5CE265E638 +:10A1D00070E0CE0183960E949A0E65EC73E2CE0188 +:10A1E0008D5B9F4F0E94705C20E130E04BEE5CE2A3 +:10A1F00063E470E0CE018B5B9F4F0E949A0E65EC8A +:10A2000073E2CE018B599F4F0E94705C20E130E0D9 +:10A210004BEF5CE261E270E0CE0189599F4F0E94F2 +:10A220009A0E0E948823BE016F5F7F4F85E60E94D1 +:10A23000F2227BC190E3D7019C9311968C9362E04C +:10A2400070E0C7010E947D3C80910B2D8C5F809354 +:10A250000B2D24CFBE016F5B7D4FC7013BDB8823F5 +:10A2600009F4E7C08091862D811103C06DEE73E281 +:10A2700027C08130A1F0912C80E090E000E010E058 +:10A2800027E6822E7E01BFEFEB1ABDEFFB0A30E01E +:10A29000C32E34E2D32EA12C42E0B42E40C06091F4 +:10A2A000872DE7E66E9FB00111246C587E4E40E486 +:10A2B00050E0CE0101960E94165CBE016F5F7F4F99 +:10A2C00085E60E94F22255C00130F2E01F0760F5DA +:10A2D000E92DF0E0E957F24D6081869EB00111242E +:10A2E0006C587E4E40E450E0C7010E94165CFF921D +:10A2F000EF92DF92CF92C501801B910B9F938F93BA +:10A3000081E090E08C0F9D1F800F911F9F938F9392 +:10A310000E94775C080F191F9394CDBFDEBF209178 +:10A32000862D921688F204C0081B190BF12C06C06A +:10A33000013032E01307C0F7FF24F394EDEFFFEF95 +:10A34000EC0FFD1FE00FF11F8EE28083EEEFFFEFB9 +:10A35000EC0FFD1FE00FF11F1082BE016F5F7F4FFA +:10A3600085E60E94F222F11004C088EE90E10E947E +:10A37000321981EE90E10E94321962E070E086E9C4 +:10A380009DE20E9410238BED90E10E9432196091B2 +:10A39000A32D70E089E99DE20E94102385ED90E1F4 +:10A3A0000E94321961E070E088E99DE20E9410236A +:10A3B00037C0BE016F5B7D4FC7018CDA8823C9F1BE +:10A3C0008091862D813039F58091872D833009F475 +:10A3D000BDC028F4813059F0823099F0DFC08A3056 +:10A3E00031F008F4DBC08D50823058F0D7C0809136 +:10A3F000A32D843009F4ACC0873009F0CFC015E03C +:10A40000AAC08091A32D843009F4A4C0873009F03C +:10A41000C5C017E0A0C067E074E285E60E94F222A2 +:10A420001092CA2C1092862D0E9488231092A52D7E +:10A430007CC0CF5BDD4F08811981C154D240B5C0CB +:10A440001092852D009709F475C096958795285F21 +:10A450003F4F820F931F54E0880F991F5A95E1F7E1 +:10A460000E94D523E0913E2FF0913F2F62857385A6 +:10A47000CF0183539F428F5F9F4F0E94EE6260E047 +:10A4800070E085E60E94F2220115184008F455C0DC +:10A49000B8E7AB2EB12C0CE01DE260E8E62EF12C03 +:10A4A00073EE672E73E2772EEAE05E2EFE013196A0 +:10A4B0006F01F9EE8F2EF3E29F2EFF92EF927F92C3 +:10A4C0006F921F925F92DF92CF920E94775CC601DB +:10A4D0000E942D19D8018C91CDBFDEBF882389F150 +:10A4E0001F928F939F928F921F925F92DF92CF92D3 +:10A4F0000E94775CC6010E942D19CDBFDEBF8AE4A1 +:10A5000091E10E943219D8011D928D01B0E1EB0E4C +:10A51000F11CC8018C509D428A159B0570F2109267 +:10A52000A52D1092CA2C0E942C2C00E010E03DC0FA +:10A530008C013BC00E94F02395CFA8E2AA2EB12C3B +:10A54000AACF6DE283E090E273D7D9CF11E003C0C8 +:10A5500014E001C016E06DE274E285E60E94F2228A +:10A56000812F0E94FD0DE0912B2FF0912C2F19953A +:10A57000E091352FF091362F89E99DE21995E09110 +:10A580003B2FF0913C2F4091392F69E97DE283E127 +:10A5900019950E9490100E94121742CF68E374E24E +:10A5A0003CCF662309F40DCDFECCC801CE5BDD4F58 +:10A5B000CDBFDEBFDF91CF911F910F91FF90EF9044 +:10A5C000DF90CF90BF90AF909F908F907F906F90D3 +:10A5D0005F90089581E080931F2EE0913E2FF091CF +:10A5E0003F2F82859385809320209093212008958A +:10A5F00010921F2E1092A62D089508950895F8CF59 +:10A600000F931F93CF93DF93CDB7DEB72A97CDBFBC +:10A61000DEBF2091A62D213009F026C18C0180914A +:10A620001F2E833009F446C028F4813061F0823057 +:10A63000D1F019C1853009F452C008F476C08630D3 +:10A6400009F499C010C188E0809306068091202EFD +:10A65000811109C1F8018081863219F0823509F033 +:10A6600002C182E076C08091202E8130B1F4623147 +:10A67000710599F4F801808185FD0FC08181807E8C +:10A6800061F4828180FD09C062E170E0C8010E942E +:10A69000D94A882311F083E05CC08091202E81117B +:10A6A0005BC0F8018081863209F4DDC0823509F093 +:10A6B00053C0D9C08091202E81114EC060317105E8 +:10A6C00009F04AC0F8018081982F907F903909F0F5 +:10A6D00043C08970813009F03FC085E03AC0809165 +:10A6E000202E813061F46D32710549F46DE270E025 +:10A6F000C8010E94D94A882311F084E02AC081E071 +:10A7000080931F2E88E080930606809120209091F0 +:10A710002120811528E0920708F494C060E070E0E1 +:10A7200083E594E20E94F2229EC08091202E811146 +:10A7300013C06834710581F4F8018081982F907FEF +:10A74000903951F48970813039F48181803721F456 +:10A7500086E080931F2E87C081E080931F2E88E0C3 +:10A760008093060680912020909121208115F8E0A9 +:10A770009F07A0F667C08091202E813009F053C05A +:10A780006B31710509F04FC06BE170E0C8010E94A8 +:10A79000D94A882309F447C0F801808182FD7BCF24 +:10A7A00081E080931F2E88E080930506E0912020B1 +:10A7B000F0912120E058F10994E0F695E7959A95FB +:10A7C000E1F7E955F24D80818F5F808360E070E0B2 +:10A7D00085E60E94F222809121208F938091202093 +:10A7E0008F9383EE93E29F938F931F928AE08F93D0 +:10A7F0008E010F5F1F4F1F930F930E94775CC8015C +:10A800000E942D19E0913E2FF0913F2F62857385B4 +:10A81000CF0183539F428F5F9F4F0E94EE62E8DE1D +:10A82000CDBFDEBF20C081E080931F2E88E08093E3 +:10A83000060680912020909121208115E8E09E0756 +:10A8400008F06CCFFC01E058F10984E0F695E7953B +:10A850008A95E1F7E955F24D10820E94E02380933A +:10A8600020209093212002C080E090E02A96CDBF66 +:10A87000DEBFDF91CF911F910F9108950F931F932A +:10A88000CF93DF93CDB7DEB7EA97CDBFDEBF05EA42 +:10A8900013E395D2F80181938F01F3E30D3A1F077B +:10A8A000C1F70E94E21906D3882309F4FAC0809107 +:10A8B000A5339091A633953009F46FC030F49130F0 +:10A8C00069F168F0933051F1ECC0983009F4C2C0DE +:10A8D000993009F4C8C0963009F0E3C072C08038DE +:10A8E00091F0823809F0DDC08091A9338F7087D252 +:10A8F000E091AF33F091B033118112FB112710F9C1 +:10A9000080E07DD206C01091A1338091A2338111E5 +:10A910001260EAD2812F63D280E0A1C0282F2D7F60 +:10A9200009F0BFC0882319F0823061F0BAC080916D +:10A93000A733813009F0B5C0933009F080E08093EF +:10A94000A23327C08091A733811123C0E091A9339E +:10A950001E2F1F7009F4A5C0812F51D28091A633FC +:10A96000833011F4EDD215C0E091AF33F091B033E4 +:10A9700081818B7F818324E8129FF0011124ED50A7 +:10A98000FC4C1082E091AF33F091B03380818E7F28 +:10A99000808380E034D2A8D264C0811182C010913B +:10A9A000A7331F77A1D28FD35FD28823E9F3109307 +:10A9B000C304111102C082E001C083E08093A4337C +:10A9C00070C08058823008F06CC08091A73390919D +:10A9D000A8338C3DE3E09E0761F583E08A838AE338 +:10A9E00089834FB7F894DE01139620E038E052E0F7 +:10A9F0005093CA01E32FF0E0E4911092CA0120FFC6 +:10AA000003C0E295EF703F5FEF708E2F90E0EA3069 +:10AA100010F0C79601C0C0968D939D932F5F2C3187 +:10AA200039F74FBF61D26AE370E0CE010196A5D03D +:10AA30000FC0AE014F5F5F4F6091A9330E940E0DB2 +:10AA40008C01892B71F150D2B80189819A8111D181 +:10AA5000A7D127C0803829F547D28091A033BFD134 +:10AA600086D131D31EC081111CC08091A733909133 +:10AA7000A83399270297ACF437D28091A7338093FB +:10AA8000A03321D38091A033811106C08091C304EB +:10AA9000811102C081E001C084E08093A4330E9450 +:10AAA000DE1908D2882311F01FD24AD2EA96CDBF10 +:10AAB000DEBFDF91CF911F910F9108950895CF933D +:10AAC0008091A433882351F0C091B13380E097D1B5 +:10AAD000F1D18111D3DE8C2FCF9191C1CF91089507 +:10AAE000CF92DF92EF92FF920F931F93CF93DF935A +:10AAF000EC018B017A01FDD2811136C0E114F10421 +:10AB000039F0F70180819181081B190BC80FD91FFB +:10AB1000C12CD12C0115110531F18091AD339091EB +:10AB2000AE33FC01EF5BFF4F208131978081281706 +:10AB300090F01DD1C4DFE114F10449F0F7018081E8 +:10AB40009181C80ED91EC082D18285E00DC0D1D2BC +:10AB5000882301F309C0899142D101501109FFEF07 +:10AB6000CF1ADF0AD7CF80E0DF91CF911F910F91ED +:10AB7000FF90EF90DF90CF900895DF92EF92FF92D9 +:10AB80000F931F93CF93DF93D82FC92F8B01809101 +:10AB9000B133806834D18091AB339091AC3380175E +:10ABA000910728F00115110519F4E1D001C08C01BD +:10ABB000ED2EFC2ED12C0115110509F440C0809119 +:10ABC000A433811102C082E04CC0853011F483E0CF +:10ABD00048C070D1882311F081E043C051D1811168 +:10ABE0003CC042D1882339F32091B1338091AD33F9 +:10ABF0009091AE33FC0127FF05C0EF5BFF4FC08192 +:10AC0000D0E013C0E05CFF4FC08131968081D0E07E +:10AC1000C81BD1090AC0C830D10550F4F701819191 +:10AC20007F01DDD00150110921960115110599F719 +:10AC3000DD24D394289709F0D12C99D0BCCFD11022 +:10AC4000BECF0BC08091A433882309F4BCCF8530DC +:10AC500009F4BDCF2FD18111BFCF12D1882391F339 +:10AC600080E0DF91CF911F910F91FF90EF90DF90E7 +:10AC70000895DF92EF92FF920F931F93CF93DF938C +:10AC8000D82FC92F8B018091B1338068B8D08091C3 +:10AC9000AB339091AC338017910728F00115110563 +:10ACA00019F465D001C08C01ED2EFC2ED12C0115BC +:10ACB000110509F442C08091A433811102C082E0E1 +:10ACC0004EC0853011F483E04AC0F4D0882311F0DF +:10ACD00081E045C0D5D081113EC0C6D0882339F36C +:10ACE0002091B1338091AD339091AE33FC0127FFB9 +:10ACF00005C0EF5BFF4FC081D0E015C0E05CFF4FA7 +:10AD0000C08131968081D0E0C81BD1090CC0C83009 +:10AD1000D10560F4F701849162D0FFEFEF1AFF0ACA +:10AD20000150110921960115110589F7DD24D394ED +:10AD3000289709F0D12C1BD0BACFD110BCCF0BC0B3 +:10AD40008091A433882309F4BACF853009F4BBCFAE +:10AD5000B1D08111BDCF94D0882391F380E0DF91F1 +:10AD6000CF911F910F91FF90EF90DF900895E091A8 +:10AD7000AF33F091B033A091AD33B091AE33AF5B50 +:10AD8000BF4F8C9190E08283938380818D79808303 +:10AD9000E091AD33F091AE33EF5BFF4F1082089539 +:10ADA000E091AF33F091B03380818D798083E09171 +:10ADB000AD33F091AE33EF5BFF4F10820895809179 +:10ADC000AD339091AE33FC01EF5BFF4F208131E05A +:10ADD000320F3083FC01E20FF11D80810895209134 +:10ADE000AD333091AE33F901EF5BFF4F908141E01D +:10ADF000490F4083F901E90FF11D80830895809385 +:10AE0000B133482F4F7050E06091C6047091C70471 +:10AE10009A0194E0220F331F9A95E1F7E4E887FF47 +:10AE200011C0E49FC001E59F900D11248C509C4CF3 +:10AE30008093AD339093AE33C90108969B01280FE0 +:10AE4000391F0DC0E49FC001E59F900D11248E5461 +:10AE50009C4C8093AD339093AE33260F371F2093D5 +:10AE6000AF333093B03308958091B1338068C7DF3A +:10AE7000E091AF33F091B033808186958170089571 +:10AE80008091B1338F77BBDFA091AF33B091B033F6 +:10AE90008C9185FF0DC0E091AD33F091AE331296E9 +:10AEA0008D919C911397E05CFF4F808381E0089522 +:10AEB00080E008958091B1338F77A1DFA091AF3307 +:10AEC000B091B0338C9184FF0DC0E091AD33F0911F +:10AED000AE3312968D919C911397E05CFF4F808367 +:10AEE00081E0089580E008958091B1338F7787DF06 +:10AEF000E091AF33F091B03380818D788083E09121 +:10AF0000AF33F091B033808181608083E091AD33C5 +:10AF1000F091AE33EF5BFF4F10828091B1338068C8 +:10AF20006EDFE091AF33F091B03380818160808338 +:10AF3000E091AD33F091AE33EF5BFF4F1082089597 +:10AF4000E091AF33F091B033818184608183E091EF +:10AF5000AF33F091B0338181807C803459F480919B +:10AF6000B13380584CDFE091AF33F091B033818141 +:10AF70008460818308951F93CF93DF93C82F162F8A +:10AF8000D42F3DDFE091AF33F091B0331182E091E7 +:10AF9000AF33F091B0338C2F881F8827881F880F1C +:10AFA0008083E091AF33F091B0331183E091AF3300 +:10AFB000F091B033128213822091AD333091AE33D1 +:10AFC00024833583CC0FCC0BCD23F901E05CFF4FFC +:10AFD000C0833196108281E0DF91CF911F91089557 +:10AFE000CF92DF92EF92FF920F931F93CF93DF9355 +:10AFF000C62E8C01D12CDC1409F43FC0F801D0819D +:10B00000D11104C0D3940B5F1F4FF5CFF801E1803D +:10B01000F28093818481823010F488E001C088E15D +:10B0200028E030E0C0E02E153F0520F4CF5F220F6E +:10B03000331FF9CFC82B8D2F8F70863010F080E032 +:10B040001DC0CF7EF1E4EF16F104C8F7992321F07B +:10B05000913021F4C06C0AC0C06403C0C068911173 +:10B0600005C04E2D6C2F80E88D0F85DF4E2D6C2F87 +:10B070008D2F81DF8111C6CFE2CF81E0DF91CF91AB +:10B080001F910F91FF90EF90DF90CF90089580E097 +:10B0900090E0E091C604F091C7049C0144E0220FC7 +:10B0A000331F4A95E1F7E20FF31F11864091C60462 +:10B0B0005091C704FA01E20FF31F11820196863006 +:10B0C000910539F708958091A53387FF0DC0D8DE2B +:10B0D000811105C08091A4338111F9CF09C060CEE0 +:10B0E0008091A433882321F0BFDE8823C9F33FCEAB +:10B0F00008950F931F93CF93E091C604F091C70476 +:10B10000E05AFF4F00811181C4E68091B13387FF7F +:10B110000AC0AADE811105C08091A433811105C047 +:10B1200022C080E025C0ACDEF5CF8530F1F0E091A3 +:10B13000AF33F091B033818182FD19C0E091C60434 +:10B14000F091C704E05AFF4F8081918108171907D9 +:10B1500011F48C01DACF2FEF2C0FCC2311F0C22F7A +:10B16000F8CF84E005C082E003C083E001C081E045 +:10B17000CF911F910F91089563D069D0E0ECF4E076 +:10B1800081818E7F818380818F7780831092A3332A +:10B190000895CF93DF93E0E4F0E01482848183602C +:10B1A00084834ED054D0C0ECD4E088818F778883DC +:10B1B0008881806888831092A4331092A033109203 +:10B1C000A2331092A13388818064888348E068E4C8 +:10B1D00080E8D1DE48E068E480E0CDDE88858064E8 +:10B1E0008887898181608983DF91CF910895CF938A +:10B1F000DF933FB7F894C0ECD1E022E02A87EAE180 +:10B20000F0E0E491A0ECB4E0DA96EC93DA97EBE1AD +:10B21000F0E0E491DB96EC93DB971A868BEC96E3F7 +:10B220008E7F16968D939C93179785E18C93189635 +:10B230002C933FBF81E08093A333DF91CF91A9CFBF +:10B24000E0ECF4E080858370808711860895E0EC5F +:10B25000F4E08FEF8287848708951F920F920FB6D4 +:10B260000F92112408B60F9218BE09B60F9219BE9C +:10B270000BB60F921BBE2F933F934F935F936F9329 +:10B280007F938F939F93AF93BF93EF93FF9380919F +:10B29000CA0487FF08C08091C80487FF04C080E803 +:10B2A0008093CA040BDC8091CA0486FF07C080E447 +:10B2B0008093CA041092A4330E94CD198091CA04CD +:10B2C00085FF14C080E28093CA048091A033882354 +:10B2D00011F084E007C08091C304811102C081E0B5 +:10B2E00001C083E08093A4330E94BC198091CA04FA +:10B2F00084FF14C080E18093CA0482E08093A43369 +:10B300001092A0331092C304C2DE48E068E480E8E3 +:10B3100032DE48E068E480E02EDED0DBFF91EF9182 +:10B32000BF91AF919F918F917F916F915F914F915D +:10B330003F912F910F900BBE0F9009BE0F9008BE4A +:10B340000F900FBE0F901F901895CF93DF93EC01D5 +:10B35000FC0170968BE0DF011D928A95E9F782E08F +:10B360008C83898783E08E8761E0CE01019638DE89 +:10B37000882361F061E0CE01069632DE882331F049 +:10B3800061E0CE010B96DF91CF912ACE80E0DF9174 +:10B39000CF9108950F931F93CF93DF932091A43300 +:10B3A0002430E1F4FC010489158926893789012BB1 +:10B3B000022B032B99F0EB01818121DDFE0101902D +:10B3C0000020E9F73197BF016C1B7D0B40E050E096 +:10B3D000CE01DF91CF911F910F9182CB82E0DF915F +:10B3E000CF911F910F9108950F931F93CF93DF93E8 +:10B3F0002091A4332430B1F4FC01048915892689F5 +:10B400003789012B022B032B69F08A01EB01818123 +:10B41000F6DC40E050E0B801CE01DF91CF911F9102 +:10B420000F915ECB82E0DF91CF911F910F91089534 +:10B430000F931F93CF932091A433243009F5FC017F +:10B440000489158926893789012B022B032BC1F02A +:10B45000C62F8181D4DC8091AD339091AE33FC0155 +:10B46000EF5BFF4F208131978081281720F48C2FCC +:10B47000B6DC80E006C07BDC3CDE8823C1F301C083 +:10B4800082E0CF911F910F910895CF93DF93209188 +:10B49000A433243091F5FC01448955896689778964 +:10B4A000452B462B472B49F18181A9DC8091B13393 +:10B4B0002091AD333091AE33F90187FF05C0EF5BCA +:10B4C000FF4F808190E008C0E05CFF4F80813196A3 +:10B4D000408190E0841B9109892B69F0F901EF5BB1 +:10B4E000FF4FD0813197C08142DCDC1720F001DEB4 +:10B4F000811104C03CDC80E001C082E0DF91CF918B +:10B500000895CF93DF932091A433243099F4FC0164 +:10B510004489558966897789452B462B472B51F0FD +:10B52000EC0181816CDCA0DC882321F0CE01DF916D +:10B53000CF91ABCFDF91CF910895CF93DF9320913F +:10B54000A433243019F08FEF9FEF46C0FC014489EB +:10B55000558966897789452B462B472BA1F3868130 +:10B560004EDC8EDC882379F38091B1332091AD33AA +:10B570003091AE33F90187FF05C0EF5BFF4F80814B +:10B5800090E008C0E05CFF4F80813196208190E020 +:10B59000821B9109892B21F012DCC82FD0E002C058 +:10B5A000CFEFDFEF2091B1338091AD339091AE3387 +:10B5B000FC0127FF05C0EF5BFF4F208130E008C092 +:10B5C000E05CFF4F20813196808130E0281B3109FB +:10B5D000232B09F4E5DBCE01DF91CF910895089587 +:10B5E000FF920F931F93CF93DF93EC0163DC8823CB +:10B5F00009F48EC0888190E02091A9333091AA335C +:10B600002817390709F084C08091A633813259F098 +:10B6100018F4803249F17CC0823209F457C0833279 +:10B6200009F467C075C08091A533813A09F070C0F4 +:10B630005BDC1ADC8823E9F38C89FD880E891F897D +:10B64000CEDB8F2DCCDB802FCADB812FC8DB888D32 +:10B65000C6DB898DC4DB8A8DC2DB89DBDF91CF91AC +:10B660001F910F91FF902FCD8091A533813209F06A +:10B670004FC03ADC05DC811105C08091A4338111F3 +:10B68000F9CF46C09CDBF82E9ADB182F98DB082FE9 +:10B6900096DB402F50E060E070E0BA015527442768 +:10B6A000782B4F29512B4C8B5D8B6E8B7F8B87DBDF +:10B6B000888F85DB898F83DB8A8F72DB04DDCE0187 +:10B6C000DF91CF911F910F91FF9089CF8091A5338A +:10B6D0008132F1F409DCF7DC8091A7339091A83333 +:10B6E000888B998BCE01DF91CF911F910F91FF90A5 +:10B6F00076CF8091A533813259F4F6DBE4DC60919A +:10B70000A733CE01DF91CF911F910F91FF9067CFAB +:10B71000DF91CF911F910F91FF900895AA1BBB1B42 +:10B7200051E107C0AA1FBB1FA617B70710F0A61B41 +:10B73000B70B881F991F5A95A9F780959095BC0162 +:10B74000CD010895B7FF04C003D0821B930B089569 +:10B7500009D0A59F900DB49F900DA49F800D911DC1 +:10B7600011240895A29FB001B39FC001A39F700D43 +:10B77000811D1124911DB29F700D811D1124911DF9 +:10B7800008958F929F92AF92BF92CF92DF92EF92E5 +:10B79000FF92CF93DF93EC01688179818A819B814D +:10B7A000611571058105910521F464E279ED8BE560 +:10B7B00097E02DE133EF41E050E037D749015A01DE +:10B7C0009B01AC01A7EAB1E4C3DF6B017C01ACEEE5 +:10B7D000B4EFA5019401B8DFDC01CB018C0D9D1DF8 +:10B7E000AE1DBF1DB7FF03C00197A109B0488883F4 +:10B7F0009983AA83BB839F77DF91CF91FF90EF90CE +:10B80000DF90CF90BF90AF909F908F900895B9CF69 +:10B8100082E290E2B6CFA0E0B0E080932220909345 +:10B820002320A0932420B09325200895FB01DC0160 +:10B8300002C005900D9241505040D8F70895FB0189 +:10B84000DC018D91059080190110D9F3990B0895B1 +:10B85000FB01DC014150504048F005900D92002062 +:10B86000C9F701C01D9241505040E0F70895FB0117 +:10B87000DC0104C08D910190801921F441505040A9 +:10B88000C8F7881B990B0895FB01DC0102C00190E9 +:10B890000D9241505040D8F708956817790768F421 +:10B8A000FB01DC01E40FF51FA40FB51F02C00290DD +:10B8B0000E9241505040D8F70895E6CFDC0101C008 +:10B8C0006D9341505040E0F70895FC018191861737 +:10B8D00021F08823D9F7992708953197CF0108954A +:10B8E000FB01DC0101900D920020E1F708950F9318 +:10B8F0001F93CF93DF93CDB7DEB72E97CDBFDEBFBB +:10B900000E891F89888D998D26E02C8309831A83DF +:10B9100097FF02C080E090E801978D839E83AE017F +:10B92000445E5F4F6A8D7B8DCE01019667D04D815D +:10B930005E8157FD0AC02F813885421753070CF4EA +:10B940009A01F801E20FF31F10822E96CDBFDEBFE1 +:10B95000DF91CF911F910F9108950F931F93CF9374 +:10B96000DF93CDB7DEB72E97CDBFDEBF0E891F891F +:10B97000888D998D2EE02C8309831A8397FF02C04E +:10B9800080E090E801978D839E83AE01445E5F4F17 +:10B990006A8D7B8DCE01019631D04D815E8157FD40 +:10B9A0000AC02F813885421753070CF49A01F80119 +:10B9B000E20FF31F10822E96CDBFDEBFDF91CF9135 +:10B9C0001F910F910895CF93DF93CDB7DEB72E97D8 +:10B9D000CDBFDEBF8DE08C838C899D8989839A835E +:10B9E000AE01485E5F4F6E897F89CE010196A9D373 +:10B9F0002E96CDBFDEBFDF91CF9108952F923F925B +:10BA00004F925F926F927F928F929F92AF92BF926E +:10BA1000CF92DF92EF92FF920F931F93CF93DF931A +:10BA2000CDB7DEB72B97CDBFDEBF6C017B018A019E +:10BA3000FC0116821782838181FFBFC1CE0101966E +:10BA40003C01F6019381F70193FD859193FF81916C +:10BA50007F01882309F4ADC1853239F493FD8591C6 +:10BA600093FF81917F01853221F4B60190E0E7D404 +:10BA7000E8CF912C212C312CFFE1F315D8F08B323B +:10BA800079F038F4803279F08332A1F4232D2061EB +:10BA90001DC08D3261F0803369F4232D216016C002 +:10BAA000832D8260382EE32DE4603E2E2AC0F32DD4 +:10BAB000F8601DC037FC2DC020ED280F2A3040F063 +:10BAC0008E32B9F436FC75C1232D2064322E19C094 +:10BAD00036FE06C08AE0989E200D1124922E11C0D9 +:10BAE000EAE02E9E200D1124222EF32DF0623F2E2F +:10BAF00008C08C3621F4832D8068382E02C0883629 +:10BB000041F4F70193FD859193FF81917F018111AC +:10BB1000B3CF982F9F7D9554933028F40C5F1F4F1F +:10BB20009FE399830DC0833631F0833771F08335FD +:10BB300009F055C020C0F801808189830E5F1F4F36 +:10BB400088248394912C530112C02801F2E04F0EF7 +:10BB5000511CF801A080B18036FE03C0692D70E051 +:10BB600002C06FEF7FEFC50121D44C018201F32D9C +:10BB7000FF773F2E15C0280122E0420E511CF8012C +:10BB8000A080B18036FE03C0692D70E002C06FEF67 +:10BB90007FEFC50100D44C01F32DF0683F2E8201E8 +:10BBA00033FC19C0822D90E088169906A0F4B601E6 +:10BBB00080E290E044D42A94F5CFF50137FC8591DA +:10BBC00037FE81915F01B60190E039D421102A94AB +:10BBD00021E0821A91088114910479F7E1C084363A +:10BBE00011F0893639F5F80137FE07C0608171819F +:10BBF000828193810C5F1F4F08C060817181072E85 +:10BC0000000C880B990B0E5F1F4FF32DFF763F2E14 +:10BC100097FF09C090958095709561957F4F8F4FE4 +:10BC20009F4FF0683F2E2AE030E0A3015DD4882EBC +:10BC3000861844C0853731F4232D2F7EB22E2AE09A +:10BC400030E025C0932D997FB92E8F36C1F018F4BE +:10BC5000883579F0AEC0803719F0883721F0A9C057 +:10BC6000E92FE061BE2EB4FE0DC0FB2DF460BF2EA7 +:10BC700009C034FE0AC0292F2660B22E06C028E073 +:10BC800030E005C020E130E002C020E132E0F80100 +:10BC9000B7FE07C060817181828193810C5F1F4F65 +:10BCA00006C06081718180E090E00E5F1F4FA301AC +:10BCB0001BD4882E8618FB2DFF773F2E36FE0DC035 +:10BCC000232D2E7FA22E891458F434FE0BC032FC93 +:10BCD00009C0832D8E7EA82E05C0B82CA32C03C0CE +:10BCE000B82C01C0B92CA4FE0FC0FE01E80DF11D57 +:10BCF0008081803321F49A2D997EA92E09C0A2FE5D +:10BD000006C0B394B39404C08A2D867809F0B39426 +:10BD1000A3FC10C0A0FE06C0B21480F4280C922C24 +:10BD20009B180DC0B21458F4B60180E290E087D39E +:10BD3000B394F8CFB21418F42B1802C0982C212C0D +:10BD4000A4FE0FC0B60180E390E079D3A2FE16C036 +:10BD5000A1FC03C088E790E002C088E590E0B6014E +:10BD60000CC08A2D867851F0A1FE02C08BE201C082 +:10BD700080E2A7FC8DE2B60190E061D3891430F433 +:10BD8000B60180E390E05BD39A94F8CF8A94F301F4 +:10BD9000E80DF11D8081B60190E051D38110F6CFFE +:10BDA000222009F44ECEB60180E290E048D32A94D6 +:10BDB000F7CFF6018681978102C08FEF9FEF2B9618 +:10BDC000CDBFDEBFDF91CF911F910F91FF90EF901C +:10BDD000DF90CF90BF90AF909F908F907F906F90AB +:10BDE0005F904F903F902F90089520FD09C0FC0177 +:10BDF00023FD05C022FF02C0738362835183408309 +:10BE0000089544FD17C046FD17C0AB01BC01DA011F +:10BE1000FB01AA0FBB1FEE1FFF1F1094D1F74A0FA3 +:10BE20005B1F6E1F7F1FCB01BA01660F771F881F34 +:10BE3000991F09C033E001C034E0660F771F881FE7 +:10BE4000991F3150D1F7620F711D811D911D089509 +:10BE50000F931F93CF93DF938C01C801B2D2EC01F3 +:10BE600097FD06C085D2892BC1F7B801CE0123D337 +:10BE7000CE01DF91CF911F910F9108958F929F92E4 +:10BE8000AF92BF92EF92FF920F931F93CF93DF93E6 +:10BE90008C01D62F7A01B22E94D29C0133272B32FB +:10BEA000310531F02D32310559F48B2D8068B82ED3 +:10BEB000D15011F480E061C0C80183D297FDFACF60 +:10BEC000CB2DCD7F2B2D2073F9F48033E9F4AA24F8 +:10BED000AA94AD0E09F43EC0C80173D297FD3AC0D2 +:10BEE0009C012F7D33272835310541F4C264D2509F +:10BEF00089F1C80166D297FF07C02CC0B6FE02C008 +:10BF0000C26001C0C261DA2D812C912C540120ED58 +:10BF1000280F283078F0C4FF03C0B801CCD217C076 +:10BF20002A3040F0C6FFF9CF2F7D3FEE320F36307A +:10BF3000A0F727504C2FC501B40163DF4B015C0112 +:10BF4000C260D15051F0C8013CD297FFE0CFC1FD93 +:10BF500004C0B0CF812C912C5401C7FF08C0B0940D +:10BF6000A09490948094811C911CA11CB11C2C2F36 +:10BF7000B501A401C70139DF81E0DF91CF911F91A5 +:10BF80000F91FF90EF90BF90AF909F908F9008958A +:10BF90005F926F927F928F929F92AF92BF92CF9259 +:10BFA000DF92EF92FF920F931F93CF93DF93CDB762 +:10BFB000DEB7A097CDBFDEBF5C01962E7A01F901F6 +:10BFC0008E010F5F1F4F680180E2D8011D928A9594 +:10BFD000E9F7D50113968C9080E090E0612C712CEC +:10BFE00030E061E070E083FC259183FE21918F01B8 +:10BFF000522E211103C080E090E090C02E3511F444 +:10C00000009751F1432F50E0481759073CF42D3564 +:10C0100059F12D3219F4772009F103C0772009F482 +:10C0200068C0452D469546954695D601A40FB11D8D +:10C03000452D47708B0102C0000F111F4A95E2F792 +:10C04000A8015C91452B4C93651459F0561410F4DB +:10C050005394E7CF5A94E5CF31E004C0772473942A +:10C0600001C0712C0196BFCF772019F08E818062BC +:10C070008E83311103C08824839417C0F6019E017A +:10C080002F5D3F4F8081809581932E173F07D1F719 +:10C09000F2CFE114F10429F0D7018C93F701319626 +:10C0A0007F019A94812C9920E9F0C5018AD197FDEE +:10C0B00017C0FC01FF2723E0F595E7952A95E1F7E6 +:10C0C000EC0DFD1D208130E0AC014770552702C00A +:10C0D000359527954A95E2F720FDDBCFB501EBD1E9 +:10C0E000811089CFE114F10411F0D7011C92C8012D +:10C0F00015C0422F469546954695D601A40FB11D11 +:10C10000422F47708B0102C0000F111F4A95E2F7C2 +:10C11000A8015C91452B4C93622EA4CFA096CDBF75 +:10C12000DEBFDF91CF911F910F91FF90EF90DF90D5 +:10C13000CF90BF90AF909F908F907F906F905F90C7 +:10C1400008955F926F927F928F929F92AF92BF926B +:10C15000CF92DF92EF92FF920F931F93CF93DF93D3 +:10C160006C01EB015A01FC0116821782512CF60179 +:10C17000E380FE01E3FC8591E3FE8191182FEF013E +:10C18000882309F4E0C090E0F3D0892B19F0C601B0 +:10C190005FDEEDCF153241F4FE01E3FC1591E3FEC5 +:10C1A0001191EF01153271F4C6010BD197FDC9C091 +:10C1B000412F50E09C01332724173507C1F2B60107 +:10C1C0007AD1C1C01A3239F4E3FC1591E3FE119122 +:10C1D000EF0101E001C000E0F12C20ED210F2A3039 +:10C1E00078F402606F2D70E080E090E040E209DEBC +:10C1F000F62EFE01E3FC1591E3FE1191EF01EDCF68 +:10C2000001FF03C0F11003C09EC0FF24FA9418364A +:10C2100019F01C3651F010C0FE01E3FC1591E3FE4D +:10C220001191EF01183641F408600460FE01E3FC4F +:10C230001591E3FE1191EF01112309F484C0612FE0 +:10C2400070E08CEF91E09CD0892B09F47CC000FD5C +:10C2500007C0F50180809180C50102965C0102C093 +:10C26000812C912C1E3649F4F6014681578160E0FD +:10C2700070E0202FC401B9DD7ACF1336A1F401FD9F +:10C2800002C0FF24F394C6019CD097FD5AC08114CC +:10C29000910429F0F4018083C40101964C01FA94C1 +:10C2A000F110F1CF4AC01B3551F49E01A4016F2D4E +:10C2B000C6016EDEEC01892B09F03FC039C0C60112 +:10C2C000C7DD97FD3EC01F3649F128F4143621F131 +:10C2D000193639F125C0133771F01537E9F020C050 +:10C2E0008114910429F0F4016082C40101964C018B +:10C2F000FA94FF2059F0C60164D03C0197FD06C0B6 +:10C3000037D0892B69F3B601C301D5D081149104CC +:10C31000A1F0F401108211C0006203C0006101C0ED +:10C320000064202FA4016F2DC601A8DD811105C076 +:10C33000F6018381807329F406C000FD18CF539461 +:10C3400016CF552019F0852D90E002C08FEF9FEF9A +:10C35000DF91CF911F910F91FF90EF90DF90CF90E1 +:10C36000BF90AF909F908F907F906F905F90089557 +:10C37000911118C1803219F089508550D0F7089575 +:10C38000FC010590061621F00020D9F7C0010895A0 +:10C390003197CF010895FC01059061507040011064 +:10C3A000D8F7809590958E0F9F1F0895FC016150DE +:10C3B000704001900110D8F7809590958E0F9F1FC7 +:10C3C0000895CF93DF93EC012B8120FF33C026FF2C +:10C3D0000AC02F7B2B838E819F8101968E839F8342 +:10C3E0008A8190E029C022FF0FC0E881F981808115 +:10C3F000082E000C990B009719F420622B831AC0A9 +:10C400003196E883F9830EC0EA85FB85199597FF7D +:10C4100009C02B81019611F080E201C080E1822BDE +:10C420008B8308C02E813F812F5F3F4F2E833F8338 +:10C43000992702C08FEF9FEFDF91CF9108950F935F +:10C440001F93CF93DF93FB01238121FD03C08FEF67 +:10C450009FEF2CC022FF16C0468157812481358171 +:10C460004217530744F4A081B1819D012F5F3F4FD4 +:10C47000208331838C93268137812F5F3F4F268322 +:10C48000378314C08B01EC01FB010084F185E02DA2 +:10C490001995892BE1F6D80116968D919C911797E5 +:10C4A000019616968D939C931797CE01DF91CF91AD +:10C4B0001F910F910895FB01238120FF12C026FDDB +:10C4C00010C08F3F3FEF930761F082832F7D206480 +:10C4D0002383268137812150310926833783992789 +:10C4E00008958FEF9FEF0895FA01AA27283051F1A0 +:10C4F000203181F1E8946F936E7F6E5F7F4F8F4F95 +:10C500009F4FAF4FB1E03ED0B4E03CD0670F781FF3 +:10C51000891F9A1FA11D680F791F8A1F911DA11DD8 +:10C520006A0F711D811D911DA11D20D009F4689411 +:10C530003F912AE0269F11243019305D3193DEF6B9 +:10C54000CF010895462F4770405D4193B3E00FD06F +:10C55000C9F7F6CF462F4F70405D4A3318F0495D5A +:10C5600031FD4052419302D0A9F7EACFB4E0A6953D +:10C570009795879577956795BA95C9F7009761055F +:10C58000710508959B01AC010A2E069457954795B5 +:10C5900037952795BA95C9F7620F731F841F951FAA +:10C5A000A01D089599278827089503D08081992791 +:10C5B0000895E0ECF1E0378537FDFDCF3485386034 +:10C5C0003487FC01E050F04F0895262FF2DF008001 +:10C5D000021611F008D00197019708950196272FB0 +:10C5E000F5DFF3CF262FE0ECF1E0378537FDFDCF07 +:10C5F0003485377F3487378531FF09C036E332878A +:10C6000038ED34BF31E03387378537FDFDCF33E375 +:10C610003287808391831282248325E3228728ED49 +:10C6200031E024BF338701960895052E97FB16F459 +:10C6300000940FD057FD05D014D007FC02D046F46B +:10C6400008C050954095309521953F4F4F4F5F4F13 +:10C65000089590958095709561957F4F8F4F9F4F6E +:10C660000895A1E21A2EAA1BBB1BFD010DC0AA1F33 +:10C67000BB1FEE1FFF1FA217B307E407F50720F04B +:10C68000A21BB30BE40BF50B661F771F881F991FC6 +:10C690001A9469F760957095809590959B01AC010F +:0AC6A000BD01CF010895F894FFCF0B +:10C6AA0002400F00831000000104100000018208FC +:10C6BA00000001000000000000000000000004006B +:10C6CA00800001000000000000001D25242524250B +:10C6DA0030253C254625632571259A259D25A125CA +:10C6EA003E000426140004043E00042E040C040434 +:10C6FA000008000800000000000000080008080800 +:10C70A0008080800080008000000080800080808CF +:10C71A00008000800000000000000080008080800F +:10C72A0080808000800080000000808000808080FF +:10C73A0000010001000000000000000100010101E9 +:10C74A0001010100010001000000010100010101D5 +:10C75A0000000000000000000000000000000000CF +:10C76A0001010101010101010101010101010101AF +:10C77A00010101010101010101010101010101019F +:10C78A00010101010101010101010101010101018F +:10C79A00000000000000000000000000000000008F +:10C7AA00000000000000000000000000000000007F +:10C7BA00000000000000000000000000000000006F +:10C7CA00010101010101010101010101010101014F +:10C7DA00000000000000000000000000000000004F +:10C7EA00000000000000000000000000000000003F +:10C7FA00010101010101010101010101010101011F +:10C80A00000000000000000000000000000000001E +:10C81A0001010101010101010101010101010101FE +:10C82A0001010101010101010101010101010101EE +:10C83A0000000000000000000000000000000000EE +:10C84A0001010101010101010101010101010101CE +:10C85A0000000002020000020002020202000002BE +:10C86A0000000002020000020002020202000002AE +:10C87A00000000020200000200020202020000029E +:10C88A00040404060604040604060606060404064E +:10C89A00040404060604040604060606060404063E +:10C8AA00000000020200000200020202020000026E +:10C8BA00000000020200000200020202020000025E +:10C8CA00040404060604040604060606060404060E +:10C8DA00000000020200000200020202020000023E +:10C8EA0004040406060404060406060606040406EE +:10C8FA0004040406060404060406060606040406DE +:10C90A0004040406060404060406060606040406CD +:10C91A0004040406060404060406060606040406BD +:10C92A0000000002020000020002020202000002ED +:10C93A0000000002020000020002020202000002DD +:10C94A00040404060604040604060606060404068D +:10C95A00000808080000000800000800080800088D +:10C96A00000808080000000800000800080800087D +:10C97A00000808080000000800000800080800086D +:10C98A00101818181010101810101810181810185D +:10C99A00101818181010101810101810181810184D +:10C9AA00000808080000000800000800080800083D +:10C9BA00000808080000000800000800080800082D +:10C9CA00101818181010101810101810181810181D +:10C9DA00000808080000000800000800080800080D +:10C9EA0010181818101010181010181018181018FD +:10C9FA0010181818101010181010181018181018ED +:10CA0A0010181818101010181010181018181018DC +:10CA1A0010181818101010181010181018181018CC +:10CA2A0000080808000000080000080008080008BC +:10CA3A0000080808000000080000080008080008AC +:10CA4A00101818181010101810101810181810189C +:10CA5A00434C4F4E4500546F6F206D616E792064D0 +:10CA6A006174612E000D0A000D0A50415249545951 +:10CA7A00204552524F52000D0A50415249545920F2 +:10CA8A004F4B002534753A200025337500556E6BDF +:10CA9A006E6F776E206361726420747970652E0000 +:10CAAA002573206F7220004D756C7469706C652057 +:10CABA00706F73736962696C69746965732C206E2F +:10CACA006F7420636C6F6E61626C652100436C6FDA +:10CADA006E6564204F4B2100436C6F6E6520756E46 +:10CAEA00737570706F7274656421004E4F204441F3 +:0ACAFA0054410046414C5345000032 :020000021000EC :1000000000000000000000000000000000000000F0 :1000100000000000000000000000000000000000E0