From dc73b67a610552cdd739858ba1cec07969156a32 Mon Sep 17 00:00:00 2001 From: chrfriese123 Date: Sun, 17 Jan 2021 15:26:10 +0000 Subject: [PATCH] Added ENS160 (Air quality) and ENS210 (Temperature & Humidity) sensor --- lib/lib_i2c/ScioSense_ENS160/LICENSE.md | 21 + lib/lib_i2c/ScioSense_ENS160/README.md | 151 ++++ .../ens160basic_custom/ens160basic_custom.ino | 80 ++ .../ens160basic_normal/ens160basic_normal.ino | 78 ++ .../examples/ens160envdata/ens160envdata.ino | 107 +++ .../clare_fw_app_production_v2.3.1.h | 774 ++++++++++++++++++ .../examples/ens160flash/ens160flash.ino | 75 ++ lib/lib_i2c/ScioSense_ENS160/keywords.txt | 60 ++ .../ScioSense_ENS160/library.properties | 9 + .../ScioSense_ENS160/src/ScioSense_ENS160.cpp | 547 +++++++++++++ .../ScioSense_ENS160/src/ScioSense_ENS160.h | 195 +++++ lib/lib_i2c/ScioSense_ENS210/LICENSE | 21 + lib/lib_i2c/ScioSense_ENS210/README.md | 41 + .../examples/ens210basic/ens210basic.ino | 71 ++ lib/lib_i2c/ScioSense_ENS210/keywords.txt | 47 ++ .../ScioSense_ENS210/library.properties | 9 + .../ScioSense_ENS210/src/ScioSense_ENS210.cpp | 447 ++++++++++ .../ScioSense_ENS210/src/ScioSense_ENS210.h | 121 +++ 18 files changed, 2854 insertions(+) create mode 100644 lib/lib_i2c/ScioSense_ENS160/LICENSE.md create mode 100644 lib/lib_i2c/ScioSense_ENS160/README.md create mode 100644 lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_custom/ens160basic_custom.ino create mode 100644 lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_normal/ens160basic_normal.ino create mode 100644 lib/lib_i2c/ScioSense_ENS160/examples/ens160envdata/ens160envdata.ino create mode 100644 lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/clare_fw_app_production_v2.3.1.h create mode 100644 lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/ens160flash.ino create mode 100644 lib/lib_i2c/ScioSense_ENS160/keywords.txt create mode 100644 lib/lib_i2c/ScioSense_ENS160/library.properties create mode 100644 lib/lib_i2c/ScioSense_ENS160/src/ScioSense_ENS160.cpp create mode 100644 lib/lib_i2c/ScioSense_ENS160/src/ScioSense_ENS160.h create mode 100644 lib/lib_i2c/ScioSense_ENS210/LICENSE create mode 100644 lib/lib_i2c/ScioSense_ENS210/README.md create mode 100644 lib/lib_i2c/ScioSense_ENS210/examples/ens210basic/ens210basic.ino create mode 100644 lib/lib_i2c/ScioSense_ENS210/keywords.txt create mode 100644 lib/lib_i2c/ScioSense_ENS210/library.properties create mode 100644 lib/lib_i2c/ScioSense_ENS210/src/ScioSense_ENS210.cpp create mode 100644 lib/lib_i2c/ScioSense_ENS210/src/ScioSense_ENS210.h diff --git a/lib/lib_i2c/ScioSense_ENS160/LICENSE.md b/lib/lib_i2c/ScioSense_ENS160/LICENSE.md new file mode 100644 index 000000000..dbc30683e --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Sciosense + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/lib_i2c/ScioSense_ENS160/README.md b/lib/lib_i2c/ScioSense_ENS160/README.md new file mode 100644 index 000000000..cae1d1d60 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/README.md @@ -0,0 +1,151 @@ +# ScioSense ENS160 +Arduino library for the ENS160 digital four channel MOX gas sensor with I2C interface from ScioSense + +## Introduction +This project is an Arduino *library*. It implements a driver with examples for the ENS160. +The ENS160 chip is a digital gas sensor for TVOC and eCO2 with an I2C interface. +The driver in this Arduino library is based on the code supplied by *Sciosense*, the manufacturer of the chip. + +Note that the ENS160 requires a supply voltage of 1.71V .. 1.98V. +The ENS160 also requires a IO voltage of 1.71V .. 3.6V. + +## Links +The ENS160 is made by [Sciosense](http://www.sciosense.com). + - The datasheet of the ENS160 is not yet released but can be provided on request + +## Prerequisites +It is assumed that + - The Arduino IDE has been installed. + If not, refer to "Install the Arduino Desktop IDE" on the + [Arduino site](https://www.arduino.cc/en/Guide/HomePage). + - The library directory is at its default location. + For me, that is `C:\Users\sciosense\Documents\Arduino\libraries`. + +## Installation +- Visit the project page for the Arduino CCS811 library. +- Click the green button Clone or download on the right side. +- From the pop-up choose Download ZIP. +- In Arduino IDE, select Sketch > Include Library > Manage Libraries ... and browse to the just downloaded ZIP file. +- When the IDE is ready this README.md should be located at e.g. `C:\Users\sciosense\Documents\Arduino\libraries\sciosense_ens160\README.md`. + +## Build an example +To build an example sketch + - (Re)start Arduino. + - Open File > Example > Examples from Custom Libraries > ENS160 > ENS160basic_normal + - Make sure Tools > Board lists the correct board. + - Select Sketch > Verify/Compile. + +## Functions +> bool begin(bool debug=false, bool bootloader=false) + +Required to initialize the sensor during startup. The function takes up to two arguments: + +First one enables a debug mode to provide further output during sensor operation. Default setting is false (deactivated) + +Second one enables bootloader mode, which is only required to flash a new firmware. Default setting is false (deactivated) + +Returns true in case of success and false in case of any issues. + +> bool available() + +Provides true/false feedback whether the sensor is available or not. The information will be created during initialization. + +> bool setMode(uint8_t mode) + +This function is used to set the sensor operation mode. Currently two modes are implemented and can be set by the following commands: + +*ENS160_OPMODE_STD*: operates the sensor with a predefined heater scheme and provides prediction for eCO2 and TVOC + +*ENS160_OPMODE_CUSTOM*: operates the sensor with a custom defined heaterand measurement scheme, only raw resistance values will be + +reported (see also initCustomMode / addCustomStep) + +Returns true in case of success and false in case of any issues. + +> bool initCustomMode(uint16_t stepNum) + +To be able ot use the custom mode, first it has to be initialized. The number of steps is required as input parameter. Each step has to be configured individually by calling *addCustomStep*. + +Returns true in case of success and false in case of any issues. + +> bool addCustomStep(uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3) + +For each of the steps defined in *initCustomMode* all releavant parameters have to be defined. These are + +*time* defines the duration of the step + +*measureHP* defines if the resistance value for a specific hotplate should be measured + +*tempHP* sets the temperatuer for the specific hotplate + +Returns true in case of success and false in case of any issues. + +> bool measure(bool waitForNew = True) + +Performs the sensor measurement, which means that values from the ASIC internal registers will be stored as result in internal variables. + +If the variable *waitForNew* is set (default), the function will only terminate once new data is stored in the ASIC internal registers. Due to the measurement frequency this can take up to 1sec. + +If the variable *waitForNew* is not set, the function might terminate with pervious non-updates results stored in the internal variables. + +Returns true in case of success and false in case of any issues. + +> bool set_envdata210(uint16_t t, uint16_t h) + +In case temperature and humidity compensation is reuqired for sensor operation, this function allowe the storage of t and h (in ENS210 format) to ENV_DATA register. + +Returns true in case of success and false in case of any issues. + +> uint8_t getMajorRev() + +Function returns the major number of the firmware release. + +> uint8_t getMinorRev() + +Function returns the minor number of the firmware release. + +> uint8_t getBuild() + +Function returns the build number of the firmware release. + +> uint16_t getTVOC() + +Function returns the TVOC value stored in the internal variable. + +> uint16_t geteCO2() + +Function returns the equivalent CO2 value stored in the internal variable. + +> uint32_t getHP0() + +Function returns the raw resistance value of hotplate 0 stored in the internal variable. + +> uint32_t getHP1() + +Function returns the raw resistance value of hotplate 1 stored in the internal variable. + +> uint32_t getHP2() + +Function returns the raw resistance value of hotplate 2 stored in the internal variable. + +> uint32_t getHP3() + +Function returns the raw resistance value of hotplate 3 stored in the internal variable. + +> uint32_t getHP0BL() + +Function returns the stored baseline of hotplate 0 (resistance). + +> uint32_t getHP1BL() + +Function returns the stored baseline of hotplate 1 (resistance). + +> uint32_t getHP2BL() + +Function returns the stored baseline of hotplate 2 (resistance). + +> uint32_t getHP3BL() + +Function returns the stored baseline of hotplate 3 (resistance). + +### ScioSense is a Joint Venture of ams AG diff --git a/lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_custom/ens160basic_custom.ino b/lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_custom/ens160basic_custom.ino new file mode 100644 index 000000000..a409a0630 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_custom/ens160basic_custom.ino @@ -0,0 +1,80 @@ +/*************************************************************************** + This is a example for ENS160 basic reading + + Written by Christoph Friese for Sciosense / 29-April-2020 + ***************************************************************************/ + +#include +int ArduinoLED = 13; + +//------------------------------------------------------------- +//ENS160 related items +//------------------------------------------------------------- +#include "ScioSense_ENS160.h" // ENS160 library +ScioSense_ENS160 ens160(ENS160_I2CADDR_0); +//ScioSense_ENS160 ens160(ENS160_I2CADDR_1); + +/*-------------------------------------------------------------------------- + SETUP function + initiate sensor + --------------------------------------------------------------------------*/ +void setup() { + bool ok; + + //------------------------------------------------------------- + // General setup steps + //------------------------------------------------------------- + + Serial.begin(9600); + + while (!Serial) {} + + //Switch on LED for init + pinMode(ArduinoLED, OUTPUT); + digitalWrite(ArduinoLED, LOW); + + Serial.println("ENS160 example"); + delay(1000); + + //------------------------------------------------------------- + //ENS160 related items + //------------------------------------------------------------- + Serial.print("ENS160..."); + ok = ens160.begin(); + Serial.println(ens160.available() ? "done." : "failed!"); + if (ens160.available()) { + // Print ENS160 versions + Serial.print("Rev: "); Serial.print(ens160.getMajorRev()); + Serial.print("."); Serial.print(ens160.getMinorRev()); + Serial.print("."); Serial.println(ens160.getBuild()); + + Serial.print("setup: ENS160 custom mode "); + ens160.initCustomMode(3); // Create custom sequence with three steps + ens160.addCustomStep(50, 0, 0, 0, 0, 80, 80, 80, 80); // Step 1: 50ms, no measurments, all hotplates at low temperatures + ens160.addCustomStep(350, 1, 1, 1, 1, 160, 215, 215, 200); // Step 2: 350ms, no measurments, all hotplates at medium temperatures + ens160.addCustomStep(600, 1, 1, 1, 1, 250, 350, 350, 325); // Step 3: 600ms, measurments done, all hotplates at high temperatures + if (!ens160.setMode(ENS160_OPMODE_CUSTOM) ) { + Serial.println("FAILED"); + } else { + Serial.println("successful"); + } + } +} + +/*-------------------------------------------------------------------------- + MAIN LOOP FUNCTION + Cylce every 1000ms and perform action + --------------------------------------------------------------------------*/ + +void loop() { + + if (ens160.available()) { + ens160.measure(); + + Serial.print("R HP0: ");Serial.print(ens160.getHP0());Serial.print("Ohm\t"); + Serial.print("R HP1: ");Serial.print(ens160.getHP1());Serial.print("Ohm\t"); + Serial.print("R HP2: ");Serial.print(ens160.getHP2());Serial.print("Ohm\t"); + Serial.print("R HP3: ");Serial.print(ens160.getHP3());Serial.println("Ohm"); + } + delay(1000); +} diff --git a/lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_normal/ens160basic_normal.ino b/lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_normal/ens160basic_normal.ino new file mode 100644 index 000000000..9651ece0b --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/examples/ens160basic_normal/ens160basic_normal.ino @@ -0,0 +1,78 @@ +/*************************************************************************** + This is a example for ENS160 basic reading + + Written by Christoph Friese for Sciosense / 8-April-2020 + ***************************************************************************/ + +#include +int ArduinoLED = 13; + +//------------------------------------------------------------- +//ENS160 related items +//------------------------------------------------------------- +#include "ScioSense_ENS160.h" // ENS160 library +ScioSense_ENS160 ens160(ENS160_I2CADDR_0); +//sciosense_ENS160 ens160(ENS160_I2CADDR_1); + +/*-------------------------------------------------------------------------- + SETUP function + initiate sensor + --------------------------------------------------------------------------*/ +void setup() { + bool ok; + + //------------------------------------------------------------- + // General setup steps + //------------------------------------------------------------- + + Serial.begin(9600); + + while (!Serial) {} + + //Switch on LED for init + pinMode(ArduinoLED, OUTPUT); + digitalWrite(ArduinoLED, LOW); + + Serial.println("ENS160 example"); + delay(1000); + + //------------------------------------------------------------- + //ENS160 related items + //------------------------------------------------------------- + Serial.print("ENS160..."); + ok = ens160.begin(); + Serial.println(ens160.available() ? "done." : "failed!"); + if (ens160.available()) { + // Print ENS160 versions + Serial.print("Rev: "); Serial.print(ens160.getMajorRev()); + Serial.print("."); Serial.print(ens160.getMinorRev()); + Serial.print("."); Serial.println(ens160.getBuild()); + + Serial.print("setup: ENS160 standard mode "); + if (!ens160.setMode(ENS160_OPMODE_STD) ) { + Serial.println("FAILED"); + } else { + Serial.println("successful"); + } + } +} + +/*-------------------------------------------------------------------------- + MAIN LOOP FUNCTION + Cylce every 1000ms and perform action + --------------------------------------------------------------------------*/ + +void loop() { + + if (ens160.available()) { + ens160.measure(); + + Serial.print("TVOC (0x22): ");Serial.print(ens160.getTVOC());Serial.print("ppb\t"); + Serial.print("eCO2 (0x24): ");Serial.print(ens160.geteCO2());Serial.print("ppm\t"); + Serial.print("R HP0: ");Serial.print(ens160.getHP0());Serial.print("Ohm\t"); + Serial.print("R HP1: ");Serial.print(ens160.getHP1());Serial.print("Ohm\t"); + Serial.print("R HP2: ");Serial.print(ens160.getHP2());Serial.print("Ohm\t"); + Serial.print("R HP3: ");Serial.print(ens160.getHP3());Serial.println("Ohm"); + } + delay(1000); +} diff --git a/lib/lib_i2c/ScioSense_ENS160/examples/ens160envdata/ens160envdata.ino b/lib/lib_i2c/ScioSense_ENS160/examples/ens160envdata/ens160envdata.ino new file mode 100644 index 000000000..a96fd656d --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/examples/ens160envdata/ens160envdata.ino @@ -0,0 +1,107 @@ +/*************************************************************************** + This is a example for ENS160 basic reading + + Written by Christoph Friese for Sciosense / 8-April-2020 + ***************************************************************************/ + +#include +int ArduinoLED = 13; + +//------------------------------------------------------------- +//ENS160 related items +//------------------------------------------------------------- +#include "ScioSense_ENS160.h" // ENS160 library +ScioSense_ENS160 ens160(ENS160_I2CADDR_0); +//sciosense_ENS160 ens160(ENS160_I2CADDR_1); + +//------------------------------------------------------------- +//ENS210 related items +//------------------------------------------------------------- +#include "ScioSense_ENS210.h" +ScioSense_ENS210 ens210; + +/*-------------------------------------------------------------------------- + SETUP function + initiate sensor + --------------------------------------------------------------------------*/ +void setup() { + bool ok; + + //------------------------------------------------------------- + // General setup steps + //------------------------------------------------------------- + + Serial.begin(9600); + + while (!Serial) {} + + //Switch on LED for init + pinMode(ArduinoLED, OUTPUT); + digitalWrite(ArduinoLED, LOW); + + Serial.println("ENS160 example with RH & T compensation"); + delay(1000); + + //------------------------------------------------------------- + //ENS160 related items + //------------------------------------------------------------- + Serial.print("ENS160..."); + ok = ens160.begin(); + Serial.println(ens160.available() ? "done." : "failed!"); + if (ens160.available()) { + // Print ENS160 versions + Serial.print("Rev: "); Serial.print(ens160.getMajorRev()); + Serial.print("."); Serial.print(ens160.getMinorRev()); + Serial.print("."); Serial.println(ens160.getBuild()); + + Serial.print("setup: ENS160 standard mode "); + if (!ens160.setMode(ENS160_OPMODE_STD) ) { + Serial.println("FAILED"); + } else { + Serial.println("successful"); + } + } + + //------------------------------------------------------------- + //ENS210 related items + //------------------------------------------------------------- + Serial.print("ENS210..."); + ok = ens210.begin(); + Serial.println(ens210.available() ? "done." : "failed!"); + ens210.setSingleMode(false); + + //blink LED + digitalWrite(ArduinoLED, HIGH); + delay(100); + digitalWrite(ArduinoLED, LOW); + +} + +/*-------------------------------------------------------------------------- + MAIN LOOP FUNCTION + Cylce every 1000ms and perform action + --------------------------------------------------------------------------*/ + +void loop() { + + + if (ens160.available()) { + if (ens210.available()) { + ens210.measure(); + ens160.set_envdata210(ens210.getDataT(),ens210.getDataH()); + } + ens160.measure(); + } + + Serial.print("TVOC (0x22): ");Serial.print(ens160.getTVOC());Serial.print("ppb\t"); + Serial.print("eCO2 (0x24): ");Serial.print(ens160.getEtOH());Serial.print("ppm\t"); + Serial.print("R HP0: ");Serial.print(ens160.getHP0());Serial.print("Ohm\t"); + Serial.print("R HP1: ");Serial.print(ens160.getHP1());Serial.print("Ohm\t"); + Serial.print("R HP2: ");Serial.print(ens160.getHP2());Serial.print("Ohm\t"); + Serial.print("R HP3: ");Serial.print(ens160.getHP3());Serial.print("Ohm\t"); + + Serial.print("Temperature: ");Serial.print(ens210.getTempCelsius());Serial.print("°C\t"); + Serial.print("Humidity: "); Serial.print(ens210.getHumidityPercent());Serial.println("%"); + + delay(1000); +} diff --git a/lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/clare_fw_app_production_v2.3.1.h b/lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/clare_fw_app_production_v2.3.1.h new file mode 100644 index 000000000..9154f3be9 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/clare_fw_app_production_v2.3.1.h @@ -0,0 +1,774 @@ +// Hex dump of 'c:\Users\cfri\Desktop\clare_fw_app_production_v2.3.1\clare_fw_app_production_v2.3.1.bin' created at 2019-12-21 18:31:29.368520 + +#include + +const uint8_t image_data[] PROGMEM = { + 0x50, 0x07, 0x00, 0x20, 0x69, 0x08, 0x00, 0x10, 0x71, 0x08, 0x00, 0x10, 0x73, 0x08, 0x00, 0x10, + 0x75, 0x08, 0x00, 0x10, 0x77, 0x08, 0x00, 0x10, 0x79, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x08, 0x00, 0x10, + 0x7d, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x00, 0x10, 0x65, 0x17, 0x00, 0x10, + 0x85, 0x0b, 0x00, 0x10, 0x6d, 0x0c, 0x00, 0x10, 0x99, 0x0c, 0x00, 0x10, 0xc9, 0x0c, 0x00, 0x10, + 0xfd, 0x0c, 0x00, 0x10, 0x03, 0x48, 0x85, 0x46, 0x00, 0xf0, 0x40, 0xf9, 0x00, 0x48, 0x00, 0x47, + 0x09, 0x21, 0x00, 0x10, 0x50, 0x07, 0x00, 0x20, 0x08, 0x48, 0x80, 0x47, 0x08, 0x48, 0x00, 0x47, + 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, + 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0x05, 0x21, 0x00, 0x10, + 0x55, 0x08, 0x00, 0x10, 0xf8, 0xb5, 0x02, 0x46, 0x4a, 0x40, 0xd4, 0x0f, 0x42, 0x00, 0x4b, 0x00, + 0x52, 0x08, 0x5b, 0x08, 0x9a, 0x42, 0x02, 0xd2, 0x02, 0x46, 0x08, 0x46, 0x11, 0x46, 0x4a, 0x00, + 0x23, 0xd0, 0xc3, 0x0d, 0x4a, 0x00, 0xdd, 0xb2, 0x12, 0x0e, 0xad, 0x1a, 0x20, 0x2d, 0x35, 0xda, + 0x49, 0x02, 0x01, 0x26, 0x49, 0x0a, 0xf6, 0x05, 0x8a, 0x19, 0x00, 0x2c, 0x00, 0xd0, 0x52, 0x42, + 0x20, 0x21, 0x4f, 0x1b, 0x11, 0x46, 0xb9, 0x40, 0x2a, 0x41, 0x10, 0x18, 0xc2, 0x0d, 0x9a, 0x42, + 0x21, 0xd0, 0x00, 0x2c, 0x17, 0xd0, 0x01, 0x2d, 0x08, 0xdc, 0xda, 0x05, 0x80, 0x1a, 0xd2, 0x0f, + 0x80, 0x19, 0xd2, 0x07, 0xdb, 0xb2, 0x00, 0xf0, 0x0b, 0xf9, 0xf8, 0xbd, 0xda, 0x05, 0x80, 0x1a, + 0x01, 0x23, 0x40, 0x00, 0x1b, 0x06, 0xc0, 0x18, 0x80, 0x18, 0x5a, 0x42, 0x80, 0x18, 0xca, 0x0f, + 0x10, 0x43, 0x49, 0x00, 0x07, 0xe0, 0x49, 0x08, 0xc2, 0x07, 0x11, 0x43, 0xda, 0x05, 0x80, 0x1a, + 0x80, 0x19, 0x40, 0x08, 0x80, 0x18, 0x00, 0xf0, 0xeb, 0xf8, 0xf8, 0xbd, 0x61, 0x00, 0x01, 0x22, + 0x51, 0x1a, 0x00, 0x1b, 0xf7, 0xe7, 0x01, 0x22, 0xd2, 0x07, 0x51, 0x40, 0xaa, 0xe7, 0x01, 0x22, + 0xd2, 0x07, 0x50, 0x40, 0xa6, 0xe7, 0x02, 0x46, 0x70, 0xb5, 0x4a, 0x40, 0xd3, 0x0f, 0xdb, 0x07, + 0x40, 0x00, 0x2d, 0xd0, 0x4a, 0x00, 0x2a, 0xd0, 0x01, 0x0e, 0x14, 0x0e, 0x00, 0x02, 0x12, 0x02, + 0x09, 0x19, 0x40, 0x0a, 0x52, 0x0a, 0x84, 0x18, 0xe5, 0x01, 0x04, 0x46, 0x54, 0x43, 0x00, 0x0a, + 0x12, 0x0a, 0x2e, 0x04, 0x50, 0x43, 0xa4, 0x19, 0x42, 0x19, 0x20, 0x0c, 0xc5, 0x43, 0xaa, 0x18, + 0x12, 0x0c, 0x01, 0x25, 0xad, 0x03, 0x52, 0x1c, 0x52, 0x19, 0x12, 0x04, 0x7f, 0x39, 0x24, 0x04, + 0x00, 0xd0, 0x52, 0x1c, 0x10, 0x43, 0x01, 0xd4, 0x40, 0x00, 0x49, 0x1e, 0xc2, 0xb2, 0x0c, 0x06, + 0xc0, 0x09, 0x20, 0x18, 0x40, 0x1c, 0x40, 0x08, 0x80, 0x2a, 0x02, 0xd0, 0x03, 0xe0, 0x00, 0x20, + 0x70, 0xbd, 0x40, 0x08, 0x40, 0x00, 0x00, 0x29, 0x00, 0xda, 0x00, 0x20, 0x18, 0x43, 0x70, 0xbd, + 0x70, 0xb5, 0x02, 0x46, 0x4a, 0x40, 0xd5, 0x0f, 0x40, 0x00, 0x4a, 0x00, 0xed, 0x07, 0x40, 0x08, + 0x52, 0x08, 0x00, 0x28, 0x14, 0xd0, 0x00, 0x2a, 0x12, 0xd0, 0xc4, 0x0d, 0xd3, 0x0d, 0x41, 0x02, + 0x01, 0x20, 0xc0, 0x05, 0x52, 0x02, 0x49, 0x0a, 0x52, 0x0a, 0xe4, 0x1a, 0x09, 0x18, 0x12, 0x18, + 0x7d, 0x34, 0x91, 0x42, 0x01, 0xd3, 0x64, 0x1c, 0x00, 0xe0, 0x49, 0x00, 0x00, 0x2c, 0x01, 0xda, + 0x00, 0x20, 0x70, 0xbd, 0x00, 0x23, 0x91, 0x42, 0x01, 0xd3, 0x89, 0x1a, 0x03, 0x43, 0x40, 0x08, + 0x49, 0x00, 0x00, 0x28, 0xf7, 0xd1, 0x00, 0x29, 0x0a, 0xd0, 0x91, 0x42, 0x02, 0xd1, 0x01, 0x21, + 0xc9, 0x07, 0x05, 0xe0, 0x91, 0x42, 0x01, 0xd2, 0x01, 0x21, 0x01, 0xe0, 0x01, 0x21, 0xc9, 0x43, + 0xe0, 0x05, 0xc0, 0x18, 0x40, 0x19, 0x00, 0xf0, 0x63, 0xf8, 0x70, 0xbd, 0x42, 0x00, 0x05, 0xd0, + 0x42, 0x00, 0x12, 0x0e, 0x52, 0x42, 0x8a, 0x42, 0x01, 0xdb, 0x00, 0x20, 0x70, 0x47, 0xc9, 0x05, + 0x08, 0x18, 0x70, 0x47, 0x10, 0xb5, 0x41, 0x00, 0x0d, 0xd0, 0x41, 0x00, 0x09, 0x0e, 0x96, 0x29, + 0x09, 0xdc, 0x7e, 0x29, 0x0a, 0xdc, 0x07, 0xdb, 0x41, 0x02, 0x05, 0xd0, 0xc0, 0x0f, 0x7f, 0x21, + 0xc0, 0x07, 0xc9, 0x05, 0x40, 0x18, 0x10, 0xbd, 0x00, 0x20, 0x10, 0xbd, 0x96, 0x22, 0x54, 0x1a, + 0x20, 0x21, 0x0a, 0x1b, 0x01, 0x46, 0x91, 0x40, 0xe0, 0x40, 0x00, 0xf0, 0x39, 0xf8, 0xa0, 0x40, + 0x10, 0xbd, 0xc2, 0x17, 0xc1, 0x0f, 0x50, 0x40, 0x10, 0xb5, 0x40, 0x18, 0xca, 0x07, 0x96, 0x23, + 0x00, 0x21, 0x00, 0xf0, 0x35, 0xf8, 0x10, 0xbd, 0xc2, 0x0f, 0x41, 0x00, 0x40, 0x02, 0x01, 0x23, + 0x40, 0x0a, 0xdb, 0x05, 0xd2, 0x07, 0x09, 0x0e, 0xc0, 0x18, 0x7f, 0x29, 0x01, 0xda, 0x00, 0x20, + 0x70, 0x47, 0x96, 0x29, 0x03, 0xdc, 0x96, 0x23, 0x59, 0x1a, 0xc8, 0x40, 0x01, 0xe0, 0x96, 0x39, + 0x88, 0x40, 0x00, 0x2a, 0xf4, 0xd0, 0x40, 0x42, 0x70, 0x47, 0x00, 0x00, 0x06, 0x4c, 0x01, 0x25, + 0x06, 0x4e, 0x05, 0xe0, 0xe3, 0x68, 0x07, 0xcc, 0x2b, 0x43, 0x0c, 0x3c, 0x98, 0x47, 0x10, 0x34, + 0xb4, 0x42, 0xf7, 0xd3, 0xff, 0xf7, 0xb2, 0xfe, 0xc4, 0x2e, 0x00, 0x10, 0xe4, 0x2e, 0x00, 0x10, + 0x00, 0x29, 0x04, 0xda, 0x40, 0x1c, 0x49, 0x00, 0x01, 0xd1, 0x40, 0x08, 0x40, 0x00, 0x70, 0x47, + 0x70, 0xb4, 0x00, 0x24, 0x05, 0x0c, 0x05, 0xd1, 0x10, 0x24, 0x00, 0x04, 0x02, 0xd1, 0x00, 0x29, + 0x21, 0xd0, 0x11, 0x24, 0x05, 0x0e, 0x01, 0xd1, 0x00, 0x02, 0x08, 0x34, 0x05, 0x0f, 0x01, 0xd1, + 0x00, 0x01, 0x24, 0x1d, 0x85, 0x0f, 0x01, 0xd1, 0x80, 0x00, 0xa4, 0x1c, 0x00, 0x28, 0x01, 0xdb, + 0x40, 0x00, 0x64, 0x1c, 0x00, 0x29, 0x08, 0xd0, 0x20, 0x25, 0x2e, 0x1b, 0x0d, 0x46, 0xf5, 0x40, + 0xa1, 0x40, 0x00, 0xd0, 0x01, 0x21, 0x29, 0x43, 0x08, 0x43, 0x01, 0x06, 0x1b, 0x1b, 0x00, 0x0a, + 0xdb, 0x1d, 0x02, 0xd5, 0x00, 0x20, 0x70, 0xbc, 0x70, 0x47, 0xdb, 0x05, 0x18, 0x18, 0x80, 0x18, + 0x00, 0x29, 0xf8, 0xda, 0x40, 0x1c, 0x49, 0x00, 0xf5, 0xd1, 0x70, 0xbc, 0x40, 0x08, 0x40, 0x00, + 0x70, 0x47, 0x00, 0x00, 0x70, 0xb5, 0x31, 0x48, 0x41, 0x68, 0x49, 0x1c, 0x41, 0x60, 0x30, 0x4e, + 0x71, 0x6a, 0x30, 0x4a, 0x0a, 0x40, 0x30, 0x4c, 0x22, 0x81, 0x4a, 0x0b, 0x01, 0x25, 0x2a, 0x40, + 0x22, 0x73, 0x89, 0x0b, 0x03, 0x22, 0x0a, 0x40, 0xe2, 0x71, 0x21, 0x79, 0x0c, 0x22, 0x4a, 0x43, + 0x80, 0x69, 0x81, 0x18, 0x08, 0x22, 0x89, 0x56, 0x00, 0x29, 0x31, 0xdb, 0x31, 0x68, 0x40, 0x88, + 0x89, 0x0d, 0x81, 0x42, 0x06, 0xd2, 0x30, 0x68, 0x80, 0x0d, 0x03, 0xd0, 0x23, 0x48, 0x71, 0x6b, + 0x01, 0x40, 0x21, 0x61, 0x0f, 0x20, 0x00, 0x02, 0x31, 0x68, 0x01, 0x42, 0x20, 0xd0, 0x00, 0xbf, + 0x00, 0xbf, 0x00, 0xf0, 0x39, 0xfe, 0xe1, 0x79, 0x1d, 0x48, 0x00, 0x29, 0x04, 0xd1, 0x61, 0x89, + 0x01, 0x40, 0x89, 0xb2, 0x71, 0x61, 0xe1, 0x79, 0x01, 0x29, 0x04, 0xd1, 0x61, 0x89, 0x01, 0x40, + 0x89, 0xb2, 0xb1, 0x61, 0xe1, 0x79, 0x02, 0x29, 0x04, 0xd1, 0x61, 0x89, 0x01, 0x40, 0x89, 0xb2, + 0xf1, 0x61, 0xe1, 0x79, 0x03, 0x29, 0x03, 0xd1, 0x61, 0x89, 0x01, 0x40, 0x88, 0xb2, 0x30, 0x62, + 0x20, 0x7b, 0x00, 0x28, 0x08, 0xd0, 0xe5, 0x70, 0xa2, 0x79, 0x23, 0x79, 0x59, 0x1c, 0x00, 0x20, + 0x9a, 0x42, 0x00, 0xd0, 0x08, 0x46, 0x60, 0x71, 0x0a, 0x48, 0x05, 0x60, 0x0a, 0x48, 0x01, 0x78, + 0x20, 0x22, 0x0a, 0x43, 0x02, 0x70, 0x00, 0xbf, 0x00, 0xbf, 0x70, 0xbd, 0x70, 0x01, 0x00, 0x20, + 0x08, 0x00, 0x00, 0x40, 0xff, 0x03, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x20, 0xff, 0xff, 0x3f, 0x00, + 0xff, 0x3f, 0x00, 0x00, 0x80, 0xe2, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x40, 0x80, 0xb5, 0x07, 0x48, + 0x01, 0x68, 0x49, 0x1c, 0x01, 0x60, 0x00, 0xf0, 0x4b, 0xfd, 0x05, 0x48, 0x02, 0x21, 0x01, 0x60, + 0x04, 0x48, 0x01, 0x78, 0x40, 0x22, 0x0a, 0x43, 0x02, 0x70, 0x80, 0xbd, 0x70, 0x00, 0x00, 0x20, + 0x80, 0xe2, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x40, 0x07, 0x48, 0x01, 0x21, 0x81, 0x70, 0x07, 0x48, + 0x81, 0x68, 0x49, 0x1c, 0x81, 0x60, 0x06, 0x48, 0x04, 0x21, 0x01, 0x60, 0x05, 0x48, 0x01, 0x78, + 0x80, 0x22, 0x0a, 0x43, 0x02, 0x70, 0x70, 0x47, 0xf0, 0x01, 0x00, 0x20, 0x70, 0x01, 0x00, 0x20, + 0x80, 0xe2, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x40, 0x10, 0xb5, 0x09, 0x4c, 0x20, 0x69, 0x00, 0x28, + 0x01, 0xd0, 0x00, 0xf0, 0xef, 0xf8, 0x07, 0x48, 0x08, 0x21, 0x01, 0x60, 0x06, 0x48, 0x01, 0x78, + 0x01, 0x70, 0xe0, 0x68, 0x40, 0x1c, 0xe0, 0x60, 0x00, 0xbf, 0x00, 0xbf, 0x10, 0xbd, 0xc0, 0x46, + 0x70, 0x01, 0x00, 0x20, 0x80, 0xe2, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x40, 0x05, 0x48, 0x01, 0x68, + 0x49, 0x1c, 0x01, 0x60, 0x04, 0x48, 0x10, 0x21, 0x01, 0x60, 0x04, 0x48, 0x01, 0x78, 0x01, 0x70, + 0x70, 0x47, 0xc0, 0x46, 0x74, 0x00, 0x00, 0x20, 0x80, 0xe2, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x40, + 0x10, 0xb5, 0x00, 0xf0, 0x13, 0xf8, 0x06, 0x4c, 0xf0, 0x21, 0x20, 0x46, 0x01, 0xf0, 0x96, 0xfd, + 0x20, 0x20, 0x04, 0x49, 0x00, 0x22, 0x0a, 0x54, 0x03, 0x48, 0x84, 0x61, 0x10, 0xbd, 0xc0, 0x46, + 0x78, 0x00, 0x00, 0x20, 0xf0, 0x01, 0x00, 0x20, 0x70, 0x01, 0x00, 0x20, 0x10, 0xb5, 0x01, 0x20, + 0x81, 0x07, 0x0b, 0x68, 0x03, 0x22, 0x93, 0x43, 0x02, 0x22, 0x13, 0x43, 0x0b, 0x60, 0x00, 0x23, + 0x01, 0xe0, 0x00, 0xbf, 0x5b, 0x1c, 0xdc, 0xb2, 0x07, 0x2c, 0xfa, 0xd9, 0x0b, 0x68, 0x93, 0x43, + 0x0b, 0x60, 0x98, 0x22, 0x8b, 0x58, 0x80, 0x24, 0xa3, 0x43, 0x8b, 0x50, 0x08, 0x49, 0x08, 0x60, + 0x04, 0x20, 0x08, 0x60, 0x21, 0x20, 0x07, 0x4c, 0x00, 0x21, 0x21, 0x54, 0x60, 0x1c, 0x06, 0x21, + 0x01, 0xf0, 0x64, 0xfd, 0x04, 0x48, 0x20, 0x61, 0x00, 0xf0, 0x3e, 0xfd, 0x10, 0xbd, 0xc0, 0x46, + 0x80, 0xe2, 0x00, 0xe0, 0xf0, 0x01, 0x00, 0x20, 0x9a, 0x19, 0x12, 0x00, 0xb0, 0xb5, 0x81, 0x1e, + 0x02, 0x29, 0x10, 0xd3, 0x01, 0x46, 0xd0, 0x39, 0x02, 0x29, 0x0c, 0xd3, 0xc0, 0x28, 0x19, 0xd0, + 0xb1, 0x28, 0x21, 0xd1, 0x14, 0x48, 0x18, 0x49, 0x81, 0x61, 0x15, 0x48, 0x00, 0x21, 0x81, 0x71, + 0x01, 0x21, 0xc1, 0x70, 0xb0, 0xbd, 0xd0, 0x38, 0x41, 0x1e, 0x88, 0x41, 0x21, 0x21, 0x10, 0x4c, + 0x60, 0x54, 0x0d, 0x49, 0x0f, 0x4a, 0x8a, 0x61, 0x01, 0x25, 0xa5, 0x71, 0x00, 0xf0, 0x1e, 0xf8, + 0xe5, 0x70, 0xb0, 0xbd, 0x08, 0x48, 0x09, 0x49, 0x81, 0x61, 0x09, 0x48, 0x01, 0x21, 0xc1, 0x70, + 0x20, 0x21, 0x41, 0x5c, 0x81, 0x71, 0xb0, 0xbd, 0x03, 0x48, 0x04, 0x49, 0x81, 0x61, 0x20, 0x20, + 0x03, 0x49, 0x08, 0x5c, 0x88, 0x71, 0xb0, 0xbd, 0x70, 0x01, 0x00, 0x20, 0x78, 0x00, 0x00, 0x20, + 0xf0, 0x01, 0x00, 0x20, 0xac, 0x2e, 0x00, 0x10, 0xa0, 0x2e, 0x00, 0x10, 0xf0, 0xb5, 0x87, 0xb0, + 0x07, 0x46, 0x02, 0xa9, 0x01, 0x91, 0x01, 0xf0, 0x01, 0xf9, 0x06, 0x46, 0x18, 0x4d, 0x2c, 0x1d, + 0x40, 0x21, 0x20, 0x46, 0x01, 0xf0, 0x0a, 0xfd, 0x01, 0x20, 0x00, 0x2e, 0x39, 0x46, 0x00, 0xd0, + 0x01, 0x46, 0x00, 0x2f, 0x00, 0xd0, 0x39, 0x46, 0x34, 0x22, 0xa9, 0x54, 0x11, 0x49, 0x12, 0x4a, + 0x12, 0x4b, 0x00, 0x27, 0x8f, 0x63, 0xca, 0x63, 0x11, 0x49, 0x29, 0x60, 0x6b, 0x61, 0xab, 0x61, + 0xe8, 0x63, 0x00, 0x2e, 0x0f, 0xd1, 0x01, 0x98, 0x00, 0x78, 0x01, 0x28, 0x0b, 0xd1, 0x02, 0xa8, + 0x00, 0x1d, 0x4e, 0xc8, 0x4e, 0xc4, 0x35, 0x20, 0x04, 0x21, 0x29, 0x54, 0xff, 0x20, 0x2e, 0x30, + 0x00, 0x21, 0xa8, 0x63, 0xe9, 0x63, 0x00, 0xbf, 0x00, 0xbf, 0x07, 0xb0, 0xf0, 0xbd, 0xc0, 0x46, + 0x90, 0x02, 0x00, 0x20, 0x50, 0x02, 0x00, 0x20, 0x89, 0x4a, 0x00, 0x64, 0x00, 0xff, 0x7f, 0x47, + 0x01, 0x53, 0x4d, 0x41, 0xfe, 0xb5, 0x2e, 0x48, 0x01, 0x78, 0x20, 0x25, 0x29, 0x40, 0x49, 0x09, + 0x02, 0x78, 0x10, 0x23, 0x13, 0x40, 0xda, 0x08, 0x0a, 0x43, 0x03, 0x78, 0x08, 0x21, 0x0b, 0x40, + 0x5b, 0x08, 0x13, 0x43, 0x02, 0x78, 0x52, 0x00, 0x0a, 0x40, 0x1a, 0x43, 0x03, 0x78, 0x5b, 0x01, + 0x40, 0x24, 0x1c, 0x40, 0x14, 0x43, 0x02, 0x78, 0x52, 0x01, 0x2a, 0x40, 0x22, 0x43, 0x21, 0x4b, + 0x01, 0x95, 0x5b, 0x5d, 0x0c, 0x24, 0x5c, 0x43, 0x1f, 0x4b, 0x1a, 0x55, 0x1b, 0x19, 0x02, 0x78, + 0x92, 0x09, 0x04, 0x79, 0xa4, 0x00, 0x14, 0x43, 0x5c, 0x80, 0x02, 0x7a, 0x1a, 0x71, 0x04, 0x7b, + 0x5c, 0x71, 0x05, 0x7c, 0x9d, 0x71, 0x06, 0x7d, 0xde, 0x71, 0x07, 0x7e, 0x02, 0x97, 0x5f, 0x72, + 0x01, 0x27, 0x00, 0x2a, 0x00, 0xd1, 0x17, 0x46, 0x02, 0x22, 0x3a, 0x43, 0x00, 0x2c, 0x00, 0xd0, + 0x17, 0x46, 0x04, 0x22, 0x3a, 0x43, 0x00, 0x2d, 0x00, 0xd0, 0x17, 0x46, 0x39, 0x43, 0x00, 0x2e, + 0x00, 0xd0, 0x0f, 0x46, 0x00, 0x7f, 0x1f, 0x72, 0xc0, 0x09, 0x98, 0x72, 0x04, 0xd0, 0x01, 0x20, + 0x02, 0x99, 0x00, 0xf0, 0x13, 0xf8, 0xfe, 0xbd, 0x00, 0x20, 0x02, 0x99, 0x00, 0xf0, 0x0e, 0xf8, + 0x01, 0x99, 0x04, 0x48, 0x02, 0x46, 0x50, 0x5c, 0x40, 0x1c, 0x50, 0x54, 0xfe, 0xbd, 0xc0, 0x46, + 0xd0, 0x00, 0x00, 0x40, 0xf0, 0x01, 0x00, 0x20, 0x78, 0x00, 0x00, 0x20, 0x10, 0xb5, 0x03, 0x46, + 0x3f, 0x24, 0x0c, 0x40, 0x01, 0x22, 0x05, 0x48, 0x00, 0x2b, 0x01, 0xd0, 0xc0, 0x21, 0x00, 0xe0, + 0x80, 0x21, 0x0c, 0x43, 0xe1, 0xb2, 0x00, 0xf0, 0x23, 0xfc, 0x10, 0xbd, 0x0c, 0x01, 0x00, 0x40, + 0xf0, 0xb5, 0x95, 0xb0, 0x01, 0x24, 0xa6, 0x07, 0x5c, 0x4b, 0x98, 0x78, 0x00, 0x28, 0x07, 0x96, + 0x00, 0xd1, 0x9f, 0xe0, 0x00, 0x20, 0x98, 0x70, 0x59, 0x48, 0x18, 0x80, 0x02, 0x94, 0x18, 0x79, + 0x0c, 0x25, 0x68, 0x43, 0x57, 0x4f, 0xb9, 0x69, 0x08, 0x5c, 0xc0, 0x07, 0x56, 0x4c, 0x12, 0xd0, + 0x30, 0x6b, 0x20, 0x40, 0x19, 0x46, 0x18, 0x31, 0x00, 0xf0, 0x96, 0xfc, 0x4f, 0x4b, 0x38, 0x21, + 0x52, 0x48, 0x41, 0x5c, 0x06, 0x29, 0x06, 0xd8, 0x1a, 0x8b, 0x4b, 0x00, 0xc2, 0x52, 0x4b, 0x4b, + 0x49, 0x1c, 0x38, 0x22, 0x81, 0x54, 0x18, 0x79, 0x68, 0x43, 0xb9, 0x69, 0x08, 0x5c, 0x80, 0x07, + 0x13, 0xd5, 0x39, 0x20, 0x49, 0x4e, 0x37, 0x5c, 0x07, 0x98, 0x40, 0x6b, 0x20, 0x40, 0x19, 0x46, + 0x1a, 0x31, 0x00, 0xf0, 0x79, 0xfc, 0x41, 0x4b, 0x06, 0x2f, 0x06, 0xd8, 0x78, 0x00, 0x30, 0x18, + 0x59, 0x8b, 0xc1, 0x81, 0x78, 0x1c, 0x39, 0x21, 0x70, 0x54, 0x18, 0x79, 0x68, 0x43, 0x3d, 0x49, + 0x89, 0x69, 0x08, 0x5c, 0x40, 0x07, 0x13, 0xd5, 0x3a, 0x20, 0x3c, 0x4e, 0x37, 0x5c, 0x07, 0x98, + 0x80, 0x6b, 0x20, 0x40, 0x19, 0x46, 0x1c, 0x31, 0x00, 0xf0, 0x5e, 0xfc, 0x33, 0x4b, 0x06, 0x2f, + 0x06, 0xd8, 0x78, 0x00, 0x30, 0x18, 0x99, 0x8b, 0x81, 0x83, 0x78, 0x1c, 0x3a, 0x21, 0x70, 0x54, + 0x18, 0x79, 0x68, 0x43, 0x2f, 0x49, 0x89, 0x69, 0x08, 0x5c, 0x00, 0x07, 0x13, 0xd5, 0x3b, 0x20, + 0x2e, 0x4e, 0x37, 0x5c, 0x07, 0x98, 0xc0, 0x6b, 0x20, 0x40, 0x19, 0x46, 0x1e, 0x31, 0x00, 0xf0, + 0x43, 0xfc, 0x26, 0x4b, 0x06, 0x2f, 0x06, 0xd8, 0x78, 0x00, 0x30, 0x18, 0xd9, 0x8b, 0x41, 0x85, + 0x78, 0x1c, 0x3b, 0x21, 0x70, 0x54, 0x19, 0x79, 0x28, 0x46, 0x48, 0x43, 0x21, 0x4f, 0xba, 0x69, + 0x10, 0x5c, 0x2f, 0x22, 0x02, 0x40, 0x20, 0x2a, 0x07, 0x9e, 0x02, 0xd1, 0x72, 0x6b, 0x22, 0x40, + 0x5a, 0x61, 0x4f, 0x22, 0x02, 0x40, 0x40, 0x2a, 0x02, 0xd1, 0xf2, 0x6b, 0x22, 0x40, 0x1a, 0x61, + 0x40, 0x06, 0x00, 0xd1, 0x44, 0xe1, 0x38, 0x78, 0x01, 0x24, 0xc0, 0x28, 0x01, 0xd0, 0xb1, 0x28, + 0x06, 0xd1, 0x30, 0x46, 0x9c, 0x30, 0x22, 0x46, 0x00, 0xf0, 0x82, 0xfb, 0x0f, 0x4b, 0x38, 0x78, + 0x01, 0x46, 0xc0, 0x39, 0x11, 0x29, 0x2c, 0xd9, 0x81, 0x1e, 0x02, 0x29, 0x2e, 0xd3, 0xb1, 0x28, + 0x2c, 0xd0, 0x9f, 0xe0, 0x58, 0x78, 0x18, 0x70, 0x09, 0x28, 0x00, 0xd9, 0x2d, 0xe1, 0x40, 0x00, + 0x78, 0x44, 0x80, 0x88, 0x40, 0x00, 0x87, 0x44, 0x14, 0x00, 0x2a, 0x01, 0x2e, 0x01, 0xea, 0x02, + 0x28, 0x01, 0x28, 0x01, 0x13, 0x00, 0x28, 0x01, 0xa5, 0x00, 0x23, 0x01, 0xf0, 0x01, 0x00, 0x20, + 0x06, 0x06, 0x00, 0x00, 0x70, 0x01, 0x00, 0x20, 0xff, 0xff, 0x3f, 0x00, 0x50, 0x02, 0x00, 0x20, + 0x44, 0xe7, 0x58, 0x1c, 0xd9, 0x78, 0x00, 0x29, 0x00, 0xd1, 0x0c, 0xe1, 0x5c, 0x70, 0xd8, 0x1c, + 0x09, 0xe1, 0x22, 0x46, 0x8a, 0x40, 0xfa, 0x49, 0x0a, 0x42, 0xcd, 0xd0, 0x0c, 0x94, 0x18, 0x79, + 0x45, 0x43, 0xb8, 0x69, 0x40, 0x5d, 0x40, 0x06, 0x80, 0x0f, 0xfa, 0x4d, 0x32, 0xd0, 0x19, 0x7c, + 0x30, 0x46, 0xf0, 0x30, 0x37, 0x46, 0x00, 0x26, 0x32, 0x46, 0x1c, 0x46, 0xf6, 0x4b, 0x98, 0x47, + 0x61, 0x7c, 0x38, 0x46, 0xf4, 0x30, 0x32, 0x46, 0xf3, 0x4b, 0x98, 0x47, 0x61, 0x8a, 0x3f, 0x20, + 0x0b, 0x90, 0x01, 0x40, 0x38, 0x46, 0xf8, 0x30, 0x32, 0x46, 0xef, 0x4b, 0x98, 0x47, 0xfc, 0x37, + 0x38, 0x46, 0x31, 0x46, 0x32, 0x46, 0xec, 0x4f, 0xb8, 0x47, 0x21, 0x7d, 0x28, 0x46, 0x32, 0x46, + 0xb8, 0x47, 0x61, 0x7d, 0x28, 0x1d, 0x32, 0x46, 0xb8, 0x47, 0xe1, 0x8a, 0x0b, 0x98, 0x01, 0x40, + 0x28, 0x46, 0x08, 0x30, 0x32, 0x46, 0xb8, 0x47, 0x0c, 0x35, 0x28, 0x46, 0x31, 0x46, 0x0c, 0x9a, + 0xb8, 0x47, 0x2d, 0xe0, 0x19, 0x7e, 0x30, 0x46, 0xf0, 0x30, 0x34, 0x46, 0x00, 0x26, 0x32, 0x46, + 0x1f, 0x46, 0xdd, 0x4b, 0x98, 0x47, 0x79, 0x7e, 0x20, 0x46, 0xf4, 0x30, 0x32, 0x46, 0xda, 0x4b, + 0x98, 0x47, 0xb9, 0x7e, 0x20, 0x46, 0xf8, 0x30, 0x32, 0x46, 0xd7, 0x4b, 0x98, 0x47, 0xf9, 0x7e, + 0xfc, 0x34, 0x20, 0x46, 0x32, 0x46, 0xd4, 0x4c, 0xa0, 0x47, 0x39, 0x7f, 0x28, 0x46, 0x32, 0x46, + 0xa0, 0x47, 0x79, 0x7f, 0x28, 0x1d, 0x32, 0x46, 0xa0, 0x47, 0xb9, 0x7f, 0x28, 0x46, 0x08, 0x30, + 0x32, 0x46, 0xa0, 0x47, 0x23, 0x46, 0xf9, 0x7f, 0x0c, 0x35, 0x28, 0x46, 0x0c, 0x9a, 0x98, 0x47, + 0xca, 0x48, 0x01, 0x46, 0x48, 0x69, 0x40, 0x1c, 0x48, 0x61, 0x00, 0xbf, 0x00, 0xbf, 0x08, 0x78, + 0xc7, 0x4b, 0x07, 0x9e, 0x01, 0x46, 0xd0, 0x39, 0x02, 0x29, 0x03, 0xd3, 0x80, 0x1e, 0x01, 0x28, + 0x00, 0xd9, 0x85, 0xe0, 0x98, 0x79, 0x59, 0x79, 0x81, 0x42, 0x00, 0xd0, 0x80, 0xe0, 0x08, 0x20, + 0x58, 0x70, 0x02, 0x9c, 0x05, 0x20, 0x90, 0x21, 0x72, 0x58, 0x00, 0x2a, 0x02, 0xda, 0x40, 0x1e, + 0xf9, 0xd1, 0x0d, 0xe0, 0x70, 0x58, 0x05, 0x21, 0x94, 0x22, 0xb2, 0x58, 0x00, 0x2a, 0x02, 0xda, + 0x49, 0x1e, 0xf9, 0xd1, 0x04, 0xe0, 0x94, 0x21, 0x71, 0x58, 0xb6, 0x4a, 0xd1, 0x87, 0x90, 0x87, + 0x12, 0xa8, 0x00, 0xf0, 0xb1, 0xfc, 0x38, 0x22, 0xb2, 0x49, 0x02, 0xe0, 0x00, 0x23, 0x8b, 0x54, + 0x52, 0x1c, 0x3c, 0x2a, 0xfa, 0xd1, 0x09, 0x22, 0xad, 0x4b, 0x5a, 0x70, 0x00, 0x28, 0x57, 0xd1, + 0x02, 0x94, 0x62, 0x02, 0x0c, 0x92, 0xac, 0x4b, 0x18, 0x68, 0x90, 0x43, 0x18, 0x60, 0x12, 0xaf, + 0x38, 0x78, 0x9c, 0x22, 0xb0, 0x50, 0xb8, 0x88, 0xa0, 0x22, 0xb0, 0x50, 0x78, 0x88, 0xa4, 0x22, + 0xb0, 0x50, 0xf8, 0x88, 0xa8, 0x22, 0xb0, 0x50, 0x88, 0x8f, 0xbc, 0x22, 0xb0, 0x50, 0xc8, 0x8f, + 0xc0, 0x21, 0x70, 0x50, 0x45, 0x20, 0x04, 0x06, 0xa0, 0x4d, 0x68, 0x68, 0x21, 0x46, 0xff, 0xf7, + 0x32, 0xfb, 0x01, 0xf0, 0x05, 0xfb, 0xac, 0x21, 0x70, 0x50, 0xa8, 0x68, 0x21, 0x46, 0xff, 0xf7, + 0x2a, 0xfb, 0x01, 0xf0, 0xfd, 0xfa, 0xb0, 0x21, 0x70, 0x50, 0xe8, 0x68, 0x21, 0x46, 0xff, 0xf7, + 0x22, 0xfb, 0x01, 0xf0, 0xf5, 0xfa, 0xb4, 0x21, 0x70, 0x50, 0x28, 0x69, 0x21, 0x46, 0xff, 0xf7, + 0x1a, 0xfb, 0x01, 0xf0, 0xed, 0xfa, 0xb8, 0x21, 0x70, 0x50, 0xf7, 0x4a, 0x10, 0x68, 0x0c, 0x99, + 0x08, 0x43, 0x10, 0x60, 0x38, 0x7a, 0x80, 0x07, 0x0f, 0xd5, 0x28, 0x68, 0xf3, 0x49, 0x88, 0x42, + 0x0b, 0xd1, 0x02, 0x98, 0x0d, 0x90, 0x28, 0x1d, 0x0d, 0xa9, 0x0a, 0x1d, 0x78, 0xc8, 0x78, 0xc2, + 0x21, 0x20, 0xeb, 0x4a, 0x10, 0x5c, 0x00, 0xf0, 0x9d, 0xfe, 0x00, 0xbf, 0x00, 0xbf, 0xe8, 0x4b, + 0x58, 0x79, 0x18, 0x71, 0x58, 0x1c, 0x00, 0x21, 0x01, 0x70, 0x15, 0xb0, 0xf0, 0xbd, 0x02, 0x20, + 0x58, 0x70, 0x00, 0x20, 0x18, 0x73, 0x02, 0x94, 0x58, 0x79, 0x0c, 0x21, 0x09, 0x91, 0x48, 0x43, + 0xe0, 0x4f, 0xb9, 0x69, 0x0a, 0x18, 0x53, 0x88, 0x9b, 0x05, 0x12, 0x7a, 0x0f, 0x24, 0x0a, 0x94, + 0x22, 0x40, 0x12, 0x02, 0x1a, 0x43, 0x08, 0x5c, 0x6f, 0x21, 0x01, 0x40, 0x11, 0x43, 0x10, 0x20, + 0x08, 0x43, 0x70, 0x60, 0xd6, 0x48, 0x00, 0x69, 0xff, 0xf7, 0x7b, 0xfb, 0x01, 0x46, 0x25, 0x20, + 0x40, 0x06, 0xff, 0xf7, 0xc8, 0xfa, 0x21, 0x21, 0x49, 0x06, 0xff, 0xf7, 0xcc, 0xfa, 0x35, 0x21, + 0x09, 0x06, 0xff, 0xf7, 0xc8, 0xfa, 0xd2, 0x49, 0x08, 0x60, 0x3d, 0x6b, 0x09, 0x68, 0x28, 0x46, + 0xff, 0xf7, 0x68, 0xfa, 0x01, 0x46, 0x28, 0x46, 0xff, 0xf7, 0xfa, 0xfa, 0x01, 0x46, 0x7c, 0x6b, + 0x20, 0x46, 0xff, 0xf7, 0xb8, 0xfa, 0xb9, 0x6b, 0xff, 0xf7, 0xad, 0xfa, 0xf9, 0x6b, 0x06, 0x91, + 0xff, 0xf7, 0xa9, 0xfa, 0xc6, 0x4e, 0x70, 0x60, 0x20, 0x46, 0x29, 0x46, 0xff, 0xf7, 0xab, 0xfa, + 0x04, 0x46, 0x0c, 0x94, 0x3f, 0x6c, 0x31, 0x68, 0x38, 0x46, 0xff, 0xf7, 0x9c, 0xfa, 0x01, 0x46, + 0x20, 0x46, 0xff, 0xf7, 0xa0, 0xfa, 0x06, 0x46, 0x28, 0x46, 0x39, 0x46, 0xff, 0xf7, 0x42, 0xfa, + 0x07, 0x46, 0xbb, 0x4c, 0x21, 0x68, 0x28, 0x46, 0xff, 0xf7, 0x3c, 0xfa, 0x01, 0x46, 0x38, 0x46, + 0x27, 0x46, 0xff, 0xf7, 0x90, 0xfa, 0x01, 0x46, 0x30, 0x46, 0xff, 0xf7, 0xc9, 0xfa, 0xb8, 0x60, + 0xb0, 0x48, 0x46, 0x6c, 0x39, 0x68, 0x30, 0x46, 0xff, 0xf7, 0x7d, 0xfa, 0x01, 0x46, 0x0c, 0x98, + 0xff, 0xf7, 0x81, 0xfa, 0x04, 0x46, 0x28, 0x46, 0x31, 0x46, 0xff, 0xf7, 0x23, 0xfa, 0x06, 0x46, + 0x39, 0x68, 0x28, 0x46, 0xff, 0xf7, 0x1e, 0xfa, 0x01, 0x46, 0x30, 0x46, 0xff, 0xf7, 0x73, 0xfa, + 0x01, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xac, 0xfa, 0xf8, 0x60, 0x89, 0x20, 0xc1, 0x05, 0xa1, 0x4c, + 0x60, 0x6f, 0xff, 0xf7, 0x68, 0xfa, 0x0b, 0x90, 0x6b, 0x20, 0xc5, 0x05, 0xa0, 0x6e, 0x26, 0x46, + 0x29, 0x46, 0xff, 0xf7, 0x60, 0xfa, 0xf9, 0x68, 0xff, 0xf7, 0x5d, 0xfa, 0x7f, 0x21, 0xc9, 0x05, + 0x0c, 0x91, 0xff, 0xf7, 0xff, 0xf9, 0x04, 0x46, 0xf0, 0x6e, 0x29, 0x46, 0xff, 0xf7, 0x53, 0xfa, + 0x06, 0x46, 0xf8, 0x68, 0xf9, 0x68, 0xff, 0xf7, 0x4e, 0xfa, 0x01, 0x46, 0x30, 0x46, 0xff, 0xf7, + 0x4a, 0xfa, 0x01, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xed, 0xf9, 0x01, 0x46, 0x0b, 0x98, 0xff, 0xf7, + 0x42, 0xfa, 0xb8, 0x61, 0x8b, 0x4e, 0xf0, 0x69, 0x01, 0xf0, 0x0b, 0xfa, 0x73, 0x21, 0xcc, 0x05, + 0x21, 0x46, 0xff, 0xf7, 0x38, 0xfa, 0x75, 0x21, 0xc9, 0x05, 0x01, 0x91, 0xff, 0xf7, 0x33, 0xfa, + 0x05, 0x90, 0x30, 0x6a, 0x01, 0xf0, 0xfd, 0xf9, 0x21, 0x46, 0xff, 0xf7, 0x2c, 0xfa, 0x00, 0x95, + 0x29, 0x46, 0xff, 0xf7, 0x28, 0xfa, 0x7e, 0x49, 0x0a, 0x46, 0x0b, 0x90, 0x50, 0x79, 0x09, 0x9b, + 0x58, 0x43, 0xb1, 0x69, 0x08, 0x18, 0x04, 0x1d, 0x10, 0x79, 0x58, 0x43, 0x08, 0x18, 0x00, 0x1d, + 0x03, 0x90, 0x0a, 0x98, 0xc5, 0x43, 0x00, 0x26, 0x04, 0x94, 0x8c, 0xe0, 0xa0, 0x5d, 0x00, 0x28, + 0x08, 0xd0, 0x03, 0x99, 0x89, 0x5d, 0x81, 0x42, 0x1a, 0xd2, 0x40, 0x1a, 0x19, 0xe0, 0xc0, 0x46, + 0x01, 0x00, 0x03, 0x00, 0x79, 0x19, 0x00, 0x20, 0xc8, 0x62, 0xc8, 0x65, 0x39, 0x46, 0x5c, 0x31, + 0x75, 0xe0, 0xc0, 0x46, 0x00, 0x01, 0x00, 0x40, 0xe1, 0x17, 0x00, 0x10, 0x70, 0x01, 0x00, 0x20, + 0xf0, 0x01, 0x00, 0x20, 0x50, 0x02, 0x00, 0x20, 0x00, 0x08, 0x00, 0x40, 0x90, 0x02, 0x00, 0x20, + 0x08, 0x1a, 0x65, 0x28, 0x03, 0xdb, 0x78, 0x19, 0x00, 0x21, 0xc1, 0x65, 0xc1, 0x66, 0xa0, 0x5d, + 0x01, 0xf0, 0xb7, 0xf9, 0x01, 0x46, 0xff, 0xf7, 0x8d, 0xf9, 0x06, 0x99, 0xff, 0xf7, 0xdb, 0xf9, + 0x04, 0x46, 0xf1, 0xb2, 0x5b, 0x48, 0x24, 0x30, 0x00, 0x29, 0x0a, 0x95, 0x09, 0x96, 0x03, 0xd0, + 0x03, 0x29, 0x01, 0xd0, 0x57, 0x48, 0x28, 0x30, 0x00, 0x68, 0x01, 0xf0, 0xa2, 0xf9, 0x77, 0x21, + 0xc9, 0x05, 0xff, 0xf7, 0xd0, 0xf9, 0x07, 0x46, 0x56, 0x49, 0xff, 0xf7, 0xcc, 0xf9, 0x08, 0x90, + 0x20, 0x46, 0x05, 0x9e, 0x31, 0x46, 0xff, 0xf7, 0xc6, 0xf9, 0x0c, 0x99, 0xff, 0xf7, 0x6a, 0xf9, + 0x05, 0x46, 0x20, 0x46, 0x0b, 0x99, 0xff, 0xf7, 0xbe, 0xf9, 0x01, 0x46, 0x20, 0x46, 0xff, 0xf7, + 0xba, 0xf9, 0x01, 0x46, 0x28, 0x46, 0xff, 0xf7, 0x5d, 0xf9, 0x08, 0x99, 0xff, 0xf7, 0xb3, 0xf9, + 0x08, 0x90, 0x38, 0x46, 0x48, 0x49, 0xff, 0xf7, 0xae, 0xf9, 0x04, 0x46, 0x44, 0x4f, 0x79, 0x68, + 0x30, 0x46, 0xff, 0xf7, 0xa8, 0xf9, 0x0c, 0x99, 0xff, 0xf7, 0x4c, 0xf9, 0x05, 0x46, 0x79, 0x68, + 0x0b, 0x98, 0xff, 0xf7, 0xa0, 0xf9, 0x79, 0x68, 0xff, 0xf7, 0x9d, 0xf9, 0x01, 0x46, 0x28, 0x46, + 0xff, 0xf7, 0x40, 0xf9, 0x01, 0x46, 0x20, 0x46, 0xff, 0xf7, 0x95, 0xf9, 0x01, 0x46, 0x08, 0x98, + 0xff, 0xf7, 0x38, 0xf9, 0x39, 0x46, 0x1c, 0x31, 0x04, 0x9c, 0x0a, 0x9d, 0x09, 0x9e, 0x49, 0x19, + 0x08, 0x61, 0x2d, 0x1d, 0x76, 0x1c, 0x00, 0x2d, 0x00, 0xd0, 0x6f, 0xe7, 0x2d, 0x4e, 0xb0, 0x6c, + 0x01, 0x99, 0xff, 0xf7, 0x80, 0xf9, 0x0b, 0x90, 0x30, 0x6d, 0x00, 0x9e, 0x31, 0x46, 0xff, 0xf7, + 0x7a, 0xf9, 0xb9, 0x68, 0xff, 0xf7, 0x77, 0xf9, 0x0c, 0x9c, 0x21, 0x46, 0xff, 0xf7, 0x1a, 0xf9, + 0x05, 0x46, 0x24, 0x48, 0x40, 0x6d, 0x31, 0x46, 0xff, 0xf7, 0x6d, 0xf9, 0xb9, 0x68, 0xff, 0xf7, + 0x6a, 0xf9, 0xb9, 0x68, 0xff, 0xf7, 0x67, 0xf9, 0x01, 0x46, 0x28, 0x46, 0xff, 0xf7, 0x0a, 0xf9, + 0x01, 0x46, 0x0b, 0x98, 0xff, 0xf7, 0x5f, 0xf9, 0x38, 0x61, 0x1a, 0x49, 0x88, 0x6d, 0x0d, 0x46, + 0x01, 0x99, 0xff, 0xf7, 0x58, 0xf9, 0xb9, 0x68, 0xff, 0xf7, 0x55, 0xf9, 0x21, 0x46, 0xff, 0xf7, + 0xf9, 0xf8, 0x04, 0x46, 0xe8, 0x6d, 0x31, 0x46, 0xff, 0xf7, 0x4d, 0xf9, 0xb9, 0x68, 0xff, 0xf7, + 0x4a, 0xf9, 0xb9, 0x68, 0xff, 0xf7, 0x47, 0xf9, 0x01, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xea, 0xf8, + 0x01, 0x46, 0xe8, 0x6c, 0xff, 0xf7, 0x3f, 0xf9, 0x10, 0x49, 0xff, 0xf7, 0xe3, 0xf8, 0x08, 0x4b, + 0x78, 0x61, 0x00, 0xbf, 0x00, 0xbf, 0x03, 0x20, 0x58, 0x70, 0x02, 0x9c, 0x07, 0x9e, 0x98, 0x20, + 0x31, 0x58, 0x80, 0x22, 0x0a, 0x43, 0x32, 0x50, 0x30, 0x68, 0x20, 0x43, 0x30, 0x60, 0x31, 0xe6, + 0xf0, 0x01, 0x00, 0x20, 0x70, 0x01, 0x00, 0x20, 0x00, 0x08, 0x00, 0x40, 0x01, 0x53, 0x4d, 0x41, + 0xe0, 0x02, 0x00, 0x20, 0x52, 0xb8, 0x5e, 0x3f, 0xb8, 0x1e, 0x05, 0x3e, 0x00, 0x00, 0xe0, 0xc0, + 0x00, 0x20, 0x01, 0xe0, 0x00, 0xbf, 0x40, 0x1c, 0xc1, 0xb2, 0x18, 0x29, 0xfa, 0xd3, 0x05, 0x21, + 0x08, 0x48, 0x02, 0x68, 0x00, 0x2a, 0x05, 0xda, 0x01, 0x22, 0x52, 0x02, 0x00, 0x23, 0x49, 0x1e, + 0xf7, 0xd1, 0x01, 0xe0, 0x03, 0x68, 0x00, 0x22, 0x03, 0x48, 0x83, 0x70, 0x81, 0x6f, 0x89, 0x18, + 0x81, 0x67, 0x70, 0x47, 0x84, 0x00, 0x00, 0x40, 0x70, 0x01, 0x00, 0x20, 0x10, 0xb5, 0x04, 0x46, + 0x03, 0x48, 0x04, 0x70, 0xff, 0xf7, 0xfa, 0xfa, 0x20, 0x46, 0xff, 0xf7, 0x27, 0xfb, 0x10, 0xbd, + 0x70, 0x01, 0x00, 0x20, 0x02, 0x48, 0x01, 0x68, 0x49, 0x1c, 0x01, 0x60, 0x70, 0x47, 0xc0, 0x46, + 0x68, 0x01, 0x00, 0x20, 0x70, 0xb5, 0x04, 0x46, 0x7c, 0x20, 0x15, 0x4d, 0x60, 0x21, 0x29, 0x54, + 0x7d, 0x20, 0x01, 0x21, 0x29, 0x54, 0x00, 0xf0, 0x47, 0xf8, 0xc4, 0x20, 0x00, 0x26, 0x2e, 0x50, + 0x10, 0x48, 0x01, 0x68, 0xff, 0x22, 0x91, 0x43, 0xb0, 0x22, 0x0a, 0x43, 0x02, 0x60, 0xff, 0xf7, + 0xd5, 0xfa, 0x2e, 0x60, 0xae, 0x60, 0xee, 0x60, 0x2e, 0x61, 0x6e, 0x61, 0xae, 0x61, 0xee, 0x61, + 0x2e, 0x62, 0x6e, 0x62, 0x00, 0x2c, 0x04, 0xd0, 0xc5, 0x20, 0x40, 0x21, 0x29, 0x54, 0x00, 0x21, + 0x29, 0x54, 0x05, 0x48, 0x05, 0x49, 0x01, 0x60, 0x00, 0x21, 0x81, 0x60, 0x70, 0xbd, 0xc0, 0x46, + 0x04, 0x00, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x0c, 0x00, 0x40, 0xff, 0x07, 0x00, 0x00, + 0x70, 0xb5, 0x0b, 0x4e, 0x35, 0x46, 0x1c, 0x35, 0x0a, 0x4b, 0x1c, 0x68, 0xb0, 0x42, 0x04, 0xd3, + 0xa8, 0x42, 0x02, 0xd8, 0x01, 0x25, 0xad, 0x02, 0x01, 0xe0, 0x01, 0x25, 0x6d, 0x02, 0xac, 0x43, + 0x1c, 0x60, 0x01, 0x70, 0x00, 0x2a, 0x02, 0xd0, 0x18, 0x68, 0x28, 0x43, 0x18, 0x60, 0x70, 0xbd, + 0xf0, 0x00, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x03, 0x20, 0x40, 0x02, 0x0c, 0x49, 0x0a, 0x68, + 0x82, 0x43, 0x0a, 0x60, 0x0b, 0x48, 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x81, 0x60, 0xc1, 0x60, + 0x01, 0x61, 0x41, 0x61, 0x81, 0x61, 0xc1, 0x61, 0x01, 0x62, 0x41, 0x62, 0x81, 0x62, 0x81, 0x65, + 0xc1, 0x65, 0x01, 0x66, 0x41, 0x66, 0x81, 0x66, 0xc1, 0x66, 0x01, 0x67, 0x41, 0x67, 0x70, 0x47, + 0x00, 0x08, 0x00, 0x40, 0x98, 0x00, 0x00, 0x40, 0xf8, 0xb5, 0x27, 0x4d, 0x28, 0x89, 0x01, 0xf0, + 0x40, 0xf8, 0x01, 0x46, 0x25, 0x4c, 0x20, 0x69, 0xff, 0xf7, 0x6d, 0xf8, 0x61, 0x69, 0xff, 0xf7, + 0x11, 0xf8, 0xe9, 0x79, 0x89, 0x00, 0x65, 0x18, 0xe8, 0x62, 0xe8, 0x69, 0xe9, 0x6a, 0xff, 0xf7, + 0x5a, 0xf8, 0xe8, 0x63, 0xe8, 0x6b, 0xe9, 0x6c, 0xff, 0xf7, 0x04, 0xf8, 0xe8, 0x65, 0x2e, 0x46, + 0x5c, 0x36, 0x2f, 0x46, 0x4c, 0x37, 0xe8, 0x6d, 0x3c, 0x35, 0x00, 0x24, 0x21, 0x46, 0x01, 0xf0, + 0x04, 0xf8, 0x00, 0x28, 0x01, 0xd1, 0x00, 0x20, 0x30, 0x60, 0x30, 0x68, 0x38, 0x60, 0x14, 0x4f, + 0x38, 0x6e, 0x29, 0x68, 0xff, 0xf7, 0x47, 0xf8, 0x05, 0x46, 0x78, 0x6e, 0x31, 0x68, 0xff, 0xf7, + 0x42, 0xf8, 0x01, 0x46, 0x28, 0x46, 0xfe, 0xf7, 0xe5, 0xff, 0x05, 0x46, 0x21, 0x46, 0x00, 0xf0, + 0xde, 0xff, 0x00, 0x28, 0x08, 0xd1, 0x0b, 0x4e, 0x28, 0x46, 0x31, 0x46, 0x00, 0xf0, 0xc9, 0xff, + 0x00, 0x28, 0x2c, 0x46, 0x00, 0xd1, 0x34, 0x46, 0x20, 0x46, 0x01, 0xf0, 0x01, 0xf8, 0x02, 0x49, + 0x48, 0x81, 0x00, 0xbf, 0x00, 0xbf, 0xf8, 0xbd, 0xf0, 0x01, 0x00, 0x20, 0xe0, 0x02, 0x00, 0x20, + 0x70, 0x01, 0x00, 0x20, 0x00, 0xfc, 0x7f, 0x46, 0xb0, 0xb5, 0x0c, 0x46, 0x13, 0x49, 0x40, 0x18, + 0xff, 0xf7, 0xbf, 0xf8, 0x41, 0x21, 0x09, 0x06, 0xff, 0xf7, 0x15, 0xf8, 0x35, 0x21, 0x09, 0x06, + 0xff, 0xf7, 0x11, 0xf8, 0x05, 0x46, 0x00, 0xbf, 0x00, 0xbf, 0x0d, 0x48, 0x00, 0x6f, 0x0d, 0x49, + 0xff, 0xf7, 0x09, 0xf8, 0x01, 0x46, 0x28, 0x46, 0xff, 0xf7, 0x05, 0xf8, 0x00, 0xf0, 0x6a, 0xf8, + 0x09, 0x49, 0x89, 0x69, 0xfe, 0xf7, 0xff, 0xff, 0x45, 0x21, 0x09, 0x06, 0xfe, 0xf7, 0xfb, 0xff, + 0x00, 0xf0, 0xe2, 0xff, 0x00, 0xf0, 0x0a, 0xf8, 0x20, 0x80, 0xb0, 0xbd, 0x00, 0x00, 0xf0, 0xff, + 0x70, 0x01, 0x00, 0x20, 0x10, 0x02, 0xce, 0x3f, 0xe0, 0x02, 0x00, 0x20, 0xfe, 0xb5, 0x02, 0x46, + 0x0a, 0x43, 0x01, 0x26, 0xf4, 0x07, 0x00, 0x2a, 0x46, 0xd0, 0x00, 0x24, 0x24, 0x4a, 0x04, 0xe0, + 0xa4, 0x18, 0xc3, 0x0f, 0x49, 0x00, 0x19, 0x43, 0x40, 0x00, 0xc3, 0x0a, 0x4d, 0x05, 0x1d, 0x43, + 0xcb, 0x0a, 0x2b, 0x43, 0x00, 0x2b, 0xf3, 0xd0, 0x05, 0xe0, 0xf2, 0x02, 0xa4, 0x18, 0x42, 0x08, + 0xc8, 0x07, 0x10, 0x43, 0x49, 0x08, 0x02, 0x0b, 0x0b, 0x05, 0x13, 0x43, 0x0a, 0x0b, 0x1a, 0x43, + 0x00, 0x2a, 0xf2, 0xd1, 0xb2, 0x02, 0x02, 0x92, 0x0b, 0x22, 0x23, 0xe0, 0x01, 0x92, 0x02, 0x46, + 0x0b, 0x46, 0x00, 0xf0, 0xf5, 0xfe, 0x4b, 0x05, 0xc2, 0x0a, 0x1a, 0x43, 0x4b, 0x02, 0xc0, 0x0d, + 0x18, 0x43, 0xcb, 0x0d, 0x03, 0x43, 0x00, 0x2b, 0x37, 0x46, 0x35, 0x46, 0x00, 0xd1, 0x1d, 0x46, + 0xea, 0x40, 0x1f, 0x26, 0x6e, 0x40, 0xc9, 0x0a, 0x48, 0x00, 0xb0, 0x40, 0x10, 0x43, 0x02, 0x9e, + 0xa2, 0x19, 0x00, 0x2b, 0x00, 0xd0, 0x14, 0x46, 0xe9, 0x40, 0x01, 0x9a, 0x52, 0x1e, 0x76, 0x10, + 0x02, 0x96, 0x3e, 0x46, 0x00, 0x2a, 0xd9, 0xd1, 0x20, 0x46, 0x03, 0xb0, 0xf0, 0xbd, 0xc0, 0x46, + 0x00, 0xf8, 0xff, 0xff, 0xf8, 0xb5, 0x04, 0x46, 0x00, 0x25, 0x29, 0x46, 0x00, 0xf0, 0x37, 0xff, + 0x01, 0x46, 0x8f, 0x20, 0xc0, 0x05, 0x00, 0x29, 0x00, 0xd0, 0x62, 0x48, 0x21, 0x46, 0xfe, 0xf7, + 0x8a, 0xff, 0x00, 0xf0, 0x5d, 0xff, 0x09, 0x21, 0x09, 0x04, 0x88, 0x42, 0x00, 0xd9, 0xb5, 0xe0, + 0x5d, 0x49, 0x41, 0x18, 0x00, 0x29, 0x0b, 0x46, 0x00, 0xda, 0x03, 0x46, 0x5b, 0x48, 0x1a, 0x18, + 0xc8, 0x17, 0x01, 0x21, 0x0e, 0x06, 0x86, 0x19, 0x59, 0x48, 0x30, 0x40, 0x06, 0x01, 0x00, 0x2a, + 0x00, 0xda, 0x06, 0x46, 0xb0, 0x00, 0x00, 0x2a, 0x00, 0xda, 0x1a, 0x46, 0x55, 0x4b, 0xd3, 0x18, + 0x00, 0x2b, 0x00, 0xda, 0x30, 0x46, 0x00, 0x2b, 0x00, 0xda, 0x13, 0x46, 0x52, 0x4a, 0x9a, 0x18, + 0x00, 0x2a, 0x04, 0xdb, 0x40, 0x00, 0x8b, 0x07, 0x98, 0x42, 0x01, 0xd9, 0x8e, 0xe0, 0x1a, 0x46, + 0x4e, 0x4b, 0xd3, 0x18, 0x45, 0x08, 0x45, 0x19, 0x00, 0x2b, 0x00, 0xda, 0x05, 0x46, 0xa8, 0x08, + 0x28, 0x18, 0x00, 0x2b, 0x00, 0xda, 0x13, 0x46, 0x49, 0x4a, 0x9a, 0x18, 0x00, 0x2a, 0x00, 0xda, + 0x28, 0x46, 0xc5, 0x08, 0x45, 0x19, 0x00, 0x2a, 0x00, 0xda, 0x1a, 0x46, 0x45, 0x4b, 0xd3, 0x18, + 0x00, 0x2b, 0x00, 0xda, 0x05, 0x46, 0x28, 0x09, 0x28, 0x18, 0x00, 0x2b, 0x00, 0xda, 0x13, 0x46, + 0x41, 0x4a, 0x9a, 0x18, 0x00, 0x2a, 0x00, 0xda, 0x28, 0x46, 0x45, 0x09, 0x45, 0x19, 0x00, 0x2a, + 0x00, 0xda, 0x1a, 0x46, 0x3d, 0x4b, 0xd3, 0x18, 0x00, 0x2b, 0x00, 0xda, 0x05, 0x46, 0xa8, 0x09, + 0x2e, 0x18, 0x00, 0x2b, 0x00, 0xda, 0x13, 0x46, 0x39, 0x48, 0x1f, 0x18, 0x00, 0x2f, 0x00, 0xda, + 0x2e, 0x46, 0xf0, 0x09, 0x30, 0x18, 0x00, 0x2f, 0x00, 0xda, 0x1f, 0x46, 0x35, 0x4a, 0xba, 0x18, + 0x00, 0x2a, 0x00, 0xda, 0x30, 0x46, 0x03, 0x0a, 0xc3, 0x18, 0x00, 0x2a, 0x00, 0xda, 0x3a, 0x46, + 0x0d, 0x02, 0x2a, 0x42, 0x00, 0xd0, 0x18, 0x46, 0x43, 0x0a, 0xc3, 0x18, 0x80, 0x25, 0x2a, 0x42, + 0x00, 0xd0, 0x18, 0x46, 0x83, 0x0a, 0xc3, 0x18, 0x40, 0x25, 0x2a, 0x42, 0x00, 0xd0, 0x18, 0x46, + 0xc3, 0x0a, 0xc3, 0x18, 0x20, 0x25, 0x2a, 0x42, 0x00, 0xd0, 0x18, 0x46, 0x03, 0x0b, 0xc3, 0x18, + 0x10, 0x25, 0x2a, 0x42, 0x00, 0xd0, 0x18, 0x46, 0x43, 0x0b, 0xc3, 0x18, 0x08, 0x25, 0x2a, 0x42, + 0x00, 0xd0, 0x18, 0x46, 0x83, 0x0b, 0xc3, 0x18, 0x04, 0x25, 0x2a, 0x42, 0x00, 0xd0, 0x18, 0x46, + 0xc3, 0x0b, 0xc3, 0x18, 0x02, 0x25, 0x2a, 0x42, 0x00, 0xd0, 0x18, 0x46, 0x03, 0x0c, 0xc3, 0x18, + 0x0a, 0x42, 0x00, 0xd0, 0x18, 0x46, 0x00, 0xf0, 0xac, 0xfe, 0x6f, 0x21, 0xc9, 0x05, 0xfe, 0xf7, + 0xda, 0xfe, 0x05, 0x46, 0x00, 0x21, 0x20, 0x46, 0x00, 0xf0, 0x87, 0xfe, 0x00, 0x28, 0x05, 0xd1, + 0x7f, 0x20, 0xc0, 0x05, 0x29, 0x46, 0xfe, 0xf7, 0x0b, 0xff, 0x05, 0x46, 0x28, 0x46, 0x01, 0xb0, + 0xf0, 0xbd, 0xc0, 0x46, 0x00, 0x00, 0x80, 0xc7, 0x6f, 0x74, 0xfa, 0xff, 0x38, 0x3a, 0xfd, 0xff, + 0x00, 0x00, 0x01, 0xff, 0x1c, 0x9d, 0xfe, 0xff, 0x8e, 0x4e, 0xff, 0xff, 0x33, 0x98, 0xff, 0xff, + 0xe0, 0xc6, 0xff, 0xff, 0xd9, 0xe1, 0xff, 0xff, 0x7b, 0xf0, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, + 0x08, 0xfc, 0xff, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xf0, 0xb5, 0x8d, 0xb0, 0x08, 0x90, 0x00, 0x25, + 0x0c, 0x95, 0x0b, 0x95, 0x0a, 0x95, 0x09, 0x95, 0x24, 0x20, 0xf0, 0x4f, 0x01, 0xe0, 0x3d, 0x50, + 0x00, 0x1d, 0x34, 0x28, 0xfb, 0xd1, 0x3b, 0x20, 0x07, 0x90, 0x3a, 0x21, 0x39, 0x22, 0x38, 0x23, + 0x3e, 0x68, 0x01, 0x20, 0xeb, 0x4c, 0xa6, 0x42, 0x00, 0xd0, 0xcd, 0xe1, 0xe8, 0x4e, 0xf3, 0x5c, + 0x01, 0x2b, 0x00, 0xd0, 0xc8, 0xe1, 0xb2, 0x5c, 0x01, 0x2a, 0x00, 0xd0, 0xc4, 0xe1, 0x71, 0x5c, + 0x01, 0x29, 0x00, 0xd0, 0xc0, 0xe1, 0x07, 0x9c, 0x31, 0x5d, 0x01, 0x29, 0x00, 0xd0, 0xbb, 0xe1, + 0x08, 0x98, 0x05, 0x72, 0xb0, 0x8f, 0x00, 0x28, 0x00, 0xd1, 0x85, 0xe0, 0x00, 0xf0, 0x49, 0xfe, + 0x31, 0x46, 0x06, 0x46, 0xc8, 0x8f, 0x00, 0xf0, 0x44, 0xfe, 0x21, 0x06, 0xfe, 0xf7, 0x73, 0xfe, + 0x07, 0x90, 0x79, 0x20, 0xc1, 0x05, 0x30, 0x46, 0xfe, 0xf7, 0x6d, 0xfe, 0x06, 0x46, 0xd6, 0x49, + 0xfe, 0xf7, 0x10, 0xfe, 0xd5, 0x49, 0xfe, 0xf7, 0x66, 0xfe, 0x04, 0x46, 0xd4, 0x49, 0x30, 0x46, + 0xfe, 0xf7, 0x08, 0xfe, 0x01, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0x9a, 0xfe, 0x00, 0xf0, 0x48, 0xff, + 0xd0, 0x49, 0xfe, 0xf7, 0x58, 0xfe, 0x01, 0x46, 0x07, 0x98, 0xfe, 0xf7, 0x54, 0xfe, 0x04, 0x46, + 0xcd, 0x49, 0x30, 0x46, 0xfe, 0xf7, 0x4f, 0xfe, 0x01, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0x88, 0xfe, + 0xca, 0x49, 0xfe, 0xf7, 0x48, 0xfe, 0x04, 0x46, 0x7f, 0x20, 0xc6, 0x05, 0x20, 0x46, 0x31, 0x46, + 0x00, 0xf0, 0xe5, 0xfd, 0x00, 0x28, 0x07, 0xd1, 0xc5, 0x49, 0x20, 0x46, 0x00, 0xf0, 0xd1, 0xfd, + 0x00, 0x28, 0x26, 0x46, 0x00, 0xd1, 0xc2, 0x4e, 0xc2, 0x49, 0x30, 0x46, 0xfe, 0xf7, 0x70, 0xfe, + 0x00, 0xf0, 0xcc, 0xff, 0xc0, 0x49, 0x04, 0x46, 0x06, 0x94, 0xfe, 0xf7, 0x2c, 0xfe, 0x07, 0x90, + 0xb3, 0x48, 0x00, 0x88, 0x00, 0xf0, 0xf5, 0xfd, 0x1d, 0x21, 0x4e, 0x06, 0x31, 0x46, 0xfe, 0xf7, + 0x22, 0xfe, 0x01, 0x46, 0x07, 0x98, 0xfe, 0xf7, 0xc5, 0xfd, 0x07, 0x90, 0x78, 0x62, 0xb7, 0x49, + 0x20, 0x46, 0xfe, 0xf7, 0x18, 0xfe, 0x04, 0x46, 0xa9, 0x48, 0xc0, 0x89, 0x00, 0xf0, 0xe1, 0xfd, + 0x31, 0x46, 0xfe, 0xf7, 0x10, 0xfe, 0x01, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0xb3, 0xfd, 0x05, 0x90, + 0xb8, 0x62, 0xaf, 0x49, 0x06, 0x98, 0xfe, 0xf7, 0x06, 0xfe, 0x04, 0x46, 0xa0, 0x49, 0x08, 0x46, + 0x80, 0x8b, 0x00, 0xf0, 0xce, 0xfd, 0x31, 0x46, 0x9d, 0x4e, 0xfe, 0xf7, 0xfc, 0xfd, 0x01, 0x46, + 0x20, 0x46, 0xfe, 0xf7, 0x9f, 0xfd, 0x17, 0xe0, 0x30, 0x88, 0x00, 0xf0, 0xc2, 0xfd, 0x1d, 0x21, + 0x4c, 0x06, 0x21, 0x46, 0xfe, 0xf7, 0xef, 0xfd, 0x07, 0x90, 0x78, 0x62, 0xf0, 0x89, 0x00, 0xf0, + 0xb8, 0xfd, 0x21, 0x46, 0xfe, 0xf7, 0xe7, 0xfd, 0x05, 0x90, 0xb8, 0x62, 0xb0, 0x8b, 0x00, 0xf0, + 0xb0, 0xfd, 0x21, 0x46, 0xfe, 0xf7, 0xdf, 0xfd, 0x04, 0x90, 0xf8, 0x62, 0x70, 0x8d, 0x00, 0xf0, + 0xa8, 0xfd, 0x1d, 0x21, 0x49, 0x06, 0xfe, 0xf7, 0xd6, 0xfd, 0x38, 0x63, 0x34, 0x21, 0x79, 0x5c, + 0x0f, 0x22, 0xd4, 0x43, 0x06, 0x91, 0x01, 0x29, 0x00, 0xd0, 0x93, 0xe0, 0x03, 0x90, 0xb8, 0x6b, + 0x4b, 0x21, 0x89, 0x00, 0x00, 0x22, 0x88, 0x42, 0x07, 0xd8, 0x40, 0x1c, 0xb8, 0x63, 0x08, 0x9a, + 0x10, 0x7a, 0x04, 0x21, 0x01, 0x43, 0x11, 0x72, 0x01, 0x22, 0xf9, 0x6b, 0x89, 0x48, 0x81, 0x42, + 0x07, 0x98, 0x05, 0x9e, 0x11, 0xd3, 0x20, 0x46, 0x05, 0xe0, 0x39, 0x18, 0x4a, 0x6a, 0x4a, 0x61, + 0x4a, 0x6b, 0x4a, 0x62, 0x00, 0x1d, 0x00, 0x28, 0xf7, 0xd1, 0x01, 0x20, 0xf8, 0x63, 0x08, 0x9a, + 0x10, 0x7a, 0x02, 0x21, 0x01, 0x43, 0x11, 0x72, 0x6c, 0xe0, 0x01, 0x91, 0x02, 0x92, 0x7e, 0x49, + 0x00, 0xf0, 0x37, 0xfd, 0x00, 0x28, 0x0a, 0xd1, 0x39, 0x6c, 0x7c, 0x48, 0x42, 0x1c, 0x91, 0x42, + 0x02, 0x9a, 0x06, 0xd2, 0x49, 0x1c, 0x39, 0x64, 0x81, 0x42, 0x02, 0xd8, 0x4b, 0xe0, 0x00, 0x20, + 0x38, 0x64, 0x79, 0x69, 0x07, 0x98, 0x00, 0xf0, 0x40, 0xfd, 0x00, 0x28, 0x01, 0xd1, 0x07, 0x98, + 0x78, 0x61, 0xb9, 0x69, 0x30, 0x46, 0x00, 0xf0, 0x38, 0xfd, 0x00, 0x28, 0x00, 0xd1, 0xbe, 0x61, + 0xf9, 0x69, 0x04, 0x98, 0x00, 0xf0, 0x15, 0xfd, 0x00, 0x28, 0x01, 0xd1, 0x04, 0x98, 0xf8, 0x61, + 0x39, 0x6a, 0x03, 0x9e, 0x30, 0x46, 0x00, 0xf0, 0x0c, 0xfd, 0x00, 0x28, 0x00, 0xd1, 0x3e, 0x62, + 0x79, 0x68, 0x07, 0x9e, 0x30, 0x46, 0x00, 0xf0, 0x20, 0xfd, 0x00, 0x28, 0x00, 0xd1, 0x7e, 0x60, + 0xb9, 0x68, 0x05, 0x9e, 0x30, 0x46, 0x00, 0xf0, 0x18, 0xfd, 0x00, 0x28, 0x00, 0xd1, 0xbe, 0x60, + 0xf9, 0x68, 0x04, 0x9e, 0x30, 0x46, 0x00, 0xf0, 0xf4, 0xfc, 0x00, 0x28, 0x00, 0xd1, 0xfe, 0x60, + 0x39, 0x69, 0x03, 0x9e, 0x30, 0x46, 0x00, 0xf0, 0xec, 0xfc, 0x00, 0x28, 0x00, 0xd1, 0x3e, 0x61, + 0x02, 0x9a, 0x00, 0x2a, 0x09, 0xd0, 0x04, 0x20, 0x03, 0xe0, 0x39, 0x18, 0x09, 0x69, 0x39, 0x50, + 0x00, 0x1d, 0x14, 0x28, 0xf9, 0xd1, 0x00, 0x2a, 0x0c, 0xd1, 0x01, 0x98, 0x40, 0x1c, 0xf8, 0x63, + 0x08, 0xe0, 0x39, 0x19, 0x48, 0x6b, 0x49, 0x69, 0xfe, 0xf7, 0x35, 0xfd, 0x09, 0xa9, 0x09, 0x19, + 0x08, 0x61, 0x24, 0x1d, 0x00, 0x2c, 0xf4, 0xd1, 0x0b, 0x98, 0x49, 0x49, 0x07, 0x90, 0xfe, 0xf7, + 0x32, 0xfd, 0x48, 0x49, 0xfe, 0xf7, 0xd6, 0xfc, 0x04, 0x46, 0x0c, 0x98, 0x46, 0x49, 0xfe, 0xf7, + 0x2a, 0xfd, 0x01, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0xcd, 0xfc, 0x05, 0x90, 0x0a, 0x98, 0x43, 0x49, + 0xfe, 0xf7, 0x21, 0xfd, 0x42, 0x49, 0xfe, 0xf7, 0xc5, 0xfc, 0x00, 0xf0, 0x73, 0xfd, 0x41, 0x49, + 0xfe, 0xf7, 0x19, 0xfd, 0x06, 0x46, 0x40, 0x4c, 0x21, 0x46, 0x00, 0xf0, 0xd4, 0xfc, 0x00, 0x28, + 0x00, 0xd1, 0x34, 0x46, 0x3d, 0x49, 0x07, 0x98, 0xfe, 0xf7, 0x0d, 0xfd, 0x3c, 0x49, 0xfe, 0xf7, + 0xb1, 0xfc, 0x00, 0xf0, 0x5f, 0xfd, 0x3b, 0x49, 0xfe, 0xf7, 0xac, 0xfc, 0x35, 0x49, 0xfe, 0xf7, + 0x02, 0xfd, 0x06, 0x46, 0x29, 0x46, 0x00, 0xf0, 0xa2, 0xfc, 0x00, 0x28, 0x07, 0xd1, 0x36, 0x49, + 0x30, 0x46, 0x00, 0xf0, 0x8e, 0xfc, 0x00, 0x28, 0x35, 0x46, 0x00, 0xd1, 0x32, 0x4d, 0x38, 0x6b, + 0x39, 0x69, 0x00, 0xf0, 0xb0, 0xfc, 0x00, 0x28, 0x01, 0xd0, 0x30, 0x4f, 0x14, 0xe0, 0x05, 0x98, + 0x00, 0xf0, 0x40, 0xfd, 0x2e, 0x49, 0xfe, 0xf7, 0x8d, 0xfc, 0x06, 0x46, 0x2d, 0x4f, 0x39, 0x46, + 0x00, 0xf0, 0x85, 0xfc, 0x00, 0x28, 0x07, 0xd1, 0x2b, 0x49, 0x30, 0x46, 0x00, 0xf0, 0x71, 0xfc, + 0x00, 0x28, 0x37, 0x46, 0x00, 0xd1, 0x28, 0x4f, 0x08, 0x9e, 0x06, 0x98, 0x30, 0x70, 0x38, 0x46, + 0x00, 0xf0, 0xa6, 0xfc, 0x70, 0x80, 0x28, 0x46, 0x00, 0xf0, 0xa2, 0xfc, 0xb0, 0x80, 0x20, 0x46, + 0x00, 0xf0, 0x9e, 0xfc, 0xf0, 0x80, 0x00, 0x20, 0x0d, 0xb0, 0xf0, 0xbd, 0x90, 0x02, 0x00, 0x20, + 0x50, 0x02, 0x00, 0x20, 0x01, 0x53, 0x4d, 0x41, 0x33, 0x93, 0x88, 0xc3, 0x29, 0x5c, 0x8d, 0x41, + 0x33, 0x33, 0xed, 0xc1, 0x81, 0x95, 0xc3, 0x40, 0x25, 0x06, 0x05, 0x41, 0x4b, 0x1f, 0x90, 0x41, + 0x00, 0x00, 0xc8, 0x42, 0xec, 0x51, 0x38, 0x41, 0x1f, 0x85, 0x6b, 0x3e, 0xe1, 0x7a, 0x94, 0x3e, + 0x9a, 0x99, 0x19, 0x3e, 0x81, 0x51, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x41, 0xff, 0xa2, 0x02, 0x00, + 0x14, 0xae, 0xc7, 0xbf, 0x00, 0x00, 0x18, 0x41, 0xd7, 0xa3, 0xf0, 0x3e, 0xcd, 0xcc, 0xcc, 0x3f, + 0xf6, 0x28, 0xec, 0xc0, 0x00, 0x00, 0x7a, 0x44, 0x00, 0xff, 0x7f, 0x47, 0x14, 0xae, 0xe7, 0xbf, + 0x00, 0x00, 0x80, 0xbf, 0x8f, 0xc2, 0xf5, 0xbe, 0x00, 0x40, 0x9c, 0x46, 0x00, 0x00, 0xc8, 0x43, + 0xe6, 0x09, 0x9d, 0xc3, 0x00, 0x00, 0xbe, 0x43, 0x00, 0xe8, 0x7d, 0x47, 0x70, 0xb5, 0x0c, 0x46, + 0x06, 0x46, 0x0d, 0x4d, 0x28, 0x46, 0x24, 0x30, 0x0c, 0x49, 0x34, 0x22, 0x00, 0xf0, 0xed, 0xfb, + 0x01, 0x20, 0x01, 0x2e, 0x0e, 0xd8, 0x69, 0x6a, 0x09, 0x4a, 0x91, 0x42, 0x0a, 0xd1, 0x54, 0x21, + 0x69, 0x5c, 0x89, 0x07, 0x06, 0xd4, 0x2c, 0x35, 0x14, 0x22, 0x20, 0x46, 0x29, 0x46, 0x00, 0xf0, + 0xdc, 0xfb, 0x00, 0x20, 0x70, 0xbd, 0xc0, 0x46, 0xf0, 0x01, 0x00, 0x20, 0x00, 0x38, 0x00, 0x10, + 0x02, 0x53, 0x4d, 0x41, 0x70, 0xb5, 0x1c, 0x4c, 0x62, 0x6a, 0x1c, 0x4b, 0x9a, 0x42, 0x31, 0xd1, + 0x00, 0xbf, 0x00, 0xbf, 0x01, 0x28, 0x2b, 0xd8, 0x17, 0x20, 0x40, 0x02, 0x18, 0x4d, 0x28, 0x64, + 0x01, 0x20, 0xc6, 0x02, 0x28, 0x68, 0x30, 0x42, 0xfc, 0xd1, 0x20, 0x46, 0x2c, 0x30, 0x00, 0x29, + 0x06, 0xd0, 0x14, 0x22, 0x00, 0xf0, 0xb9, 0xfb, 0x60, 0x6d, 0x02, 0x21, 0x88, 0x43, 0x06, 0xe0, + 0x14, 0x21, 0xff, 0x22, 0x00, 0xf0, 0xc3, 0xfb, 0x61, 0x6d, 0x02, 0x20, 0x08, 0x43, 0x60, 0x65, + 0x24, 0x34, 0x00, 0x20, 0x0a, 0xe0, 0x21, 0x68, 0xe9, 0x63, 0x07, 0x21, 0x49, 0x02, 0x01, 0x43, + 0x29, 0x64, 0x29, 0x68, 0x31, 0x42, 0xfc, 0xd1, 0x40, 0x1c, 0x24, 0x1d, 0x0d, 0x28, 0xf2, 0xd1, + 0x00, 0xbf, 0x00, 0xbf, 0x70, 0xbd, 0xc0, 0x46, 0xf0, 0x01, 0x00, 0x20, 0x02, 0x53, 0x4d, 0x41, + 0x04, 0x0c, 0x00, 0x40, 0x70, 0x47, 0xc0, 0x46, 0xf0, 0xb5, 0x99, 0xb0, 0xa4, 0x4f, 0x00, 0x24, + 0xbc, 0x67, 0x20, 0x46, 0xff, 0xf7, 0x2e, 0xfb, 0xa2, 0x49, 0xc0, 0x39, 0xa2, 0x48, 0x41, 0x60, + 0xff, 0x21, 0x12, 0x91, 0x09, 0x06, 0xa1, 0x4b, 0x1a, 0x68, 0x8a, 0x43, 0x03, 0x21, 0x18, 0x91, + 0x89, 0x07, 0x11, 0x43, 0x19, 0x60, 0x84, 0x60, 0x07, 0x26, 0x06, 0x60, 0x16, 0x94, 0x3c, 0x61, + 0xf0, 0x22, 0x02, 0x21, 0x81, 0x50, 0x01, 0x21, 0x17, 0x91, 0x81, 0x50, 0x04, 0x21, 0x81, 0x50, + 0x10, 0x21, 0x81, 0x50, 0x08, 0x21, 0x14, 0x91, 0x07, 0x92, 0x81, 0x50, 0x94, 0x4d, 0x2c, 0x46, + 0x24, 0x34, 0x94, 0x49, 0x34, 0x22, 0x20, 0x46, 0x00, 0xf0, 0x5f, 0xfb, 0x2a, 0x46, 0x17, 0x20, + 0x43, 0x02, 0x51, 0x6a, 0x90, 0x4d, 0x91, 0x48, 0x81, 0x42, 0x17, 0xd0, 0x50, 0x62, 0x16, 0x98, + 0xc0, 0x43, 0x50, 0x65, 0x2b, 0x64, 0x17, 0x98, 0xc0, 0x02, 0x29, 0x68, 0x01, 0x42, 0xfc, 0xd1, + 0x00, 0x21, 0x09, 0xe0, 0x22, 0x68, 0xea, 0x63, 0x72, 0x02, 0x0a, 0x43, 0x2a, 0x64, 0x2a, 0x68, + 0x02, 0x42, 0xfc, 0xd1, 0x49, 0x1c, 0x24, 0x1d, 0x0d, 0x29, 0xf3, 0xd1, 0x11, 0x93, 0xfe, 0xf7, + 0xb7, 0xfd, 0xff, 0xf7, 0xad, 0xfa, 0x16, 0x98, 0x78, 0x70, 0x2f, 0x21, 0xc8, 0x43, 0x2f, 0x30, + 0x38, 0x70, 0x17, 0x98, 0x03, 0x07, 0x28, 0x68, 0x00, 0x0f, 0x7d, 0x4c, 0xd0, 0x22, 0x06, 0x92, + 0x7c, 0x4a, 0x00, 0x28, 0x1a, 0xd0, 0x28, 0x68, 0x98, 0x42, 0x17, 0xd3, 0x16, 0x98, 0xc0, 0x43, + 0x15, 0x90, 0x79, 0x4b, 0x21, 0xcb, 0xed, 0x43, 0x08, 0x3b, 0xa8, 0x42, 0x0e, 0xd1, 0x98, 0x68, + 0x13, 0x90, 0xdd, 0x68, 0x15, 0x98, 0x45, 0x40, 0x13, 0x98, 0xa8, 0x42, 0x06, 0xd1, 0x18, 0x69, + 0x10, 0x40, 0x72, 0x4d, 0xa8, 0x42, 0x00, 0xd0, 0x23, 0x46, 0x1c, 0x46, 0x70, 0x48, 0x09, 0x02, + 0x18, 0x9b, 0x5b, 0x02, 0x18, 0x93, 0xb8, 0x33, 0xf8, 0x61, 0x3b, 0x62, 0x79, 0x62, 0xb9, 0x62, + 0x20, 0x69, 0x10, 0x40, 0x17, 0x99, 0x0d, 0x02, 0x49, 0x02, 0x68, 0x4a, 0x90, 0x42, 0x15, 0x91, + 0x13, 0x95, 0x00, 0xd0, 0xd2, 0xe0, 0x90, 0x20, 0x20, 0x58, 0x0f, 0x21, 0x09, 0x91, 0x08, 0x40, + 0xe0, 0x35, 0x12, 0x99, 0x09, 0x02, 0x63, 0x4a, 0x0f, 0x28, 0x13, 0xd0, 0xa0, 0x6a, 0x13, 0x46, + 0x02, 0x0c, 0x3a, 0x62, 0x0a, 0x46, 0xff, 0x32, 0x02, 0x40, 0xfa, 0x61, 0x60, 0x6a, 0x02, 0x0c, + 0x18, 0x40, 0xb8, 0x62, 0x1a, 0x40, 0x7a, 0x62, 0x1a, 0x46, 0xe0, 0x6a, 0x05, 0x0c, 0x10, 0x40, + 0x07, 0x90, 0x15, 0x40, 0x05, 0x95, 0x60, 0x69, 0x03, 0x0c, 0x13, 0x40, 0x22, 0x6b, 0x0d, 0x92, + 0x65, 0x6b, 0xa2, 0x6b, 0x0a, 0x92, 0xe2, 0x6b, 0x0b, 0x92, 0x22, 0x6a, 0x17, 0x92, 0x04, 0x93, + 0xfb, 0x62, 0x0a, 0x46, 0xff, 0x32, 0x02, 0x40, 0x00, 0x02, 0x08, 0x40, 0x8a, 0x42, 0x00, 0xd8, + 0x10, 0x46, 0x00, 0xf0, 0x1e, 0xfb, 0xf1, 0x06, 0xfe, 0xf7, 0x4d, 0xfb, 0x0c, 0x90, 0x0b, 0x98, + 0x48, 0x49, 0x0a, 0x46, 0x10, 0x40, 0x12, 0x90, 0x13, 0x98, 0xff, 0x30, 0x0a, 0x99, 0x01, 0x40, + 0x0e, 0x91, 0x17, 0x99, 0x01, 0x40, 0x17, 0x91, 0x20, 0x6c, 0x10, 0x40, 0x10, 0x90, 0xe1, 0x69, + 0x08, 0x0c, 0x11, 0x40, 0x0f, 0x91, 0x10, 0x40, 0x11, 0x90, 0x46, 0x20, 0x20, 0x5a, 0x08, 0x90, + 0x30, 0x48, 0x05, 0x40, 0x28, 0x46, 0x00, 0xf0, 0xfc, 0xfa, 0x77, 0x21, 0xc9, 0x05, 0x00, 0x91, + 0xfe, 0xf7, 0x29, 0xfb, 0x03, 0x90, 0x0d, 0x9e, 0x30, 0x46, 0x37, 0x49, 0x0d, 0x46, 0x28, 0x40, + 0x00, 0xf0, 0xef, 0xfa, 0x7b, 0x21, 0xc9, 0x05, 0xfe, 0xf7, 0x1d, 0xfb, 0x02, 0x90, 0x30, 0x0c, + 0x28, 0x40, 0x00, 0xf0, 0xe6, 0xfa, 0x3d, 0x21, 0x09, 0x06, 0xfe, 0xf7, 0x14, 0xfb, 0x0d, 0x90, + 0x0a, 0x98, 0x00, 0x0c, 0x1f, 0x4d, 0x28, 0x40, 0x00, 0xf0, 0xdb, 0xfa, 0x00, 0x9e, 0x31, 0x46, + 0xfe, 0xf7, 0x09, 0xfb, 0x01, 0x90, 0x0b, 0x98, 0x00, 0x0c, 0x28, 0x40, 0x00, 0xf0, 0xd1, 0xfa, + 0x31, 0x46, 0xfe, 0xf7, 0x00, 0xfb, 0x0b, 0x90, 0xa5, 0x69, 0x28, 0x46, 0x21, 0x49, 0x08, 0x40, + 0x00, 0xf0, 0xc7, 0xfa, 0x09, 0x99, 0x8c, 0x06, 0x21, 0x46, 0xfe, 0xf7, 0xf4, 0xfa, 0x0a, 0x90, + 0x28, 0x0c, 0x17, 0x9d, 0x1b, 0x49, 0x08, 0x40, 0x00, 0xf0, 0xbb, 0xfa, 0x75, 0x21, 0xc9, 0x05, + 0xfe, 0xf7, 0xe9, 0xfa, 0x09, 0x90, 0x08, 0x98, 0xfa, 0x49, 0x08, 0x40, 0x00, 0xf0, 0xb1, 0xfa, + 0x31, 0x46, 0xfe, 0xf7, 0xe0, 0xfa, 0x08, 0x90, 0x04, 0x98, 0x00, 0xf0, 0xaa, 0xfa, 0x21, 0x46, + 0x02, 0x9c, 0xfe, 0xf7, 0xd8, 0xfa, 0x01, 0x9a, 0x03, 0x9b, 0x07, 0x99, 0x05, 0x9e, 0x3f, 0xe0, + 0x70, 0x01, 0x00, 0x20, 0xff, 0x1f, 0x00, 0x00, 0x10, 0xe0, 0x00, 0xe0, 0x20, 0xed, 0x00, 0xe0, + 0xf0, 0x01, 0x00, 0x20, 0x00, 0x38, 0x00, 0x10, 0x04, 0x0c, 0x00, 0x40, 0x02, 0x53, 0x4d, 0x41, + 0x00, 0x3c, 0x00, 0x10, 0x00, 0x00, 0xff, 0xff, 0x00, 0x40, 0x00, 0x10, 0x00, 0x00, 0xa5, 0xa5, + 0xd7, 0x23, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x11, 0x98, 0xe0, 0x30, + 0xf8, 0x62, 0x7f, 0x20, 0xc0, 0x05, 0x0c, 0x90, 0xe1, 0x48, 0x11, 0x90, 0x00, 0x1d, 0x12, 0x90, + 0x14, 0x31, 0x10, 0x91, 0x2e, 0x46, 0xe0, 0x36, 0x28, 0x46, 0xc4, 0x30, 0x0e, 0x90, 0x6b, 0x35, + 0xdc, 0x48, 0x08, 0x90, 0xdc, 0x4b, 0xdd, 0x4c, 0xdd, 0x48, 0x0d, 0x90, 0xdd, 0x4a, 0xde, 0x48, + 0x0a, 0x90, 0xde, 0x48, 0x09, 0x90, 0xde, 0x48, 0x0f, 0x90, 0xf0, 0x21, 0xdd, 0x48, 0x0b, 0x92, + 0x3b, 0x63, 0x7c, 0x63, 0x0d, 0x9b, 0xbb, 0x63, 0x08, 0x9b, 0xfb, 0x63, 0x3a, 0x64, 0x0b, 0x9a, + 0x7a, 0x64, 0x0a, 0x9a, 0xba, 0x64, 0x09, 0x9a, 0xfa, 0x64, 0x0c, 0x9a, 0x3a, 0x67, 0x78, 0x67, + 0x08, 0x46, 0x00, 0xf0, 0x4e, 0xfa, 0x1f, 0x21, 0x4c, 0x06, 0x21, 0x46, 0xfe, 0xf7, 0x7b, 0xfa, + 0x38, 0x66, 0x30, 0x46, 0x00, 0xf0, 0x45, 0xfa, 0x21, 0x46, 0xfe, 0xf7, 0x74, 0xfa, 0x78, 0x66, + 0x28, 0x46, 0x13, 0x9e, 0x30, 0x40, 0x00, 0xf0, 0x3c, 0xfa, 0x04, 0x46, 0xe8, 0xb2, 0x00, 0xf0, + 0x38, 0xfa, 0x21, 0x46, 0xfe, 0xf7, 0x5f, 0xfa, 0xb8, 0x66, 0x0e, 0x9d, 0x2e, 0x40, 0x70, 0x42, + 0xfe, 0xf7, 0x07, 0xfb, 0x79, 0x21, 0x17, 0x91, 0xce, 0x05, 0x31, 0x46, 0xfe, 0xf7, 0x5b, 0xfa, + 0x04, 0x46, 0xe8, 0xb2, 0x00, 0xf0, 0x25, 0xfa, 0x31, 0x46, 0xfe, 0xf7, 0x54, 0xfa, 0x01, 0x46, + 0x20, 0x46, 0xfe, 0xf7, 0xf7, 0xf9, 0xf8, 0x66, 0xb0, 0x48, 0x45, 0x1c, 0x0f, 0x9c, 0x20, 0x46, + 0x28, 0x40, 0x40, 0x42, 0xfe, 0xf7, 0xed, 0xfa, 0x31, 0x46, 0xfe, 0xf7, 0x44, 0xfa, 0x13, 0x90, + 0xaa, 0x48, 0x04, 0x40, 0x20, 0x46, 0x00, 0xf0, 0x0c, 0xfa, 0x31, 0x46, 0xfe, 0xf7, 0x3b, 0xfa, + 0x01, 0x46, 0x13, 0x98, 0xfe, 0xf7, 0xde, 0xf9, 0x38, 0x65, 0x10, 0x9c, 0x20, 0x46, 0x28, 0x40, + 0x40, 0x42, 0xfe, 0xf7, 0xd6, 0xfa, 0x75, 0x21, 0xce, 0x05, 0x31, 0x46, 0xfe, 0xf7, 0x2b, 0xfa, + 0x13, 0x90, 0x9e, 0x48, 0x04, 0x40, 0x20, 0x46, 0x00, 0xf0, 0xf3, 0xf9, 0x31, 0x46, 0xfe, 0xf7, + 0x22, 0xfa, 0x01, 0x46, 0x13, 0x98, 0xfe, 0xf7, 0xc5, 0xf9, 0x78, 0x65, 0x11, 0x9c, 0x20, 0x46, + 0x28, 0x40, 0x40, 0x42, 0xfe, 0xf7, 0xbd, 0xfa, 0x31, 0x46, 0xfe, 0xf7, 0x14, 0xfa, 0x13, 0x90, + 0x92, 0x48, 0x04, 0x40, 0x20, 0x46, 0x00, 0xf0, 0xdc, 0xf9, 0x31, 0x46, 0xfe, 0xf7, 0x0b, 0xfa, + 0x01, 0x46, 0x13, 0x98, 0xfe, 0xf7, 0xae, 0xf9, 0xb8, 0x65, 0x12, 0x9e, 0x35, 0x40, 0x68, 0x42, + 0xfe, 0xf7, 0xa7, 0xfa, 0x0f, 0x21, 0x8c, 0x06, 0x21, 0x46, 0xfe, 0xf7, 0xfc, 0xf9, 0x05, 0x46, + 0x86, 0x48, 0x06, 0x40, 0x30, 0x46, 0x00, 0xf0, 0xc4, 0xf9, 0x21, 0x46, 0xfe, 0xf7, 0xf3, 0xf9, + 0x01, 0x46, 0x28, 0x46, 0xfe, 0xf7, 0x96, 0xf9, 0xf8, 0x65, 0x00, 0xbf, 0x00, 0xbf, 0x01, 0x24, + 0x89, 0x4e, 0x8a, 0x4d, 0xb1, 0xe0, 0x01, 0x20, 0x38, 0x70, 0xae, 0xe0, 0x22, 0x46, 0x8a, 0x40, + 0x87, 0x49, 0x0a, 0x42, 0x00, 0xd1, 0xd3, 0xe0, 0xfe, 0xf7, 0x0a, 0xfd, 0xa5, 0xe0, 0xfe, 0xf7, + 0xdd, 0xfb, 0xff, 0xf7, 0x41, 0xf9, 0x28, 0x68, 0x15, 0x99, 0x08, 0x43, 0x28, 0x60, 0x00, 0x20, + 0x30, 0x63, 0x28, 0x68, 0x14, 0x99, 0x88, 0x43, 0x28, 0x60, 0x28, 0x68, 0x20, 0x43, 0x28, 0x60, + 0xf0, 0x6f, 0xf0, 0x67, 0xf0, 0x6f, 0xf0, 0x67, 0x8f, 0xe0, 0x05, 0x20, 0x0b, 0x21, 0xc9, 0x43, + 0x72, 0x58, 0x00, 0x2a, 0x04, 0xda, 0x40, 0x1e, 0xf8, 0xd1, 0x16, 0x99, 0x15, 0x98, 0x01, 0xe0, + 0x71, 0x58, 0x00, 0x20, 0xba, 0x6f, 0x10, 0x18, 0xb8, 0x67, 0xc8, 0xb2, 0x7a, 0x78, 0x82, 0x42, + 0x7b, 0xd0, 0x16, 0x9a, 0x3a, 0x61, 0x79, 0x70, 0x31, 0x78, 0x21, 0x42, 0x02, 0xd0, 0x31, 0x68, + 0xa1, 0x43, 0x31, 0x60, 0x00, 0x28, 0x68, 0xd0, 0xce, 0x28, 0x1d, 0xd0, 0xc2, 0x28, 0x2b, 0xd0, + 0xcc, 0x28, 0x2e, 0xd0, 0x0e, 0x28, 0x5e, 0xd1, 0x30, 0x46, 0x58, 0x30, 0x50, 0x21, 0x00, 0x22, + 0x13, 0x92, 0x65, 0x4b, 0x98, 0x47, 0x30, 0x46, 0x68, 0x30, 0x02, 0x21, 0x13, 0x9a, 0x62, 0x4b, + 0x98, 0x47, 0x30, 0x46, 0x6c, 0x30, 0x03, 0x21, 0x13, 0x9a, 0x5f, 0x4b, 0x98, 0x47, 0x30, 0x46, + 0x70, 0x30, 0x01, 0x21, 0x13, 0x9a, 0x43, 0xe0, 0x38, 0x20, 0x31, 0x5c, 0x06, 0x9a, 0x91, 0x42, + 0x05, 0xd0, 0x30, 0x5c, 0x06, 0x99, 0x49, 0x1c, 0xc9, 0xb2, 0x88, 0x42, 0x3d, 0xd1, 0x01, 0x20, + 0x00, 0x21, 0xff, 0xf7, 0x17, 0xfd, 0x38, 0xe0, 0xfe, 0xf7, 0x62, 0xfb, 0x53, 0x48, 0x38, 0x61, + 0x33, 0xe0, 0x30, 0x46, 0x58, 0x30, 0x00, 0x21, 0x13, 0x91, 0x0a, 0x46, 0x4e, 0x4b, 0x98, 0x47, + 0x30, 0x46, 0x5c, 0x30, 0x13, 0x99, 0x0a, 0x46, 0x4b, 0x4b, 0x98, 0x47, 0x30, 0x46, 0x60, 0x30, + 0x13, 0x99, 0x0a, 0x46, 0x48, 0x4b, 0x98, 0x47, 0x30, 0x46, 0x64, 0x30, 0x13, 0x99, 0x0a, 0x46, + 0x45, 0x4b, 0x98, 0x47, 0x30, 0x46, 0x68, 0x30, 0x13, 0x99, 0x0a, 0x46, 0x42, 0x4b, 0x98, 0x47, + 0x30, 0x46, 0x6c, 0x30, 0x13, 0x99, 0x0a, 0x46, 0x3f, 0x4b, 0x98, 0x47, 0x30, 0x46, 0x70, 0x30, + 0x13, 0x99, 0x0a, 0x46, 0x3c, 0x4b, 0x98, 0x47, 0x30, 0x46, 0x74, 0x30, 0x13, 0x99, 0x0a, 0x46, + 0x39, 0x4b, 0x98, 0x47, 0x01, 0xe0, 0x00, 0x20, 0x78, 0x70, 0x79, 0x78, 0x30, 0x46, 0x74, 0x30, + 0x49, 0x1c, 0xc9, 0xb2, 0x22, 0x46, 0xff, 0xf7, 0x83, 0xf8, 0xb8, 0x6f, 0x00, 0x28, 0x15, 0xd0, + 0x30, 0x68, 0x40, 0x21, 0x01, 0x43, 0x31, 0x60, 0x28, 0x68, 0x18, 0x99, 0x08, 0x43, 0x28, 0x60, + 0x78, 0x20, 0x39, 0x5c, 0x30, 0x46, 0x64, 0x30, 0x00, 0x22, 0xff, 0xf7, 0x71, 0xf8, 0x17, 0x98, + 0x39, 0x5c, 0x30, 0x46, 0x68, 0x30, 0x22, 0x46, 0xff, 0xf7, 0x6a, 0xf8, 0xb8, 0x78, 0x39, 0x78, + 0x88, 0x42, 0x02, 0xd0, 0xff, 0xf7, 0x1a, 0xf8, 0x38, 0x78, 0x21, 0x28, 0xdd, 0xd0, 0x81, 0x1e, + 0x03, 0x29, 0x00, 0xd2, 0x30, 0xe7, 0x01, 0x46, 0xc0, 0x39, 0x11, 0x29, 0x00, 0xd8, 0x25, 0xe7, + 0x00, 0x28, 0x00, 0xd1, 0x2b, 0xe7, 0x01, 0x28, 0x00, 0xd1, 0x3e, 0xe7, 0xb1, 0x28, 0x00, 0xd1, + 0x22, 0xe7, 0xf0, 0x28, 0x00, 0xd0, 0x16, 0xe7, 0x20, 0x46, 0xff, 0xf7, 0x13, 0xf8, 0xbf, 0xf3, + 0x4f, 0x8f, 0x13, 0x20, 0xc0, 0x43, 0x13, 0x49, 0x03, 0x4a, 0x11, 0x50, 0xbf, 0xf3, 0x4f, 0x8f, + 0x00, 0xbf, 0xfd, 0xe7, 0xff, 0x1f, 0x00, 0x00, 0x20, 0xed, 0x00, 0xe0, 0xff, 0x3f, 0x00, 0x00, + 0x29, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x41, 0x00, 0x20, 0x7c, 0x41, 0x00, 0x8c, 0x15, 0x44, + 0x00, 0x74, 0x8d, 0x43, 0x00, 0x00, 0x60, 0x41, 0x00, 0x00, 0x0f, 0x43, 0x00, 0x00, 0xe0, 0x40, + 0x20, 0x74, 0x00, 0x00, 0x00, 0x80, 0xbb, 0x42, 0x98, 0x00, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, + 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0xfa, 0x05, 0xe1, 0x17, 0x00, 0x10, 0xb5, 0x0e, 0x00, 0x10, + 0xf0, 0xb5, 0x1f, 0xb4, 0x86, 0xb0, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x06, 0x98, + 0x06, 0x99, 0x80, 0xb2, 0x04, 0x90, 0x07, 0x98, 0x09, 0x0c, 0x02, 0x04, 0x00, 0x14, 0x11, 0x43, + 0x07, 0x90, 0x00, 0x27, 0x08, 0x9d, 0x09, 0x98, 0x06, 0x91, 0x3e, 0x46, 0x3c, 0x46, 0x03, 0x90, + 0x03, 0x98, 0xa9, 0xb2, 0x02, 0x04, 0x00, 0x0c, 0x03, 0x90, 0x04, 0x98, 0x2d, 0x0c, 0x15, 0x43, + 0x48, 0x43, 0x00, 0x21, 0x22, 0x46, 0x00, 0xf0, 0xa7, 0xf8, 0xc7, 0x19, 0x71, 0x41, 0x10, 0x34, + 0x0e, 0x46, 0x40, 0x2c, 0xec, 0xdb, 0x38, 0x46, 0x02, 0x9a, 0x00, 0xf0, 0x9d, 0xf8, 0x00, 0x9a, + 0x01, 0x9b, 0x80, 0x18, 0x00, 0x90, 0x59, 0x41, 0x02, 0x98, 0x01, 0x91, 0x10, 0x30, 0x02, 0x90, + 0x40, 0x28, 0xcc, 0xdb, 0x00, 0x98, 0x0b, 0xb0, 0xf0, 0xbd, 0x03, 0x46, 0x0b, 0x43, 0x9b, 0x07, + 0x03, 0xd0, 0x09, 0xe0, 0x08, 0xc9, 0x12, 0x1f, 0x08, 0xc0, 0x04, 0x2a, 0xfa, 0xd2, 0x03, 0xe0, + 0x0b, 0x78, 0x03, 0x70, 0x40, 0x1c, 0x49, 0x1c, 0x52, 0x1e, 0xf9, 0xd2, 0x70, 0x47, 0xd2, 0xb2, + 0x01, 0xe0, 0x02, 0x70, 0x40, 0x1c, 0x49, 0x1e, 0xfb, 0xd2, 0x70, 0x47, 0x00, 0x22, 0xf6, 0xe7, + 0x10, 0xb5, 0x13, 0x46, 0x0a, 0x46, 0x04, 0x46, 0x19, 0x46, 0xff, 0xf7, 0xf0, 0xff, 0x20, 0x46, + 0x10, 0xbd, 0x01, 0x22, 0xd2, 0x07, 0x00, 0x28, 0x00, 0xdb, 0x10, 0x1a, 0x00, 0x29, 0x00, 0xdb, + 0x51, 0x1a, 0x81, 0x42, 0x01, 0xd8, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x22, + 0xd2, 0x07, 0x00, 0x28, 0x00, 0xdb, 0x10, 0x1a, 0x00, 0x29, 0x00, 0xdb, 0x51, 0x1a, 0x81, 0x42, + 0x01, 0xd2, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x22, 0xd2, 0x07, 0x00, 0x28, + 0x00, 0xdb, 0x10, 0x1a, 0x00, 0x29, 0x00, 0xdb, 0x51, 0x1a, 0x81, 0x42, 0x01, 0xd3, 0x01, 0x20, + 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x22, 0xd2, 0x07, 0x00, 0x28, 0x00, 0xdb, 0x10, 0x1a, + 0x00, 0x29, 0x00, 0xdb, 0x51, 0x1a, 0x81, 0x42, 0x01, 0xd9, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, + 0x70, 0x47, 0x10, 0xb5, 0x00, 0x22, 0x96, 0x23, 0x11, 0x46, 0xfe, 0xf7, 0x11, 0xf9, 0x10, 0xbd, + 0x41, 0x00, 0x40, 0x02, 0x01, 0x22, 0x40, 0x0a, 0xd2, 0x05, 0x09, 0x0e, 0x80, 0x18, 0x7f, 0x29, + 0x01, 0xda, 0x00, 0x20, 0x70, 0x47, 0x96, 0x29, 0x03, 0xdc, 0x96, 0x22, 0x51, 0x1a, 0xc8, 0x40, + 0x70, 0x47, 0x96, 0x39, 0x88, 0x40, 0x70, 0x47, 0x41, 0x00, 0x0a, 0x0e, 0x40, 0x02, 0x01, 0x21, + 0x40, 0x0a, 0xc9, 0x05, 0x10, 0xb5, 0x40, 0x18, 0x7f, 0x2a, 0x02, 0xda, 0x00, 0x20, 0x01, 0x46, + 0x10, 0xbd, 0x00, 0x21, 0x96, 0x2a, 0x03, 0xdc, 0x96, 0x23, 0x9a, 0x1a, 0xd0, 0x40, 0x10, 0xbd, + 0x96, 0x3a, 0x00, 0xf0, 0x01, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x20, 0x2a, 0x04, 0xdb, 0x01, 0x46, + 0x20, 0x3a, 0x91, 0x40, 0x00, 0x20, 0x10, 0xbd, 0x91, 0x40, 0x20, 0x23, 0x9c, 0x1a, 0x03, 0x46, + 0xe3, 0x40, 0x19, 0x43, 0x90, 0x40, 0x10, 0xbd, 0x41, 0x00, 0x08, 0x02, 0x00, 0xd0, 0x04, 0x20, + 0x0a, 0x0e, 0x01, 0xd0, 0x01, 0x22, 0x10, 0x43, 0x09, 0x0e, 0xff, 0x29, 0x01, 0xd1, 0x02, 0x21, + 0x08, 0x43, 0x01, 0x28, 0x00, 0xd1, 0x05, 0x20, 0x70, 0x47, 0x10, 0xb5, 0x7f, 0x20, 0x00, 0x21, + 0xc0, 0x05, 0xfe, 0xf7, 0x15, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x01, 0x21, 0xfe, 0xf7, 0x4e, 0xf8, + 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x21, 0x08, 0x46, 0xfe, 0xf7, 0x0a, 0xf8, 0x10, 0xbd, 0x10, 0xb5, + 0x07, 0x20, 0x61, 0x21, 0x00, 0x07, 0xfe, 0xf7, 0x41, 0xf8, 0x10, 0xbd, 0x5e, 0x21, 0x10, 0xb5, + 0xc9, 0x43, 0x08, 0x07, 0xfe, 0xf7, 0x3a, 0xf8, 0x10, 0xbd, 0x02, 0xe0, 0x08, 0xc8, 0x12, 0x1f, + 0x08, 0xc1, 0x00, 0x2a, 0xfa, 0xd1, 0x70, 0x47, 0x70, 0x47, 0x00, 0x20, 0x01, 0xe0, 0x01, 0xc1, + 0x12, 0x1f, 0x00, 0x2a, 0xfb, 0xd1, 0x70, 0x47, 0x01, 0x49, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x20, 0xf8, 0xb5, 0x04, 0x46, 0x99, 0x21, 0x40, 0x00, 0x09, 0x06, 0x3f, 0x4a, + 0x00, 0x25, 0x41, 0x18, 0x91, 0x42, 0x3f, 0xd8, 0x02, 0x21, 0x20, 0x46, 0xfe, 0xf7, 0x16, 0xf8, + 0xfe, 0xf7, 0x20, 0xf8, 0x06, 0x46, 0xfe, 0xf7, 0x47, 0xf8, 0x07, 0x46, 0x01, 0x21, 0xc9, 0x43, + 0x30, 0x46, 0xfe, 0xf7, 0x0b, 0xf8, 0x21, 0x46, 0xfd, 0xf7, 0x89, 0xff, 0x04, 0x46, 0x34, 0x49, + 0xfd, 0xf7, 0x89, 0xff, 0x33, 0x49, 0xfd, 0xf7, 0x2d, 0xff, 0x21, 0x46, 0xfd, 0xf7, 0x83, 0xff, + 0x31, 0x49, 0xfd, 0xf7, 0x27, 0xff, 0x21, 0x46, 0xfd, 0xf7, 0x7d, 0xff, 0x2f, 0x49, 0xfd, 0xf7, + 0x21, 0xff, 0x21, 0x46, 0xfd, 0xf7, 0x77, 0xff, 0x01, 0x46, 0xb8, 0x07, 0x04, 0x0f, 0x2c, 0x48, + 0x78, 0x44, 0x00, 0x59, 0xfd, 0xf7, 0x6f, 0xff, 0x2a, 0x49, 0x79, 0x44, 0x09, 0x59, 0xfd, 0xf7, + 0x11, 0xff, 0x29, 0x49, 0x79, 0x44, 0x09, 0x59, 0xfd, 0xf7, 0x0c, 0xff, 0xb9, 0x10, 0x00, 0x2d, + 0x27, 0xd1, 0xfd, 0xf7, 0xdb, 0xff, 0xf8, 0xbd, 0xe1, 0x43, 0x49, 0x00, 0x09, 0x0e, 0x06, 0xd0, + 0x67, 0x21, 0x09, 0x06, 0x88, 0x42, 0x0c, 0xd2, 0x7f, 0x20, 0xc0, 0x05, 0xf8, 0xbd, 0x01, 0x21, + 0xc9, 0x05, 0x20, 0x46, 0xcc, 0x42, 0x01, 0xd1, 0x00, 0x20, 0xf8, 0xbd, 0xff, 0xf7, 0x74, 0xff, + 0xf8, 0xbd, 0x1a, 0x49, 0x88, 0x42, 0x0a, 0xd9, 0x02, 0x20, 0xff, 0xf7, 0x95, 0xff, 0x00, 0x2c, + 0x02, 0xda, 0xff, 0xf7, 0x7b, 0xff, 0xf8, 0xbd, 0xff, 0xf7, 0x71, 0xff, 0xf8, 0xbd, 0x01, 0x25, + 0x9a, 0xe7, 0xfd, 0xf7, 0xb3, 0xff, 0x04, 0x00, 0x03, 0xd0, 0xff, 0x20, 0xc0, 0x05, 0x84, 0x42, + 0x02, 0xd1, 0x02, 0x20, 0xff, 0xf7, 0x80, 0xff, 0x20, 0x46, 0xff, 0xf7, 0x3d, 0xff, 0x04, 0x28, + 0x01, 0xd1, 0xff, 0xf7, 0x63, 0xff, 0x20, 0x46, 0xf8, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1e, + 0x81, 0xa4, 0x1d, 0x3c, 0x20, 0x6e, 0x63, 0x3d, 0xef, 0xfd, 0x75, 0x3e, 0x17, 0x72, 0x31, 0x3f, + 0x2c, 0x04, 0x00, 0x00, 0x12, 0x04, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x86, + 0xf8, 0xb5, 0x04, 0x46, 0x99, 0x21, 0x40, 0x00, 0x09, 0x06, 0x48, 0x4a, 0x00, 0x25, 0x41, 0x18, + 0x91, 0x42, 0x46, 0xd8, 0x46, 0x49, 0x20, 0x46, 0xfd, 0xf7, 0x05, 0xff, 0xfd, 0xf7, 0x8a, 0xff, + 0x06, 0x46, 0xfd, 0xf7, 0xb1, 0xff, 0x07, 0x46, 0x42, 0x49, 0x30, 0x46, 0xfd, 0xf7, 0xfb, 0xfe, + 0x00, 0x90, 0x41, 0x49, 0x30, 0x46, 0xfd, 0xf7, 0xf6, 0xfe, 0x21, 0x46, 0xfd, 0xf7, 0xef, 0xfe, + 0x00, 0x99, 0xfd, 0xf7, 0xe8, 0xfe, 0x04, 0x46, 0x3c, 0x49, 0xfd, 0xf7, 0xec, 0xfe, 0x3c, 0x49, + 0xfd, 0xf7, 0x90, 0xfe, 0x21, 0x46, 0xfd, 0xf7, 0xe6, 0xfe, 0x3a, 0x49, 0xfd, 0xf7, 0x8a, 0xfe, + 0x21, 0x46, 0xfd, 0xf7, 0xe0, 0xfe, 0x38, 0x49, 0xfd, 0xf7, 0x84, 0xfe, 0x21, 0x46, 0xfd, 0xf7, + 0xda, 0xfe, 0x01, 0x46, 0xb8, 0x07, 0x04, 0x0f, 0x34, 0x48, 0x78, 0x44, 0x00, 0x59, 0xfd, 0xf7, + 0xd2, 0xfe, 0x33, 0x49, 0x79, 0x44, 0x09, 0x59, 0xfd, 0xf7, 0x74, 0xfe, 0x31, 0x49, 0x79, 0x44, + 0x09, 0x59, 0xfd, 0xf7, 0x6f, 0xfe, 0xb9, 0x10, 0x00, 0x2d, 0x2a, 0xd1, 0xfd, 0xf7, 0x3e, 0xff, + 0xf8, 0xbd, 0xe1, 0x43, 0x49, 0x00, 0x09, 0x0e, 0x09, 0xd0, 0x67, 0x21, 0x09, 0x06, 0x88, 0x42, + 0x0f, 0xd2, 0x7f, 0x21, 0xc9, 0x05, 0x20, 0x46, 0xfd, 0xf7, 0x5c, 0xfe, 0xf8, 0xbd, 0x01, 0x21, + 0xc9, 0x05, 0x20, 0x46, 0xcc, 0x42, 0x01, 0xd1, 0x00, 0x20, 0xf8, 0xbd, 0xff, 0xf7, 0xd4, 0xfe, + 0xf8, 0xbd, 0x21, 0x49, 0x88, 0x42, 0x0a, 0xd9, 0x02, 0x20, 0xff, 0xf7, 0xf5, 0xfe, 0x00, 0x2c, + 0x02, 0xda, 0xff, 0xf7, 0xdb, 0xfe, 0xf8, 0xbd, 0xff, 0xf7, 0xd1, 0xfe, 0xf8, 0xbd, 0x01, 0x25, + 0x90, 0xe7, 0xfd, 0xf7, 0x13, 0xff, 0x04, 0x00, 0x09, 0xd0, 0xff, 0x20, 0xc0, 0x05, 0x84, 0x42, + 0x0b, 0xd1, 0x02, 0x20, 0xff, 0xf7, 0xe0, 0xfe, 0xff, 0xf7, 0xc1, 0xfe, 0xf8, 0xbd, 0x02, 0x20, + 0xff, 0xf7, 0xda, 0xfe, 0xff, 0xf7, 0xc2, 0xfe, 0xf8, 0xbd, 0x20, 0x46, 0xff, 0xf7, 0x94, 0xfe, + 0x04, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0xba, 0xfe, 0x20, 0x46, 0xf8, 0xbd, 0x00, 0x00, 0x50, 0x1e, + 0x3b, 0xaa, 0xb8, 0x40, 0xf4, 0xfd, 0x05, 0x37, 0x00, 0x70, 0x31, 0x3e, 0x12, 0xbb, 0x2a, 0x3d, + 0x12, 0xbb, 0x2a, 0x3e, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0x7f, 0x3f, 0x82, 0x02, 0x00, 0x00, + 0x68, 0x02, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x85, 0xf8, 0xb5, 0x01, 0x21, + 0xc9, 0x05, 0x7f, 0x22, 0x00, 0x26, 0x41, 0x1a, 0x12, 0x06, 0x91, 0x42, 0x7e, 0xd2, 0x01, 0x21, + 0xc9, 0x04, 0x41, 0x18, 0xca, 0x15, 0x01, 0x23, 0x41, 0x02, 0x1b, 0x07, 0xc9, 0x18, 0x4d, 0x0f, + 0x7f, 0x21, 0x7f, 0x3a, 0x2b, 0x05, 0xc9, 0x05, 0xb6, 0x18, 0x5c, 0x18, 0xd2, 0x05, 0x87, 0x1a, + 0x30, 0x46, 0x28, 0x43, 0x3a, 0xd0, 0x21, 0x46, 0x38, 0x46, 0xfd, 0xf7, 0xeb, 0xfd, 0x00, 0x90, + 0x21, 0x46, 0x38, 0x46, 0xfd, 0xf7, 0x37, 0xfe, 0x00, 0x99, 0xfd, 0xf7, 0x79, 0xfe, 0x07, 0x46, + 0x01, 0x46, 0xfd, 0xf7, 0x38, 0xfe, 0x3f, 0x49, 0x00, 0x90, 0xfd, 0xf7, 0x34, 0xfe, 0x3e, 0x49, + 0xfd, 0xf7, 0xd8, 0xfd, 0x04, 0x46, 0x38, 0x46, 0x00, 0x99, 0xfd, 0xf7, 0x2c, 0xfe, 0x21, 0x46, + 0xfd, 0xf7, 0x29, 0xfe, 0x01, 0x46, 0x39, 0x48, 0xad, 0x00, 0x78, 0x44, 0x40, 0x59, 0xfd, 0xf7, + 0xc9, 0xfd, 0x04, 0x46, 0x36, 0x49, 0x38, 0x46, 0xfd, 0xf7, 0x1d, 0xfe, 0x21, 0x46, 0xfd, 0xf7, + 0xc1, 0xfd, 0x04, 0x46, 0x30, 0x46, 0xfd, 0xf7, 0xbc, 0xfe, 0x32, 0x49, 0x79, 0x44, 0x49, 0x59, + 0xfd, 0xf7, 0xb8, 0xfd, 0x21, 0x46, 0xfd, 0xf7, 0xb5, 0xfd, 0xf8, 0xbd, 0x38, 0x46, 0xfd, 0xf7, + 0x02, 0xfe, 0x05, 0x46, 0x2c, 0x49, 0xfd, 0xf7, 0x06, 0xfe, 0x2c, 0x49, 0xfd, 0xf7, 0xaa, 0xfd, + 0x29, 0x46, 0xfd, 0xf7, 0x00, 0xfe, 0x2a, 0x49, 0xfd, 0xf7, 0xa4, 0xfd, 0x29, 0x46, 0xfd, 0xf7, + 0xfa, 0xfd, 0x28, 0x49, 0xfd, 0xf7, 0x9e, 0xfd, 0x04, 0x46, 0x29, 0x46, 0x08, 0x46, 0xfd, 0xf7, + 0xf2, 0xfd, 0x21, 0x46, 0xfd, 0xf7, 0xef, 0xfd, 0x04, 0x46, 0x23, 0x49, 0x28, 0x46, 0xfd, 0xf7, + 0xea, 0xfd, 0x21, 0x46, 0xfd, 0xf7, 0x8e, 0xfd, 0x04, 0x46, 0x20, 0x49, 0x28, 0x46, 0xfd, 0xf7, + 0xe2, 0xfd, 0x21, 0x46, 0xfd, 0xf7, 0x86, 0xfd, 0xf8, 0xbd, 0xff, 0xe7, 0xff, 0x22, 0x41, 0x00, + 0x12, 0x06, 0x91, 0x42, 0x02, 0xd9, 0xff, 0xf7, 0xff, 0xfd, 0xf8, 0xbd, 0xff, 0x22, 0xd2, 0x05, + 0x90, 0x42, 0xfa, 0xd0, 0x14, 0x02, 0xa0, 0x42, 0x05, 0xd9, 0x01, 0x20, 0xff, 0xf7, 0x1c, 0xfe, + 0xff, 0xf7, 0xf7, 0xfd, 0xf8, 0xbd, 0x41, 0x00, 0x05, 0xd0, 0x16, 0x26, 0xf6, 0x43, 0x17, 0x21, + 0xfd, 0xf7, 0x3c, 0xfe, 0x63, 0xe7, 0x02, 0x20, 0xff, 0xf7, 0x0e, 0xfe, 0xff, 0xf7, 0xdd, 0xfd, + 0x60, 0x40, 0xf8, 0xbd, 0xc9, 0xd5, 0x13, 0x3f, 0x4e, 0x38, 0x76, 0x3f, 0x52, 0x01, 0x00, 0x00, + 0x3b, 0xaa, 0x38, 0x40, 0x10, 0x01, 0x00, 0x00, 0x0e, 0x9c, 0x8c, 0x3e, 0xd0, 0xc2, 0xb8, 0xbe, + 0xe1, 0x39, 0xf6, 0x3e, 0x3b, 0xaa, 0x38, 0xbf, 0x29, 0x3b, 0xaa, 0x3b, 0x00, 0x00, 0xb8, 0x3f, + 0x00, 0x00, 0x80, 0x3f, 0x00, 0x30, 0x98, 0x3f, 0x00, 0x00, 0xb5, 0x3f, 0x00, 0x40, 0xd7, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x32, 0x0a, 0x7e, 0x39, 0x7f, 0x66, 0x1e, 0x39, 0x5b, 0x99, 0x1f, 0x39, + 0x00, 0x00, 0x80, 0x3f, 0xf0, 0x37, 0x98, 0x3f, 0xf3, 0x04, 0xb5, 0x3f, 0xfd, 0x44, 0xd7, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x3e, 0x00, 0xd0, 0xa4, 0x3e, 0x00, 0x30, 0xeb, 0x3e, + 0x00, 0xc0, 0x15, 0x3f, 0x00, 0x50, 0x33, 0x3f, 0x00, 0xa0, 0x4e, 0x3f, 0x00, 0x20, 0x68, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xdf, 0xcf, 0x51, 0x36, 0x9a, 0x97, 0xf0, 0x37, 0x19, 0xf0, 0xa9, 0x38, + 0xdf, 0xcf, 0xd1, 0x35, 0x89, 0x47, 0x8e, 0x34, 0xa8, 0xfe, 0x6c, 0x39, 0x93, 0xb6, 0x1f, 0x39, + 0x00, 0x00, 0x80, 0x3f, 0x00, 0x30, 0x98, 0x3f, 0x00, 0x00, 0xb5, 0x3f, 0x00, 0x40, 0xd7, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x32, 0x0a, 0x7e, 0x39, 0x7f, 0x66, 0x1e, 0x39, 0x5b, 0x99, 0x1f, 0x39, + 0x00, 0x00, 0x80, 0x3f, 0xf0, 0x37, 0x98, 0x3f, 0xf3, 0x04, 0xb5, 0x3f, 0xfd, 0x44, 0xd7, 0x3f, + 0x0f, 0x00, 0x3e, 0x03, 0xaf, 0xaf, 0xaf, 0xaf, 0x0f, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x29, 0x00, + 0x66, 0x80, 0xbc, 0xac, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, 0x80, 0xbc, 0xac, + 0x83, 0x01, 0x01, 0x00, 0xf0, 0x2e, 0x00, 0x10, 0x60, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, + 0xca, 0x29, 0x00, 0x10, 0x00, 0x2f, 0x00, 0x10, 0x70, 0x00, 0x00, 0x20, 0xe0, 0x06, 0x00, 0x00, + 0xda, 0x29, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x03, 0x01, 0xfe, 0x2b, 0x05, 0x1c, 0xc2, +}; \ No newline at end of file diff --git a/lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/ens160flash.ino b/lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/ens160flash.ino new file mode 100644 index 000000000..05ba85613 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/examples/ens160flash/ens160flash.ino @@ -0,0 +1,75 @@ +/*************************************************************************** + This is a example for ENS160 flash programming + + Written by Christoph Friese for Sciosense / 8-April-2020 + ***************************************************************************/ + +#include +int ArduinoLED = 13; + +//------------------------------------------------------------- +//ENS160 related items +//------------------------------------------------------------- +#include "ScioSense_ENS160.h" // ENS160 library +ScioSense_ENS160 ens160(ENS160_I2CADDR_0); +//sciosense_ENS160 ens160(ENS160_I2CADDR_1); + +#include "clare_fw_app_production_v2.3.1.h" + +/*-------------------------------------------------------------------------- + SETUP function + initiate sensor + --------------------------------------------------------------------------*/ +void setup() { + bool ok; + + //------------------------------------------------------------- + // General setup steps + //------------------------------------------------------------- + + Serial.begin(115200); + + while (!Serial) {} + + //Switch on LED for init + pinMode(ArduinoLED, OUTPUT); + digitalWrite(ArduinoLED, LOW); + + Serial.println("ENS160 flash example"); + delay(1000); + + + //------------------------------------------------------------- + //ENS160 related items + //------------------------------------------------------------- + Serial.print("Init "); + ok = ens160.begin(1,1); + Serial.println(); + + if (ens160.available()) { + // Print ENS160 version + Serial.print("Current rev: "); Serial.print(ens160.getMajorRev()); + Serial.print("."); Serial.print(ens160.getMinorRev()); + Serial.print("."); Serial.println(ens160.getBuild()); + + ok = ens160.flash(image_data, sizeof(image_data)); + + if (ok) { + // Print ENS160 version + Serial.print("Updated rev: "); Serial.print(ens160.getMajorRev()); + Serial.print("."); Serial.print(ens160.getMinorRev()); + Serial.print("."); Serial.println(ens160.getBuild()); + } else { + Serial.println("--- FAILED ---"); + } + } +} + +/*-------------------------------------------------------------------------- + MAIN LOOP FUNCTION + Cylce every 1000ms and perform action + --------------------------------------------------------------------------*/ + +void loop() { + +} diff --git a/lib/lib_i2c/ScioSense_ENS160/keywords.txt b/lib/lib_i2c/ScioSense_ENS160/keywords.txt new file mode 100644 index 000000000..406f08a00 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/keywords.txt @@ -0,0 +1,60 @@ +####################################### +# Syntax Coloring Map +####################################### +# https://spencer.bliven.us/index.php/2012/01/18/arduino-ide-keywords/ +# KEYWORD1 Classes, datatypes, and C++ keywords +# KEYWORD2 Methods and functions +# KEYWORD3 setup and loop functions, as well as the Serial keywords +# LITERAL1 Constants +# LITERAL2 Built-in variables (unused by default) + + +####################################### +# Classes, datatypes (KEYWORD1) +####################################### +ENS160 KEYWORD1 +ens160 KEYWORD1 +sciosense_ens160 KEYWORD1 +SCIOSENSE_ENS160 KEYWORD1 +ScioSense_ens160 KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +available KEYWORD2 +setMode KEYWORD2 + +initCustomMode KEYWORD2 +addCustomStep KEYWORD2 + +measure KEYWORD2 +set_envdata210 KEYWORD2 +getMajorRev KEYWORD2 +getMinorRev KEYWORD2 +getBuild KEYWORD2 + +getIAQ KEYWORD2 +getTVOC KEYWORD2 +geteCO2 KEYWORD2 +getNO2 KEYWORD2 +getHP0 KEYWORD2 +getHP0BL KEYWORD2 +getHP1 KEYWORD2 +getHP1BL KEYWORD2 +getHP2 KEYWORD2 +getHP2BL KEYWORD2 +getHP3 KEYWORD2 +getHP3BL KEYWORD2 + +flash KEYWORD2 + +###################################### +# Constants (LITERAL1) +####################################### + +ENS160_I2CADDR_0 LITERAL1 +ENS160_I2CADDR_1 LITERAL1 +ENS160_OPMODE_IDLE LITERAL1 +ENS160_OPMODE_STD LITERAL1 +ENS160_OPMODE_CUSTOM LITERAL1 diff --git a/lib/lib_i2c/ScioSense_ENS160/library.properties b/lib/lib_i2c/ScioSense_ENS160/library.properties new file mode 100644 index 000000000..a136ed198 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/library.properties @@ -0,0 +1,9 @@ +name=ScioSense ENS160 +version=1.0.0 +author=Christoph Friese +maintainer=Christoph Friese +sentence=Arduino library for the ENS160 digital four channel MOX gas sensor with I2C interface from ams +paragraph=This library controls the ENS160. The main feature of this library is performing a single shot measurement, retrieving the measurement data. +category=Device Control +url=https://github.com/sciosense/ens160 +architectures=* diff --git a/lib/lib_i2c/ScioSense_ENS160/src/ScioSense_ENS160.cpp b/lib/lib_i2c/ScioSense_ENS160/src/ScioSense_ENS160.cpp new file mode 100644 index 000000000..5eccf52b2 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS160/src/ScioSense_ENS160.cpp @@ -0,0 +1,547 @@ +/* + ScioSense_ENS160.h - Library for the ENS160 sensor with I2C interface from ScioSense + 2020 Apr 06 v3 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams + 2020 Feb 15 v2 Giuseppe Pasetti Corrected firmware flash option + 2019 May 05 v1 Christoph Friese Created + based on application note "ENS160 Software Integration.pdf" rev 0.01 +*/ + +#include "ScioSense_ENS160.h" +#include "math.h" + +ScioSense_ENS160::ScioSense_ENS160(uint8_t slaveaddr) { + this->_slaveaddr = slaveaddr; + + this->_ADDR = -1; + this->_nINT = -1; + this->_nCS = -1; +} + +ScioSense_ENS160::ScioSense_ENS160(uint8_t ADDR, uint8_t nCS, uint8_t nINT) { + this->_slaveaddr = ENS160_I2CADDR_0; + + this->_ADDR = ADDR; + this->_nINT = nINT; + this->_nCS = nCS; +} + +ScioSense_ENS160::ScioSense_ENS160(uint8_t slaveaddr, uint8_t ADDR, uint8_t nCS, uint8_t nINT) { + this->_slaveaddr = slaveaddr; + + this->_ADDR = ADDR; + this->_nINT = nINT; + this->_nCS = nCS; +} + +// Init I2C communication, resets ENS160 and checks its PART_ID. Returns false on I2C problems or wrong PART_ID. +bool ScioSense_ENS160::begin(bool debug, bool bootloader) +{ + bool result; + //uint16_t partid; + uint8_t i2cbuf[2]; + + debugENS160 = debug; + + //Set pin levels + if (this->_ADDR > -1) { + pinMode(this->_ADDR, OUTPUT); + digitalWrite(this->_ADDR, LOW); + } + if (this->_nINT > -1) pinMode(this->_nINT, INPUT_PULLUP); + if (this->_nCS > -1) { + pinMode(this->_nCS, OUTPUT); + digitalWrite(this->_nCS, HIGH); + } + + //init I2C + _i2c_init(); + if (debugENS160) { + Serial.println("begin() - I2C init done"); + } + delay(ENS160_BOOTING); // Wait to boot after reset + + this->_available = false; + result = this->reset(); + + this->_available = this->checkPartID(); + + if (this->_available) { + //sciosenseEither select bootloader or idle mode + if (bootloader) { + result = this->setMode(ENS160_OPMODE_BOOTLOADER); + } else { + result = this->setMode(ENS160_OPMODE_IDLE); + } + + result = this->clearCommand(); + result = this->getFirmware(); + } + if (debugENS160) { + if (bootloader) { + Serial.println("ENS160 in bootloader mode"); + } else { + Serial.println("ENS160 in idle mode"); + } + } + return this->_available; +} + + +// Sends a reset to the ENS160. Returns false on I2C problems. +bool ScioSense_ENS160::reset(void) +{ + uint8_t result = this->write8(_slaveaddr, ENS160_REG_OPMODE, ENS160_OPMODE_RESET); + + if (debugENS160) { + Serial.print("reset() result: "); + Serial.println(result == 0 ? "ok" : "nok"); + } + delay(ENS160_BOOTING); // Wait to boot after reset + + return result == 0; +} + +//Reads the part ID and confirms valid sensor +bool ScioSense_ENS160::checkPartID(void) { + uint8_t i2cbuf[2]; + uint16_t part_id; + + uint8_t result = this->read(_slaveaddr, ENS160_REG_PART_ID, i2cbuf, 2); + part_id = i2cbuf[1] | ((uint16_t)i2cbuf[0] << 8); + + if (debugENS160) { + Serial.print("checkPartID() result: "); + Serial.println(part_id == ENS160_PARTID ? "ok" : "nok"); + } + delay(ENS160_BOOTING); // Wait to boot after reset + + return part_id == ENS160_PARTID; +} + +//Initialize idle mode and confirms +bool ScioSense_ENS160::clearCommand(void) { + uint8_t status; + uint8_t result; + + result = this->write8(_slaveaddr, ENS160_REG_COMMAND, ENS160_COMMAND_NOP); + result = this->write8(_slaveaddr, ENS160_REG_COMMAND, ENS160_COMMAND_CLRGPR); + if (debugENS160) { + Serial.print("clearCommand() result: "); + Serial.println(result == 0 ? "ok" : "nok"); + } + delay(ENS160_BOOTING); // Wait to boot after reset + + status = this->read8(_slaveaddr, ENS160_REG_DATA_STATUS); + if (debugENS160) { + Serial.print("clearCommand() status: 0x"); + Serial.println(status, HEX); + } + delay(ENS160_BOOTING); // Wait to boot after reset + + return result == 0; +} + +bool ScioSense_ENS160::getFirmware() { + uint8_t i2cbuf[3]; + uint8_t result; + + this->clearCommand(); + + delay(ENS160_BOOTING); // Wait to boot after reset + + result = this->write8(_slaveaddr, ENS160_REG_COMMAND, ENS160_COMMAND_GET_APPVER); + result = this->read(_slaveaddr, ENS160_REG_GPR_READ_4, i2cbuf, 3); + + this->_fw_ver_major = i2cbuf[0]; + this->_fw_ver_minor = i2cbuf[1]; + this->_fw_ver_build = i2cbuf[2]; + + if (debugENS160) { + Serial.println(this->_fw_ver_major); + Serial.println(this->_fw_ver_minor); + Serial.println(this->_fw_ver_build); + Serial.print("getFirmware() result: "); + Serial.println(result == 0 ? "ok" : "nok"); + } + delay(ENS160_BOOTING); // Wait to boot after reset + + return result == 0; +} + +bool ScioSense_ENS160::setMode(uint8_t mode) { + uint8_t result; + + result = this->write8(_slaveaddr, ENS160_REG_OPMODE, mode); + + if (debugENS160) { + Serial.print("setMode() activate result: "); + Serial.println(result == 0 ? "ok" : "nok"); + } + + delay(ENS160_BOOTING); // Wait to boot after reset + + return result == 0; +} + + +// Define custom mode with number of steps +bool ScioSense_ENS160::initCustomMode(uint16_t stepNum) { + uint8_t result; + + if (stepNum > 0) { + this->_stepCount = stepNum; + + result = this->setMode(ENS160_OPMODE_IDLE); + result = this->clearCommand(); + + result = this->write8(_slaveaddr, ENS160_REG_COMMAND, ENS160_COMMAND_SETSEQ); + } else { + result = 1; + } + delay(ENS160_BOOTING); // Wait to boot after reset + + return result == 0; +} + +// Add custom mode step with definition of temperatures, duration and measurement +bool ScioSense_ENS160::addCustomStep(uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3) { + uint8_t result; + uint8_t seq_ack; + uint8_t temp; + + if (debugENS160) { + Serial.print("setCustomMode() write step "); + Serial.println(this->_stepCount); + } + delay(ENS160_BOOTING); // Wait to boot after reset + + temp = (uint8_t)((time / 24) << 6); + if (measureHP0) temp = temp | 0x20; + if (measureHP1) temp = temp | 0x10; + if (measureHP2) temp = temp | 0x8; + if (measureHP3) temp = temp | 0x4; + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_0, temp); + + temp = (uint8_t)((time / 24) >> 2); + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_1, temp); + + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_2, (uint8_t)(tempHP0/2)); + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_3, (uint8_t)(tempHP1/2)); + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_4, (uint8_t)(tempHP2/2)); + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_5, (uint8_t)(tempHP3/2)); + + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_6, (uint8_t)(this->_stepCount - 1)); + + if (this->_stepCount == 0) { + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_7, 0); + } else { + result = this->write8(_slaveaddr, ENS160_REG_GPR_WRITE_7, 128); + } + delay(ENS160_BOOTING); + + seq_ack = this->read8(_slaveaddr, ENS160_REG_GPR_READ_7); + delay(ENS160_BOOTING); // Wait to boot after reset + + if ((ENS160_SEQ_ACK_COMPLETE | this->_stepCount) != seq_ack) { + this->_stepCount = this->_stepCount - 1; + return 0; + } else { + return 1; + } + +} + +// Performs one single shot temperature and relative humidity measurement. +bool ScioSense_ENS160::measure(bool waitForNew) +{ + bool ok; + uint8_t i2cbuf[8]; + uint8_t status; + uint8_t result; + + // Set default status for early bail out + if (debugENS160) Serial.println("Start measurement"); + + // Either wait that new data is available (might take up to 1sec) or proceed even with old data + if (waitForNew) { + do { + delay(ENS160_BOOTING); + status = this->read8(_slaveaddr, ENS160_REG_DATA_STATUS); + + if (debugENS160) { + Serial.print("Status: "); + Serial.println(status); + } + + } while (!IS_NEW_DATA_AVAILABLE(status)); + } else { + status = this->read8(_slaveaddr, ENS160_REG_DATA_STATUS); + } + + // Read predictions + if (IS_NEWDAT(status)) { + result = this->read(_slaveaddr, ENS160_REG_DATA_AQI, i2cbuf, 7); + _data_tvoc = i2cbuf[1] | ((uint16_t)i2cbuf[2] << 8); + _data_eco2 = i2cbuf[3] | ((uint16_t)i2cbuf[4] << 8); + + } + + // Read raw resistance values + if (IS_NEWGPR(status)) { + result = this->read(_slaveaddr, ENS160_REG_GPR_READ_0, i2cbuf, 8); + _hp0_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8))); + _hp1_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[2] | ((uint16_t)i2cbuf[3] << 8))); + _hp2_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[4] | ((uint16_t)i2cbuf[5] << 8))); + _hp3_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[6] | ((uint16_t)i2cbuf[7] << 8))); + + } + + // Read baselines + if ((IS_NEWGPR(status)) or (IS_NEWDAT(status))) { + result = this->read(_slaveaddr, ENS160_REG_DATA_BL, i2cbuf, 8); + _hp0_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8))); + _hp1_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[2] | ((uint16_t)i2cbuf[3] << 8))); + _hp2_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[4] | ((uint16_t)i2cbuf[5] << 8))); + _hp3_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[6] | ((uint16_t)i2cbuf[7] << 8))); + + result = this->read(_slaveaddr, ENS160_REG_DATA_MISR, i2cbuf, 1); + _misr = i2cbuf[0]; + } + + return ok==0; +} + +// Writes t and h (in ENS210 format) to ENV_DATA. Returns false on I2C problems. +bool ScioSense_ENS160::set_envdata210(uint16_t t, uint16_t h) { + uint16_t trh; + uint8_t trh_in[4]; + + trh = (uint16_t)((t + 273.15f) * 64.0f); + trh_in[0] = trh & 0xff; + trh_in[1] = (trh >> 8) & 0xff; + + trh = (uint16_t)(h * 512.0f); + trh_in[2] = trh & 0xff; + trh_in[3] = (trh >> 8) & 0xff; + + uint8_t result = this->write(_slaveaddr, ENS160_REG_TEMP_IN, trh_in, 4); + + return result; +} + +// A helper function to read back and verify status of command +int ScioSense_ENS160::blCMDWriteVerify(uint8_t command) { + uint8_t status[2]; + + uint8_t result = this->write8(_slaveaddr, ENS160_REG_COMMAND, ENS160_COMMAND_NOP); + Serial.print("1. Write 0x");Serial.print(ENS160_COMMAND_NOP,HEX); + Serial.print(" with result 0x");Serial.println(result,HEX); + + result = this->write8(_slaveaddr, ENS160_REG_COMMAND, command); + Serial.print("2. Write 0x");Serial.print(command,HEX); + Serial.print(" with result 0x");Serial.println(result,HEX); + + do { + if (command == ENS160_BL_CMD_WRITE) delay(100); + else delay(2000); + result = this->read(_slaveaddr, ENS160_REG_DATA_STATUS, status, 1); + Serial.print("3. Read DATA_STATUS with 0x"); + Serial.print(status[0],HEX); + Serial.print("\t0x"); + Serial.println(status[0] & ENS160_DATA_STATUS_NEWGPR); + } while (!(status[0] & ENS160_DATA_STATUS_NEWGPR)); + + result = this->read(_slaveaddr, ENS160_REG_GPR_READ_6, status, 2); + Serial.print("4. Read GPR_READ_6 with 0x"); + Serial.print(status[0],HEX); + Serial.print("\t0x"); + Serial.println(status[1],HEX); + + if (status[1] != command + 1) { + // status[0] is the MSB 8bit of AMS_ERR_BL_XXX error code + // documented in the ‘ENS160 Bootloader User Guide’. + return status[0]; + } + return 0; +} + +// Flashes the firmware of the ENS160 with size bytes from image - image _must_ be in PROGMEM +/*bool ScioSense_ENS160::flash(const uint8_t * app_img, int size) { + int error = 0; + int idx = 0; + uint8_t result = this->write8(_slaveaddr,ENS160_REG_OPMODE,ENS160_OPMODE_BOOTLOADER); + delay(ENS160_BOOTING); // Wait to boot after reset + // Write magic word and start bootloader + result = this->write(_slaveaddr, ENS160_REG_GPR_WRITE_0, ENS160_BL_MAGIC, 4); + error = blCMDWriteVerify(ENS160_BL_CMD_START); + if (error) { + Serial.print("Write failed ENS160_BL_CMD_START. Error code: "); + Serial.println(error); + return false; + } else { + Serial.print("Write success ENS160_BL_CMD_START."); + } + + // Erase stored baseline + error = blCMDWriteVerify(ENS160_BL_CMD_ERASE_BLINE); + if (error) { + Serial.print("Write failed ENS160_BL_CMD_ERASE_BLINE. Error code: "); + Serial.println(error); + return false; + } else { + Serial.print("Write success ENS160_BL_CMD_ERASE_BLINE."); + } + + // Erase application FLASH memory + error = blCMDWriteVerify(ENS160_BL_CMD_ERASE_APP); + if (error) { + Serial.print("Write failed ENS160_BL_CMD_ERASE_APP. Error code: "); + Serial.println(error); + return false; + } else { + Serial.print("Write success ENS160_BL_CMD_ERASE_APP."); + } + + // Write application binary in pieces of 8 bytes + uint8_t len = 0; + for(idx = 0; idx < size; idx+=8) { + int len = (size - idx) < 8 ? (size - idx) : 8; + Serial.println(size); + Serial.println(len); + Serial.println(idx); + uint8_t ram[8]; + memcpy_P(ram, app_img, len); // Copy up to 8 bytes from PROGMEM to RAM + + result = this->write(_slaveaddr, ENS160_REG_GPR_WRITE_0, ram, len); + + error = blCMDWriteVerify(ENS160_BL_CMD_WRITE); + if (error) { + Serial.print("Write failed ENS160_BL_CMD_WRITE. Error code: "); + Serial.println(error); + return false; + } + app_img += len; + } + + // idx should match sizeof(app_img); + if(idx != size) { + Serial.println("Failed to complete application image update."); + return false; + } else { + Serial.println("Write success of complete application image."); + } + + // Verify application FLASH memory + error = blCMDWriteVerify(ENS160_BL_CMD_VERIFY); + if (error) { + Serial.print("Write failed ENS160_BL_CMD_VERIFY. Error code: "); + Serial.println(error); + return false; + } else { + Serial.print("Write success ENS160_BL_CMD_VERIFY."); + } + + // Verify application FLASH memory + error = blCMDWriteVerify(ENS160_BL_CMD_EXITBL); + if (error) { + Serial.print("Write failed ENS160_BL_CMD_EXITBL. Error code: "); + Serial.println(error); + return false; + } else { + Serial.print("Write success ENS160_BL_CMD_EXITBL."); + } + + this->reset(); + + result = this->clearCommand(); + + result = this->getFirmware(); + + return true; + +} + +*/ +/****************************************************************************/ +/* General functions */ +/****************************************************************************/ + +void ScioSense_ENS160::_i2c_init() +{ + Wire.begin(); +} + +/**************************************************************************/ + +uint8_t ScioSense_ENS160::read8(uint8_t addr, byte reg) +{ + uint8_t ret; + this->read(addr, reg, &ret, 1); + + return ret; +} + +uint8_t ScioSense_ENS160::read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num) +{ + uint8_t pos = 0; + uint8_t result = 0; + + if (debugENS160) { + Serial.print("I2C read address: 0x"); + Serial.print(addr, HEX); + Serial.print(" - register: 0x"); + Serial.println(reg, HEX); + } + + //on arduino we need to read in 32 byte chunks + while(pos < num){ + + uint8_t read_now = min((uint8_t)32, (uint8_t)(num - pos)); + Wire.beginTransmission((uint8_t)addr); + + Wire.write((uint8_t)reg + pos); + result = Wire.endTransmission(); + Wire.requestFrom((uint8_t)addr, read_now); + + for(int i=0; iwrite(addr, reg, &value, 1); + return result; +} + +uint8_t ScioSense_ENS160::write(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num) +{ + if (debugENS160) { + Serial.print("I2C write address: 0x"); + Serial.print(addr, HEX); + Serial.print(" - register: 0x"); + Serial.print(reg, HEX); + Serial.print(" - value:"); + for (int i = 0; i= 100) + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +// Chip constants +#define ENS160_PARTID 0x6001 +#define ENS160_BOOTING 50 + +// 7-bit I2C slave address of the ENS160 +#define ENS160_I2CADDR_0 0x52 //ADDR low +#define ENS160_I2CADDR_1 0x53 //ADDR high + +// ENS160 registers for version V0 +#define ENS160_REG_PART_ID 0x00 // 2 byte register +#define ENS160_REG_OPMODE 0x10 +#define ENS160_REG_CONFIG 0x11 +#define ENS160_REG_COMMAND 0x12 +#define ENS160_REG_TEMP_IN 0x13 +#define ENS160_REG_RH_IN 0x15 +#define ENS160_REG_DATA_STATUS 0x20 +#define ENS160_REG_DATA_AQI 0x21 +#define ENS160_REG_DATA_TVOC 0x22 +#define ENS160_REG_DATA_ECO2 0x24 +#define ENS160_REG_DATA_BL 0x28 +#define ENS160_REG_DATA_T 0x30 +#define ENS160_REG_DATA_RH 0x32 +#define ENS160_REG_DATA_MISR 0x38 +#define ENS160_REG_GPR_WRITE_0 0x40 +#define ENS160_REG_GPR_WRITE_1 ENS160_REG_GPR_WRITE_0 + 1 +#define ENS160_REG_GPR_WRITE_2 ENS160_REG_GPR_WRITE_0 + 2 +#define ENS160_REG_GPR_WRITE_3 ENS160_REG_GPR_WRITE_0 + 3 +#define ENS160_REG_GPR_WRITE_4 ENS160_REG_GPR_WRITE_0 + 4 +#define ENS160_REG_GPR_WRITE_5 ENS160_REG_GPR_WRITE_0 + 5 +#define ENS160_REG_GPR_WRITE_6 ENS160_REG_GPR_WRITE_0 + 6 +#define ENS160_REG_GPR_WRITE_7 ENS160_REG_GPR_WRITE_0 + 7 +#define ENS160_REG_GPR_READ_0 0x48 +#define ENS160_REG_GPR_READ_4 ENS160_REG_GPR_READ_0 + 4 +#define ENS160_REG_GPR_READ_6 ENS160_REG_GPR_READ_0 + 6 +#define ENS160_REG_GPR_READ_7 ENS160_REG_GPR_READ_0 + 7 + +//ENS160 data register fields +#define ENS160_COMMAND_NOP 0x00 +#define ENS160_COMMAND_CLRGPR 0xCC +#define ENS160_COMMAND_GET_APPVER 0x0E +#define ENS160_COMMAND_SETTH 0x02 +#define ENS160_COMMAND_SETSEQ 0xC2 + +#define ENS160_OPMODE_RESET 0xF0 +#define ENS160_OPMODE_DEP_SLEEP 0x00 +#define ENS160_OPMODE_IDLE 0x01 +#define ENS160_OPMODE_STD 0x02 +#define ENS160_OPMODE_INTERMEDIATE 0x03 +#define ENS160_OPMODE_CUSTOM 0xC0 +#define ENS160_OPMODE_D0 0xD0 +#define ENS160_OPMODE_D1 0xD1 +#define ENS160_OPMODE_BOOTLOADER 0xB0 + +#define ENS160_BL_CMD_START 0x02 +#define ENS160_BL_CMD_ERASE_APP 0x04 +#define ENS160_BL_CMD_ERASE_BLINE 0x06 +#define ENS160_BL_CMD_WRITE 0x08 +#define ENS160_BL_CMD_VERIFY 0x0A +#define ENS160_BL_CMD_GET_BLVER 0x0C +#define ENS160_BL_CMD_GET_APPVER 0x0E +#define ENS160_BL_CMD_EXITBL 0x12 + +#define ENS160_SEQ_ACK_NOTCOMPLETE 0x80 +#define ENS160_SEQ_ACK_COMPLETE 0xC0 + +#define IS_ENS160_SEQ_ACK_NOT_COMPLETE(x) (ENS160_SEQ_ACK_NOTCOMPLETE == (ENS160_SEQ_ACK_NOTCOMPLETE & (x))) +#define IS_ENS160_SEQ_ACK_COMPLETE(x) (ENS160_SEQ_ACK_COMPLETE == (ENS160_SEQ_ACK_COMPLETE & (x))) + +#define ENS160_DATA_STATUS_NEWDAT 0x02 +#define ENS160_DATA_STATUS_NEWGPR 0x01 + +#define IS_NEWDAT(x) (ENS160_DATA_STATUS_NEWDAT == (ENS160_DATA_STATUS_NEWDAT & (x))) +#define IS_NEWGPR(x) (ENS160_DATA_STATUS_NEWGPR == (ENS160_DATA_STATUS_NEWGPR & (x))) +#define IS_NEW_DATA_AVAILABLE(x) (0 != ((ENS160_DATA_STATUS_NEWDAT | ENS160_DATA_STATUS_NEWGPR ) & (x))) + +#define CONVERT_RS_RAW2OHMS_I(x) (1 << ((x) >> 11)) +#define CONVERT_RS_RAW2OHMS_F(x) (pow (2, (float)(x) / 2048)) + +static uint8_t ENS160_BL_MAGIC[4] = {0x53, 0xCE, 0x1A, 0xBF}; + +class ScioSense_ENS160 { + + public: + ScioSense_ENS160(uint8_t slaveaddr = ENS160_I2CADDR_0); // Constructor using slave address (5A or 5B) + ScioSense_ENS160(uint8_t ADDR, uint8_t nCS, uint8_t nINT); // Constructor with pin definition + ScioSense_ENS160(uint8_t slaveaddr, uint8_t ADDR, uint8_t nCS, uint8_t nINT); // Constructor with slave address and pin definition + + bool begin(bool debug=false, bool bootloader=false); // init i2c interface, get partID und uID. Returns false on I2C problems or wrong PART_ID. + bool available() { return this->_available; } + + bool setMode(uint8_t mode); + + bool initCustomMode(uint16_t stepNum); + bool addCustomStep(uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3); + + + bool measure(bool waitForNew = true); // perfrom measurement and stores result in internal variables + bool set_envdata210(uint16_t t, uint16_t h); // Writes t and h (in ENS210 format) to ENV_DATA. Returns false on I2C problems. + uint8_t getMajorRev() {return this->_fw_ver_major; } + uint8_t getMinorRev() {return this->_fw_ver_minor; } + uint8_t getBuild() {return this->_fw_ver_build; } + + uint8_t getAQI() {return this->_data_aqi; } + uint16_t getTVOC() {return this->_data_tvoc; } + uint16_t geteCO2() {return this->_data_eco2; } + uint32_t getHP0() {return this->_hp0_rs; } + uint32_t getHP1() {return this->_hp1_rs; } + uint32_t getHP2() {return this->_hp2_rs; } + uint32_t getHP3() {return this->_hp3_rs; } + uint32_t getHP0BL() {return this->_hp0_bl; } + uint32_t getHP1BL() {return this->_hp1_bl; } + uint32_t getHP2BL() {return this->_hp2_bl; } + uint32_t getHP3BL() {return this->_hp3_bl; } + uint8_t getMISR() {return this->_misr; } + +// bool flash(const uint8_t * app_img, int size); // Flashes the firmware of the CCS811 with size bytes from image - image _must_ be in PROGMEM + + private: + uint8_t _ADDR; + uint8_t _nINT; + uint8_t _nCS; + bool debugENS160 = false; + + bool reset(void); // Sends a reset to the ENS160. Returns false on I2C problems. + bool checkPartID(); + bool clearCommand(void); + bool getFirmware(); + + int blCMDWriteVerify(uint8_t command); + + + bool _available = false; // ENS160 available + + uint8_t _fw_ver_major; + uint8_t _fw_ver_minor; + uint8_t _fw_ver_build; + + uint16_t _stepCount; // Counter for custom sequence + + uint8_t _data_aqi; + uint16_t _data_tvoc; + uint16_t _data_eco2; + uint32_t _hp0_rs; + uint32_t _hp0_bl; + uint32_t _hp1_rs; + uint32_t _hp1_bl; + uint32_t _hp2_rs; + uint32_t _hp2_bl; + uint32_t _hp3_rs; + uint32_t _hp3_bl; + uint16_t _temp; + int _slaveaddr; // Slave address of the ENS160 + uint8_t _misr; + + + //Isotherm, HP0 252°C / HP1 350°C / HP2 250°C / HP3 324°C / measure every 1008ms + uint8_t _seq_steps[1][8] = { + { 0x7C, 0x0A, 0x7E, 0xAF, 0xAF, 0xA2, 0x00, 0x80 }, + }; + + +/****************************************************************************/ +/* General functions */ +/****************************************************************************/ + void _i2c_init(); + + uint8_t read8(uint8_t addr, byte reg); + uint8_t read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num); + + uint8_t write8(uint8_t addr, byte reg, byte value); + uint8_t write(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num); + +}; + + +#endif diff --git a/lib/lib_i2c/ScioSense_ENS210/LICENSE b/lib/lib_i2c/ScioSense_ENS210/LICENSE new file mode 100644 index 000000000..dbc30683e --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS210/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Sciosense + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/lib_i2c/ScioSense_ENS210/README.md b/lib/lib_i2c/ScioSense_ENS210/README.md new file mode 100644 index 000000000..099ed079c --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS210/README.md @@ -0,0 +1,41 @@ +# ScioSense ENS210 +Arduino library for the ENS210 temperature & humidity sensor with I2C interface from ScioSense +It is based on a library written by Maarten Pennings. Thanks for all the work. +https://github.com/maarten-pennings/ENS210 + +## Introduction +This project is an Arduino *library*. It implements a driver with examples for the ENS210. The ENS210 chip is a digital temperature & humidity sensor with an I2C interface. + +The driver in this Arduino library is based on the code supplied by *Sciosense*, the manufacturer of the chip. + +Note that the ENS210 requires a supply voltage of 1.71V .. 1.98V. + +## Links +The ENS210 is made by [Sciosense](http://www.sciosense.com). + - The datasheet and further documents regading the ENS210 can be downloaded here + https://www.sciosense.com/products/relative-humidity-and-temperature-sensors/ens210-relative-humidity-and-temperature-sensor/ + +## Prerequisites +It is assumed that + - The Arduino IDE has been installed. + If not, refer to "Install the Arduino Desktop IDE" on the + [Arduino site](https://www.arduino.cc/en/Guide/HomePage). + - The library directory is at its default location. + For me, that is `C:\Users\sciosense\Documents\Arduino\libraries`. + +## Installation +Installation steps +- Visit the project page for the Arduino CCS811 library. +- Click the green button Clone or download on the right side. +- From the pop-up choose Download ZIP. +- In Arduino IDE, select Sketch > Include Library > Manage Libraries ... and browse to the just downloaded ZIP file. +- When the IDE is ready this README.md should be located at e.g. `C:\Users\sciosense\Documents\Arduino\libraries\sciosense_ens210\README.md`. + +## Build an example +To build an example sketch + - (Re)start Arduino. + - Open File > Example > Examples from Custom Libraries > ENS210 > ENS210basic. + - Make sure Tools > Board lists the correct board. + - Select Sketch > Verify/Compile. + +### ScioSense is a Joint Venture of ams AG diff --git a/lib/lib_i2c/ScioSense_ENS210/examples/ens210basic/ens210basic.ino b/lib/lib_i2c/ScioSense_ENS210/examples/ens210basic/ens210basic.ino new file mode 100644 index 000000000..c0d4cc168 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS210/examples/ens210basic/ens210basic.ino @@ -0,0 +1,71 @@ +/*************************************************************************** + This is a example for ENS210 basic reading + + Written by Christoph Friese for Sciosense / 8-April-2020 + ***************************************************************************/ + +#include +#define ArduinoIDE true +int ArduinoLED = 13; + +//------------------------------------------------------------- +//ENS210 related items +//------------------------------------------------------------- +#include "ScioSense_ENS210.h" +ScioSense_ENS210 ens210; + +/*-------------------------------------------------------------------------- + SETUP function + initiate sensor + --------------------------------------------------------------------------*/ +void setup() { + bool ok; + + //------------------------------------------------------------- + // General setup steps + //------------------------------------------------------------- + + Serial.begin(9600); + + while (!Serial) {} + + //Switch on LED for init + pinMode(ArduinoLED, OUTPUT); + digitalWrite(ArduinoLED, LOW); + + if (ArduinoIDE) { + Serial.println("ENS210 example"); + delay(1000); + } + + if (ArduinoIDE) Serial.print("ENS210..."); + ok = ens210.begin(); + if (ArduinoIDE) Serial.println(ens210.available() ? "done." : "failed!"); + ens210.setSingleMode(false); + + //blink LED + digitalWrite(ArduinoLED, HIGH); + delay(100); + digitalWrite(ArduinoLED, LOW); + +} + +/*-------------------------------------------------------------------------- + MAIN LOOP FUNCTION + Cylce every 1000ms and perform action + --------------------------------------------------------------------------*/ + +void loop() { + + if (ens210.available()) ens210.measure(); + + if (ArduinoIDE) { + Serial.print("Temperature: ");Serial.print(ens210.getTempCelsius());Serial.print("°C\t"); + Serial.print("Humidity: "); Serial.print(ens210.getHumidityPercent());Serial.println("%"); + } else { + Serial.print(ens210.getTempCelsius());Serial.print(","); + Serial.print(ens210.getHumidityPercent());Serial.println(""); + } + + delay(1000); +} diff --git a/lib/lib_i2c/ScioSense_ENS210/keywords.txt b/lib/lib_i2c/ScioSense_ENS210/keywords.txt new file mode 100644 index 000000000..5b3bb0e54 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS210/keywords.txt @@ -0,0 +1,47 @@ +####################################### +# Syntax Coloring Map +####################################### +# https://spencer.bliven.us/index.php/2012/01/18/arduino-ide-keywords/ +# KEYWORD1 Classes, datatypes, and C++ keywords +# KEYWORD2 Methods and functions +# KEYWORD3 setup and loop functions, as well as the Serial keywords +# LITERAL1 Constants +# LITERAL2 Built-in variables (unused by default) + + +####################################### +# Classes, datatypes (KEYWORD1) +####################################### +ENS210 KEYWORD1 +ens210 KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +setSingleMode KEYWORD2 +available KEYWORD2 +getPartID KEYWORD2 +getHighUID KEYWORD2 +measure KEYWORD2 +getTempKelvin KEYWORD2 +getTempCelsius KEYWORD2 +getTempFahrenheit KEYWORD2 +getHumidityPercent KEYWORD2 +getAbsoluteHumidityPercent KEYWORD2 +getStatusT KEYWORD2 +getDataT KEYWORD2 +getStatusH KEYWORD2 +getDataH KEYWORD2 +status_str KEYWORD2 +correction_set KEYWORD2 +correction_get KEYWORD2 + +###################################### +# Constants (LITERAL1) +####################################### + +ENS210_STATUS_I2CERROR LITERAL1 +ENS210_STATUS_CRCERROR LITERAL1 +ENS210_STATUS_INVALID LITERAL1 +ENS210_STATUS_OK LITERAL1 diff --git a/lib/lib_i2c/ScioSense_ENS210/library.properties b/lib/lib_i2c/ScioSense_ENS210/library.properties new file mode 100644 index 000000000..0a9f30ed6 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS210/library.properties @@ -0,0 +1,9 @@ +name=ScioSense ENS210 +version=3.0.0 +author=Christoph Friese +maintainer=Christoph Friese +sentence=Arduino library for the ENS210 digital temperature & humidity sensor with I2C interface from ScioSense +paragraph=This library controls the ENS210. The main feature of this library is performing a single shot measurement, retrieving the measurement data. +category=Device Control +url=https://github.com/sciosense/ens210 +architectures=* diff --git a/lib/lib_i2c/ScioSense_ENS210/src/ScioSense_ENS210.cpp b/lib/lib_i2c/ScioSense_ENS210/src/ScioSense_ENS210.cpp new file mode 100644 index 000000000..ed309d315 --- /dev/null +++ b/lib/lib_i2c/ScioSense_ENS210/src/ScioSense_ENS210.cpp @@ -0,0 +1,447 @@ +/* + ScioSense_ENS210.h - Library for the ENS210 relative humidity and temperature sensor with I2C interface from ScioSense + 2020 Apr 06 v3 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams + 2018 Aug 28 v2 Christoph Friese Adjusted I2C communication + 2017 Aug 01 v1 Maarten Pennings Created +*/ + +#include "ScioSense_ENS210.h" +#include + +// Compute the CRC-7 of 'val' (should only have 17 bits) +// https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Computation +static uint32_t crc7( uint32_t val ) +{ + // Setup polynomial + uint32_t pol= CRC7POLY; + // Align polynomial with data + pol = pol << (DATA7WIDTH-CRC7WIDTH-1); + // Loop variable (indicates which bit to test, start with highest) + uint32_t bit = DATA7MSB; + // Make room for CRC value + val = val << CRC7WIDTH; + bit = bit << CRC7WIDTH; + pol = pol << CRC7WIDTH; + // Insert initial vector + val |= CRC7IVEC; + // Apply division until all bits done + while( bit & (DATA7MASK<>= 1; + pol >>= 1; + } + return val; +} + +// Init I2C communication, resets ENS210 and checks its PART_ID. Returns false on I2C problems or wrong PART_ID. +// Stores solder correction. +bool ScioSense_ENS210::begin(bool debug) +{ + bool result; + + debugENS210 = debug; + + //init I2C + _i2c_init(); + if (debugENS210) { + Serial.println("ens210 debug - I2C init done"); + } + + // Record solder correction + this->_soldercorrection= 0; + this->_available = false; + this->_singleMode = true; + this->_t_data = -1; + this->_h_data = -1; + this->lowpower(false); + + result = getversion(); + + if(this->_partID == ENS210_PARTID ) { + this->_available = true; + } + return result; +} + + +// Sends a reset to the ENS210. Returns false on I2C problems. +bool ScioSense_ENS210::reset(void) +{ + uint8_t result = this->write8(_slaveaddress, ENS210_REG_SYS_CTRL, 0x80); + if (debugENS210) { + Serial.print("ens210 debug - reset: 0x"); + Serial.println(result,HEX); + } + delay(ENS210_BOOTING); // Wait to boot after reset + return result==0; +} + + +// Sets ENS210 to low (true) or high (false) power. Returns false on I2C problems. +bool ScioSense_ENS210::lowpower(bool enable) +{ + uint8_t power = enable ? 0x01: 0x00; + uint8_t result = this->write8(this->_slaveaddress, ENS210_REG_SYS_CTRL, power); + if (debugENS210) { + Serial.print("ens210 debug - lowpower: 0x"); + Serial.println(result,HEX); + } + delay(ENS210_BOOTING); // Wait boot-time after power switch + return result==0; +} + + +// Reads PART_ID and UID of ENS210. Returns false on I2C problems. +bool ScioSense_ENS210::getversion()//(uint16_t partid, uint64_t uid) +{ + bool ok; + uint8_t i2cbuf[8]; + uint8_t result; + + // Must disable low power to read PART_ID or UID + ok= lowpower(false); if(!ok) goto errorexit; + + // Read the PART_ID + result = this->read(this->_slaveaddress, ENS210_REG_PART_ID, i2cbuf, 2); + if (debugENS210) { + Serial.print("ens210 debug - PART_ID I2C result: 0x"); + Serial.println(result, HEX); + } + //this->_partID = (uint16_t)(i2cbuf[1]*256U + i2cbuf[0]*1U); + this->_partID = (uint16_t)(((uint16_t)i2cbuf[1] << 8) | ((uint16_t)i2cbuf[0])); + if (debugENS210) { + Serial.print("PART_ID: 0x"); + Serial.println(this->_partID,HEX); + } + + // Read the UID + result = this->read(_slaveaddress, ENS210_REG_UID,i2cbuf,8); + if (debugENS210) { + Serial.print("ens210 debug - UID 0x"); + Serial.println(result,HEX); + } + this->_uID = (uint64_t)((uint64_t)i2cbuf[7]<<56 | (uint64_t)i2cbuf[6]<<48 | (uint64_t)i2cbuf[5]<<40 | (uint64_t)i2cbuf[4]<<32 | (uint64_t)i2cbuf[3]<<24 | (uint64_t)i2cbuf[2]<<16 | (uint64_t)i2cbuf[1]<<8 | (uint64_t)i2cbuf[0]); + + //for( int i=0; i<8; i++) ((uint8_t*)this->_uID)[i]=i2cbuf[i]; //((uint8_t*)this->_uID)[i]=i2cbuf[i]; + this->_uIDhi = (uint32_t)(this->_uID >> 32); + this->_uIDlo = (uint32_t)(this->_uID & 0xFFFFFFFF); + + if (debugENS210) { + Serial.print("UID hi 0x"); + Serial.print(this->_uIDhi,HEX); + Serial.print(" - 0x"); + Serial.println(this->_uIDlo,HEX); + } + + // Go back to default power mode (low power enabled) + ok= lowpower(true); if(!ok) goto errorexit; + + // Success + return true; + + errorexit: + // Try to go back to default mode (low power enabled) + ok= lowpower(true); + + // Hopefully enabling low power was successful; but there was an error before that anyhow + return false; +} + +// Configures ENS210 measurement mode +// false for continuous mode / true for single shot measurement. Returns false on I2C problems. +bool ScioSense_ENS210::setSingleMode(bool enable) +{ + this->_singleMode = enable; + uint8_t mode = enable ? 0x00: 0x03; + uint8_t result = this->write8(_slaveaddress, ENS210_REG_SENS_RUN, mode); + if (debugENS210) { + Serial.print("ens210 debug - start mode 0x"); + Serial.print(mode,HEX); + Serial.print(" - result 0x"); + Serial.println(result,HEX); + } + return result==0; +} + +// Performs one single shot temperature and relative humidity measurement. +void ScioSense_ENS210::measure() //int * t_data, int * t_status, int * h_data, int * h_status ) +{ + bool ok; + // Set default status for early bail out + if (debugENS210) Serial.println("Start measurement"); + this->_t_status = ENS210_STATUS_I2CERROR; + this->_h_status = ENS210_STATUS_I2CERROR; + + // Start a single shot measurement + if (this->_singleMode) + { + uint8_t result = this->write8(_slaveaddress, ENS210_REG_SENS_RUN, 0x00); + if (debugENS210) { + Serial.print("ens210 debug - start single 0x"); + Serial.println(result,HEX); + } + } + + //Trigger measurement + uint8_t result = this->write8(_slaveaddress, ENS210_REG_SENS_START, 0x03); + if (debugENS210) { + Serial.print("ens210 debug - trigger measurement 0x"); + Serial.println(result,HEX); + } + + // Wait for measurement to complete + if (this->_singleMode) delay(ENS210_THCONV_SINGLE_MS); + else delay(ENS210_THCONV_CONT_MS); + + // Get the measurement data + if (debugENS210) Serial.println("Start measurement"); + ok = readValue(); if(!ok) return; + if (debugENS210) Serial.println("Measurement ok"); +} + +// Reads measurement data from the ENS210. Returns false on I2C problems. +bool ScioSense_ENS210::readValue() //uint32_t *t_val, uint32_t *h_val) +{ + uint8_t i2cbuf[6]; + uint8_t valid; + uint32_t crc; + uint32_t payload; + uint8_t crc_ok; + + // Read T_VAL and H_VAL + uint8_t result = this->read(_slaveaddress, ENS210_REG_T_VAL, i2cbuf, 6); + if (debugENS210) { + Serial.print("ens210 debug - readValue:"); + Serial.println(result); + Serial.print(i2cbuf[0],HEX); Serial.print("\t"); + Serial.print(i2cbuf[1],HEX); Serial.print("\t"); + Serial.print(i2cbuf[2],HEX); Serial.print("\t"); + Serial.print(i2cbuf[3],HEX); Serial.print("\t"); + Serial.print(i2cbuf[4],HEX); Serial.print("\t"); + Serial.print(i2cbuf[5],HEX); Serial.println("\t"); + } + // Retrieve and pack bytes into t_val and h_val + uint32_t t_val= (uint32_t)((uint32_t)i2cbuf[2]<<16 | (uint32_t)i2cbuf[1]<<8 | (uint32_t)i2cbuf[0]); + this->_t_data = (t_val>>0) & 0xffff; + valid = (t_val>>16) & 0x1; + crc = (t_val>>17) & 0x7f; + payload = (t_val>>0 ) & 0x1ffff; + crc_ok = crc7(payload)==crc; + if( !crc_ok ) this->_t_status = ENS210_STATUS_CRCERROR; + else if( !valid ) this->_t_status = ENS210_STATUS_INVALID; + else this->_t_status = ENS210_STATUS_OK; + if (debugENS210) { + Serial.print("_t_data 0x"); + Serial.print(t_val,HEX); + Serial.print(" - 0x"); + Serial.println(this->_t_data,HEX); + Serial.print("Valid: "); + Serial.print(valid); + Serial.print(" Status: "); + Serial.println(this->_t_status); + } + + uint32_t h_val= (uint32_t)((uint32_t)i2cbuf[5]<<16 | (uint32_t)i2cbuf[4]<<8 | (uint32_t)i2cbuf[3]); + this->_h_data = (h_val>>0) & 0xffff; + + valid = (h_val>>16) & 0x1; + crc = (h_val>>17) & 0x7f; + payload = (h_val>>0 ) & 0x1ffff; + crc_ok= crc7(payload)==crc; + if( !crc_ok ) this->_h_status= ENS210_STATUS_CRCERROR; + else if( !valid ) this->_h_status= ENS210_STATUS_INVALID; + else this->_h_status= ENS210_STATUS_OK; + if (debugENS210) { + Serial.print("_h_data 0x"); + Serial.print(h_val,HEX); + Serial.print(" - 0x"); + Serial.println(this->_h_data,HEX); + Serial.print("Valid: "); + Serial.print(valid); + Serial.print(" Status: "); + Serial.println(this->_h_status); + } + + // Success + return true; +} + + +// Converts a status (ENS210_STATUS_XXX) to a human readable string. +const char * ScioSense_ENS210::status_str( int status ) +{ + switch( status ) { + case ENS210_STATUS_I2CERROR : return "i2c-error"; + case ENS210_STATUS_CRCERROR : return "crc-error"; + case ENS210_STATUS_INVALID : return "data-invalid"; + case ENS210_STATUS_OK : return "ok"; + default : return "unknown-status"; + } +} + + +// Convert raw `t_data` temperature to Kelvin (also applies the solder correction). +// The output value is in Kelvin multiplied by parameter `multiplier`. +float ScioSense_ENS210::getTempKelvin() +{ + // Force 32 bits + float t = this->_t_data & 0xFFFF; + // Compensate for soldering effect + t-= _soldercorrection; + // Return m*K. This equals m*(t/64) = (m*t)/64 + // Note m is the multiplier, K is temperature in Kelvin, t is raw t_data value. + // Uses K=t/64. + return t/64; //IDIV(t,64); +} + +// Convert raw `t_data` temperature to Celsius (also applies the solder correction). +// The output value is in Celsius multiplied by parameter `multiplier`. +float ScioSense_ENS210::getTempCelsius() +{ + //assert( (1<=multiplier) && (multiplier<=1024) ); + // Force 32 bits + float t= this->_t_data & 0xFFFF; + // Compensate for soldering effect + t-= _soldercorrection; + // Return m*C. This equals m*(K-273.15) = m*K - 27315*m/100 = m*t/64 - 27315*m/100 + // Note m is the multiplier, C is temperature in Celsius, K is temperature in Kelvin, t is raw t_data value. + // Uses C=K-273.15 and K=t/64. + return t/64 - 27315L/100; //IDIV(t,64) - IDIV(27315L,100); +} + + +// Convert raw `t_data` temperature to Fahrenheit (also applies the solder correction). +float ScioSense_ENS210::getTempFahrenheit() +{ + float t= this->_t_data & 0xFFFF; + // Compensate for soldering effect + t-= _soldercorrection; + // Return m*F. This equals m*(1.8*(K-273.15)+32) = m*(1.8*K-273.15*1.8+32) = 1.8*m*K-459.67*m = 9*m*K/5 - 45967*m/100 = 9*m*t/320 - 45967*m/100 + // Note m is the multiplier, F is temperature in Fahrenheit, K is temperature in Kelvin, t is raw t_data value. + // Uses F=1.8*(K-273.15)+32 and K=t/64. + return 9*t/320 - 45967/100; //IDIV(9*t,320) - IDIV(45967L,100); + // The first multiplication stays below 32 bits (t:16, multiplier:11, 9:4) + // The second multiplication stays below 32 bits (multiplier:10, 45967:16) +} + + +// Convert raw `h_data` relative humidity to %RH. +float ScioSense_ENS210::getHumidityPercent() +{ + float h= this->_h_data & 0xFFFF; + // Return m*H. This equals m*(h/512) = (m*h)/512 + // Note m is the multiplier, H is the relative humidity in %RH, h is raw h_data value. + // Uses H=h/512. + return h/512; //IDIV(h, 512); +} + + +// Convert raw `h_data` absolute humidity to %RH. +#define MOLAR_MASS_OF_WATER 18.01534 +#define UNIVERSAL_GAS_CONSTANT 8.21447215 + +float ScioSense_ENS210::getAbsoluteHumidityPercent() +{ + //taken from https://carnotcycle.wordpress.com/2012/08/04/how-to-convert-relative-humidity-to-absolute-humidity/ + //precision is about 0.1°C in range -30 to 35°C + //August-Roche-Magnus 6.1094 exp(17.625 x T)/(T + 243.04) + //Buck (1981) 6.1121 exp(17.502 x T)/(T + 240.97) + //reference https://www.eas.ualberta.ca/jdwilson/EAS372_13/Vomel_CIRES_satvpformulae.html // Use Buck (1981) + + return (6.1121 * pow(2.718281828,(17.67* this->getTempCelsius())/(this->getTempCelsius() + 243.5))* this->getHumidityPercent() *MOLAR_MASS_OF_WATER)/((273.15+ this->getTempCelsius() )*UNIVERSAL_GAS_CONSTANT); +} + + +// Sets the solder correction (default is 50mK) - only used by the `toXxx` functions. +void ScioSense_ENS210::correction_set(int correction) +{ + assert( -1*64_soldercorrection = correction; +} + + +/****************************************************************************/ +/* General functions */ +/****************************************************************************/ + +void ScioSense_ENS210::_i2c_init() +{ + Wire.begin(); +} +/**************************************************************************/ + +uint8_t ScioSense_ENS210::read8(uint8_t addr, byte reg) +{ + uint8_t ret; + this->read(addr, reg, &ret, 1); + + return ret; +} + +uint8_t ScioSense_ENS210::read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num) +{ + uint8_t pos = 0; + uint8_t result = 0; + + if (debugENS210) { + Serial.print("I2C read address: 0x"); + Serial.print(addr, HEX); + Serial.print(" - register: 0x"); + Serial.println(reg, HEX); + } + + //on arduino we need to read in 32 byte chunks + while(pos < num){ + + uint8_t read_now = 32;//min((uint8_t)32, (uint8_t)(num - pos)); + Wire.beginTransmission((uint8_t)addr); + + Wire.write((uint8_t)reg + pos); + result = Wire.endTransmission(); + Wire.requestFrom((uint8_t)addr, read_now); + + //for(int i=0; iwrite(addr, reg, &value, 1); + return result; +} + +uint8_t ScioSense_ENS210::write(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num) +{ + if (debugENS210) { + Serial.print("I2C write address: 0x"); + Serial.print(addr, HEX); + Serial.print(" - register: 0x"); + Serial.print(reg, HEX); + Serial.print(" - value: 0x"); + for (int i = 0; i= 100) + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +// Chip constants +#define ENS210_PARTID 0x0210 // The expected part id of the ENS210 +#define ENS210_BOOTING 2 // Booting time in ms (also after reset, or going to high power) +#define ENS210_THCONV_SINGLE_MS 130 // Conversion time in ms for single shot T/H measurement +#define ENS210_THCONV_CONT_MS 238 // Conversion time in ms for continuous T/H measurement + +// Addresses of the ENS210 registers +#define ENS210_REG_PART_ID 0x00 +#define ENS210_REG_UID 0x04 +#define ENS210_REG_SYS_CTRL 0x10 +#define ENS210_REG_SYS_STAT 0x11 +#define ENS210_REG_SENS_RUN 0x21 +#define ENS210_REG_SENS_START 0x22 +#define ENS210_REG_SENS_STOP 0x23 +#define ENS210_REG_SENS_STAT 0x24 +#define ENS210_REG_T_VAL 0x30 +#define ENS210_REG_H_VAL 0x33 + +// Division macro (used in conversion functions), implementing integer division with rounding. +// It supports both positive and negative dividends (n), but ONLY positive divisors (d). +//#define IDIV(n,d) ((n)>0 ? ((n)+(d)/2)/(d) : ((n)-(d)/2)/(d)) + +// 7654 3210 +// Polynomial 0b 1000 1001 ~ x^7+x^3+x^0 +// 0x 8 9 +#define CRC7WIDTH 7 // A 7 bits CRC has polynomial of 7th order, which has 8 terms +#define CRC7POLY 0x89 // The 8 coefficients of the polynomial +#define CRC7IVEC 0x7F // Initial vector has all 7 bits high +// Payload data +#define DATA7WIDTH 17 +#define DATA7MASK ((1UL<_available; } + uint16_t getPartID() { return this->_partID; } + uint32_t getHighUID(bool high) { uint32_t result = high ? this->_uIDhi : this->_uIDlo; return result; } + void measure(); // perfrom measurement and stores result in internal variables + float getTempKelvin (); // Converts and returns data (from `measure`) in Kelvin + float getTempCelsius (); // Converts and returns data (from `measure`) in Celsius + float getTempFahrenheit (); // Converts and returns data (from `measure`) in Fahrenheit + float getHumidityPercent(); // Converts and returns data (from `measure`) in %RH + float getAbsoluteHumidityPercent(); // Converts and returns data (from `measure`) in %aH + char getStatusT() { return this->_t_status; } // Converts a status (ENS210_STATUS_XXX) to a human readable string. + uint32_t getDataT() { return this->_t_data; } + char getStatusH() { return this->_h_status; } // Converts a status (ENS210_STATUS_XXX) to a human readable string. + uint32_t getDataH() { return this->_h_data; } + static const char * status_str( int status ); // Converts a status (ENS210_STATUS_XXX) to a human readable string. + + // Optionally set a solder `correction` (units: 1/64K, default from `begin` is 0). + // See "Effect of Soldering on Temperature Readout" in "Design-Guidelines" from + // https://download.ams.com/ENVIRONMENTAL-SENSORS/ENS210/Documentation + void correction_set(int correction=50*64/1000); // Sets the solder correction (default is 50mK) - only used by the `toXxx()` functions. + int correction_get() {return this->_soldercorrection;} // Gets the solder correction. + + private: + bool debugENS210 = false; + bool reset(void); // Sends a reset to the ENS210. Returns false on I2C problems. + bool lowpower(bool enable); // Sets ENS210 to low (true) or high (false) power. Returns false on I2C problems. + bool getversion(); // Reads PART_ID and UID of ENS210. Returns false on I2C problems. + bool readValue(); // Reads measurement data from the ENS210. Returns false on I2C problems. + + bool _available = false; // ENS210 available + uint16_t _partID; // Part ID of ENS210, should be 0x210 + uint64_t _uID; // Unique ID of this specific ENS210 + uint32_t _uIDhi; // First 32bit of unique ID of this specific ENS210 + uint32_t _uIDlo; // Second 32bit of unique ID of this specific ENS210 + bool _singleMode = true; // Measurement mode: true single shot / false continuous + uint32_t _t_data; + uint8_t _t_status; + uint32_t _h_data; + uint8_t _h_status; + uint8_t _slaveaddress = 0x43; // Slave address of ENS210 + uint8_t _soldercorrection; // Correction due to soldering (in 1/64K); subtracted from `t_data` by conversion functions. + + /****************************************************************************/ + /* General functions */ + /****************************************************************************/ + + uint8_t write8(uint8_t addr, byte reg, byte value); + uint8_t read8(uint8_t addr, byte reg); + + uint8_t read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num); + uint8_t write(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t num); + void _i2c_init(); +}; + + +#endif