From f864b5ea47e6369416b1b1e7adf19e43d386e3c8 Mon Sep 17 00:00:00 2001 From: lewisxhe Date: Wed, 15 May 2024 11:38:17 +0800 Subject: [PATCH] Added SensorLib --- lib/SensorLib/.piopm | 1 + lib/SensorLib/LICENSE | 21 + lib/SensorLib/README.md | 73 + .../BAM423_Accelerometer.ino | 88 + .../BAM423_Orientation/BAM423_Orientation.ino | 142 + .../BAM423_Temperature/BAM423_Temperature.ino | 77 + .../examples/BHI260AP_6DoF/BHI260AP_6DoF.ino | 140 + .../BHI260AP_DebugInfo/BHI260AP_DebugInfo.ino | 107 + .../BHI260AP_Orientation.ino | 163 + .../BHI260AP_StepCounter.ino | 125 + .../BMA423_Feature/BMA423_Feature.ino | 140 + .../BMM150_GetDataExample.ino | 102 + .../CM32181_LightSensor.ino | 97 + .../CM32181_LightSensorInterrupt.ino | 134 + .../examples/DRV2605_Basic/DRV2605_Basic.ino | 468 + .../ESP_IDF_TouchDrv_Example/CMakeLists.txt | 8 + .../ESP_IDF_TouchDrv_Example/Makefile | 10 + .../ESP_IDF_TouchDrv_Example/README.md | 181 + .../main/CMakeLists.txt | 5 + .../main/Kconfig.projbuild | 52 + .../main/component.mk | 4 + .../main/i2c_driver.cpp | 253 + .../main/i2c_driver.h | 32 + .../ESP_IDF_TouchDrv_Example/main/main.cpp | 83 + .../main/touch_drv.cpp | 166 + .../sdkconfig.defaults | 6 + .../LTR553ALS_Sensor/LTR553ALS_Sensor.ino | 193 + .../PCF85063_AlarmByUnits.ino | 214 + .../PCF85063_SimpleTime.ino | 92 + .../PCF8563_AlarmByUnits.ino | 193 + .../PCF8563_SimpleTime/PCF8563_SimpleTime.ino | 87 + .../PCF8563_TimeLib/PCF8563_TimeLib.ino | 98 + .../PCF8563_TimeSynchronization.ino | 150 + .../QMC6310_CalibrateExample.ino | 244 + .../QMC6310_CompassExample.ino | 234 + .../QMC6310_GetDataExample.ino | 155 + .../QMC6310_GetPolarExample.ino | 133 + .../QMI8658_BlockExample.ino | 262 + .../QMI8658_GetDataExample.ino | 195 + .../QMI8658_InterruptBlockExample.ino | 272 + .../QMI8658_InterruptExample.ino | 247 + .../QMI8658_LockingMechanismExample.ino | 246 + .../QMI8658_MadgwickAHRS.ino | 204 + .../QMI8658_PedometerExample.ino | 196 + .../QMI8658_ReadFromFifoExample.ino | 218 + .../QMI8658_WakeOnMotion.ino | 160 + .../QMI8658_WakeOnMotionCallBackExample.ino | 152 + .../TouchDrv_CHSC5816_GetPoint.ino | 92 + .../TouchDrv_CSTxxx_GetPoint.ino | 175 + .../TouchDrv_FT3267_LilyGo_T_RGB.ino | 115 + .../TouchDrv_FT6232_GetPoint.ino | 92 + .../TouchDrv_GT911_GetPoint.ino | 121 + .../TouchDrv_GT911_LilyGo_T_RGB.ino | 161 + .../TouchDrv_Interface_T_RGB.ino | 204 + .../XL9555_ExtensionIOInterrupt.ino | 83 + .../XL9555_ExtensionIORead.ino | 117 + .../XL9555_ExtensionIOWirte.ino | 94 + lib/SensorLib/keywords.txt | 177 + lib/SensorLib/library.json | 32 + lib/SensorLib/library.properties | 9 + lib/SensorLib/src/ExtensionIOXL9555.hpp | 204 + lib/SensorLib/src/ExtensionSPI.tpp | 124 + lib/SensorLib/src/REG/BMA423Constants.h | 726 ++ lib/SensorLib/src/REG/CHSC5816Constants.h | 66 + lib/SensorLib/src/REG/CM32181Constants.h | 62 + lib/SensorLib/src/REG/CSTxxxConstants.h | 46 + lib/SensorLib/src/REG/DRV2605Constants.h | 80 + lib/SensorLib/src/REG/FT6X36Constants.h | 65 + lib/SensorLib/src/REG/GT911Constants.h | 156 + lib/SensorLib/src/REG/LTR533Constants.h | 63 + lib/SensorLib/src/REG/MPU6886Constants.h | 115 + lib/SensorLib/src/REG/PCF85063Constants.h | 63 + lib/SensorLib/src/REG/PCF8563Constants.h | 70 + lib/SensorLib/src/REG/QMC6310Constants.h | 53 + lib/SensorLib/src/REG/QMI8658Constants.h | 133 + lib/SensorLib/src/REG/XL9555Constants.h | 32 + lib/SensorLib/src/SensorBHI260AP.hpp | 690 ++ lib/SensorLib/src/SensorBMA423.hpp | 846 ++ lib/SensorLib/src/SensorBMM150.hpp | 332 + lib/SensorLib/src/SensorCM32181.hpp | 234 + lib/SensorLib/src/SensorCommon.tpp | 699 ++ lib/SensorLib/src/SensorDRV2605.hpp | 235 + lib/SensorLib/src/SensorLTR553.hpp | 349 + lib/SensorLib/src/SensorLib.h | 233 + lib/SensorLib/src/SensorPCF85063.hpp | 379 + lib/SensorLib/src/SensorPCF8563.hpp | 359 + lib/SensorLib/src/SensorQMC6310.hpp | 402 + lib/SensorLib/src/SensorQMI8658.hpp | 1510 +++ lib/SensorLib/src/SensorRTC.h | 344 + lib/SensorLib/src/SensorWireHelper.cpp | 123 + lib/SensorLib/src/SensorWireHelper.h | 46 + lib/SensorLib/src/TouchDrvCHSC5816.hpp | 312 + lib/SensorLib/src/TouchDrvCSTXXX.hpp | 295 + lib/SensorLib/src/TouchDrvFT6X36.hpp | 426 + lib/SensorLib/src/TouchDrvGT911.hpp | 424 + lib/SensorLib/src/TouchDrvInterface.cpp | 100 + lib/SensorLib/src/TouchDrvInterface.hpp | 145 + lib/SensorLib/src/bosch/BMM150/bmm150.c | 2187 +++++ lib/SensorLib/src/bosch/BMM150/bmm150.h | 479 + lib/SensorLib/src/bosch/BMM150/bmm150_defs.h | 643 ++ lib/SensorLib/src/bosch/BoschParse.cpp | 177 + lib/SensorLib/src/bosch/BoschParse.h | 58 + lib/SensorLib/src/bosch/SensorBhy2Define.h | 202 + lib/SensorLib/src/bosch/bhi3.c | 730 ++ lib/SensorLib/src/bosch/bhi3.h | 330 + lib/SensorLib/src/bosch/bhi3_defs.h | 204 + lib/SensorLib/src/bosch/bhi3_multi_tap.c | 211 + lib/SensorLib/src/bosch/bhi3_multi_tap.h | 111 + lib/SensorLib/src/bosch/bhi3_multi_tap_defs.h | 189 + lib/SensorLib/src/bosch/bhy2.c | 1785 ++++ lib/SensorLib/src/bosch/bhy2.h | 664 ++ lib/SensorLib/src/bosch/bhy2_bsec.c | 77 + lib/SensorLib/src/bosch/bhy2_bsec.h | 74 + lib/SensorLib/src/bosch/bhy2_defs.h | 789 ++ lib/SensorLib/src/bosch/bhy2_head_tracker.c | 353 + lib/SensorLib/src/bosch/bhy2_head_tracker.h | 213 + .../src/bosch/bhy2_head_tracker_defs.h | 138 + lib/SensorLib/src/bosch/bhy2_hif.c | 1757 ++++ lib/SensorLib/src/bosch/bhy2_hif.h | 576 ++ lib/SensorLib/src/bosch/bhy2_klio.c | 373 + lib/SensorLib/src/bosch/bhy2_klio.h | 227 + lib/SensorLib/src/bosch/bhy2_klio_defs.h | 349 + lib/SensorLib/src/bosch/bhy2_parse.c | 96 + lib/SensorLib/src/bosch/bhy2_parse.h | 109 + lib/SensorLib/src/bosch/bhy2_swim.c | 203 + lib/SensorLib/src/bosch/bhy2_swim.h | 101 + lib/SensorLib/src/bosch/bhy2_swim_defs.h | 126 + .../src/bosch/common/bosch_interfaces.cpp | 157 + .../src/bosch/common/bosch_interfaces.h | 60 + lib/SensorLib/src/bosch/common/common.cpp | 987 ++ lib/SensorLib/src/bosch/common/common.h | 65 + .../src/bosch/firmware/BHI260AP.fw.h | 8642 +++++++++++++++++ lib/SensorLib/src/platform/esp_arduino.cpp | 66 + lib/SensorLib/src/platform/esp_arduino.h | 22 + lib/SensorLib/src/touch/TouchClassCST226.cpp | 323 + lib/SensorLib/src/touch/TouchClassCST226.h | 97 + lib/SensorLib/src/touch/TouchClassCST816.cpp | 328 + lib/SensorLib/src/touch/TouchClassCST816.h | 102 + 138 files changed, 43016 insertions(+) create mode 100644 lib/SensorLib/.piopm create mode 100644 lib/SensorLib/LICENSE create mode 100644 lib/SensorLib/README.md create mode 100644 lib/SensorLib/examples/BAM423_Accelerometer/BAM423_Accelerometer.ino create mode 100644 lib/SensorLib/examples/BAM423_Orientation/BAM423_Orientation.ino create mode 100644 lib/SensorLib/examples/BAM423_Temperature/BAM423_Temperature.ino create mode 100644 lib/SensorLib/examples/BHI260AP_6DoF/BHI260AP_6DoF.ino create mode 100644 lib/SensorLib/examples/BHI260AP_DebugInfo/BHI260AP_DebugInfo.ino create mode 100644 lib/SensorLib/examples/BHI260AP_Orientation/BHI260AP_Orientation.ino create mode 100644 lib/SensorLib/examples/BHI260AP_StepCounter/BHI260AP_StepCounter.ino create mode 100644 lib/SensorLib/examples/BMA423_Feature/BMA423_Feature.ino create mode 100644 lib/SensorLib/examples/BMM150_GetDataExample/BMM150_GetDataExample.ino create mode 100644 lib/SensorLib/examples/CM32181_LightSensor/CM32181_LightSensor.ino create mode 100644 lib/SensorLib/examples/CM32181_LightSensorInterrupt/CM32181_LightSensorInterrupt.ino create mode 100644 lib/SensorLib/examples/DRV2605_Basic/DRV2605_Basic.ino create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/CMakeLists.txt create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/Makefile create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/README.md create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/CMakeLists.txt create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/Kconfig.projbuild create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/component.mk create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.cpp create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.h create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/main.cpp create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/touch_drv.cpp create mode 100644 lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/sdkconfig.defaults create mode 100644 lib/SensorLib/examples/LTR553ALS_Sensor/LTR553ALS_Sensor.ino create mode 100644 lib/SensorLib/examples/PCF85063_AlarmByUnits/PCF85063_AlarmByUnits.ino create mode 100644 lib/SensorLib/examples/PCF85063_SimpleTime/PCF85063_SimpleTime.ino create mode 100644 lib/SensorLib/examples/PCF8563_AlarmByUnits/PCF8563_AlarmByUnits.ino create mode 100644 lib/SensorLib/examples/PCF8563_SimpleTime/PCF8563_SimpleTime.ino create mode 100644 lib/SensorLib/examples/PCF8563_TimeLib/PCF8563_TimeLib.ino create mode 100644 lib/SensorLib/examples/PCF8563_TimeSynchronization/PCF8563_TimeSynchronization.ino create mode 100644 lib/SensorLib/examples/QMC6310_CalibrateExample/QMC6310_CalibrateExample.ino create mode 100644 lib/SensorLib/examples/QMC6310_CompassExample/QMC6310_CompassExample.ino create mode 100644 lib/SensorLib/examples/QMC6310_GetDataExample/QMC6310_GetDataExample.ino create mode 100644 lib/SensorLib/examples/QMC6310_GetPolarExample/QMC6310_GetPolarExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_BlockExample/QMI8658_BlockExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_GetDataExample/QMI8658_GetDataExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_InterruptBlockExample/QMI8658_InterruptBlockExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_InterruptExample/QMI8658_InterruptExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_LockingMechanismExample/QMI8658_LockingMechanismExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_MadgwickAHRS/QMI8658_MadgwickAHRS.ino create mode 100644 lib/SensorLib/examples/QMI8658_PedometerExample/QMI8658_PedometerExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_ReadFromFifoExample/QMI8658_ReadFromFifoExample.ino create mode 100644 lib/SensorLib/examples/QMI8658_WakeOnMotion/QMI8658_WakeOnMotion.ino create mode 100644 lib/SensorLib/examples/QMI8658_WakeOnMotionCallBackExample/QMI8658_WakeOnMotionCallBackExample.ino create mode 100644 lib/SensorLib/examples/TouchDrv_CHSC5816_GetPoint/TouchDrv_CHSC5816_GetPoint.ino create mode 100644 lib/SensorLib/examples/TouchDrv_CSTxxx_GetPoint/TouchDrv_CSTxxx_GetPoint.ino create mode 100644 lib/SensorLib/examples/TouchDrv_FT3267_LilyGo_T_RGB/TouchDrv_FT3267_LilyGo_T_RGB.ino create mode 100644 lib/SensorLib/examples/TouchDrv_FT6232_GetPoint/TouchDrv_FT6232_GetPoint.ino create mode 100644 lib/SensorLib/examples/TouchDrv_GT911_GetPoint/TouchDrv_GT911_GetPoint.ino create mode 100644 lib/SensorLib/examples/TouchDrv_GT911_LilyGo_T_RGB/TouchDrv_GT911_LilyGo_T_RGB.ino create mode 100644 lib/SensorLib/examples/TouchDrv_Interface_T_RGB/TouchDrv_Interface_T_RGB.ino create mode 100644 lib/SensorLib/examples/XL9555_ExtensionIOInterrupt/XL9555_ExtensionIOInterrupt.ino create mode 100644 lib/SensorLib/examples/XL9555_ExtensionIORead/XL9555_ExtensionIORead.ino create mode 100644 lib/SensorLib/examples/XL9555_ExtensionIOWirte/XL9555_ExtensionIOWirte.ino create mode 100644 lib/SensorLib/keywords.txt create mode 100644 lib/SensorLib/library.json create mode 100644 lib/SensorLib/library.properties create mode 100644 lib/SensorLib/src/ExtensionIOXL9555.hpp create mode 100644 lib/SensorLib/src/ExtensionSPI.tpp create mode 100644 lib/SensorLib/src/REG/BMA423Constants.h create mode 100644 lib/SensorLib/src/REG/CHSC5816Constants.h create mode 100644 lib/SensorLib/src/REG/CM32181Constants.h create mode 100644 lib/SensorLib/src/REG/CSTxxxConstants.h create mode 100644 lib/SensorLib/src/REG/DRV2605Constants.h create mode 100644 lib/SensorLib/src/REG/FT6X36Constants.h create mode 100644 lib/SensorLib/src/REG/GT911Constants.h create mode 100644 lib/SensorLib/src/REG/LTR533Constants.h create mode 100644 lib/SensorLib/src/REG/MPU6886Constants.h create mode 100644 lib/SensorLib/src/REG/PCF85063Constants.h create mode 100644 lib/SensorLib/src/REG/PCF8563Constants.h create mode 100644 lib/SensorLib/src/REG/QMC6310Constants.h create mode 100644 lib/SensorLib/src/REG/QMI8658Constants.h create mode 100644 lib/SensorLib/src/REG/XL9555Constants.h create mode 100644 lib/SensorLib/src/SensorBHI260AP.hpp create mode 100644 lib/SensorLib/src/SensorBMA423.hpp create mode 100644 lib/SensorLib/src/SensorBMM150.hpp create mode 100644 lib/SensorLib/src/SensorCM32181.hpp create mode 100644 lib/SensorLib/src/SensorCommon.tpp create mode 100644 lib/SensorLib/src/SensorDRV2605.hpp create mode 100644 lib/SensorLib/src/SensorLTR553.hpp create mode 100644 lib/SensorLib/src/SensorLib.h create mode 100644 lib/SensorLib/src/SensorPCF85063.hpp create mode 100644 lib/SensorLib/src/SensorPCF8563.hpp create mode 100644 lib/SensorLib/src/SensorQMC6310.hpp create mode 100644 lib/SensorLib/src/SensorQMI8658.hpp create mode 100644 lib/SensorLib/src/SensorRTC.h create mode 100644 lib/SensorLib/src/SensorWireHelper.cpp create mode 100644 lib/SensorLib/src/SensorWireHelper.h create mode 100644 lib/SensorLib/src/TouchDrvCHSC5816.hpp create mode 100644 lib/SensorLib/src/TouchDrvCSTXXX.hpp create mode 100644 lib/SensorLib/src/TouchDrvFT6X36.hpp create mode 100644 lib/SensorLib/src/TouchDrvGT911.hpp create mode 100644 lib/SensorLib/src/TouchDrvInterface.cpp create mode 100644 lib/SensorLib/src/TouchDrvInterface.hpp create mode 100644 lib/SensorLib/src/bosch/BMM150/bmm150.c create mode 100644 lib/SensorLib/src/bosch/BMM150/bmm150.h create mode 100644 lib/SensorLib/src/bosch/BMM150/bmm150_defs.h create mode 100644 lib/SensorLib/src/bosch/BoschParse.cpp create mode 100644 lib/SensorLib/src/bosch/BoschParse.h create mode 100644 lib/SensorLib/src/bosch/SensorBhy2Define.h create mode 100644 lib/SensorLib/src/bosch/bhi3.c create mode 100644 lib/SensorLib/src/bosch/bhi3.h create mode 100644 lib/SensorLib/src/bosch/bhi3_defs.h create mode 100644 lib/SensorLib/src/bosch/bhi3_multi_tap.c create mode 100644 lib/SensorLib/src/bosch/bhi3_multi_tap.h create mode 100644 lib/SensorLib/src/bosch/bhi3_multi_tap_defs.h create mode 100644 lib/SensorLib/src/bosch/bhy2.c create mode 100644 lib/SensorLib/src/bosch/bhy2.h create mode 100644 lib/SensorLib/src/bosch/bhy2_bsec.c create mode 100644 lib/SensorLib/src/bosch/bhy2_bsec.h create mode 100644 lib/SensorLib/src/bosch/bhy2_defs.h create mode 100644 lib/SensorLib/src/bosch/bhy2_head_tracker.c create mode 100644 lib/SensorLib/src/bosch/bhy2_head_tracker.h create mode 100644 lib/SensorLib/src/bosch/bhy2_head_tracker_defs.h create mode 100644 lib/SensorLib/src/bosch/bhy2_hif.c create mode 100644 lib/SensorLib/src/bosch/bhy2_hif.h create mode 100644 lib/SensorLib/src/bosch/bhy2_klio.c create mode 100644 lib/SensorLib/src/bosch/bhy2_klio.h create mode 100644 lib/SensorLib/src/bosch/bhy2_klio_defs.h create mode 100644 lib/SensorLib/src/bosch/bhy2_parse.c create mode 100644 lib/SensorLib/src/bosch/bhy2_parse.h create mode 100644 lib/SensorLib/src/bosch/bhy2_swim.c create mode 100644 lib/SensorLib/src/bosch/bhy2_swim.h create mode 100644 lib/SensorLib/src/bosch/bhy2_swim_defs.h create mode 100644 lib/SensorLib/src/bosch/common/bosch_interfaces.cpp create mode 100644 lib/SensorLib/src/bosch/common/bosch_interfaces.h create mode 100644 lib/SensorLib/src/bosch/common/common.cpp create mode 100644 lib/SensorLib/src/bosch/common/common.h create mode 100644 lib/SensorLib/src/bosch/firmware/BHI260AP.fw.h create mode 100644 lib/SensorLib/src/platform/esp_arduino.cpp create mode 100644 lib/SensorLib/src/platform/esp_arduino.h create mode 100644 lib/SensorLib/src/touch/TouchClassCST226.cpp create mode 100644 lib/SensorLib/src/touch/TouchClassCST226.h create mode 100644 lib/SensorLib/src/touch/TouchClassCST816.cpp create mode 100644 lib/SensorLib/src/touch/TouchClassCST816.h diff --git a/lib/SensorLib/.piopm b/lib/SensorLib/.piopm new file mode 100644 index 0000000..413f7d4 --- /dev/null +++ b/lib/SensorLib/.piopm @@ -0,0 +1 @@ +{"type": "library", "name": "SensorLib", "version": "0.2.0", "spec": {"owner": "lewisxhe", "id": 15035, "name": "SensorLib", "requirements": null, "uri": null}} \ No newline at end of file diff --git a/lib/SensorLib/LICENSE b/lib/SensorLib/LICENSE new file mode 100644 index 0000000..8b49a9e --- /dev/null +++ b/lib/SensorLib/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 lewis he + +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/SensorLib/README.md b/lib/SensorLib/README.md new file mode 100644 index 0000000..3838bd8 --- /dev/null +++ b/lib/SensorLib/README.md @@ -0,0 +1,73 @@ +``` + _____ _ _ _ +/ ___| | | (_)| | +\ `--. ___ _ __ ___ ___ _ __ | | _ | |__ + `--. \ / _ \| '_ \ / __| / _ \ | '__|| | | || '_ \ +/\__/ /| __/| | | |\__ \| (_) || | | |____| || |_) | +\____/ \___||_| |_||___/ \___/ |_| \_____/|_||_.__/ + ··· ··· +> Commonly used I2C , SPI device multi-platform libraries + +``` + +[![Build esp-idf](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml) +[![Arduino CI](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml) +[![PlatformIO CI](https://github.com/lewisxhe/SensorLib/actions/workflows/pio.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/pio.yml) +[![arduino-library-badge](https://www.ardu-badge.com/badge/SensorLib.svg?)](https://www.ardu-badge.com/SensorLib) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/lewisxhe/library/SensorLib.svg)](https://registry.platformio.org/libraries/lewisxhe/SensorLib) + + +[![LICENSE](https://img.shields.io/github/license/lewisxhe/SensorLib)](https://github.com/lewisxhe/SensorLib/blob/master/LICENSE) +[![ISSUES](https://img.shields.io/github/issues/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/issues) +[![FROK](https://img.shields.io/github/forks/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/graphs/contributors) +[![STAR](https://img.shields.io/github/stars/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/stargazers) +[![releases](https://img.shields.io/github/release/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorLib/releases) + +![PCF8563](https://img.shields.io/badge/PCB8563-GREEN) +![PCF85063](https://img.shields.io/badge/PCF85063-GREEN) +![HYM8563](https://img.shields.io/badge/HYM8563-GREEN) +![QMI8658](https://img.shields.io/badge/QMI8658-blue) +![BMM150](https://img.shields.io/badge/BMM150-blue) +![QMC6310](https://img.shields.io/badge/QMC6310-blue) +![BMA423](https://img.shields.io/badge/BMA423-blue) +![BHI260AP](https://img.shields.io/badge/BHI260AP-blue) +![XL9555](https://img.shields.io/badge/XL9555-yellow) +![DRV2605](https://img.shields.io/badge/DRV2605-teal) +![CM32181](https://img.shields.io/badge/CM32181-brown) +![LTR553](https://img.shields.io/badge/LTR553-brown) +![FT5206](https://img.shields.io/badge/FT5206-red) +![FT6206](https://img.shields.io/badge/FT6206-red) +![FT6236](https://img.shields.io/badge/FT6236-red) +![FT3267](https://img.shields.io/badge/FT3267-red) +![CST816S](https://img.shields.io/badge/CST816S-red) +![CST816D](https://img.shields.io/badge/CST816D-red) +![CST816T](https://img.shields.io/badge/CST816T-red) +![CST820](https://img.shields.io/badge/CST820-red) +![CST226SE](https://img.shields.io/badge/CST226SE-red) +![CHSC5816](https://img.shields.io/badge/CHSC5816-red) +![GT911](https://img.shields.io/badge/GT911-red) + +Support list: + +| Sensor | Description | I2C | SPI | +| --------------- | ------------------------ | --- | --- | +| PCF8563/HYM8563 | Real-time clock | ✔️ | ❌ | +| PCF85063 | Real-time clock | ✔️ | ❌ | +| QMI8658 | IMU | ✔️ | ✔️ | +| BHI260AP | IMU | ✔️ | ✔️ | +| QMC6310 | Magnetic Sensor | ✔️ | ❌ | +| BMM150 | Magnetic Sensor | ✔️ | ❌ | +| XL9555 | I/O expander | ✔️ | ❌ | +| BMA423 | Accelerometer | ✔️ | ❌ | +| DRV2605 | Haptic Driver | ✔️ | ❌ | +| CM32181 | Ambient Light Sensor | ✔️ | ❌ | +| LTR553 | Light & Proximity Sensor | ✔️ | ❌ | +| FT3267 | Capacitive touch | ✔️ | ❌ | +| FT5206 | Capacitive touch | ✔️ | ❌ | +| FT6206 | Capacitive touch | ✔️ | ❌ | +| FT6236 | Capacitive touch | ✔️ | ❌ | +| CST820 | Capacitive touch | ✔️ | ❌ | +| CST816S/T/D | Capacitive touch | ✔️ | ❌ | +| CST226SE | Capacitive touch | ✔️ | ❌ | +| CHSC5816 | Capacitive touch | ✔️ | ❌ | +| GT911 | Capacitive touch | ✔️ | ❌ | diff --git a/lib/SensorLib/examples/BAM423_Accelerometer/BAM423_Accelerometer.ino b/lib/SensorLib/examples/BAM423_Accelerometer/BAM423_Accelerometer.ino new file mode 100644 index 0000000..d9e8561 --- /dev/null +++ b/lib/SensorLib/examples/BAM423_Accelerometer/BAM423_Accelerometer.ino @@ -0,0 +1,88 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file BAM423_Accelerometer.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-01 + * + */ +#include +#include +#include +#include "SensorBMA423.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 21 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 22 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 39 +#endif + +SensorBMA423 accel; +uint32_t lastMillis; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT); + + if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find BMA423 - check your wiring!"); + while (1) { + delay(1000); + } + } + Serial.println("Init BAM423 Sensor success!"); + + //Default 4G ,200HZ + accel.configAccelerometer(); + + accel.enableAccelerometer(); +} + + +void loop() +{ + int16_t x, y, z; + accel.getAccelerometer(x, y, z); + Serial.print("X:"); + Serial.print(x); Serial.print(" "); + Serial.print("Y:"); + Serial.print(y); Serial.print(" "); + Serial.print("Z:"); + Serial.print(z); + Serial.println(); + + delay(50); +} + + + diff --git a/lib/SensorLib/examples/BAM423_Orientation/BAM423_Orientation.ino b/lib/SensorLib/examples/BAM423_Orientation/BAM423_Orientation.ino new file mode 100644 index 0000000..a10535d --- /dev/null +++ b/lib/SensorLib/examples/BAM423_Orientation/BAM423_Orientation.ino @@ -0,0 +1,142 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file BAM423_Orientation.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-03 + * + */ +#include +#include +#include +#include "SensorBMA423.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 21 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 22 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 39 +#endif + +SensorBMA423 accel; +char report[256]; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT); + + if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find BMA423 - check your wiring!"); + while (1) { + delay(1000); + } + } + Serial.println("Init BAM423 Sensor success!"); + + //Default 4G ,200HZ + accel.configAccelerometer(); + + accel.enableAccelerometer(); + + Serial.println("Output ..."); +} + + + +void loop() +{ + uint8_t direction = accel.direction(); + switch (direction) { + case SensorBMA423::DIRECTION_BOTTOM_LEFT: + + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n |________________| \r\n" ); + + break; + case SensorBMA423::DIRECTION_TOP_RIGHT: + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n |________________| \r\n" ); + break; + case SensorBMA423::DIRECTION_TOP_LEFT: + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n |________________| \r\n" ); + break; + case SensorBMA423::DIRECTION_BOTTOM_RIGHT: + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n |________________| \r\n" ); + break; + case SensorBMA423::DIRECTION_BOTTOM: + sprintf( report, "\r\n ________________ " \ + "\r\n |________________| " \ + "\r\n * \r\n" ); + break; + case SensorBMA423::DIRECTION_TOP: + sprintf( report, "\r\n __*_____________ " \ + "\r\n |________________| \r\n" ); + break; + default: + sprintf( report, "None of the 3D orientation axes is set in BMA423 - accelerometer.\r\n" ); + break; + } + + Serial.println(direction); + Serial.println(report); + + delay(1000); +} + + + diff --git a/lib/SensorLib/examples/BAM423_Temperature/BAM423_Temperature.ino b/lib/SensorLib/examples/BAM423_Temperature/BAM423_Temperature.ino new file mode 100644 index 0000000..fad6e99 --- /dev/null +++ b/lib/SensorLib/examples/BAM423_Temperature/BAM423_Temperature.ino @@ -0,0 +1,77 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file BAM423_Temperature.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-01 + * + */ +#include +#include +#include +#include "SensorBMA423.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 21 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 22 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 39 +#endif + +SensorBMA423 accel; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT); + + if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find BMA423 - check your wiring!"); + while (1) { + delay(1000); + } + } + Serial.println("Init BAM423 Sensor success!"); +} + + +void loop() +{ + Serial.print("getTemperature:"); + Serial.print(accel.getTemperature(SensorBMA423::TEMP_DEG)); + Serial.print("*C "); + Serial.print(accel.getTemperature(SensorBMA423::TEMP_FAHREN)); + Serial.print("*F"); + delay(1000); +} + + + diff --git a/lib/SensorLib/examples/BHI260AP_6DoF/BHI260AP_6DoF.ino b/lib/SensorLib/examples/BHI260AP_6DoF/BHI260AP_6DoF.ino new file mode 100644 index 0000000..bb1635b --- /dev/null +++ b/lib/SensorLib/examples/BHI260AP_6DoF/BHI260AP_6DoF.ino @@ -0,0 +1,140 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file BHI260AP_6DoF.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-06 + * + */ +#include +#include +#include +#include "SensorBHI260AP.hpp" + +#ifdef BHY2_USE_I2C +#define BHI260AP_SDA 21 +#define BHI260AP_SCL 22 +#define BHI260AP_IRQ 39 +#define BHI260AP_RST -1 +#else +#define BHI260AP_MOSI 33 +#define BHI260AP_MISO 34 +#define BHI260AP_SCK 35 +#define BHI260AP_CS 36 +#define BHI260AP_IRQ 37 +#define BHI260AP_RST 47 +#endif + + +SensorBHI260AP bhy; +void accel_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len) +{ + struct bhy2_data_xyz data; + float scaling_factor = get_sensor_default_scaling(sensor_id); + bhy2_parse_xyz(data_ptr, &data); + Serial.print(bhy.getSensorName(sensor_id)); + Serial.print(":"); + Serial.printf("x: %f, y: %f, z: %f;\r\n", + data.x * scaling_factor, + data.y * scaling_factor, + data.z * scaling_factor + ); +} + + +void gyro_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len) +{ + struct bhy2_data_xyz data; + float scaling_factor = get_sensor_default_scaling(sensor_id); + bhy2_parse_xyz(data_ptr, &data); + Serial.print(bhy.getSensorName(sensor_id)); + Serial.print(":"); + Serial.printf("x: %f, y: %f, z: %f;\r\n", + data.x * scaling_factor, + data.y * scaling_factor, + data.z * scaling_factor + ); +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + // Set the reset pin and interrupt pin, if any + bhy.setPins(BHI260AP_RST, BHI260AP_IRQ); + +#ifdef BHY2_USE_I2C + // Using I2C interface + // BHI260AP_SLAVE_ADDRESS_L = 0x28 + // BHI260AP_SLAVE_ADDRESS_H = 0x29 + if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#else + // Using SPI interface + if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#endif + + Serial.println("Init BHI260AP Sensor success!"); + + // Output all available sensors to Serial + bhy.printSensors(Serial); + + float sample_rate = 100.0; /* Read out hintr_ctrl measured at 100Hz */ + uint32_t report_latency_ms = 0; /* Report immediately */ + + // Enable acceleration + bhy.configure(SENSOR_ID_ACC_PASS, sample_rate, report_latency_ms); + // Enable gyroscope + bhy.configure(SENSOR_ID_GYRO_PASS, sample_rate, report_latency_ms); + + // Set the acceleration sensor result callback function + bhy.onResultEvent(SENSOR_ID_ACC_PASS, accel_process_callback); + + // Set the gyroscope sensor result callback function + bhy.onResultEvent(SENSOR_ID_GYRO_PASS, gyro_process_callback); + +} + + +void loop() +{ + // Update sensor fifo + bhy.update(); + delay(50); +} + + + diff --git a/lib/SensorLib/examples/BHI260AP_DebugInfo/BHI260AP_DebugInfo.ino b/lib/SensorLib/examples/BHI260AP_DebugInfo/BHI260AP_DebugInfo.ino new file mode 100644 index 0000000..1f9bed1 --- /dev/null +++ b/lib/SensorLib/examples/BHI260AP_DebugInfo/BHI260AP_DebugInfo.ino @@ -0,0 +1,107 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file BHI260AP_DebugInfo.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-08 + * + */ +#include +#include +#include +#include "SensorBHI260AP.hpp" + +#ifdef BHY2_USE_I2C +#define BHI260AP_SDA 21 +#define BHI260AP_SCL 22 +#define BHI260AP_IRQ 39 +#define BHI260AP_RST -1 +#else +#define BHI260AP_MOSI 33 +#define BHI260AP_MISO 34 +#define BHI260AP_SCK 35 +#define BHI260AP_CS 36 +#define BHI260AP_IRQ 37 +#define BHI260AP_RST 47 +#endif + +SensorBHI260AP bhy; + + +void quaternion_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len) +{ + Serial.println(bhy.getSensorName(sensor_id)); +} + + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + // Set the reset pin and interrupt pin, if any + bhy.setPins(BHI260AP_RST, BHI260AP_IRQ); + +#ifdef BHY2_USE_I2C + // Using I2C interface + // BHI260AP_SLAVE_ADDRESS_L = 0x28 + // BHI260AP_SLAVE_ADDRESS_H = 0x29 + if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#else + // Using SPI interface + if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#endif + + Serial.println("Init BHI260AP Sensor success!"); + + + // Output all current sensor information + bhy.printInfo(Serial); + + // Output interrupt configuration information to Serial + bhy.printInterruptCtrl(Serial); +} + + +void loop() +{ + // Update sensor fifo + bhy.update(); + delay(50); +} + diff --git a/lib/SensorLib/examples/BHI260AP_Orientation/BHI260AP_Orientation.ino b/lib/SensorLib/examples/BHI260AP_Orientation/BHI260AP_Orientation.ino new file mode 100644 index 0000000..1d40748 --- /dev/null +++ b/lib/SensorLib/examples/BHI260AP_Orientation/BHI260AP_Orientation.ino @@ -0,0 +1,163 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file BHI260AP_Orientation.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-07 + * + */ +#include +#include +#include +#include "SensorBHI260AP.hpp" + +#ifdef BHY2_USE_I2C +#define BHI260AP_SDA 21 +#define BHI260AP_SCL 22 +#define BHI260AP_IRQ 39 +#define BHI260AP_RST -1 +#else +#define BHI260AP_MOSI 33 +#define BHI260AP_MISO 34 +#define BHI260AP_SCK 35 +#define BHI260AP_CS 36 +#define BHI260AP_IRQ 37 +#define BHI260AP_RST 47 +#endif + +void orientation_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len); + +SensorBHI260AP bhy; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + // Set the reset pin and interrupt pin, if any + bhy.setPins(BHI260AP_RST, BHI260AP_IRQ); + +#ifdef BHY2_USE_I2C + // Using I2C interface + // BHI260AP_SLAVE_ADDRESS_L = 0x28 + // BHI260AP_SLAVE_ADDRESS_H = 0x29 + if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#else + // Using SPI interface + if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#endif + + Serial.println("Init BHI260AP Sensor success!"); + + // Output all available sensors to Serial + bhy.printSensors(Serial); + + float sample_rate = 100.0; /* Read out hintr_ctrl measured at 100Hz */ + uint32_t report_latency_ms = 0; /* Report immediately */ + + // Direction detection relies on the accelerometer, and the accelerometer needs to be turned on first. + bhy.configure(SENSOR_ID_ACC_PASS, sample_rate, report_latency_ms); + // Enable direction detection + bhy.configure(SENSOR_ID_DEVICE_ORI, sample_rate, report_latency_ms); + // Set the direction detection result output processing function + bhy.onResultEvent(SENSOR_ID_DEVICE_ORI, orientation_process_callback); +} + + +void loop() +{ + // Update sensor fifo + bhy.update(); + delay(50); +} + + +void orientation_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len) +{ + char report[256]; + uint8_t direction = *data_ptr; + switch (direction) { + case BHY2_DIRECTION_BOTTOM_LEFT: + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n |________________| \r\n" ); + + break; + case BHY2_DIRECTION_TOP_RIGHT: + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n |________________| \r\n" ); + break; + case BHY2_DIRECTION_TOP_LEFT: + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n |________________| \r\n" ); + break; + case BHY2_DIRECTION_BOTTOM_RIGHT: + sprintf( report, "\r\n ________________ " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | | " \ + "\r\n | * | " \ + "\r\n |________________| \r\n" ); + break; + default: + sprintf( report, "None of the 3D orientation axes is set in BHI260 - accelerometer.\r\n" ); + break; + } + Serial.print(bhy.getSensorName(sensor_id)); + Serial.print(":"); + Serial.println(direction); + Serial.println(report); +} diff --git a/lib/SensorLib/examples/BHI260AP_StepCounter/BHI260AP_StepCounter.ino b/lib/SensorLib/examples/BHI260AP_StepCounter/BHI260AP_StepCounter.ino new file mode 100644 index 0000000..c2f39d4 --- /dev/null +++ b/lib/SensorLib/examples/BHI260AP_StepCounter/BHI260AP_StepCounter.ino @@ -0,0 +1,125 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file BHI260AP_StepCounter.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-08 + * + */ +#include +#include +#include +#include "SensorBHI260AP.hpp" + +#ifdef BHY2_USE_I2C +#define BHI260AP_SDA 21 +#define BHI260AP_SCL 22 +#define BHI260AP_IRQ 39 +#define BHI260AP_RST -1 +#else +#define BHI260AP_MOSI 33 +#define BHI260AP_MISO 34 +#define BHI260AP_SCK 35 +#define BHI260AP_CS 36 +#define BHI260AP_IRQ 37 +#define BHI260AP_RST 47 +#endif + +SensorBHI260AP bhy; + + +void step_detector_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len) +{ + Serial.print(bhy.getSensorName(sensor_id)); + Serial.println(" detected."); +} + +void step_counter_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len) +{ + Serial.print(bhy.getSensorName(sensor_id)); + Serial.print(":"); + Serial.println(bhy2_parse_step_counter(data_ptr)); +} + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + // Set the reset pin and interrupt pin, if any + bhy.setPins(BHI260AP_RST, BHI260AP_IRQ); + +#ifdef BHY2_USE_I2C + // Using I2C interface + // BHI260AP_SLAVE_ADDRESS_L = 0x28 + // BHI260AP_SLAVE_ADDRESS_H = 0x29 + if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#else + // Using SPI interface + if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) { + Serial.print("Failed to init BHI260AP - "); + Serial.println(bhy.getError()); + while (1) { + delay(1000); + } + } +#endif + + Serial.println("Init BHI260AP Sensor success!"); + + // Output all available sensors to Serial + bhy.printSensors(Serial); + + float sample_rate = 100.0; /* Read out hintr_ctrl measured at 100Hz */ + uint32_t report_latency_ms = 0; /* Report immediately */ + + // Direction Step count relies on the accelerometer, and the accelerometer needs to be turned on first. + bhy.configure(SENSOR_ID_ACC_PASS, sample_rate, report_latency_ms); + // Enable Step detector + bhy.configure(SENSOR_ID_STD, sample_rate, report_latency_ms); + // Enable Step counter + bhy.configure(SENSOR_ID_STC, sample_rate, report_latency_ms); + + // Set the number of steps to detect the callback function + bhy.onResultEvent(SENSOR_ID_STD, step_detector_process_callback); + bhy.onResultEvent(SENSOR_ID_STC, step_counter_process_callback); +} + + +void loop() +{ + // Update sensor fifo + bhy.update(); + delay(50); +} + + diff --git a/lib/SensorLib/examples/BMA423_Feature/BMA423_Feature.ino b/lib/SensorLib/examples/BMA423_Feature/BMA423_Feature.ino new file mode 100644 index 0000000..bf59df2 --- /dev/null +++ b/lib/SensorLib/examples/BMA423_Feature/BMA423_Feature.ino @@ -0,0 +1,140 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file BMA423_Feature.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-03 + * + */ +#include +#include +#include +#include "SensorBMA423.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 21 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 22 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 39 +#endif + +SensorBMA423 accel; +uint32_t lastMillis; +bool sensorIRQ = false; + + +void setFlag() +{ + sensorIRQ = true; +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT); + attachInterrupt(SENSOR_IRQ, setFlag, RISING); + + if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find BMA423 - check your wiring!"); + while (1) { + delay(1000); + } + } + + Serial.println("Init BAM423 Sensor success!"); + + //Default 4G ,200HZ + accel.configAccelerometer(); + + // Enable acceleration sensor + accel.enableAccelerometer(); + + // Enable pedometer steps + accel.enablePedometer(); + + // Emptying the pedometer steps + accel.resetPedometer(); + + // Enable sensor features + accel.enableFeature(SensorBMA423::FEATURE_STEP_CNTR | + SensorBMA423::FEATURE_ANY_MOTION | + SensorBMA423::FEATURE_ACTIVITY | + SensorBMA423::FEATURE_TILT | + SensorBMA423::FEATURE_WAKEUP, + true); + + // Pedometer interrupt enable + accel.enablePedometerIRQ(); + // Tilt interrupt enable + accel.enableTiltIRQ(); + // DoubleTap interrupt enable + accel.enableWakeupIRQ(); + // Any motion / no motion interrupt enable + accel.enableAnyNoMotionIRQ(); + // Activity interruption enable + accel.enableActivityIRQ(); + // Chip interrupt function enable + accel.configInterrupt(); + +} + + +void loop() +{ + int16_t x, y, z; + if (sensorIRQ) { + sensorIRQ = false; + // The interrupt status must be read after an interrupt is detected + uint16_t status = accel.readIrqStatus(); + Serial.printf("Accelerometer interrupt mask : 0x%x\n", status); + + if (accel.isPedometer()) { + uint32_t stepCounter = accel.getPedometerCounter(); + Serial.printf("Step count interrupt,step Counter:%u\n", stepCounter); + } + if (accel.isActivity()) { + Serial.println("Activity interrupt"); + } + if (accel.isTilt()) { + Serial.println("Tilt interrupt"); + } + if (accel.isDoubleTap()) { + Serial.println("DoubleTap interrupt"); + } + if (accel.isAnyNoMotion()) { + Serial.println("Any motion / no motion interrupt"); + } + } + delay(50); +} + + + diff --git a/lib/SensorLib/examples/BMM150_GetDataExample/BMM150_GetDataExample.ino b/lib/SensorLib/examples/BMM150_GetDataExample/BMM150_GetDataExample.ino new file mode 100644 index 0000000..4009221 --- /dev/null +++ b/lib/SensorLib/examples/BMM150_GetDataExample/BMM150_GetDataExample.ino @@ -0,0 +1,102 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file BMM150_GetDataExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-10 + * + */ +#include +#include +#include +#include "SensorBMM150.hpp" +#include "SensorWireHelper.h" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 33 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 35 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +#ifndef SENSOR_RST +#define SENSOR_RST -1 +#endif + + +SensorBMM150 bmm; + + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + // Using I2C interface + if (!bmm.init(Wire, SENSOR_SDA, SENSOR_SCL, BMM150_I2C_ADDRESS_CSB_HIGH_SDO_LOW)) { + Serial.print("Failed to init BMM150 - check your wiring!"); + while (1) { + delay(1000); + } + } + + Serial.println("Init BMM150 Sensor success!"); + + /* Set magnetometer run mode */ + /** + * * POWERMODE_NORMAL, + * * POWERMODE_FORCED, + * * POWERMODE_SLEEP, + * * POWERMODE_SUSPEND, + */ + bmm.setMode(SensorBMM150::POWERMODE_NORMAL); + +} + + +void loop() +{ + int16_t x, y, z; + /* Read mag data */ + /* Unit for magnetometer data is microtesla(uT) */ + if (bmm.getMag(x, y, z)) { + Serial.print("X:"); + Serial.print(x); + Serial.print("uT,"); + Serial.print("Y:"); + Serial.print(y); + Serial.print("uT,"); + Serial.print("Z:"); + Serial.print(z); + Serial.println("uT"); + } + delay(50); +} + diff --git a/lib/SensorLib/examples/CM32181_LightSensor/CM32181_LightSensor.ino b/lib/SensorLib/examples/CM32181_LightSensor/CM32181_LightSensor.ino new file mode 100644 index 0000000..41ee441 --- /dev/null +++ b/lib/SensorLib/examples/CM32181_LightSensor/CM32181_LightSensor.ino @@ -0,0 +1,97 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file CM32181_LightSensor.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-14 + * + */ +#include +#include +#include +#include "SensorCM32181.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 39 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 40 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 1 +#endif + +SensorCM32181 light; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + if (!light.begin(Wire, CM32181_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find CM32181 - check your wiring!"); + while (1) { + delay(1000); + } + } + + Serial.println("Init CM32181 Sensor success!"); + + int id = light.getChipID(); + Serial.print("CM32181 ID = "); Serial.println(id); + + /* + Sensitivity mode selection + SAMPLING_X1 + SAMPLING_X2 + SAMPLING_X1_8 + SAMPLING_X1_4 + */ + light.setSampling(SensorCM32181::SAMPLING_X2); + + //Power On sensor + light.powerOn(); + +} + + +void loop() +{ + // Get raw data + uint16_t raw = light.getRaw(); + + // Get conversion data , The manual does not provide information on how to obtain the + // calibration value, now use the calibration value 0.28 provided by the manual + float lux = light.getLux(); + Serial.printf("RAW:%u Lux:%.2f\n", raw, lux); + delay(500); +} + + + diff --git a/lib/SensorLib/examples/CM32181_LightSensorInterrupt/CM32181_LightSensorInterrupt.ino b/lib/SensorLib/examples/CM32181_LightSensorInterrupt/CM32181_LightSensorInterrupt.ino new file mode 100644 index 0000000..03e847f --- /dev/null +++ b/lib/SensorLib/examples/CM32181_LightSensorInterrupt/CM32181_LightSensorInterrupt.ino @@ -0,0 +1,134 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file CM32181_LightSensorInterrupt.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-13 + * + */ +#include +#include +#include +#include "SensorCM32181.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 39 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 40 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 1 +#endif + +SensorCM32181 light; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + if (!light.begin(Wire, CM32181_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find CM32181 - check your wiring!"); + while (1) { + delay(1000); + } + } + + Serial.println("Init CM32181 Sensor success!"); + + int id = light.getChipID(); + Serial.print("CM32181 ID = "); Serial.println(id); + + /* + Sensitivity mode selection + SAMPLING_X1 + SAMPLING_X2 + SAMPLING_X1_8 + SAMPLING_X1_4 + */ + light.setSampling(SensorCM32181::SAMPLING_X2, + SensorCM32181::INTEGRATION_TIME_400MS + ); + + // Set high and low thresholds. If the threshold is higher or lower than the set threshold, an interrupt will be triggered. + uint16_t lowThresholdRaw = 100; + uint16_t highThresholdRaw = 250; + light.setIntThreshold(lowThresholdRaw, highThresholdRaw); + + //Power On sensor + light.powerOn(); + + // Turn on interrupt + light.enableINT(); +} + + +void loop() +{ + int pinVal = digitalRead(SENSOR_IRQ) ; + if (pinVal == LOW) { + + // After triggering the interrupt, the interrupt status must be read + SensorCM32181::InterruptEvent event = light.getIrqStatus(); + + // Turn off interrupts + light.disableINT(); + + // Get Status + switch (event) { + case SensorCM32181::ALS_EVENT_LOW_TRIGGER: + Serial.println("Low interrupt event"); + break; + case SensorCM32181::ALS_EVENT_HIGH_TRIGGER: + Serial.println("High interrupt event"); + break; + default: + Serial.println("This is an impossible place to reach"); + break; + } + + // Get raw data + uint16_t raw = light.getRaw(); + + // Get conversion data , The manual does not provide information on how to obtain the + // calibration value, now use the calibration value 0.28 provided by the manual + float lux = light.getLux(); + Serial.printf("IRQ:%d RAW:%u Lux:%.2f\n", pinVal, raw, lux); + + + // Turn on interrupts + light.enableINT(); + } + + delay(800); +} + + + diff --git a/lib/SensorLib/examples/DRV2605_Basic/DRV2605_Basic.ino b/lib/SensorLib/examples/DRV2605_Basic/DRV2605_Basic.ino new file mode 100644 index 0000000..194e244 --- /dev/null +++ b/lib/SensorLib/examples/DRV2605_Basic/DRV2605_Basic.ino @@ -0,0 +1,468 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file DRV2605_Basic.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-03 + * + */ +#include +#include +#include +#include "SensorDRV2605.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 21 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 22 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 39 +#endif + +SensorDRV2605 drv; + +uint8_t effect = 1; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT); + + if (!drv.begin(Wire, DRV2605_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find DRV2605 - check your wiring!"); + while (1) { + delay(1000); + } + } + Serial.println("Init DRV2605 Sensor success!"); + + + drv.selectLibrary(1); + + // I2C trigger by sending 'run' command + // default, internal trigger when sending RUN command + drv.setMode(DRV2605_MODE_INTTRIG); +} + + +void loop() +{ + Serial.print("Effect #"); Serial.println(effect); + + if (effect == 1) { + Serial.println("11.2 Waveform Library Effects List"); + } + + if (effect == 1) { + Serial.println(F("1 - Strong Click - 100%")); + } + if (effect == 2) { + Serial.println(F("2 - Strong Click - 60%")); + } + if (effect == 3) { + Serial.println(F("3 - Strong Click - 30%")); + } + if (effect == 4) { + Serial.println(F("4 - Sharp Click - 100%")); + } + if (effect == 5) { + Serial.println(F("5 - Sharp Click - 60%")); + } + if (effect == 6) { + Serial.println(F("6 - Sharp Click - 30%")); + } + if (effect == 7) { + Serial.println(F("7 - Soft Bump - 100%")); + } + if (effect == 8) { + Serial.println(F("8 - Soft Bump - 60%")); + } + if (effect == 9) { + Serial.println(F("9 - Soft Bump - 30%")); + } + if (effect == 10) { + Serial.println(F("10 - Double Click - 100%")); + } + if (effect == 11) { + Serial.println(F("11 - Double Click - 60%")); + } + if (effect == 12) { + Serial.println(F("12 - Triple Click - 100%")); + } + if (effect == 13) { + Serial.println(F("13 - Soft Fuzz - 60%")); + } + if (effect == 14) { + Serial.println(F("14 - Strong Buzz - 100%")); + } + if (effect == 15) { + Serial.println(F("15 - 750 ms Alert 100%")); + } + if (effect == 16) { + Serial.println(F("16 - 1000 ms Alert 100%")); + } + if (effect == 17) { + Serial.println(F("17 - Strong Click 1 - 100%")); + } + if (effect == 18) { + Serial.println(F("18 - Strong Click 2 - 80%")); + } + if (effect == 19) { + Serial.println(F("19 - Strong Click 3 - 60%")); + } + if (effect == 20) { + Serial.println(F("20 - Strong Click 4 - 30%")); + } + if (effect == 21) { + Serial.println(F("21 - Medium Click 1 - 100%")); + } + if (effect == 22) { + Serial.println(F("22 - Medium Click 2 - 80%")); + } + if (effect == 23) { + Serial.println(F("23 - Medium Click 3 - 60%")); + } + if (effect == 24) { + Serial.println(F("24 - Sharp Tick 1 - 100%")); + } + if (effect == 25) { + Serial.println(F("25 - Sharp Tick 2 - 80%")); + } + if (effect == 26) { + Serial.println(F("26 - Sharp Tick 3 - 60%")); + } + if (effect == 27) { + Serial.println(F("27 - Short Double Click Strong 1 - 100%")); + } + if (effect == 28) { + Serial.println(F("28 - Short Double Click Strong 2 - 80%")); + } + if (effect == 29) { + Serial.println(F("29 - Short Double Click Strong 3 - 60%")); + } + if (effect == 30) { + Serial.println(F("30 - Short Double Click Strong 4 - 30%")); + } + if (effect == 31) { + Serial.println(F("31 - Short Double Click Medium 1 - 100%")); + } + if (effect == 32) { + Serial.println(F("32 - Short Double Click Medium 2 - 80%")); + } + if (effect == 33) { + Serial.println(F("33 - Short Double Click Medium 3 - 60%")); + } + if (effect == 34) { + Serial.println(F("34 - Short Double Sharp Tick 1 - 100%")); + } + if (effect == 35) { + Serial.println(F("35 - Short Double Sharp Tick 2 - 80%")); + } + if (effect == 36) { + Serial.println(F("36 - Short Double Sharp Tick 3 - 60%")); + } + if (effect == 37) { + Serial.println(F("37 - Long Double Sharp Click Strong 1 - 100%")); + } + if (effect == 38) { + Serial.println(F("38 - Long Double Sharp Click Strong 2 - 80%")); + } + if (effect == 39) { + Serial.println(F("39 - Long Double Sharp Click Strong 3 - 60%")); + } + if (effect == 40) { + Serial.println(F("40 - Long Double Sharp Click Strong 4 - 30%")); + } + if (effect == 41) { + Serial.println(F("41 - Long Double Sharp Click Medium 1 - 100%")); + } + if (effect == 42) { + Serial.println(F("42 - Long Double Sharp Click Medium 2 - 80%")); + } + if (effect == 43) { + Serial.println(F("43 - Long Double Sharp Click Medium 3 - 60%")); + } + if (effect == 44) { + Serial.println(F("44 - Long Double Sharp Tick 1 - 100%")); + } + if (effect == 45) { + Serial.println(F("45 - Long Double Sharp Tick 2 - 80%")); + } + if (effect == 46) { + Serial.println(F("46 - Long Double Sharp Tick 3 - 60%")); + } + if (effect == 47) { + Serial.println(F("47 - Buzz 1 - 100%")); + } + if (effect == 48) { + Serial.println(F("48 - Buzz 2 - 80%")); + } + if (effect == 49) { + Serial.println(F("49 - Buzz 3 - 60%")); + } + if (effect == 50) { + Serial.println(F("50 - Buzz 4 - 40%")); + } + if (effect == 51) { + Serial.println(F("51 - Buzz 5 - 20%")); + } + if (effect == 52) { + Serial.println(F("52 - Pulsing Strong 1 - 100%")); + } + if (effect == 53) { + Serial.println(F("53 - Pulsing Strong 2 - 60%")); + } + if (effect == 54) { + Serial.println(F("54 - Pulsing Medium 1 - 100%")); + } + if (effect == 55) { + Serial.println(F("55 - Pulsing Medium 2 - 60%")); + } + if (effect == 56) { + Serial.println(F("56 - Pulsing Sharp 1 - 100%")); + } + if (effect == 57) { + Serial.println(F("57 - Pulsing Sharp 2 - 60%")); + } + if (effect == 58) { + Serial.println(F("58 - Transition Click 1 - 100%")); + } + if (effect == 59) { + Serial.println(F("59 - Transition Click 2 - 80%")); + } + if (effect == 60) { + Serial.println(F("60 - Transition Click 3 - 60%")); + } + if (effect == 61) { + Serial.println(F("61 - Transition Click 4 - 40%")); + } + if (effect == 62) { + Serial.println(F("62 - Transition Click 5 - 20%")); + } + if (effect == 63) { + Serial.println(F("63 - Transition Click 6 - 10%")); + } + if (effect == 64) { + Serial.println(F("64 - Transition Hum 1 - 100%")); + } + if (effect == 65) { + Serial.println(F("65 - Transition Hum 2 - 80%")); + } + if (effect == 66) { + Serial.println(F("66 - Transition Hum 3 - 60%")); + } + if (effect == 67) { + Serial.println(F("67 - Transition Hum 4 - 40%")); + } + if (effect == 68) { + Serial.println(F("68 - Transition Hum 5 - 20%")); + } + if (effect == 69) { + Serial.println(F("69 - Transition Hum 6 - 10%")); + } + if (effect == 70) { + Serial.println(F("70 - Transition Ramp Down Long Smooth 1 - 100 to 0%")); + } + if (effect == 71) { + Serial.println(F("71 - Transition Ramp Down Long Smooth 2 - 100 to 0%")); + } + if (effect == 72) { + Serial.println(F("72 - Transition Ramp Down Medium Smooth 1 - 100 to 0%")); + } + if (effect == 73) { + Serial.println(F("73 - Transition Ramp Down Medium Smooth 2 - 100 to 0%")); + } + if (effect == 74) { + Serial.println(F("74 - Transition Ramp Down Short Smooth 1 - 100 to 0%")); + } + if (effect == 75) { + Serial.println(F("75 - Transition Ramp Down Short Smooth 2 - 100 to 0%")); + } + if (effect == 76) { + Serial.println(F("76 - Transition Ramp Down Long Sharp 1 - 100 to 0%")); + } + if (effect == 77) { + Serial.println(F("77 - Transition Ramp Down Long Sharp 2 - 100 to 0%")); + } + if (effect == 78) { + Serial.println(F("78 - Transition Ramp Down Medium Sharp 1 - 100 to 0%")); + } + if (effect == 79) { + Serial.println(F("79 - Transition Ramp Down Medium Sharp 2 - 100 to 0%")); + } + if (effect == 80) { + Serial.println(F("80 - Transition Ramp Down Short Sharp 1 - 100 to 0%")); + } + if (effect == 81) { + Serial.println(F("81 - Transition Ramp Down Short Sharp 2 - 100 to 0%")); + } + if (effect == 82) { + Serial.println(F("82 - Transition Ramp Up Long Smooth 1 - 0 to 100%")); + } + if (effect == 83) { + Serial.println(F("83 - Transition Ramp Up Long Smooth 2 - 0 to 100%")); + } + if (effect == 84) { + Serial.println(F("84 - Transition Ramp Up Medium Smooth 1 - 0 to 100%")); + } + if (effect == 85) { + Serial.println(F("85 - Transition Ramp Up Medium Smooth 2 - 0 to 100%")); + } + if (effect == 86) { + Serial.println(F("86 - Transition Ramp Up Short Smooth 1 - 0 to 100%")); + } + if (effect == 87) { + Serial.println(F("87 - Transition Ramp Up Short Smooth 2 - 0 to 100%")); + } + if (effect == 88) { + Serial.println(F("88 - Transition Ramp Up Long Sharp 1 - 0 to 100%")); + } + if (effect == 89) { + Serial.println(F("89 - Transition Ramp Up Long Sharp 2 - 0 to 100%")); + } + if (effect == 90) { + Serial.println(F("90 - Transition Ramp Up Medium Sharp 1 - 0 to 100%")); + } + if (effect == 91) { + Serial.println(F("91 - Transition Ramp Up Medium Sharp 2 - 0 to 100%")); + } + if (effect == 92) { + Serial.println(F("92 - Transition Ramp Up Short Sharp 1 - 0 to 100%")); + } + if (effect == 93) { + Serial.println(F("93 - Transition Ramp Up Short Sharp 2 - 0 to 100%")); + } + if (effect == 94) { + Serial.println(F("94 - Transition Ramp Down Long Smooth 1 - 50 to 0%")); + } + if (effect == 95) { + Serial.println(F("95 - Transition Ramp Down Long Smooth 2 - 50 to 0%")); + } + if (effect == 96) { + Serial.println(F("96 - Transition Ramp Down Medium Smooth 1 - 50 to 0%")); + } + if (effect == 97) { + Serial.println(F("97 - Transition Ramp Down Medium Smooth 2 - 50 to 0%")); + } + if (effect == 98) { + Serial.println(F("98 - Transition Ramp Down Short Smooth 1 - 50 to 0%")); + } + if (effect == 99) { + Serial.println(F("99 - Transition Ramp Down Short Smooth 2 - 50 to 0%")); + } + if (effect == 100) { + Serial.println(F("100 - Transition Ramp Down Long Sharp 1 - 50 to 0%")); + } + if (effect == 101) { + Serial.println(F("101 - Transition Ramp Down Long Sharp 2 - 50 to 0%")); + } + if (effect == 102) { + Serial.println(F("102 - Transition Ramp Down Medium Sharp 1 - 50 to 0%")); + } + if (effect == 103) { + Serial.println(F("103 - Transition Ramp Down Medium Sharp 2 - 50 to 0%")); + } + if (effect == 104) { + Serial.println(F("104 - Transition Ramp Down Short Sharp 1 - 50 to 0%")); + } + if (effect == 105) { + Serial.println(F("105 - Transition Ramp Down Short Sharp 2 - 50 to 0%")); + } + if (effect == 106) { + Serial.println(F("106 - Transition Ramp Up Long Smooth 1 - 0 to 50%")); + } + if (effect == 107) { + Serial.println(F("107 - Transition Ramp Up Long Smooth 2 - 0 to 50%")); + } + if (effect == 108) { + Serial.println(F("108 - Transition Ramp Up Medium Smooth 1 - 0 to 50%")); + } + if (effect == 109) { + Serial.println(F("109 - Transition Ramp Up Medium Smooth 2 - 0 to 50%")); + } + if (effect == 110) { + Serial.println(F("110 - Transition Ramp Up Short Smooth 1 - 0 to 50%")); + } + if (effect == 111) { + Serial.println(F("111 - Transition Ramp Up Short Smooth 2 - 0 to 50%")); + } + if (effect == 112) { + Serial.println(F("112 - Transition Ramp Up Long Sharp 1 - 0 to 50%")); + } + if (effect == 113) { + Serial.println(F("113 - Transition Ramp Up Long Sharp 2 - 0 to 50%")); + } + if (effect == 114) { + Serial.println(F("114 - Transition Ramp Up Medium Sharp 1 - 0 to 50%")); + } + if (effect == 115) { + Serial.println(F("115 - Transition Ramp Up Medium Sharp 2 - 0 to 50%")); + } + if (effect == 116) { + Serial.println(F("116 - Transition Ramp Up Short Sharp 1 - 0 to 50%")); + } + if (effect == 117) { + Serial.println(F("117 - Transition Ramp Up Short Sharp 2 - 0 to 50%")); + } + if (effect == 118) { + Serial.println(F("118 - Long buzz for programmatic stopping - 100%")); + } + if (effect == 119) { + Serial.println(F("119 - Smooth Hum 1 (No kick or brake pulse) - 50%")); + } + if (effect == 120) { + Serial.println(F("120 - Smooth Hum 2 (No kick or brake pulse) - 40%")); + } + if (effect == 121) { + Serial.println(F("121 - Smooth Hum 3 (No kick or brake pulse) - 30%")); + } + if (effect == 122) { + Serial.println(F("122 - Smooth Hum 4 (No kick or brake pulse) - 20%")); + } + if (effect == 123) { + Serial.println(F("123 - Smooth Hum 5 (No kick or brake pulse) - 10%")); + } + + // set the effect to play + drv.setWaveform(0, effect); // play effect + drv.setWaveform(1, 0); // end waveform + + // play the effect! + drv.run(); + + // wait a bit + delay(500); + + effect++; + if (effect > 117) effect = 1; +} + + + diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/CMakeLists.txt b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/CMakeLists.txt new file mode 100644 index 0000000..f023400 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS ../../../SensorLib) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ESP_IDF_TouchDrv_Example) diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/Makefile b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/Makefile new file mode 100644 index 0000000..431bec3 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/Makefile @@ -0,0 +1,10 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := ESP_IDF_TouchDrv_Example + +EXTRA_COMPONENT_DIRS = ../../../SensorLib + +include $(IDF_PATH)/make/project.mk diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/README.md b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/README.md new file mode 100644 index 0000000..05788b2 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/README.md @@ -0,0 +1,181 @@ +# ESP_IDF_TouchDrv_Example + +``` +The current example only writes the CSTxxx series touch application. +The other sensors have not been added, but the methods are the same. +``` + + +### Configure the Project + +Open the project configuration menu (`idf.py menuconfig`). + + +In the `SensorLib Example Configuration` menu: + +* Select the PMU Type in the `SensorLib read and write methods` option,Choose according to the situation + 1. Implemented using built-in read and write methods (Read and write methods are provided internally by SensorLib, supporting high version esp-idf >= 5.0, and low version methods (< 5.0)) + 2. Implemented using read and write callback methods (Implemented using externally provided methods, suitable for multiple platforms) +* In `Sensor SCL GPIO Num` select the clock pin to connect to the PMU,the default is 17 +* In `Sensor SDA GPIO Num` select the data pin connected to the PMU,the default is 18 +* Select the interrupt pin connected to the PMU in `Sensor Interrupt Pin`, the default is 16 +* Select `Sensor reset Pin` , the default is 21 +* `Master Frequency` The maximum communication frequency defaults to 100000HZ, and you can decide whether to change it according to the situation. + +## How to Use Example + +Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. default use **esp32s3** + + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +The output information is to configure the output voltage and enable status of the PMU + +``` +ESP-ROM:esp32s3-20210327 +Build:Mar 27 2021 +rst:0x15 (USB_UART_CHIP_RESET),boot:0xa (SPI_FAST_FLASH_BOOT) +Saved PC:0x403788f6 +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3fce3810,len:0x178c +load:0x403c9700,len:0x4 +load:0x403c9704,len:0xbfc +load:0x403cc700,len:0x2d64 +entry 0x403c9900 +I (26) boot: ESP-IDF v5.3-dev-1288-g5524b692ee 2nd stage bootloader +I (27) boot: compile time Jan 10 2024 22:49:17 +I (27) boot: Multicore bootloader +I (31) boot: chip revision: v0.2 +I (35) boot.esp32s3: Boot SPI Speed : 80MHz +I (40) boot.esp32s3: SPI Mode : DIO +I (45) boot.esp32s3: SPI Flash Size : 2MB +I (49) boot: Enabling RNG early entropy source... +I (55) boot: Partition Table: +I (58) boot: ## Label Usage Type ST Offset Length +I (66) boot: 0 nvs WiFi data 01 02 00009000 00006000 +I (73) boot: 1 phy_init RF data 01 01 0000f000 00001000 +I (81) boot: 2 factory factory app 00 00 00010000 00100000 +I (88) boot: End of partition table +I (92) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=0e0dch ( 57564) map +I (111) esp_image: segment 1: paddr=0001e104 vaddr=3fc93100 size=01f14h ( 7956) load +I (113) esp_image: segment 2: paddr=00020020 vaddr=42000020 size=1acb0h (109744) map +I (137) esp_image: segment 3: paddr=0003acd8 vaddr=3fc95014 size=00994h ( 2452) load +I (138) esp_image: segment 4: paddr=0003b674 vaddr=40374000 size=0f0e0h ( 61664) load +I (163) boot: Loaded app from partition at offset 0x10000 +I (163) boot: Disabling RNG early entropy source... +I (163) cpu_start: Multicore app +I (176) cpu_start: Pro cpu start user code +I (176) cpu_start: cpu freq: 240000000 Hz +I (177) cpu_start: Application information: +I (177) cpu_start: Project name: ESP_IDF_TouchDrv_Example +I (177) cpu_start: App version: v0.1.4-6-gfeaf675-dirty +I (177) cpu_start: Compile time: Jan 11 2024 14:01:31 +I (177) cpu_start: ELF file SHA256: 3ce1527fc... +I (178) cpu_start: ESP-IDF: v5.3-dev-1288-g5524b692ee +I (178) cpu_start: Min chip rev: v0.0 +I (178) cpu_start: Max chip rev: v0.99 +I (178) cpu_start: Chip rev: v0.2 +I (178) heap_init: Initializing. RAM available for dynamic allocation: +I (179) heap_init: At 3FC96290 len 00053480 (333 KiB): RAM +I (179) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM +I (179) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM +I (180) heap_init: At 600FE010 len 00001FD8 (7 KiB): RTCRAM +I (181) spi_flash: detected chip: winbond +I (181) spi_flash: flash io: dio +W (181) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header. +W (181) i2c: This driver is an old driver, please migrate your application code to adapt `driver/i2c_master.h` +I (182) sleep: Configure to isolate all GPIO pins in sleep state +I (182) sleep: Enable automatic switching of GPIO sleep configuration +I (183) main_task: Started on CPU0 +I (193) main_task: Calling app_main() +I (193) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2 +I (193) I2C: Implemented using read and write callback methods (Use lower version < 5.0 API) +I (193) mian: I2C initialized successfully +I (193) TOUCH: ----touch_drv_init---- +0 1 2 3 4 5 6 7 8 9 a b c d e f +00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +10: -- -- -- -- -- 15 -- -- -- -- -- -- -- -- -- -- +20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +I (303) TOUCH: Find touch address 0x15 +I (303) TOUCH: Find touch address 0x15 +I (303) TOUCH: Implemented using built-in read and write methods (Use lower version < 5.0 API) +Using ESP-IDF Driver interface. +E (303) i2c: i2c driver install error +I (303) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 +I (303) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 +Chip ID:0xb5 +Version :0x2 +Touch type:CST816T +I (383) TOUCH: Init touch SUCCESS! +I (383) TOUCH: Some CST816 will automatically enter sleep,can use the touch.disableAutoSleep() to turn off +I (383) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 +I (513) mian: Run... +I (513) main_task: Returned from app_main() +X[0]:143 Y[0]:127 +X[0]:143 Y[0]:127 +X[0]:142 Y[0]:127 +X[0]:141 Y[0]:126 +X[0]:138 Y[0]:125 +X[0]:135 Y[0]:123 +X[0]:131 Y[0]:121 +X[0]:126 Y[0]:119 +X[0]:121 Y[0]:117 +X[0]:84 Y[0]:146 +X[0]:85 Y[0]:146 +X[0]:86 Y[0]:145 +X[0]:87 Y[0]:143 +X[0]:88 Y[0]:140 +X[0]:89 Y[0]:136 +X[0]:90 Y[0]:132 +X[0]:91 Y[0]:127 +X[0]:92 Y[0]:123 +X[0]:93 Y[0]:119 +X[0]:94 Y[0]:115 +X[0]:95 Y[0]:111 +I (513563) TOUCH: Touch Home button pressed! +I (513573) TOUCH: Touch Home button pressed! +I (513583) TOUCH: Touch Home button pressed! +I (513603) TOUCH: Touch Home button pressed! +I (513613) TOUCH: Touch Home button pressed! +I (513633) TOUCH: Touch Home button pressed! +I (513643) TOUCH: Touch Home button pressed! +``` + +## Build process example + +Assuming you don't have esp-idf yet + +``` +mkdir -p ~/esp +cd ~/esp +git clone --recursive https://github.com/espressif/esp-idf.git +git clone https://github.com/lewisxhe/XPowersLib.git +cd esp-idf +./install.sh +. ./export.sh +cd .. +cd SensorLib/examples/ESP_IDF_Example + +Configure SDA,SCL,INT,RST,Pin +... + +idf.py menuconfig +idf.py build +idf.py -b 921600 flash +idf.py monitor + +``` \ No newline at end of file diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/CMakeLists.txt b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/CMakeLists.txt new file mode 100644 index 0000000..128fbec --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register(SRCS + "touch_drv.cpp" + "i2c_driver.cpp" + "main.cpp" + INCLUDE_DIRS ".") diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/Kconfig.projbuild b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/Kconfig.projbuild new file mode 100644 index 0000000..cccfbd5 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/Kconfig.projbuild @@ -0,0 +1,52 @@ +menu "SensorLib Example Configuration" + + choice I2C_COMMUNICATION_METHOD + prompt "SensorLib read and write methods" + default I2C_COMMUNICATION_METHOD_BUILTIN_RW + help + Define SensorLib read and write methods + + config I2C_COMMUNICATION_METHOD_BUILTIN_RW + bool "Implemented using built-in read and write methods" + config I2C_COMMUNICATION_METHOD_CALLBACK_RW + bool "Implemented using read and write callback methods" + endchoice + + config I2C_MASTER_PORT_NUM + int "Sensor I2C Port Number" + default 1 + help + Port number for I2C Master device. + + config I2C_MASTER_FREQUENCY + int "Master Frequency" + default 100000 + help + I2C Speed of Master device. + + config SENSOR_SCL + int "Sensor SCL GPIO Num" + default 17 + help + GPIO number for I2C clock line. + + config SENSOR_SDA + int "Sensor SDA GPIO Num" + default 18 + help + GPIO number for I2C data line. + + config SENSOR_IRQ + int "Sensor Interrupt Pin" + default 16 + help + Sensor interrupt pin. + + config SENSOR_RST + int "Sensor reset Pin" + default 21 + help + Sensor reset pin. + + +endmenu diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/component.mk b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/component.mk new file mode 100644 index 0000000..a98f634 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.cpp b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.cpp new file mode 100644 index 0000000..b444fa4 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.cpp @@ -0,0 +1,253 @@ +/** + * @file port_i2c.cpp + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd + * @date 2024-01-10 + * + */ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include "sdkconfig.h" +#include "i2c_driver.h" + +static const char *TAG = "I2C"; + +#define I2C_MASTER_NUM (i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM +#define I2C_MASTER_SDA_IO (gpio_num_t)CONFIG_SENSOR_SDA +#define I2C_MASTER_SCL_IO (gpio_num_t)CONFIG_SENSOR_SCL +#define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY /*!< I2C master clock frequency */ +#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ + +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) +#include "soc/clk_tree_defs.h" + +i2c_master_dev_handle_t i2c_device; + +// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle, +// * which is useful when the bus shares multiple devices. +i2c_master_bus_handle_t bus_handle; +#endif + + +#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW + +/** + * @brief Read a sequence of bytes from a pmu registers + */ +int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len) +{ + esp_err_t ret; + if (len == 0) { + return ESP_OK; + } + if (data == NULL) { + return ESP_FAIL; + } + +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) + + ret = i2c_master_transmit_receive( + i2c_device, + (const uint8_t *)®Addr, + 1, + data, + len, + -1); +#else + + i2c_cmd_handle_t cmd; + + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, regAddr, true); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000)); + i2c_cmd_link_delete(cmd); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "PMU i2c_master_cmd_begin FAILED! > "); + return ESP_FAIL; + } + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_READ, true); + if (len > 1) { + i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK); + } + i2c_master_read_byte(cmd, &data[len - 1], I2C_MASTER_NACK); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000)); + i2c_cmd_link_delete(cmd); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "i2c_read_error."); + } +#endif + return ret == ESP_OK ? 0 : -1; +} + +/** + * @brief Write a byte to a pmu register + */ +int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len) +{ + esp_err_t ret; + if (data == NULL) { + return ESP_FAIL; + } + +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) + uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (len + 1)); + if (!write_buffer) { + return -1; + } + write_buffer[0] = regAddr; + memcpy(write_buffer + 1, data, len); + + ret = i2c_master_transmit( + i2c_device, + write_buffer, + len + 1, + -1); + free(write_buffer); +#else + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, regAddr, true); + i2c_master_write(cmd, data, len, true); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000)); + i2c_cmd_link_delete(cmd); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "i2c_write_error."); + } +#endif + return ret == ESP_OK ? 0 : -1; +} + +esp_err_t i2c_drv_device_init(uint8_t address) +{ +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) + i2c_device_config_t i2c_dev_conf = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = address, + .scl_speed_hz = I2C_MASTER_FREQ_HZ, + }; + return i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &i2c_device); +#else + return ESP_OK; +#endif +} + +#endif //CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW + + +/** + * @brief i2c master initialization + */ +esp_err_t i2c_drv_init(void) +{ +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) + + ESP_LOGI(TAG, "Implemented using read and write callback methods (Use higher version >= 5.0 API)"); + + i2c_master_bus_config_t i2c_bus_config; + memset(&i2c_bus_config, 0, sizeof(i2c_bus_config)); + i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT; + i2c_bus_config.i2c_port = I2C_MASTER_NUM; + i2c_bus_config.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO; + i2c_bus_config.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO; + i2c_bus_config.glitch_ignore_cnt = 7; + + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle)); + + return ESP_OK; +#else + + ESP_LOGI(TAG, "Implemented using read and write callback methods (Use lower version < 5.0 API)"); + + i2c_config_t i2c_conf ; + memset(&i2c_conf, 0, sizeof(i2c_conf)); + i2c_conf.mode = I2C_MODE_MASTER; + i2c_conf.sda_io_num = I2C_MASTER_SDA_IO; + i2c_conf.scl_io_num = I2C_MASTER_SCL_IO; + i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + i2c_conf.master.clk_speed = I2C_MASTER_FREQ_HZ; + i2c_param_config(I2C_MASTER_NUM, &i2c_conf); + return i2c_driver_install(I2C_MASTER_NUM, i2c_conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); +#endif +} + +void i2c_drv_scan() +{ +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) + + esp_err_t err = ESP_OK; + uint8_t address = 0x00; + printf("Scand I2C Devices:\n"); + printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); + for (int i = 0; i < 128; i += 16) { + printf("%02x: ", i); + for (int j = 0; j < 16; j++) { + fflush(stdout); + address = i + j; + err = i2c_master_probe(bus_handle, address, 1000); + if (err == ESP_OK) { + printf("%02x ", address); + } else if (err == ESP_ERR_TIMEOUT) { + printf("UU "); + } else { + printf("-- "); + } + } + printf("\r\n"); + } + printf("\n\n\n"); +#else + uint8_t address; + printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); + for (int i = 0; i < 128; i += 16) { + printf("%02x: ", i); + for (int j = 0; j < 16; j++) { + fflush(stdout); + address = i + j; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true); + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS); + i2c_cmd_link_delete(cmd); + if (ret == ESP_OK) { + printf("%02x ", address); + } else if (ret == ESP_ERR_TIMEOUT) { + printf("UU "); + } else { + printf("-- "); + } + } + printf("\r\n"); + } +#endif +} + +bool i2c_drv_probe(uint8_t devAddr) +{ +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) + return ESP_OK == i2c_master_probe(bus_handle, devAddr, 1000); +#else + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true); + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS); + i2c_cmd_link_delete(cmd); + return (ret == ESP_OK); +#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) +} + diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.h b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.h new file mode 100644 index 0000000..8f13b48 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/i2c_driver.h @@ -0,0 +1,32 @@ +/** + * @file i2c_driver.h + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd + * @date 2024-01-10 + * + */ +#pragma once + +#include "esp_err.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "esp_idf_version.h" +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) +#include "driver/i2c_master.h" +#else +#include "driver/i2c.h" +#endif //ESP_IDF_VERSION + + +esp_err_t i2c_drv_init(void); +void i2c_drv_scan(); +bool i2c_drv_probe(uint8_t devAddr); +int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len); +int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len); + +#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW +esp_err_t i2c_drv_device_init(uint8_t address); +#endif + + diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/main.cpp b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/main.cpp new file mode 100644 index 0000000..b837b84 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/main/main.cpp @@ -0,0 +1,83 @@ +/** + * @file main.cpp + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd + * @date 2024-01-10 + * + */ +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "freertos/queue.h" +#include "i2c_driver.h" + +#define SENSOR_INPUT_PIN (gpio_num_t)CONFIG_SENSOR_IRQ /*!< axp power chip interrupt Pin*/ +#define SENSOR_INPUT_PIN_SEL (1ULL<= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API) + + ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)"); + + // * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle, + // * which is useful when the bus shares multiple devices. + extern i2c_master_bus_handle_t bus_handle; + + if (touch.begin(bus_handle, address)) { + ESP_LOGI(TAG, "Init touch SUCCESS!"); + } else { + ESP_LOGE(TAG, "Init touch FAILED!"); + return false; + } + +#else + + ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)"); + if (touch.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, address, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) { + ESP_LOGI(TAG, "Init touch SUCCESS!"); + } else { + ESP_LOGE(TAG, "Init touch FAILED!"); + return false; + } +#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) +#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW + + const char *model = touch.getModelName(); + if (strncmp(model, "CST8", 3) == 0) { + ESP_LOGI(TAG, "Some CST816 will automatically enter sleep,can use the touch.disableAutoSleep() to turn off"); + // Some CST816 will automatically enter sleep, + // can use the touch.disableAutoSleep() to turn off + touch.disableAutoSleep(); + + /** + * Some touch screens have touch buttons, + * and the touch coordinates need to be given + * before the touch button callback function can be used. + */ + // Example touch coordinates using T-Display-S3 touch + touch.setCenterButtonCoordinate(85, 360); + + touch.setHomeButtonCallback(touch_home_button_callback); + } + + // Set the maximum valid coordinates + // touch.setMaxCoordinates(320, 170); + + // Swap XY coordinates + // touch.setSwapXY(true); + + // Mirror XY coordinates + // touch.setMirrorXY(false, true); + + return ESP_OK; +} + +static void touch_home_button_callback(void *user_data) +{ + ESP_LOGI(TAG, "Touch Home button pressed!"); +} + +void touch_drv_isr_handler() +{ + int16_t x[5], y[5]; + uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); + if (touched) { + for (int i = 0; i < touched; ++i) { + printf("X["); + printf("%d", i); + printf("]:"); + printf("%d", x[i]); + printf(" "); + printf(" Y["); + printf("%d", i); + printf("]:"); + printf("%d", y[i]); + printf(" "); + } + printf("\n"); + } +} + + diff --git a/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/sdkconfig.defaults b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/sdkconfig.defaults new file mode 100644 index 0000000..0061a57 --- /dev/null +++ b/lib/SensorLib/examples/ESP_IDF_TouchDrv_Example/sdkconfig.defaults @@ -0,0 +1,6 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 + diff --git a/lib/SensorLib/examples/LTR553ALS_Sensor/LTR553ALS_Sensor.ino b/lib/SensorLib/examples/LTR553ALS_Sensor/LTR553ALS_Sensor.ino new file mode 100644 index 0000000..fffd981 --- /dev/null +++ b/lib/SensorLib/examples/LTR553ALS_Sensor/LTR553ALS_Sensor.ino @@ -0,0 +1,193 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file LTR553ALS_Sensor.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-09 + * + */ +#include +#include +#include +#include "SensorLTR553.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 5 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 6 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 21 +#endif + +SensorLTR553 als; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + if (!als.begin(Wire, LTR553_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find LTR553 - check your wiring!"); + while (1) { + delay(1000); + } + } + + Serial.println("Init LTR553 Sensor success!"); + + // Set the ambient light high and low thresholds. + // If the value exceeds or falls below the set value, an interrupt will be triggered. + als.setLightSensorThreshold(10, 200); + + // Set the high and low thresholds of the proximity sensor. + // If the value exceeds or falls below the set value, an interrupt will be triggered. + als.setProximityThreshold(10, 30); + + // Controls the Light Sensor N number of times the measurement data is outside the range + // defined by the upper and lower threshold limits before asserting the interrupt. + als.setLightSensorPersists(5); + + // Controls the Proximity N number of times the measurement data is outside the range + // defined by the upper and lower threshold limits before asserting the interrupt. + als.setProximityPersists(5); + + /* + * ALS_IRQ_ACTIVE_LOW, // INT pin is considered active when it is a logic 0 (default) + * ALS_IRQ_ACTIVE_HIGH // INT pin is considered active when it is a logic 1 + * * */ + als.setIRQLevel(SensorLTR553::ALS_IRQ_ACTIVE_LOW); + + /* + * ALS_IRQ_ONLY_PS, // Only PS measurement can trigger interrupt + * ALS_IRQ_ONLY_ALS, // Only ALS measurement can trigger interrupt + * ALS_IRQ_BOTH, // Both ALS and PS measurement can trigger interrupt + * * * */ + als.enableIRQ(SensorLTR553::ALS_IRQ_BOTH); + + /* + * ALS_GAIN_1X , -> 1 lux to 64k lux (default) + * ALS_GAIN_2X , -> 0.5 lux to 32k lux + * ALS_GAIN_4X , -> 0.25 lux to 16k lux + * ALS_GAIN_8X , -> 0.125 lux to 8k lux + * ALS_GAIN_48X , -> 0.02 lux to 1.3k lux + * ALS_GAIN_96X , -> 0.01 lux to 600 lux + * */ + als.setLightSensorGain(SensorLTR553::ALS_GAIN_8X); + + /* + * PS_LED_PLUSE_30KHZ, + * PS_LED_PLUSE_40KHZ, + * PS_LED_PLUSE_50KHZ, + * PS_LED_PLUSE_60KHZ, + * PS_LED_PLUSE_70KHZ, + * PS_LED_PLUSE_80KHZ, + * PS_LED_PLUSE_90KHZ, + * PS_LED_PLUSE_100KHZ, + * * * * * * * * * * */ + als.setPsLedPulsePeriod(SensorLTR553::PS_LED_PLUSE_100KHZ); + + + /* + * PS_LED_DUTY_25, + * PS_LED_DUTY_50, + * PS_LED_DUTY_75, + * PS_LED_DUTY_100, + * * * */ + als.setPsLedDutyCycle(SensorLTR553::PS_LED_DUTY_100); + + + /* + * PS_LED_CUR_5MA, + * PS_LED_CUR_10MA, + * PS_LED_CUR_20MA, + * PS_LED_CUR_50MA, + * PS_LED_CUR_100MA, + * * * * * * * */ + als.setPsLedCurrnet(SensorLTR553::PS_LED_CUR_50MA); + + /* + * PS_MEAS_RATE_50MS, + * PS_MEAS_RATE_70MS, + * PS_MEAS_RATE_100MS, + * PS_MEAS_RATE_200MS, + * PS_MEAS_RATE_500MS, + * PS_MEAS_RATE_1000MS, + * PS_MEAS_RATE_2000MS, + * PS_MEAS_RATE_10MS + * * * * * * * */ + als.setProximityRate(SensorLTR553::PS_MEAS_RATE_200MS); + + // Number of pulses + als.setPsLedPulses(1); + + // Enable proximity sensor saturation indication + als.enablePsIndicator(); + + // Enable ambient light sensor + als.enableLightSensor(); + + // Enable proximity sensor + als.enableProximity(); + +} + +bool canRead() +{ +#if SENSOR_IRQ != -1 + return digitalRead(SENSOR_IRQ) == LOW; +#else + static uint32_t lastReadMillis; + if (millis() > lastReadMillis) { + lastReadMillis = millis() + 500; + return true; + } + return false; +#endif +} + +void loop() +{ + /* + * PS Saturation Flag is used for monitoring the internal IC saturation. + * It will be flagged when the IC has reached saturation + * and not able to perform any further PS measurement + * */ + bool saturated = false; + if (canRead()) { + Serial.print(" ALS: CH1:"); Serial.print(als.getLightSensor(1)); + Serial.print(" - CH0:"); Serial.print(als.getLightSensor(0)); + Serial.print(" - PS:"); Serial.print(als.getProximity(&saturated)); + Serial.print(" - "); Serial.println(saturated ? "PS saturated" : "PS not saturated"); + } + delay(5); +} + + + diff --git a/lib/SensorLib/examples/PCF85063_AlarmByUnits/PCF85063_AlarmByUnits.ino b/lib/SensorLib/examples/PCF85063_AlarmByUnits/PCF85063_AlarmByUnits.ino new file mode 100644 index 0000000..a84e014 --- /dev/null +++ b/lib/SensorLib/examples/PCF85063_AlarmByUnits/PCF85063_AlarmByUnits.ino @@ -0,0 +1,214 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file PCF85063_AlarmByUnits.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-12-11 + * + */ +#include +#include +#include +#include +#include "SensorPCF85063.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 4 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 5 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 14 +#endif + + +SensorPCF85063 rtc; + + +uint32_t lastMillis = 0; +uint8_t nextHour = 22; +uint8_t nextMonth = 1; +uint8_t nextDay = 1; +uint8_t nextMinute = 59; +uint8_t nextSecond = 20; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + if (!rtc.begin(Wire, PCF85063_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find PCF8563 - check your wiring!"); + while (1) { + delay(1000); + } + } + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + + nextSecond = 55; + + // First test alarm seconds + rtc.setAlarmBySecond(30); + + rtc.enableAlarm(); + +} + +void printDateTime() +{ + if (millis() - lastMillis > 1000) { + /** + /// Format output time* + Option: + DATETIME_FORMAT_HM + DATETIME_FORMAT_HMS + DATETIME_FORMAT_YYYY_MM_DD + DATETIME_FORMAT_MM_DD_YYYY + DATETIME_FORMAT_DD_MM_YYYY + DATETIME_FORMAT_YYYY_MM_DD_H_M_S + default: DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK + */ + Serial.println(rtc.strftime()); + + lastMillis = millis(); + } +} + +// Test seconds timing +void testAlarmSeconds() +{ + while (1) { + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.println("testAlarmSeconds Interrupt .... "); + if (rtc.isAlarmActive()) { + Serial.println("Alarm active"); + rtc.resetAlarm(); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + rtc.setAlarmByMinutes(0); + return; + } + } + printDateTime(); + } +} + + +// Test minute timing +void testAlarmMinute() +{ + while (1) { + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.println("testAlarmMinute Interrupt .... "); + if (rtc.isAlarmActive()) { + Serial.println("Alarm active"); + rtc.resetAlarm(); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + nextHour++; + if (nextHour >= 24) { + nextHour = 23; + nextDay = 25; + rtc.setAlarmByHours(0); + Serial.println("setAlarmByHours"); + return; + } + } + } + printDateTime(); + } +} + +// Test hour timing +void testAlarmHour() +{ + while (1) { + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.println("testAlarmHour Interrupt .... "); + if (rtc.isAlarmActive()) { + Serial.println("Alarm active"); + rtc.resetAlarm(); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + nextDay++; + if (nextDay >= 30) { + nextMonth = 1; + nextHour = 23; + nextMinute = 59; + nextSecond = 55; + nextDay = rtc.getDaysInMonth(nextMonth, 2022); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + rtc.setAlarmByDays(1); + Serial.println("setAlarmByDays"); + return; + } + } + } + printDateTime(); + } +} + +// Test day timing +void testAlarmDay() +{ + while (1) { + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.println("testAlarmDay Interrupt .... "); + if (rtc.isAlarmActive()) { + Serial.println("Alarm active"); + rtc.resetAlarm(); + nextDay = rtc.getDaysInMonth(nextMonth, 2022); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + nextMonth++; + if (nextMonth >= 12) { + return; + } + } + } + printDateTime(); + } +} + + + + +void loop() +{ + testAlarmSeconds(); + testAlarmMinute(); + testAlarmHour(); + testAlarmDay(); + + Serial.println("Test done ..."); + while (1) { + delay(100); + } +} + + + diff --git a/lib/SensorLib/examples/PCF85063_SimpleTime/PCF85063_SimpleTime.ino b/lib/SensorLib/examples/PCF85063_SimpleTime/PCF85063_SimpleTime.ino new file mode 100644 index 0000000..b476eae --- /dev/null +++ b/lib/SensorLib/examples/PCF85063_SimpleTime/PCF85063_SimpleTime.ino @@ -0,0 +1,92 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file PCF85063_SimpleTime.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-07 + * + */ +#include +#include +#include +#include "SensorPCF85063.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 7 +#endif + +SensorPCF85063 rtc; +uint32_t lastMillis; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + if (!rtc.begin(Wire, PCF85063_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find PCF8563 - check your wiring!"); + while (1) { + delay(1000); + } + } + + uint16_t year = 2023; + uint8_t month = 9; + uint8_t day = 7; + uint8_t hour = 11; + uint8_t minute = 24; + uint8_t second = 30; + + rtc.setDateTime(year, month, day, hour, minute, second); + +} + + +void loop() +{ + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + RTC_DateTime datetime = rtc.getDateTime(); + Serial.printf(" Year :"); Serial.print(datetime.year); + Serial.printf(" Month:"); Serial.print(datetime.month); + Serial.printf(" Day :"); Serial.print(datetime.day); + Serial.printf(" Hour:"); Serial.print(datetime.hour); + Serial.printf(" Minute:"); Serial.print(datetime.minute); + Serial.printf(" Sec :"); Serial.println(datetime.second); + + } +} + + + diff --git a/lib/SensorLib/examples/PCF8563_AlarmByUnits/PCF8563_AlarmByUnits.ino b/lib/SensorLib/examples/PCF8563_AlarmByUnits/PCF8563_AlarmByUnits.ino new file mode 100644 index 0000000..c905411 --- /dev/null +++ b/lib/SensorLib/examples/PCF8563_AlarmByUnits/PCF8563_AlarmByUnits.ino @@ -0,0 +1,193 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file PCF8563_AlarmByUnits.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-12-11 + * + */ +#include +#include +#include +#include +#include "SensorPCF8563.hpp" + +#ifdef ESP32 +#define SENSOR_SDA 42 +#define SENSOR_SCL 41 +#define SENSOR_IRQ 14 +#else +#define _PINNUM(port, pin) ((port)*32 + (pin)) +#define SENSOR_SDA _PINNUM(0,26) +#define SENSOR_SCL _PINNUM(0,27) +#define SENSOR_IRQ _PINNUM(0,16) +#endif + + +SensorPCF8563 rtc; + + +uint32_t lastMillis = 0; +uint8_t nextHour = 22; +uint8_t nextMonth = 1; +uint8_t nextDay = 1; +uint8_t nextMinute = 59; +uint8_t nextSecond = 55; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find PCF8563 - check your wiring!"); + while (1) { + delay(1000); + } + } + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + + // From minute timer + rtc.setAlarmByMinutes(0); + + rtc.enableAlarm(); + +} + +void printDateTime() +{ + if (millis() - lastMillis > 1000) { + /** + /// Format output time* + Option: + DATETIME_FORMAT_HM + DATETIME_FORMAT_HMS + DATETIME_FORMAT_YYYY_MM_DD + DATETIME_FORMAT_MM_DD_YYYY + DATETIME_FORMAT_DD_MM_YYYY + DATETIME_FORMAT_YYYY_MM_DD_H_M_S + default: DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK + */ + Serial.println(rtc.strftime()); + + lastMillis = millis(); + } +} + +// Test minute timing +void testAlarmMinute() +{ + while (1) { + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.println("testAlarmMinute Interrupt .... "); + if (rtc.isAlarmActive()) { + Serial.println("Alarm active"); + rtc.resetAlarm(); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + nextHour++; + if (nextHour >= 24) { + nextHour = 23; + nextDay = 25; + rtc.setAlarmByHours(0); + Serial.println("setAlarmByHours"); + return; + } + } + } + printDateTime(); + } +} + +// Test hour timing +void testAlarmHour() +{ + while (1) { + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.println("testAlarmHour Interrupt .... "); + if (rtc.isAlarmActive()) { + Serial.println("Alarm active"); + rtc.resetAlarm(); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + nextDay++; + if (nextDay >= 30) { + nextMonth = 1; + nextHour = 23; + nextMinute = 59; + nextSecond = 55; + nextDay = rtc.getDaysInMonth(nextMonth, 2022); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + rtc.setAlarmByDays(1); + Serial.println("setAlarmByDays"); + return; + } + } + } + printDateTime(); + } +} + +// Test day timing +void testAlarmDay() +{ + while (1) { + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.println("testAlarmDay Interrupt .... "); + if (rtc.isAlarmActive()) { + Serial.println("Alarm active"); + rtc.resetAlarm(); + nextDay = rtc.getDaysInMonth(nextMonth, 2022); + rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond); + nextMonth++; + if (nextMonth >= 12) { + return; + } + } + } + printDateTime(); + } +} + + + + +void loop() +{ + testAlarmMinute(); + testAlarmHour(); + testAlarmDay(); + + Serial.println("Test done ..."); + while (1) { + delay(100); + } +} + + + diff --git a/lib/SensorLib/examples/PCF8563_SimpleTime/PCF8563_SimpleTime.ino b/lib/SensorLib/examples/PCF8563_SimpleTime/PCF8563_SimpleTime.ino new file mode 100644 index 0000000..468a2a6 --- /dev/null +++ b/lib/SensorLib/examples/PCF8563_SimpleTime/PCF8563_SimpleTime.ino @@ -0,0 +1,87 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file PCF8563_SimpleTime.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-12-12 + * + */ +#include +#include +#include +#include "SensorPCF8563.hpp" + +// lilygo t-beam-s3-core pin +#define SENSOR_SDA 42 +#define SENSOR_SCL 41 +#define SENSOR_IRQ 14 + +SensorPCF8563 rtc; +uint32_t lastMillis; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find PCF8563 - check your wiring!"); + while (1) { + delay(1000); + } + } + + uint16_t year = 2022; + uint8_t month = 12; + uint8_t day = 12; + uint8_t hour = 21; + uint8_t minute = 00; + uint8_t second = 30; + + rtc.setDateTime(year, month, day, hour, minute, second); + +} + + +void loop() +{ + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + RTC_DateTime datetime = rtc.getDateTime(); + Serial.printf(" Year :"); Serial.print(datetime.year); + Serial.printf(" Month:"); Serial.print(datetime.month); + Serial.printf(" Day :"); Serial.print(datetime.day); + Serial.printf(" Hour:"); Serial.print(datetime.hour); + Serial.printf(" Minute:"); Serial.print(datetime.minute); + Serial.printf(" Sec :"); Serial.println(datetime.second); + + } +} + + + diff --git a/lib/SensorLib/examples/PCF8563_TimeLib/PCF8563_TimeLib.ino b/lib/SensorLib/examples/PCF8563_TimeLib/PCF8563_TimeLib.ino new file mode 100644 index 0000000..3cea9d9 --- /dev/null +++ b/lib/SensorLib/examples/PCF8563_TimeLib/PCF8563_TimeLib.ino @@ -0,0 +1,98 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file PCF8563_TimeLib.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-12-12 + * + */ +#include +#include +#include +#include "SensorPCF8563.hpp" +#include + +// lilygo t-beam-s3-core pin +#define SENSOR_SDA 42 +#define SENSOR_SCL 41 +#define SENSOR_IRQ 14 + +SensorPCF8563 rtc; +uint32_t lastMillis; +char buf[64]; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find PCF8563 - check your wiring!"); + while (1) { + delay(1000); + } + } + +} + + +void loop() +{ + if (millis() - lastMillis > 1000) { + + lastMillis = millis(); + + struct tm timeinfo; + // Get the time C library structure + rtc.getDateTime(&timeinfo); + + // Format the output using the strftime function + // For more formats, please refer to : + // https://man7.org/linux/man-pages/man3/strftime.3.html + + size_t written = strftime(buf, 64, "%A, %B %d %Y %H:%M:%S", &timeinfo); + + if (written != 0) { + Serial.println(buf); + } + + written = strftime(buf, 64, "%b %d %Y %H:%M:%S", &timeinfo); + if (written != 0) { + Serial.println(buf); + } + + + written = strftime(buf, 64, "%A, %d. %B %Y %I:%M%p", &timeinfo); + if (written != 0) { + Serial.println(buf); + } + } +} + + + diff --git a/lib/SensorLib/examples/PCF8563_TimeSynchronization/PCF8563_TimeSynchronization.ino b/lib/SensorLib/examples/PCF8563_TimeSynchronization/PCF8563_TimeSynchronization.ino new file mode 100644 index 0000000..a557959 --- /dev/null +++ b/lib/SensorLib/examples/PCF8563_TimeSynchronization/PCF8563_TimeSynchronization.ino @@ -0,0 +1,150 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file PCF8563_TimeSynchronization.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-12-12 + * + */ +#include +#include +#include +#include +#include +#include +#include "SensorPCF8563.hpp" + +// lilygo t-beam-s3-core pin +#define SENSOR_SDA 42 +#define SENSOR_SCL 41 +#define SENSOR_IRQ 14 + +const char *ssid = "YOUR_SSID"; +const char *password = "YOUR_PASS"; + +const char *ntpServer1 = "pool.ntp.org"; +const char *ntpServer2 = "time.nist.gov"; +const long gmtOffset_sec = 3600; +const int daylightOffset_sec = 3600; + +const char *time_zone = "CST-8"; // TimeZone rule for Europe/Rome including daylight adjustment rules (optional) + +SensorPCF8563 rtc; +uint32_t lastMillis; + + +// Callback function (get's called when time adjusts via NTP) +void timeavailable(struct timeval *t) +{ + Serial.println("Got time adjustment from NTP, Write the hardware clock"); + + // Write synchronization time to hardware + rtc.hwClockWrite(); +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + + if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find PCF8563 - check your wiring!"); + while (1) { + delay(1000); + } + } + + // set notification call-back function + sntp_set_time_sync_notification_cb( timeavailable ); + + /** + * NTP server address could be aquired via DHCP, + * + * NOTE: This call should be made BEFORE esp32 aquires IP address via DHCP, + * otherwise SNTP option 42 would be rejected by default. + * NOTE: configTime() function call if made AFTER DHCP-client run + * will OVERRIDE aquired NTP server address + */ + sntp_servermode_dhcp(1); // (optional) + + /** + * This will set configured ntp servers and constant TimeZone/daylightOffset + * should be OK if your time zone does not need to adjust daylightOffset twice a year, + * in such a case time adjustment won't be handled automagicaly. + */ + // configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2); + + /** + * A more convenient approach to handle TimeZones with daylightOffset + * would be to specify a environmnet variable with TimeZone definition including daylight adjustmnet rules. + * A list of rules for your zone could be obtained from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h + */ + configTzTime(time_zone, ntpServer1, ntpServer2); + + //connect to WiFi + Serial.printf("Connecting to %s ", ssid); + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(" CONNECTED"); + +} + + + + +void loop() +{ + if (millis() - lastMillis > 1000) { + + lastMillis = millis(); + + // hardware clock + struct tm hwTimeinfo; + rtc.getDateTime(&hwTimeinfo); + Serial.print("Hardware clock :"); + Serial.println(&hwTimeinfo, "%A, %B %d %Y %H:%M:%S"); + + // system clock + struct tm timeinfo; + if (!getLocalTime(&timeinfo)) { + Serial.println("No time available (yet)"); + return; + } + + Serial.print("System clock :"); + Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); + Serial.println(); + + } +} + + + diff --git a/lib/SensorLib/examples/QMC6310_CalibrateExample/QMC6310_CalibrateExample.ino b/lib/SensorLib/examples/QMC6310_CalibrateExample/QMC6310_CalibrateExample.ino new file mode 100644 index 0000000..98aa401 --- /dev/null +++ b/lib/SensorLib/examples/QMC6310_CalibrateExample/QMC6310_CalibrateExample.ino @@ -0,0 +1,244 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMC6310_CalibrateExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#include "SensorQMC6310.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + + +SensorQMC6310 qmc; + + +void calibrate() +{ + qmc.setDataOutputRate(SensorQMC6310::DATARATE_200HZ); + + int32_t x_min = 65535; + int32_t x_max = -65535; + int32_t y_min = 65535; + int32_t y_max = -65535; + int32_t z_min = 65535; + int32_t z_max = -65535; + Serial.println("Place the sensor on the plane and slowly rotate the sensor..."); + + int32_t range = 1000; + int32_t i = 0; + int32_t x = 0, y = 0, z = 0;; + float a = 0.5 ; + float x_offset = 0; + float y_offset = 0; + float z_offset = 0; + + while (i < range) { + i += 1; + + if (qmc.isDataReady()) { + + qmc.readData(); + + x = a * qmc.getRawX() + (1 - a) * x; + y = a * qmc.getRawY() + (1 - a) * y; + z = a * qmc.getRawZ() + (1 - a) * z; + if (x < x_min) { + x_min = x; + i = 0; + } + if (x > x_max) { + x_max = x; + i = 0; + } + if (y < y_min) { + y_min = y; + i = 0; + } + if (y > y_max) { + y_max = y; + i = 0; + } + if (z < z_min) { + z_min = z; + i = 0; + } + if (z > z_max) { + z_max = z; + i = 0; + } + int j = round(10 * i / range); + + Serial.print("["); + for (int k = 0; k < j; ++k) { + Serial.print("*"); + } + Serial.println("]"); + } + delay(5); + } + + x_offset = (x_max + x_min) / 2; + y_offset = (y_max + y_min) / 2; + z_offset = (z_max + z_min) / 2; + + Serial.printf("x_min:%d x_max:%d y_min:%d y_max:%d z_min:%d z_max:%d\n", x_min, x_max, y_min, y_max, z_min, z_max); + Serial.printf("x_offset:%.2f y_offset:%.2f z_offset:%.2f \n", x_offset, y_offset, z_offset); + + // Set the calibration value and the user calculates the deviation + qmc.setOffset(x_offset, y_offset, z_offset); +} + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMC6310 - check your wiring!"); + while (1) { + delay(1000); + } + } + + /* Get Magnetometer chip id*/ + Serial.print("Device ID:"); + Serial.println(qmc.getChipID(), HEX); + + /* Config Magnetometer */ + qmc.configMagnetometer( + /* + * Run Mode + * MODE_SUSPEND + * MODE_NORMAL + * MODE_SINGLE + * MODE_CONTINUOUS + * * */ + SensorQMC6310::MODE_CONTINUOUS, + /* + * Full Range + * RANGE_30G + * RANGE_12G + * RANGE_8G + * RANGE_2G + * * */ + SensorQMC6310::RANGE_8G, + /* + * Output data rate + * DATARATE_10HZ + * DATARATE_50HZ + * DATARATE_100HZ + * DATARATE_200HZ + * * */ + SensorQMC6310::DATARATE_200HZ, + /* + * Over sample Ratio1 + * OSR_8 + * OSR_4 + * OSR_2 + * OSR_1 + * * * */ + SensorQMC6310::OSR_1, + + /* + * Down sample Ratio1 + * DSR_8 + * DSR_4 + * DSR_2 + * DSR_1 + * * */ + SensorQMC6310::DSR_1); + + + + + // Calibration algorithm reference from + // https://github.com/CoreElectronics/CE-PiicoDev-QMC6310-MicroPython-Module + calibrate(); + + Serial.println("Calibration done ."); + delay(5000); + + Serial.println("Read data now..."); +} + +void loop() +{ + + //Wiat data ready + if (qmc.isDataReady()) { + + qmc.readData(); + + Serial.print("GYR: "); + Serial.print("X:"); + Serial.print(qmc.getX()); + Serial.print(" Y:"); + Serial.print(qmc.getY()); + Serial.print(" Z:"); + Serial.print(qmc.getZ()); + Serial.println(" uT"); + Serial.print("RAW: "); + Serial.print("X:"); + Serial.print(qmc.getRawX()); + Serial.print(" Y:"); + Serial.print(qmc.getRawY()); + Serial.print(" Z:"); + Serial.println(qmc.getRawZ()); + + /* + float x, y, z; + qmc.getMag(x, y, z); + Serial.print("X:"); + Serial.print(x); + Serial.print(" Y:"); + Serial.print(y); + Serial.print(" Z:"); + Serial.println(x); + */ + } + + + delay(100); +} + + + diff --git a/lib/SensorLib/examples/QMC6310_CompassExample/QMC6310_CompassExample.ino b/lib/SensorLib/examples/QMC6310_CompassExample/QMC6310_CompassExample.ino new file mode 100644 index 0000000..f20ed55 --- /dev/null +++ b/lib/SensorLib/examples/QMC6310_CompassExample/QMC6310_CompassExample.ino @@ -0,0 +1,234 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMC6310_GetDataExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include + +#ifndef ARDUINO_ARCH_RP2040 +#include "SensorQMC6310.hpp" +#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306 + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + + +#define I2C1_SDA 22 //Display Wire SDA Pin +#define I2C1_SCL 21 //Display Wire SCL Pin + +SH1106Wire display(0x3c, I2C1_SDA, I2C1_SCL); +SensorQMC6310 qmc; + +int last_dx, last_dy, dx, dy, angle; + +const int centreX = 32; +const int centreY = 30; +const int radius = 22; + +//Compass application from https://github.com/G6EJD/ESP8266_micro_compass_HMC5883_OLED +void arrow(int x2, int y2, int x1, int y1, int alength, int awidth, OLEDDISPLAY_COLOR color) +{ + display.setColor(color); + float distance; + int dx, dy, x2o, y2o, x3, y3, x4, y4, k; + distance = sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2)); + dx = x2 + (x1 - x2) * alength / distance; + dy = y2 + (y1 - y2) * alength / distance; + k = awidth / alength; + x2o = x2 - dx; + y2o = dy - y2; + x3 = y2o * k + dx; + y3 = x2o * k + dy; + x4 = dx - y2o * k; + y4 = dy - x2o * k; + display.drawLine(x1, y1, x2, y2); + display.drawLine(x1, y1, dx, dy); + display.drawLine(x3, y3, x4, y4); + display.drawLine(x3, y3, x2, y2); + display.drawLine(x2, y2, x4, y4); +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMC6310 - check your wiring!"); + while (1) { + delay(1000); + } + } + + display.init(); + + last_dx = centreX; + last_dy = centreY; + + /* Get Magnetometer chip id*/ + Serial.print("Device ID:"); + Serial.println(qmc.getChipID(), HEX); + + /* Config Magnetometer */ + int r = qmc.configMagnetometer( + /* + * Run Mode + * MODE_SUSPEND + * MODE_NORMAL + * MODE_SINGLE + * MODE_CONTINUOUS + * * */ + SensorQMC6310::MODE_NORMAL, + /* + * Full Range + * RANGE_30G + * RANGE_12G + * RANGE_8G + * RANGE_2G + * * */ + SensorQMC6310::RANGE_2G, + /* + * Output data rate + * DATARATE_10HZ + * DATARATE_50HZ + * DATARATE_100HZ + * DATARATE_200HZ + * * */ + SensorQMC6310::DATARATE_100HZ, + /* + * Over sample Ratio1 + * OSR_8 + * OSR_4 + * OSR_2 + * OSR_1 + * * * */ + SensorQMC6310::OSR_1, + + /* + * Down sample Ratio1 + * DSR_8 + * DSR_4 + * DSR_2 + * DSR_1 + * * */ + SensorQMC6310::DSR_1); + + if (r != DEV_WIRE_NONE) { + Serial.println("Device config failed!"); + while (1)delay(1000); + } + + // Print register configuration information + qmc.dumpCtrlRegister(); + + Serial.println("Read data now..."); +} + +void loop() +{ + + //Wiat data ready + if (qmc.isDataReady()) { + + qmc.readData(); + + + display.drawString(29, 0, "N"); + display.drawString( 0, 28, "W"); + display.drawString(60, 28, "E"); + display.drawString(29, 53, "S"); + + display.drawLine(1, 1, 7, 7); + display.drawLine(62, 1, 56, 7); + display.drawLine(1, 62, 7, 56); + display.drawLine(56, 56, 62, 62); + + //Compass application from https://github.com/G6EJD/ESP8266_micro_compass_HMC5883_OLED + float heading = atan2(qmc.getY(), qmc.getX()); // Result is in radians + // Now add the 'Declination Angle' for you location. Declination is the variation in magnetic field at your location. + // Find your declination here: http://www.magnetic-declination.com/ + // At my location it is : -2° 20' W, or -2.33 Degrees, which needs to be in radians so = -2.33 / 180 * PI = -0.041 West is + E is - + // Make declination = 0 if you can't find your Declination value, the error is negible for nearly all locations + float declination = -0.041; + heading = heading + declination; + + if (heading < 0) heading += 2 * PI; // Correct for when signs are reversed. + if (heading > 2 * PI) heading -= 2 * PI; // Correct for when heading exceeds 360-degree, especially when declination is included + angle = int(heading * 180 / M_PI); // Convert radians to degrees for more a more usual result + // For the screen -X = up and +X = down and -Y = left and +Y = right, so does not follow coordinate conventions + dx = (0.7 * radius * cos((angle - 90) * 3.14 / 180)) + centreX; // calculate X position for the screen coordinates - can be confusing! + dy = (0.7 * radius * sin((angle - 90) * 3.14 / 180)) + centreY; // calculate Y position for the screen coordinates - can be confusing! + arrow(last_dx, last_dy, centreX, centreY, 2, 2, BLACK); // Erase last arrow + arrow(dx, dy, centreX, centreY, 2, 2, WHITE); // Draw arrow in new position + + display.setColor(BLACK); + display.fillRect(80, 50, 25, 48); + display.setColor(WHITE); + display.drawString(80, 50, String(angle) + "°"); + display.display(); + + last_dx = dx; + last_dy = dy; + + // for debug. + Serial.print("GYR: "); + Serial.print("X:"); + Serial.print(qmc.getX()); + Serial.print(" Y:"); + Serial.print(qmc.getY()); + Serial.print(" Z:"); + Serial.print(qmc.getZ()); + Serial.println(" uT"); + } + + + delay(100); +} +#else +void setup() +{ + Serial.begin(115200); +} + +void loop() +{ + Serial.println("display lib not support RP2040"); delay(1000); +} +#endif diff --git a/lib/SensorLib/examples/QMC6310_GetDataExample/QMC6310_GetDataExample.ino b/lib/SensorLib/examples/QMC6310_GetDataExample/QMC6310_GetDataExample.ino new file mode 100644 index 0000000..8d84cc9 --- /dev/null +++ b/lib/SensorLib/examples/QMC6310_GetDataExample/QMC6310_GetDataExample.ino @@ -0,0 +1,155 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMC6310_GetDataExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#include "SensorQMC6310.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +SensorQMC6310 qmc; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMC6310 - check your wiring!"); + while (1) { + delay(1000); + } + } + + /* Get Magnetometer chip id*/ + Serial.print("Device ID:"); + Serial.println(qmc.getChipID(), HEX); + + /* Config Magnetometer */ + qmc.configMagnetometer( + /* + * Run Mode + * MODE_SUSPEND + * MODE_NORMAL + * MODE_SINGLE + * MODE_CONTINUOUS + * * */ + SensorQMC6310::MODE_CONTINUOUS, + /* + * Full Range + * RANGE_30G + * RANGE_12G + * RANGE_8G + * RANGE_2G + * * */ + SensorQMC6310::RANGE_8G, + /* + * Output data rate + * DATARATE_10HZ + * DATARATE_50HZ + * DATARATE_100HZ + * DATARATE_200HZ + * * */ + SensorQMC6310::DATARATE_200HZ, + /* + * Over sample Ratio1 + * OSR_8 + * OSR_4 + * OSR_2 + * OSR_1 + * * * */ + SensorQMC6310::OSR_1, + + /* + * Down sample Ratio1 + * DSR_8 + * DSR_4 + * DSR_2 + * DSR_1 + * * */ + SensorQMC6310::DSR_1); + + Serial.println("Read data now..."); +} + +void loop() +{ + + //Wiat data ready + if (qmc.isDataReady()) { + + qmc.readData(); + + Serial.print("GYR: "); + Serial.print("X:"); + Serial.print(qmc.getX()); + Serial.print(" Y:"); + Serial.print(qmc.getY()); + Serial.print(" Z:"); + Serial.print(qmc.getZ()); + Serial.println(" uT"); + Serial.print("RAW: "); + Serial.print("X:"); + Serial.print(qmc.getRawX()); + Serial.print(" Y:"); + Serial.print(qmc.getRawY()); + Serial.print(" Z:"); + Serial.println(qmc.getRawZ()); + + /* + float x, y, z; + qmc.getMag(x, y, z); + Serial.print("X:"); + Serial.print(x); + Serial.print(" Y:"); + Serial.print(y); + Serial.print(" Z:"); + Serial.println(x); + */ + } + + + delay(100); +} + + + diff --git a/lib/SensorLib/examples/QMC6310_GetPolarExample/QMC6310_GetPolarExample.ino b/lib/SensorLib/examples/QMC6310_GetPolarExample/QMC6310_GetPolarExample.ino new file mode 100644 index 0000000..ea9da61 --- /dev/null +++ b/lib/SensorLib/examples/QMC6310_GetPolarExample/QMC6310_GetPolarExample.ino @@ -0,0 +1,133 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMC6310_GetPolarExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#include "SensorQMC6310.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +SensorQMC6310 qmc; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMC6310 - check your wiring!"); + while (1) { + delay(1000); + } + } + + /* Get Magnetometer chip id*/ + Serial.print("Device ID:"); + Serial.println(qmc.getChipID(), HEX); + + /* Config Magnetometer */ + qmc.configMagnetometer( + /* + * Run Mode + * MODE_SUSPEND + * MODE_NORMAL + * MODE_SINGLE + * MODE_CONTINUOUS + * * */ + SensorQMC6310::MODE_NORMAL, + /* + * Full Range + * RANGE_30G + * RANGE_12G + * RANGE_8G + * RANGE_2G + * * */ + SensorQMC6310::RANGE_8G, + /* + * Output data rate + * DATARATE_10HZ + * DATARATE_50HZ + * DATARATE_100HZ + * DATARATE_200HZ + * * */ + SensorQMC6310::DATARATE_200HZ, + /* + * Over sample Ratio1 + * OSR_8 + * OSR_4 + * OSR_2 + * OSR_1 + * * * */ + SensorQMC6310::OSR_8, + + /* + * Down sample Ratio1 + * DSR_8 + * DSR_4 + * DSR_2 + * DSR_1 + * * */ + SensorQMC6310::DSR_1); + + qmc.dumpCtrlRegister(); + + // Declination is the difference between magnetic-north and true-north ("heading") and depends on location + qmc.setDeclination(-2.77); // Found with: https://www.magnetic-declination.com/CHINA/SHENZHEN/475119.html + + Serial.println("Read data now..."); +} + +void loop() +{ + Polar data; + // Wait for data ready + if (qmc.readPolar(data)) { + Serial.print(" polar:"); Serial.print(data.polar); Serial.print("°"); + Serial.print(" Gauss:"); Serial.print(data.Gauss); + Serial.print(" uT:"); Serial.println(data.uT); + } + + delay(100); +} + + + diff --git a/lib/SensorLib/examples/QMI8658_BlockExample/QMI8658_BlockExample.ino b/lib/SensorLib/examples/QMI8658_BlockExample/QMI8658_BlockExample.ino new file mode 100644 index 0000000..d2c3382 --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_BlockExample/QMI8658_BlockExample.ino @@ -0,0 +1,262 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_BlockExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#ifndef ARDUINO_ARCH_RP2040 +#include "SensorQMI8658.hpp" +#include //MadgwickAHRS from https://github.com/arduino-libraries/MadgwickAHRS +#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306 + +// #define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +#define I2C1_SDA 22 //Display Wire SDA Pin +#define I2C1_SCL 21 //Display Wire SCL Pin + +SH1106Wire display(0x3c, I2C1_SDA, I2C1_SCL); + +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + +Madgwick filter; +unsigned long microsPerReading, microsPrevious; + +float posX = 64; +float posY = 32; +float lastPosX = posX; +float lastPosY = posY; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + display.init(); + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + +#ifndef CONFIG_IDF_TARGET_ESP32 +//Use tbeams3 defalut spi pin +#define SPI_MOSI (35) +#define SPI_SCK (36) +#define SPI_MISO (37) +#define SPI_CS (47) +#define IMU_CS (34) +#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin + + pinMode(SPI_CS, OUTPUT); //sdcard pin set high + digitalWrite(SPI_CS, HIGH); + if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) { + +#else +//Use esp32dev module defalut spi pin +#define IMU_CS (5) +#define IMU_INT1 (15) +#define IMU_INT2 (22) + if (!qmi.begin(IMU_CS)) { +#endif + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + display.flipScreenVertically(); + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_2G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_1000Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_256DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_896_8Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + // Print register configuration information + qmi.dumpCtrlRegister(); + + // start filter + filter.begin(25); + + // initialize variables to pace updates to correct rate + microsPerReading = 1000000 / 25; + microsPrevious = micros(); + + Serial.println("Read data now..."); +} + +const uint8_t rectWidth = 10; + +void loop() +{ + float roll, pitch, heading; + + // check if it's time to read data and update the filter + if (micros() - microsPrevious >= microsPerReading) { + + // read raw data from IMU + if (qmi.getDataReady()) { + + qmi.getAccelerometer(acc.x, acc.y, acc.z); + qmi.getGyroscope(gyr.x, gyr.y, gyr.z); + + // update the filter, which computes orientation + filter.updateIMU(gyr.x, gyr.y, gyr.z, acc.x, acc.y, acc.z); + + // print the heading, pitch and roll + roll = filter.getRoll(); + pitch = filter.getPitch(); + heading = filter.getYaw(); + + posX -= roll * 2; + posY += pitch; + + Serial.printf("x:%.2f y:%.2f \n", posX, posY); + posX = constrain(posX, 0, display.width() - rectWidth); + posY = constrain(posY, 0, display.height() - rectWidth); + + display.setColor(BLACK); + display.fillRect(lastPosX, lastPosY, 10, 10); + display.setColor(WHITE); + display.fillRect(posX, posY, 10, 10); + display.display(); + + lastPosX = posX; + lastPosY = posY; + } + // increment previous time, so we keep proper pace + microsPrevious = microsPrevious + microsPerReading; + } +} +#else +void setup() +{ + Serial.begin(115200); +} + +void loop() +{ + Serial.println("display lib not support RP2040"); delay(1000); +} +#endif + + diff --git a/lib/SensorLib/examples/QMI8658_GetDataExample/QMI8658_GetDataExample.ino b/lib/SensorLib/examples/QMI8658_GetDataExample/QMI8658_GetDataExample.ino new file mode 100644 index 0000000..e18d11b --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_GetDataExample/QMI8658_GetDataExample.ino @@ -0,0 +1,195 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_GetDataExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" + +#define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + + +#define IMU_CS 5 + +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + if (!qmi.begin(IMU_CS)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_4G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_1000Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_64DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_896_8Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + // Print register configuration information + qmi.dumpCtrlRegister(); + + Serial.println("Read data now..."); +} + + +void loop() +{ + + if (qmi.getDataReady()) { + + if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) { + Serial.print("{ACCEL: "); + Serial.print(acc.x); + Serial.print(","); + Serial.print(acc.y); + Serial.print(","); + Serial.print(acc.z); + Serial.println("}"); + } + + if (qmi.getGyroscope(gyr.x, gyr.y, gyr.z)) { + Serial.print("{GYRO: "); + Serial.print(gyr.x); + Serial.print(","); + Serial.print(gyr.y ); + Serial.print(","); + Serial.print(gyr.z); + Serial.println("}"); + } + Serial.printf("\t\t\t\t > %lu %.2f *C\n", qmi.getTimestamp(), qmi.getTemperature_C()); + } + delay(100); +} + + + diff --git a/lib/SensorLib/examples/QMI8658_InterruptBlockExample/QMI8658_InterruptBlockExample.ino b/lib/SensorLib/examples/QMI8658_InterruptBlockExample/QMI8658_InterruptBlockExample.ino new file mode 100644 index 0000000..447a87f --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_InterruptBlockExample/QMI8658_InterruptBlockExample.ino @@ -0,0 +1,272 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_InterruptBlockExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#ifndef ARDUINO_ARCH_RP2040 +#include "SensorQMI8658.hpp" +#include //MadgwickAHRS from https://github.com/arduino-libraries/MadgwickAHRS +#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306 + +// #define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + + +#define I2C1_SDA 22 //Display Wire SDA Pin +#define I2C1_SCL 21 //Display Wire SCL Pin + +SH1106Wire display(0x3c, I2C1_SDA, I2C1_SCL); +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + +Madgwick filter; +unsigned long microsPerReading, microsPrevious; + +float posX = 64; +float posY = 32; +float lastPosX = posX; +float lastPosY = posY; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + display.init(); + display.flipScreenVertically(); + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + +#ifndef CONFIG_IDF_TARGET_ESP32 +//Use tbeams3 defalut spi pin +#define SPI_MOSI (35) +#define SPI_SCK (36) +#define SPI_MISO (37) +#define SPI_CS (47) +#define IMU_CS (34) +#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin + + pinMode(SPI_CS, OUTPUT); //sdcard pin set high + digitalWrite(SPI_CS, HIGH); + if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) { + +#else +//Use esp32dev module defalut spi pin +#define IMU_CS (5) +#define IMU_INT1 (15) +#define IMU_INT2 (22) + if (!qmi.begin(IMU_CS)) { +#endif + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_2G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_1000Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_256DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_896_8Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + pinMode(IMU_INT1, INPUT); +#ifdef IMU_INT2 + pinMode(IMU_INT2, INPUT); +#endif + + // qmi.enableINT(SensorQMI8658::IntPin1); //no use + // Enable data ready to interrupt pin2 + qmi.enableINT(SensorQMI8658::IntPin2); + qmi.enableDataReadyINT(); + + // Print register configuration information + qmi.dumpCtrlRegister(); + + // start filter + filter.begin(25); + + // initialize variables to pace updates to correct rate + microsPerReading = 1000000 / 25; + microsPrevious = micros(); + + Serial.println("Read data now..."); +} + +const uint8_t rectWidth = 10; + +void loop() +{ + float roll, pitch, heading; + + // check if it's time to read data and update the filter + if (micros() - microsPrevious >= microsPerReading) { + + // read raw data from IMU + if (digitalRead(IMU_INT1) == HIGH) { + + qmi.getAccelerometer(acc.x, acc.y, acc.z); + qmi.getGyroscope(gyr.x, gyr.y, gyr.z); + + // update the filter, which computes orientation + filter.updateIMU(gyr.x, gyr.y, gyr.z, acc.x, acc.y, acc.z); + + // print the heading, pitch and roll + roll = filter.getRoll(); + pitch = filter.getPitch(); + heading = filter.getYaw(); + + posX -= roll * 2; + posY += pitch; + + Serial.printf("x:%.2f y:%.2f \n", posX, posY); + posX = constrain(posX, 0, display.width() - rectWidth); + posY = constrain(posY, 0, display.height() - rectWidth); + + display.setColor(BLACK); + display.fillRect(lastPosX, lastPosY, 10, 10); + display.setColor(WHITE); + display.fillRect(posX, posY, 10, 10); + display.display(); + + lastPosX = posX; + lastPosY = posY; + } + // increment previous time, so we keep proper pace + microsPrevious = microsPrevious + microsPerReading; + } +} +#else +void setup() +{ + Serial.begin(115200); +} + +void loop() +{ + Serial.println("display lib not support RP2040"); + delay(1000); +} +#endif + + diff --git a/lib/SensorLib/examples/QMI8658_InterruptExample/QMI8658_InterruptExample.ino b/lib/SensorLib/examples/QMI8658_InterruptExample/QMI8658_InterruptExample.ino new file mode 100644 index 0000000..df12391 --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_InterruptExample/QMI8658_InterruptExample.ino @@ -0,0 +1,247 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_InterruptExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-11-03 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" + +// #define USE_WIRE + + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + +#ifndef CONFIG_IDF_TARGET_ESP32 +//Use tbeams3 defalut spi pin +#define SPI_MOSI (35) +#define SPI_SCK (36) +#define SPI_MISO (37) +#define SPI_CS (47) +#define IMU_CS (34) +#define IMU_INT1 (33) + + pinMode(SPI_CS, OUTPUT); //sdcard pin set high + digitalWrite(SPI_CS, HIGH); + if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) { + +#else +//Use esp32dev module defalut spi pin +#define IMU_CS (5) +#define IMU_INT1 (15) +#define IMU_INT2 (22) + if (!qmi.begin(IMU_CS)) { +#endif + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_4G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_1000Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_64DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_896_8Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + + pinMode(IMU_INT1, INPUT); +#ifdef IMU_INT2 + pinMode(IMU_INT2, INPUT); +#endif + + // qmi.enableINT(SensorQMI8658::IntPin1); //no use + // Enable data ready to interrupt pin2 + qmi.enableINT(SensorQMI8658::IntPin2); + qmi.enableDataReadyINT(); + + // Print register configuration information + qmi.dumpCtrlRegister(); + + Serial.println("Read data now..."); +} + +void readSensorData(const char *name) +{ + uint8_t status = qmi.getIrqStatus(); + // status == 0x01 + // If syncSmpl (CTRL7.bit7) = 1: + // 0: Sensor Data is not available + // 1: Sensor Data is available for reading + // If syncSmpl = 0, this bit shows the same value of INT2 level + Serial.print(name); + Serial.print(" -> ["); + Serial.print(millis()); + Serial.print("]: - "); + Serial.print(status); + Serial.print(" - "); + Serial.println(status, BIN); + if (status & 0x01) { + if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) { + Serial.print("{ACCEL: "); + Serial.print(acc.x); + Serial.print(","); + Serial.print(acc.y); + Serial.print(","); + Serial.print(acc.z); + Serial.println("}"); + } + + if (qmi.getGyroscope(gyr.x, gyr.y, gyr.z)) { + Serial.print("{GYRO: "); + Serial.print(gyr.x); + Serial.print(","); + Serial.print(gyr.y ); + Serial.print(","); + Serial.print(gyr.z); + Serial.println("}"); + } + Serial.printf("\t\t\t\t > %lu %.2f *C\n", qmi.getTimestamp(), qmi.getTemperature_C()); + } + +} + +void loop() +{ + if (digitalRead(IMU_INT1) == HIGH) { + readSensorData("INT1"); + } + +#ifdef IMU_INT2 + if (digitalRead(IMU_INT2) == HIGH) { + readSensorData("INT2"); + } +#endif + +} + + + + diff --git a/lib/SensorLib/examples/QMI8658_LockingMechanismExample/QMI8658_LockingMechanismExample.ino b/lib/SensorLib/examples/QMI8658_LockingMechanismExample/QMI8658_LockingMechanismExample.ino new file mode 100644 index 0000000..4a7d8c1 --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_LockingMechanismExample/QMI8658_LockingMechanismExample.ino @@ -0,0 +1,246 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_LockingMechanismExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-11-07 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" + +// #define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + +bool interruptFlag = false; + +void setFlag(void) +{ + interruptFlag = true; +} + +// Callback when data is locked +void lockingMechanismHandler() +{ + if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) { + Serial.print("{ACCEL: "); + Serial.print(acc.x); + Serial.print(","); + Serial.print(acc.y); + Serial.print(","); + Serial.print(acc.z); + Serial.println("}"); + } + + if (qmi.getGyroscope(gyr.x, gyr.y, gyr.z)) { + Serial.print("{GYRO: "); + Serial.print(gyr.x); + Serial.print(","); + Serial.print(gyr.y ); + Serial.print(","); + Serial.print(gyr.z); + Serial.println("}"); + } + Serial.printf("\t\t\t\t > %lu %.2f *C\n", qmi.getTimestamp(), qmi.getTemperature_C()); +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + +#ifndef CONFIG_IDF_TARGET_ESP32 +//Use tbeams3 defalut spi pin +#define SPI_MOSI (35) +#define SPI_SCK (36) +#define SPI_MISO (37) +#define SPI_CS (47) +#define IMU_CS (34) +#define IMU_INT1 (33) + + pinMode(SPI_CS, OUTPUT); //sdcard pin set high + digitalWrite(SPI_CS, HIGH); + if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) { + +#else +//Use esp32dev module defalut spi pin +#define IMU_CS (5) +#define IMU_INT1 (15) +#define IMU_INT2 (22) + if (!qmi.begin(IMU_CS)) { +#endif + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_4G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_1000Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_64DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_896_8Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + //Enable Locking Mechanism + qmi.enableLockingMechanism(); + + // Set locking data event callback + qmi.setDataLockingEvevntCallBack(lockingMechanismHandler); + + + // Use interrupt . + // QMI8658 interrupt always outputs low level by default, + // and the interrupt is triggered when the rising edge + pinMode(IMU_INT1, INPUT_PULLUP); +#ifdef IMU_INT2 + pinMode(IMU_INT2, INPUT_PULLUP); + attachInterrupt(IMU_INT2, setFlag, RISING); +#else + attachInterrupt(IMU_INT1, setFlag, RISING); +#endif + + // qmi.enableINT(SensorQMI8658::IntPin1); //no use + // Enable data ready to interrupt pin2 + qmi.enableINT(SensorQMI8658::IntPin2); + + + // Print register configuration information + qmi.dumpCtrlRegister(); + + + Serial.println("Read data now..."); +} + + +void loop() +{ + if (interruptFlag) { + interruptFlag = false; + qmi.readSensorStatus(); + } + delay(100); +} + + + + diff --git a/lib/SensorLib/examples/QMI8658_MadgwickAHRS/QMI8658_MadgwickAHRS.ino b/lib/SensorLib/examples/QMI8658_MadgwickAHRS/QMI8658_MadgwickAHRS.ino new file mode 100644 index 0000000..e78650e --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_MadgwickAHRS/QMI8658_MadgwickAHRS.ino @@ -0,0 +1,204 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_MadgwickAHRS.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" +#include //MadgwickAHRS from https://github.com/arduino-libraries/MadgwickAHRS + +#define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +#define IMU_CS 5 + +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + +Madgwick filter; +unsigned long microsPerReading, microsPrevious; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + if (!qmi.begin(IMU_CS)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_2G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_1000Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_256DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_896_8Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + // Print register configuration information + qmi.dumpCtrlRegister(); + + // start filter + filter.begin(25); + + // initialize variables to pace updates to correct rate + microsPerReading = 1000000 / 25; + microsPrevious = micros(); + + Serial.println("Read data now..."); +} + + +void loop() +{ + float roll, pitch, heading; + + // check if it's time to read data and update the filter + if (micros() - microsPrevious >= microsPerReading) { + + // read raw data from IMU + if (qmi.getDataReady()) { + qmi.getAccelerometer(acc.x, acc.y, acc.z); + qmi.getGyroscope(gyr.x, gyr.y, gyr.z); + // update the filter, which computes orientation + filter.updateIMU(gyr.x, gyr.y, gyr.z, acc.x, acc.y, acc.z); + + // print the heading, pitch and roll + roll = filter.getRoll(); + pitch = filter.getPitch(); + heading = filter.getYaw(); + Serial.print("Orientation: "); + Serial.print(heading); + Serial.print(" "); + Serial.print(pitch); + Serial.print(" "); + Serial.println(roll); + } + // increment previous time, so we keep proper pace + microsPrevious = microsPrevious + microsPerReading; + } +} + + + diff --git a/lib/SensorLib/examples/QMI8658_PedometerExample/QMI8658_PedometerExample.ino b/lib/SensorLib/examples/QMI8658_PedometerExample/QMI8658_PedometerExample.ino new file mode 100644 index 0000000..9d5de7c --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_PedometerExample/QMI8658_PedometerExample.ino @@ -0,0 +1,196 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_GetDataExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" + +#define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +#define IMU_CS 5 + +SensorQMI8658 qmi; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + if (!qmi.begin(IMU_CS)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_4G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_125Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_64DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_112_1Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + + qmi.configPedometer(0x007D, 0x00CC, 0x0066, 0x00C8, 0x14, 0x0A, 0, 0x04); + + qmi.enablePedometer(); + + // Print register configuration information + qmi.dumpCtrlRegister(); + + Serial.println("Read data now..."); + +} + + +void loop() +{ + // Get IMU status + uint8_t status = qmi.getStatusRegister(); + Serial.printf("STATUS:0x%x BIN:", status); + Serial.println(status, BIN); + + if (status & SensorQMI8658::EVENT_TAP_MOTION) { + Serial.println("Detected TAP event"); + qmi.getTapStatus(); + } + if (status & SensorQMI8658::EVENT_WOM_MOTION) { + Serial.println("Detected Wom event"); + } + if (status & SensorQMI8658::EVENT_PEDOMETER_MOTION) { + Serial.println("Detected Pedometer event"); + uint32_t val = qmi.getPedometerCounter(); + Serial.println(val); + } + if (status & SensorQMI8658::EVENT_ANY_MOTION) { + Serial.println("Detected Any Motion event"); + } + if (status & SensorQMI8658::EVENT_NO_MOTION) { + Serial.println("Detected No Motion event"); + } + if (status & SensorQMI8658::EVENT_SIGNIFICANT_MOTION) { + Serial.println("Detected Significant Motion event"); + } + + delay(500); +} \ No newline at end of file diff --git a/lib/SensorLib/examples/QMI8658_ReadFromFifoExample/QMI8658_ReadFromFifoExample.ino b/lib/SensorLib/examples/QMI8658_ReadFromFifoExample/QMI8658_ReadFromFifoExample.ino new file mode 100644 index 0000000..e5a1d71 --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_ReadFromFifoExample/QMI8658_ReadFromFifoExample.ino @@ -0,0 +1,218 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_ReadFromFifoExample.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" + +#define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +#define IMU_CS 5 + +SensorQMI8658 qmi; + + +IMUdata acc[128]; +IMUdata gyr[128]; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + //Using SPI !! + if (!qmi.begin(IMU_CS)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + + qmi.configAccelerometer( + /* + * ACC_RANGE_2G + * ACC_RANGE_4G + * ACC_RANGE_8G + * ACC_RANGE_16G + * */ + SensorQMI8658::ACC_RANGE_4G, + /* + * ACC_ODR_1000H + * ACC_ODR_500Hz + * ACC_ODR_250Hz + * ACC_ODR_125Hz + * ACC_ODR_62_5Hz + * ACC_ODR_31_25Hz + * ACC_ODR_LOWPOWER_128Hz + * ACC_ODR_LOWPOWER_21Hz + * ACC_ODR_LOWPOWER_11Hz + * ACC_ODR_LOWPOWER_3H + * */ + SensorQMI8658::ACC_ODR_1000Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_0, + // selfTest enable + true); + + + qmi.configGyroscope( + /* + * GYR_RANGE_16DPS + * GYR_RANGE_32DPS + * GYR_RANGE_64DPS + * GYR_RANGE_128DPS + * GYR_RANGE_256DPS + * GYR_RANGE_512DPS + * GYR_RANGE_1024DPS + * */ + SensorQMI8658::GYR_RANGE_64DPS, + /* + * GYR_ODR_7174_4Hz + * GYR_ODR_3587_2Hz + * GYR_ODR_1793_6Hz + * GYR_ODR_896_8Hz + * GYR_ODR_448_4Hz + * GYR_ODR_224_2Hz + * GYR_ODR_112_1Hz + * GYR_ODR_56_05Hz + * GYR_ODR_28_025H + * */ + SensorQMI8658::GYR_ODR_896_8Hz, + /* + * LPF_MODE_0 //2.66% of ODR + * LPF_MODE_1 //3.63% of ODR + * LPF_MODE_2 //5.39% of ODR + * LPF_MODE_3 //13.37% of ODR + * */ + SensorQMI8658::LPF_MODE_3, + // selfTest enable + true); + + qmi.configFIFO( + /** + * FIFO_MODE_BYPASS -- Disable fifo + * FIFO_MODE_FIFO -- Will not overwrite + * FIFO_MODE_STREAM -- Cover + */ + SensorQMI8658::FIFO_MODE_FIFO, + /* + * FIFO_SAMPLES_16 + * FIFO_SAMPLES_32 + * FIFO_SAMPLES_64 + * FIFO_SAMPLES_128 + * */ + SensorQMI8658::FIFO_SAMPLES_16, + + //FiFo mapped interrupt IO port + SensorQMI8658::IntPin1, + // watermark level + 8); + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + qmi.enableGyroscope(); + qmi.enableAccelerometer(); + + // Print register configuration information + qmi.dumpCtrlRegister(); + + Serial.println("Read data now..."); + +} + + + +void loop() +{ + // If the reading is successful, true will be returned + if (!qmi.readFromFifo(acc, 128, gyr, 128)) { + return; + } + + for (int i = 0; i < 16; ++i) { + Serial.print("ACCEL: "); + Serial.print("X:"); + Serial.print(acc[i].x); + Serial.print(" Y:"); + Serial.print(acc[i].y); + Serial.print(" Z:"); + Serial.println(acc[i].z); + Serial.print("GYRO: "); + Serial.print(" X:"); + Serial.print(gyr[i].x); + Serial.print(" Y:"); + Serial.print(gyr[i].y ); + Serial.print(" Z:"); + Serial.println(gyr[i].z); + } + + delay(100); +} + + + + + diff --git a/lib/SensorLib/examples/QMI8658_WakeOnMotion/QMI8658_WakeOnMotion.ino b/lib/SensorLib/examples/QMI8658_WakeOnMotion/QMI8658_WakeOnMotion.ino new file mode 100644 index 0000000..36b86da --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_WakeOnMotion/QMI8658_WakeOnMotion.ino @@ -0,0 +1,160 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_WakeOnMotion.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-11-05 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" + +// #define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + + +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + + +bool interruptFlag = false; + +void setFlag(void) +{ + interruptFlag = true; + +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + +#ifndef CONFIG_IDF_TARGET_ESP32 + //Use tbeams3 defalut spi pinz +#define SPI_MOSI (35) +#define SPI_SCK (36) +#define SPI_MISO (37) +#define SPI_CS (47) +#define IMU_CS (34) +#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin + + pinMode(SPI_CS, OUTPUT); //sdcard pin set high + digitalWrite(SPI_CS, HIGH); + if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) { + +#else +//Use esp32dev module defalut spi pin +#define IMU_CS (5) +#define IMU_INT1 (15) +#define IMU_INT2 (22) + if (!qmi.begin(IMU_CS)) { +#endif + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + // enabling wake on motion low power mode with a threshold of 120 mg and + // an accelerometer data rate of 128 Hz. + qmi.configWakeOnMotion(); + + /* + * When the QMI8658 is configured as Wom, the interrupt level is arbitrary, + * not absolute high or low, and it is in the jump transition state + */ + pinMode(IMU_INT1, INPUT_PULLUP); +#ifdef IMU_INT2 + pinMode(IMU_INT2, INPUT_PULLUP); + attachInterrupt(IMU_INT2, setFlag, CHANGE); +#else + attachInterrupt(IMU_INT1, setFlag, CHANGE); +#endif + + + // Print register configuration information + qmi.dumpCtrlRegister(); +} + + +void loop() +{ + + if (interruptFlag) { + interruptFlag = false; + uint8_t status = qmi.getStatusRegister(); + Serial.printf("status:0x%X BIN:", status); + Serial.println(status, BIN); + + if (status & SensorQMI8658::EVENT_SIGNIFICANT_MOTION) { + Serial.println("EVENT_SIGNIFICANT_MOTION"); + } else if (status & SensorQMI8658::EVENT_NO_MOTION) { + Serial.println("EVENT_NO_MOITON"); + } else if (status & SensorQMI8658::EVENT_ANY_MOTION) { + Serial.println("EVENT_ANY_MOTION"); + } else if (status & SensorQMI8658::EVENT_PEDOMETER_MOTION) { + Serial.println("EVENT_PEDOMETER_MOTION"); + } else if (status & SensorQMI8658::EVENT_WOM_MOTION) { + Serial.println("EVENT_WOM_MOTION"); + } else if (status & SensorQMI8658::EVENT_TAP_MOTION) { + Serial.println("EVENT_TAP_MOTION"); + } + } +} + + + diff --git a/lib/SensorLib/examples/QMI8658_WakeOnMotionCallBackExample/QMI8658_WakeOnMotionCallBackExample.ino b/lib/SensorLib/examples/QMI8658_WakeOnMotionCallBackExample/QMI8658_WakeOnMotionCallBackExample.ino new file mode 100644 index 0000000..38f3dcc --- /dev/null +++ b/lib/SensorLib/examples/QMI8658_WakeOnMotionCallBackExample/QMI8658_WakeOnMotionCallBackExample.ino @@ -0,0 +1,152 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658_WakeOnMotionCallBack.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2022-11-07 + * + */ +#include +#include +#include +#include "SensorQMI8658.hpp" + +// #define USE_WIRE + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + + +SensorQMI8658 qmi; + +IMUdata acc; +IMUdata gyr; + + +bool interruptFlag = false; + +void setFlag(void) +{ + interruptFlag = true; +} + +void wakeUp() +{ + Serial.println("Awake!"); +} + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + +#ifdef USE_WIRE + //Using WIRE !! + if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#else + +#ifndef CONFIG_IDF_TARGET_ESP32 + //Use tbeams3 defalut spi pinz +#define SPI_MOSI (35) +#define SPI_SCK (36) +#define SPI_MISO (37) +#define SPI_CS (47) +#define IMU_CS (34) +#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin + + pinMode(SPI_CS, OUTPUT); //sdcard pin set high + digitalWrite(SPI_CS, HIGH); + if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) { + +#else +//Use esp32dev module defalut spi pin +#define IMU_CS (5) +#define IMU_INT1 (15) +#define IMU_INT2 (22) + if (!qmi.begin(IMU_CS)) { +#endif + Serial.println("Failed to find QMI8658 - check your wiring!"); + while (1) { + delay(1000); + } + } +#endif + + /* Get chip id*/ + Serial.print("Device ID:"); + Serial.println(qmi.getChipID(), HEX); + + // enabling wake on motion low power mode with a threshold of 200 mg and + // an accelerometer data rate of 128 Hz. + qmi.configWakeOnMotion(); + + + qmi.setWakeupMotionEventCallBack(wakeUp); + + /* + * When the QMI8658 is configured as Wom, the interrupt level is arbitrary, + * not absolute high or low, and it is in the jump transition state + */ + pinMode(IMU_INT1, INPUT_PULLUP); +#ifdef IMU_INT2 + pinMode(IMU_INT2, INPUT_PULLUP); + attachInterrupt(IMU_INT2, setFlag, CHANGE); +#else + attachInterrupt(IMU_INT1, setFlag, CHANGE); +#endif + + + // Print register configuration information + qmi.dumpCtrlRegister(); +} + + +void loop() +{ + + if (interruptFlag) { + interruptFlag = false; + qmi.readSensorStatus(); + } +} + + + diff --git a/lib/SensorLib/examples/TouchDrv_CHSC5816_GetPoint/TouchDrv_CHSC5816_GetPoint.ino b/lib/SensorLib/examples/TouchDrv_CHSC5816_GetPoint/TouchDrv_CHSC5816_GetPoint.ino new file mode 100644 index 0000000..d1b7bfc --- /dev/null +++ b/lib/SensorLib/examples/TouchDrv_CHSC5816_GetPoint/TouchDrv_CHSC5816_GetPoint.ino @@ -0,0 +1,92 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrv_CHSC5816_GetPoint.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-17 + * + */ +#include +#include +#include +#include "TouchDrvCHSC5816.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 39 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 40 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 13 +#endif + +#ifndef SENSOR_RST +#define SENSOR_RST 14 +#endif + +TouchDrvCHSC5816 touch; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + touch.setPins(SENSOR_RST, SENSOR_IRQ); + if (!touch.begin(Wire, CHSC5816_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find CHSC5816 - check your wiring!"); + while (1) { + delay(1000); + } + } + + Serial.println("Init CHSC5816 Touch device success!"); +} + + +void loop() +{ + int16_t x[2], y[2]; + if (digitalRead(SENSOR_IRQ) == LOW) { + uint8_t touched = touch.getPoint(x, y); + for (int i = 0; i < touched; ++i) { + Serial.print("X["); + Serial.print(i); + Serial.print("]:"); + Serial.print(x[i]); + Serial.print(" "); + Serial.print(" Y["); + Serial.print(i); + Serial.print("]:"); + Serial.print(y[i]); + Serial.print(" "); + } + Serial.println(); + } +} + + + diff --git a/lib/SensorLib/examples/TouchDrv_CSTxxx_GetPoint/TouchDrv_CSTxxx_GetPoint.ino b/lib/SensorLib/examples/TouchDrv_CSTxxx_GetPoint/TouchDrv_CSTxxx_GetPoint.ino new file mode 100644 index 0000000..d6da0ac --- /dev/null +++ b/lib/SensorLib/examples/TouchDrv_CSTxxx_GetPoint/TouchDrv_CSTxxx_GetPoint.ino @@ -0,0 +1,175 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrv_CSTxxx_GetPoint.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-24 + * + */ +#include +#include +#include +#include "TouchDrvCSTXXX.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 8 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 10 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 5 +#endif + +#ifndef SENSOR_RST +#define SENSOR_RST -1 +#endif + +TouchDrvCSTXXX touch; +int16_t x[5], y[5]; + +void scanDevices(void) +{ + byte error, address; + int nDevices = 0; + Serial.println("Scanning for I2C devices ..."); + for (address = 0x01; address < 0x7f; address++) { + Wire.beginTransmission(address); + error = Wire.endTransmission(); + if (error == 0) { + Serial.printf("I2C device found at address 0x%02X\n", address); + nDevices++; + } else if (error != 2) { + Serial.printf("Error %d at address 0x%02X\n", error, address); + } + } + if (nDevices == 0) { + Serial.println("No I2C devices found"); + } +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + +#if SENSOR_RST != -1 + pinMode(SENSOR_RST, OUTPUT); + digitalWrite(SENSOR_RST, LOW); + delay(30); + digitalWrite(SENSOR_RST, HIGH); + delay(50); + // delay(1000); +#endif + + // Search for known CSTxxx device addresses + uint8_t address = 0xFF; + +#ifdef ARDUINO_ARCH_RP2040 + Wire.setSCL(SENSOR_SCL); + Wire.setSDA(SENSOR_SDA); +#else + Wire.begin(SENSOR_SDA, SENSOR_SCL); +#endif + + // Scan I2C devices + scanDevices(); + + Wire.beginTransmission(CST816_SLAVE_ADDRESS); + if (Wire.endTransmission() == 0) { + address = CST816_SLAVE_ADDRESS; + } + Wire.beginTransmission(CST226SE_SLAVE_ADDRESS); + if (Wire.endTransmission() == 0) { + address = CST226SE_SLAVE_ADDRESS; + } + Wire.beginTransmission(CST328_SLAVE_ADDRESS); + if (Wire.endTransmission() == 0) { + address = CST328_SLAVE_ADDRESS; + } + while (address == 0xFF) { + Serial.println("Could't find touch chip!"); delay(1000); + } + + touch.setPins(SENSOR_RST, SENSOR_IRQ); + touch.begin(Wire, address, SENSOR_SDA, SENSOR_SCL); + + + Serial.print("Model :"); Serial.println(touch.getModelName()); + + // T-Display-S3 CST816 touch panel, touch button coordinates are is 85 , 160 + touch.setCenterButtonCoordinate(85, 360); + + // T-Display-AMOLED 1.91 Inch CST816T touch panel, touch button coordinates is 600, 120. + // touch.setCenterButtonCoordinate(600, 120); // Only suitable for AMOLED 1.91 inch + + + // Depending on the touch panel, not all touch panels have touch buttons. + touch.setHomeButtonCallback([](void *user_data) { + Serial.println("Home key pressed!"); + }, NULL); + + + // Unable to obtain coordinates after turning on sleep + // CST816T sleep current = 1.1 uA + // CST226SE sleep current = 60 uA + // touch.sleep(); + + // Set touch max xy + // touch.setMaxCoordinates(536, 240); + + // Set swap xy + // touch.setSwapXY(true); + + // Set mirror xy + // touch.setMirrorXY(true, true); + +} + +void loop() +{ + uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); + if (touched) { + for (int i = 0; i < touched; ++i) { + Serial.print("X["); + Serial.print(i); + Serial.print("]:"); + Serial.print(x[i]); + Serial.print(" "); + Serial.print(" Y["); + Serial.print(i); + Serial.print("]:"); + Serial.print(y[i]); + Serial.print(" "); + } + Serial.println(); + } + + delay(5); +} + + + diff --git a/lib/SensorLib/examples/TouchDrv_FT3267_LilyGo_T_RGB/TouchDrv_FT3267_LilyGo_T_RGB.ino b/lib/SensorLib/examples/TouchDrv_FT3267_LilyGo_T_RGB/TouchDrv_FT3267_LilyGo_T_RGB.ino new file mode 100644 index 0000000..2dfe4f5 --- /dev/null +++ b/lib/SensorLib/examples/TouchDrv_FT3267_LilyGo_T_RGB/TouchDrv_FT3267_LilyGo_T_RGB.ino @@ -0,0 +1,115 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrv_FT3267_LilyGo_T_RGB.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-17 + * + */ +#include +#include +#include +#include "TouchDrvFT6X36.hpp" +#include "ExtensionIOXL9555.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 8 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 48 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 1 +#endif + +#ifndef SENSOR_RST +#define SENSOR_RST 1 +#endif + +TouchDrvFT6X36 touch; +ExtensionIOXL9555 extIO; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT); + + // T-RGB Use 0x20 device address + if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS0, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find XL9555 - check your wiring!"); + while (1) { + delay(1000); + } + } + + // Set PORT0 as output + extIO.configPort(ExtensionIOXL9555::PORT0, OUTPUT); + extIO.writePort(ExtensionIOXL9555::PORT0, 0xFF); + + extIO.digitalWrite(SENSOR_RST, LOW); + delay(300); + extIO.digitalWrite(SENSOR_RST, HIGH); + delay(300); + + + if (!touch.begin(Wire, FT3267_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find FT3267 - check your wiring!"); + while (1) { + delay(1000); + } + } + touch.interruptTrigger(); + + Serial.println("Init FT3267 Sensor success!"); +} + + +void loop() +{ + int16_t x[2], y[2]; + if (digitalRead(SENSOR_IRQ) == LOW) { + uint8_t touched = touch.getPoint(x, y, 2); + for (int i = 0; i < touched; ++i) { + Serial.print("X["); + Serial.print(i); + Serial.print("]:"); + Serial.print(x[i]); + Serial.print(" "); + Serial.print(" Y["); + Serial.print(i); + Serial.print("]:"); + Serial.print(y[i]); + Serial.print(" "); + } + Serial.println(); + } + delay(50); +} + + + diff --git a/lib/SensorLib/examples/TouchDrv_FT6232_GetPoint/TouchDrv_FT6232_GetPoint.ino b/lib/SensorLib/examples/TouchDrv_FT6232_GetPoint/TouchDrv_FT6232_GetPoint.ino new file mode 100644 index 0000000..54bf807 --- /dev/null +++ b/lib/SensorLib/examples/TouchDrv_FT6232_GetPoint/TouchDrv_FT6232_GetPoint.ino @@ -0,0 +1,92 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrv_FT6232_GetPoint.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-02 + * + */ +#include +#include +#include +#include "TouchDrvFT6X36.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 21 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 22 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 39 +#endif + +TouchDrvFT6X36 touch; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + pinMode(SENSOR_IRQ, INPUT); + + if (!touch.begin(Wire, FT6X36_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find FT6X36 - check your wiring!"); + while (1) { + delay(1000); + } + } + touch.interruptTrigger(); + + Serial.println("Init FT6X36 Sensor success!"); +} + + +void loop() +{ + int16_t x[2], y[2]; + if (digitalRead(SENSOR_IRQ) == LOW) { + uint8_t touched = touch.getPoint(x, y, 2); + for (int i = 0; i < touched; ++i) { + Serial.print("X["); + Serial.print(i); + Serial.print("]:"); + Serial.print(x[i]); + Serial.print(" "); + Serial.print(" Y["); + Serial.print(i); + Serial.print("]:"); + Serial.print(y[i]); + Serial.print(" "); + } + Serial.println(); + } + delay(50); +} + + + diff --git a/lib/SensorLib/examples/TouchDrv_GT911_GetPoint/TouchDrv_GT911_GetPoint.ino b/lib/SensorLib/examples/TouchDrv_GT911_GetPoint/TouchDrv_GT911_GetPoint.ino new file mode 100644 index 0000000..007282d --- /dev/null +++ b/lib/SensorLib/examples/TouchDrv_GT911_GetPoint/TouchDrv_GT911_GetPoint.ino @@ -0,0 +1,121 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file GT911_GetPoint.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-12 + * + */ +#include +#include +#include +#include "TouchDrvGT911.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 2 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 3 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 1 +#endif + +#ifndef SENSOR_RST +#define SENSOR_RST 10 +#endif + +TouchDrvGT911 touch; +int16_t x[5], y[5]; + + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + Wire.begin(SENSOR_SDA, SENSOR_SCL); + /* + * The touch reset pin uses hardware pull-up, + * and the function of setting the I2C device address cannot be used. + * Use scanning to obtain the touch device address. + * * */ + uint8_t touchAddress = 0; + Wire.beginTransmission(0x14); + if (Wire.endTransmission() == 0) { + touchAddress = 0x14; + } + Wire.beginTransmission(0x5D); + if (Wire.endTransmission() == 0) { + touchAddress = 0x5D; + } + if (touchAddress == 0) { + while (1) { + Serial.println("Failed to find GT911 - check your wiring!"); + delay(1000); + } + } + + touch.setPins(SENSOR_RST, SENSOR_IRQ); + + if (!touch.begin(Wire, touchAddress, SENSOR_SDA, SENSOR_SCL )) { + while (1) { + Serial.println("Failed to find GT911 - check your wiring!"); + delay(1000); + } + } + + //Set to trigger on falling edge + touch.setInterruptMode(FALLING); + + Serial.println("Init GT911 Sensor success!"); + +} + +void loop() +{ + if (touch.isPressed()) { + uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); + for (int i = 0; i < touched; ++i) { + Serial.print("X["); + Serial.print(i); + Serial.print("]:"); + Serial.print(x[i]); + Serial.print(" "); + Serial.print(" Y["); + Serial.print(i); + Serial.print("]:"); + Serial.print(y[i]); + Serial.print(" "); + } + Serial.println(); + } + delay(5); +} + + + diff --git a/lib/SensorLib/examples/TouchDrv_GT911_LilyGo_T_RGB/TouchDrv_GT911_LilyGo_T_RGB.ino b/lib/SensorLib/examples/TouchDrv_GT911_LilyGo_T_RGB/TouchDrv_GT911_LilyGo_T_RGB.ino new file mode 100644 index 0000000..77430a0 --- /dev/null +++ b/lib/SensorLib/examples/TouchDrv_GT911_LilyGo_T_RGB/TouchDrv_GT911_LilyGo_T_RGB.ino @@ -0,0 +1,161 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrv_GT911_LilyGo_T_RGB.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-12 + * + */ +#include +#include +#include +#include "TouchDrvGT911.hpp" +#include "ExtensionIOXL9555.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 8 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 48 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 1 +#endif + +#ifndef SENSOR_RST +#define SENSOR_RST 1 +#endif + +TouchDrvGT911 touch; +ExtensionIOXL9555 extIO; +int16_t x[5], y[5]; + +void scanDevices(void) +{ + byte error, address; + int nDevices = 0; + Serial.println("Scanning for I2C devices ..."); + for (address = 0x01; address < 0x7f; address++) { + Wire.beginTransmission(address); + error = Wire.endTransmission(); + if (error == 0) { + Serial.printf("I2C device found at address 0x%02X\n", address); + nDevices++; + } else if (error != 2) { + Serial.printf("Error %d at address 0x%02X\n", error, address); + } + } + if (nDevices == 0) { + Serial.println("No I2C devices found"); + } +} + + +void digitalWrite_CB(uint32_t pin, uint8_t value) +{ + extIO.digitalWrite(pin, value); +} + +void pinMode_CB(uint32_t pin, uint8_t mode) +{ + extIO.pinMode(pin, mode); +} + + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + Serial.println("Start!"); + +#ifdef ARDUINO_ARCH_RP2040 + Wire.setSCL(SENSOR_SCL); + Wire.setSDA(SENSOR_SDA); +#else + Wire.begin(SENSOR_SDA, SENSOR_SCL); +#endif + + scanDevices(); + + // T-RGB Use 0x20 device address + if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS0, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find XL9555 - check your wiring!"); + while (1) { + delay(1000); + } + } + // Set PORT0 as output + extIO.configPort(ExtensionIOXL9555::PORT0, OUTPUT); + extIO.writePort(ExtensionIOXL9555::PORT0, 0xFF); + + + touch.setPins(SENSOR_RST, SENSOR_IRQ); + touch.setGpioWriteCallback(digitalWrite_CB); + touch.setGpioModeCallback(pinMode_CB); + + if (!touch.begin(Wire, GT911_SLAVE_ADDRESS_L, SENSOR_SDA, SENSOR_SCL )) { + scanDevices(); + + while (1) { + Serial.println("Failed to find GT911 - check your wiring!"); + delay(1000); + } + } + + //Set to trigger on falling edge + touch.setInterruptMode(FALLING); + + Serial.println("Init GT911 Sensor success!"); + +} + +void loop() +{ + if (touch.isPressed()) { + uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); + if (touched) { + for (int i = 0; i < touched; ++i) { + Serial.print("X["); + Serial.print(i); + Serial.print("]:"); + Serial.print(x[i]); + Serial.print(" "); + Serial.print(" Y["); + Serial.print(i); + Serial.print("]:"); + Serial.print(y[i]); + Serial.print(" "); + } + Serial.println(); + } + } + delay(5); +} + + + + diff --git a/lib/SensorLib/examples/TouchDrv_Interface_T_RGB/TouchDrv_Interface_T_RGB.ino b/lib/SensorLib/examples/TouchDrv_Interface_T_RGB/TouchDrv_Interface_T_RGB.ino new file mode 100644 index 0000000..11e5317 --- /dev/null +++ b/lib/SensorLib/examples/TouchDrv_Interface_T_RGB/TouchDrv_Interface_T_RGB.ino @@ -0,0 +1,204 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2024 lewis he + * + * 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. + * + * @file TouchDrv_LilyGo_T_RGB.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2024-01-21 + * @note T-RGB has three types of screens, each of which uses different touch driver chips. + * The example demonstrates using the touch interface class and one sketch is suitable for three types of touch chips. + */ +#include +#include +#include +#include "ExtensionIOXL9555.hpp" +#include "TouchDrvGT911.hpp" +#include "TouchDrvFT6X36.hpp" +#include "TouchDrvCSTXXX.hpp" + + + +#ifndef SENSOR_SDA +#define SENSOR_SDA 8 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 48 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ 1 //ESP32S3 GPIO1 +#endif + +#ifndef SENSOR_RST +#define SENSOR_RST 1 //XL9555 GPIO1 +#endif + +TouchDrvInterface *touchDrv = NULL; +ExtensionIOXL9555 extension; + +ExtensionIOXL9555::ExtensionGPIO tp_reset = ExtensionIOXL9555::IO1; +ExtensionIOXL9555::ExtensionGPIO power_enable = ExtensionIOXL9555::IO2; + +int16_t x[5], y[5]; + + +//GPIO callback function +void TouchDrvDigitalWrite(uint32_t gpio, uint8_t level) +{ + if (gpio & 0x80) { + extension.digitalWrite(gpio & 0x7F, level); + } else { + digitalWrite(gpio, level); + } +} + +//GPIO callback function +int TouchDrvDigitalRead(uint32_t gpio) +{ + if (gpio & 0x80) { + return extension.digitalRead(gpio & 0x7F); + } else { + return digitalRead(gpio); + } +} + +//GPIO callback function +void TouchDrvPinMode(uint32_t gpio, uint8_t mode) +{ + if (gpio & 0x80) { + extension.pinMode(gpio & 0x7F, mode); + } else { + pinMode(gpio, mode); + } +} + + +bool setupTouchDrv() +{ + //Touch interrupt uses ESP32S3 GPIO1, touch reset uses XL9555 extended IO chip GPIO1, and needs to add a mask to distinguish + const uint8_t touch_reset_pin = 1 | 0x80; + const uint8_t touch_irq_pin = 1; + bool result = false; + + touchDrv = new TouchDrvCSTXXX(); + // T-RGB reset GPIO is connected through the expansion chip, and the GPIO callback function needs to be set. + touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead); + touchDrv->setPins(touch_reset_pin, touch_irq_pin); + result = touchDrv->begin(Wire, CST816_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL); + if (result) { + const char *model = touchDrv->getModelName(); + Serial.printf("Successfully initialized %s, using %s Driver!", model, model); + return true; + } + + delete touchDrv; + + touchDrv = new TouchDrvGT911(); + // T-RGB reset GPIO is connected through the expansion chip, and the GPIO callback function needs to be set. + touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead); + touchDrv->setPins(touch_reset_pin, touch_irq_pin); + result = touchDrv->begin(Wire, GT911_SLAVE_ADDRESS_H, SENSOR_SDA, SENSOR_SCL); + if (result) { + Serial.println("Successfully initialized GT911, using GT911 Driver!"); + return true; + } + delete touchDrv; + + touchDrv = new TouchDrvFT6X36(); + // T-RGB reset GPIO is connected through the expansion chip, and the GPIO callback function needs to be set. + touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead); + touchDrv->setPins(touch_reset_pin, touch_irq_pin); + result = touchDrv->begin(Wire, FT3267_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL); + if (result) { + const char *model = touchDrv->getModelName(); + Serial.printf("Successfully initialized %s, using %s Driver!", model, model); + return true; + } + delete touchDrv; + + return false; +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + Serial.println("Start!"); + +#ifdef ARDUINO_ARCH_RP2040 + Wire.setSCL(SENSOR_SCL); + Wire.setSDA(SENSOR_SDA); +#else + Wire.begin(SENSOR_SDA, SENSOR_SCL); +#endif + + // T-RGB XL9555 Use 0x20 device address + if (!extension.begin(Wire, XL9555_SLAVE_ADDRESS0, SENSOR_SDA, SENSOR_SCL)) { + while (1) { + Serial.println("Failed to find XL9555 - check your wiring!"); + delay(1000); + } + } + + // T-RGB power enable GPIO connected to XL9555 expansion chip GPIO + extension.pinMode(power_enable, OUTPUT); + extension.digitalWrite(power_enable, HIGH); + + // Initialize touch using touch driver interface class + if (!setupTouchDrv()) { + while (1) { + Serial.println("Failed to find touch - check your wiring!"); + delay(1000); + } + } +} + +void loop() +{ + if (touchDrv) { + if (touchDrv->isPressed()) { + uint8_t touched = touchDrv->getPoint(x, y, touchDrv->getSupportTouchPoint()); + if (touched) { + for (int i = 0; i < touched; ++i) { + Serial.print("X["); + Serial.print(i); + Serial.print("]:"); + Serial.print(x[i]); + Serial.print(" "); + Serial.print(" Y["); + Serial.print(i); + Serial.print("]:"); + Serial.print(y[i]); + Serial.print(" "); + } + Serial.println(); + } + } + } + delay(5); +} + + + + diff --git a/lib/SensorLib/examples/XL9555_ExtensionIOInterrupt/XL9555_ExtensionIOInterrupt.ino b/lib/SensorLib/examples/XL9555_ExtensionIOInterrupt/XL9555_ExtensionIOInterrupt.ino new file mode 100644 index 0000000..a61e5ad --- /dev/null +++ b/lib/SensorLib/examples/XL9555_ExtensionIOInterrupt/XL9555_ExtensionIOInterrupt.ino @@ -0,0 +1,83 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file XL9555_ExtensionIOInterrupt.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-01-03 + * + */ +#include +#include +#include +#include +#include "ExtensionIOXL9555.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +ExtensionIOXL9555 extIO; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + // Device address 0x20~0x27 + if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS4, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find XL9555 - check your wiring!"); + while (1) { + delay(1000); + } + } + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + // Set PORT0 as input,mask = 0xFF = all pin input + extIO.configPort(ExtensionIOXL9555::PORT0, 0xFF); + // Set PORT1 as input,mask = 0xFF = all pin input + extIO.configPort(ExtensionIOXL9555::PORT1, 0xFF); +} + +void loop() +{ + // When the interrupt occurs, we read the mask value of PORT + if (digitalRead(SENSOR_IRQ) == LOW) { + Serial.print("PORT0:0b"); + Serial.print(extIO.readPort(ExtensionIOXL9555::PORT0), BIN); + Serial.print("\tPORT1:0b"); + Serial.println(extIO.readPort(ExtensionIOXL9555::PORT1), BIN); + } +} + + + diff --git a/lib/SensorLib/examples/XL9555_ExtensionIORead/XL9555_ExtensionIORead.ino b/lib/SensorLib/examples/XL9555_ExtensionIORead/XL9555_ExtensionIORead.ino new file mode 100644 index 0000000..8849ae2 --- /dev/null +++ b/lib/SensorLib/examples/XL9555_ExtensionIORead/XL9555_ExtensionIORead.ino @@ -0,0 +1,117 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file XL9555_ExtensionIORead.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-01-03 + * + */ +#include +#include +#include +#include +#include "ExtensionIOXL9555.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +ExtensionIOXL9555 extIO; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + // Device address 0x20~0x27 + if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS4, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find XL9555 - check your wiring!"); + while (1) { + delay(1000); + } + } + + pinMode(SENSOR_IRQ, INPUT_PULLUP); + // Set PORT0 as input,mask = 0xFF = all pin input + extIO.configPort(ExtensionIOXL9555::PORT0, 0xFF); + // Set PORT1 as input,mask = 0xFF = all pin input + extIO.configPort(ExtensionIOXL9555::PORT1, 0xFF); +} + +void loop() +{ + Serial.print("PORT0:0b"); + Serial.print(extIO.readPort(ExtensionIOXL9555::PORT0), BIN); + Serial.print("\tPORT1:0b"); + Serial.println(extIO.readPort(ExtensionIOXL9555::PORT1), BIN); + + //Allowable range of parameter input: IO0 ~ IO15 + Serial.println("IO0:\tIO1:\tIO2:\tIO3:\tIO4:\tIO5:\tIO6:\tIO7:\tIO8:\tIO9:\tIO10:\tIO11:\tIO12:\tIO13:\tIO14:\tIO15:\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO0)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO1)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO2)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO3)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO4)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO5)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO6)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO7)); + Serial.print("\t"); + + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO8)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO9)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO10)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO11)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO12)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO13)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO14)); + Serial.print("\t"); + Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO15)); + Serial.println(); + delay(1000); +} + + + diff --git a/lib/SensorLib/examples/XL9555_ExtensionIOWirte/XL9555_ExtensionIOWirte.ino b/lib/SensorLib/examples/XL9555_ExtensionIOWirte/XL9555_ExtensionIOWirte.ino new file mode 100644 index 0000000..a3aac20 --- /dev/null +++ b/lib/SensorLib/examples/XL9555_ExtensionIOWirte/XL9555_ExtensionIOWirte.ino @@ -0,0 +1,94 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file XL9555_ExtensionIOWirte.ino + * @author Lewis He (lewishe@outlook.com) + * @date 2023-01-03 + * + */ +#include +#include +#include +#include +#include "ExtensionIOXL9555.hpp" + +#ifndef SENSOR_SDA +#define SENSOR_SDA 17 +#endif + +#ifndef SENSOR_SCL +#define SENSOR_SCL 18 +#endif + +#ifndef SENSOR_IRQ +#define SENSOR_IRQ -1 +#endif + +ExtensionIOXL9555 extIO; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + + + // Device address 0x20~0x27 + if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS4, SENSOR_SDA, SENSOR_SCL)) { + Serial.println("Failed to find XL9555 - check your wiring!"); + while (1) { + delay(1000); + } + } + // Set PORT0 as output ,mask = 0x00 = all pin output + extIO.configPort(ExtensionIOXL9555::PORT0, 0x00); + // Set PORT1 as output ,mask = 0x00 = all pin output + extIO.configPort(ExtensionIOXL9555::PORT1, 0x00); +} + +void loop() +{ + // Set all PORTs to 1, and the parameters here are mask values, corresponding to the 0~7 bits + Serial.println("Set port HIGH"); + extIO.writePort(ExtensionIOXL9555::PORT0, 0xFF); + delay(1000); + + Serial.println("Set port LOW"); + // Set all PORTs to 0, and the parameters here are mask values, corresponding to the 0~7 bits + extIO.writePort(ExtensionIOXL9555::PORT1, 0x00); + delay(1000); + + Serial.println("digitalWrite"); + extIO.digitalWrite(ExtensionIOXL9555::IO0, HIGH); + delay(1000); + + Serial.println("digitalToggle"); + extIO.digitalToggle(ExtensionIOXL9555::IO0); + delay(1000); + + +} + + + diff --git a/lib/SensorLib/keywords.txt b/lib/SensorLib/keywords.txt new file mode 100644 index 0000000..96b1e5e --- /dev/null +++ b/lib/SensorLib/keywords.txt @@ -0,0 +1,177 @@ +####################################### +# Syntax Coloring Map For SensorLib By lewis He +# github:https://github.com/lewisxhe +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### +ExtensionIOXL9555 KEYWORD1 +RTC_DateTime KEYWORD1 +RTC_Alarm KEYWORD1 +SensorPCF8563 KEYWORD1 +SensorQMC6310 KEYWORD1 +MagRange KEYWORD1 +OutputRate KEYWORD1 +CtrlReg KEYWORD1 +OverSampleRatio KEYWORD1 +DownSampleRatio KEYWORD1 + +SensorQMI8658 KEYWORD1 +AccelRange KEYWORD1 +GyroRange KEYWORD1 +AccelODR KEYWORD1 +GyroODR KEYWORD1 +LpfMode KEYWORD1 +MotionEvent KEYWORD1 +IntPin KEYWORD1 +Fifo_Samples KEYWORD1 +FIFO_Mode KEYWORD1 +SampleMode KEYWORD1 +CommandTable KEYWORD1 +StatusReg KEYWORD1 +TagPriority KEYWORD1 +SensorStatus KEYWORD1 + + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +# XL9555 Coloring Map + +init KEYWORD2 +deinit KEYWORD2 +pinMode KEYWORD2 +digitalRead KEYWORD2 +digitalWrite KEYWORD2 +digitalToggle KEYWORD2 +readPort KEYWORD2 +writePort KEYWORD2 +readConfig KEYWORD2 +configPort KEYWORD2 + + +# PCF8563 Coloring Map +setDateTime KEYWORD2 +getDateTime KEYWORD2 +getAlarm KEYWORD2 +enableAlarm KEYWORD2 +disableAlarm KEYWORD2 +resetAlarm KEYWORD2 +isAlarmActive KEYWORD2 +setAlarm KEYWORD2 +setAlarmByMinutes KEYWORD2 +setAlarmByDays KEYWORD2 +setAlarmByHours KEYWORD2 +setAlarmByWeekDay KEYWORD2 +isCountdownTimerEnable KEYWORD2 +isCountdownTimerActive KEYWORD2 +enableCountdownTimer KEYWORD2 +disableCountdownTimer KEYWORD2 +setCountdownTimer KEYWORD2 +clearCountdownTimer KEYWORD2 +enableCLK KEYWORD2 +strftime KEYWORD2 +conversionUnixTime KEYWORD2 +hwClockRead KEYWORD2 +hwClockWrite KEYWORD2 +getDayOfWeek KEYWORD2 +getNextMonth KEYWORD2 +getNextYear KEYWORD2 +getLeapYear KEYWORD2 +getDaysInMonth KEYWORD2 + +# SensorQMC6310 Coloring Map +reset KEYWORD2 +getChipID KEYWORD2 +getStatus KEYWORD2 +isDataReady KEYWORD2 +isDataOverflow KEYWORD2 +setSelfTest KEYWORD2 +setMode KEYWORD2 +setCtrlRegister KEYWORD2 +setDataOutputRate KEYWORD2 +setOverSampleRate KEYWORD2 +setDownSampleRate KEYWORD2 +setSign KEYWORD2 +configMagnetometer KEYWORD2 +setMagRange KEYWORD2 +setOffset KEYWORD2 +readData KEYWORD2 +setDeclination KEYWORD2 +readPolar KEYWORD2 +getRawX KEYWORD2 +getRawY KEYWORD2 +getRawZ KEYWORD2 +getX KEYWORD2 +getY KEYWORD2 +getZ KEYWORD2 +getMag KEYWORD2 +dumpCtrlRegister KEYWORD2 + +# SensorQMI8658 Coloring Map +whoAmI KEYWORD2 +getTimestamp KEYWORD2 +getTemperature_C KEYWORD2 +enableINT KEYWORD2 +getIrqStatus KEYWORD2 +enableDataReadyINT KEYWORD2 +configAccelerometer KEYWORD2 +configGyroscope KEYWORD2 +configFIFO KEYWORD2 +getFifoNeedBytes KEYWORD2 +readFromFifo KEYWORD2 +enableAccelerometer KEYWORD2 +disableAccelerometer KEYWORD2 +isEnableAccelerometer KEYWORD2 +isEnableGyroscope KEYWORD2 +enableGyroscope KEYWORD2 +disableGyroscope KEYWORD2 +getAccelRaw KEYWORD2 +getAccelerometer KEYWORD2 +getAccelerometerScales KEYWORD2 +getGyroscopeScales KEYWORD2 +getGyroRaw KEYWORD2 +getGyroscope KEYWORD2 +getDataReady KEYWORD2 +enableSyncSampleMode KEYWORD2 +disableSyncSampleMode KEYWORD2 +enableLockingMechanism KEYWORD2 +disableLockingMechanism KEYWORD2 +powerDown KEYWORD2 +powerOn KEYWORD2 +getStatusRegister KEYWORD2 +configActivityInterruptMap KEYWORD2 +configPedometer KEYWORD2 +getPedometerCounter KEYWORD2 +clearPedometerCounter KEYWORD2 +enablePedometer KEYWORD2 +disablePedometer KEYWORD2 +configTap KEYWORD2 +enableTap KEYWORD2 +disableTap KEYWORD2 +getTapStatus KEYWORD2 +configMotion KEYWORD2 +enableMotionDetect KEYWORD2 +disableMotionDetect KEYWORD2 +configWakeOnMotion KEYWORD2 +getChipUsid KEYWORD2 +getChipFirmwareVersion KEYWORD2 +readSensorStatus KEYWORD2 +setWakeupMotionEventCallBack KEYWORD2 +setTapEventCallBack KEYWORD2 +setPedometerEventCallBack KEYWORD2 +setNoMotionEventCallBack KEYWORD2 +setAnyMotionEventCallBack KEYWORD2 +setSignificantMotionEventCallBack KEYWORD2 +setGyroDataReadyCallBack KEYWORD2 +setAccelDataReadyEventCallBack KEYWORD2 +setDataLockingEvevntCallBack KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### + + diff --git a/lib/SensorLib/library.json b/lib/SensorLib/library.json new file mode 100644 index 0000000..dea1a44 --- /dev/null +++ b/lib/SensorLib/library.json @@ -0,0 +1,32 @@ +{ + "name": "SensorLib", + "version": "0.2.0", + "description": "Commonly used I2C , SPI device multi-platform libraries", + "keywords": "QMC6310, QMI8658, PCF8563, PCF85063, XL9555, BMA423, BHI260AP, DRV2605, CM32181, LTR553, FT5206, FT3267, FT6236, FT6336, CST816S,CST816T,CST816D, CST820, CST226, CHSC5816, GT911", + "authors": [ + { + "name": "LewisHe", + "url": "https://github.com/lewisxhe", + "maintainer": true + } + ], + "repository": { + "type": "git", + "url": "https://github.com/lewisxhe/SensorsLib.git" + }, + "homepage": "https://github.com/lewisxhe/SensorsLib", + "export": { + "include": [ + "LICENSE", + "library.json", + "library.properties", + "README.md", + "keywords.txt", + "src/*", + "examples/*" + ] + }, + "frameworks": ["arduino", "espidf"], + "platforms": "esp32,raspberrypi,ststm32,espressif32", + "license": "MIT" +} diff --git a/lib/SensorLib/library.properties b/lib/SensorLib/library.properties new file mode 100644 index 0000000..997034c --- /dev/null +++ b/lib/SensorLib/library.properties @@ -0,0 +1,9 @@ +name=SensorLib +version=0.2.0 +author=Lewis He +maintainer=Lewis He +sentence=Commonly used I2C , SPI device multi-platform libraries +paragraph=Support QMC6310,QMI8658,PCF8563,PCF85063,XL9555,BMA423,BHI260AP,DRV2605,CM32181,LTR553,FT5206,FT3267,FT6236,FT6336,CST816S/T/D,CST820,CST226,CHSC5816,GT911 +category=Communication +url=https://github.com/lewisxhe/SensorsLib +architectures=esp32 diff --git a/lib/SensorLib/src/ExtensionIOXL9555.hpp b/lib/SensorLib/src/ExtensionIOXL9555.hpp new file mode 100644 index 0000000..01e6d09 --- /dev/null +++ b/lib/SensorLib/src/ExtensionIOXL9555.hpp @@ -0,0 +1,204 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file ExtensionIOXL9555.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2022-12-27 + * + */ +#pragma once + +#include "REG/XL9555Constants.h" +#include "SensorCommon.tpp" +#include "ExtensionSPI.tpp" + +class ExtensionIOXL9555 : + public SensorCommon, + public ExtensionSPI +{ + friend class SensorCommon; + friend class ExtensionSPI; +public: + + enum { + PORT0, + PORT1, + }; + + enum ExtensionGPIO { + IO0, + IO1, + IO2, + IO3, + IO4, + IO5, + IO6, + IO7, + IO8, + IO9, + IO10, + IO11, + IO12, + IO13, + IO14, + IO15, + }; + + +#if defined(ARDUINO) + ExtensionIOXL9555(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = XL9555_SLAVE_ADDRESS0) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + ExtensionIOXL9555() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = XL9555_SLAVE_ADDRESS0; + } + + ~ExtensionIOXL9555() + { + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = XL9555_SLAVE_ADDRESS0) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + + void pinMode(uint8_t pin, uint8_t mode) + { + uint8_t registers = 0; + if (pin >= IO8) { + pin -= IO8; + registers = XL9555_CTRL_CFG1; + } else { + registers = XL9555_CTRL_CFG0; + } + switch (mode) { + case INPUT: + setRegisterBit(registers, pin); + break; + case OUTPUT: + clrRegisterBit(registers, pin); + break; + default: + break; + } + } + + int digitalRead(uint8_t pin) + { + uint8_t registers = 0; + if (pin >= IO8) { + pin -= IO8; + registers = XL9555_CTRL_INP1; + } else { + registers = XL9555_CTRL_INP0; + } + return getRegisterBit(registers, pin); + } + + void digitalWrite(uint8_t pin, uint8_t val) + { + uint8_t registers = 0; + if (pin >= IO8) { + pin -= IO8; + registers = XL9555_CTRL_OUTP1; + } else { + registers = XL9555_CTRL_OUTP0; + } + val ? setRegisterBit(registers, pin) : clrRegisterBit(registers, pin); + } + + void digitalToggle(uint8_t pin) + { + int state = 1 - digitalRead(pin); + digitalWrite(pin, state); + } + + int readPort(uint8_t port) + { + return readRegister(port == PORT0 ? XL9555_CTRL_INP0 : XL9555_CTRL_INP1); + } + + int writePort(uint8_t port, uint8_t mask) + { + return writeRegister(port == PORT0 ? XL9555_CTRL_OUTP0 : XL9555_CTRL_OUTP1, mask); + } + + int readConfig(uint8_t port) + { + return readRegister(port == PORT0 ? XL9555_CTRL_CFG0 : XL9555_CTRL_CFG1); + } + + int configPort(uint8_t port, uint8_t mask) + { + return writeRegister(port == PORT0 ? XL9555_CTRL_CFG0 : XL9555_CTRL_CFG1, mask); + } + + +private: + bool initImpl() + { + int cfg1 = readConfig(PORT0); + if (cfg1 == DEV_WIRE_ERR)return false; + configPort(PORT0, 0x03); + uint8_t val = readConfig(PORT0); + if (val != 0x03) { + return false; + } + writePort(PORT0, cfg1); + return true; + } + + int getReadMaskImpl() + { + return -1; + } + +protected: + +}; + + + diff --git a/lib/SensorLib/src/ExtensionSPI.tpp b/lib/SensorLib/src/ExtensionSPI.tpp new file mode 100644 index 0000000..2c002cc --- /dev/null +++ b/lib/SensorLib/src/ExtensionSPI.tpp @@ -0,0 +1,124 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2024 lewis he + * + * 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. + * + * @file ExtensionSPI.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2024-01-19 + * + */ +#pragma once + +#include "SensorLib.h" + +template +class ExtensionSPI +{ +public: + void beginSPI(int mosi, + int miso, + int sck, + int cs + ) + { + _mosi = mosi; + _miso = miso; + _sck = sck; + _cs = cs; + + thisChip().pinMode(_mosi, OUTPUT); + thisChip().pinMode(_sck, OUTPUT); + + if (_cs != SENSOR_PIN_NONE) { + thisChip().pinMode(_cs, OUTPUT); + thisChip().digitalWrite(_cs, HIGH); + } + + if (_miso != SENSOR_PIN_NONE) { + thisChip().pinMode(_miso, INPUT); + } + thisChip().digitalWrite(_mosi, HIGH); + thisChip().digitalWrite(_sck, HIGH); + + } + + void setBitOrder(uint8_t order) + { + _order = order & 1; + } + + uint8_t transfer8(uint8_t val) + { + return transferDataBits(val, 8); + } + + uint16_t transfer9(uint16_t val) + { + return transferDataBits(val, 9); + } + + uint32_t transferDataBits(uint32_t val, uint32_t bits) + { + uint32_t mask = _BV(bits - 1); + uint8_t out = 0; + if (_cs != SENSOR_PIN_NONE) { + thisChip().digitalWrite(_cs, LOW); + } + for (int i = 0; i < bits ; i++) { + thisChip().digitalWrite(_sck, LOW); + out <<= 1; + if (_miso != SENSOR_PIN_NONE) { + if (thisChip().digitalRead(_miso)) { + out |= 0x01; + } + } + thisChip().digitalWrite(_mosi, val & mask ? HIGH : LOW); + val <<= 1; + thisChip().digitalWrite(_sck, HIGH); + } + if (_cs != SENSOR_PIN_NONE) { + thisChip().digitalWrite(_cs, HIGH); + } + return out; + } + + +protected: + + inline const chipType &thisChip() const + { + return static_cast(*this); + } + + inline chipType &thisChip() + { + return static_cast(*this); + } + +private: + int _mosi; + int _sck; + int _miso; + int _order; + int _cs; +}; \ No newline at end of file diff --git a/lib/SensorLib/src/REG/BMA423Constants.h b/lib/SensorLib/src/REG/BMA423Constants.h new file mode 100644 index 0000000..d969cbd --- /dev/null +++ b/lib/SensorLib/src/REG/BMA423Constants.h @@ -0,0 +1,726 @@ +#pragma once + + +#define BMA423_SLAVE_ADDRESS (0x19) + + +#define BAM423_SENSOR_RESOLUTION (12) + +#define BMA423_RESET_REG (0x7E) + +/**\name CHIP ID ADDRESS*/ +#define BMA4_CHIP_ID_ADDR (0x00) + +/**\name Chip ID of BMA423 sensor */ +#define BMA423_CHIP_ID (0x13) + +/**\name POWER_CTRL REGISTER*/ +#define BMA4_POWER_CONF_ADDR (0x7C) +#define BMA4_POWER_CTRL_ADDR (0x7D) + + +/**\name ADVANCE POWER SAVE POSITION AND MASK*/ +#define BMA4_ADVANCE_POWER_SAVE_MSK (0x01) + +/**\name MAP INTERRUPT 1 and 2 REGISTERS*/ +#define BMA4_INT_MAP_1_ADDR (0X56) +#define BMA4_INT_MAP_2_ADDR (0X57) +#define BMA4_INT_MAP_DATA_ADDR (0x58) +#define BMA4_INIT_CTRL_ADDR (0x59) + + +/**\name FEATURE CONFIG RELATED */ +#define BMA4_RESERVED_REG_5B_ADDR (0x5B) +#define BMA4_RESERVED_REG_5C_ADDR (0x5C) +#define BMA4_FEATURE_CONFIG_ADDR (0x5E) +#define BMA4_INTERNAL_ERROR (0x5F) + +/**\name GPIO REGISTERS*/ +#define BMA4_STEP_CNT_OUT_0_ADDR (0x1E) +#define BMA4_HIGH_G_OUT_ADDR (0x1F) +#define BMA4_ACTIVITY_OUT_ADDR (0x27) +#define BMA4_ORIENTATION_OUT_ADDR (0x28) +#define BMA4_INTERNAL_STAT (0x2A) + + + + +/**\name SENSOR TIME REGISTERS*/ +#define BMA4_SENSORTIME_0_ADDR (0X18) + +/**\name INTERRUPT/FEATURE STATUS REGISTERS*/ +#define BMA4_INT_STAT_0_ADDR (0X1C) + +/**\name INTERRUPT/FEATURE STATUS REGISTERS*/ +#define BMA4_INT_STAT_1_ADDR (0X1D) + +/**\name BUS READ AND WRITE LENGTH FOR MAG & ACCEL*/ +#define BMA4_MAG_TRIM_DATA_SIZE (16) +#define BMA4_MAG_XYZ_DATA_LENGTH (6) +#define BMA4_MAG_XYZR_DATA_LENGTH (8) +#define BMA4_ACCEL_DATA_LENGTH (6) +#define BMA4_FIFO_DATA_LENGTH (2) +#define BMA4_TEMP_DATA_SIZE (1) + +/**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/ +#define BMA4_DATA_0_ADDR (0X0A) +#define BMA4_DATA_8_ADDR (0X12) + + +/**\name Feature offset address */ +#define BMA423_ANY_NO_MOTION_OFFSET (0x00) +#define BMA423_STEP_CNTR_OFFSET (0x36) +#define BMA423_STEP_CNTR_PARAM_OFFSET (0x04) +#define BMA423_WAKEUP_OFFSET (0x38) +#define BMA423_TILT_OFFSET (0x3A) +#define BMA423_CONFIG_ID_OFFSET (0x3C) +#define BMA423_AXES_REMAP_OFFSET (0x3E) + +/**\name Sensor feature size */ +#define BMA423_FEATURE_SIZE (64) +#define BMA423_ANYMOTION_EN_LEN (2) +#define BMA423_RD_WR_MIN_LEN (2) + +/**************************************************************/ +/**\name Remap Axes */ +/**************************************************************/ +#define BMA423_X_AXIS_MASK (0x03) +#define BMA423_X_AXIS_SIGN_MASK (0x04) +#define BMA423_Y_AXIS_MASK (0x18) +#define BMA423_Y_AXIS_SIGN_MASK (0x20) +#define BMA423_Z_AXIS_MASK (0xC0) +#define BMA423_Z_AXIS_SIGN_MASK (0x01) + + + +/**\name ACCELEROMETER ENABLE POSITION AND MASK*/ +#define BMA4_ACCEL_ENABLE_MSK (0x04) +#define BMA4_ASIC_INITIALIZED (0x01) + +#define BMA4_CONFIG_STREAM_SIZE (6144) + + +/**\name Feature configuration file */ +static const unsigned char bma423_config_file[] = { + 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfe, 0x00, 0xc8, 0x2e, 0x00, 0x2e, + 0x80, 0x2e, 0xfa, 0x00, 0x80, 0x2e, 0x23, 0xb1, 0x80, 0x2e, 0xfd, 0x00, + 0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0x5a, 0xb1, 0x50, 0x39, 0x21, 0x2e, + 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfc, 0x01, + 0x5d, 0x50, 0x45, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42, + 0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf, + 0xb8, 0x2e, 0xb6, 0xd6, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0xfd, 0x2d, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x24, 0x01, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x98, 0x2e, + 0x99, 0x01, 0x20, 0x26, 0x98, 0x2e, 0xf6, 0x00, 0x98, 0x2e, 0xe9, 0x01, + 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, + 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xdd, 0x00, 0x01, 0x2e, 0x56, 0x00, + 0x00, 0xb2, 0x11, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x56, 0x00, 0x41, 0x50, + 0x98, 0x2e, 0xcc, 0xb0, 0x41, 0x50, 0x98, 0x2e, 0x8f, 0xb4, 0x01, 0x2e, + 0x03, 0xf0, 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x45, 0x50, + 0x21, 0x2e, 0xbc, 0xf0, 0x01, 0x2e, 0x55, 0x00, 0x00, 0xb2, 0x1a, 0x2f, + 0x00, 0x30, 0x21, 0x2e, 0x55, 0x00, 0x43, 0x50, 0x98, 0x2e, 0xcc, 0xb0, + 0x43, 0x50, 0x98, 0x2e, 0xdc, 0xb1, 0x43, 0x50, 0x98, 0x2e, 0x92, 0xb5, + 0x43, 0x50, 0x98, 0x2e, 0x00, 0xb0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc, + 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0, + 0x02, 0x2d, 0x21, 0x2e, 0xba, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0xc3, 0x2d, + 0x01, 0x2e, 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x03, 0x2e, + 0x00, 0xf0, 0x45, 0x54, 0x01, 0x2e, 0x59, 0xf0, 0x4a, 0x0e, 0x02, 0x2f, + 0xf1, 0x33, 0x0d, 0x2c, 0x01, 0x08, 0xf2, 0x30, 0x4a, 0x08, 0x79, 0x84, + 0x82, 0xa2, 0x04, 0x2f, 0x02, 0x34, 0x82, 0x0a, 0x47, 0xa2, 0x03, 0x2c, + 0x10, 0x22, 0x45, 0x52, 0x01, 0x0a, 0xc0, 0x2e, 0x21, 0x2e, 0x59, 0xf0, + 0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, 0xc8, 0x2e, + 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0x44, 0x47, 0xaa, 0x00, 0x05, 0x00, + 0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, 0x04, 0x00, 0x3f, 0x7b, + 0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04, 0xec, 0xe6, 0x0c, 0x46, + 0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00, 0xa0, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x43, 0x28, 0x88, 0x00, + 0x52, 0x00, 0x4f, 0x00, 0x80, 0x00, 0x5b, 0x00, 0x00, 0x40, 0xaf, 0x00, + 0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0, + 0xc0, 0x00, 0x00, 0x01, 0x5e, 0xf0, 0x39, 0xf0, 0x89, 0xf0, 0x00, 0x20, + 0xff, 0x7f, 0x7d, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x7c, 0x00, 0xff, 0xfb, + 0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, 0x90, 0x01, + 0x00, 0xf8, 0x67, 0x00, 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00, + 0x82, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0xeb, 0x07, 0xae, 0x07, + 0x72, 0x00, 0x6f, 0x00, 0xa1, 0x01, 0x1e, 0x05, 0x47, 0xfd, 0x73, 0x00, + 0x77, 0x00, 0x79, 0x00, 0x76, 0x00, 0xcc, 0x00, 0x30, 0x50, 0x50, 0x40, + 0x00, 0x18, 0x50, 0x40, 0x56, 0x25, 0x47, 0x25, 0x00, 0x18, 0x2e, 0x00, + 0x41, 0x40, 0xa7, 0x02, 0x09, 0x18, 0xc6, 0x00, 0xfb, 0x7f, 0x00, 0x30, + 0x49, 0x52, 0x05, 0x30, 0x05, 0x2c, 0x17, 0x03, 0x1e, 0xbd, 0xd2, 0xba, + 0x92, 0xb8, 0x6a, 0x0b, 0x61, 0x0e, 0xf9, 0x2f, 0x61, 0x1a, 0x01, 0x2f, + 0x5d, 0x0e, 0xf5, 0x2f, 0xd4, 0x7f, 0x02, 0x30, 0x1f, 0x2c, 0xe3, 0x7f, + 0x85, 0x01, 0xd1, 0x03, 0x7c, 0x0e, 0x03, 0x2f, 0x7c, 0x1a, 0x0f, 0x2f, + 0x73, 0x0f, 0x0d, 0x2f, 0xe3, 0x6f, 0xde, 0x04, 0x5f, 0xba, 0x11, 0xbf, + 0xb4, 0x0b, 0xd4, 0x6f, 0x27, 0x07, 0xb3, 0x25, 0xd1, 0xbf, 0xeb, 0x7f, + 0x07, 0x00, 0xb4, 0x25, 0x96, 0x02, 0xdb, 0x7f, 0x2f, 0xbf, 0x9e, 0xbf, + 0x01, 0xb8, 0xd2, 0xba, 0x21, 0xb9, 0x92, 0xb8, 0x06, 0x0a, 0x6f, 0x0b, + 0x40, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f, + 0xb8, 0x2e, 0x57, 0x50, 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42, + 0x18, 0x82, 0x4b, 0x50, 0x60, 0x42, 0x70, 0x3c, 0x4d, 0x54, 0x42, 0x42, + 0x69, 0x82, 0x82, 0x32, 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42, + 0x42, 0x80, 0x02, 0x3f, 0x01, 0x40, 0x10, 0x50, 0x4a, 0x08, 0xfb, 0x7f, + 0x11, 0x42, 0x0b, 0x31, 0x0b, 0x42, 0x3e, 0x80, 0x01, 0x32, 0x01, 0x42, + 0x00, 0x2e, 0x01, 0x2e, 0x40, 0xf0, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30, + 0x51, 0x50, 0x4f, 0x54, 0xf4, 0x34, 0x06, 0x30, 0x55, 0x52, 0x55, 0x32, + 0x1d, 0x1a, 0xe3, 0x22, 0x18, 0x1a, 0x53, 0x58, 0xe3, 0x22, 0x04, 0x30, + 0xd5, 0x40, 0xb5, 0x0d, 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d, + 0x01, 0x89, 0xb5, 0x23, 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0xf4, 0x34, + 0xeb, 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30, + 0x02, 0x2c, 0x08, 0x22, 0x30, 0x30, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, + 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, + 0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xb1, 0xf0, 0x59, 0x52, + 0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc, + 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e, + 0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0x1a, 0x24, 0x26, 0x00, + 0x80, 0x2e, 0x8f, 0x00, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x01, 0x01, + 0x92, 0xbd, 0x20, 0x50, 0x03, 0x2e, 0x01, 0x01, 0xbf, 0xba, 0x21, 0xbd, + 0x2f, 0xbb, 0x1f, 0xba, 0x40, 0x91, 0xf0, 0x7f, 0x04, 0x2f, 0x80, 0x91, + 0x02, 0x2f, 0x00, 0xb3, 0x90, 0x2e, 0xc7, 0xb0, 0x03, 0x2e, 0x7b, 0x00, + 0x01, 0x80, 0x40, 0x90, 0x14, 0x2f, 0x41, 0x84, 0xf1, 0x6f, 0x25, 0x2e, + 0x7b, 0x00, 0x41, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x47, 0x52, 0x12, 0x40, + 0x52, 0x42, 0x02, 0x30, 0x00, 0x40, 0x40, 0x42, 0xe0, 0x5f, 0x25, 0x2e, + 0x57, 0x00, 0x25, 0x2e, 0x58, 0x00, 0x25, 0x2e, 0x5d, 0x00, 0xb8, 0x2e, + 0x07, 0x2e, 0x00, 0x01, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x00, 0x01, + 0x24, 0xbd, 0x0f, 0x2e, 0x59, 0x00, 0xb5, 0xbd, 0x93, 0xbc, 0x2f, 0xb9, + 0xb5, 0xb9, 0x93, 0xb8, 0x3a, 0x1a, 0x06, 0x2f, 0x07, 0x30, 0x25, 0x2e, + 0x59, 0x00, 0x2f, 0x2e, 0x57, 0x00, 0x2f, 0x2e, 0x58, 0x00, 0x40, 0xb3, + 0x05, 0x30, 0x07, 0x30, 0x0a, 0x2f, 0xf7, 0x6f, 0xe6, 0x7f, 0x00, 0x2e, + 0xc6, 0x41, 0x0f, 0x2e, 0x5a, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xee, 0x05, + 0xf7, 0x23, 0xe6, 0x6f, 0x80, 0xb3, 0x06, 0x30, 0x09, 0x2f, 0xe7, 0x7f, + 0x00, 0x2e, 0x06, 0x40, 0x0f, 0x2e, 0x5b, 0x00, 0xb7, 0x05, 0x80, 0xa9, + 0xee, 0x05, 0xb7, 0x23, 0xe7, 0x6f, 0x00, 0xb3, 0x04, 0x30, 0x0b, 0x2f, + 0xf4, 0x6f, 0x02, 0x89, 0xe7, 0x7f, 0x00, 0x2e, 0x04, 0x41, 0x0f, 0x2e, + 0x5c, 0x00, 0x27, 0x05, 0x00, 0xa9, 0xec, 0x05, 0x27, 0x23, 0xe7, 0x6f, + 0x7b, 0x0f, 0x17, 0x30, 0x0b, 0x2f, 0x73, 0x0f, 0x05, 0x30, 0x17, 0x30, + 0x07, 0x2f, 0x63, 0x0f, 0x15, 0x30, 0x17, 0x30, 0x00, 0x2f, 0x07, 0x30, + 0xe3, 0x0e, 0x00, 0x2f, 0x05, 0x30, 0x80, 0x90, 0x05, 0x2e, 0x57, 0x00, + 0x13, 0x30, 0x13, 0x29, 0xf2, 0x6f, 0x47, 0x5c, 0x17, 0x2f, 0xc0, 0x91, + 0x05, 0x30, 0x0b, 0x2f, 0x07, 0x2e, 0x58, 0x00, 0xc1, 0x86, 0x2b, 0x2e, + 0x57, 0x00, 0x59, 0x0e, 0x27, 0x2e, 0x58, 0x00, 0x24, 0x2f, 0x2b, 0x2e, + 0x5d, 0x00, 0x22, 0x2d, 0x61, 0x0e, 0x29, 0x2e, 0x57, 0x00, 0x2b, 0x2e, + 0x58, 0x00, 0x1b, 0x2f, 0x27, 0x2e, 0x5d, 0x00, 0x19, 0x2d, 0x40, 0x91, + 0x05, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x57, 0x00, 0x23, 0x2e, 0x5d, 0x00, + 0x06, 0x2d, 0x29, 0x2e, 0x57, 0x00, 0x61, 0x0e, 0x01, 0x2f, 0x27, 0x2e, + 0x5d, 0x00, 0x81, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x30, 0x25, 0x47, 0x52, + 0xd4, 0x40, 0x54, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x43, 0x42, 0x00, 0x2e, + 0x03, 0x2e, 0x5d, 0x00, 0x40, 0xb2, 0x0d, 0x2f, 0x81, 0x40, 0x23, 0x2e, + 0x5a, 0x00, 0x11, 0x40, 0x91, 0x43, 0x01, 0x34, 0x00, 0x40, 0x80, 0x43, + 0x23, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00, + 0xe0, 0x5f, 0xb8, 0x2e, 0x50, 0x50, 0xf0, 0x7f, 0x1a, 0x25, 0x13, 0x40, + 0x7b, 0x84, 0xe0, 0x7f, 0x83, 0x42, 0x35, 0x30, 0x11, 0x40, 0x04, 0x40, + 0xc1, 0x7f, 0xd4, 0x7f, 0x86, 0x31, 0x07, 0x2e, 0x59, 0xf0, 0x03, 0x2e, + 0x1f, 0x01, 0x0d, 0x09, 0x02, 0xab, 0x05, 0x30, 0x8e, 0x09, 0x2c, 0x23, + 0xe3, 0xba, 0x42, 0xab, 0x16, 0x30, 0x75, 0x23, 0x59, 0x5c, 0x8e, 0x09, + 0x66, 0xbb, 0x82, 0xab, 0x27, 0x30, 0xbe, 0x23, 0x3e, 0x80, 0x25, 0x1a, + 0x06, 0x2f, 0x2e, 0x1a, 0x04, 0x2f, 0x26, 0x1a, 0x02, 0x2f, 0xf7, 0x3d, + 0x03, 0x2c, 0xdf, 0x08, 0x07, 0x32, 0xdf, 0x0a, 0x14, 0x01, 0x55, 0x01, + 0x04, 0x41, 0x14, 0x42, 0x16, 0x01, 0x42, 0x41, 0x45, 0x30, 0x4d, 0x09, + 0x04, 0x41, 0x12, 0x42, 0x04, 0x42, 0x40, 0xb3, 0x04, 0x2f, 0xf0, 0x6f, + 0x02, 0x30, 0x04, 0x40, 0x94, 0x04, 0x02, 0x42, 0x00, 0x32, 0x08, 0x08, + 0x00, 0xb2, 0x00, 0x30, 0x05, 0x2f, 0xe2, 0x6f, 0x00, 0x2e, 0x84, 0x40, + 0x04, 0x05, 0x84, 0x42, 0x00, 0x2e, 0x5b, 0x54, 0x4a, 0x08, 0x40, 0xb2, + 0xf1, 0x6f, 0x04, 0x2f, 0x42, 0x82, 0x00, 0x2e, 0x42, 0x40, 0x02, 0x04, + 0x40, 0x42, 0xb0, 0x5f, 0x27, 0x2e, 0x59, 0xf0, 0xb8, 0x2e, 0x50, 0x50, + 0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0, 0xf8, 0xbf, 0xff, 0xbb, + 0xc0, 0xb3, 0x2a, 0x2f, 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xe6, 0x7f, + 0x7e, 0xbb, 0xd5, 0x7f, 0x37, 0x30, 0x5f, 0x5a, 0xbe, 0x05, 0x67, 0x41, + 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11, + 0x41, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41, + 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30, + 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42, + 0x29, 0x2e, 0x56, 0x00, 0x45, 0x56, 0x27, 0x2e, 0xb8, 0xf0, 0xe6, 0x6f, + 0xd5, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xf7, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e, + 0x50, 0x50, 0xe5, 0x7f, 0xd7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0b, 0x2e, + 0x01, 0xf0, 0xde, 0xbe, 0xde, 0xbb, 0x61, 0x5a, 0xb7, 0x05, 0x67, 0x41, + 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11, + 0x43, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41, + 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30, + 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42, + 0x29, 0x2e, 0x55, 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, + 0xe5, 0x6f, 0xd7, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e, + 0x40, 0x50, 0xf6, 0x7f, 0x1a, 0x18, 0x63, 0x56, 0x33, 0x00, 0x06, 0x30, + 0xfe, 0x03, 0x0e, 0xb8, 0xf2, 0xbf, 0x07, 0x0a, 0x2a, 0x18, 0x63, 0x5a, + 0xb5, 0x01, 0x03, 0x30, 0xfb, 0x03, 0x6e, 0xbb, 0xf2, 0xbf, 0xe1, 0x7f, + 0xf7, 0x0b, 0x56, 0x40, 0x36, 0x25, 0x46, 0x40, 0x06, 0x28, 0xc7, 0x7f, + 0x22, 0x18, 0xd1, 0x7f, 0xb5, 0x00, 0x01, 0x30, 0x39, 0x03, 0x2e, 0xb9, + 0x42, 0xbe, 0x14, 0x0b, 0xf2, 0x6f, 0x10, 0x18, 0xb5, 0x00, 0xb9, 0x03, + 0x2e, 0xb9, 0x62, 0xbf, 0x96, 0x0a, 0xb6, 0x6f, 0x30, 0x18, 0x75, 0x01, + 0xb9, 0x03, 0x5c, 0x28, 0xe2, 0xbf, 0xde, 0xb9, 0xd6, 0x6f, 0xdf, 0x0a, + 0x8a, 0x28, 0xc4, 0x6f, 0x82, 0x43, 0x23, 0x29, 0xe5, 0x6f, 0xc0, 0x2e, + 0x44, 0x43, 0xc0, 0x5f, 0x40, 0x50, 0xd0, 0x7f, 0x4a, 0x17, 0x00, 0x40, + 0x01, 0x18, 0x46, 0x25, 0x07, 0x25, 0x65, 0x56, 0xd9, 0x04, 0x53, 0x18, + 0xeb, 0x18, 0x05, 0x30, 0x49, 0x16, 0x69, 0x06, 0xca, 0x18, 0xa6, 0x00, + 0xc7, 0x02, 0x65, 0x58, 0xcb, 0x7f, 0x98, 0x2e, 0x7f, 0xb6, 0xcb, 0x6f, + 0xd2, 0x6f, 0xc0, 0x2e, 0x80, 0x42, 0xc0, 0x5f, 0x09, 0x2e, 0x1b, 0x01, + 0x05, 0x2e, 0x1b, 0x01, 0xa3, 0xbc, 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9, + 0x07, 0x2e, 0x1b, 0x01, 0x4a, 0x25, 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd, + 0xf2, 0x7f, 0xbf, 0xb9, 0xeb, 0x7f, 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30, + 0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43, 0x0b, 0x43, 0x80, 0xb2, 0xd3, 0x7f, + 0xc1, 0x7f, 0x90, 0x2e, 0x87, 0xb2, 0x20, 0x25, 0x01, 0x2e, 0x64, 0x00, + 0x01, 0x90, 0x0e, 0x2f, 0x67, 0x52, 0x01, 0x2e, 0x61, 0x00, 0xb4, 0x7f, + 0xa2, 0x7f, 0x98, 0x2e, 0x8d, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x64, 0x00, + 0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e, + 0x1b, 0x01, 0x06, 0xbc, 0x06, 0xbb, 0x57, 0x25, 0x01, 0x2e, 0x1b, 0x01, + 0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, 0x0f, 0xbb, 0x6b, 0x50, 0x80, 0xb3, + 0x0f, 0x2f, 0x0d, 0x2e, 0x1b, 0x01, 0x6f, 0x5e, 0xb7, 0x09, 0x2d, 0x2e, + 0x1b, 0x01, 0x71, 0x5c, 0x69, 0x5e, 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43, + 0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2, + 0x05, 0x2f, 0x69, 0x50, 0x00, 0x2e, 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f, + 0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, 0x61, 0x00, 0x67, 0x52, 0x6d, 0x5c, + 0x98, 0x2e, 0xd3, 0xb2, 0x90, 0x6f, 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f, + 0x00, 0xb2, 0x08, 0x2f, 0x69, 0x58, 0x6b, 0x50, 0x12, 0x41, 0x12, 0x42, + 0x21, 0x30, 0x04, 0x41, 0x04, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f, + 0x00, 0xb2, 0x26, 0x2f, 0x74, 0x6f, 0x80, 0x6f, 0x71, 0x54, 0x88, 0xbd, + 0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, 0x91, 0x42, 0x90, 0x42, 0x88, 0xba, + 0x69, 0x52, 0xf3, 0x6f, 0x54, 0x42, 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42, + 0x15, 0x2f, 0x6b, 0x52, 0x00, 0x2e, 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04, + 0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f, 0x40, 0x90, 0x0b, 0x2f, 0xb1, 0x6f, + 0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f, 0x80, 0xb2, 0x05, 0x2f, 0x6b, 0x54, + 0x21, 0x30, 0x94, 0x42, 0x80, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f, + 0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, 0x60, 0x00, 0x09, 0x2e, 0x7c, 0x00, + 0x04, 0x1a, 0x0d, 0x2f, 0x73, 0x50, 0x29, 0x2e, 0x60, 0x00, 0x24, 0x42, + 0x44, 0x30, 0x02, 0x40, 0x02, 0x42, 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42, + 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x64, 0x00, 0xeb, 0x6f, 0x70, 0x5f, + 0xb8, 0x2e, 0x09, 0x86, 0x49, 0x54, 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04, + 0xc3, 0x40, 0x13, 0x05, 0x05, 0x40, 0x25, 0x05, 0x8a, 0x17, 0x73, 0x30, + 0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08, 0xe3, 0x00, 0x4c, 0x82, 0x95, 0x00, + 0xb3, 0xb5, 0x23, 0xb5, 0x53, 0x42, 0x52, 0x42, 0x53, 0x42, 0x42, 0x42, + 0x71, 0x82, 0x75, 0x54, 0x52, 0x42, 0x10, 0x50, 0x77, 0x54, 0x52, 0x42, + 0xfb, 0x7f, 0x22, 0x30, 0x79, 0x56, 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30, + 0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, 0x4b, 0x42, 0x35, 0x82, 0x8c, 0x80, + 0x8b, 0x42, 0x0b, 0x42, 0x39, 0x80, 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80, + 0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, 0xc6, 0xb2, 0x8b, 0x83, 0xfb, 0x6f, + 0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42, 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30, + 0x51, 0x82, 0x02, 0x42, 0x13, 0x30, 0x41, 0x40, 0x4b, 0x08, 0x7b, 0x54, + 0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e, 0x40, 0x51, + 0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30, 0x42, 0x43, 0x32, 0x30, 0x82, 0x43, + 0xc6, 0x7f, 0xe5, 0x7f, 0xb4, 0x7f, 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f, + 0x98, 0x2e, 0x54, 0x01, 0xc0, 0x7e, 0x00, 0xac, 0x01, 0x2f, 0x65, 0x50, + 0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f, 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f, + 0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f, 0x11, 0x7f, 0x00, 0x2e, 0x64, 0x41, + 0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f, 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40, + 0x32, 0x7f, 0x82, 0x8e, 0xc2, 0x6e, 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f, + 0x02, 0x7f, 0x98, 0x2e, 0x8a, 0xb1, 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40, + 0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f, + 0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f, 0x4e, 0x82, 0x42, 0x6f, 0x50, 0x6f, + 0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e, + 0x98, 0x2e, 0x8a, 0xb1, 0xe0, 0x7e, 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80, + 0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f, 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8, + 0x91, 0x04, 0x4a, 0x22, 0x89, 0x16, 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4, + 0x09, 0x18, 0x8e, 0x16, 0x13, 0x30, 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f, + 0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00, 0x41, 0x40, 0x21, 0xb5, 0x50, 0x7f, + 0x43, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f, + 0x13, 0x40, 0x84, 0x40, 0x01, 0x40, 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18, + 0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a, 0xc0, 0x6f, 0x11, 0x30, 0x02, 0x2f, + 0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42, 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e, + 0xd6, 0x6f, 0x44, 0x41, 0x8a, 0x87, 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f, + 0x15, 0x2f, 0x04, 0x6f, 0x7d, 0x5e, 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5, + 0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1, 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f, + 0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40, 0x81, 0x8d, 0x07, 0x30, 0x3c, 0x05, + 0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42, 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30, + 0x86, 0x86, 0x94, 0x6f, 0xd7, 0x7e, 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89, + 0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29, 0x45, 0x41, 0x86, 0x41, 0xbe, 0x80, + 0x21, 0x41, 0x75, 0x23, 0x82, 0x40, 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f, + 0x20, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f, + 0x22, 0x40, 0x05, 0x41, 0x43, 0x40, 0x13, 0x01, 0x43, 0x86, 0xac, 0x0f, + 0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f, 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88, + 0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f, 0xf5, 0x7e, 0x98, 0x2e, 0xc2, 0xb1, + 0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f, 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04, + 0x04, 0x41, 0x43, 0x82, 0xa2, 0x0e, 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42, + 0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, 0x25, 0x6f, + 0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e, 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30, + 0x03, 0x30, 0x0c, 0x2f, 0x04, 0x40, 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f, + 0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41, 0xb4, 0x0e, 0x03, 0x2f, 0x02, 0x88, + 0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42, 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80, + 0x05, 0x6f, 0x94, 0x0f, 0x76, 0x7f, 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89, + 0x42, 0x43, 0x03, 0x43, 0x49, 0x88, 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f, + 0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e, 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42, + 0x80, 0x2e, 0x77, 0xb4, 0x04, 0x40, 0x25, 0x29, 0x04, 0x42, 0x83, 0x42, + 0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, 0xc0, 0xb2, 0x90, 0x2e, 0x63, 0xb4, + 0x15, 0x87, 0x3c, 0x8c, 0xc4, 0x40, 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40, + 0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3, 0x0c, 0x2f, 0x90, 0x6f, 0x16, 0x80, + 0x46, 0x25, 0x00, 0x40, 0x57, 0x25, 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30, + 0x06, 0x30, 0x75, 0x25, 0x46, 0x23, 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40, + 0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f, 0x09, 0x2f, 0x93, 0x6f, 0xd8, 0x88, + 0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40, 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30, + 0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3, 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90, + 0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f, 0x98, 0x2e, 0xc6, 0xb2, 0x4d, 0x2c, + 0x04, 0x30, 0x8d, 0x88, 0x43, 0x40, 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f, + 0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80, 0x40, 0x42, 0xc2, 0x0f, 0x02, 0x2f, + 0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d, 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc, + 0x92, 0x6f, 0x4f, 0x04, 0x90, 0x84, 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40, + 0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84, 0x21, 0x30, 0x02, 0x2f, 0x11, 0x30, + 0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f, 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e, + 0x00, 0x40, 0x81, 0x40, 0x04, 0xbd, 0x40, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, + 0x50, 0x6f, 0x11, 0x30, 0x02, 0x40, 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80, + 0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f, 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f, + 0x04, 0x30, 0x4d, 0x54, 0x03, 0x30, 0x11, 0x2c, 0x10, 0x80, 0x55, 0x6f, + 0x06, 0x40, 0x75, 0x01, 0x58, 0xbb, 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86, + 0x47, 0x40, 0x51, 0x25, 0xbe, 0x01, 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41, + 0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43, 0x5e, 0x0e, 0xed, 0x2f, 0x31, 0x6f, + 0x60, 0x6f, 0x42, 0x40, 0x15, 0x30, 0x02, 0x82, 0x95, 0x08, 0x04, 0x42, + 0x52, 0x42, 0x02, 0x2c, 0x44, 0x42, 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f, + 0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41, 0xb5, 0x8d, 0x93, 0x0e, 0xd0, 0x6f, + 0x01, 0x2f, 0x98, 0x2e, 0xc6, 0xb2, 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41, + 0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f, 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f, + 0x3c, 0x82, 0x00, 0x40, 0x41, 0x40, 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00, + 0x04, 0xbc, 0x91, 0xb4, 0x01, 0x0e, 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f, + 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x02, 0x2f, 0xa1, 0x6f, 0x05, 0x42, + 0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f, 0xc0, 0x5e, 0xb8, 0x2e, 0x03, 0x2e, + 0x1c, 0x01, 0x9c, 0xbc, 0x1d, 0xb9, 0x02, 0x82, 0x25, 0x2e, 0x8e, 0x00, + 0x83, 0x56, 0x13, 0x18, 0x01, 0x2e, 0x66, 0x00, 0x43, 0x40, 0xd8, 0x04, + 0x05, 0x2e, 0x65, 0x00, 0x40, 0x50, 0x27, 0x2e, 0x65, 0x00, 0xfb, 0x7f, + 0xda, 0x05, 0x8b, 0x50, 0x4b, 0x40, 0x02, 0x40, 0x81, 0x82, 0x01, 0x42, + 0x03, 0x80, 0x81, 0x52, 0xb1, 0x00, 0x03, 0x40, 0x3b, 0x82, 0x85, 0x58, + 0x14, 0x01, 0xc0, 0xb2, 0x37, 0x2e, 0x66, 0x00, 0xd1, 0x7f, 0xe2, 0x7f, + 0x04, 0x2f, 0x05, 0x2e, 0x6b, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x6b, 0x00, + 0x62, 0x40, 0x3a, 0x0f, 0x45, 0x40, 0xc1, 0x7f, 0x21, 0x30, 0x12, 0x30, + 0x42, 0x2f, 0x0d, 0x2e, 0x69, 0x00, 0x3e, 0x0e, 0x33, 0x2f, 0x05, 0x2e, + 0x6a, 0x00, 0x01, 0x35, 0x91, 0x0e, 0x01, 0x30, 0x03, 0x2f, 0x09, 0x2e, + 0x6e, 0x00, 0x00, 0xb3, 0x24, 0x2f, 0xc0, 0x35, 0x90, 0x0e, 0x39, 0x2f, + 0x8f, 0x50, 0x02, 0x30, 0x01, 0x40, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x2f, + 0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0xc0, 0xb2, 0x11, 0x30, 0x02, 0x2f, + 0x25, 0x2e, 0x6d, 0x00, 0x03, 0x2d, 0x23, 0x2e, 0x6d, 0x00, 0x21, 0x30, + 0x25, 0x2e, 0x6b, 0x00, 0x42, 0xb2, 0x04, 0x2f, 0x41, 0xb2, 0x02, 0x2f, + 0x25, 0x2e, 0x6d, 0x00, 0x31, 0x30, 0x3e, 0x80, 0x04, 0x86, 0x25, 0x2e, + 0x6c, 0x00, 0x02, 0x42, 0xc2, 0x42, 0x18, 0x2d, 0x02, 0x35, 0x01, 0x42, + 0x25, 0x2e, 0x6a, 0x00, 0x13, 0x2d, 0x2c, 0x04, 0x38, 0x1e, 0x21, 0x2e, + 0x69, 0x00, 0x7f, 0x50, 0x11, 0x30, 0x22, 0x30, 0x98, 0x2e, 0x66, 0xb5, + 0x09, 0x2c, 0x01, 0x30, 0x2c, 0x00, 0x38, 0x1c, 0x21, 0x2e, 0x68, 0x00, + 0x7f, 0x50, 0x98, 0x2e, 0x66, 0xb5, 0x01, 0x30, 0xc0, 0x6f, 0xd4, 0xb1, + 0xf5, 0xbd, 0x6b, 0xba, 0x91, 0x5a, 0x02, 0x40, 0x15, 0x18, 0xf5, 0xbe, + 0xeb, 0xbb, 0xe3, 0x0a, 0x3d, 0x0b, 0xd2, 0x6f, 0xe3, 0x00, 0x84, 0x40, + 0x63, 0x05, 0x93, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x03, 0x42, 0xeb, 0xbb, + 0xfd, 0x0b, 0xe0, 0x6f, 0x58, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x95, 0x42, + 0x18, 0x04, 0x85, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba, + 0x2c, 0x0b, 0xdc, 0x04, 0x18, 0x1c, 0x80, 0x42, 0x84, 0x80, 0x02, 0x30, + 0x00, 0x40, 0x00, 0xb2, 0x0c, 0x2f, 0x01, 0x2e, 0x6b, 0x00, 0x03, 0x35, + 0x83, 0x0e, 0x07, 0x2f, 0x8d, 0x50, 0x3e, 0x80, 0x25, 0x2e, 0x6d, 0x00, + 0x02, 0x42, 0x03, 0x80, 0x00, 0x2e, 0x02, 0x42, 0x40, 0xb2, 0x04, 0x2f, + 0x8b, 0x50, 0x04, 0x80, 0x25, 0x2e, 0x6a, 0x00, 0x02, 0x42, 0x42, 0xb2, + 0x89, 0x56, 0x9a, 0x22, 0x41, 0xb2, 0x01, 0x2e, 0x1c, 0x01, 0x87, 0x52, + 0x0b, 0xbc, 0x8a, 0x22, 0x0f, 0xb8, 0x00, 0x90, 0x01, 0x32, 0x06, 0x2f, + 0x10, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0, + 0x06, 0x2d, 0x20, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x01, 0x2f, 0x23, 0x2e, + 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88, + 0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f, + 0x01, 0x35, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40, + 0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42, + 0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0x01, 0x35, + 0xa9, 0x0e, 0x0e, 0x2f, 0x03, 0x3b, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f, + 0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80, + 0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e, + 0x03, 0x2e, 0x1d, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x90, 0x50, 0x40, 0xb2, + 0x90, 0x2e, 0x71, 0xb6, 0x12, 0x40, 0x03, 0x30, 0x11, 0x40, 0x80, 0xa8, + 0x5a, 0x05, 0x9f, 0x58, 0x55, 0x23, 0x00, 0x40, 0x75, 0x7f, 0x40, 0xa8, + 0x16, 0x41, 0xd9, 0x05, 0xcf, 0x23, 0x56, 0x05, 0x40, 0xa9, 0x9d, 0x05, + 0x87, 0x7f, 0x6e, 0x23, 0x17, 0x41, 0xa5, 0x7f, 0x3e, 0x8b, 0x04, 0x41, + 0x52, 0x43, 0x00, 0xa8, 0x98, 0x05, 0xf2, 0x7f, 0x86, 0x22, 0xcf, 0x05, + 0xc0, 0xa9, 0x9f, 0x05, 0xbe, 0x23, 0x04, 0x05, 0x92, 0x7f, 0x00, 0xa9, + 0xdc, 0x05, 0x51, 0x43, 0xb6, 0x7f, 0x27, 0x23, 0xa7, 0x54, 0xe1, 0x7f, + 0x02, 0x18, 0x7d, 0x83, 0x40, 0x43, 0xeb, 0xba, 0x75, 0xbd, 0xaa, 0x0a, + 0x0b, 0x2e, 0x71, 0x00, 0x77, 0x5c, 0x2e, 0x18, 0xf5, 0xbe, 0x6b, 0xbb, + 0x75, 0x0b, 0xaa, 0x00, 0xc4, 0x7f, 0x25, 0x2e, 0x71, 0x00, 0xb2, 0x6f, + 0xa5, 0x6f, 0xaa, 0x00, 0x54, 0x01, 0x84, 0x6f, 0x72, 0x6f, 0x94, 0x05, + 0x80, 0xa9, 0xde, 0x05, 0xb7, 0x23, 0x99, 0x5e, 0x77, 0x0e, 0x41, 0x40, + 0x97, 0x5c, 0xb1, 0x01, 0xd5, 0x7f, 0x00, 0x2e, 0x85, 0x41, 0x0e, 0x2f, + 0x00, 0xa0, 0x0c, 0x2f, 0x14, 0x0f, 0x04, 0x2f, 0xe0, 0x6f, 0x00, 0xac, + 0x10, 0x30, 0x08, 0x2c, 0x18, 0x22, 0xf0, 0x6f, 0x00, 0xac, 0x30, 0x30, + 0x24, 0x30, 0x02, 0x2c, 0x20, 0x22, 0x40, 0x30, 0x0d, 0x2e, 0x71, 0x00, + 0x80, 0xa1, 0x1e, 0x23, 0x79, 0x5e, 0x37, 0x0f, 0xbc, 0x23, 0x00, 0x90, + 0x14, 0x30, 0x10, 0x30, 0x18, 0x2f, 0x9d, 0x50, 0x30, 0x00, 0x9b, 0x56, + 0x43, 0x0e, 0x02, 0x2f, 0x10, 0x30, 0x0a, 0x2c, 0x03, 0x30, 0x99, 0x50, + 0x10, 0x0e, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x90, 0x0f, 0x10, 0x30, + 0x00, 0x2f, 0x00, 0x30, 0x00, 0x90, 0x10, 0x30, 0x00, 0x2f, 0x00, 0x30, + 0xc0, 0x90, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x40, 0xb2, 0x87, 0x5c, + 0x22, 0x2f, 0x41, 0x90, 0x4a, 0x2f, 0xa5, 0x50, 0x00, 0x2e, 0x01, 0x40, + 0x41, 0x82, 0x01, 0x42, 0x02, 0x80, 0x4a, 0xa8, 0x01, 0x40, 0x06, 0x2f, + 0xd0, 0x6f, 0x85, 0x0e, 0x3e, 0x2f, 0x41, 0x80, 0x21, 0x2e, 0x78, 0x00, + 0x3b, 0x2d, 0x95, 0x50, 0xfb, 0x7f, 0x4a, 0xa8, 0x06, 0x2f, 0x98, 0x2e, + 0x73, 0xb6, 0xc0, 0x90, 0xfb, 0x6f, 0x32, 0x2f, 0x00, 0x2e, 0x30, 0x2d, + 0x98, 0x2e, 0x73, 0xb6, 0x29, 0x2e, 0x7a, 0x00, 0x2b, 0x2c, 0xfb, 0x6f, + 0xa1, 0x52, 0xd2, 0x6f, 0x95, 0x0e, 0x41, 0x40, 0x05, 0x2f, 0x00, 0x90, + 0x17, 0x2f, 0x05, 0x2e, 0x7a, 0x00, 0x80, 0x90, 0x13, 0x2f, 0x7f, 0x82, + 0x40, 0xac, 0x23, 0x2e, 0x77, 0x00, 0x01, 0x30, 0x18, 0x2f, 0xa1, 0x54, + 0x82, 0x84, 0x23, 0x2e, 0x77, 0x00, 0x82, 0x40, 0x80, 0xb2, 0x11, 0x2f, + 0x00, 0x90, 0x23, 0x2e, 0x79, 0x00, 0x0d, 0x2f, 0x29, 0x2e, 0x72, 0x00, + 0x0b, 0x2d, 0x41, 0x80, 0x21, 0x2e, 0x77, 0x00, 0x0f, 0xa4, 0x05, 0x2f, + 0xa3, 0x50, 0x3e, 0x80, 0xf1, 0x30, 0x29, 0x2e, 0x79, 0x00, 0x01, 0x42, + 0x06, 0x30, 0x34, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x80, 0x30, 0x21, 0x2e, + 0x5e, 0xf0, 0x70, 0x5f, 0xb8, 0x2e, 0x04, 0x84, 0x01, 0x30, 0x81, 0x42, + 0x82, 0x84, 0x01, 0x42, 0xa1, 0x42, 0x81, 0x42, 0x82, 0x84, 0x00, 0x2e, + 0x91, 0x42, 0x81, 0x42, 0xb8, 0x2e, 0x30, 0x50, 0xf3, 0x7f, 0xc0, 0xac, + 0xe4, 0x7f, 0xd5, 0x7f, 0x03, 0x2f, 0x00, 0x30, 0x82, 0x04, 0xf3, 0x6f, + 0xc3, 0x06, 0x40, 0xad, 0x05, 0x2f, 0xe0, 0x6f, 0x05, 0x30, 0x28, 0x04, + 0xd1, 0x6f, 0x69, 0x07, 0xe0, 0x7f, 0x40, 0xa1, 0x01, 0x30, 0x20, 0x2f, + 0x13, 0x25, 0x02, 0x25, 0x04, 0x32, 0x06, 0x30, 0x02, 0x30, 0x03, 0x30, + 0xaf, 0xbb, 0xb1, 0xbd, 0xdf, 0x0a, 0x9f, 0xbb, 0x21, 0xbd, 0x97, 0x0a, + 0x8f, 0xbb, 0x91, 0xbc, 0x01, 0xbc, 0x4f, 0x0a, 0x6b, 0x0e, 0x04, 0x2f, + 0x6b, 0x1a, 0x07, 0x2f, 0xe7, 0x6f, 0x7a, 0x0f, 0x04, 0x2f, 0xe7, 0x6f, + 0x97, 0x04, 0x17, 0x30, 0x07, 0x0a, 0xdd, 0x06, 0x81, 0x8d, 0x34, 0x0e, + 0xe6, 0x2f, 0x00, 0x2e, 0x0d, 0x2d, 0x6b, 0x0e, 0x00, 0x30, 0x05, 0x2f, + 0x6b, 0x1a, 0x07, 0x2f, 0xe0, 0x6f, 0x42, 0x0f, 0x00, 0x30, 0x03, 0x2f, + 0xe0, 0x6f, 0x90, 0x04, 0xdd, 0x06, 0x10, 0x30, 0xf5, 0x6f, 0xc3, 0x7f, + 0xb2, 0x7f, 0x40, 0xad, 0x06, 0x2f, 0x03, 0x30, 0xb2, 0x6f, 0x9a, 0x04, + 0xc4, 0x6f, 0xdc, 0x06, 0xb2, 0x7f, 0xc3, 0x7f, 0x00, 0x2e, 0xd2, 0x6f, + 0xaa, 0x0c, 0x80, 0xac, 0x02, 0x30, 0x01, 0x2f, 0x10, 0x04, 0x51, 0x06, + 0xd0, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00 +}; + +#define BMA4_ACCEL_CONFIG_ADDR (0X40) +#define BMA4_TEMPERATURE_ADDR (0X22) + + +/**************************************************************/ +/**\name Step Counter & Detector */ +/**************************************************************/ +/**\name Step counter enable macros */ +#define BMA423_STEP_CNTR_EN_POS (4) +#define BMA423_STEP_CNTR_EN_MSK (0x10) +#define BMA423_ACTIVITY_EN_MSK (0x20) + +/**\name Step counter watermark macros */ +#define BMA423_STEP_CNTR_WM_MSK (0x03FF) + +/**\name Step counter reset macros */ +#define BMA423_STEP_CNTR_RST_POS (2) +#define BMA423_STEP_CNTR_RST_MSK (0x04) + +/**\name Step detector enable macros */ +#define BMA423_STEP_DETECTOR_EN_POS (3) +#define BMA423_STEP_DETECTOR_EN_MSK (0x08) + +/**\name Tilt enable macros */ +#define BMA423_TILT_EN_MSK (0x01) + +/**\name Step count output length*/ +#define BMA423_STEP_CNTR_DATA_SIZE (4) + +/**\name Wakeup enable macros */ +#define BMA423_WAKEUP_EN_MSK (0x01) + +/**\name Wake up sensitivity macros */ +#define BMA423_WAKEUP_SENS_POS (1) +#define BMA423_WAKEUP_SENS_MSK (0x0E) + +/**\name Tap selection macro */ +#define BMA423_TAP_SEL_POS (4) +#define BMA423_TAP_SEL_MSK (0x10) + +/**************************************************************/ +/**\name Any Motion */ +/**************************************************************/ +/**\name Any motion threshold macros */ +#define BMA423_ANY_NO_MOTION_THRES_POS (0) +#define BMA423_ANY_NO_MOTION_THRES_MSK (0x07FF) + +/**\name Any motion selection macros */ +#define BMA423_ANY_NO_MOTION_SEL_POS (3) +#define BMA423_ANY_NO_MOTION_SEL_MSK (0x08) + +/**\name Any motion enable macros */ +#define BMA423_ANY_NO_MOTION_AXIS_EN_POS (5) +#define BMA423_ANY_NO_MOTION_AXIS_EN_MSK (0xE0) + +/**\name Any motion duration macros */ +#define BMA423_ANY_NO_MOTION_DUR_MSK (0x1FFF) + +/**\name INTERRUPT MAPS */ +#define BMA4_INTR1_MAP (0) +#define BMA4_INTR2_MAP (1) + +/**\name INTERRUPT ENABLE REGISTERS*/ +#define BMA4_INT1_IO_CTRL_ADDR (0X53) +#define BMA4_INT2_IO_CTRL_ADDR (0X54) + +/**\name LATCH DURATION REGISTERS*/ +#define BMA4_INTR_LATCH_ADDR (0X55) + +/**\name CONSTANTS */ +#define BMA4_FIFO_CONFIG_LENGTH (2) +#define BMA4_ACCEL_CONFIG_LENGTH (2) +#define BMA4_FIFO_WM_LENGTH (2) +#define BMA4_CONFIG_STREAM_SIZE (6144) +#define BMA4_NON_LATCH_MODE (0) +#define BMA4_LATCH_MODE (1) +#define BMA4_OPEN_DRAIN (1) +#define BMA4_PUSH_PULL (0) +#define BMA4_ACTIVE_HIGH (1) +#define BMA4_ACTIVE_LOW (0) +#define BMA4_EDGE_TRIGGER (1) +#define BMA4_LEVEL_TRIGGER (0) +#define BMA4_OUTPUT_ENABLE (1) +#define BMA4_OUTPUT_DISABLE (0) +#define BMA4_INPUT_ENABLE (1) +#define BMA4_INPUT_DISABLE (0) + + +/**\name OUTPUT TYPE ENABLE POSITION AND MASK*/ +#define BMA4_INT_EDGE_CTRL_MASK (0x01) +#define BMA4_INT_EDGE_CTRL_POS (0x00) +#define BMA4_INT_LEVEL_MASK (0x02) +#define BMA4_INT_LEVEL_POS (0x01) +#define BMA4_INT_OPEN_DRAIN_MASK (0x04) +#define BMA4_INT_OPEN_DRAIN_POS (0x02) +#define BMA4_INT_OUTPUT_EN_MASK (0x08) +#define BMA4_INT_OUTPUT_EN_POS (0x03) +#define BMA4_INT_INPUT_EN_MASK (0x10) +#define BMA4_INT_INPUT_EN_POS (0x04) + + +/**\name Interrupt status macros */ +#define BMA423_STEP_CNTR_INT (0x02) +#define BMA423_ACTIVITY_INT (0x04) +#define BMA423_TILT_INT (0x08) +#define BMA423_WAKEUP_INT (0x20) +#define BMA423_ANY_NO_MOTION_INT (0x40) +#define BMA423_ERROR_INT (0x80) diff --git a/lib/SensorLib/src/REG/CHSC5816Constants.h b/lib/SensorLib/src/REG/CHSC5816Constants.h new file mode 100644 index 0000000..f12832d --- /dev/null +++ b/lib/SensorLib/src/REG/CHSC5816Constants.h @@ -0,0 +1,66 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file CHSC5816Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-17 + * + */ + +#pragma once + +#define CHSC5816_SLAVE_ADDRESS (0x2E) + +#define CHSC5816_REG_CMD_BUFF (0x20000000U) +#define CHSC5816_REG_RSP_BUFF (0x20000000U) +#define CHSC5816_REG_IMG_HEAD (0x20000014U) +#define CHSC5816_REG_POINT (0x2000002CU) +#define CHSC5816_REG_WR_BUFF (0x20002000U) +#define CHSC5816_REG_RD_BUFF (0x20002400U) +#define CHSC5816_REG_HOLD_MCU (0x40007000U) +#define CHSC5816_REG_AUTO_FEED (0x40007010U) +#define CHSC5816_REG_REMAP_MCU (0x40007000U) +#define CHSC5816_REG_RELEASE_MCU (0x40007000U) +#define CHSC5816_REG_BOOT_STATE (0x20000018U) + + + +#define CHSC5816_HOLD_MCU_VAL (0x12044000U) +#define CHSC5816_AUTO_FEED_VAL (0x0000925aU) +#define CHSC5816_REMAP_MCU_VAL (0x12044002U) +#define CHSC5816_RELEASE_MCU_VAL (0x12044003U) + +#define CHSC5816_REG_VID_PID_BACKUP (40 * 1024 + 0x10U) + +#define CHSC5816_SIG_VALUE (0x43534843U) +/*ctp work staus*/ +#define CHSC5816_POINTING_WORK (0x00000000U) +#define CHSC5816_READY_UPGRADE (1 << 1) +#define CHSC5816_UPGRAD_RUNING (1 << 2) +#define CHSC5816_SLFTEST_RUNING (1 << 3) +#define CHSC5816_SUSPEND_GATE (1 << 16) +#define CHSC5816_GUESTURE_GATE (1 << 17) +#define CHSC5816_PROXIMITY_GATE (1 << 18) +#define CHSC5816_GLOVE_GATE (1 << 19) +#define CHSC5816_ORIENTATION_GATE (1 << 20) diff --git a/lib/SensorLib/src/REG/CM32181Constants.h b/lib/SensorLib/src/REG/CM32181Constants.h new file mode 100644 index 0000000..aba30fd --- /dev/null +++ b/lib/SensorLib/src/REG/CM32181Constants.h @@ -0,0 +1,62 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file CM32181Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-14 + * + */ + +#pragma once + +#define CM32181_SLAVE_ADDRESS (0x10) + + + +// CM32181 slave address can be 0x10 or 0x48, determined by pin ADDR configuration +#define CM32181_ADDR_ALS (0x10) // 7-bit +#define CM32181_ADDR_ALS1 (0x48) // 7-bit + +// CM32181 registers +#define CM32181_REG_ALS_CONF (uint8_t)(0x00) +#define CM32181_REG_ALS_THDH (uint8_t)(0x01) +#define CM32181_REG_ALS_THDL (uint8_t)(0x02) +#define CM32181_REG_ALS_PSM (uint8_t)(0x03) +#define CM32181_REG_ALS_DATA (uint8_t)(0x04) +#define CM32181_REG_ALS_STATUS (uint8_t)(0x06) +#define CM32181_REG_ID (uint8_t)(0x07) + +#define CM32181_CHIP_ID (0x81) + + + + + + + + + + + + diff --git a/lib/SensorLib/src/REG/CSTxxxConstants.h b/lib/SensorLib/src/REG/CSTxxxConstants.h new file mode 100644 index 0000000..18ccd9b --- /dev/null +++ b/lib/SensorLib/src/REG/CSTxxxConstants.h @@ -0,0 +1,46 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file CSTxxxConstants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-24 + * + */ + +#pragma once + +#define CSTXXX_SLAVE_ADDRESS (0x15) +#define CST816_SLAVE_ADDRESS (0x15) +#define CST328_SLAVE_ADDRESS (0x1A) +#define CST226SE_SLAVE_ADDRESS (0x5A) + +#define CST816S_CHIP_ID (0xB4) +#define CST816T_CHIP_ID (0xB5) +#define CST716_CHIP_ID (0x20) +#define CST226SE_CHIP_ID (0xA8) + + + + + diff --git a/lib/SensorLib/src/REG/DRV2605Constants.h b/lib/SensorLib/src/REG/DRV2605Constants.h new file mode 100644 index 0000000..9371a0c --- /dev/null +++ b/lib/SensorLib/src/REG/DRV2605Constants.h @@ -0,0 +1,80 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file DRV2605Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-03 + * + */ + +#pragma once + +#define DRV2605_SLAVE_ADDRESS (0x5A) + +#define DRV2604_CHIP_ID (0x04) //* DRV2604 (contains RAM, does not contain licensed ROM library) +#define DRV2605_CHIP_ID (0x03) //* DRV2605 (contains licensed ROM library, does not contain RAM) +#define DRV2604L_CHIP_ID (0x06) //* DRV2604L (low-voltage version of the DRV2604 device) +#define DRV2605L_CHIP_ID (0x07) //* DRV2605L (low-voltage version of the DRV2605 device) + +#define DRV2605_REG_STATUS (0x00) //* Status register +#define DRV2605_REG_MODE (0x01) //* Mode register +#define DRV2605_MODE_INTTRIG (0x00) //* Internal trigger mode +#define DRV2605_MODE_EXTTRIGEDGE (0x01) //* External edge trigger mode +#define DRV2605_MODE_EXTTRIGLVL (0x02) //* External level trigger mode +#define DRV2605_MODE_PWMANALOG (0x03) //* PWM/Analog input mode +#define DRV2605_MODE_AUDIOVIBE (0x04) //* Audio-to-vibe mode +#define DRV2605_MODE_REALTIME (0x05) //* Real-time playback (RTP) mode +#define DRV2605_MODE_DIAGNOS (0x06) //* Diagnostics mode +#define DRV2605_MODE_AUTOCAL (0x07) //* Auto calibration mode +#define DRV2605_REG_RTPIN (0x02) //* Real-time playback input register +#define DRV2605_REG_LIBRARY (0x03) //* Waveform library selection register +#define DRV2605_REG_WAVESEQ1 (0x04) //* Waveform sequence register 1 +#define DRV2605_REG_WAVESEQ2 (0x05) //* Waveform sequence register 2 +#define DRV2605_REG_WAVESEQ3 (0x06) //* Waveform sequence register 3 +#define DRV2605_REG_WAVESEQ4 (0x07) //* Waveform sequence register 4 +#define DRV2605_REG_WAVESEQ5 (0x08) //* Waveform sequence register 5 +#define DRV2605_REG_WAVESEQ6 (0x09) //* Waveform sequence register 6 +#define DRV2605_REG_WAVESEQ7 (0x0A) //* Waveform sequence register 7 +#define DRV2605_REG_WAVESEQ8 (0x0B) //* Waveform sequence register 8 +#define DRV2605_REG_GO (0x0C) //* Go register +#define DRV2605_REG_OVERDRIVE (0x0D) //* Overdrive time offset register +#define DRV2605_REG_SUSTAINPOS (0x0E) //* Sustain time offset, positive register +#define DRV2605_REG_SUSTAINNEG (0x0F) //* Sustain time offset, negative register +#define DRV2605_REG_BREAK (0x10) //* Brake time offset register +#define DRV2605_REG_AUDIOCTRL (0x11) //* Audio-to-vibe control register +#define DRV2605_REG_AUDIOLVL (0x12) //* Audio-to-vibe minimum input level register +#define DRV2605_REG_AUDIOMAX (0x13) //* Audio-to-vibe maximum input level register +#define DRV2605_REG_AUDIOOUTMIN (0x14) //* Audio-to-vibe minimum output drive register +#define DRV2605_REG_AUDIOOUTMAX (0x15) //* Audio-to-vibe maximum output drive register +#define DRV2605_REG_RATEDV (0x16) //* Rated voltage register +#define DRV2605_REG_CLAMPV (0x17) //* Overdrive clamp voltage register +#define DRV2605_REG_AUTOCALCOMP (0x18) //* Auto-calibration compensation result register +#define DRV2605_REG_AUTOCALEMP (0x19) //* Auto-calibration back-EMF result register +#define DRV2605_REG_FEEDBACK (0x1A) //* Feedback control register +#define DRV2605_REG_CONTROL1 (0x1B) //* Control1 Register +#define DRV2605_REG_CONTROL2 (0x1C) //* Control2 Register +#define DRV2605_REG_CONTROL3 (0x1D) //* Control3 Register +#define DRV2605_REG_CONTROL4 (0x1E) //* Control4 Register +#define DRV2605_REG_VBAT (0x21) //* Vbat voltage-monitor register +#define DRV2605_REG_LRARESON (0x22) //* LRA resonance-period register \ No newline at end of file diff --git a/lib/SensorLib/src/REG/FT6X36Constants.h b/lib/SensorLib/src/REG/FT6X36Constants.h new file mode 100644 index 0000000..6b2362e --- /dev/null +++ b/lib/SensorLib/src/REG/FT6X36Constants.h @@ -0,0 +1,65 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file FT6X36Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-01 + * + */ + +#pragma once + +#define FT3267_SLAVE_ADDRESS (0x38) +#define FT5206_SLAVE_ADDRESS (0x38) +#define FT6X36_SLAVE_ADDRESS (0x38) + +#define FT6X36_VEND_ID (0x11) +#define FT3267_CHIP_ID (0x33) +#define FT6206_CHIP_ID (0x06) +#define FT6236_CHIP_ID (0x36) +#define FT6236U_CHIP_ID (0x64) +#define FT5206U_CHIP_ID (0x64) + +#define FT6X36_REG_MODE (0x00) +#define FT6X36_REG_GEST (0x01) +#define FT6X36_REG_STATUS (0x02) +#define FT6X36_REG_TOUCH1_XH (0x03) +#define FT6X36_REG_TOUCH1_XL (0x04) +#define FT6X36_REG_TOUCH1_YH (0x05) +#define FT6X36_REG_TOUCH1_YL (0x06) +#define FT6X36_REG_THRESHOLD (0x80) +#define FT6X36_REG_MONITOR_TIME (0x87) +#define FT6X36_REG_PERIOD_ACTIVE (0x88) +#define FT6X36_REG_PERIOD_MONITOR (0x89) + + +#define FT6X36_REG_AUTO_CLB_MODE (0xA0) +#define FT6X36_REG_LIB_VERSION_H (0xA1) +#define FT6X36_REG_LIB_VERSION_L (0xA2) +#define FT6X36_REG_INT_STATUS (0xA4) +#define FT6X36_REG_POWER_MODE (0xA5) +#define FT6X36_REG_FIRM_VERS (0xA6) +#define FT6X36_REG_CHIP_ID (0xA3) +#define FT6X36_REG_VENDOR1_ID (0xA8) +#define FT6X36_REG_ERROR_STATUS (0xA9) \ No newline at end of file diff --git a/lib/SensorLib/src/REG/GT911Constants.h b/lib/SensorLib/src/REG/GT911Constants.h new file mode 100644 index 0000000..d5f71c0 --- /dev/null +++ b/lib/SensorLib/src/REG/GT911Constants.h @@ -0,0 +1,156 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file GT911Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-12 + * + */ + +#pragma once + +#define GT911_SLAVE_ADDRESS_H (0x14) +#define GT911_SLAVE_ADDRESS_L (0x5D) + +// Real-time command (Write only) +#define GT911_COMMAND (0x8040) +#define GT911_ESD_CHECK (0x8041) +#define GT911_COMMAND_CHECK (0x8046) + +// Configuration information (R/W) +#define GT911_CONFIG_START (0x8047) +#define GT911_CONFIG_VERSION (0x8047) +#define GT911_X_OUTPUT_MAX_LOW (0x8048) +#define GT911_X_OUTPUT_MAX_HIGH (0x8049) +#define GT911_Y_OUTPUT_MAX_LOW (0x804A) +#define GT911_Y_OUTPUT_MAX_HIGH (0x804B) +#define GT911_TOUCH_NUMBER (0x804C) +#define GT911_MODULE_SWITCH_1 (0x804D) +#define GT911_MODULE_SWITCH_2 (0x804E) +#define GT911_SHAKE_COUNT (0x804F) +#define GT911_FILTER (0x8050) +#define GT911_LARGE_TOUCH (0x8051) +#define GT911_NOISE_REDUCTION (0x8052) +#define GT911_SCREEN_TOUCH_LEVEL (0x8053) +#define GT911_SCREEN_RELEASE_LEVEL (0x8054) +#define GT911_LOW_POWER_CONTROL (0x8055) +#define GT911_REFRESH_RATE (0x8056) +#define GT911_X_THRESHOLD (0x8057) +#define GT911_Y_THRESHOLD (0x8058) +#define GT911_X_SPEED_LIMIT (0x8059) // Reserve +#define GT911_Y_SPEED_LIMIT (0x805A) // Reserve +#define GT911_SPACE_TOP_BOTTOM (0x805B) +#define GT911_SPACE_LEFT_RIGHT (0x805C) +#define GT911_MINI_FILTER (0x805D) +#define GT911_STRETCH_R0 (0x805E) +#define GT911_STRETCH_R1 (0x805F) +#define GT911_STRETCH_R2 (0x8060) +#define GT911_STRETCH_RM (0x8061) +#define GT911_DRV_GROUPA_NUM (0x8062) +#define GT911_DRV_GROUPB_NUM (0x8063) +#define GT911_SENSOR_NUM (0x8064) +#define GT911_FREQ_A_FACTOR (0x8065) +#define GT911_FREQ_B_FACTOR (0x8066) +#define GT911_PANEL_BIT_FREQ_L (0x8067) +#define GT911_PANEL_BIT_FREQ_H (0x8068) +#define GT911_PANEL_SENSOR_TIME_L (0x8069) // Reserve +#define GT911_PANEL_SENSOR_TIME_H (0x806A) +#define GT911_PANEL_TX_GAIN (0x806B) +#define GT911_PANEL_RX_GAIN (0x806C) +#define GT911_PANEL_DUMP_SHIFT (0x806D) +#define GT911_DRV_FRAME_CONTROL (0x806E) +#define GT911_CHARGING_LEVEL_UP (0x806F) +#define GT911_MODULE_SWITCH3 (0x8070) +#define GT911_GESTURE_DIS (0X8071) +#define GT911_GESTURE_LONG_PRESS_TIME (0x8072) +#define GT911_X_Y_SLOPE_ADJUST (0X8073) +#define GT911_GESTURE_CONTROL (0X8074) +#define GT911_GESTURE_SWITCH1 (0X8075) +#define GT911_GESTURE_SWITCH2 (0X8076) +#define GT911_GESTURE_REFRESH_RATE (0x8077) +#define GT911_GESTURE_TOUCH_LEVEL (0x8078) +#define GT911_NEWGREENWAKEUPLEVEL (0x8079) +#define GT911_FREQ_HOPPING_START (0x807A) +#define GT911_FREQ_HOPPING_END (0X807B) +#define GT911_NOISE_DETECT_TIMES (0x807C) +#define GT911_HOPPING_FLAG (0X807D) +#define GT911_HOPPING_THRESHOLD (0X807E) +#define GT911_NOISE_THRESHOLD (0X807F) // Reserve +#define GT911_NOISE_MIN_THRESHOLD (0X8080) +#define GT911_HOPPING_SENSOR_GROUP (0X8082) +#define GT911_HOPPING_SEG1_NORMALIZE (0X8083) +#define GT911_HOPPING_SEG1_FACTOR (0X8084) +#define GT911_MAIN_CLOCK_AJDUST (0X8085) +#define GT911_HOPPING_SEG2_NORMALIZE (0X8086) +#define GT911_HOPPING_SEG2_FACTOR (0X8087) +#define GT911_HOPPING_SEG3_NORMALIZE (0X8089) +#define GT911_HOPPING_SEG3_FACTOR (0X808A) +#define GT911_HOPPING_SEG4_NORMALIZE (0X808C) +#define GT911_HOPPING_SEG4_FACTOR (0X808D) +#define GT911_HOPPING_SEG5_NORMALIZE (0X808F) +#define GT911_HOPPING_SEG5_FACTOR (0X8090) +#define GT911_HOPPING_SEG6_NORMALIZE (0X8092) +#define GT911_KEY_1 (0X8093) +#define GT911_KEY_2 (0X8094) +#define GT911_KEY_3 (0X8095) +#define GT911_KEY_4 (0X8096) +#define GT911_KEY_AREA (0X8097) +#define GT911_KEY_TOUCH_LEVEL (0X8098) +#define GT911_KEY_LEAVE_LEVEL (0X8099) +#define GT911_KEY_SENS_1_2 (0X809A) +#define GT911_KEY_SENS_3_4 (0X809B) +#define GT911_KEY_RESTRAIN (0X809C) +#define GT911_KEY_RESTRAIN_TIME (0X809D) +#define GT911_GESTURE_LARGE_TOUCH (0X809E) +#define GT911_HOTKNOT_NOISE_MAP (0X80A1) +#define GT911_LINK_THRESHOLD (0X80A2) +#define GT911_PXY_THRESHOLD (0X80A3) +#define GT911_GHOT_DUMP_SHIFT (0X80A4) +#define GT911_GHOT_RX_GAIN (0X80A5) +#define GT911_FREQ_GAIN0 (0X80A6) +#define GT911_FREQ_GAIN1 (0X80A7) +#define GT911_FREQ_GAIN2 (0X80A8) +#define GT911_FREQ_GAIN3 (0X80A9) +#define GT911_COMBINE_DIS (0X80B3) +#define GT911_SPLIT_SET (0X80B4) +#define GT911_SENSOR_CH0 (0X80B7) +#define GT911_DRIVER_CH0 (0X80D5) +#define GT911_CONFIG_CHKSUM (0X80FF) +#define GT911_CONFIG_FRESH (0X8100) +#define GT911_CONFIG_SIZE (0xFF - 0x46) + +// Coordinate information +#define GT911_PRODUCT_ID (0x8140) +#define GT911_FIRMWARE_VERSION (0x8144) +#define GT911_X_RESOLUTION (0x8146) +#define GT911_Y_RESOLUTION (0x8148) + +#define GT911_VENDOR_ID (0X8140) +#define GT911_IMFORMATION (0X8140) +#define GT911_POINT_INFO (0X814E) +#define GT911_POINT_1 (0X814F) +#define GT911_POINT_2 (0X8157) +#define GT911_POINT_3 (0X815F) +#define GT911_POINT_4 (0X8167) +#define GT911_POINT_5 (0X816F) \ No newline at end of file diff --git a/lib/SensorLib/src/REG/LTR533Constants.h b/lib/SensorLib/src/REG/LTR533Constants.h new file mode 100644 index 0000000..9df1278 --- /dev/null +++ b/lib/SensorLib/src/REG/LTR533Constants.h @@ -0,0 +1,63 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file LTR533Constants.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-09 + */ +#pragma once + +#define LTR553_SLAVE_ADDRESS (0x23) + +#define LTR553_REG_ALS_CONTR (0x80) +#define LTR553_REG_PS_CONTR (0x81) +#define LTR553_REG_PS_LED (0x82) +#define LTR553_REG_PS_N_PULSES (0x83) +#define LTR553_REG_PS_MEAS_RATE (0x84) +#define LTR553_REG_ALS_MEAS_RATE (0x85) +#define LTR553_REG_PART_ID (0x86) +#define LTR553_REG_MANUFAC_ID (0x87) +#define LTR553_REG_ALS_DATA_CH1_0 (0x88) +#define LTR553_REG_ALS_DATA_CH1_1 (0x89) +#define LTR553_REG_ALS_DATA_CH0_0 (0x8A) +#define LTR553_REG_ALS_DATA_CH0_1 (0x8B) +#define LTR553_REG_ALS_PS_STATUS (0x8C) +#define LTR553_REG_PS_DATA_0 (0x8D) +#define LTR553_REG_PS_DATA_1 (0x8E) +#define LTR553_REG_INTERRUPT (0x8F) +#define LTR553_REG_PS_THRES_UP_0 (0x90) +#define LTR553_REG_PS_THRES_UP_1 (0x91) +#define LTR553_REG_PS_THRES_LOW_0 (0x92) +#define LTR553_REG_PS_THRES_LOW_1 (0x93) +#define LTR553_REG_PS_OFFSET_1 (0x94) +#define LTR553_REG_PS_OFFSET_0 (0x95) +#define LTR553_REG_ALS_THRES_UP_0 (0x97) +#define LTR553_REG_ALS_THRES_UP_1 (0x98) +#define LTR553_REG_ALS_THRES_LOW_0 (0x99) +#define LTR553_REG_ALS_THRES_LOW_1 (0x9A) +#define LTR553_REG_INTERRUPT_PERSIST (0x9E) + + + +#define LTR553_DEFAULT_MAN_ID (0x05) \ No newline at end of file diff --git a/lib/SensorLib/src/REG/MPU6886Constants.h b/lib/SensorLib/src/REG/MPU6886Constants.h new file mode 100644 index 0000000..459bad2 --- /dev/null +++ b/lib/SensorLib/src/REG/MPU6886Constants.h @@ -0,0 +1,115 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file MPU6886Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ + +#pragma once + + +#define MPU6886_SLAVE_ADDRESS (0x68) + +#define MPU6886_REG_XG_OFFS_TC_H (0x04) +#define MPU6886_REG_XG_OFFS_TC_L (0x05) +#define MPU6886_REG_YG_OFFS_TC_H (0x07) +#define MPU6886_REG_YG_OFFS_TC_L (0x08) +#define MPU6886_REG_ZG_OFFS_TC_H (0x0A) +#define MPU6886_REG_ZG_OFFS_TC_L (0x0B) +#define MPU6886_REG_SELF_TEST_X_ACCEL (0x0D) +#define MPU6886_REG_SELF_TEST_Y_ACCEL (0x0E) +#define MPU6886_REG_SELF_TEST_Z_ACCEL (0x0F) +#define MPU6886_REG_XG_OFFS_USRH (0x13) +#define MPU6886_REG_XG_OFFS_USRL (0x14) +#define MPU6886_REG_YG_OFFS_USRH (0x15) +#define MPU6886_REG_YG_OFFS_USRL (0x16) +#define MPU6886_REG_ZG_OFFS_USRH (0x17) +#define MPU6886_REG_ZG_OFFS_USRL (0x18) +#define MPU6886_REG_SMPLRT_DIV (0x19) +#define MPU6886_REG_CONFIG (0x1A) +#define MPU6886_REG_GYRO_CONFIG (0x1B) +#define MPU6886_REG_ACCEL_CONFIG (0x1C) +#define MPU6886_REG_ACCEL_CONFIG_2 (0x1D) +#define MPU6886_REG_LP_MODE_CFG (0x1E) +#define MPU6886_REG_ACCEL_WOM_X_THR (0x20) +#define MPU6886_REG_ACCEL_WOM_Y_THR (0x21) +#define MPU6886_REG_ACCEL_WOM_Z_THR (0x22) +#define MPU6886_REG_FIFO_EN (0x23) +#define MPU6886_REG_FSYNC_INT (0x36) +#define MPU6886_REG_INT_PIN_CFG (0x37) +#define MPU6886_REG_INT_ENABLE (0x38) +#define MPU6886_REG_FIFO_WM_INT_STATUS (0x39) +#define MPU6886_REG_INT_STATUS (0x3A) +#define MPU6886_REG_ACCEL_XOUT_H (0x3B) +#define MPU6886_REG_ACCEL_XOUT_L (0x3C) +#define MPU6886_REG_ACCEL_YOUT_H (0x3D) +#define MPU6886_REG_ACCEL_YOUT_L (0x3E) +#define MPU6886_REG_ACCEL_ZOUT_H (0x3F) +#define MPU6886_REG_ACCEL_ZOUT_L (0x40) +#define MPU6886_REG_TEMP_OUT_H (0x41) +#define MPU6886_REG_TEMP_OUT_L (0x42) +#define MPU6886_REG_GYRO_XOUT_H (0x43) +#define MPU6886_REG_GYRO_XOUT_L (0x44) +#define MPU6886_REG_GYRO_YOUT_H (0x45) +#define MPU6886_REG_GYRO_YOUT_L (0x46) +#define MPU6886_REG_GYRO_ZOUT_H (0x47) +#define MPU6886_REG_GYRO_ZOUT_L (0x48) +#define MPU6886_REG_SELF_TEST_X_GYRO (0x50) +#define MPU6886_REG_SELF_TEST_Y_GYRO (0x51) +#define MPU6886_REG_SELF_TEST_Z_GYRO (0x52) +#define MPU6886_REG_E_ID0 (0x53) +#define MPU6886_REG_E_ID1 (0x54) +#define MPU6886_REG_E_ID2 (0x55) +#define MPU6886_REG_E_ID3 (0x56) +#define MPU6886_REG_E_ID4 (0x57) +#define MPU6886_REG_E_ID5 (0x58) +#define MPU6886_REG_E_ID6 (0x59) +#define MPU6886_REG_FIFO_WM_TH1 (0x60) +#define MPU6886_REG_FIFO_WM_TH2 (0x61) +#define MPU6886_REG_SIGNAL_PATH_RESET (0x68) +#define MPU6886_REG_ACCEL_INTEL_CTRL (0x69) +#define MPU6886_REG_USER_CTRL (0x6A) +#define MPU6886_REG_PWR_MGMT_1 (0x6B) +#define MPU6886_REG_PWR_MGMT_2 (0x6C) +#define MPU6886_REG_I2C_IF (0x70) +#define MPU6886_REG_FIFO_COUNTH (0x72) +#define MPU6886_REG_FIFO_COUNTL (0x73) +#define MPU6886_REG_FIFO_R_W (0x74) +#define MPU6886_REG_WHO_AM_I (0x75) +#define MPU6886_REG_XA_OFFSET_H (0x77) +#define MPU6886_REG_XA_OFFSET_L (0x78) +#define MPU6886_REG_YA_OFFSET_H (0x7A) +#define MPU6886_REG_YA_OFFSET_L (0x7B) +#define MPU6886_REG_ZA_OFFSET_H (0x7D) +#define MPU6886_REG_ZA_OFFSET_L (0x7E) + + +#define MPU6886_WHO_AM_I_RES (0x19) + + + + + diff --git a/lib/SensorLib/src/REG/PCF85063Constants.h b/lib/SensorLib/src/REG/PCF85063Constants.h new file mode 100644 index 0000000..17f89bc --- /dev/null +++ b/lib/SensorLib/src/REG/PCF85063Constants.h @@ -0,0 +1,63 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file PCF85063Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-07 + * + */ + +#pragma once + + +#define PCF85063_SLAVE_ADDRESS (0x51) + +#define PCF85063_CTRL1_REG (0x00) +#define PCF85063_CTRL2_REG (0x01) +#define PCF85063_OFFSET_REG (0x02) +#define PCF85063_RAM_REG (0x03) +#define PCF85063_SEC_REG (0x04) +#define PCF85063_MIN_REG (0x05) +#define PCF85063_HR_REG (0x06) +#define PCF85063_DAY_REG (0x07) +#define PCF85063_WEEKDAY_REG (0x08) +#define PCF85063_MONTH_REG (0x09) +#define PCF85063_YEAR_REG (0x0A) +#define PCF85063_ALRM_SEC_REG (0x0B) +#define PCF85063_ALRM_MIN_REG (0x0C) +#define PCF85063_ALRM_HR_REG (0x0D) +#define PCF85063_ALRM_DAY_REG (0x0E) +#define PCF85063_ALRM_WEEK_REG (0x0F) +#define PCF85063_TIMER_VAL_REG (0x10) +#define PCF85063_TIMER_MD_REG (0x11) + +#define PCF85063_CTRL1_TEST_EN_MASK (1<<7u) +#define PCF85063_CTRL1_CLOCK_EN_MASK (1<<5u) +#define PCF85063_CTRL1_SOFTRST_EN_MASK (1<<4u) +#define PCF85063_CTRL1_CIE_EN_MASK (1<<2u) +#define PCF85063_CTRL1_HOUR_FORMAT_12H_MASK (1<<1u) + + +#define PCF85063_NO_ALARM (0xFF) +#define PCF85063_ALARM_ENABLE (0x80) \ No newline at end of file diff --git a/lib/SensorLib/src/REG/PCF8563Constants.h b/lib/SensorLib/src/REG/PCF8563Constants.h new file mode 100644 index 0000000..685fc05 --- /dev/null +++ b/lib/SensorLib/src/REG/PCF8563Constants.h @@ -0,0 +1,70 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file PCF8563Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2022-12-09 + * + */ + +#pragma once + + +#define PCF8563_SLAVE_ADDRESS (0x51) + +#define PCF8563_STAT1_REG (0x00) +#define PCF8563_STAT2_REG (0x01) +#define PCF8563_SEC_REG (0x02) +#define PCF8563_MIN_REG (0x03) +#define PCF8563_HR_REG (0x04) +#define PCF8563_DAY_REG (0x05) +#define PCF8563_WEEKDAY_REG (0x06) +#define PCF8563_MONTH_REG (0x07) +#define PCF8563_YEAR_REG (0x08) +#define PCF8563_ALRM_MIN_REG (0x09) +#define PCF8563_SQW_REG (0x0D) +#define PCF8563_TIMER1_REG (0x0E) +#define PCF8563_TIMER2_REG (0x0F) + +#define PCF8563_VOL_LOW_MASK (0x80) +#define PCF8563_MINUTES_MASK (0x7F) +#define PCF8563_HOUR_MASK (0x3F) +#define PCF8563_WEEKDAY_MASK (0x07) +#define PCF8563_CENTURY_MASK (0x80) +#define PCF8563_DAY_MASK (0x3F) +#define PCF8563_MONTH_MASK (0x1F) +#define PCF8563_TIMER_CTL_MASK (0x03) + + +#define PCF8563_ALARM_AF (0x08) +#define PCF8563_TIMER_TF (0x04) +#define PCF8563_ALARM_AIE (0x02) +#define PCF8563_TIMER_TIE (0x01) +#define PCF8563_TIMER_TE (0x80) +#define PCF8563_TIMER_TD10 (0x03) + +#define PCF8563_NO_ALARM (0xFF) +#define PCF8563_ALARM_ENABLE (0x80) +#define PCF8563_CLK_ENABLE (0x80) + diff --git a/lib/SensorLib/src/REG/QMC6310Constants.h b/lib/SensorLib/src/REG/QMC6310Constants.h new file mode 100644 index 0000000..4f0fcd0 --- /dev/null +++ b/lib/SensorLib/src/REG/QMC6310Constants.h @@ -0,0 +1,53 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMC6310Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ + +#pragma once + +// @brief device address +#define QMC6310_SLAVE_ADDRESS (0x1C) +#define QMC6310_DEFAULT_ID (0x80) + + +#define QMC6310_REG_CHIP_ID (0x00) +#define QMC6310_REG_LSB_DX (0X01) +#define QMC6310_REG_MSB_DX (0X02) +#define QMC6310_REG_LSB_DY (0X03) +#define QMC6310_REG_MSB_DY (0X04) +#define QMC6310_REG_LSB_DZ (0X05) +#define QMC6310_REG_MSB_DZ (0X06) +#define QMC6310_REG_STAT (0X09) +#define QMC6310_REG_CMD1 (0x0A) +#define QMC6310_REG_CMD2 (0x0B) + + +#define QMC6310_REG_SIGN (0x29) + + + diff --git a/lib/SensorLib/src/REG/QMI8658Constants.h b/lib/SensorLib/src/REG/QMI8658Constants.h new file mode 100644 index 0000000..ec55bcc --- /dev/null +++ b/lib/SensorLib/src/REG/QMI8658Constants.h @@ -0,0 +1,133 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file QMI8658Constants.h + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#pragma once + +// @brief device address +#define QMI8658_L_SLAVE_ADDRESS (0x6B) +#define QMI8658_H_SLAVE_ADDRESS (0x6A) + + +// @brief registers default value +#define QMI8658_REG_WHOAMI_DEFAULT (0x05) +#define QMI8658_REG_STATUS_DEFAULT (0x03) +#define QMI8658_REG_RESET_DEFAULT (0xB0) + + +// @brief registers list +#define QMI8658_REG_WHOAMI (0x00) +#define QMI8658_REG_REVISION (0x01) +#define QMI8658_REG_CTRL1 (0x02) +#define QMI8658_REG_CTRL2 (0x03) +#define QMI8658_REG_CTRL3 (0x04) +// #define QMI8658_REG_CTRL4 (0x05) +#define QMI8658_REG_CTRL5 (0x06) +// #define QMI8658_REG_CTRL6 (0x07) +#define QMI8658_REG_CTRL7 (0x08) +#define QMI8658_REG_CTRL8 (0x09) +#define QMI8658_REG_CTRL9 (0x0A) + +#define QMI8658_REG_CAL1_L (0x0B) +#define QMI8658_REG_CAL1_H (0x0C) +#define QMI8658_REG_CAL2_L (0x0D) +#define QMI8658_REG_CAL2_H (0x0E) +#define QMI8658_REG_CAL3_L (0x0F) +#define QMI8658_REG_CAL3_H (0x10) +#define QMI8658_REG_CAL4_L (0x11) +#define QMI8658_REG_CAL4_H (0x12) + +#define QMI8658_REG_FIFOWMKTH (0x13) +#define QMI8658_REG_FIFOCTRL (0x14) +#define QMI8658_REG_FIFOCOUNT (0x15) +#define QMI8658_REG_FIFOSTATUS (0x16) +#define QMI8658_REG_FIFODATA (0x17) +// #define QMI8658_REG_STATUSI2CM (0x2C) +#define QMI8658_REG_STATUSINT (0x2D) +#define QMI8658_REG_STATUS0 (0x2E) +#define QMI8658_REG_STATUS1 (0x2F) +#define QMI8658_REG_TIMESTAMP_L (0x30) +#define QMI8658_REG_TIMESTAMP_M (0x31) +#define QMI8658_REG_TIMESTAMP_H (0x32) +#define QMI8658_REG_TEMPEARTURE_L (0x33) +#define QMI8658_REG_TEMPEARTURE_H (0x34) +#define QMI8658_REG_AX_L (0x35) +#define QMI8658_REG_AX_H (0x36) +#define QMI8658_REG_AY_L (0x37) +#define QMI8658_REG_AY_H (0x38) +#define QMI8658_REG_AZ_L (0x39) +#define QMI8658_REG_AZ_H (0x3A) +#define QMI8658_REG_GX_L (0x3B) +#define QMI8658_REG_GX_H (0x3C) +#define QMI8658_REG_GY_L (0x3D) +#define QMI8658_REG_GY_H (0x3E) +#define QMI8658_REG_GZ_L (0x3F) +#define QMI8658_REG_GZ_H (0x40) + +#define QMI8658_REG_COD_STATUS (0x46) + +#define QMI8658_REG_DQW_L (0x49) +#define QMI8658_REG_DQW_H (0x4A) +#define QMI8658_REG_DQX_L (0x4B) +#define QMI8658_REG_DQX_H (0x4C) +#define QMI8658_REG_DQY_L (0x4D) +#define QMI8658_REG_DQY_H (0x4E) +#define QMI8658_REG_DQZ_L (0x4F) +#define QMI8658_REG_DQZ_H (0x50) + +#define QMI8658_REG_DVX_L (0x51) +#define QMI8658_REG_DVX_H (0x52) +#define QMI8658_REG_DVY_L (0x53) +#define QMI8658_REG_DVY_H (0x54) +#define QMI8658_REG_DVZ_L (0x55) +#define QMI8658_REG_DVZ_H (0x56) + +#define QMI8658_REG_TAP_STATUS (0x59) +#define QMI8658_REG_PEDO_L (0x5A) +#define QMI8658_REG_PEDO_M (0x5B) +#define QMI8658_REG_PEDO_H (0x5C) +#define QMI8658_REG_RESET (0x60) + +#define QMI8658_REG_RST_RESULT (0x4D) +#define QMI8658_REG_RST_RESULT_VAL (0x80) + +#define STATUS0_ACCE_AVAIL (0x01) +#define STATUS0_GYRO_AVAIL (0x02) +#define QMI8658_ACCEL_LPF_MASK (0xF9) +#define QMI8658_GYRO_LPF_MASK (0x9F) + + + + + +#define QMI8658_ACCEL_EN_MASK (0x01) +#define QMI8658_GYRO_EN_MASK (0x02) +#define QMI8658_ACCEL_GYRO_EN_MASK (0x03) + + +#define QMI8658_FIFO_MAP_INT1 0x04 // ctrl1 diff --git a/lib/SensorLib/src/REG/XL9555Constants.h b/lib/SensorLib/src/REG/XL9555Constants.h new file mode 100644 index 0000000..40df01b --- /dev/null +++ b/lib/SensorLib/src/REG/XL9555Constants.h @@ -0,0 +1,32 @@ +#pragma once + +// A0, A1, A2 connect to GND +#define XL9555_SLAVE_ADDRESS0 (0x20) +#define XL9555_SLAVE_ADDRESS1 (0x21) +#define XL9555_SLAVE_ADDRESS2 (0x22) +#define XL9555_SLAVE_ADDRESS3 (0x23) +#define XL9555_SLAVE_ADDRESS4 (0x24) +#define XL9555_SLAVE_ADDRESS5 (0x25) +#define XL9555_SLAVE_ADDRESS6 (0x26) +#define XL9555_SLAVE_ADDRESS7 (0x27) + +// Input Port 0 /R +#define XL9555_CTRL_INP0 (0x00) +// Input Port 1 /R +#define XL9555_CTRL_INP1 (0x01) +// Output Port 0 /RW +#define XL9555_CTRL_OUTP0 (0x02) +// Output Port 1 /RW +#define XL9555_CTRL_OUTP1 (0x03) +// Polarity Inversion Port 0 /RW +#define XL9555_CTRL_PIP0 (0x04) +// Polarity Inversion Port 1 /RW +#define XL9555_CTRL_PIP1 (0x05) +// Configuration Port 0 /RW +#define XL9555_CTRL_CFG0 (0x06) +// Configuration Port 1 /RW +#define XL9555_CTRL_CFG1 (0x07) + + + + diff --git a/lib/SensorLib/src/SensorBHI260AP.hpp b/lib/SensorLib/src/SensorBHI260AP.hpp new file mode 100644 index 0000000..51d7933 --- /dev/null +++ b/lib/SensorLib/src/SensorBHI260AP.hpp @@ -0,0 +1,690 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorBHI260AP.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-06 + * @note Most source code references come from the https://github.com/boschsensortec/BHY2-Sensor-API + * Simplification for Arduino + */ +#pragma once + +#include "bosch/BoschParse.h" +#include "bosch/SensorBhy2Define.h" +#include "bosch/firmware/BHI260AP.fw.h" + + + +#if defined(ARDUINO) + +class SensorBHI260AP +{ + friend class BoschParse; +public: + SensorBHI260AP(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BHI260AP_SLAVE_ADDRESS_L) + { + __handler.u.i2c_dev.scl = scl; + __handler.u.i2c_dev.sda = sda; + __handler.u.i2c_dev.addr = addr; + __handler.u.i2c_dev.wire = &w; + __handler.intf = SENSORLIB_I2C_INTERFACE; + } + + SensorBHI260AP(int cs, int mosi = -1, int miso = -1, int sck = -1, + PLATFORM_SPI_TYPE &spi = SPI + ) + { + __handler.u.spi_dev.cs = cs; + __handler.u.spi_dev.miso = miso; + __handler.u.spi_dev.mosi = mosi; + __handler.u.spi_dev.sck = sck; + __handler.u.spi_dev.spi = &spi; + __handler.intf = SENSORLIB_SPI_INTERFACE; + } + + ~SensorBHI260AP() + { + deinit(); + } + + SensorBHI260AP() + { + memset(&__handler, 0, sizeof(__handler)); + } + + void setPins(int rst, int irq) + { + __handler.irq = irq; + __handler.rst = rst; + + } + + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BHI260AP_SLAVE_ADDRESS_L) + { + __handler.u.i2c_dev.scl = scl; + __handler.u.i2c_dev.sda = sda; + __handler.u.i2c_dev.addr = addr; + __handler.u.i2c_dev.wire = &w; + __handler.intf = SENSORLIB_I2C_INTERFACE; + return initImpl(); + } + + bool init( + PLATFORM_SPI_TYPE &spi, + int cs, int mosi = MOSI, int miso = MISO, int sck = SCK) + { + __handler.u.spi_dev.cs = cs; + __handler.u.spi_dev.miso = miso; + __handler.u.spi_dev.mosi = mosi; + __handler.u.spi_dev.sck = sck; + __handler.u.spi_dev.spi = &spi; + __handler.intf = SENSORLIB_SPI_INTERFACE; + return initImpl(); + } + + bool init() + { + return initImpl(); + } + + void deinit() + { + if (processBuffer) { + free(processBuffer); + } + processBuffer = NULL; + + if (bhy2) { + free(bhy2); + bhy2 = NULL; + } + + if (__handler.irq != SENSOR_PIN_NONE) { + detachInterrupt(__handler.irq); + } + // end(); + } + + void reset() + { + if (__handler.rst != SENSOR_PIN_NONE) { + digitalWrite(__handler.rst, HIGH); + delay(5); + digitalWrite(__handler.rst, LOW); + delay(10); + digitalWrite(__handler.rst, HIGH); + delay(5); + } + } + + void update() + { + if (!processBuffer) { + return; + } + if (__handler.irq != SENSOR_PIN_NONE) { + if (__data_available) { + bhy2_get_and_process_fifo(processBuffer, processBufferSize, bhy2); + } + } else { + bhy2_get_and_process_fifo(processBuffer, processBufferSize, bhy2); + } + } + + bool enablePowerSave() + { + return true; + } + + bool disablePowerSave() + { + + return true; + } + + void disableInterruptCtrl() + { + } + + void enableInterruptCtrl() + { + } + + bhy2_dev *getHandler() + { + return bhy2; + } + + void printSensors(Stream &port) + { + uint8_t cnt = 0; + bool presentBuff[256]; + + for (uint16_t i = 0; i < sizeof(bhy2->present_buff); i++) { + for (uint8_t j = 0; j < 8; j++) { + presentBuff[i * 8 + j] = ((bhy2->present_buff[i] >> j) & 0x01); + } + } + + port.println("Present sensors: "); + for (int i = 0; i < (int)sizeof(presentBuff); i++) { + if (presentBuff[i]) { + cnt++; + port.print(i); + port.print(" - "); + port.print(get_sensor_name(i)); + port.println(); + } + } + port.printf("Total %u Sensor online .\n", cnt); + } + + + bool printInfo(Stream &stream) + { + uint16_t kernel_version = 0, user_version = 0; + uint16_t rom_version = 0; + uint8_t product_id = 0; + uint8_t host_status = 0, feat_status = 0; + uint8_t boot_status = 0; + uint8_t sensor_error; + struct bhy2_sensor_info info; + + /* Get product_id */ + __error_code = (bhy2_get_product_id(&product_id, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_product_id failed!", false); + + /* Get Kernel version */ + __error_code = (bhy2_get_kernel_version(&kernel_version, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_kernel_version failed!", false); + + /* Get User version */ + __error_code = (bhy2_get_user_version(&user_version, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_user_version failed!", false); + + /* Get ROM version */ + __error_code = (bhy2_get_rom_version(&rom_version, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_rom_version failed!", false); + + __error_code = (bhy2_get_host_status(&host_status, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_host_status failed!", false); + + __error_code = (bhy2_get_feature_status(&feat_status, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_feature_status failed!", false); + + stream.printf("Product ID : %02x\r\n", product_id); + stream.printf("Kernel version : %04u\r\n", kernel_version); + stream.printf("User version : %04u\r\n", user_version); + stream.printf("ROM version : %04u\r\n", rom_version); + stream.printf("Power state : %s\r\n", (host_status & BHY2_HST_POWER_STATE) ? "sleeping" : "active"); + stream.printf("Host interface : %s\r\n", (host_status & BHY2_HST_HOST_PROTOCOL) ? "SPI" : "I2C"); + stream.printf("Feature status : 0x%02x\r\n", feat_status); + + /* Read boot status */ + __error_code = (bhy2_get_boot_status(&boot_status, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_boot_status failed!", false); + + stream.printf("Boot Status : 0x%02x: \r\n", boot_status); + + if (boot_status & BHY2_BST_FLASH_DETECTED) { + stream.println("\tFlash detected. "); + } + + if (boot_status & BHY2_BST_FLASH_VERIFY_DONE) { + stream.println("\tFlash verify done. "); + } + + if (boot_status & BHY2_BST_FLASH_VERIFY_ERROR) { + stream.println("Flash verification failed. "); + } + + if (boot_status & BHY2_BST_NO_FLASH) { + stream.println("\tNo flash installed. "); + } + + if (boot_status & BHY2_BST_HOST_INTERFACE_READY) { + stream.println("\tHost interface ready. "); + } + + if (boot_status & BHY2_BST_HOST_FW_VERIFY_DONE) { + stream.println("\tFirmware verification done. "); + } + + if (boot_status & BHY2_BST_HOST_FW_VERIFY_ERROR) { + stream.println("\tFirmware verification error. "); + } + + if (boot_status & BHY2_BST_HOST_FW_IDLE) { + stream.println("\tFirmware halted. "); + } + + /* Read error value */ + __error_code = (bhy2_get_error_value(&sensor_error, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_error_value failed!", false); + if (sensor_error) { + log_e("%s\r\n", get_sensor_error_text(sensor_error)); + } + + + if (feat_status & BHY2_FEAT_STATUS_OPEN_RTOS_MSK) { + + bhy2_update_virtual_sensor_list(bhy2); + + /* Get present virtual sensor */ + bhy2_get_virt_sensor_list(bhy2); + + stream.printf("Virtual sensor list.\r\n"); + stream.printf("Sensor ID | Sensor Name | ID | Ver | Min rate | Max rate |\r\n"); + stream.printf("----------+--------------------------------------+-----+-----+-----------+-----------|\r\n"); + for (uint8_t i = 0; i < BHY2_SENSOR_ID_MAX; i++) { + if (bhy2_is_sensor_available(i, bhy2)) { + if (i < BHY2_SENSOR_ID_CUSTOM_START) { + stream.printf(" %8u | %36s ", i, get_sensor_name(i)); + } + __error_code = (bhy2_get_sensor_info(i, &info, bhy2)); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_sensor_info failed!", false); + stream.printf("| %3u | %3u | %9.4f | %9.4f |\r\n", + info.driver_id, + info.driver_version, + info.min_rate.f_val, + info.max_rate.f_val); + } + } + } + return true; + } + + bool setInterruptCtrl(uint8_t data) + { + __error_code = bhy2_set_host_interrupt_ctrl(data, bhy2); + if (__error_code != BHY2_OK) { + return false; + } + } + + uint8_t getInterruptCtrl() + { + uint8_t data; + __error_code = bhy2_get_host_interrupt_ctrl(&data, bhy2); + if (__error_code != BHY2_OK) { + return 0; + } + return data; + } + + void printInterruptCtrl(Stream &stream) + { + uint8_t data; + __error_code = bhy2_get_host_interrupt_ctrl(&data, bhy2); + if (__error_code != BHY2_OK) { + return ; + } + stream.printf("Host interrupt control\r\n"); + stream.printf("-- Wake up FIFO %s.\r\n", (data & BHY2_ICTL_DISABLE_FIFO_W) ? "disabled" : "enabled"); + stream.printf("-- Non wake up FIFO %s.\r\n", (data & BHY2_ICTL_DISABLE_FIFO_NW) ? "disabled" : "enabled"); + stream.printf("-- Status FIFO %s.\r\n", (data & BHY2_ICTL_DISABLE_STATUS_FIFO) ? "disabled" : "enabled"); + stream.printf("-- Debugging %s.\r\n", (data & BHY2_ICTL_DISABLE_DEBUG) ? "disabled" : "enabled"); + stream.printf("-- Fault %s.\r\n", (data & BHY2_ICTL_DISABLE_FAULT) ? "disabled" : "enabled"); + stream.printf("-- Interrupt is %s.\r\n", (data & BHY2_ICTL_ACTIVE_LOW) ? "active low" : "active high"); + stream.printf("-- Interrupt is %s triggered.\r\n", (data & BHY2_ICTL_EDGE) ? "pulse" : "level"); + stream.printf("-- Interrupt pin drive is %s.\r\n", (data & BHY2_ICTL_OPEN_DRAIN) ? "open drain" : "push-pull"); + } + + bool isReady() + { + uint8_t boot_status = 0; + __error_code = bhy2_get_boot_status(&boot_status, bhy2); + log_i("boot_status:0x%x", boot_status); + if (__error_code != BHY2_OK) { + return false; + } + return (boot_status & BHY2_BST_HOST_INTERFACE_READY) == false; + } + + uint16_t getKernelVersion() + { + uint16_t version = 0; + __error_code = bhy2_get_kernel_version(&version, bhy2); + if ((__error_code != BHY2_OK) && (version == 0)) { + return 0; + } + log_i("Boot successful. Kernel version %u.\r\n", version); + return version; + } + + + + void onEvent(BhySensorEvent event_id, BhyEventCb callback) + { + SensorEventCbList_t newEventHandler; + newEventHandler.cb = callback; + newEventHandler.event = event_id; + BoschParse::bhyEventVector.push_back(newEventHandler); + } + + void removeEvent(BhySensorEvent event_id, BhyEventCb callback) + { + if (!callback) { + return; + } + for (uint32_t i = 0; i < BoschParse::bhyEventVector.size(); i++) { + SensorEventCbList_t entry = BoschParse::bhyEventVector[i]; + if (entry.cb == callback && entry.event == event_id) { + BoschParse::bhyEventVector.erase(BoschParse::bhyEventVector.begin() + i); + } + } + } + + + void onResultEvent(BhySensorID sensor_id, BhyParseDataCallback callback) + { + ParseCallBackList_t newEventHandler; + newEventHandler.cb = callback; + newEventHandler.id = sensor_id; + BoschParse::bhyParseEventVector.push_back(newEventHandler); + } + + void removeResultEvent(BhySensorID sensor_id, BhyParseDataCallback callback) + { + if (!callback) { + return; + } + for (uint32_t i = 0; i < BoschParse::bhyParseEventVector.size(); i++) { + ParseCallBackList_t entry = BoschParse::bhyParseEventVector[i]; + if (entry.cb == callback && entry.id == sensor_id) { + BoschParse::bhyParseEventVector.erase(BoschParse::bhyParseEventVector.begin() + i); + } + } + } + + void setProcessBufferSize(uint32_t size) + { + processBufferSize = size; + } + + + bool uploadFirmware(const uint8_t *firmware, uint32_t length, bool write2Flash = false) + { + uint8_t sensor_error; + uint8_t boot_status; + + log_i("Upload Firmware ..."); + + __error_code = bhy2_get_boot_status(&boot_status, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_boot_status failed!", false); + + if (write2Flash) { + if (boot_status & BHY2_BST_FLASH_DETECTED) { + uint32_t start_addr = BHY2_FLASH_SECTOR_START_ADDR; + uint32_t end_addr = start_addr + length; + log_i("Flash detected. Erasing flash to upload firmware\r\n"); + __error_code = bhy2_erase_flash(start_addr, end_addr, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_erase_flash failed!", false); + } else { + log_e("Flash not detected\r\n"); + return false; + } + printf("Loading firmware into FLASH.\r\n"); + __error_code = bhy2_upload_firmware_to_flash(firmware, length, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_upload_firmware_to_flash failed!", false); + } else { + log_i("Loading firmware into RAM.\r\n"); + log_i("upload size = %lu", length); + __error_code = bhy2_upload_firmware_to_ram(firmware, length, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_upload_firmware_to_ram failed!", false); + } + + log_i("Loading firmware into RAM Done\r\n"); + __error_code = bhy2_get_error_value(&sensor_error, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_error_value failed!", false); + if (sensor_error != BHY2_OK) { + __error_code = bhy2_get_error_value(&sensor_error, bhy2); + log_e("%s\r\n", get_sensor_error_text(sensor_error)); + return false; + } + + + if (write2Flash) { + log_i("Booting from FLASH.\r\n"); + __error_code = bhy2_boot_from_flash(bhy2); + } else { + log_i("Booting from RAM.\r\n"); + __error_code = bhy2_boot_from_ram(bhy2); + } + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2 boot failed!", false); + + __error_code = bhy2_get_error_value(&sensor_error, bhy2); + if (sensor_error) { + log_e("%s\r\n", get_sensor_error_text(sensor_error)); + return false; + } + return sensor_error == BHY2_OK; + } + + String getError() + { + String err = get_api_error(__error_code); + err += " Code:" + String(__error_code); + return err; + } + + bool configure(uint8_t sensor_id, float sample_rate, uint32_t report_latency_ms) + { + __error_code = bhy2_set_virt_sensor_cfg(sensor_id, sample_rate, report_latency_ms, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_set_virt_sensor_cfg failed!", false); + log_i("Enable %s at %.2fHz.\r\n", get_sensor_name(sensor_id), sample_rate); + return true; + } + + struct bhy2_virt_sensor_conf getConfigure(uint8_t sensor_id) + { + bhy2_virt_sensor_conf conf; + bhy2_get_virt_sensor_cfg(sensor_id, &conf, bhy2); + log_i("range:%u sample_rate:%f latency:%lu sensitivity:%u\n", conf.range, conf.sample_rate, conf.latency, conf.sensitivity); + return conf; + } + + float getScaling(uint8_t sensor_id) + { + return get_sensor_default_scaling(sensor_id); + } + + void setFirmware(const uint8_t *image, size_t image_len, bool write_flash) + { + __firmware = image; + __firmware_size = image_len; + __write_flash = write_flash; + } + + static const char *getSensorName(uint8_t sensor_id) + { + return get_sensor_name(sensor_id); + } + +private: + static void handleISR() + { + __data_available = true; + } + + + bool initImpl() + { + uint8_t product_id = 0; + + if (__handler.rst != SENSOR_PIN_NONE) { + pinMode(__handler.rst, OUTPUT); + } + + reset(); + + bhy2 = (struct bhy2_dev *)malloc(sizeof(struct bhy2_dev )); + BHY2_RLST_CHECK(!bhy2, " Device handler malloc failed!", false); + + switch (__handler.intf) { + case BHY2_I2C_INTERFACE: + // esp32s3 test I2C maximum read and write is 64 bytes + __max_rw_length = 64; + BHY2_RLST_CHECK(!__handler.u.i2c_dev.wire, "Wire ptr NULL", false); + if (!SensorInterfaces::setup_interfaces(__handler)) { + log_e("setup_interfaces failed"); + return false; + } + __error_code = bhy2_init(BHY2_I2C_INTERFACE, + SensorInterfaces::bhy2_i2c_read, + SensorInterfaces::bhy2_i2c_write, + SensorInterfaces::bhy2_delay_us, + __max_rw_length, &__handler, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_init failed!", false); + // __error_code = bhy2_set_host_intf_ctrl(BHY2_I2C_INTERFACE, bhy2); + // BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_set_host_intf_ctrl failed!", false); + break; + + case BHY2_SPI_INTERFACE: + // esp32s3 test SPI maximum read and write is 256 bytes + __max_rw_length = 256; + BHY2_RLST_CHECK(!__handler.u.spi_dev.spi, "SPI ptr NULL", false); + if (!SensorInterfaces::setup_interfaces(__handler)) { + log_e("setup_interfaces failed"); + return false; + } + __error_code = bhy2_init(BHY2_SPI_INTERFACE, + SensorInterfaces::bhy2_spi_read, + SensorInterfaces::bhy2_spi_write, + SensorInterfaces::bhy2_delay_us, + __max_rw_length, + &__handler, + bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_init failed!", false); + // __error_code = bhy2_set_host_intf_ctrl(BHY2_SPI_INTERFACE, bhy2); + // BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_set_host_intf_ctrl failed!", false); + break; + default: + return false; + } + + + + __error_code = bhy2_soft_reset(bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "reset bhy2 failed!", false); + + __error_code = bhy2_get_product_id(&product_id, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_product_id failed!", false); + + + /* Check for a valid product ID */ + if (product_id != BHY2_PRODUCT_ID) { + log_e("Product ID read %X. Expected %X\r\n", product_id, BHY2_PRODUCT_ID); + return false; + } else { + log_i("BHI260/BHA260 found. Product ID read %X\r\n", product_id); + } + + if (!__firmware) { + // Default write to ram + setFirmware(bhy2_firmware_image, sizeof(bhy2_firmware_image), false); + } + + if (!isReady()) { + if (!uploadFirmware(__firmware, __firmware_size, __write_flash)) { + log_e("uploadFirmware failed!"); + return false; + } + } + + uint16_t version = getKernelVersion(); + BHY2_RLST_CHECK(!version, "getKernelVersion failed!", false); + log_i("Boot successful. Kernel version %u.\r\n", version); + + //Set event callback + __error_code = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_META_EVENT, BoschParse::parseMetaEvent, NULL, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_register_fifo_parse_callback failed!", false); + + __error_code = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_META_EVENT_WU, BoschParse::parseMetaEvent, NULL, bhy2); + BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_register_fifo_parse_callback failed!", false); + + // __error_code = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_DEBUG_MSG, BoschParse::parseDebugMessage, NULL, bhy2); + // BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_register_fifo_parse_callback parseDebugMessage failed!", false); + + //Set process buffer +#if defined(ESP32) && defined(BOARD_HAS_PSRAM) + processBuffer = (uint8_t *)ps_malloc(processBufferSize); +#else + processBuffer = (uint8_t *)malloc(processBufferSize); +#endif + BHY2_RLST_CHECK(!processBuffer, "process buffer malloc failed!", false); + + __error_code = bhy2_get_and_process_fifo(processBuffer, processBufferSize, bhy2); + if (__error_code != BHY2_OK) { + log_e("bhy2_get_and_process_fifo failed"); + free(processBuffer); + return false; + } + + /* Update the callback table to enable parsing of sensor hintr_ctrl */ + bhy2_update_virtual_sensor_list(bhy2); + + /* Get present virtual sensor */ + bhy2_get_virt_sensor_list(bhy2); + + // Only register valid sensor IDs + for (uint8_t i = 0; i < BHY2_SENSOR_ID_MAX; i++) { + if (bhy2_is_sensor_available(i, bhy2)) { + bhy2_register_fifo_parse_callback(i, BoschParse::parseData, NULL, bhy2); + } + } + + if (__handler.irq != SENSOR_PIN_NONE) { +#if defined(ARDUINO_ARCH_RP2040) + attachInterrupt((pin_size_t)(__handler.irq), handleISR, (PinStatus )RISING); +#elif defined(NRF52840_XXAA) || defined(NRF52832_XXAA) || defined(ESP32) + attachInterrupt(__handler.irq, handleISR, RISING); +#else +#error "No support ." +#endif + } + + return __error_code == BHY2_OK; + } + +protected: + struct bhy2_dev *bhy2 = NULL; + SensorLibConfigure __handler; + int8_t __error_code; + static volatile bool __data_available; + uint8_t *processBuffer = NULL; + size_t processBufferSize = BHY_PROCESS_BUFFER_SZIE; + const uint8_t *__firmware; + size_t __firmware_size; + bool __write_flash; + uint16_t __max_rw_length; +}; + +volatile bool SensorBHI260AP::__data_available; + +#endif /*defined(ARDUINO)*/ + + + + diff --git a/lib/SensorLib/src/SensorBMA423.hpp b/lib/SensorLib/src/SensorBMA423.hpp new file mode 100644 index 0000000..7adc9de --- /dev/null +++ b/lib/SensorLib/src/SensorBMA423.hpp @@ -0,0 +1,846 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorBMA423.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2022-03-31 + * @note Most source code references come from the https://github.com/boschsensortec/BMA423-Sensor-API + * Simplification for Arduino + */ +#pragma once + +#include "REG/BMA423Constants.h" +#include "SensorCommon.tpp" + +class SensorBMA423 : + public SensorCommon +{ + friend class SensorCommon; +public: + + enum AccelRange { + RANGE_2G, + RANGE_4G, + RANGE_8G, + RANGE_16G + }; + + /*! Output data rate in Hz */ + enum AccelODR { + ODR_0_78HZ = 1, + ODR_1_56HZ, + ODR_3_12HZ, + ODR_6_25HZ, + ODR_12_5HZ, + ODR_25HZ, + ODR_50HZ, + ODR_100HZ, + ODR_200HZ, + ODR_400HZ, + ODR_800HZ, + ODR_1600HZ, + }; + + /*! Bandwidth parameter, determines filter configuration */ + enum BandWidth { + BW_OSR4_AVG1, + BW_OSR2_AVG2, + BW_NORMAL_AVG4, + BW_CIC_AVG8, + BW_RES_AVG16, + BW_RES_AVG32, + BW_RES_AVG64, + BW_RES_AVG128, + }; + + enum PerformanceMode { + PERF_CIC_AVG_MODE, + PERF_CONTINUOUS_MODE, + }; + + enum TemperatureUnit { + TEMP_DEG, + TEMP_FAHREN, + TEMP_KELVIN, + }; + + // Calculate direction facing the front of the chip + enum SensorDir { + DIRECTION_BOTTOM_LEFT, + DIRECTION_TOP_RIGHT, + DIRECTION_TOP_LEFT, + DIRECTION_BOTTOM_RIGHT, + DIRECTION_BOTTOM, + DIRECTION_TOP + }; + + // Chip orientation and orientation + enum SensorRemap { + // Top right corner + REMAP_TOP_LAYER_RIGHT_CORNER, + // Front bottom left corner + REMAP_TOP_LAYER_BOTTOM_LEFT_CORNER, + // Top left corner + REMAP_TOP_LAYER_LEFT_CORNER, + // Top bottom right corner + REMAP_TOP_LAYER_BOTTOM_RIGHT_CORNER, + // Bottom top right corner + REMAP_BOTTOM_LAYER_TOP_RIGHT_CORNER, + // Bottom bottom left corner + REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER, + // Bottom bottom right corner + REMAP_BOTTOM_LAYER_BOTTOM_RIGHT_CORNER, + // Bottom top left corner + REMAP_BOTTOM_LAYER_TOP_LEFT_CORNER, + }; + + enum Feature { + /**\name Feature enable macros for the sensor */ + FEATURE_STEP_CNTR = 0x01, + /**\name Below macros are mutually exclusive */ + FEATURE_ANY_MOTION = 0x02, + FEATURE_NO_MOTION = 0x04, + FEATURE_ACTIVITY = 0x08, + FEATURE_TILT = 0x10, + FEATURE_WAKEUP = 0x20, + }; + + /**\name Interrupt status macros */ + enum FeatureInterrupt { + INT_STEP_CNTR = 0x02, + INT_ACTIVITY = 0x04, + INT_TILT = 0x05, + INT_WAKEUP = 0x20, + INT_ANY_NO_MOTION = 0x40, + }; + +#if defined(ARDUINO) + SensorBMA423(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMA423_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + SensorBMA423() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = BMA423_SLAVE_ADDRESS; + } + + ~SensorBMA423() + { + deinit(); + } + + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMA423_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + void reset() + { + writeRegister(BMA423_RESET_REG, 0xB6); + delay(20); + } + + bool enablePowerSave() + { + uint8_t val; + + val = readRegister(BMA4_POWER_CONF_ADDR); + val |= BMA4_ADVANCE_POWER_SAVE_MSK; + writeRegister(BMA4_POWER_CONF_ADDR, val); + return true; + } + + bool disablePowerSave() + { + uint8_t val; + val = readRegister(BMA4_POWER_CONF_ADDR); + val &= ~(BMA4_ADVANCE_POWER_SAVE_MSK); + writeRegister(BMA4_POWER_CONF_ADDR, val); + return true; + } + + void disableInterruptCtrl() + { + writeRegister(BMA4_INIT_CTRL_ADDR, 0x00); + } + + void enableInterruptCtrl() + { + writeRegister(BMA4_INIT_CTRL_ADDR, 0x01); + } + + + bool enableAccelerometer() + { + uint8_t val; + val = readRegister(BMA4_POWER_CTRL_ADDR); + val |= BMA4_ACCEL_ENABLE_MSK; + writeRegister(BMA4_POWER_CTRL_ADDR, val); + return true; + } + + bool disableAccelerometer() + { + uint8_t val; + val = readRegister( BMA4_POWER_CTRL_ADDR); + val &= (~BMA4_ACCEL_ENABLE_MSK); + writeRegister(BMA4_POWER_CTRL_ADDR, val); + return true; + } + + bool configAccelerometer(AccelRange range = RANGE_4G, AccelODR odr = ODR_200HZ, + BandWidth bw = BW_NORMAL_AVG4, + PerformanceMode perfMode = PERF_CONTINUOUS_MODE) + + { + uint8_t buffer[2] = {0, 0}; + if (perfMode == PERF_CONTINUOUS_MODE) { + if (bw > BW_NORMAL_AVG4) { + return false; + } + } else if (perfMode == PERF_CIC_AVG_MODE) { + if (bw > BW_RES_AVG128) { + return false; + } + } else { + return false; + } + if ((odr < ODR_0_78HZ) || (odr > ODR_1600HZ)) { + return false; + } + + buffer[0] = odr & 0x0F; + buffer[0] |= (uint8_t)(bw << 4); + buffer[0] |= (uint8_t)(perfMode << 7); + buffer[1] = range & 0x03; + + /* Burst write is not possible in + suspend mode hence individual write is + used with delay of 1 ms */ + writeRegister(BMA4_ACCEL_CONFIG_ADDR, buffer[0]); + delay(2); + writeRegister(BMA4_ACCEL_CONFIG_ADDR + 1, buffer[1]); + return true; + } + + + bool getAccelRaw(int16_t *rawBuffer) + { + uint8_t buffer[6] = {0}; + if (readRegister(BMA4_DATA_8_ADDR, buffer, 6) != DEV_WIRE_ERR) { + /* Accel data x axis */ + rawBuffer[0] = (int16_t)(buffer[1] << 8) | (buffer[0]); + /* Accel data y axis */ + rawBuffer[1] = (int16_t)(buffer[3] << 8) | (buffer[2]); + /* Accel data z axis */ + rawBuffer[2] = (int16_t)(buffer[5] << 8) | (buffer[4]); + } else { + return false; + } + return true; + } + + bool getAccelerometer(int16_t &x, int16_t &y, int16_t &z) + { + int16_t raw[3]; + if (getAccelRaw(raw)) { + x = raw[0] / 16; + y = raw[1] / 16; + z = raw[2] / 16; + return true; + } + return false; + } + + float getTemperature(TemperatureUnit unit) + { + int32_t raw = readRegister(BMA4_TEMPERATURE_ADDR); + /* '0' value read from the register corresponds to 23 degree C */ + raw = (raw * 1000) + (23 * 1000); + switch (unit) { + case TEMP_FAHREN: + /* Temperature in degree Fahrenheit */ + /* 1800 = 1.8 * 1000 */ + raw = ((raw / 1000) * 1800) + (32 * 1000); + break; + case TEMP_KELVIN: + /* Temperature in degree Kelvin */ + /* 273150 = 273.15 * 1000 */ + raw = raw + 273150; + break; + default: + break; + } + float res = (float)raw / (float)1000.0; + /* 0x80 - raw read from the register and 23 is the ambient raw added. + * If the raw read from register is 0x80, it means no valid + * information is available */ + if (((raw - 23) / 1000) == 0x80) { + return 0; + } + return res; + } + + + uint8_t direction() + { + int16_t x = 0, y = 0, z = 0; + getAccelerometer(x, y, z); + uint16_t absX = abs(x); + uint16_t absY = abs(y); + uint16_t absZ = abs(z); + if ((absZ > absX) && (absZ > absY)) { + if (z > 0) { + return DIRECTION_TOP; + } else { + return DIRECTION_BOTTOM; + } + } else if ((absY > absX) && (absY > absZ)) { + if (y > 0) { + return DIRECTION_TOP_RIGHT; + } else { + return DIRECTION_BOTTOM_LEFT; + } + } else { + if (x < 0) { + return DIRECTION_BOTTOM_RIGHT; + } else { + return DIRECTION_TOP_LEFT; + } + } + return 0; + } + + bool setReampAxes(SensorRemap remap) + { + //Top + // No.1 REG: 0x3e -> 0x88 REG: 0x3f -> 0x0 + // No.2 REG: 0x3e -> 0xac REG: 0x3f -> 0x0 + // No.3 REG: 0x3e -> 0x85 REG: 0x3f -> 0x0 + // No.4 REG: 0x3e -> 0xa1 REG: 0x3f -> 0x0 + + // Bottom + // No.5 REG: 0x3e -> 0x81 REG: 0x3f -> 0x1 + // No.6 REG: 0x3e -> 0xa5 REG: 0x3f -> 0x1 + // No.7 REG: 0x3e -> 0x8c REG: 0x3f -> 0x1 + // No.8 REG: 0x3e -> 0xa8 REG: 0x3f -> 0x1 + + uint8_t configReg0[] = {0x88, 0xAC, 0x85, 0xA1, 0x81, 0xA5, 0x8C, 0xA8}; + if (remap > sizeof(configReg0) / sizeof(configReg0[0])) { + return false; + } + uint8_t buffer[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_AXES_REMAP_OFFSET; + if (readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE) == DEV_WIRE_ERR) { + return false; + } + buffer[index] = configReg0[remap]; + buffer[index + 1] = remap >= 4 ? 0x00 : 0x01; + return writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE) != DEV_WIRE_ERR; + } + + + + + bool setStepCounterWatermark(uint16_t watermark) + { + uint8_t buffer[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_STEP_CNTR_OFFSET; + uint16_t wm_lsb = 0; + uint16_t wm_msb = 0; + int rslt; + uint16_t data = 0; + + rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE); + if (rslt != DEV_WIRE_ERR) { + wm_lsb = buffer[index]; + wm_msb = buffer[index + 1] << 8; + data = wm_lsb | wm_msb; + /* Sets only watermark bits in the complete 16 bits of data */ + data = ((data & ~(0x03FFU)) | (watermark & 0x03FFU)); + /* Splits 16 bits of data to individual 8 bits data */ + buffer[index] = (uint8_t)(data & 0x00FFU); + buffer[index + 1] = (uint8_t)((data & 0xFF00U) >> 8); + /* Writes stepcounter watermark settings in the sensor */ + rslt = writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE); + } + return rslt != DEV_WIRE_ERR; + } + + bool disablePedometer() + { + return enablePedometer(false); + } + + bool enablePedometer(bool enable = true) + { + int rslt; + uint8_t buffer[BMA423_FEATURE_SIZE] = {0}; + /* Step detector enable bit pos. is 1 byte ahead of the base address */ + uint8_t index = BMA423_STEP_CNTR_OFFSET + 1; + rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE); + if (rslt != DEV_WIRE_ERR) { + buffer[index] = ((buffer[index] & ~0x08) | ((enable << 3) & 0x08)); + rslt = writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE); + } + return rslt != DEV_WIRE_ERR; + } + + uint32_t getPedometerCounter() + { + uint8_t buffer[4] = {0}; + /* Reads the step counter output data from the gpio register */ + int rslt = readRegister(BMA4_STEP_CNT_OUT_0_ADDR, buffer, 4); + if (rslt != DEV_WIRE_ERR) { + return ((uint32_t)buffer[0]) | ((uint32_t)buffer[1] << 8) | ((uint32_t)buffer[2] << 16) | ((uint32_t)buffer[3] << 24); + } + return DEV_WIRE_NONE; + } + + void resetPedometer() + { + uint8_t buffer[BMA423_FEATURE_SIZE] = {0}; + /* Reset bit is 1 byte ahead of base address */ + uint8_t index = BMA423_STEP_CNTR_OFFSET + 1; + int rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE); + if (rslt != DEV_WIRE_ERR) { + buffer[index] = ((buffer[index] & ~0x04U) | ((1 << 2U) & 0x04U)); + writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE); + } + } + + bool enableFeature(uint8_t feature, uint8_t enable) + { + uint8_t buffer[BMA423_FEATURE_SIZE] = {0}; + int rslt; + uint8_t len; + /* Update the length for read and write */ + update_len(&len, feature, enable); + rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, len); + if (rslt != DEV_WIRE_ERR) { + if (enable) { + /* Enables the feature */ + rslt = feature_enable(feature, len, buffer); + } else { + /* Disables the feature */ + rslt = feature_disable(feature, len, buffer); + } + } + return rslt != DEV_WIRE_ERR; + } + + uint16_t readIrqStatus() + { + uint8_t data[2] = {0}; + if (readRegister(BMA4_INT_STAT_0_ADDR, data, 2) != DEV_WIRE_ERR) { + int_status = data[0] | (data[1] << 8); + return int_status; + } + return DEV_WIRE_NONE; + } + + uint16_t getIrqStatus() + { + return int_status; + } + + bool configInterrupt( + /*! Trigger condition of interrupt pin */ + uint8_t edge_ctrl = BMA4_LEVEL_TRIGGER, + /*! Level of interrupt pin */ + uint8_t level = BMA4_ACTIVE_HIGH, + /*! Behaviour of interrupt pin to open drain */ + uint8_t od = BMA4_PUSH_PULL, + /*! Output enable for interrupt pin */ + uint8_t output_en = BMA4_OUTPUT_ENABLE, + /*! Input enable for interrupt pin */ + uint8_t input_en = BMA4_INPUT_DISABLE, + /*! Variable used to select the interrupt pin1 or pin2 for interrupt configuration. */ + uint8_t int_line = BMA4_INTR1_MAP + ) + { + uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR}; + uint8_t data = 0; + if (int_line > 1) { + return false; + } + data = ((uint8_t)((edge_ctrl & BMA4_INT_EDGE_CTRL_MASK) | + ((level << 1) & BMA4_INT_LEVEL_MASK) | + ((od << 2) & BMA4_INT_OPEN_DRAIN_MASK) | + ((output_en << 3) & BMA4_INT_OUTPUT_EN_MASK) | + ((input_en << 4) & BMA4_INT_INPUT_EN_MASK))); + + this->int_line = int_line; + + return writeRegister(interrupt_address_array[int_line], &data, 1) != DEV_WIRE_ERR; + } + + bool configreFeatureInterrupt(uint16_t feature_interrupt_mask, bool enable) + { + return interruptMap(int_line, feature_interrupt_mask, enable); + } + + + bool enablePedometerIRQ() + { + return (interruptMap(int_line, INT_STEP_CNTR, true)); + } + + bool enableTiltIRQ() + { + return (interruptMap(int_line, INT_TILT, true)); + } + + bool enableWakeupIRQ() + { + return (interruptMap(int_line, INT_WAKEUP, true)); + } + + bool enableAnyNoMotionIRQ() + { + return (interruptMap(int_line, INT_ANY_NO_MOTION, true)); + } + + bool enableActivityIRQ() + { + return (interruptMap(int_line, INT_ACTIVITY, true)); + } + + bool disablePedometerIRQ() + { + return (interruptMap(int_line, INT_STEP_CNTR, false)); + } + + bool disableTiltIRQ() + { + return (interruptMap(int_line, INT_TILT, false)); + } + + bool disableWakeupIRQ() + { + return (interruptMap(int_line, INT_WAKEUP, false)); + } + + bool disableAnyNoMotionIRQ() + { + return (interruptMap(int_line, INT_ANY_NO_MOTION, false)); + } + + bool disableActivityIRQ() + { + return (interruptMap(int_line, INT_ACTIVITY, false)); + } + + + inline bool isActivity() + { + return (int_status & BMA423_ACTIVITY_INT); + } + + inline bool isTilt() + { + return (int_status & BMA423_TILT_INT); + } + + inline bool isDoubleTap() + { + return (int_status & BMA423_WAKEUP_INT); + } + + inline bool isAnyNoMotion() + { + return (int_status & BMA423_ACTIVITY_INT); + } + + inline bool isPedometer() + { + return (int_status & BMA423_STEP_CNTR_INT); + } + +private: + + bool interruptMap(uint8_t int_line, uint16_t int_map, uint8_t enable) + { + int rslt; + uint8_t data[3] = {0, 0, 0}; + uint8_t index[2] = {BMA4_INT_MAP_1_ADDR, BMA4_INT_MAP_2_ADDR}; + rslt = readRegister(BMA4_INT_MAP_1_ADDR, data, 3); + if (enable) { + /* Feature interrupt mapping */ + data[int_line] |= (uint8_t)(int_map & (0x00FF)); + /* Hardware interrupt mapping */ + if (int_line == BMA4_INTR2_MAP) + data[2] |= (uint8_t)((int_map & (0xFF00)) >> 4); + else + data[2] |= (uint8_t)((int_map & (0xFF00)) >> 8); + + rslt = writeRegister(index[int_line], &data[int_line], 1); + rslt = writeRegister(BMA4_INT_MAP_DATA_ADDR, &data[2], 1); + + } else { + /* Feature interrupt un-mapping */ + data[int_line] &= (~(uint8_t)(int_map & (0x00FF))); + /* Hardware interrupt un-mapping */ + if (int_line == BMA4_INTR2_MAP) + data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 4)); + else + data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8)); + + rslt = writeRegister(index[int_line], &data[int_line], 1); + rslt = writeRegister(BMA4_INT_MAP_DATA_ADDR, &data[2], 1); + + } + return rslt != DEV_WIRE_ERR; + } + + /*! + * @brief This API sets the interrupt mode in the sensor. + */ + bool setInterruptMode(uint8_t mode) + { + if (mode == BMA4_NON_LATCH_MODE || mode == BMA4_LATCH_MODE) + return writeRegister(BMA4_INTR_LATCH_ADDR, &mode, 1) != DEV_WIRE_ERR; + return false; + } + + + bool feature_disable(uint8_t feature, uint8_t len, uint8_t *buffer) + { + uint8_t index = 0; + + /* Disable step counter */ + if ((feature & FEATURE_STEP_CNTR) > 0) { + /* Step counter enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + buffer[index] = buffer[index] & (~BMA423_STEP_CNTR_EN_MSK); + } + + /* Disable activity */ + if ((feature & FEATURE_ACTIVITY) > 0) { + /* Activity enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + buffer[index] = buffer[index] & (~BMA423_ACTIVITY_EN_MSK); + } + /* Disable tilt */ + if ((feature & FEATURE_TILT) > 0) { + /* Tilt enable bit pos. is the base address(0x3A) of tilt */ + index = BMA423_TILT_OFFSET; + buffer[index] = buffer[index] & (~BMA423_TILT_EN_MSK); + } + + /* Disable wakeup */ + if ((feature & FEATURE_WAKEUP) > 0) { + /* Tilt enable bit pos. is the base address(0x38) of wakeup */ + index = BMA423_WAKEUP_OFFSET; + buffer[index] = buffer[index] & (~BMA423_WAKEUP_EN_MSK); + } + + /* Disable anymotion/nomotion */ + if ((feature & FEATURE_ANY_MOTION) > 0 || (feature & FEATURE_NO_MOTION) > 0) { + /* Any/Nomotion enable bit pos. is 1 bytes ahead of the + any/nomotion base address(0x00) */ + index = 1; + + if ((feature & FEATURE_ANY_MOTION) > 0) { + /* Disable anymotion */ + buffer[index] = buffer[index] | BMA423_ANY_NO_MOTION_SEL_MSK; + } else { + /* Disable nomotion */ + buffer[index] = buffer[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK); + } + /* Any/Nomotion axis enable bit pos. is 3 byte ahead of the + any/nomotion base address(0x00) */ + index = 3; + buffer[index] = buffer[index] & (~BMA423_ANY_NO_MOTION_AXIS_EN_MSK); + } + /* Write the configured settings in the sensor */ + return writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, len) != DEV_WIRE_ERR; + } + + int feature_enable(uint8_t feature, uint8_t len, uint8_t *buffer) + { + uint8_t index = 0; + + /* Enable step counter */ + if ((feature & FEATURE_STEP_CNTR) > 0) { + /* Step counter enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + buffer[index] = buffer[index] | BMA423_STEP_CNTR_EN_MSK; + } + + /* Enable activity */ + if ((feature & FEATURE_ACTIVITY) > 0) { + /* Activity enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + buffer[index] = buffer[index] | BMA423_ACTIVITY_EN_MSK; + } + /* Enable tilt */ + if ((feature & FEATURE_TILT) > 0) { + /* Tilt enable bit pos. is the base address(0x3A) of tilt */ + index = BMA423_TILT_OFFSET; + buffer[index] = buffer[index] | BMA423_TILT_EN_MSK; + } + + /* Enable wakeup */ + if ((feature & FEATURE_WAKEUP) > 0) { + /* Wakeup enable bit pos. is the base address(0x38) of wakeup */ + index = BMA423_WAKEUP_OFFSET; + buffer[index] = buffer[index] | BMA423_WAKEUP_EN_MSK; + } + + /* Enable anymotion/nomotion */ + if ((feature & FEATURE_ANY_MOTION) > 0 || (feature & FEATURE_NO_MOTION) > 0) { + /* Any/Nomotion enable bit pos. is 1 bytes ahead of the + any/nomotion base address(0x00) */ + index = 1; + + if ((feature & FEATURE_ANY_MOTION) > 0) { + /* Enable anymotion */ + buffer[index] = buffer[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK); + } else { + /* Enable nomotion */ + buffer[index] = buffer[index] | BMA423_ANY_NO_MOTION_SEL_MSK; + } + } + + /* Write the feature enable settings in the sensor */ + return writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, len) != DEV_WIRE_ERR; + } + + void update_len(uint8_t *len, uint8_t feature, uint8_t enable) + { + uint8_t length = BMA423_FEATURE_SIZE; + + if ((feature == FEATURE_ANY_MOTION) || (feature == FEATURE_NO_MOTION)) { + /* Change the feature length to 2 for reading and writing of 2 bytes for + any/no-motion enable */ + length = BMA423_ANYMOTION_EN_LEN; + + /* Read and write 4 byte to disable the any/no motion completely along with + all axis */ + if (!enable) { + /*Change the feature length to 4 for reading and writing + of 4 bytes for any/no-motion enable */ + length = length + 2; + } + } + *len = length; + } + + bool configure() + { + uint8_t val; + val = readRegister(BMA4_INTERNAL_STAT); + if (val == BMA4_ASIC_INITIALIZED) { + LOG("%s No need configure!\n", __func__); + readIrqStatus(); //clear irq status + return true; + } + + disablePowerSave(); + delay(1); + disableInterruptCtrl(); + + const uint8_t *stream_data = bma423_config_file; + const uint8_t maxReadWriteLenght = 32; + + for (size_t index = 0; index < BMA4_CONFIG_STREAM_SIZE; index += maxReadWriteLenght) { + uint8_t asic_msb = (uint8_t)((index / 2) >> 4); + uint8_t asic_lsb = ((index / 2) & 0x0F); + writeRegister(BMA4_RESERVED_REG_5B_ADDR, asic_lsb); + writeRegister(BMA4_RESERVED_REG_5C_ADDR, asic_msb); + writeRegister(BMA4_FEATURE_CONFIG_ADDR, (uint8_t *)(stream_data + index), maxReadWriteLenght); + } + + enableInterruptCtrl(); + delay(150); + val = readRegister(BMA4_INTERNAL_STAT); + if (val == BMA4_ASIC_INITIALIZED) { + LOG("%s SUCCESS!\n", __func__); + } else { + LOG("%s FAILED!\n", __func__); + } + return val == BMA4_ASIC_INITIALIZED; + } + + bool initImpl() + { + uint8_t id; + int retry = 2; + + while (retry--) { + id = readRegister(BMA4_CHIP_ID_ADDR); + if (id != BMA423_CHIP_ID) { + reset(); + } + } + + if (id == BMA423_CHIP_ID) { + return configure(); + } + + LOG("ChipID:0x%x should be 0x%x\n", id, BMA423_CHIP_ID); + return false; + + } + + + int getReadMaskImpl() + { + return DEV_WIRE_ERR; + } + + uint16_t int_status; + uint8_t int_line; + +protected: + + +}; + + + diff --git a/lib/SensorLib/src/SensorBMM150.hpp b/lib/SensorLib/src/SensorBMM150.hpp new file mode 100644 index 0000000..b07cf10 --- /dev/null +++ b/lib/SensorLib/src/SensorBMM150.hpp @@ -0,0 +1,332 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file SensorBMM150.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-09 + * @note Most source code references come from the https://github.com/boschsensortec/BMM150-Sensor-API + * Simplification for Arduino + */ +#pragma once + +#include "bosch/common/bosch_interfaces.h" +#include "bosch/BMM150/bmm150.h" +#include "bosch/SensorBhy2Define.h" + +#if defined(ARDUINO) + +/*! @name I2C ADDRESS */ +#define BMM150_DEFAULT_I2C_ADDRESS UINT8_C(0x10) +#define BMM150_I2C_ADDRESS_CSB_LOW_SDO_HIGH UINT8_C(0x11) +#define BMM150_I2C_ADDRESS_CSB_HIGH_SDO_LOW UINT8_C(0x12) +#define BMM150_I2C_ADDRESS_CSB_HIGH_SDO_HIGH UINT8_C(0x13) + + +class SensorBMM150 +{ +public: + + enum PowerMode { + POWERMODE_NORMAL, + POWERMODE_FORCED, + POWERMODE_SLEEP, + POWERMODE_SUSPEND, + }; + + enum InterruptLevel { + INTERRUPT_HIGH_ACTIVE, + INTERRUPT_LOW_ACTIVE, + }; + + SensorBMM150(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMM150_DEFAULT_I2C_ADDRESS) + { + __handler.u.i2c_dev.scl = scl; + __handler.u.i2c_dev.sda = sda; + __handler.u.i2c_dev.addr = addr; + __handler.u.i2c_dev.wire = &w; + __handler.intf = SENSORLIB_I2C_INTERFACE; + } + + SensorBMM150(int cs, int mosi = -1, int miso = -1, int sck = -1, PLATFORM_SPI_TYPE &spi = SPI ) + { + __handler.u.spi_dev.cs = cs; + __handler.u.spi_dev.miso = miso; + __handler.u.spi_dev.mosi = mosi; + __handler.u.spi_dev.sck = sck; + __handler.u.spi_dev.spi = &spi; + __handler.intf = SENSORLIB_SPI_INTERFACE; + } + + ~SensorBMM150() + { + deinit(); + } + + SensorBMM150() + { + memset(&__handler, 0, sizeof(__handler)); + } + + void setPins(int rst, int irq) + { + __handler.irq = irq; + __handler.rst = rst; + + } + + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMM150_DEFAULT_I2C_ADDRESS) + { + __handler.u.i2c_dev.scl = scl; + __handler.u.i2c_dev.sda = sda; + __handler.u.i2c_dev.addr = addr; + __handler.u.i2c_dev.wire = &w; + __handler.intf = SENSORLIB_I2C_INTERFACE; + return initImpl(); + } + + bool init( PLATFORM_SPI_TYPE &spi, int cs, int mosi = MOSI, int miso = MISO, int sck = SCK) + { + __handler.u.spi_dev.cs = cs; + __handler.u.spi_dev.miso = miso; + __handler.u.spi_dev.mosi = mosi; + __handler.u.spi_dev.sck = sck; + __handler.u.spi_dev.spi = &spi; + __handler.intf = SENSORLIB_SPI_INTERFACE; + return initImpl(); + } + + bool init() + { + return initImpl(); + } + + void deinit() + { + if (dev) { + free(dev); + dev = NULL; + } + if (__handler.irq != SENSOR_PIN_NONE) { + detachInterrupt(__handler.irq); + } + } + + void reset() + { + if (__handler.rst != SENSOR_PIN_NONE) { + digitalWrite(__handler.rst, HIGH); + delay(5); + digitalWrite(__handler.rst, LOW); + delay(10); + digitalWrite(__handler.rst, HIGH); + delay(5); + } + } + + void sleep() + { + setMode(POWERMODE_SLEEP); + } + + bool setMode(PowerMode mode) + { + settings.pwr_mode = mode; + return bmm150_set_op_mode(&settings, dev) == BMM150_OK; + } + + bool setThreshold(uint8_t high_th, uint8_t low_th) + { + settings.int_settings.high_threshold = high_th; + settings.int_settings.low_threshold = low_th; + return bmm150_set_sensor_settings(BMM150_SEL_HIGH_THRESHOLD_SETTING, &settings, dev) == BMM150_OK; + } + + bool setInterruptLevel(InterruptLevel level) + { + settings.int_settings.high_int_en = level; + return bmm150_set_sensor_settings(BMM150_SEL_HIGH_THRESHOLD_INT, &settings, dev) == BMM150_OK; + } + + bool enableINT() + { + settings.int_settings.int_pin_en = BMM150_INT_ENABLE; + return bmm150_set_sensor_settings(BMM150_SEL_INT_PIN_EN, &settings, dev) == BMM150_OK; + } + + bool disableINT() + { + settings.int_settings.int_pin_en = BMM150_INT_DISABLE; + return bmm150_set_sensor_settings(BMM150_SEL_INT_PIN_EN, &settings, dev) == BMM150_OK; + } + + bool enabledDtatReady() + { + settings.int_settings.drdy_pin_en = BMM150_INT_ENABLE; + return bmm150_set_sensor_settings(BMM150_SEL_DRDY_PIN_EN, &settings, dev) == BMM150_OK; + } + + bool disabledDtatReady() + { + settings.int_settings.drdy_pin_en = BMM150_INT_DISABLE; + return bmm150_set_sensor_settings(BMM150_SEL_DRDY_PIN_EN, &settings, dev) == BMM150_OK; + } + + uint8_t getChipID() + { + return dev->chip_id; + } + + uint8_t getInterruptStatus() + { + bmm150_get_interrupt_status(dev); + return dev->int_status; + } + + bool isDataReady() + { + return dev->int_status & BMM150_INT_ASSERTED_DRDY; + } + + bool isLowThreshold() + { + return dev->int_status & BMM150_INT_ASSERTED_LOW_THRES; + } + + bool isHighThreshold() + { + return dev->int_status & BMM150_INT_ASSERTED_HIGH_THRES; + } + + struct bmm150_mag_data getMag() + { + struct bmm150_mag_data data = {0}; + bmm150_read_mag_data(&data, dev); + return data; + } + + bool getMag(int16_t &x, int16_t &y, int16_t &z) + { + struct bmm150_mag_data data; + if (bmm150_read_mag_data(&data, dev) != BMM150_OK) { + return false; + } + x = data.x; + y = data.y; + z = data.z; + return true; + } + +private: + + static void IRAM_ATTR handleISR(void *available) + { + *(bool *)(available) = true; + } + + bool initImpl() + { + memset(&settings, 0, sizeof(settings)); + + if (__handler.rst != SENSOR_PIN_NONE) { + pinMode(__handler.rst, OUTPUT); + } + + reset(); + + dev = (struct bmm150_dev *)malloc(sizeof(struct bmm150_dev)); + BHY2_RLST_CHECK(!dev, " Device handler malloc failed!", false); + + switch (__handler.intf) { + case SENSORLIB_I2C_INTERFACE: + BHY2_RLST_CHECK(!__handler.u.i2c_dev.wire, "Wire ptr NULL", false); + if (!SensorInterfaces::setup_interfaces(__handler)) { + log_e("setup_interfaces failed"); + free(dev); + return false; + } + dev->intf = BMM150_I2C_INTF; + dev->read = SensorInterfaces::bhy2_i2c_read; + dev->write = SensorInterfaces::bhy2_i2c_write; + dev->intf_ptr = &__handler; + break; + + case SENSORLIB_SPI_INTERFACE: + BHY2_RLST_CHECK(!__handler.u.spi_dev.spi, "SPI ptr NULL", false); + if (!SensorInterfaces::setup_interfaces(__handler)) { + log_e("setup_interfaces failed"); + free(dev); + return false; + } + dev->intf = BMM150_I2C_INTF; + dev->read = SensorInterfaces::bhy2_spi_read; + dev->write = SensorInterfaces::bhy2_spi_write; + dev->intf_ptr = &__handler; + break; + default: + free(dev); + return false; + } + + dev->delay_us = SensorInterfaces::bhy2_delay_us; + __error_code = bmm150_init(dev); + if (__error_code != BMM150_OK) { + log_e("bmm150 init failed!"); + free(dev); + return false; + } + + __error_code = bmm150_soft_reset(dev); + if (__error_code != BMM150_OK) { + log_e("reset failed!"); + free(dev); + return false; + } + + bmm150_get_sensor_settings(&settings, dev); + + if (__handler.irq != SENSOR_PIN_NONE) { +#if defined(ARDUINO_ARCH_RP2040) + attachInterruptParam((pin_size_t)(__handler.irq), handleISR, (PinStatus )RISING, (void *)&__data_available); +#else + attachInterruptArg(__handler.irq, handleISR, (void *)&__data_available, RISING); +#endif + } + + return __error_code == BMM150_OK; + } + +protected: + struct bmm150_settings settings; + struct bmm150_dev *dev = NULL; + SensorLibConfigure __handler; + int8_t __error_code; + volatile bool __data_available; +}; + + +#endif /*defined(ARDUINO)*/ + + + + diff --git a/lib/SensorLib/src/SensorCM32181.hpp b/lib/SensorLib/src/SensorCM32181.hpp new file mode 100644 index 0000000..63bc874 --- /dev/null +++ b/lib/SensorLib/src/SensorCM32181.hpp @@ -0,0 +1,234 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorCM32181.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-14 + * + */ +#pragma once + +#include "REG/CM32181Constants.h" +#include "SensorCommon.tpp" + +class SensorCM32181 : + public SensorCommon +{ + friend class SensorCommon; +public: + + + enum Sampling { + SAMPLING_X1, //ALS Sensitivity x 1 + SAMPLING_X2, //ALS Sensitivity x 2 + SAMPLING_X1_8, //ALS Sensitivity x (1/8) + SAMPLING_X1_4, //ALS Sensitivity x (1/4) + }; + + enum IntegrationTime { + INTEGRATION_TIME_25MS = 0x0C, + INTEGRATION_TIME_50MS = 0x08, + INTEGRATION_TIME_100MS = 0x00, //0000 = 100ms + INTEGRATION_TIME_200MS, //0001 = 200ms + INTEGRATION_TIME_400MS, //0010 = 400ms + INTEGRATION_TIME_800MS, //0011 = 800ms + }; + + enum PowerSaveMode { + PowerSaveMode1 = 0x00, + PowerSaveMode2, + PowerSaveMode3, + PowerSaveMode4 + }; + + enum InterruptEvent { + ALS_EVENT_LOW_TRIGGER = 0x00, + ALS_EVENT_HIGH_TRIGGER, + ALS_EVENT_NULL, + }; + +#if defined(ARDUINO) + SensorCM32181(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = CM32181_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + SensorCM32181() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = CM32181_SLAVE_ADDRESS; + } + + ~SensorCM32181() + { + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = CM32181_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + void setSampling(Sampling tempSampling = SAMPLING_X1, + IntegrationTime int_time = INTEGRATION_TIME_200MS + ) + { + uint16_t data; + readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + data &= ~(0x03 << 11); + data |= tempSampling << 11; + data &= ~(0xF << 6); + data |= int_time << 6; + readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + } + + void setIntThreshold(uint16_t low_threshold, uint16_t high_threshold) + { + + uint8_t buffer[2] = {0}; + buffer[1] = highByte(high_threshold); + buffer[0] = lowByte(high_threshold);; + writeRegister(CM32181_REG_ALS_THDH, buffer, 2); + buffer[1] = highByte(low_threshold); + buffer[0] = lowByte(low_threshold); + writeRegister(CM32181_REG_ALS_THDL, buffer, 2); + } + + + void powerSave(PowerSaveMode mode, bool enable) + { + uint16_t data = 0x00; + readRegister(CM32181_REG_ALS_PSM, (uint8_t *)&data, 2); + data |= mode << 1; + enable ? data |= 0x01 : data |= 0x00; + writeRegister(CM32181_REG_ALS_PSM, (uint8_t *)&data, 2); + } + + // Read CM32181_REG_ALS_STATUS register to clear interrupt + InterruptEvent getIrqStatus() + { + uint16_t data; + readRegister(CM32181_REG_ALS_STATUS, (uint8_t *)&data, 2); + return bitRead(data, 15) ? ALS_EVENT_LOW_TRIGGER : bitRead(data, 14) ? ALS_EVENT_HIGH_TRIGGER : ALS_EVENT_NULL; + } + + void enableINT() + { + uint16_t data; + readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + bitWrite(data, 1, 1); + writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + } + + void disableINT() + { + uint16_t data; + readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + bitWrite(data, 1, 0); + writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + } + + void powerOn() + { + uint16_t data; + readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + bitClear(data, 0); + writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + } + + void powerDown() + { + uint16_t data; + readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + bitSet(data, 0); + writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2); + } + + uint16_t getRaw() + { + uint8_t buffer[2] = {0}; + readRegister(CM32181_REG_ALS_DATA, buffer, 2); + return (uint16_t) buffer[0] | (uint16_t)(buffer[1] << 8); + } + + float getLux() + { + return getRaw() * calibration_factor; + } + + int getChipID() + { + uint8_t buffer[2] = {0}; + readRegister(CM32181_REG_ID, buffer, 2); + return lowByte(buffer[0]); + } + +private: + + bool initImpl() + { + setReadRegisterSendStop(false); + + int chipID = getChipID(); + log_i("chipID:%d\n", chipID); + + if (chipID == DEV_WIRE_ERR ) { + return false; + } + if (chipID != CM32181_CHIP_ID) { + return false; + } + return true; + } + + int getReadMaskImpl() + { + return -1; + } + + +protected: + // The default calibration value, learned from the manual, + // is now unable to obtain the calibration value from the specified register + const float calibration_factor = 0.286; +}; + + + diff --git a/lib/SensorLib/src/SensorCommon.tpp b/lib/SensorLib/src/SensorCommon.tpp new file mode 100644 index 0000000..92b4fe6 --- /dev/null +++ b/lib/SensorLib/src/SensorCommon.tpp @@ -0,0 +1,699 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorCommon.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ + + +#pragma once + +#include "SensorLib.h" + +typedef union { + struct { + uint8_t low; + uint8_t high; + } bits; + uint16_t full; +} RegData_t; + +typedef int (*iic_fptr_t)(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len); +typedef void (*gpio_write_fptr_t)(uint32_t gpio, uint8_t value); +typedef int (*gpio_read_fptr_t)(uint32_t gpio); +typedef void (*gpio_mode_fptr_t)(uint32_t gpio, uint8_t mode); +typedef void (*delay_ms_fptr_t)(uint32_t ms); + +template +class SensorCommon +{ +public: + ~SensorCommon() + { +#if defined(ARDUINO) + if (__spiSetting) { + delete __spiSetting; + } +#endif + } + +#if defined(ARDUINO) + void setSpiSetting(uint32_t freq, uint8_t dataOrder = SPI_DATA_ORDER, uint8_t dataMode = SPI_MODE0) + { + __freq = freq; + __dataOrder = dataOrder; + __dataMode = dataMode; + } + + bool begin(PLATFORM_WIRE_TYPE &w, uint8_t addr, int sda, int scl) + { + log_i("Using Arduino Wire interface.\n"); + if (__has_init)return thisChip().initImpl(); + __wire = &w; + __sda = sda; + __scl = scl; +#if defined(NRF52840_XXAA) || defined(NRF52832_XXAA) + __wire->begin(); +#elif defined(ARDUINO_ARCH_RP2040) + __wire->end(); + __wire->setSDA(__sda); + __wire->setSCL(__scl); + __wire->begin(); +#else + __wire->begin(__sda, __scl); +#endif + __addr = addr; + __spi = NULL; + __i2c_master_read = NULL; + __i2c_master_write = NULL; + __has_init = thisChip().initImpl(); + return __has_init; + } + + bool begin(int cs, int mosi = -1, int miso = -1, int sck = -1, + PLATFORM_SPI_TYPE &spi = SPI + ) + { + log_i("Using Arduino SPI interface.\n"); + if (__has_init)return thisChip().initImpl(); + __cs = cs; + __spi = &spi; + pinMode(__cs, OUTPUT); + digitalWrite(__cs, HIGH); + __spiSetting = new DEFAULT_SPISETTING; + if (!__spiSetting) { + return false; + } + if (mosi != -1 && miso != -1 && sck != -1) { +#if defined(NRF52840_XXAA) || defined(NRF52832_XXAA) + __spi->begin(); +#elif defined(ARDUINO_ARCH_RP2040) + __spi->setSCK(sck); + __spi->setRX(miso); + __spi->setTX(mosi); + __spi->begin(); +#else + __spi->begin(sck, miso, mosi); +#endif + } else { + __spi->begin(); + } + __wire = NULL; + __readMask = thisChip().getReadMaskImpl(); + __has_init = thisChip().initImpl(); + return __has_init; + } + +#elif defined(ESP_PLATFORM) && !defined(ARDUINO) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + // * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle, + // * which is useful when the bus shares multiple devices. + + bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) + { + log_i("Using ESP-IDF Driver interface.\n"); + if (i2c_dev_bus_handle == NULL) return false; + if (__has_init)return thisChip().initImpl(); + + __i2c_master_read = NULL; + __i2c_master_write = NULL; + __addr = addr; + + /* + i2c_master_bus_config_t i2c_bus_config; + memset(&i2c_bus_config, 0, sizeof(i2c_bus_config)); + i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT; + i2c_bus_config.i2c_port = port_num; + i2c_bus_config.scl_io_num = (gpio_num_t)__scl; + i2c_bus_config.sda_io_num = (gpio_num_t)__sda; + i2c_bus_config.glitch_ignore_cnt = 7; + + i2c_new_master_bus(&i2c_bus_config, &bus_handle); + */ + bus_handle = i2c_dev_bus_handle; + + __i2c_dev_conf.dev_addr_length = I2C_ADDR_BIT_LEN_7; + __i2c_dev_conf.device_address = __addr; + __i2c_dev_conf.scl_speed_hz = SENSORLIB_I2C_MASTER_SEEED; + + if (ESP_OK != i2c_master_bus_add_device(bus_handle, + &__i2c_dev_conf, + &__i2c_device)) { + log_i("i2c_master_bus_add_device failed !\n"); + return false; + } + log_i("Added Device Address : 0x%X New Dev Address: %p Speed :%lu \n", __addr, __i2c_device, __i2c_dev_conf.scl_speed_hz); + __has_init = thisChip().initImpl(); + + if (!__has_init) { + // Initialization failed, delete device + log_i("i2c_master_bus_rm_device !\n"); + i2c_master_bus_rm_device(__i2c_device); + } + + return __has_init; + } + +#else //ESP 4.X + + bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) + { + __i2c_num = port_num; + log_i("Using ESP-IDF Driver interface.\n"); + if (__has_init)return thisChip().initImpl(); + __sda = sda; + __scl = scl; + __addr = addr; + __i2c_master_read = NULL; + __i2c_master_write = NULL; + + i2c_config_t i2c_conf; + memset(&i2c_conf, 0, sizeof(i2c_conf)); + i2c_conf.mode = I2C_MODE_MASTER; + i2c_conf.sda_io_num = sda; + i2c_conf.scl_io_num = scl; + i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + i2c_conf.master.clk_speed = SENSORLIB_I2C_MASTER_SEEED; + + /** + * @brief Without checking whether the initialization is successful, + * I2C may be initialized externally, + * so just make sure there is an initialization here. + */ + i2c_param_config(__i2c_num, &i2c_conf); + i2c_driver_install(__i2c_num, + i2c_conf.mode, + SENSORLIB_I2C_MASTER_RX_BUF_DISABLE, + SENSORLIB_I2C_MASTER_TX_BUF_DISABLE, 0); + __has_init = thisChip().initImpl(); + return __has_init; + } +#endif //ESP 5.X + +#endif + + + bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) + { + log_i("Using Custom interface.\n"); + if (__has_init)return thisChip().initImpl(); + __i2c_master_read = readRegCallback; + __i2c_master_write = writeRegCallback; + __addr = addr; +#if defined(ARDUINO) + __spi = NULL; +#endif + __has_init = thisChip().initImpl(); + return __has_init; + } + + void setGpioWriteCallback(gpio_write_fptr_t cb) + { + __set_gpio_level = cb; + } + + void setGpioReadCallback(gpio_read_fptr_t cb) + { + __get_gpio_level = cb; + } + + void setGpioModeCallback(gpio_mode_fptr_t cb) + { + __set_gpio_mode = cb; + } + + void setDelayCallback(delay_ms_fptr_t cb) + { + __delay_ms = cb; + } + +protected: + + inline void setGpioMode(uint32_t gpio, uint8_t mode) + { + if (__set_gpio_mode) { + return __set_gpio_mode(gpio, mode); + } +#if defined(ARDUINO) || defined(ESP_PLATFORM) + return pinMode(gpio, mode); +#endif + } + + inline void setGpioLevel(uint32_t gpio, uint8_t level) + { + if (__set_gpio_level) { + return __set_gpio_level(gpio, level); + } +#if defined(ARDUINO) || defined(ESP_PLATFORM) + return digitalWrite(gpio, level); +#endif + } + + inline int getGpioLevel(uint32_t gpio) + { + if (__get_gpio_level) { + return __get_gpio_level(gpio); + } +#if defined(ARDUINO) || defined(ESP_PLATFORM) + return digitalRead(gpio); +#endif + } + + + + bool probe() + { +#if defined(ARDUINO) + if (__wire) { + __wire->beginTransmission(__addr); + return __wire->endTransmission() == 0; + } + return false; +#elif defined(ESP_PLATFORM) +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + return i2c_master_probe(bus_handle, __addr, 1000); +#else + return true; +#endif +#else + return true; +#endif + } + + //! Write method + int writeRegister(uint8_t reg, uint8_t norVal, uint8_t orVal) + { + int val = readRegister(reg); + if (val == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + val &= norVal; + val |= orVal; + return writeRegister(reg, val); + } + + int writeRegister(int reg, uint8_t val) + { + return writeRegister(reg, &val, 1); + } + + int writeRegister(int reg, RegData_t data) + { + return writeRegister(reg, (uint8_t *)&data.full, 2); + } + + int writeThenRead(uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len) + { +#if defined(ARDUINO) + if (__wire) { + __wire->beginTransmission(__addr); + __wire->write(write_buffer, write_len); + if (__wire->endTransmission(__sendStop) != 0) { + return DEV_WIRE_ERR; + } + __wire->requestFrom(__addr, read_len); + return __wire->readBytes(read_buffer, read_len) == read_len ? DEV_WIRE_NONE : DEV_WIRE_ERR; + } +#elif defined(ESP_PLATFORM) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + if (ESP_OK == i2c_master_transmit_receive( + __i2c_device, + write_buffer, + write_len, + read_buffer, + read_len, + -1)) { + return DEV_WIRE_NONE; + } +#else //ESP_IDF_VERSION + if (ESP_OK == i2c_master_write_read_device( + __i2c_num, + __addr, + write_buffer, + write_len, + read_buffer, + read_len, + SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) { + return DEV_WIRE_NONE; + } +#endif //ESP_IDF_VERSION + +#endif //ESP_PLATFORM + return DEV_WIRE_ERR; + } + + int writeBuffer(uint8_t *buf, size_t length) + { +#if defined(ARDUINO) + if (__wire) { + __wire->beginTransmission(__addr); + __wire->write(buf, length); + uint8_t ret = (__wire->endTransmission()); + return ret == 0 ? DEV_WIRE_NONE : DEV_WIRE_ERR; + } +#elif defined(ESP_PLATFORM) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + if (ESP_OK == i2c_master_transmit( + __i2c_device, + buf, + length, + -1)) { + return DEV_WIRE_NONE; + } +#else //ESP_IDF_VERSION + if (ESP_OK == i2c_master_write_to_device(__i2c_num, + __addr, + buf, + length, + SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) { + return DEV_WIRE_NONE; + } +#endif //ESP_IDF_VERSION + +#endif //ESP_PLATFORM + return DEV_WIRE_ERR; + } + + int writeRegister(int reg, uint8_t *buf, uint8_t length) + { + if (__i2c_master_write) { + return __i2c_master_write(__addr, reg, buf, length); + } +#if defined(ARDUINO) + if (__wire) { + __wire->beginTransmission(__addr); + if (__reg_addr_len == 1) { + __wire->write(reg); + } else { + for (int i = 0; i < __reg_addr_len; ++i) { + __wire->write(reg >> (8 * ((__reg_addr_len - 1) - i))); + } + } + __wire->write(buf, length); + return (__wire->endTransmission() == 0) ? DEV_WIRE_NONE : DEV_WIRE_ERR; + } + if (__spi) { + __spi->beginTransaction(*__spiSetting); + digitalWrite(__cs, LOW); + if (__reg_addr_len == 1) { + __spi->transfer(reg); + } else { + for (int i = 0; i < __reg_addr_len; ++i) { + __spi->transfer(reg >> (8 * ((__reg_addr_len - 1) - i))); + } + } + __spi->transfer(buf, length); + digitalWrite(__cs, HIGH); + __spi->endTransaction(); + return DEV_WIRE_NONE; + } + return DEV_WIRE_ERR; + +#elif defined(ESP_PLATFORM) + uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (length + __reg_addr_len)); + if (!write_buffer) { + return DEV_WIRE_ERR; + } + write_buffer[0] = reg; + memcpy(write_buffer, ®, __reg_addr_len); + memcpy(write_buffer + __reg_addr_len, buf, length); + int ret = writeBuffer(write_buffer, __reg_addr_len + length); + free(write_buffer); + return ret; +#endif //ESP_PLATFORM + } + + //! Read method + int readRegister(int reg) + { + uint8_t val = 0; + return readRegister(reg, &val, 1) == -1 ? -1 : val; + } + + int readRegister(int reg, RegData_t *data) + { + return readRegister(reg, (uint8_t *)data, 2); + } + + int readRegister(int reg, uint8_t *buf, uint8_t length) + { + if (__i2c_master_read) { + return __i2c_master_read(__addr, reg, buf, length); + } +#if defined(ARDUINO) + if (__wire) { + __wire->beginTransmission(__addr); + if (__reg_addr_len == 1) { + __wire->write(reg); + } else { + for (int i = 0; i < __reg_addr_len; ++i) { + __wire->write(reg >> (8 * ((__reg_addr_len - 1) - i))); + } + } + if (__wire->endTransmission(__sendStop) != 0) { + return DEV_WIRE_ERR; + } + __wire->requestFrom(__addr, length); + return __wire->readBytes(buf, length) == length ? DEV_WIRE_NONE : DEV_WIRE_ERR; + } + if (__spi) { + __spi->beginTransaction(*__spiSetting); + digitalWrite(__cs, LOW); + if (__reg_addr_len == 1) { + __spi->transfer(__readMask != -1 ? (reg | __readMask) : reg); + } else { + uint8_t firstBytes = reg >> (8 * ((__reg_addr_len - 1))); + __spi->transfer(__readMask != -1 ? (firstBytes | __readMask) : firstBytes); + for (int i = 1; i < __reg_addr_len; ++i) { + __spi->transfer(reg >> (8 * ((__reg_addr_len - 1) - i))); + } + } + for (size_t i = 0; i < length; i++) { + buf[i] = __spi->transfer(0x00); + } + digitalWrite(__cs, HIGH); + __spi->endTransaction(); + return DEV_WIRE_NONE; + } +#elif defined(ESP_PLATFORM) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + if (ESP_OK == i2c_master_transmit_receive( + __i2c_device, + (const uint8_t *)®, + __reg_addr_len, + buf, + length, + -1)) { + return DEV_WIRE_NONE; + } +#else //ESP_IDF_VERSION + if (ESP_OK == i2c_master_write_read_device(__i2c_num, + __addr, + (uint8_t *)®, + __reg_addr_len, + buf, + length, + SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) { + return DEV_WIRE_NONE; + } +#endif //ESP_IDF_VERSION + +#endif //ESP_PLATFORM + return DEV_WIRE_ERR; + } + + bool inline clrRegisterBit(int registers, uint8_t bit) + { + int val = readRegister(registers); + if (val == DEV_WIRE_ERR) { + return false; + } + return writeRegister(registers, (val & (~_BV(bit)))) == 0; + } + + bool inline setRegisterBit(int registers, uint8_t bit) + { + int val = readRegister(registers); + if (val == DEV_WIRE_ERR) { + return false; + } + return writeRegister(registers, (val | (_BV(bit)))) == 0; + } + + bool inline getRegisterBit(int registers, uint8_t bit) + { + int val = readRegister(registers); + if (val == DEV_WIRE_ERR) { + return false; + } + return val & _BV(bit); + } + + uint16_t inline readRegisterH8L4(uint8_t highReg, uint8_t lowReg) + { + int h8 = readRegister(highReg); + int l4 = readRegister(lowReg); + if (h8 == DEV_WIRE_ERR || l4 == DEV_WIRE_ERR)return 0; + return (h8 << 4) | (l4 & 0x0F); + } + + uint16_t inline readRegisterH8L5(uint8_t highReg, uint8_t lowReg) + { + int h8 = readRegister(highReg); + int l5 = readRegister(lowReg); + if (h8 == DEV_WIRE_ERR || l5 == DEV_WIRE_ERR)return 0; + return (h8 << 5) | (l5 & 0x1F); + } + + uint16_t inline readRegisterH6L8(uint8_t highReg, uint8_t lowReg) + { + int h6 = readRegister(highReg); + int l8 = readRegister(lowReg); + if (h6 == DEV_WIRE_ERR || l8 == DEV_WIRE_ERR)return 0; + return ((h6 & 0x3F) << 8) | l8; + } + + uint16_t inline readRegisterH5L8(uint8_t highReg, uint8_t lowReg) + { + int h5 = readRegister(highReg); + int l8 = readRegister(lowReg); + if (h5 == DEV_WIRE_ERR || l8 == DEV_WIRE_ERR)return 0; + return ((h5 & 0x1F) << 8) | l8; + } + + void setRegAddressLength(uint8_t len) + { + __reg_addr_len = len; + } + + + void setReadRegisterSendStop(bool sendStop) + { + __sendStop = sendStop; + } + + + + /* + * CRTP Helper + */ +protected: + +// bool begin() +// { +// #if defined(ARDUINO) +// if (__has_init) return thisChip().initImpl(); +// __has_init = true; + +// if (__wire) { +// log_i("SDA:%d SCL:%d", __sda, __scl); +// #if defined(NRF52840_XXAA) || defined(NRF52832_XXAA) +// __wire->begin(); +// #elif defined(ARDUINO_ARCH_RP2040) +// __wire->end(); +// __wire->setSDA(__sda); +// __wire->setSCL(__scl); +// __wire->begin(); +// #else +// __wire->begin(__sda, __scl); +// #endif +// } +// if (__spi) { +// // int cs, int mosi = -1, int miso = -1, int sck = -1, SPIClass &spi = SPI +// begin(__cs, __mosi, __miso, __sck, *__spi); +// } + +// #endif /*ARDUINO*/ +// return thisChip().initImpl(); +// } + + void end() + { +#if defined(ARDUINO) + if (__wire) { +#if defined(ESP_IDF_VERSION) +#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4,4,0) + __wire->end(); +#endif /*ESP_IDF_VERSION*/ +#endif /*ESP_IDF_VERSION*/ + } +#endif /*ARDUINO*/ + } + + + inline const chipType &thisChip() const + { + return static_cast(*this); + } + + inline chipType &thisChip() + { + return static_cast(*this); + } + +protected: + bool __has_init = false; +#if defined(ARDUINO) + PLATFORM_WIRE_TYPE *__wire = NULL; + PLATFORM_SPI_TYPE *__spi = NULL; + SPISettings *__spiSetting = NULL; + uint8_t __dataOrder = SPI_DATA_ORDER; + uint8_t __dataMode = SPI_MODE0; + uint32_t __freq = 400000; + +#elif defined(ESP_PLATFORM) + i2c_port_t __i2c_num; +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + i2c_master_bus_handle_t bus_handle; + i2c_master_dev_handle_t __i2c_device; + i2c_device_config_t __i2c_dev_conf; +#endif //ESP_IDF_VERSION + +#endif //ESP_PLATFORM + + int __readMask = -1; + int __sda = -1; + int __scl = -1; + int __cs = -1; + int __miso = -1; + int __mosi = -1; + int __sck = -1; + bool __sendStop = true; + uint8_t __addr = 0xFF; + uint8_t __reg_addr_len = 1; + iic_fptr_t __i2c_master_read = NULL; + iic_fptr_t __i2c_master_write = NULL; + gpio_write_fptr_t __set_gpio_level = NULL; + gpio_read_fptr_t __get_gpio_level = NULL; + gpio_mode_fptr_t __set_gpio_mode = NULL; + delay_ms_fptr_t __delay_ms = NULL; + +}; diff --git a/lib/SensorLib/src/SensorDRV2605.hpp b/lib/SensorLib/src/SensorDRV2605.hpp new file mode 100644 index 0000000..87eef56 --- /dev/null +++ b/lib/SensorLib/src/SensorDRV2605.hpp @@ -0,0 +1,235 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorDRV2605.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-03 + * @note Source code from https://github.com/adafruit/Adafruit_DRV2605_Library + */ +#pragma once + +#include "REG/DRV2605Constants.h" +#include "SensorCommon.tpp" + +class SensorDRV2605 : + public SensorCommon +{ + friend class SensorCommon; +public: + +#if defined(ARDUINO) + SensorDRV2605(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = DRV2605_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + SensorDRV2605() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = DRV2605_SLAVE_ADDRESS; + } + + ~SensorDRV2605() + { + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = DRV2605_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + /**************************************************************************/ + /*! + @brief Select the haptic waveform to use. + @param slot The waveform slot to set, from 0 to 7 + @param w The waveform sequence value, refers to an index in the ROM library. + + Playback starts at slot 0 and continues through to slot 7, stopping if it + encounters a value of 0. A list of available waveforms can be found in + section 11.2 of the datasheet: http://www.adafruit.com/datasheets/DRV2605.pdf + */ + /**************************************************************************/ + void setWaveform(uint8_t slot, uint8_t w) + { + writeRegister(DRV2605_REG_WAVESEQ1 + slot, w); + } + + /**************************************************************************/ + /*! + @brief Select the waveform library to use. + @param lib Library to use, 0 = Empty, 1-5 are ERM, 6 is LRA. + + See section 7.6.4 in the datasheet for more details: + http://www.adafruit.com/datasheets/DRV2605.pdf + */ + /**************************************************************************/ + void selectLibrary(uint8_t lib) + { + writeRegister(DRV2605_REG_LIBRARY, lib); + } + + /**************************************************************************/ + /*! + @brief Start playback of the waveforms (start moving!). + */ + /**************************************************************************/ + void run() + { + writeRegister(DRV2605_REG_GO, 1); + } + + /**************************************************************************/ + /*! + @brief Stop playback. + */ + /**************************************************************************/ + void stop() + { + writeRegister(DRV2605_REG_GO, 0); + } + + /**************************************************************************/ + /*! + @brief Set the device mode. + @param mode Mode value, see datasheet section 7.6.2: + http://www.adafruit.com/datasheets/DRV2605.pdf + + 0: Internal trigger, call run() to start playback\n + 1: External trigger, rising edge on IN pin starts playback\n + 2: External trigger, playback follows the state of IN pin\n + 3: PWM/analog input\n + 4: Audio\n + 5: Real-time playback\n + 6: Diagnostics\n + 7: Auto calibration + */ + /**************************************************************************/ + void setMode(uint8_t mode) + { + writeRegister(DRV2605_REG_MODE, mode); + } + + /**************************************************************************/ + /*! + @brief Set the realtime value when in RTP mode, used to directly drive the + haptic motor. + @param rtp 8-bit drive value. + */ + /**************************************************************************/ + void setRealtimeValue(uint8_t rtp) + { + writeRegister(DRV2605_REG_RTPIN, rtp); + } + + /**************************************************************************/ + /*! + @brief Use ERM (Eccentric Rotating Mass) mode. + */ + /**************************************************************************/ + void useERM() + { + writeRegister(DRV2605_REG_FEEDBACK, readRegister(DRV2605_REG_FEEDBACK) & 0x7F); + } + + /**************************************************************************/ + /*! + @brief Use LRA (Linear Resonance Actuator) mode. + */ + /**************************************************************************/ + void useLRA() + { + writeRegister(DRV2605_REG_FEEDBACK, readRegister(DRV2605_REG_FEEDBACK) | 0x80); + } + +private: + bool initImpl() + { + int chipID = readRegister(DRV2605_REG_STATUS); + if (chipID == -1) { + return false; + } + chipID >>= 5; + + if (chipID != DRV2604_CHIP_ID && + chipID != DRV2605_CHIP_ID && + chipID != DRV2604L_CHIP_ID && + chipID != DRV2605L_CHIP_ID ) { + LOG("ChipID:0x%x should be 0x03 or 0x04 or 0x06 or 0x07\n", chipID); + return false; + } + + writeRegister(DRV2605_REG_MODE, 0x00); // out of standby + + writeRegister(DRV2605_REG_RTPIN, 0x00); // no real-time-playback + + writeRegister(DRV2605_REG_WAVESEQ1, 1); // strong click + writeRegister(DRV2605_REG_WAVESEQ2, 0); // end sequence + + writeRegister(DRV2605_REG_OVERDRIVE, 0); // no overdrive + + writeRegister(DRV2605_REG_SUSTAINPOS, 0); + writeRegister(DRV2605_REG_SUSTAINNEG, 0); + writeRegister(DRV2605_REG_BREAK, 0); + writeRegister(DRV2605_REG_AUDIOMAX, 0x64); + + // ERM open loop + + // turn off N_ERM_LRA + writeRegister(DRV2605_REG_FEEDBACK, + readRegister(DRV2605_REG_FEEDBACK) & 0x7F); + // turn on ERM_OPEN_LOOP + writeRegister(DRV2605_REG_CONTROL3, + readRegister(DRV2605_REG_CONTROL3) | 0x20); + + return true; + } + + int getReadMaskImpl() + { + return -1; + } + +protected: + +}; + + + diff --git a/lib/SensorLib/src/SensorLTR553.hpp b/lib/SensorLib/src/SensorLTR553.hpp new file mode 100644 index 0000000..ef1d5cc --- /dev/null +++ b/lib/SensorLib/src/SensorLTR553.hpp @@ -0,0 +1,349 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file SensorLTR553ALS.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-09 + * + */ +#pragma once + +#include "REG/LTR533Constants.h" +#include "SensorCommon.tpp" + + +class SensorLTR553 : + public SensorCommon +{ + friend class SensorCommon; +public: + + enum IrqLevel { + ALS_IRQ_ACTIVE_LOW, // INT pin is considered active when it is a logic 0 (default) + ALS_IRQ_ACTIVE_HIGH // INT pin is considered active when it is a logic 1 + }; + enum IrqMode { + ALS_IRQ_ONLY_PS = 1, // Only PS measurement can trigger interrupt + ALS_IRQ_ONLY_ALS, // Only ALS measurement can trigger interrupt + ALS_IRQ_BOTH, // Both ALS and PS measurement can trigger interrupt + }; + + enum LightSensorGain { + ALS_GAIN_1X = 0x00, // 1 lux to 64k lux (default) + ALS_GAIN_2X = 0x01, // 0.5 lux to 32k lux + ALS_GAIN_4X = 0x02, // 0.25 lux to 16k lux + ALS_GAIN_8X = 0x03, // 0.125 lux to 8k lux + ALS_GAIN_48X = 0x06, // 0.02 lux to 1.3k lux + ALS_GAIN_96X = 0x07, // 0.01 lux to 600 lux + }; + + enum PsLedPeriod { + PS_LED_PLUSE_30KHZ = 0x00, + PS_LED_PLUSE_40KHZ, + PS_LED_PLUSE_50KHZ, + PS_LED_PLUSE_60KHZ, + PS_LED_PLUSE_70KHZ, + PS_LED_PLUSE_80KHZ, + PS_LED_PLUSE_90KHZ, + PS_LED_PLUSE_100KHZ, + }; + enum PsLedDuty { + PS_LED_DUTY_25 = 0x00, + PS_LED_DUTY_50, + PS_LED_DUTY_75, + PS_LED_DUTY_100, + }; + enum PsLedCurrent { + PS_LED_CUR_5MA = 0x00, + PS_LED_CUR_10MA, + PS_LED_CUR_20MA, + PS_LED_CUR_50MA, + PS_LED_CUR_100MA, + }; + enum PsRate { + PS_MEAS_RATE_50MS, + PS_MEAS_RATE_70MS, + PS_MEAS_RATE_100MS, + PS_MEAS_RATE_200MS, + PS_MEAS_RATE_500MS, + PS_MEAS_RATE_1000MS, + PS_MEAS_RATE_2000MS, + PS_MEAS_RATE_10MS = 8, + }; + + enum IntegrationTime { + ALS_INTEGRATION_TIME_100MS = 0x00, + ALS_INTEGRATION_TIME_50MS, + ALS_INTEGRATION_TIME_200MS, + ALS_INTEGRATION_TIME_400MS, + ALS_INTEGRATION_TIME_150MS, + ALS_INTEGRATION_TIME_250MS, + ALS_INTEGRATION_TIME_300MS, + ALS_INTEGRATION_TIME_350MS, + }; + + enum MeasurementRate { + ALS_MEASUREMENT_TIME_50MS, + ALS_MEASUREMENT_TIME_100MS, + ALS_MEASUREMENT_TIME_200MS, + ALS_MEASUREMENT_TIME_500MS, + ALS_MEASUREMENT_TIME_1000MS, + ALS_MEASUREMENT_TIME_2000MS, + }; + +#if defined(ARDUINO) + SensorLTR553(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = LTR553_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + SensorLTR553() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = LTR553_SLAVE_ADDRESS; + } + + ~SensorLTR553() + { + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = LTR553_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + void setIRQLevel(IrqLevel level) + { + level ? setRegisterBit(LTR553_REG_INTERRUPT, 2) : clrRegisterBit(LTR553_REG_INTERRUPT, 2); + } + + void enableIRQ(IrqMode mode) + { + writeRegister(LTR553_REG_INTERRUPT, 0xFC, mode); + } + + void disableIRQ() + { + writeRegister(LTR553_REG_INTERRUPT, 0xFC, 0x00); + } + + + //! Light Sensor ! + bool psAvailable() + { + return getRegisterBit(LTR553_REG_ALS_PS_STATUS, 0); + } + + void setLightSensorThreshold(uint16_t low, uint16_t high) + { + uint8_t buffer[4] = { + (uint8_t)(high & 0xFF), + (uint8_t)((high >> 8) & 0xFF), + (uint8_t)(low & 0xFF), + (uint8_t)((low >> 8) & 0xFF), + }; + writeRegister(LTR553_REG_ALS_THRES_UP_0, buffer, 4); + } + + // Controls the N number of times the measurement data is outside the range + // defined by the upper and lower threshold limits before asserting the interrupt. + void setLightSensorPersists(uint8_t count) + { + writeRegister(LTR553_REG_INTERRUPT_PERSIST, 0xF0, count - 1); + } + + void setLightSensorRate(IntegrationTime integrationTime, MeasurementRate measurementRate) + { + writeRegister(LTR553_REG_ALS_MEAS_RATE, 0x00, (integrationTime & 0xF) << 8 | (measurementRate & 0xF)); + } + + void enableLightSensor() + { + setRegisterBit(LTR553_REG_ALS_CONTR, 0); + } + + void disableLightSensor() + { + clrRegisterBit(LTR553_REG_ALS_CONTR, 0); + } + + void setLightSensorGain(LightSensorGain gain) + { + writeRegister(LTR553_REG_ALS_CONTR, 0xE3, gain); + } + + int getLightSensor(uint8_t ch) + { + uint8_t buffer[2] = {0}; + // Check ALS Data is Valid + if (getRegisterBit(LTR553_REG_ALS_PS_STATUS, 7) != false) { + return 0; + } + int val = readRegister(ch == 1 ? LTR553_REG_ALS_DATA_CH1_0 : LTR553_REG_ALS_DATA_CH0_0, buffer, 2); + if (val == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + return buffer[0] | (buffer[1] << 8); + } + + //! Proximity sensor ! + // Controls the N number of times the measurement data is outside the range + // defined by the upper and lower threshold limits before asserting the interrupt. + void setProximityPersists(uint8_t count) + { + writeRegister(LTR553_REG_INTERRUPT_PERSIST, 0x0F, count == 0 ? 0 : count - 1); + } + + void setProximityThreshold(uint16_t low, uint16_t high) + { + writeRegister(LTR553_REG_PS_THRES_UP_0, lowByte(high)); + writeRegister(LTR553_REG_PS_THRES_UP_1, lowByte(high >> 8) & 0x0F); + writeRegister(LTR553_REG_PS_THRES_LOW_0, lowByte(low)); + writeRegister(LTR553_REG_PS_THRES_LOW_1, lowByte(low >> 8) & 0x0F); + } + + void setProximityRate(PsRate rate) + { + writeRegister(LTR553_REG_PS_MEAS_RATE, 0xF0, rate & 0x0F); + } + + void enableProximity() + { + writeRegister(LTR553_REG_PS_CONTR, 0xF3u, 0x03u); + } + + void disableProximity() + { + writeRegister(LTR553_REG_PS_CONTR, 0xF3u, 0x00u); + } + + void enablePsIndicator() + { + setRegisterBit(LTR553_REG_PS_CONTR, 5); + } + + void disablePsIndicator() + { + clrRegisterBit(LTR553_REG_PS_CONTR, 5); + } + + int getProximity(bool *saturated = NULL ) + { + uint8_t buffer[2] = {0}; + int val = readRegister(LTR553_REG_PS_DATA_0, buffer, 2); + if (val == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + if (saturated) { + *saturated = buffer[1] & 0x80; + } + return buffer[0] | (buffer[1] & 0x03); + } + + void setPsLedPulsePeriod(PsLedPeriod period) + { + writeRegister(LTR553_REG_PS_LED, 0x1F, period); + } + + void setPsLedDutyCycle(PsLedDuty duty) + { + writeRegister(LTR553_REG_PS_LED, 0xE7, duty); + } + + void setPsLedCurrnet(PsLedCurrent cur) + { + writeRegister(LTR553_REG_PS_LED, 0xF8, cur); + } + + void setPsLedPulses(uint8_t pulesNum) + { + writeRegister(LTR553_REG_PS_N_PULSES, 0xF0, pulesNum & 0x0F); + } + + int getPartID() + { + int val = readRegister(LTR553_REG_PART_ID); + if (val == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + return (val >> 4) & 0x0F; + } + + int getRevisionID() + { + int val = readRegister(LTR553_REG_PART_ID); + if (val == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + return (val) & 0x0F; + } + + int getManufacturerID() + { + // Manufacturer ID (0x05H) + return readRegister(LTR553_REG_MANUFAC_ID); + } + + void reset() + { + setRegisterBit(LTR553_REG_ALS_CONTR, 1); + } + +private: + + bool initImpl() + { + setReadRegisterSendStop(false); + reset(); + return getManufacturerID() == LTR553_DEFAULT_MAN_ID; + } + + int getReadMaskImpl() + { + return -1; + } + +protected: + +}; + + + diff --git a/lib/SensorLib/src/SensorLib.h b/lib/SensorLib/src/SensorLib.h new file mode 100644 index 0000000..4456fc4 --- /dev/null +++ b/lib/SensorLib/src/SensorLib.h @@ -0,0 +1,233 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorLib.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-05 + */ + +#pragma once + +#if defined(ARDUINO) +#include +#include +#include +#elif defined(ESP_PLATFORM) +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "esp_log.h" +#include "esp_err.h" +#include +#include "esp_idf_version.h" +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) +#include "driver/i2c_master.h" +#else +#include "driver/i2c.h" +#endif //ESP_IDF_VERSION +#else +#include +#include +#include +#endif + +#ifdef ARDUINO_ARCH_MBED +// Not supported at the moment +#error The Arduino RP2040 MBED board package is not supported when PIO is used. Use the community package by Earle Philhower. +#endif + +#if defined(ARDUINO) +#if defined(ARDUINO_ARCH_RP2040) +#define PLATFORM_SPI_TYPE SPIClassRP2040 +#define PLATFORM_WIRE_TYPE TwoWire +#define SPI_DATA_ORDER SPI_MSB_FIRST +#define DEFAULT_SDA (0xFF) +#define DEFAULT_SCL (0xFF) +#define DEFAULT_SPISETTING SPISettings() +#elif defined(NRF52840_XXAA) || defined(NRF52832_XXAA) +#define PLATFORM_SPI_TYPE SPIClass +#define PLATFORM_WIRE_TYPE TwoWire +#define SPI_DATA_ORDER MSBFIRST +#define DEFAULT_SDA (0xFF) +#define DEFAULT_SCL (0xFF) +#define DEFAULT_SPISETTING SPISettings() +#else +#define PLATFORM_SPI_TYPE SPIClass +#define PLATFORM_WIRE_TYPE TwoWire +#define SPI_DATA_ORDER SPI_MSBFIRST +#define DEFAULT_SDA (SDA) +#define DEFAULT_SCL (SCL) +#define DEFAULT_SPISETTING SPISettings(__freq, __dataOrder, __dataMode); +#endif + +#elif defined(ESP_PLATFORM) + +#define SENSORLIB_I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define SENSORLIB_I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define SENSORLIB_I2C_MASTER_TIMEOUT_MS 1000 +#define SENSORLIB_I2C_MASTER_SEEED 400000 + +#endif + +enum SensorLibInterface { + SENSORLIB_SPI_INTERFACE = 1, + SENSORLIB_I2C_INTERFACE +}; + +typedef struct __SensorLibPins { + int irq; + int rst; + union __ { + struct { + int sda; + int scl; + int addr; +#ifdef ARDUINO + PLATFORM_WIRE_TYPE *wire; +#endif + } i2c_dev; + struct { + int cs; + int miso; + int mosi; + int sck; +#ifdef ARDUINO + PLATFORM_SPI_TYPE *spi; +#endif + } spi_dev; + } u ; + SensorLibInterface intf; +} SensorLibConfigure; + + + + +#define SENSOR_PIN_NONE (-1) +#define DEV_WIRE_NONE (0) +#define DEV_WIRE_ERR (-1) +#define DEV_WIRE_TIMEOUT (-2) + + + + +#ifndef IRAM_ATTR +#define IRAM_ATTR +#endif + +#ifdef _BV +#undef _BV +#endif +#define _BV(b) (1UL << (uint32_t)(b)) + +// #define LOG_PORT Serial +#ifdef LOG_PORT +#define LOG(fmt, ...) LOG_PORT.printf("[%s] " fmt "\n", __func__, ##__VA_ARGS__) +#define LOG_BIN(x) LOG_PORT.println(x,BIN); +#else +#define LOG(fmt, ...) printf("[%s] " fmt "\n", __func__, ##__VA_ARGS__) +#define LOG_BIN(x) printf("[%s] 0x%X\n", __func__, x) +#endif + +#ifndef lowByte +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#endif + +#ifndef highByte +#define highByte(w) ((uint8_t) ((w) >> 8)) +#endif + +#ifndef bitRead +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#endif + +#ifndef bitSet +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#endif + +#ifndef bitClear +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#endif + +#ifndef bitToggle +#define bitToggle(value, bit) ((value) ^= (1UL << (bit))) +#endif + +#ifndef bitWrite +#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit)) +#endif + +#define SENSORLIB_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented"))) + +#define SENSORLIB_COUNT(x) (sizeof(x)/sizeof(*x)) + +#ifdef ARDUINO +#ifndef ESP32 +#ifndef log_e +#define log_e(...) Serial.printf(__VA_ARGS__) +#endif +#ifndef log_i +#define log_i(...) Serial.printf(__VA_ARGS__) +#endif +#ifndef log_d +#define log_d(...) Serial.printf(__VA_ARGS__) +#endif +#endif +#elif defined(ESP_PLATFORM) +#define log_e(...) printf(__VA_ARGS__) +#define log_i(...) printf(__VA_ARGS__) +#define log_d(...) printf(__VA_ARGS__) +#else +#define log_e(...) +#define log_i(...) +#define log_d(...) +#endif + +#if !defined(ARDUINO) && defined(ESP_PLATFORM) + +#ifndef INPUT +#define INPUT (0x0) +#endif + +#ifndef OUTPUT +#define OUTPUT (0x1) +#endif + +#ifndef RISING +#define RISING (0x01) +#endif + +#ifndef FALLING +#define FALLING (0x02) +#endif + +#ifndef LOW +#define LOW 0 +#endif + +#ifndef HIGH +#define HIGH 1 +#endif + +#include "platform/esp_arduino.h" + +#endif diff --git a/lib/SensorLib/src/SensorPCF85063.hpp b/lib/SensorLib/src/SensorPCF85063.hpp new file mode 100644 index 0000000..0fcdfc8 --- /dev/null +++ b/lib/SensorLib/src/SensorPCF85063.hpp @@ -0,0 +1,379 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorPCF85063.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-07 + * + */ +#pragma once +#include "REG/PCF85063Constants.h" +#include "SensorCommon.tpp" +#include "SensorRTC.h" + + +class SensorPCF85063 : + public SensorCommon, + public RTCCommon +{ + friend class SensorCommon; + friend class RTCCommon; +public: + + enum { + CLK_32_768KHZ, + CLK_1024KHZ, + CLK_32HZ, + CLK_1HZ, + }; + + +#if defined(ARDUINO) + SensorPCF85063(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF85063_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + SensorPCF85063() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = PCF85063_SLAVE_ADDRESS; + } + + ~SensorPCF85063() + { + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF85063_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + void setDateTime(RTC_DateTime datetime) + { + setDateTime(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second); + } + + void setDateTime(uint16_t year, + uint8_t month, + uint8_t day, + uint8_t hour, + uint8_t minute, + uint8_t second) + { + uint8_t buffer[7]; + buffer[0] = DEC2BCD(second) & 0x7F; + buffer[1] = DEC2BCD(minute); + buffer[2] = DEC2BCD(hour); + buffer[3] = DEC2BCD(day); + buffer[4] = getDayOfWeek(day, month, year); + buffer[5] = DEC2BCD(month); + buffer[6] = DEC2BCD(year % 100); + + writeRegister(PCF85063_SEC_REG, buffer, 7); + } + + + RTC_DateTime getDateTime() + { + RTC_DateTime datetime; + uint8_t buffer[7]; + readRegister(PCF85063_SEC_REG, buffer, 7); + datetime.available = ((buffer[0] & 0x80) == 0x80) ? false : true; + datetime.second = BCD2DEC(buffer[0] & 0x7F); + datetime.minute = BCD2DEC(buffer[1] & 0x7F); + if (is24Hour) { + datetime.hour = BCD2DEC(buffer[2] & 0x3F); // 24-hour mode + } else { + datetime.AMPM = (buffer[2] & 0x20) == 0x20 ? 'A' : 'P'; + datetime.hour = BCD2DEC(buffer[2] & 0x1F); // 12-hour mode + } + datetime.day = BCD2DEC(buffer[3] & 0x3F); + datetime.week = BCD2DEC(buffer[4] & 0x07); + datetime.month = BCD2DEC(buffer[5] & 0x1F); + datetime.year = BCD2DEC(buffer[6]) + 2000; + return datetime; + } + + void getDateTime(struct tm *timeinfo) + { + if (!timeinfo)return; + *timeinfo = conversionUnixTime(getDateTime()); + } + + /* + Defalut use 24H mode + bool is24HourMode() + { + return is24Hour; + } + + bool is12HourMode() + { + return !is24Hour; + } + + void set24Hour() + { + is24Hour = true; + clrRegisterBit(PCF85063_CTRL1_REG, 1); + } + + void set12Hour() + { + is24Hour = false; + setRegisterBit(PCF85063_CTRL1_REG, 1); + } + */ + + void stop() + { + setRegisterBit(PCF85063_CTRL1_REG, 5); + } + + void start() + { + clrRegisterBit(PCF85063_CTRL1_REG, 5); + } + + bool isRunning() + { + return !getRegisterBit(PCF85063_CTRL1_REG, 5); + } + + void enableAlarm() + { + setRegisterBit(PCF85063_CTRL2_REG, 7); + } + + void disableAlarm() + { + clrRegisterBit(PCF85063_CTRL2_REG, 7); + } + + void resetAlarm() + { + clrRegisterBit(PCF85063_CTRL2_REG, 6); + } + + bool isAlarmActive() + { + return getRegisterBit(PCF85063_CTRL2_REG, 6); + } + + RTC_Alarm getAlarm() + { + uint8_t buffer[5]; + readRegister(PCF85063_ALRM_MIN_REG, buffer, 5); + buffer[0] = BCD2DEC(buffer[0] & 0x80); //second + buffer[1] = BCD2DEC(buffer[1] & 0x40); //minute + buffer[2] = BCD2DEC(buffer[2] & 0x40); //hour + buffer[3] = BCD2DEC(buffer[3] & 0x08); //day + buffer[4] = BCD2DEC(buffer[4] & 0x08); //weekday + // RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week) + return RTC_Alarm(buffer[2], buffer[1], buffer[0], buffer[3], buffer[4]); + } + + void setAlarm(RTC_Alarm alarm) + { + setAlarm(alarm.hour, + alarm.minute, + alarm.second, + alarm.day, + alarm.week); + } + + void setAlarm(uint8_t hour, + uint8_t minute, + uint8_t second, + uint8_t day, + uint8_t week) + { + uint8_t buffer[5] = {0}; + + RTC_DateTime datetime = getDateTime(); + + uint8_t daysInMonth = getDaysInMonth(datetime.month, datetime.year); + + if (second != PCF85063_NO_ALARM) { + if (second > 59) { + second = 59; + } + buffer[0] = DEC2BCD(second); + buffer[0] &= ~PCF85063_ALARM_ENABLE; + } else { + buffer[0] = PCF85063_ALARM_ENABLE; + } + + if (minute != PCF85063_NO_ALARM) { + if (minute > 59) { + minute = 59; + } + buffer[1] = DEC2BCD(minute); + buffer[1] &= ~PCF85063_ALARM_ENABLE; + } else { + buffer[1] = PCF85063_ALARM_ENABLE; + } + if (hour != PCF85063_NO_ALARM) { + if (is24Hour) { + if (hour > 23) { + hour = 23; + } + buffer[2] = DEC2BCD(hour); + buffer[2] &= ~PCF85063_ALARM_ENABLE; + } else { + /* + if (hour > 12) { + hour = 12; + } + buffer[2] = DEC2BCD(hour); + buffer[2] |= isAM ? 0 : _BV(5); + buffer[2] &= ~PCF85063_ALARM_ENABLE; + */ + } + } else { + buffer[2] = PCF85063_ALARM_ENABLE; + } + if (day != PCF85063_NO_ALARM) { + //TODO:Check day in Month + buffer[3] = DEC2BCD(((day) < (1) ? (1) : ((day) > (daysInMonth) ? (daysInMonth) : (day)))); + buffer[3] &= ~PCF85063_ALARM_ENABLE; + } else { + buffer[3] = PCF85063_ALARM_ENABLE; + } + if (week != PCF85063_NO_ALARM) { + if (week > 6) { + week = 6; + } + buffer[4] = DEC2BCD(week); + buffer[4] &= ~PCF85063_ALARM_ENABLE; + } else { + buffer[4] = PCF85063_ALARM_ENABLE; + } + writeRegister(PCF85063_ALRM_SEC_REG, buffer, 4); + } + + void setAlarmByHours(uint8_t hour) + { + setAlarm(hour, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM); + } + + void setAlarmBySecond(uint8_t second) + { + setAlarm(PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + second, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM); + } + + void setAlarmByMinutes(uint8_t minute) + { + setAlarm(PCF85063_NO_ALARM, + minute, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM); + } + + void setAlarmByDays(uint8_t day) + { + setAlarm(PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + day, + PCF85063_NO_ALARM); + } + + void setAlarmByWeekDay(uint8_t week) + { + setAlarm(PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + PCF85063_NO_ALARM, + week); + } + +private: + + bool initImpl() + { + // 230704:Does not use power-off judgment, if the RTC backup battery is not installed, + // it will return failure. Here only to judge whether the device communication is normal + + //Check device is online + int ret = readRegister(PCF85063_SEC_REG); + if (ret == DEV_WIRE_ERR) { + return false; + } + if (BCD2DEC(ret & 0x7F) > 59) { + return false; + } + + //Default use 24-hour mode + is24Hour = !getRegisterBit(PCF85063_CTRL1_REG, 1); + if (!is24Hour) { + // Set 24H Mode + clrRegisterBit(PCF85063_CTRL1_REG, 1); + } + + //Trun on RTC + start(); + + return isRunning(); + } + + int getReadMaskImpl() + { + return -1; + } + +protected: + + bool is24Hour = true; +}; + + + diff --git a/lib/SensorLib/src/SensorPCF8563.hpp b/lib/SensorLib/src/SensorPCF8563.hpp new file mode 100644 index 0000000..f48835e --- /dev/null +++ b/lib/SensorLib/src/SensorPCF8563.hpp @@ -0,0 +1,359 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorPCF8563.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2022-12-09 + * + */ +#pragma once + +#include "REG/PCF8563Constants.h" +#include "SensorCommon.tpp" +#include "SensorRTC.h" + +class SensorPCF8563 : + public SensorCommon, + public RTCCommon +{ + friend class SensorCommon; + friend class RTCCommon; +public: + + enum { + CLK_32_768KHZ, + CLK_1024KHZ, + CLK_32HZ, + CLK_1HZ, + }; + + +#if defined(ARDUINO) + SensorPCF8563(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF8563_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + SensorPCF8563() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = PCF8563_SLAVE_ADDRESS; + } + + ~SensorPCF8563() + { + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF8563_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + void setDateTime(RTC_DateTime datetime) + { + setDateTime(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second); + } + + + void setDateTime(uint16_t year, + uint8_t month, + uint8_t day, + uint8_t hour, + uint8_t minute, + uint8_t second) + { + uint8_t buffer[7]; + buffer[0] = DEC2BCD(second) & 0x7F; + buffer[1] = DEC2BCD(minute); + buffer[2] = DEC2BCD(hour); + buffer[3] = DEC2BCD(day); + buffer[4] = getDayOfWeek(day, month, year); + buffer[5] = DEC2BCD(month); + buffer[6] = DEC2BCD(year % 100); + + if ((2000 % year) == 2000) { + buffer[5] &= 0x7F; + } else { + buffer[5] |= 0x80; + } + writeRegister(PCF8563_SEC_REG, buffer, 7); + } + + + RTC_DateTime getDateTime() + { + RTC_DateTime datetime; + uint8_t buffer[7]; + readRegister(PCF8563_SEC_REG, buffer, 7); + datetime.available = ((buffer[0] & 0x80) == 0x80) ? false : true; + datetime.second = BCD2DEC(buffer[0] & 0x7F); + datetime.minute = BCD2DEC(buffer[1] & 0x7F); + datetime.hour = BCD2DEC(buffer[2] & 0x3F); + datetime.day = BCD2DEC(buffer[3] & 0x3F); + datetime.week = BCD2DEC(buffer[4] & 0x07); + datetime.month = BCD2DEC(buffer[5] & 0x1F); + datetime.year = BCD2DEC(buffer[6]); + //cetury : 0 = 1900 , 1 = 2000 + datetime.year += (buffer[5] & PCF8563_CENTURY_MASK) ? 1900 : 2000; + return datetime; + } + + void getDateTime(struct tm *timeinfo) + { + if (!timeinfo)return; + *timeinfo = conversionUnixTime(getDateTime()); + } + + RTC_Alarm getAlarm() + { + uint8_t buffer[4]; + readRegister(PCF8563_ALRM_MIN_REG, buffer, 4); + buffer[0] = BCD2DEC(buffer[0] & 0x80); //minute + buffer[1] = BCD2DEC(buffer[1] & 0x40); //hour + buffer[2] = BCD2DEC(buffer[2] & 0x40); //day + buffer[3] = BCD2DEC(buffer[3] & 0x08); //weekday + // RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week) + return RTC_Alarm(buffer[1], buffer[0], 0, buffer[2], buffer[3]); + } + + void enableAlarm() + { + setRegisterBit(PCF8563_STAT2_REG, 1); + } + + void disableAlarm() + { + clrRegisterBit(PCF8563_STAT2_REG, 1); + } + + void resetAlarm() + { + clrRegisterBit(PCF8563_STAT2_REG, 3); + } + + bool isAlarmActive() + { + return getRegisterBit(PCF8563_STAT2_REG, 3); + } + + void setAlarm(RTC_Alarm alarm) + { + setAlarm( alarm.hour, alarm.minute, alarm.day, alarm.week); + } + + void setAlarm(uint8_t hour, uint8_t minute, uint8_t day, uint8_t week) + { + uint8_t buffer[4] = {0}; + + RTC_DateTime datetime = getDateTime(); + + uint8_t daysInMonth = getDaysInMonth(datetime.month, datetime.year); + + if (minute != PCF8563_NO_ALARM) { + if (minute > 59) { + minute = 59; + } + buffer[0] = DEC2BCD(minute); + buffer[0] &= ~PCF8563_ALARM_ENABLE; + } else { + buffer[0] = PCF8563_ALARM_ENABLE; + } + + if (hour != PCF8563_NO_ALARM) { + if (hour > 23) { + hour = 23; + } + buffer[1] = DEC2BCD(hour); + buffer[1] &= ~PCF8563_ALARM_ENABLE; + } else { + buffer[1] = PCF8563_ALARM_ENABLE; + } + if (day != PCF8563_NO_ALARM) { + //TODO:Check day in Month + buffer[2] = DEC2BCD(((day) < (1) ? (1) : ((day) > (daysInMonth) ? (daysInMonth) : (day)))); + buffer[2] &= ~PCF8563_ALARM_ENABLE; + } else { + buffer[2] = PCF8563_ALARM_ENABLE; + } + if (week != PCF8563_NO_ALARM) { + if (week > 6) { + week = 6; + } + buffer[3] = DEC2BCD(week); + buffer[3] &= ~PCF8563_ALARM_ENABLE; + } else { + buffer[3] = PCF8563_ALARM_ENABLE; + } + writeRegister(PCF8563_ALRM_MIN_REG, buffer, 4); + } + + void setAlarmByMinutes(uint8_t minute) + { + setAlarm(PCF8563_NO_ALARM, minute, PCF8563_NO_ALARM, PCF8563_NO_ALARM); + } + void setAlarmByDays(uint8_t day) + { + setAlarm(PCF8563_NO_ALARM, PCF8563_NO_ALARM, day, PCF8563_NO_ALARM); + } + void setAlarmByHours(uint8_t hour) + { + setAlarm(hour, PCF8563_NO_ALARM, PCF8563_NO_ALARM, PCF8563_NO_ALARM); + } + void setAlarmByWeekDay(uint8_t week) + { + setAlarm(PCF8563_NO_ALARM, PCF8563_NO_ALARM, PCF8563_NO_ALARM, week); + } + + bool isCountdownTimerEnable() + { + uint8_t buffer[2]; + buffer[0] = readRegister(PCF8563_STAT2_REG); + buffer[1] = readRegister(PCF8563_TIMER1_REG); + if (buffer[0] & PCF8563_TIMER_TIE) { + return buffer[1] & PCF8563_TIMER_TE ? true : false; + } + return false; + } + + bool isCountdownTimerActive() + { + return getRegisterBit(PCF8563_STAT2_REG, 2); + } + + void enableCountdownTimer() + { + setRegisterBit(PCF8563_STAT2_REG, 0); + } + + void disableCountdownTimer() + { + clrRegisterBit(PCF8563_STAT2_REG, 0); + } + + void setCountdownTimer(uint8_t val, uint8_t freq) + { + uint8_t buffer[3]; + buffer[1] = readRegister(PCF8563_TIMER1_REG); + buffer[1] |= (freq & PCF8563_TIMER_TD10); + buffer[2] = val; + writeRegister(PCF8563_TIMER1_REG, buffer[1]); + writeRegister(PCF8563_TIMER2_REG, buffer[2]); + } + + void clearCountdownTimer() + { + uint8_t val; + val = readRegister(PCF8563_STAT2_REG); + val &= ~(PCF8563_TIMER_TF | PCF8563_TIMER_TIE); + val |= PCF8563_ALARM_AF; + writeRegister(PCF8563_STAT2_REG, val); + writeRegister(PCF8563_TIMER1_REG, 0x00); + } + + void enableCLK(uint8_t freq) + { + if (freq > CLK_1HZ) return; + writeRegister(PCF8563_SQW_REG, freq | PCF8563_CLK_ENABLE); + } + + void disableCLK() + { + clrRegisterBit(PCF8563_SQW_REG, 7); + } + + + +private: + + bool initImpl() + { + // Check whether RTC time is valid? If it is invalid, it can be judged + // that there is a problem with the hardware, or the RTC power supply voltage is too low + /* + int count = 0; + for (int i = 0; i < 3; ++i) { + if (!getRegisterBit(PCF8563_SEC_REG, 7)) { + count++; + } + } + if (count != 3 ) { + return false; + } + */ + + // 230704:Does not use power-off judgment, if the RTC backup battery is not installed, + // it will return failure. Here only to judge whether the device communication is normal + + //Check device is online + int ret = readRegister(PCF8563_SEC_REG); + if (ret == DEV_WIRE_ERR) { + return false; + } + if (BCD2DEC(ret & 0x7F) > 59) { + return false; + } + + // Determine whether the hardware clock year, month, and day match the internal time of the RTC. + // If they do not match, it will be updated to the compilation date + // RTC_DateTime compileDatetime = RTC_DateTime(__DATE__, __TIME__); + // RTC_DateTime hwDatetime = getDateTime(); + // if (compileDatetime.year != hwDatetime.year || + // compileDatetime.month != hwDatetime.month || + // compileDatetime.day != hwDatetime.month + // ) { + // LOG("No match yy:mm:dd . set datetime to compilation date time"); + // setDateTime(compileDatetime); + // } + return true; + } + + int getReadMaskImpl() + { + return -1; + } + +protected: + + +}; + + + diff --git a/lib/SensorLib/src/SensorQMC6310.hpp b/lib/SensorLib/src/SensorQMC6310.hpp new file mode 100644 index 0000000..f044072 --- /dev/null +++ b/lib/SensorLib/src/SensorQMC6310.hpp @@ -0,0 +1,402 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorQMC6310.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#pragma once + +#include "REG/QMC6310Constants.h" +#include "SensorCommon.tpp" + +class Polar +{ +public: + Polar(): polar(0), Gauss(0), uT(0) {} + Polar(float polar, float Gauss, float uT): polar(polar), Gauss(Gauss), uT(uT) {} + float polar; + float Gauss; + float uT; +}; + + +class SensorQMC6310 : + public SensorCommon +{ + friend class SensorCommon; +public: + + + enum SensorMode { + MODE_SUSPEND, + MODE_NORMAL, + MODE_SINGLE, + MODE_CONTINUOUS, + }; + + // Unit:Guass + enum MagRange { + RANGE_30G, + RANGE_12G, + RANGE_8G, + RANGE_2G, + }; + + enum OutputRate { + DATARATE_10HZ, + DATARATE_50HZ, + DATARATE_100HZ, + DATARATE_200HZ, + }; + + enum CtrlReg { + SET_RESET_ON, + SET_ONLY_ON, + SET_RESET_OFF, + }; + + enum OverSampleRatio { + OSR_8, + OSR_4, + OSR_2, + OSR_1, + }; + + enum DownSampleRatio { + DSR_1, + DSR_2, + DSR_4, + DSR_8, + }; + +#if defined(ARDUINO) + SensorQMC6310(PLATFORM_WIRE_TYPE &w, int sda = SDA, int scl = SCL, uint8_t addr = QMC6310_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + SensorQMC6310() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = SDA; + __scl = SCL; +#endif + __addr = QMC6310_SLAVE_ADDRESS; + } + + ~SensorQMC6310() + { + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = QMC6310_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + + void deinit() + { + // end(); + } + + void reset() + { + writeRegister(QMC6310_REG_CMD2, 0x80); + delay(10); + writeRegister(QMC6310_REG_CMD2, 0x00); + } + + uint8_t getChipID() + { + return readRegister(QMC6310_REG_CHIP_ID); + } + + + int getStatus() + { + return readRegister(QMC6310_REG_STAT); + } + + bool isDataReady() + { + if (readRegister(QMC6310_REG_STAT) & 0x01) { + return true; + } + LOG("No ready!\n"); + return false; + } + + bool isDataOverflow() + { + if (readRegister(QMC6310_REG_STAT) & 0x02) { + return true; + } + return false; + } + + int setSelfTest(bool en) + { + return en ? setRegisterBit(QMC6310_REG_CMD2, 1) + : clrRegisterBit(QMC6310_REG_CMD2, 1); + } + + int setMode(SensorMode m) + { + return writeRegister(QMC6310_REG_CMD1, 0xFC, m); + } + + int setCtrlRegister(CtrlReg c) + { + return writeRegister(QMC6310_REG_CMD2, 0xFC, c); + } + + int setDataOutputRate(OutputRate odr) + { + return writeRegister(QMC6310_REG_CMD1, 0xF3, (odr << 2)); + } + + int setOverSampleRate(OverSampleRatio osr) + { + return writeRegister(QMC6310_REG_CMD1, 0xCF, (osr << 4)); + } + + int setDownSampleRate(DownSampleRatio dsr) + { + return writeRegister(QMC6310_REG_CMD1, 0x3F, (dsr << 6)); + } + + // Define the sign for X Y and Z axis + int setSign(uint8_t x, uint8_t y, uint8_t z) + { + int sign = x + y * 2 + z * 4; + return writeRegister(QMC6310_REG_SIGN, sign); + } + + int configMagnetometer(SensorMode mode, MagRange range, OutputRate odr, + OverSampleRatio osr, DownSampleRatio dsr) + { + if (setMagRange(range) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + if (writeRegister(QMC6310_REG_CMD1, 0xFC, mode) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + if (writeRegister(QMC6310_REG_CMD1, 0xF3, (odr << 2)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + if (writeRegister(QMC6310_REG_CMD1, 0xCF, (osr << 4)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + if (writeRegister(QMC6310_REG_CMD1, 0x3F, (dsr << 6)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + return DEV_WIRE_NONE; + } + + int setMagRange(MagRange range) + { + switch (range) { + case RANGE_30G: + sensitivity = 0.1; + break; + case RANGE_12G: + sensitivity = 0.04; + break; + case RANGE_8G: + sensitivity = 0.026; + break; + case RANGE_2G: + sensitivity = 0.0066; + break; + default: + break; + } + return writeRegister(QMC6310_REG_CMD2, 0xF3, (range << 2)); + } + + void setOffset(int x, int y, int z) + { + x_offset = x; y_offset = y; z_offset = z; + } + + int readData() + { + uint8_t buffer[6]; + int16_t x, y, z; + if (readRegister(QMC6310_REG_LSB_DX, buffer, + 6) != DEV_WIRE_ERR) { + x = (int16_t)(buffer[1] << 8) | (buffer[0]); + y = (int16_t)(buffer[3] << 8) | (buffer[2]); + z = (int16_t)(buffer[5] << 8) | (buffer[4]); + + if (x == 32767) { + x = -((65535 - x) + 1); + } + x = (x - x_offset); + if (y == 32767) { + y = -((65535 - y) + 1); + } + y = (y - y_offset); + if (z == 32767) { + z = -((65535 - z) + 1); + } + z = (z - z_offset); + + raw[0] = x; + raw[1] = y; + raw[2] = z; + + mag[0] = (float)x * sensitivity; + mag[1] = (float)y * sensitivity; + mag[2] = (float)z * sensitivity; + return DEV_WIRE_NONE; + } + return DEV_WIRE_ERR; + } + + void setDeclination(float dec) + { + _declination = dec; + } + + bool readPolar(Polar &p) + { + if (isDataReady()) { + readData(); + float x = getX(); + float y = getY(); + float z = getZ(); + float angle = (atan2(x, -y) / PI) * 180.0 + _declination; + angle = _convertAngleToPositive(angle); + float magnitude = sqrt(x * x + y * y + z * z); + p = Polar(angle, magnitude * 100, magnitude); + return true; + } + return false; + } + + int16_t getRawX() + { + return raw[0]; + } + + int16_t getRawY() + { + return raw[1]; + } + + int16_t getRawZ() + { + return raw[2]; + } + + float getX() + { + return mag[0]; + } + + float getY() + { + return mag[1]; + } + + float getZ() + { + return mag[2]; + } + + void getMag(float &x, float &y, float &z) + { + x = mag[0]; + y = mag[1]; + z = mag[2]; + } + + void dumpCtrlRegister() + { + uint8_t buffer[2]; + readRegister(QMC6310_REG_CMD1, buffer, 2); + for (int i = 0; i < 2; ++i) { +#if defined(ARDUINO) + Serial.printf("CMD%d: 0x%02x", i + 1, buffer[i]); +#else + printf("CTRL%d: 0x%02x", i + 1, buffer[i]); +#endif +#if defined(ARDUINO) + Serial.print("\t\t BIN:"); + Serial.println(buffer[i], BIN); +#else + LOG("\n"); +#endif + } +#if defined(ARDUINO) + Serial.println(); +#else + printf("\n"); +#endif + } + +private: + + float _convertAngleToPositive(float angle) + { + if (angle >= 360.0) { + angle = angle - 360.0; + } + if (angle < 0) { + angle = angle + 360.0; + } + return angle; + } + + + bool initImpl() + { + reset(); + return getChipID() == QMC6310_DEFAULT_ID; + } + + int getReadMaskImpl() + { + return -1; + } + +protected: + int16_t raw[3]; + float mag[3]; + float _declination; + float sensitivity; + int16_t x_offset = 0, y_offset = 0, z_offset = 0; +}; + diff --git a/lib/SensorLib/src/SensorQMI8658.hpp b/lib/SensorLib/src/SensorQMI8658.hpp new file mode 100644 index 0000000..99cc829 --- /dev/null +++ b/lib/SensorLib/src/SensorQMI8658.hpp @@ -0,0 +1,1510 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorQMI8658.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2022-10-16 + * + */ +#pragma once + +#include "REG/QMI8658Constants.h" +#include "SensorCommon.tpp" +#ifndef ARDUINO +#include +#include +#endif +typedef struct __IMUdata { + float x; + float y; + float z; +} IMUdata; + +class SensorQMI8658 : + public SensorCommon +{ + friend class SensorCommon; +public: + + typedef void (*EventCallBack_t)(void); + + enum AccelRange { + ACC_RANGE_2G, + ACC_RANGE_4G, + ACC_RANGE_8G, + ACC_RANGE_16G + }; + + enum GyroRange { + GYR_RANGE_16DPS, + GYR_RANGE_32DPS, + GYR_RANGE_64DPS, + GYR_RANGE_128DPS, + GYR_RANGE_256DPS, + GYR_RANGE_512DPS, + GYR_RANGE_1024DPS, + }; + + // In 6DOF mode (accelerometer and gyroscope are both enabled), + // the output data rate is derived from the nature frequency of gyroscope + enum AccelODR { + ACC_ODR_1000Hz = 3, + ACC_ODR_500Hz, + ACC_ODR_250Hz, + ACC_ODR_125Hz, + ACC_ODR_62_5Hz, + ACC_ODR_31_25Hz, + ACC_ODR_LOWPOWER_128Hz = 12, + ACC_ODR_LOWPOWER_21Hz, + ACC_ODR_LOWPOWER_11Hz, + ACC_ODR_LOWPOWER_3Hz + }; + + enum GyroODR { + GYR_ODR_7174_4Hz, + GYR_ODR_3587_2Hz, + GYR_ODR_1793_6Hz, + GYR_ODR_896_8Hz, + GYR_ODR_448_4Hz, + GYR_ODR_224_2Hz, + GYR_ODR_112_1Hz, + GYR_ODR_56_05Hz, + GYR_ODR_28_025Hz + }; + + //Low-Pass Filter. + enum LpfMode { + LPF_MODE_0, //2.66% of ODR + LPF_MODE_1, //3.63% of ODR + LPF_MODE_2, //5.39% of ODR + LPF_MODE_3, //13.37% of ODR + }; + + enum MotionEvent { + MOTION_TAP, + MOTION_ANT_MOTION, + MOTION_NO_MOTION, + MOTION_SIGNIFICANT, + MOTION_PEDOMETER, + }; + + enum IntPin { + IntPin1, + IntPin2, + }; + + enum Fifo_Samples { + FIFO_SAMPLES_16, + FIFO_SAMPLES_32, + FIFO_SAMPLES_64, + FIFO_SAMPLES_128, + FIFO_SAMPLES_MAX, + } ; + + enum FIFO_Mode { + FIFO_MODE_BYPASS, + FIFO_MODE_FIFO, + FIFO_MODE_STREAM, + FIFO_MODE_MAX, + }; + + enum SampleMode { + SYNC_MODE, //Synchronous sampling + ASYNC_MODE, //Asynchronous sampling + }; + + enum CommandTable { + CTRL_CMD_ACK = 0x00, + CTRL_CMD_RST_FIFO = 0x04, + CTRL_CMD_REQ_FIFO = 0x05, + CTRL_CMD_WRITE_WOM_SETTING = 0x08, + CTRL_CMD_ACCEL_HOST_DELTA_OFFSET = 0x09, + CTRL_CMD_GYRO_HOST_DELTA_OFFSET = 0x0A, + CTRL_CMD_CONFIGURE_TAP = 0x0C, + CTRL_CMD_CONFIGURE_PEDOMETER = 0x0D, + CTRL_CMD_CONFIGURE_MOTION = 0x0E, + CTRL_CMD_RESET_PEDOMETER = 0x0F, + CTRL_CMD_COPY_USID = 0x10, + CTRL_CMD_SET_RPU = 0x11, + CTRL_CMD_AHB_CLOCK_GATING = 0x12, + CTRL_CMD_ON_DEMAND_CALIBRATION = 0xA2, + CTRL_CMD_APPLY_GYRO_GAINS = 0xAA, + }; + + enum StatusReg { + EVENT_SIGNIFICANT_MOTION = 128, + EVENT_NO_MOTION = 64, + EVENT_ANY_MOTION = 32, + EVENT_PEDOMETER_MOTION = 16, + EVENT_WOM_MOTION = 4, + EVENT_TAP_MOTION = 2, + }; + +#if defined(ARDUINO) + SensorQMI8658(PLATFORM_WIRE_TYPE &w, int sda = SDA, int scl = SCL, uint8_t addr = QMI8658_L_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } + + SensorQMI8658(int cs, int mosi = -1, int miso = -1, int sck = -1, PLATFORM_SPI_TYPE &spi = SPI) + { + __spi = &spi; + __cs = cs; + __miso = miso; + __mosi = mosi; + __sck = sck; + } + +#endif + + SensorQMI8658() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = SDA; + __scl = SCL; +#endif + __addr = QMI8658_L_SLAVE_ADDRESS; + } + + ~SensorQMI8658() + { + log_i("~SensorQMI8658"); + deinit(); + } + +#if defined(ARDUINO) + bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = QMI8658_L_SLAVE_ADDRESS) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + + void deinit() + { + // end(); + } + + bool reset(bool waitResult = true, uint32_t timeout = 500) + { + int val = 0; // initialize with some value to avoid compilation errors + writeRegister(QMI8658_REG_RESET, QMI8658_REG_RESET_DEFAULT); + // Maximum 15ms for the Reset process to be finished + if (waitResult) { + uint32_t start = millis(); + while (millis() - start < timeout) { + val = readRegister(QMI8658_REG_RST_RESULT); + if (val != DEV_WIRE_ERR && val == QMI8658_REG_RST_RESULT_VAL) { + + //EN.ADDR_AI + setRegisterBit(QMI8658_REG_CTRL1, 6); + + return true; + } + delay(10); + } + LOG("Reset chip failed, respone val = %d - 0x%X\n", val, val); + return false; + } + + //EN.ADDR_AI + setRegisterBit(QMI8658_REG_CTRL1, 6); + + return true; + } + + uint8_t getChipID() + { + return readRegister(QMI8658_REG_REVISION); + } + + int whoAmI() + { + return readRegister(QMI8658_REG_WHOAMI); + } + + uint32_t getTimestamp() + { + uint8_t buffer[3]; + uint32_t timestamp; + if (readRegister(QMI8658_REG_TIMESTAMP_L, buffer, 3) != DEV_WIRE_ERR) { + timestamp = (uint32_t)(((uint32_t)buffer[2] << 16) | + ((uint32_t)buffer[1] << 8) | buffer[0]); + if (timestamp > lastTimestamp) { + lastTimestamp = timestamp; + } else { + lastTimestamp = (timestamp + 0x1000000 - lastTimestamp); + } + } + return lastTimestamp; + } + + + float getTemperature_C() + { + uint8_t buffer[2]; + if (readRegister(QMI8658_REG_TEMPEARTURE_L, buffer, 2) != DEV_WIRE_ERR) { + return (float)buffer[1] + ((float)buffer[0] / 256.0); + } + return NAN; + } + + void enableINT(IntPin pin, bool enable = true) + { + switch (pin) { + case IntPin1: + enable ? setRegisterBit(QMI8658_REG_CTRL1, 3) : clrRegisterBit(QMI8658_REG_CTRL1, 3); + break; + case IntPin2: + enable ? setRegisterBit(QMI8658_REG_CTRL1, 4) : clrRegisterBit(QMI8658_REG_CTRL1, 4); + break; + default: + break; + } + } + + uint8_t getIrqStatus() + { + return readRegister(QMI8658_REG_STATUSINT); + } + + + void enableDataReadyINT(bool enable = true) + { + enable ? clrRegisterBit(QMI8658_REG_CTRL7, 5) : + setRegisterBit(QMI8658_REG_CTRL7, 5); + } + + /** + * @brief + * @note + * @param range: + * @param odr: + * @param lpfOdr: + * @param lpf: + * @param selfTest: + * @retval + */ + int configAccelerometer(AccelRange range, AccelODR odr, LpfMode lpfOdr = LPF_MODE_0, + bool lpf = true, bool selfTest = true) + { + bool en = isEnableAccelerometer(); + + if (en) { + disableAccelerometer(); + } + + //setAccelRange + if (writeRegister(QMI8658_REG_CTRL2, 0x8F, (range << 4)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + switch (range) { + // Possible accelerometer scales (and their register bit settings) are: + // 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11). + // Here's a bit of an algorith to calculate DPS/(ADC tick) based on that + // 2-bit value: + case ACC_RANGE_2G: accelScales = 2.0 / 32768.0; break; + case ACC_RANGE_4G: accelScales = 4.0 / 32768.0; break; + case ACC_RANGE_8G: accelScales = 8.0 / 32768.0; break; + case ACC_RANGE_16G: accelScales = 16.0 / 32768.0; break; + } + + // setAccelOutputDataRate + if (writeRegister(QMI8658_REG_CTRL2, 0xF0, odr) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + // setAccelLowPassFitter + lpf ? setRegisterBit(QMI8658_REG_CTRL5, 0) : clrRegisterBit(QMI8658_REG_CTRL5, 0); + + // setAccelLowPassFitterOdr + if (writeRegister(QMI8658_REG_CTRL5, QMI8658_ACCEL_LPF_MASK, (lpfOdr << 1)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + // setAccelSelfTest + selfTest ? setRegisterBit(QMI8658_REG_CTRL2, 7) : clrRegisterBit(QMI8658_REG_CTRL2, 7); + + if (en) { + enableAccelerometer(); + } + + return DEV_WIRE_NONE; + } + + /** + * @brief + * @note + * @param range: + * @param odr: + * @param lpfOdr: + * @param lpf: + * @param selfTest: + * @retval + */ + int configGyroscope(GyroRange range, GyroODR odr, LpfMode lpfOdr = LPF_MODE_0, + bool lpf = true, bool selfTest = true) + { + bool en = isEnableGyroscope(); + + if (en) { + disableGyroscope(); + } + + // setGyroRange + if (writeRegister(QMI8658_REG_CTRL3, 0x8F, (range << 4)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + switch (range) { + // Possible gyro scales (and their register bit settings) are: + // 250 DPS (00), 500 DPS (01), 1000 DPS (10), and 2000 DPS (11). + // Here's a bit of an algorith to calculate DPS/(ADC tick) based on that + // 2-bit value: + case GYR_RANGE_16DPS: gyroScales = 16.0 / 32768.0; break; + case GYR_RANGE_32DPS: gyroScales = 32.0 / 32768.0; break; + case GYR_RANGE_64DPS: gyroScales = 64.0 / 32768.0; break; + case GYR_RANGE_128DPS: gyroScales = 128.0 / 32768.0; break; + case GYR_RANGE_256DPS: gyroScales = 256.0 / 32768.0; break; + case GYR_RANGE_512DPS: gyroScales = 512.0 / 32768.0; break; + case GYR_RANGE_1024DPS: gyroScales = 1024.0 / 32768.0; break; + } + + // setGyroOutputDataRate + if (writeRegister(QMI8658_REG_CTRL3, 0xF0, odr) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + // setGyroLowPassFitter + lpf ? setRegisterBit(QMI8658_REG_CTRL5, 4) : clrRegisterBit(QMI8658_REG_CTRL5, 4); + + + // setGyroLowPassFitterOdr + if (writeRegister(QMI8658_REG_CTRL5, QMI8658_GYRO_LPF_MASK, (lpfOdr << 5)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + // setGyroSelfTest + selfTest ? setRegisterBit(QMI8658_REG_CTRL3, 7) : clrRegisterBit(QMI8658_REG_CTRL3, 7); + + + if (en) { + enableGyroscope(); + } + + return DEV_WIRE_NONE; + } + + /** + * @brief + * @note + * @param mode: + * @param samples: + * @param pin: + * @param watermark: + * @retval + */ + int configFIFO(FIFO_Mode mode, + Fifo_Samples samples = FIFO_SAMPLES_16, IntPin pin = IntPin2, + uint8_t watermark = 8) + { + bool enGyro = isEnableGyroscope(); + bool enAccel = isEnableAccelerometer(); + + if (enGyro) { + disableGyroscope(); + } + + if (enAccel) { + disableAccelerometer(); + } + + ///////////////// + pin == IntPin2 ? clrRegisterBit(QMI8658_REG_CTRL1, 2) : setRegisterBit(QMI8658_REG_CTRL1, 2); + + // set fifo mode and samples len + fifoMode = (samples << 2) | mode; + if (writeRegister(QMI8658_REG_FIFOCTRL, fifoMode) == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + + // set watermark + if (writeRegister(QMI8658_REG_FIFOWMKTH, watermark) == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + + //reset fifo + writeCommand(CTRL_CMD_RST_FIFO); + ///////////////// + + if (enGyro) { + enableGyroscope(); + } + + if (enAccel) { + enableAccelerometer(); + } + + return DEV_WIRE_NONE; + } + + uint16_t getFifoNeedBytes() + { + uint8_t sam[] = {16, 32, 64, 128}; + uint8_t sensors = 0; + if (gyroEn && accelEn) { + sensors = 2; + } else if (gyroEn || accelEn) { + sensors = 1; + } + uint8_t samples = ((fifoMode >> 2) & 0x03) ; + return sam[samples] * 6 * sensors; + } + + bool readFromFifo(IMUdata *acc, uint16_t accLenght, IMUdata *gyr, uint16_t gyrLenght) + { + uint16_t bytes = getFifoNeedBytes(); + uint8_t *buffer = new uint8_t [bytes]; + if (!buffer) { + LOG("No memory!"); + return false; + } + if (!readFromFifo(buffer, bytes)) { + delete buffer; + return false; + } + + int counter = 0; + for (int i = 0; i < bytes; ) { + if (accelEn) { + if (counter < accLenght) { + acc[counter].x = (float)((int16_t)buffer[i] | (buffer[i + 1] << 8)) * accelScales; + acc[counter].y = (float)((int16_t)buffer[i + 2] | (buffer[i + 3] << 8)) * accelScales; + acc[counter].z = (float)((int16_t)buffer[i + 4] | (buffer[i + 5] << 8)) * accelScales; + } + i += 6; + } + + if (gyroEn) { + if (counter < gyrLenght) { + gyr[counter].x = (float)((int16_t)buffer[i] | (buffer[i + 1] << 8)) * gyroScales; + gyr[counter].y = (float)((int16_t)buffer[i + 2] | (buffer[i + 3] << 8)) * gyroScales; + gyr[counter].z = (float)((int16_t)buffer[i + 4] | (buffer[i + 5] << 8)) * gyroScales; + } + i += 6; + } + counter++; + } + delete buffer; + return true; + } + + bool readFromFifo(uint8_t *data, size_t lenght) + { + uint8_t status[2]; + uint8_t fifo_sensors = 1; + uint16_t fifo_bytes = 0; + uint16_t fifo_level = 0; + + // get fifo status + int val = readRegister(QMI8658_REG_FIFOSTATUS); + if (val == DEV_WIRE_ERR) { + return false; + } + LOG("fifo status:0x%x ", val); + + if (val & (1 << 5)) { + LOG("\t\tFIFO Overflow condition has happened (data dropping happened)\n"); + } + if (val & (1 << 6)) { + LOG("\t\tFIFO Water Mark Level Hit\n"); + } + if (val & (1 << 7)) { + LOG("\t\tFIFO is Full\n"); + } + + val = readRegister(QMI8658_REG_FIFOCOUNT, status, 2); + if (val == DEV_WIRE_ERR) { + return false; + } + + fifo_bytes = ((status[1] & 0x03)) << 8 | status[0]; + + if (accelEn && gyroEn) { + fifo_sensors = 2; + } else if (accelEn || gyroEn) { + fifo_sensors = 1; + } + + fifo_level = fifo_bytes / (3 * fifo_sensors); + fifo_bytes = fifo_level * (6 * fifo_sensors); + + LOG("fifo-level : %d fifo_bytes : %d fifo_sensors : %d\n", fifo_level, fifo_bytes, fifo_sensors); + if (lenght < fifo_bytes) { + writeCommand(CTRL_CMD_RST_FIFO); + return false; + } + + if (fifo_level) { + writeCommand(CTRL_CMD_REQ_FIFO); + + if (readRegister(QMI8658_REG_FIFODATA, data, fifo_bytes) == + DEV_WIRE_ERR) { + LOG("get fifo error !"); + return false; + } + + val = writeRegister(QMI8658_REG_FIFOCTRL, fifoMode); + if (val == DEV_WIRE_ERR) { + return false; + } + } + + writeCommand(CTRL_CMD_RST_FIFO); + + return fifo_level; + } + + bool enableAccelerometer() + { + accelEn = true; + return setRegisterBit(QMI8658_REG_CTRL7, 0) == DEV_WIRE_NONE; + } + + bool disableAccelerometer() + { + accelEn = false; + return clrRegisterBit(QMI8658_REG_CTRL7, 0) == DEV_WIRE_NONE; + } + + bool isEnableAccelerometer() + { + accelEn = getRegisterBit(QMI8658_REG_CTRL7, 0); + return accelEn; + } + + bool isEnableGyroscope() + { + gyroEn = getRegisterBit(QMI8658_REG_CTRL7, 1); + return gyroEn; + } + + bool enableGyroscope() + { + gyroEn = true; + return setRegisterBit(QMI8658_REG_CTRL7, 1) == DEV_WIRE_NONE; + } + + bool disableGyroscope() + { + gyroEn = false; + return clrRegisterBit(QMI8658_REG_CTRL7, 1) == DEV_WIRE_NONE; + } + + bool getAccelRaw(int16_t *rawBuffer) + { + uint8_t buffer[6] = {0}; + if (readRegister(QMI8658_REG_AX_L, buffer, 6) != DEV_WIRE_ERR) { + rawBuffer[0] = (int16_t)(buffer[1] << 8) | (buffer[0]); + rawBuffer[1] = (int16_t)(buffer[3] << 8) | (buffer[2]); + rawBuffer[2] = (int16_t)(buffer[5] << 8) | (buffer[4]); + } else { + return false; + } + return true; + } + + bool getAccelerometer(float &x, float &y, float &z) + { + int16_t raw[3]; + if (getAccelRaw(raw)) { + x = raw[0] * accelScales; + y = raw[1] * accelScales; + z = raw[2] * accelScales; + return true; + } + return false; + } + + float getAccelerometerScales() + { + return accelScales; + } + + float getGyroscopeScales() + { + return gyroScales; + } + + bool getGyroRaw(int16_t *rawBuffer) + { + uint8_t buffer[6] = {0}; + if (readRegister(QMI8658_REG_GX_L, buffer, 6) != DEV_WIRE_ERR) { + rawBuffer[0] = (int16_t)(buffer[1] << 8) | (buffer[0]); + rawBuffer[1] = (int16_t)(buffer[3] << 8) | (buffer[2]); + rawBuffer[2] = (int16_t)(buffer[5] << 8) | (buffer[4]); + } else { + return false; + } + return true; + } + + int getGyroscope(float &x, float &y, float &z) + { + int16_t raw[3]; + if (getGyroRaw(raw)) { + x = raw[0] * gyroScales; + y = raw[1] * gyroScales; + z = raw[2] * gyroScales; + return true; + } + return false; + } + + bool getDataReady() + { + switch (sampleMode) { + case SYNC_MODE: + return getRegisterBit(QMI8658_REG_STATUSINT, 1); + case ASYNC_MODE: + //TODO: When Accel and Gyro are configured with different rates, this will always be false + if (gyroEn && accelEn) { + return readRegister(QMI8658_REG_STATUS0) & 0x03; + } else if (gyroEn) { + return readRegister(QMI8658_REG_STATUS0) & 0x02; + } else if (accelEn) { + return readRegister(QMI8658_REG_STATUS0) & 0x01; + } + break; + default: + break; + } + return false; + } + + int enableSyncSampleMode() + { + sampleMode = SYNC_MODE; + return setRegisterBit(QMI8658_REG_CTRL7, 7); + } + + int disableSyncSampleMode() + { + sampleMode = ASYNC_MODE; + return clrRegisterBit(QMI8658_REG_CTRL7, 7); + } + + int enableLockingMechanism() + { + enableSyncSampleMode(); + if (writeRegister(QMI8658_REG_CAL1_L, 0x01) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + return writeCommand(CTRL_CMD_AHB_CLOCK_GATING); + + } + + int disableLockingMechanism() + { + disableSyncSampleMode(); + if (writeRegister(QMI8658_REG_CAL1_L, 0x00) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + return writeCommand(CTRL_CMD_AHB_CLOCK_GATING); + } + + + void dumpCtrlRegister() + { + uint8_t buffer[9]; + readRegister(QMI8658_REG_CTRL1, buffer, 9); + for (int i = 0; i < 9; ++i) { +#if defined(ARDUINO) + Serial.printf("CTRL%d: REG:0x%02X HEX:0x%02X ", i + 1, QMI8658_REG_CTRL1 + i, buffer[i]); +#else + printf("CTRL%d: 0x%02x", i + 1, buffer[i]); +#endif +#if defined(ARDUINO) + Serial.print(" BIN:0b"); + Serial.println(buffer[i], BIN); +#else + LOG("\n"); +#endif + } +#if defined(ARDUINO) + Serial.println(); +#else + printf("\n"); +#endif + + buffer[0] = readRegister(QMI8658_REG_FIFOCTRL); +#if defined(ARDUINO) + Serial.printf("FIFOCTRL: REG:0x%02X HEX:0x%02X ", QMI8658_REG_FIFOCTRL, buffer[0]); + Serial.print(" BIN:0b"); + Serial.println(buffer[0], BIN); +#else + printf("FIFOCTRL: REG:0x%02X HEX:0x%02X \n", QMI8658_REG_FIFOCTRL, buffer[0]); +#endif + + } + + void powerDown() + { + disableAccelerometer(); + disableGyroscope(); + setRegisterBit(QMI8658_REG_CTRL1, 1); + } + + void powerOn() + { + clrRegisterBit(QMI8658_REG_CTRL1, 1); + } + + int getStatusRegister() + { + return readRegister(QMI8658_REG_STATUS1); + } + + int configActivityInterruptMap(IntPin pin) + { + return pin == IntPin1 ? setRegisterBit(QMI8658_REG_CTRL8, 6) + : clrRegisterBit(QMI8658_REG_CTRL8, 6); + } + + /** + * @brief configPedometer + * @note The calculation of the Pedometer Detection is based on the accelerometer ODR defined by CTRL2.aODR, + * refer to Table 22 for details. + * @param ped_sample_cnt: Indicates the count of sample batch/window for calculation + * @param ped_fix_peak2peak:Indicates the threshold of the valid peak-to-peak detection + * E.g., 0x00CC means 200mg + * @param ped_fix_peak:Indicates the threshold of the peak detection comparing to average + * E.g., 0x0066 means 100mg + * @param ped_time_up:Indicates the maximum duration (timeout window) for a step. + * Reset counting calculation if no peaks detected within this duration. + * E.g., 80 means 1.6s @ ODR = 50Hz + * @param ped_time_low:Indicates the minimum duration for a step. + * The peaks detected within this duration (quiet time) is ignored. + * E.g., 12 means 0.25s @ ODR = 50Hz + * @param ped_time_cnt_entry:Indicates the minimum continuous steps to start the valid step counting. + * If the continuously detected steps is lower than this count and timeout, + * the steps will not be take into account; + * if yes, the detected steps will all be taken into account and + * counting is started to count every following step before timeout. + * This is useful to screen out the fake steps detected by non-step vibrations + * The timeout duration is defined by ped_time_up. + * E.g., 10 means 10 steps entry count + * @param ped_fix_precision:0 is recommended + * @param ped_sig_count: The amount of steps when to update the pedometer output registers. + * E.g., ped_sig_count = 4, every 4 valid steps is detected, update the registers once (added by 4). + * @retval + */ + int configPedometer(uint16_t ped_sample_cnt, uint16_t ped_fix_peak2peak, uint16_t ped_fix_peak, + uint16_t ped_time_up, uint8_t ped_time_low = 0x14, uint8_t ped_time_cnt_entry = 0x0A, uint8_t ped_fix_precision = 0x00, + uint8_t ped_sig_count = 0x04) + { + // The Pedometer can only work in Non-SyncSample mode + disableSyncSampleMode(); + + bool enGyro = isEnableGyroscope(); + bool enAccel = isEnableAccelerometer(); + + if (enGyro) { + disableGyroscope(); + } + + if (enAccel) { + disableAccelerometer(); + } + + writeRegister(QMI8658_REG_CAL1_L, ped_sample_cnt & 0xFF); + writeRegister(QMI8658_REG_CAL1_H, (ped_sample_cnt >> 8) & 0xFF); + writeRegister(QMI8658_REG_CAL2_L, ped_fix_peak2peak & 0xFF); + writeRegister(QMI8658_REG_CAL2_H, (ped_fix_peak2peak >> 8) & 0xFF); + writeRegister(QMI8658_REG_CAL3_L, ped_fix_peak & 0xFF); + writeRegister(QMI8658_REG_CAL3_H, (ped_fix_peak >> 8) & 0xFF); + writeRegister(QMI8658_REG_CAL4_H, 0x01); + writeRegister(QMI8658_REG_CAL4_L, 0x02); + + writeCommand(CTRL_CMD_CONFIGURE_PEDOMETER); + + writeRegister(QMI8658_REG_CAL1_L, ped_time_up & 0xFF); + writeRegister(QMI8658_REG_CAL1_H, (ped_time_up >> 8) & 0xFF); + writeRegister(QMI8658_REG_CAL2_L, ped_time_low); + writeRegister(QMI8658_REG_CAL2_H, ped_time_cnt_entry); + writeRegister(QMI8658_REG_CAL3_L, ped_fix_precision); + writeRegister(QMI8658_REG_CAL3_H, ped_sig_count); + writeRegister(QMI8658_REG_CAL4_H, 0x02); + writeRegister(QMI8658_REG_CAL4_L, 0x02); + + writeCommand(CTRL_CMD_CONFIGURE_PEDOMETER); + + if (enGyro) { + enableGyroscope(); + } + + if (enAccel) { + enableAccelerometer(); + } + return 0; + } + + uint32_t getPedometerCounter() + { + uint8_t buffer[3]; + if (readRegister(QMI8658_REG_PEDO_L, buffer, 3) != DEV_WIRE_ERR) { + return (uint32_t)(((uint32_t)buffer[2] << 16) | ((uint32_t)buffer[1] << 8) | buffer[0]); + } + return 0; + } + + int clearPedometerCounter() + { + return writeCommand(CTRL_CMD_RESET_PEDOMETER); + } + + // The Pedometer can only work in Non-SyncSample mode + int enablePedometer() + { + return setRegisterBit(QMI8658_REG_CTRL8, 4); + } + + int disablePedometer() + { + return clrRegisterBit(QMI8658_REG_CTRL8, 4); + } + + enum TagPriority { + PRIORITY0, // (X > Y> Z) + PRIORITY1, // (X > Z > Y) + PRIORITY2, // (Y > X > Z) + PRIORITY3, // (Y > Z > X) + PRIORITY4, // (Z > X > Y) + PRIORITY5, // (Z > Y > X) + }; + + /** + * @brief configTap + * @note The calculation of the Tap Detection is based on the accelerometer ODR defined by CTRL2.aODR, refer to Table 22 for details. + * @param priority: Priority definition between the x, y, z axes of acceleration. Only + Priority[2:0] bits are used. + The axis that output the first peak of Linear Acceleration in a valid + Tap detection, will be consider as the Tap axis. However, there is + possibility that two or three of the axes shows same Linear + Acceleration at exactly same time when reach (or be higher than) + the PeakMagThr. In this case, the defined priority is used to judge + and select the axis as Tap axis. + * @param peakWindow:Defines the maximum duration (in sample) for a valid peak. In a + valid peak, the linear acceleration should reach or be higher than + the PeakMagThr and should return to quiet (no significant + movement) within UDMThr, at the end of PeakWindow. + E.g., 20 @500Hz ODR + * @param tapWindow:Defines the minimum quiet time before the second Tap happen. + After the first Tap is detected, there should be no significant + movement (defined by UDMThr) during the TapWindow. The valid + second tap should be detected after TapWindow and before + DTapWindow. + E.g., 50 @500Hz ODR + * @param dTapWindow:Defines the maximum time for a valid second Tap for Double Tap, + count start from the first peak of the valid first Tap. + E.g., 250 @500Hz ODR + * @param alpha:Defines the ratio for calculation the average of the acceleration. + The bigger of Alpha, the bigger weight of the latest data. + E.g., 0.0625 + * @param gamma:Defines the ratio for calculating the average of the movement + magnitude. The bigger of Gamma, the bigger weight of the latest + data. + E.g., 0.25 + * @param peakMagThr:Threshold for peak detection. + E.g, 0.8g2 (0x0320) + * @param UDMThr:Undefined Motion threshold. This defines the threshold of the + Linear Acceleration for quiet status. + E.g., 0.4g2 (0x0190) + * @retval + */ + int configTap(uint8_t priority, uint8_t peakWindow, uint16_t tapWindow, uint16_t dTapWindow, + uint8_t alpha, uint8_t gamma, uint16_t peakMagThr, uint16_t UDMThr) + { + bool enGyro = isEnableGyroscope(); + bool enAccel = isEnableAccelerometer(); + + if (enGyro) { + disableGyroscope(); + } + + if (enAccel) { + disableAccelerometer(); + } + writeRegister(QMI8658_REG_CAL1_L, peakWindow); + writeRegister(QMI8658_REG_CAL1_H, priority); + writeRegister(QMI8658_REG_CAL2_L, tapWindow & 0xFF); + writeRegister(QMI8658_REG_CAL2_H, (tapWindow >> 8) & 0xFF); + writeRegister(QMI8658_REG_CAL3_L, dTapWindow & 0xFF); + writeRegister(QMI8658_REG_CAL3_H, (dTapWindow >> 8) & 0xFF); + // writeRegister(QMI8658_REG_CAL4_L, 0x02); + writeRegister(QMI8658_REG_CAL4_H, 0x01); + + writeCommand(CTRL_CMD_CONFIGURE_TAP); + + writeRegister(QMI8658_REG_CAL1_L, alpha); + writeRegister(QMI8658_REG_CAL1_H, gamma); + writeRegister(QMI8658_REG_CAL2_L, peakMagThr & 0xFF); + writeRegister(QMI8658_REG_CAL2_H, (peakMagThr >> 8) & 0xFF); + writeRegister(QMI8658_REG_CAL3_L, UDMThr & 0xFF); + writeRegister(QMI8658_REG_CAL3_H, (UDMThr >> 8) & 0xFF); + // writeRegister(QMI8658_REG_CAL4_L, 0x02); + writeRegister(QMI8658_REG_CAL4_H, 0x02); + + writeCommand(CTRL_CMD_CONFIGURE_TAP); + + if (enGyro) { + enableGyroscope(); + } + + if (enAccel) { + enableAccelerometer(); + } + + return 0; + } + + int enableTap() + { + return setRegisterBit(QMI8658_REG_CTRL8, 0); + } + + int disableTap() + { + return clrRegisterBit(QMI8658_REG_CTRL8, 0); + } + + void getTapStatus() + { + int val = readRegister(QMI8658_REG_TAP_STATUS); + if (val & _BV(7)) { + LOG("Tap was detected on the negative direction of the Tap axis\n"); + } else { + LOG("Tap was detected on the positive direction of the Tap axis\n"); + } + uint8_t t = (val >> 4) & 0x03; + switch (t) { + case 0: + LOG("No Tap was detected\n"); + break; + case 1: + LOG("Tap was detected on X axis\n"); + break; + case 2: + LOG("Tap was detected on Y axis\n"); + break; + case 3: + LOG("Tap was detected on Z axis\n"); + break; + + default: + break; + } + t = val & 0x03; + switch (t) { + case 0: + LOG("No Tap was detected\n"); + break; + case 1: + LOG("Single-Tap was detected\n"); + break; + case 2: + LOG("Double-Tap was detected\n"); + break; + default: + break; + } + LOG("\n\n\n"); + } + + + /** + * @brief + * @note + * @param AnyMotionXThr: + * @param AnyMotionYThr: + * @param AnyMotionZThr: + * @param NoMotionXThr: + * @param NoMotionYThr: + * @param NoMotionZThr: + * @param modeCtrl: + * @param AnyMotionWindow: + * @param NoMotionWindow: + * @param SigMotionWaitWindow: + * @param SigMotionConfirmWindow: + * @retval + */ + int configMotion(uint8_t AnyMotionXThr, uint8_t AnyMotionYThr, uint8_t AnyMotionZThr, + uint8_t NoMotionXThr, uint8_t NoMotionYThr, uint8_t NoMotionZThr, uint8_t modeCtrl, + uint8_t AnyMotionWindow, uint8_t NoMotionWindow, + uint16_t SigMotionWaitWindow, uint16_t SigMotionConfirmWindow) + { + bool enGyro = isEnableGyroscope(); + bool enAccel = isEnableAccelerometer(); + + if (enGyro) { + disableGyroscope(); + } + + if (enAccel) { + disableAccelerometer(); + } + writeRegister(QMI8658_REG_CAL1_L, AnyMotionXThr); + writeRegister(QMI8658_REG_CAL1_H, AnyMotionYThr); + writeRegister(QMI8658_REG_CAL2_L, AnyMotionZThr); + writeRegister(QMI8658_REG_CAL2_H, NoMotionXThr); + writeRegister(QMI8658_REG_CAL3_L, NoMotionYThr); + writeRegister(QMI8658_REG_CAL3_H, NoMotionZThr); + writeRegister(QMI8658_REG_CAL4_L, modeCtrl); + writeRegister(QMI8658_REG_CAL4_H, 0x01); + + writeCommand(CTRL_CMD_CONFIGURE_MOTION); + + writeRegister(QMI8658_REG_CAL1_L, AnyMotionWindow); + writeRegister(QMI8658_REG_CAL1_H, NoMotionWindow); + writeRegister(QMI8658_REG_CAL2_L, SigMotionWaitWindow & 0xFF); + writeRegister(QMI8658_REG_CAL2_H, (SigMotionWaitWindow >> 8) & 0xFF); + writeRegister(QMI8658_REG_CAL3_L, SigMotionConfirmWindow & 0xFF); + writeRegister(QMI8658_REG_CAL3_H, (SigMotionConfirmWindow >> 8) & 0xFF); + // writeRegister(QMI8658_REG_CAL4_L, 0x02); + writeRegister(QMI8658_REG_CAL4_H, 0x02); + + writeCommand(CTRL_CMD_CONFIGURE_MOTION); + + if (enGyro) { + enableGyroscope(); + } + + if (enAccel) { + enableAccelerometer(); + } + return 0; + } + + int enableMotionDetect() + { + setRegisterBit(QMI8658_REG_CTRL8, 1); + setRegisterBit(QMI8658_REG_CTRL8, 3); + return setRegisterBit(QMI8658_REG_CTRL8, 2); + } + + int disableMotionDetect() + { + return clrRegisterBit(QMI8658_REG_CTRL8, 2); + } + + + /** + * @brief configWakeOnMotion + * @note Configuring Wom will reset the sensor, set the function to Wom, and there will be no data output + * @param WoMThreshold: Resolution = 1mg ,default 200g + * @param odr: Accelerometer output data rate ,defalut low power 128Hz + * @param pin: Interrupt Pin( 1 or 2 ) ,defalut use pin2 + * @param defaultPinValue: WoM Interrupt Initial Value select: ,default pin high + * 01 – INT2 (with initial value 0) + * 11 – INT2 (with initial value 1) + * 00 – INT1 (with initial value 0) + * 10 – INT1 (with initial value 1) + * @param blankingTime: Interrupt Blanking Time + * (in number of accelerometer samples), the + * number of consecutive samples that will be ignored after + * enabling the WoM, to screen out unwanted fake detection + * @retval + */ + int configWakeOnMotion(uint8_t WoMThreshold = 200, + AccelODR odr = ACC_ODR_LOWPOWER_128Hz, + IntPin pin = IntPin2, + uint8_t defaultPinValue = 1, + uint8_t blankingTime = 0x20 + ) + { + + uint8_t val = 0; + + //Reset default value + if (!reset()) { + return DEV_WIRE_ERR; + } + + // Disable sensors + clrRegisterBit(QMI8658_REG_CTRL7, 0); + + //setAccelRange + if (writeRegister(QMI8658_REG_CTRL2, 0x8F, (ACC_RANGE_8G << 4)) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + // setAccelOutputDataRate + if (writeRegister(QMI8658_REG_CTRL2, 0xF0, odr) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + //set wom + if (writeRegister(QMI8658_REG_CAL1_L, WoMThreshold) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + if ( pin == IntPin1) { + val = defaultPinValue ? 0x02 : 0x00; + } else if (pin == IntPin2) { + val = defaultPinValue ? 0x03 : 0x01; + } + + val <<= 6; + val |= (blankingTime & 0x3F); + if (writeRegister(QMI8658_REG_CAL1_H, val) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + if (writeCommand(CTRL_CMD_WRITE_WOM_SETTING) != DEV_WIRE_NONE) { + return DEV_WIRE_ERR; + } + + enableAccelerometer(); + + enableINT(pin); + + return DEV_WIRE_NONE; + } + + + + void getChipUsid(uint8_t *buffer, uint8_t lenght) + { + if (lenght > 6) { + lenght = 6; + } + memcpy(buffer, usid, lenght); + } + + + uint32_t getChipFirmwareVersion() + { + return revisionID; + } + + enum SensorStatus { + STATUS_INT_CTRL9_CMD_DONE = _BV(0), + STATUS_INT_LOCKED = _BV(1), + STATUS_INT_AVAIL = _BV(2), + STATUS0_GDATA_REDAY = _BV(3), + STATUS0_ADATA_REDAY = _BV(4), + STATUS1_SIGNI_MOTION = _BV(5), + STATUS1_NO_MOTION = _BV(6), + STATUS1_ANY_MOTION = _BV(7), + STATUS1_PEDOME_MOTION = _BV(8), + STATUS1_WOM_MOTION = _BV(9), + STATUS1_TAP_MOTION = _BV(10), + }; + + /** + * @brief readSensorStatus + * @note Get the interrupt status and status 0, status 1 of the sensor + * @retval Return SensorStatus + */ + uint16_t readSensorStatus() + { + uint16_t result = 0; + // STATUSINT 0x2D + // STATUS0 0x2E + // STATUS1 0x2F + uint8_t status[3]; + if (readRegister(QMI8658_REG_STATUSINT, status, 3) != DEV_WIRE_NONE) { + return 0; + } + + // LOG("STATUSINT:0x%X BIN:", status[0]); + // LOG_BIN(status[0]); + // LOG("STATUS0:0x%X BIN:", status[1]); + // LOG_BIN(status[1]); + // LOG("STATUS1:0x%X BIN:", status[2]); + // LOG_BIN(status[2]); + // LOG("------------------\n"); + + // Ctrl9 CmdDone + // Indicates CTRL9 Command was done, as part of CTRL9 protocol + // 0: Not Completed + // 1: Done + if (status[0] & 0x80) { + result |= STATUS_INT_CTRL9_CMD_DONE; + } + // If syncSmpl (CTRL7.bit7) = 1: + // 0: Sensor Data is not locked. + // 1: Sensor Data is locked. + // If syncSmpl = 0, this bit shows the same value of INT1 level + if (status[0] & 0x02) { + result |= STATUS_INT_LOCKED; + } + // If syncSmpl (CTRL7.bit7) = 1: + // 0: Sensor Data is not available + // 1: Sensor Data is available for reading + // If syncSmpl = 0, this bit shows the same value of INT2 level + if (status[0] & 0x01) { + result |= STATUS_INT_AVAIL; + // if (eventGyroDataReady)eventGyroDataReady(); + // if (eventAccelDataReady)eventAccelDataReady(); + } + + //Locking Mechanism Can reading.. + if ((status[0] & 0x03) == 0x03) { + if (eventDataLocking)eventDataLocking(); + } + + //======================================= + // Valid only in asynchronous mode + if (sampleMode == ASYNC_MODE) { + // Gyroscope new data available + // 0: No updates since last read. + // 1: New data available + if (status[1] & 0x02) { + result |= STATUS0_GDATA_REDAY; + if (eventGyroDataReady)eventGyroDataReady(); + __gDataReady = true; + } + // Accelerometer new data available + // 0: No updates since last read. + // 1: New data available. + if (status[1] & 0x01) { + result |= STATUS0_ADATA_REDAY; + if (eventAccelDataReady)eventAccelDataReady(); + __aDataReady = true; + } + } + + //======================================= + // Significant Motion + // 0: No Significant-Motion was detected + // 1: Significant-Motion was detected + if (status[2] & 0x80) { + result |= STATUS1_SIGNI_MOTION; + if (eventSignificantMotion)eventSignificantMotion(); + } + // No Motion + // 0: No No-Motion was detected + // 1: No-Motion was detected + if (status[2] & 0x40) { + result |= STATUS1_NO_MOTION; + if (eventNoMotionEvent)eventNoMotionEvent(); + } + // Any Motion + // 0: No Any-Motion was detected + // 1: Any-Motion was detected + if (status[2] & 0x20) { + result |= STATUS1_ANY_MOTION; + if (eventAnyMotionEvent)eventAnyMotionEvent(); + } + // Pedometer + // 0: No step was detected + // 1: step was detected + if (status[2] & 0x10) { + result |= STATUS1_PEDOME_MOTION; + if (eventPedometerEvent)eventPedometerEvent(); + } + // WoM + // 0: No WoM was detected + // 1: WoM was detected + if (status[2] & 0x04) { + result |= STATUS1_WOM_MOTION; + if (eventWomEvent)eventWomEvent(); + } + // TAP + // 0: No Tap was detected + // 1: Tap was detected + if (status[2] & 0x02) { + result |= STATUS1_TAP_MOTION; + if (eventTagEvent)eventTagEvent(); + } + return result; + } + + void setWakeupMotionEventCallBack(EventCallBack_t cb) + { + eventWomEvent = cb; + } + + void setTapEventCallBack(EventCallBack_t cb) + { + eventTagEvent = cb; + } + + void setPedometerEventCallBack(EventCallBack_t cb) + { + eventPedometerEvent = cb; + } + + void setNoMotionEventCallBack(EventCallBack_t cb) + { + eventNoMotionEvent = cb; + } + + void setAnyMotionEventCallBack(EventCallBack_t cb) + { + eventAnyMotionEvent = cb; + } + + void setSignificantMotionEventCallBack(EventCallBack_t cb) + { + eventSignificantMotion = cb; + } + + void setGyroDataReadyCallBack(EventCallBack_t cb) + { + eventGyroDataReady = cb; + } + + void setAccelDataReadyEventCallBack(EventCallBack_t cb) + { + eventAccelDataReady = cb; + } + + void setDataLockingEvevntCallBack(EventCallBack_t cb) + { + eventDataLocking = cb; + } + +private: + float accelScales, gyroScales; + uint32_t lastTimestamp = 0; + uint8_t sampleMode = ASYNC_MODE; + bool accelEn, gyroEn; + uint8_t fifoMode; + uint32_t revisionID; + uint8_t usid[6]; + bool __gDataReady = false; + bool __aDataReady = false; + + EventCallBack_t eventWomEvent = NULL; + EventCallBack_t eventTagEvent = NULL; + EventCallBack_t eventPedometerEvent = NULL; + EventCallBack_t eventNoMotionEvent = NULL; + EventCallBack_t eventAnyMotionEvent = NULL; + EventCallBack_t eventSignificantMotion = NULL; + EventCallBack_t eventGyroDataReady = NULL; + EventCallBack_t eventAccelDataReady = NULL; + EventCallBack_t eventDataLocking = NULL; + + + int writeCommand(CommandTable cmd) + { + int val; + uint32_t startMillis; + if (writeRegister(QMI8658_REG_CTRL9, cmd) == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + startMillis = millis(); + do { + val = readRegister(QMI8658_REG_STATUSINT); + delay(1); + if (millis() - startMillis > 1000) { + LOG("wait for ctrl9 command done time out : %d val:%d \n", cmd, val); + return DEV_WIRE_TIMEOUT; + } + } while (val != DEV_WIRE_ERR && !(val & 0x80)); + + if (writeRegister(QMI8658_REG_CTRL9, CTRL_CMD_ACK) == DEV_WIRE_ERR) { + return DEV_WIRE_ERR; + } + + startMillis = millis(); + do { + val = readRegister(QMI8658_REG_STATUSINT); + delay(1); + if (millis() - startMillis > 1000) { + LOG("Clear ctrl9 command done flag timeout : %d val:%d \n", cmd, val); + return DEV_WIRE_TIMEOUT; + } + } while (val != DEV_WIRE_ERR && (val & 0x80)); + + return DEV_WIRE_NONE; + } + +protected: + + bool initImpl() + { + uint8_t buffer[6] = {0}; + + if (!reset()) { + return false; + } + + uint8_t id = whoAmI(); + if (id != QMI8658_REG_WHOAMI_DEFAULT) { + LOG("ERROR! ID NOT MATCH QMI8658 , Respone id is 0x%x\n", id); + return false; + } + // Eanble address auto increment, Big-Endian format + // writeRegister(QMI8658_REG_CTRL1, 0x60); + + // Little-Endian / address auto increment + // writeRegister(QMI8658_REG_CTRL1, 0x40); + + // no need . reset function has set + //EN.ADDR_AI + // setRegisterBit(QMI8658_REG_CTRL1, 6); + + + // Use STATUSINT.bit7 as CTRL9 handshake + writeRegister(QMI8658_REG_CTRL8, 0x80); + + // Get firmware version and usid + writeCommand(CTRL_CMD_COPY_USID); + + if (readRegister(QMI8658_REG_DQW_L, buffer, 3) != DEV_WIRE_ERR) { + revisionID = buffer[0] | (uint32_t)(buffer[1] << 8) | + (uint32_t)(buffer[2] << 16); + LOG("FW Version :0x%02X%02X%02X\n", buffer[0], buffer[1], buffer[2]); + } + + if (readRegister(QMI8658_REG_DVX_L, usid, 6) != DEV_WIRE_ERR) { + LOG("USID :%02X%02X%02X%02X%02X%02X\n", + usid[0], usid[1], usid[2], + usid[3], usid[4], usid[5]); + } + + return true; + } + + int getReadMaskImpl() + { + return 0x80; + } + +}; + + + + + + + + diff --git a/lib/SensorLib/src/SensorRTC.h b/lib/SensorLib/src/SensorRTC.h new file mode 100644 index 0000000..915748e --- /dev/null +++ b/lib/SensorLib/src/SensorRTC.h @@ -0,0 +1,344 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file SensorRTC.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-07 + * + */ +#pragma once + +#ifdef ARDUINO +#include +#else +#include +#endif /*defined(ARDUINO)*/ + +#include + +#define RTC_DAYS_IN_JANUARY (31u) +#define RTC_DAYS_IN_FEBRUARY (28u) +#define RTC_DAYS_IN_MARCH (31u) +#define RTC_DAYS_IN_APRIL (30u) +#define RTC_DAYS_IN_MAY (31u) +#define RTC_DAYS_IN_JUNE (30u) +#define RTC_DAYS_IN_JULY (31u) +#define RTC_DAYS_IN_AUGUST (31u) +#define RTC_DAYS_IN_SEPTEMBER (30u) +#define RTC_DAYS_IN_OCTOBER (31u) +#define RTC_DAYS_IN_NOVEMBER (30u) +#define RTC_DAYS_IN_DECEMBER (31u) + +enum { + DATETIME_FORMAT_HM, + DATETIME_FORMAT_HMS, + DATETIME_FORMAT_YYYY_MM_DD, + DATETIME_FORMAT_MM_DD_YYYY, + DATETIME_FORMAT_DD_MM_YYYY, + DATETIME_FORMAT_YYYY_MM_DD_H_M_S, + DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK, +}; + + + +class RTC_DateTime +{ +public: + RTC_DateTime() : year(0), month(0), day(0), hour(0), minute(0), second(0), week(0), available(false) {} + RTC_DateTime(const char *date, const char *time) + { + // sample input: date = "Dec 26 2009", time = "12:34:56" + year = 2000 + StringToUint8(date + 9); + // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + switch (date[0]) { + case 'J': + if ( date[1] == 'a' ) + month = 1; + else if ( date[2] == 'n' ) + month = 6; + else + month = 7; + break; + case 'F': + month = 2; + break; + case 'A': + month = date[1] == 'p' ? 4 : 8; + break; + case 'M': + month = date[2] == 'r' ? 3 : 5; + break; + case 'S': + month = 9; + break; + case 'O': + month = 10; + break; + case 'N': + month = 11; + break; + case 'D': + month = 12; + break; + } + day = StringToUint8(date + 4); + hour = StringToUint8(time); + minute = StringToUint8(time + 3); + second = StringToUint8(time + 6); + } + RTC_DateTime(uint16_t year, + uint8_t month, + uint8_t day, + uint8_t hour, + uint8_t minute, + uint8_t second + ) + { + this->year = year; + this->month = month; + this->day = day; + this->hour = hour; + this->minute = minute; + this->second = second; + this->week = week; + }; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t week; + char AMPM; + bool available; + bool operator==(RTC_DateTime d) + { + return ((d.year == year) && + (d.month == month) && + (d.day == day) && + (d.hour == hour) && + (d.minute == minute)); + } +private: + uint8_t StringToUint8(const char *pString) + { + uint8_t value = 0; + + // skip leading 0 and spaces + while ('0' == *pString || *pString == ' ') { + pString++; + } + + // calculate number until we hit non-numeral char + while ('0' <= *pString && *pString <= '9') { + value *= 10; + value += *pString - '0'; + pString++; + } + return value; + } +}; + +class RTC_Alarm +{ +public: + RTC_Alarm(void): second(0), minute(0), hour(0), day(0), week(0) {} + RTC_Alarm( + uint8_t hour, + uint8_t minute, + uint8_t second, + uint8_t day, + uint8_t week + ): second(second), minute(minute), hour(hour), day(day), week(week) + { + } + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day; + uint8_t week; +}; + +template +class RTCCommon +{ +public: + const char *strftime(uint8_t sytle = DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK) + { + const char *weekString[] = {"Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"}; + static char format[64]; + RTC_DateTime t = thisChip().getDateTime(); + switch (sytle) { + case DATETIME_FORMAT_HM: + snprintf(format, sizeof(format), "%02d:%02d", t.hour, t.minute); + break; + case DATETIME_FORMAT_HMS: + snprintf(format, sizeof(format), "%02d:%02d:%02d", t.hour, t.minute, t.second); + break; + case DATETIME_FORMAT_YYYY_MM_DD: + snprintf(format, sizeof(format), "%d-%02d-%02d", t.year, t.month, t.day); + break; + case DATETIME_FORMAT_MM_DD_YYYY: + snprintf(format, sizeof(format), "%02d-%02d-%d", t.month, t.day, t.year); + break; + case DATETIME_FORMAT_DD_MM_YYYY: + snprintf(format, sizeof(format), "%02d-%02d-%d", t.day, t.month, t.year); + break; + case DATETIME_FORMAT_YYYY_MM_DD_H_M_S: + snprintf(format, sizeof(format), "%d-%02d-%02d/%02d:%02d:%02d", t.year, t.month, t.day, t.hour, t.minute, t.second); + break; + case DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK: + snprintf(format, sizeof(format), "%d-%02d-%02d/%02d:%02d:%02d - %s", t.year, t.month, t.day, t.hour, t.minute, t.second, weekString[t.week > 6 ? 0 : t.week]); + break; + default: + snprintf(format, sizeof(format), "%02d:%02d", t.hour, t.minute); + break; + } + return format; + } + + struct tm conversionUnixTime(RTC_DateTime datetime) + { + struct tm t_tm; + t_tm.tm_hour = datetime.hour; + t_tm.tm_min = datetime.minute; + t_tm.tm_sec = datetime.second; + t_tm.tm_year = datetime.year - 1900; //Year, whose value starts from 1900 + t_tm.tm_mon = datetime.month - 1; //Month (starting from January, 0 for January) - Value range is [0,11] + t_tm.tm_mday = datetime.day; + t_tm.tm_wday = datetime.week; + return t_tm; + } + + time_t hwClockRead() + { + struct tm t_tm = conversionUnixTime(thisChip().getDateTime()); + struct timeval val; + val.tv_sec = mktime(&t_tm); + val.tv_usec = 0; +#if __BSD_VISIBLE + settimeofday(&val, NULL); +#endif /*__BSD_VISIBLE*/ + return val.tv_sec; + } + + void hwClockWrite() + { + time_t now; + struct tm info; + time(&now); + localtime_r(&now, &info); + thisChip().setDateTime(info.tm_year + 1900, + info.tm_mon + 1, + info.tm_mday, + info.tm_hour, + info.tm_min, + info.tm_sec); + } + + uint32_t getDayOfWeek(uint32_t day, uint32_t month, uint32_t year) + { + uint32_t val; + if (month < 3) { + month = 12u + month; + year--; + } + val = (day + (((month + 1u) * 26u) / 10u) + year + (year / 4u) + (6u * (year / 100u)) + (year / 400u)) % 7u; + if (0u == val) { + val = 7; + } + return (val - 1); + } + + uint8_t getNextMonth(uint8_t curMonth) + { + return ((curMonth < 12u) ? (curMonth + 1u) : 1u); + } + + uint16_t getNextYear(uint16_t curYear) + { + return (curYear + 1u); + } + + uint32_t getLeapYear(uint32_t year) + { + uint32_t val; + if (((0u == (year % 4Lu)) && (0u != (year % 100Lu))) || (0u == (year % 400Lu))) { + val = 1uL; + } else { + val = 0uL; + } + return val; + } + + uint8_t getDaysInMonth(uint8_t month, uint16_t year) + { + const uint8_t daysInMonthTable[12] = {RTC_DAYS_IN_JANUARY, + RTC_DAYS_IN_FEBRUARY, + RTC_DAYS_IN_MARCH, + RTC_DAYS_IN_APRIL, + RTC_DAYS_IN_MAY, + RTC_DAYS_IN_JUNE, + RTC_DAYS_IN_JULY, + RTC_DAYS_IN_AUGUST, + RTC_DAYS_IN_SEPTEMBER, + RTC_DAYS_IN_OCTOBER, + RTC_DAYS_IN_NOVEMBER, + RTC_DAYS_IN_DECEMBER + }; + + uint8_t val; + val = daysInMonthTable[month - 1u]; + if (2 == month) { + if (0u != getLeapYear(year)) { + val++; + } + } + return val; + } + + uint8_t BCD2DEC(uint8_t val) + { + return ((val / 16 * 10) + (val % 16)); + } + uint8_t DEC2BCD(uint8_t val) + { + return ((val / 10 * 16) + (val % 10)); + } + + /* + * CRTP Helper + */ +protected: + inline const chipType &thisChip() const + { + return static_cast(*this); + } + + inline chipType &thisChip() + { + return static_cast(*this); + } + +}; \ No newline at end of file diff --git a/lib/SensorLib/src/SensorWireHelper.cpp b/lib/SensorLib/src/SensorWireHelper.cpp new file mode 100644 index 0000000..5983ac1 --- /dev/null +++ b/lib/SensorLib/src/SensorWireHelper.cpp @@ -0,0 +1,123 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file SensorWireHelper.cpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-05 + * + */ +#include "SensorWireHelper.h" + +#if defined(ARDUINO) + + + +int SensorWireHelper::regdump(TwoWire &w, Stream &serial, uint8_t devAddr, uint8_t start, uint8_t length) +{ + uint8_t *buffer = (uint8_t *)malloc(length); + if (!buffer) return -1; + w.begin(); + w.beginTransmission(devAddr); + w.write(start); + if (w.endTransmission() != 0) { + free(buffer); + return -1; + } + size_t len = w.requestFrom(devAddr, length); + if (length != len) { + free(buffer); + return -1; + } + w.readBytes(buffer, length); + hexdump(buffer, length, serial); + free(buffer); + return 0; +} + + + +void SensorWireHelper::dumpDevices(TwoWire &w, Stream &serial, int first, int last) +{ + int i, j; + int ret; + serial.printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); + for (i = 0; i < 128; i += 16) { + serial.printf("%02x: ", i); + + for (j = 0; j < 16; j++) { + /* Skip unwanted addresses */ + if (i + j < first || i + j > last) { + serial.printf(" "); + continue; + } + + w.beginTransmission(i + j); + ret = w.endTransmission(); + + if (ret != 0) + serial.printf("-- "); + else + serial.printf("%02x ", i + j); + } + serial.printf("\n"); + } +} + + +void SensorWireHelper::hexdump(uint8_t *data, size_t len, Stream &serial) +{ + size_t rem_len = len; + for (size_t i = 0; i < len; i += 16) { + char str[80]; + snprintf(str, 80, "%07x ", i); + size_t line_len = 16; + if (rem_len < line_len) { + line_len = rem_len; + } + for (size_t j = 0; j < line_len; j++) { + snprintf(&str[8 + j * 3], 80, "%02x ", data[i + j]); + } + for (size_t j = line_len; j < 16; j++) { + snprintf(&str[8 + j * 3], 80, " "); + } + str[56] = '|'; + str[57] = ' '; + for (size_t j = 0; j < line_len; j++) { + char c = data[i + j]; + if ((c < ' ') || (c > '~')) { + c = '.'; + } + snprintf(&str[58 + j], 80, "%c", c); + } + for (size_t j = line_len; j < 16; j++) { + snprintf(&str[58 + j], 80, " "); + } + serial.println(str); + rem_len -= 16; + } +} + + + +#endif //ARDUINO diff --git a/lib/SensorLib/src/SensorWireHelper.h b/lib/SensorLib/src/SensorWireHelper.h new file mode 100644 index 0000000..bfd1131 --- /dev/null +++ b/lib/SensorLib/src/SensorWireHelper.h @@ -0,0 +1,46 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file SensorWireHelper.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-10 + * + */ +#pragma once + +#if defined(ARDUINO) +#include +#include + +class SensorWireHelper +{ +public: + static int regdump(TwoWire &w, Stream &serial, uint8_t devAddr, uint8_t start, uint8_t len); + static void dumpDevices(TwoWire &w, Stream &serial = Serial, int first = 0, int last = 127); + static void hexdump(uint8_t *data, size_t len, Stream &serial = Serial); +}; + +#endif /*ARDUINO*/ + + diff --git a/lib/SensorLib/src/TouchDrvCHSC5816.hpp b/lib/SensorLib/src/TouchDrvCHSC5816.hpp new file mode 100644 index 0000000..31efa43 --- /dev/null +++ b/lib/SensorLib/src/TouchDrvCHSC5816.hpp @@ -0,0 +1,312 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrvCHSC5816.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-12 + * + */ +#pragma once + +#include "REG/CHSC5816Constants.h" +#include "TouchDrvInterface.hpp" +#include "SensorCommon.tpp" + +typedef struct __CHSC5816_Header { + uint16_t fw_ver; + uint16_t checksum; + uint32_t sig; + uint32_t vid_pid; + uint16_t raw_offet; + uint16_t dif_offet; +} CHSC5816_Header_t; + +union __CHSC5816_PointReg { + struct { + uint8_t status; + uint8_t fingerNumber; + uint8_t x_l8; + uint8_t y_l8; + uint8_t z; + uint8_t x_h4: 4; + uint8_t y_h4: 4; + uint8_t id: 4; + uint8_t event: 4; + uint8_t p2; + } rp; + unsigned char data[8]; +}; + +class TouchDrvCHSC5816 : + public TouchDrvInterface, + public SensorCommon +{ + friend class SensorCommon; +public: + + +#if defined(ARDUINO) + TouchDrvCHSC5816(PLATFORM_WIRE_TYPE &w, + int sda = DEFAULT_SDA, + int scl = DEFAULT_SCL, + uint8_t addr = CHSC5816_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __rst = SENSOR_PIN_NONE; + __irq = SENSOR_PIN_NONE; + __addr = addr; + } +#endif + + TouchDrvCHSC5816() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __rst = SENSOR_PIN_NONE; + __irq = SENSOR_PIN_NONE; + __addr = CHSC5816_SLAVE_ADDRESS; + } + + ~TouchDrvCHSC5816() + { + // deinit(); + } + +#if defined(ARDUINO) + bool begin(PLATFORM_WIRE_TYPE &w, + uint8_t addr = CHSC5816_SLAVE_ADDRESS, + int sda = DEFAULT_SDA, + int scl = DEFAULT_SCL) + { + return SensorCommon::begin(w, addr, sda, scl); + } +#endif + +#if defined(ESP_PLATFORM) && !defined(ARDUINO) +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) + { + return SensorCommon::begin(i2c_dev_bus_handle, addr); + } +#else + bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) + { + return SensorCommon::begin(port_num, addr, sda, scl); + } +#endif //ESP_IDF_VERSION +#endif + + bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) + { + return SensorCommon::begin(addr, readRegCallback, writeRegCallback); + } + + void reset() + { + if (__rst != SENSOR_PIN_NONE) { + this->setGpioLevel(__rst, LOW); + delay(3); + this->setGpioLevel(__rst, HIGH); + delay(5); + } + } + + uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point = 1) + { + __CHSC5816_PointReg touch; + + // CHSC5816_REG_POINT + uint8_t write_buffer[] = {0x20, 0x00, 0x00, 0x2c}; + writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer), touch.data, 8); + if (touch.rp.status == 0xFF && touch.rp.fingerNumber == 0) { + return 0; + } + if (x_array) { + *x_array = (unsigned int)(touch.rp.x_h4 << 8) | touch.rp.x_l8; + } + if (y_array) { + *y_array = (unsigned int)(touch.rp.y_h4 << 8) | touch.rp.y_l8; + } + + updateXY(1, x_array, y_array); + + return 1; + } + + bool isPressed() + { + if (__irq != SENSOR_PIN_NONE) { + return this->getGpioLevel(__irq) == LOW; + } + return getPoint(NULL, NULL); + } + + const char *getModelName() + { + return "CHSC5816"; + } + + //2uA + void sleep() + { + uint8_t write_buffer[] = { + 0x20, 0x00, 0x00, 0x00, // CHSC5816_REG_CMD_BUFF + 0xF8, 0x16, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE9 + }; + writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer)); + } + + void wakeup() + { + reset(); + } + + void idle() + { + uint8_t write_buffer[] = { + 0x20, 0x00, 0x00, 0x00, // CHSC5816_REG_CMD_BUFF + 0x20, 0x16, 0x02, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE9 + }; + writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer)); + } + + uint8_t getSupportTouchPoint() + { + return 1; + } + + bool getResolution(int16_t *x, int16_t *y) + { + /* + uint8_t buffer[16] = { + 0xFC, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe9 + }; + writeRegister(CHSC5816_REG_CMD_BUFF, buffer, 16); + memset(buffer, 0, 16); + readRegister(CHSC5816_REG_CMD_BUFF, buffer, 16); + for (int i = 0; i < 16; ++i) { + Serial.print(buffer[i], HEX); + Serial.print(","); + } + Serial.println(); + return true; + */ + return false; + } + + void setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb) + { + SensorCommon::setGpioModeCallback(mode_cb); + SensorCommon::setGpioWriteCallback(write_cb); + SensorCommon::setGpioReadCallback(read_cb); + } + +private: + bool checkOnline() + { + CHSC5816_Header_t tmp; + memset(&tmp, 0, sizeof(CHSC5816_Header_t)); + memset(&__header, 0, sizeof(CHSC5816_Header_t)); + + // CHSC5816_REG_BOOT_STATE 0x20000018 + uint8_t write_buffer[] = {0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00}; + + if (writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer)) == DEV_WIRE_ERR) { + log_e("writeBuffer clean boot state failed!\n"); + return false; + } + + reset(); + + for (int i = 0; i < 10; ++i) { + delay(10); + // CHSC5816_REG_IMG_HEAD 0x20000014 + uint8_t write_buffer[] = {0x20, 0x00, 0x00, 0x14}; + if (writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer), + (uint8_t *)&__header, + sizeof(CHSC5816_Header_t)) == DEV_WIRE_ERR) { + printf("readRegister 1 failed!\n"); + return false; + } + + if (writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer), + (uint8_t *)&tmp, + sizeof(CHSC5816_Header_t)) == DEV_WIRE_ERR) { + printf("readRegister 2 failed!\n"); + return false; + } + + if (memcmp(&tmp, &__header, sizeof(CHSC5816_Header_t)) != 0 ) { + continue; + } + if (__header.sig == CHSC5816_SIG_VALUE) { + return true; + } + } + return false; + } + + bool initImpl() + { + + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, INPUT); + } + + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OUTPUT); + } + + reset(); + + if (checkOnline()) { + reset(); + return true; + } + + return false; + } + + int getReadMaskImpl() + { + return -1; + } + + +protected: + CHSC5816_Header_t __header; +}; + + + diff --git a/lib/SensorLib/src/TouchDrvCSTXXX.hpp b/lib/SensorLib/src/TouchDrvCSTXXX.hpp new file mode 100644 index 0000000..bb54164 --- /dev/null +++ b/lib/SensorLib/src/TouchDrvCSTXXX.hpp @@ -0,0 +1,295 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrvCSTXXX.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-24 + * @date last 2023-10-05 + * + */ +#pragma once + +#include "REG/CSTxxxConstants.h" +#include "touch/TouchClassCST226.h" +#include "touch/TouchClassCST816.h" +#include "SensorCommon.tpp" + +class TouchDrvCSTXXX : public TouchDrvInterface +{ +public: + TouchDrvCSTXXX(): drv(NULL) + { + } + + ~TouchDrvCSTXXX() + { + if (drv) { + delete drv; + drv = NULL; + } + } + +#if defined(ARDUINO) + bool begin(PLATFORM_WIRE_TYPE &wire, + uint8_t address, + int sda, + int scl + ) + { + if (!drv) { + drv = new TouchClassCST816(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(wire, address, sda, scl)) { + delete drv; + drv = NULL; + } + } + + if (!drv) { + drv = new TouchClassCST226(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(wire, address, sda, scl)) { + delete drv; + drv = NULL; + } + } + + return drv != NULL; + } +#elif defined(ESP_PLATFORM) +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) + { + if (!drv) { + drv = new TouchClassCST816(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(i2c_dev_bus_handle, addr)) { + delete drv; + drv = NULL; + } + } + + if (!drv) { + drv = new TouchClassCST226(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(i2c_dev_bus_handle, addr)) { + delete drv; + drv = NULL; + } + } + return drv != NULL; + } +#else + bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) + { + if (!drv) { + drv = new TouchClassCST816(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(port_num, addr, sda, scl)) { + delete drv; + drv = NULL; + } + } + + if (!drv) { + drv = new TouchClassCST226(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(port_num, addr, sda, scl)) { + delete drv; + drv = NULL; + } + } + return drv != NULL; + } +#endif //ESP_IDF_VERSION +#endif//ARDUINO + + + void setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb) + { + __set_gpio_level = write_cb; + __get_gpio_level = read_cb; + __set_gpio_mode = mode_cb; + } + + bool begin(uint8_t address, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) + { + if (!drv) { + drv = new TouchClassCST816(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(address, readRegCallback, writeRegCallback)) { + delete drv; + drv = NULL; + } + } + + if (!drv) { + drv = new TouchClassCST226(); + drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level); + drv->setPins(__rst, __irq); + if (!drv->begin(address, readRegCallback, writeRegCallback)) { + delete drv; + drv = NULL; + } + } + + return drv != NULL; + } + + + void reset() + { + if (!drv)return; + drv->reset(); + } + + uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point = 1) + { + if (!drv)return 0; + return drv->getPoint(x_array, y_array, get_point); + } + + bool isPressed() + { + if (!drv)return false; + return drv->isPressed(); + } + + const char *getModelName() + { + if (!drv)return "NULL"; + return drv->getModelName(); + } + + void sleep() + { + if (!drv)return; + drv->sleep(); + } + + void wakeup() + { + if (!drv)return; + drv->reset(); + } + + void idle() + { + if (!drv)return; + drv->idle(); + } + + uint8_t getSupportTouchPoint() + { + if (!drv)return 0; + return drv->getSupportTouchPoint(); + } + + bool getResolution(int16_t *x, int16_t *y) + { + if (!drv)return false; + return drv->getResolution(x, y); + } + + void setCenterButtonCoordinate(uint16_t x, uint16_t y) + { + if (!drv)return ; + const char *model = drv->getModelName(); + if (strncmp(model, "CST8", 3) == 0) { + TouchClassCST816 *pT = static_cast(drv); + pT->setCenterButtonCoordinate(x, y); + } + } + + void setHomeButtonCallback(home_button_callback_t callback, void *user_data = NULL) + { + if (!drv)return ; + const char *model = drv->getModelName(); + if (strncmp(model, "CST8", 3) == 0) { + TouchClassCST816 *pT = static_cast(drv); + pT->setHomeButtonCallback(callback, user_data); + // pT->setCenterButtonCoordinate(600, 120); // Only suitable for AMOLED 1.91 inch + + } if (strncmp(model, "CST2", 3) == 0) { + TouchClassCST226 *pT = static_cast(drv); + pT->setHomeButtonCallback(callback, user_data); + } + } + + void disableAutoSleep() + { + if (!drv)return ; + const char *model = drv->getModelName(); + if (strncmp(model, "CST8", 3) == 0) { + TouchClassCST816 *pT = static_cast(drv); + pT->disableAutoSleep(); + } + } + + void enableAutoSleep() + { + if (!drv)return ; + const char *model = drv->getModelName(); + if (strncmp(model, "CST8", 3) == 0) { + TouchClassCST816 *pT = static_cast(drv); + pT->enableAutoSleep(); + } + } + + void setSwapXY(bool swap) + { + if (!drv)return ; + drv->setSwapXY(swap); + } + + void setMirrorXY(bool mirrorX, bool mirrorY) + { + if (!drv)return ; + drv->setMirrorXY(mirrorX, mirrorY); + } + + void setMaxCoordinates(uint16_t x, uint16_t y) + { + if (!drv)return ; + drv->setMaxCoordinates(x, y); + } + +private: + gpio_write_fptr_t __set_gpio_level = NULL; + gpio_read_fptr_t __get_gpio_level = NULL; + gpio_mode_fptr_t __set_gpio_mode = NULL; + TouchDrvInterface *drv = NULL; +}; + + + diff --git a/lib/SensorLib/src/TouchDrvFT6X36.hpp b/lib/SensorLib/src/TouchDrvFT6X36.hpp new file mode 100644 index 0000000..e8fed40 --- /dev/null +++ b/lib/SensorLib/src/TouchDrvFT6X36.hpp @@ -0,0 +1,426 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrvFT6X36.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-01 + * + */ +#pragma once + +#include "REG/FT6X36Constants.h" +#include "TouchDrvInterface.hpp" +#include "SensorCommon.tpp" + +class TouchDrvFT6X36 : + public TouchDrvInterface, + public SensorCommon +{ + friend class SensorCommon; +public: + + + enum GesTrue { + NO_GESTURE, + MOVE_UP, + MOVE_LEFT, + MOVE_DOWN, + MOVE_RIGHT, + ZOOM_IN, + ZOOM_OUT, + } ; + + enum EventFlag { + EVENT_PUT_DOWN, + EVENT_PUT_UP, + EVENT_CONTACT, + EVENT_NONE, + } ; + + enum PowerMode { + PMODE_ACTIVE = 0, // ~4mA + PMODE_MONITOR = 1, // ~3mA + PMODE_DEEPSLEEP = 3, // ~100uA The reset pin must be pulled down to wake up + } ; + + EventFlag event; + +#if defined(ARDUINO) + TouchDrvFT6X36(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = FT6X36_SLAVE_ADDRESS) + { + __wire = &w; + __sda = sda; + __scl = scl; + __addr = addr; + } +#endif + + TouchDrvFT6X36() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __addr = FT6X36_SLAVE_ADDRESS; + } + + ~TouchDrvFT6X36() + { + deinit(); + } + +#if defined(ARDUINO) + + bool begin(PLATFORM_WIRE_TYPE &w, + uint8_t addr = FT6X36_SLAVE_ADDRESS, + int sda = DEFAULT_SDA, + int scl = DEFAULT_SCL) + { + return SensorCommon::begin(w, addr, sda, scl); + } + +#elif defined(ESP_PLATFORM) && !defined(ARDUINO) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) + { + return SensorCommon::begin(i2c_dev_bus_handle, addr); + } +#else + bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) + { + return SensorCommon::begin(port_num, addr, sda, scl); + } +#endif //ESP_IDF_VERSION + +#endif + + bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) + { + return SensorCommon::begin(addr, readRegCallback, writeRegCallback); + } + + + void deinit() + { + // end(); + } + + uint8_t getDeviceMode(void) + { + return readRegister(FT6X36_REG_MODE) & 0x03; + } + + // Obtaining gestures depends on whether the built-in firmware of the chip has this function + uint8_t getGesture() + { + int val = readRegister(FT6X36_REG_GEST); + switch (val) { + case 0x10: + return MOVE_UP; + case 0x14: + return MOVE_RIGHT; + case 0x18: + return MOVE_DOWN; + case 0x1C: + return MOVE_LEFT; + case 0x48: + return ZOOM_IN; + case 0x49: + return ZOOM_OUT; + default: + break; + } + return NO_GESTURE; + } + + void setThreshold(uint8_t value) + { + writeRegister(FT6X36_REG_THRESHOLD, value); + } + + uint8_t getThreshold(void) + { + return readRegister(FT6X36_REG_THRESHOLD); + } + + uint8_t getMonitorTime(void) + { + return readRegister(FT6X36_REG_MONITOR_TIME); + } + + void setMonitorTime(uint8_t sec) + { + writeRegister(FT6X36_REG_MONITOR_TIME, sec); + } + + // Calibration useless actually, + // any value set will not be valid, + // depending on the internal firmware of the chip. + /* + void enableAutoCalibration(void) + { + writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0x00); + } + + void disableAutoCalibration(void) + { + writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0xFF); + } + */ + + uint16_t getLibraryVersion() + { + uint8_t buffer[2]; + readRegister(FT6X36_REG_LIB_VERSION_H, buffer, 2); + return (buffer[0] << 8) | buffer[1]; + } + + // The interrupt is triggered only if a touch is detected during the scan cycle + void interruptPolling(void) + { + //datasheet this bit is 0,Actually, it's wrong + writeRegister(FT6X36_REG_INT_STATUS, 1); + } + + // Triggers an interrupt whenever a touch is detected + void interruptTrigger(void) + { + //datasheet this bit is 1,Actually, it's wrong + writeRegister(FT6X36_REG_INT_STATUS, 0); + } + + uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1) + { + uint8_t buffer[16]; + + if (!x_array || !y_array || !size) + return 0; + + if (readRegister(FT6X36_REG_MODE, buffer, 16) == DEV_WIRE_ERR) { + return 0; + } + + // uint8_t mode = buffer[0]; + //REG 0x01 + // uint8_t gesture = buffer[1]; + //REG 0x02 + uint8_t point = buffer[2] & 0x0F; + if (point == 0 || point == 0x0F) { + return 0; + } + + //REG 0x03 ~ 0x04 + // uint8_t eventFlag = (buffer[3] & 0xC0) >> 6; + uint16_t posX = ((buffer[3] & 0x0F) << 8) | buffer[4]; + //REG 0x05 ~ 0x06 + uint16_t posY = ((buffer[5] & 0x0F) << 8) | buffer[6] ; + + + x_array[0] = posX; + y_array[0] = posY; + +#ifdef LOG_PORT + LOG_PORT.println("----------------------------------------------------------------------------"); + LOG_PORT.println("Touched Gesture EvenFlag [0]PosX [0]PosY [1]PosX [1]PosY"); + LOG_PORT.print(point); LOG_PORT.print("\t"); + // LOG_PORT.print(gesture); LOG_PORT.print("\t"); + // LOG_PORT.print(eventFlag); LOG_PORT.print("\t"); + LOG_PORT.print(posX); LOG_PORT.print("\t"); + LOG_PORT.print(posY); LOG_PORT.print("\t"); +#endif + + if (point == 2) { + //REG 0x09 ~ 0x0A + posX = ((buffer[9] & 0x0F) << 8) | buffer[10]; + //REG 0x0B ~ 0x0C + posY = ((buffer[11] & 0x0F) << 8) | buffer[12] ; + +#ifdef LOG_PORT + LOG_PORT.print(posX); LOG_PORT.print("\t"); + LOG_PORT.print(posY); LOG_PORT.print("\t"); +#endif + + if (size == 2) { + x_array[1] = posX; + y_array[1] = posY; + } + } +#ifdef LOG_PORT + LOG_PORT.println(); +#endif + updateXY(point, x_array, y_array); + + return point; + } + + bool isPressed() + { + if (__irq != SENSOR_PIN_NONE) { + return this->getGpioLevel(__irq) == LOW; + } + return readRegister(FT6X36_REG_STATUS) & 0x0F; + } + + void setPowerMode(PowerMode mode) + { + writeRegister(FT6X36_REG_POWER_MODE, mode); + } + + void sleep() + { + writeRegister(FT6X36_REG_POWER_MODE, PMODE_DEEPSLEEP); + } + + void wakeup() + { + reset(); + } + + void idle() + { + + } + + uint8_t getSupportTouchPoint() + { + return 1; + } + + uint32_t getChipID(void) + { + return readRegister(FT6X36_REG_CHIP_ID); + } + + uint8_t getVendorID(void) + { + return readRegister(FT6X36_REG_VENDOR1_ID); + } + + uint8_t getErrorCode(void) + { + return readRegister(FT6X36_REG_ERROR_STATUS); + } + + const char *getModelName() + { + switch (__chipID) { + case FT6206_CHIP_ID: return "FT6206"; + case FT6236_CHIP_ID: return "FT6236"; + case FT6236U_CHIP_ID: return "FT6236U"; + case FT3267_CHIP_ID: return "FT3267"; + default: return "UNKNOWN"; + } + } + + + bool getResolution(int16_t *x, int16_t *y) + { + return false; + } + + void reset() + { + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OUTPUT); + this->setGpioLevel(__rst, HIGH); + delay(10); + this->setGpioLevel(__rst, LOW); + delay(30); + this->setGpioLevel(__rst, HIGH); + // For the variant of GPIO extended RST, + // communication and delay are carried out simultaneously, and 160ms is measured in T-RGB esp-idf new api + delay(160); + } + } + + + void setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb) + { + SensorCommon::setGpioModeCallback(mode_cb); + SensorCommon::setGpioWriteCallback(write_cb); + SensorCommon::setGpioReadCallback(read_cb); + } + +private: + bool initImpl() + { + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, INPUT); + } + + reset(); + + uint8_t vendId = readRegister(FT6X36_REG_VENDOR1_ID); + + + if (vendId != FT6X36_VEND_ID) { + log_e("Vendor id is 0x%X not match!\n", vendId); + return false; + } + + __chipID = readRegister(FT6X36_REG_CHIP_ID); + + if ((__chipID != FT6206_CHIP_ID) && + (__chipID != FT6236_CHIP_ID) && + (__chipID != FT6236U_CHIP_ID) && + (__chipID != FT3267_CHIP_ID) + ) { + log_e("Vendor id is not match!\n"); + log_e("ChipID:0x%lx should be 0x06 or 0x36 or 0x64\n", __chipID); + return false; + } + + log_i("Vend ID: 0x%X\n", vendId); + log_i("Chip ID: 0x%lx\n", __chipID); + log_i("Firm Version: 0x%X\n", readRegister(FT6X36_REG_FIRM_VERS)); + log_i("Point Rate Hz: %u\n", readRegister(FT6X36_REG_PERIOD_ACTIVE)); + log_i("Thresh : %u\n", readRegister(FT6X36_REG_THRESHOLD)); + + // change threshold to be higher/lower + writeRegister(FT6X36_REG_THRESHOLD, 60); + + log_i("Chip library version : 0x%x\n", getLibraryVersion()); + + // This register describes period of monitor status, it should not less than 30. + log_i("Chip period of monitor status : 0x%x\n", readRegister(FT6X36_REG_PERIOD_MONITOR)); + + // This register describes the period of active status, it should not less than 12 + + + return true; + } + + int getReadMaskImpl() + { + return -1; + } + +}; + + + diff --git a/lib/SensorLib/src/TouchDrvGT911.hpp b/lib/SensorLib/src/TouchDrvGT911.hpp new file mode 100644 index 0000000..f3cc801 --- /dev/null +++ b/lib/SensorLib/src/TouchDrvGT911.hpp @@ -0,0 +1,424 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrvGT911.tpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-12 + * + */ +#pragma once + +#include "REG/GT911Constants.h" +#include "TouchDrvInterface.hpp" +#include "SensorCommon.tpp" + + +typedef struct GT911_Struct { + uint8_t trackID; + int16_t x; + int16_t y; + int16_t size; +} GT911Point_t; + +class TouchDrvGT911 : + public TouchDrvInterface, + public SensorCommon +{ + friend class SensorCommon; +public: + + +#if defined(ARDUINO) + TouchDrvGT911(PLATFORM_WIRE_TYPE &w, + int sda = DEFAULT_SDA, + int scl = DEFAULT_SCL, + uint8_t addr = GT911_SLAVE_ADDRESS_H) + { + __wire = &w; + __sda = sda; + __scl = scl; + __rst = SENSOR_PIN_NONE; + __irq = SENSOR_PIN_NONE; + __addr = addr; + } +#endif + + TouchDrvGT911() + { +#if defined(ARDUINO) + __wire = &Wire; + __sda = DEFAULT_SDA; + __scl = DEFAULT_SCL; +#endif + __rst = SENSOR_PIN_NONE; + __irq = SENSOR_PIN_NONE; + __addr = GT911_SLAVE_ADDRESS_H; + } + + ~TouchDrvGT911() + { + deinit(); + } + +#if defined(ARDUINO) + bool begin(PLATFORM_WIRE_TYPE &w, + uint8_t addr = GT911_SLAVE_ADDRESS_H, + int sda = DEFAULT_SDA, + int scl = DEFAULT_SCL + ) + { + return SensorCommon::begin(w, addr, sda, scl); + } + +#elif defined(ESP_PLATFORM) && !defined(ARDUINO) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) + { + return SensorCommon::begin(i2c_dev_bus_handle, addr); + } +#else + bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) + { + return SensorCommon::begin(port_num, addr, sda, scl); + } +#endif //ESP_IDF_VERSION + +#endif + + bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) + { + return SensorCommon::begin(addr, readRegCallback, writeRegCallback); + } + + + void deinit() + { + // end(); + } + + + void reset() + { + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OUTPUT); + this->setGpioLevel(__rst, HIGH); + delay(10); + } + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, INPUT); + } + // writeRegister(GT911_COMMAND, 0x02); + writeCommand(0x02); + } + + void sleep() + { + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, OUTPUT); + this->setGpioLevel(__irq, LOW); + } + // writeRegister(GT911_COMMAND, 0x05); + writeCommand(0x05); + + /* + * Depending on the chip and platform, setting it to input after removing sleep will affect power consumption. + * The chip platform determines whether + * + * * */ + // if (__irq != SENSOR_PIN_NONE) { + // this->setGpioLevel(__irq, INPUT); + // } + } + + + + void wakeup() + { + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, OUTPUT); + this->setGpioLevel(__irq, HIGH); + delay(8); + } else { + reset(); + } + } + + void idle() + { + + } + + uint8_t getSupportTouchPoint() + { + return 5; + } + + uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1) + { + uint8_t buffer[39]; + uint8_t touchPoint = 0; + GT911Point_t p[5]; + + if (!x_array || !y_array || size == 0) + return 0; + + touchPoint = getPoint(); + if (touchPoint == 0) { + return 0; + } + + // GT911_POINT_1 0X814F + uint8_t write_buffer[2] = {0x81, 0x4F}; + if (writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer), + buffer, 39) == DEV_WIRE_ERR) { + return 0; + } + + for (uint8_t i = 0; i < size; i++) { + p[i].trackID = buffer[i * 8]; + p[i].x = buffer[0x01 + i * 8] ; + p[i].x |= (buffer[0x02 + i * 8] << 8 ); + p[i].y = buffer[0x03 + i * 8] ; + p[i].y |= (buffer[0x04 + i * 8] << 8); + p[i].size = buffer[0x05 + i * 8] ; + p[i].size |= (buffer[0x06 + i * 8] << 8) ; + + x_array[i] = p[i].x; + y_array[i] = p[i].y; + } + +#ifdef LOG_PORT + LOG_PORT.println("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------"); + LOG_PORT.println("Touched [0]ID [0]Size [0]X [0]Y [1]ID [1]Size [1]X [1]Y [2]ID [2]Size [2]X [2]Y [3]ID [3]Size [3]X [3]Y [4]ID [4]Size [4]X [4]Y "); + LOG_PORT.print(touchPoint); LOG_PORT.print("\t"); + for (int i = 0; i < size; ++i) { + LOG_PORT.print(p[i].trackID); LOG_PORT.print("\t"); + LOG_PORT.print(p[i].size); LOG_PORT.print("\t"); + LOG_PORT.print( p[i].x); LOG_PORT.print("\t"); + LOG_PORT.print( p[i].y); LOG_PORT.print("\t"); + } + LOG_PORT.println(); +#endif + + updateXY(touchPoint, x_array, y_array); + + return touchPoint; + } + + + bool isPressed() + { + if (__irq != SENSOR_PIN_NONE) { + if (__irq_mode == FALLING) { + return this->getGpioLevel(__irq) == LOW; + } else if (__irq_mode == RISING ) { + return this->getGpioLevel(__irq) == HIGH; + } + } else { + return getPoint(); + } + return false; + } + + //In the tested GT911 only the falling edge is valid to use, the rest are incorrect + bool setInterruptMode(uint8_t mode) + { + // GT911_MODULE_SWITCH_1 0x804D + uint8_t val = readGT911(GT911_MODULE_SWITCH_1); + val &= 0XFC; + if (mode == FALLING) { + val |= 0x03; + } else if (mode == RISING ) { + val |= 0x02; + } + __irq_mode = mode; + return writeGT911(GT911_MODULE_SWITCH_1, val) != DEV_WIRE_ERR; + } + + + uint8_t getPoint() + { + // GT911_POINT_INFO 0X814E + uint8_t val = readGT911(GT911_POINT_INFO) & 0x0F; + clearBuffer(); + return val & 0x0F; + } + + + uint32_t getChipID() + { + char product_id[4] = {0}; + // GT911_PRODUCT_ID 0x8140 + for (int i = 0; i < 4; ++i) { + product_id[i] = readGT911(GT911_PRODUCT_ID + i); + } + return atoi(product_id); + } + + uint16_t getFwVersion() + { + uint8_t fw_ver[2] = {0}; + // GT911_FIRMWARE_VERSION 0x8144 + for (int i = 0; i < 2; ++i) { + fw_ver[i] = readGT911(GT911_FIRMWARE_VERSION + i); + } + return fw_ver[0] | (fw_ver[1] << 8); + } + + bool getResolution(int16_t *x, int16_t *y) + { + uint8_t x_resolution[2] = {0}, y_resolution[2] = {0}; + + for (int i = 0; i < 2; ++i) { + x_resolution[i] = readGT911(GT911_X_RESOLUTION + i); + } + for (int i = 0; i < 2; ++i) { + y_resolution[i] = readGT911(GT911_Y_RESOLUTION + i); + } + + *x = x_resolution[0] | (x_resolution[1] << 8); + *y = y_resolution[0] | (y_resolution[1] << 8); + return true; + } + + int getVendorID() + { + return readGT911(GT911_VENDOR_ID); + } + + + const char *getModelName() + { + return "GT911"; + } + + void setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb) + { + SensorCommon::setGpioModeCallback(mode_cb); + SensorCommon::setGpioWriteCallback(write_cb); + SensorCommon::setGpioReadCallback(read_cb); + } + +private: + + uint8_t readGT911(uint16_t cmd) + { + uint8_t value = 0x00; + uint8_t write_buffer[2] = {highByte(cmd), lowByte(cmd)}; + writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer), + &value, 1); + return value; + } + + int writeGT911(uint16_t cmd, uint8_t value) + { + uint8_t write_buffer[3] = {highByte(cmd), lowByte(cmd), value}; + return writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer)); + } + + + void writeCommand(uint8_t command) + { + // GT911_COMMAND 0x8040 + uint8_t write_buffer[3] = {0x80, 0x40, command}; + writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer)); + } + + void inline clearBuffer() + { + writeGT911(GT911_POINT_INFO, 0x00); + } + + bool initImpl() + { + int16_t x = 0, y = 0; + + if (__addr == GT911_SLAVE_ADDRESS_H && + __rst != SENSOR_PIN_NONE && + __irq != SENSOR_PIN_NONE) { + + log_i("GT911 using 0x28 address!\n"); + + this->setGpioMode(__rst, OUTPUT); + this->setGpioMode(__irq, OUTPUT); + + this->setGpioLevel(__rst, LOW); + this->setGpioLevel(__irq, HIGH); + delayMicroseconds(120); + this->setGpioLevel(__rst, HIGH); + delay(18); + this->setGpioMode(__irq, INPUT); + + } else if (__addr == GT911_SLAVE_ADDRESS_L && + __rst != SENSOR_PIN_NONE && + __irq != SENSOR_PIN_NONE) { + + log_i("GT911 using 0xBA address!\n"); + + this->setGpioMode(__rst, OUTPUT); + this->setGpioMode(__irq, OUTPUT); + + this->setGpioLevel(__rst, LOW); + this->setGpioLevel(__irq, LOW); + delayMicroseconds(120); + this->setGpioLevel(__rst, HIGH); + delay(18); + this->setGpioMode(__irq, INPUT); + + } else { + reset(); + } + + // For variants where the GPIO is controlled by I2C, a delay is required here + delay(20); + + __chipID = getChipID(); + log_i("Product id:%ld\n", __chipID); + + if (__chipID != 911) { + log_i("Not find device GT911\n"); + return false; + } + log_i("Firmware version: 0x%x\n", getFwVersion()); + getResolution(&x, &y); + log_i("Resolution : X = %d Y = %d\n", x, y); + log_i("Vendor id:%d\n", getVendorID()); + return true; + } + + int getReadMaskImpl() + { + return -1; + } + + +protected: + int __irq_mode; +}; + + + diff --git a/lib/SensorLib/src/TouchDrvInterface.cpp b/lib/SensorLib/src/TouchDrvInterface.cpp new file mode 100644 index 0000000..5e43a30 --- /dev/null +++ b/lib/SensorLib/src/TouchDrvInterface.cpp @@ -0,0 +1,100 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrvInterface.cpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-21 + * + */ +#include "TouchDrvInterface.hpp" + +TouchDrvInterface::TouchDrvInterface() : + __resX(0), + __resY(0), + __xMax(0), + __yMax(0), + __swapXY(false), + __mirrorX(false), + __mirrorY(false), + __rst(-1), + __irq(-1), + __chipID(0x00), + __homeButtonCb(NULL), + __userData(NULL) +{ + +} + +TouchDrvInterface::~TouchDrvInterface() +{ + +} + +uint32_t TouchDrvInterface::getChipID() +{ + return __chipID; +} + + +void TouchDrvInterface::setPins(int rst, int irq) +{ + __irq = irq; + __rst = rst; +} + +void TouchDrvInterface::setSwapXY(bool swap) +{ + __swapXY = swap; +} + +void TouchDrvInterface::setMirrorXY(bool mirrorX, bool mirrorY) +{ + __mirrorX = mirrorX; + __mirrorY = mirrorY; +} + +void TouchDrvInterface::setMaxCoordinates(uint16_t x, uint16_t y) +{ + __xMax = x; + __yMax = y; +} + +void TouchDrvInterface::updateXY(uint8_t pointNum, int16_t *xBuffer, int16_t *yBuffer) +{ + if (!pointNum) + return; + for (int i = 0; i < pointNum; ++i) { + if (__swapXY) { + uint16_t tmp = xBuffer[i]; + xBuffer[i] = yBuffer[i]; + yBuffer[i] = tmp; + } + if (__mirrorX && __xMax ) { + xBuffer[i] = __xMax - xBuffer[i]; + } + if (__mirrorY && __yMax) { + yBuffer[i] = __yMax - yBuffer[i]; + } + } +} diff --git a/lib/SensorLib/src/TouchDrvInterface.hpp b/lib/SensorLib/src/TouchDrvInterface.hpp new file mode 100644 index 0000000..b41ea4d --- /dev/null +++ b/lib/SensorLib/src/TouchDrvInterface.hpp @@ -0,0 +1,145 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file TouchDrvInterface.hpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-04-17 + * + */ +#pragma once + +#include +#include +#include "SensorLib.h" +#include "SensorCommon.tpp" + +typedef void (*home_button_callback_t)(void *user_data); + + +class TouchData +{ +public: + TouchData() {} + ~TouchData() {}; + uint8_t available; + uint8_t id[5]; + int16_t x[5]; + int16_t y[5]; + uint8_t status[5]; + uint8_t pressure[5]; + + uint16_t getX(uint8_t index = 0) + { + return x[index]; + } + uint16_t getY(uint8_t index = 0) + { + return y[index]; + } + uint16_t getPressure(uint8_t index = 0) + { + return pressure[index]; + } + uint16_t getStatus(uint8_t index = 0) + { + return status[index]; + } +}; + + + +class TouchDrvInterface +{ +public: + TouchDrvInterface(); + + virtual ~TouchDrvInterface(); + +#if defined(ARDUINO) + + virtual bool begin(PLATFORM_WIRE_TYPE &wire, uint8_t address, int sda, int scl) = 0; + +#elif defined(ESP_PLATFORM) && !defined(ARDUINO) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + virtual bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) = 0; +#else + virtual bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) = 0; +#endif //ESP_IDF_VERSION + +#endif //defined(ESP_PLATFORM) && !defined(ARDUINO) + + virtual bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) = 0; + + virtual void reset() = 0; + + virtual uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point) = 0; + + virtual bool isPressed() = 0; + + virtual const char *getModelName() = 0; + + virtual void sleep() = 0; + + virtual void wakeup() = 0; + + virtual void idle() = 0; + + virtual uint8_t getSupportTouchPoint() = 0; + + virtual bool getResolution(int16_t *x, int16_t *y) = 0; + + virtual void setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb) = 0; + + uint32_t getChipID(); + + void setPins(int rst, int irq); + + void setSwapXY(bool swap); + + void setMirrorXY(bool mirrorX, bool mirrorY); + + void setMaxCoordinates(uint16_t x, uint16_t y); + + void updateXY(uint8_t pointNum, int16_t *xBuffer, int16_t *yBuffer); + +protected: + uint16_t __resX, __resY, __xMax, __yMax; + bool __swapXY, __mirrorX, __mirrorY; + int __rst; + int __irq; + uint32_t __chipID; + home_button_callback_t __homeButtonCb; + void *__userData; + +}; + + + + + + + diff --git a/lib/SensorLib/src/bosch/BMM150/bmm150.c b/lib/SensorLib/src/bosch/BMM150/bmm150.c new file mode 100644 index 0000000..1f401f0 --- /dev/null +++ b/lib/SensorLib/src/bosch/BMM150/bmm150.c @@ -0,0 +1,2187 @@ +/** + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file bmm150.c + * @date 2020-06-03 + * @version v2.0.0 + * + */ + +/*! @file bmm150.c + * @brief Sensor driver for BMM150 sensor */ +#include "bmm150.h" + +/************************** Internal macros *******************************/ +/* Sensor ODR, Repetition and axes enable/disable settings */ +#define MODE_SETTING_SEL UINT16_C(0x000F) + +/* Interrupt pin settings like polarity,latch and int_pin enable */ +#define INTERRUPT_PIN_SETTING_SEL UINT16_C(0x01F0) + +/* Settings to enable/disable interrupts */ +#define INTERRUPT_CONFIG_SEL UINT16_C(0x1E00) + +/* Interrupt settings for configuring threshold values */ +#define INTERRUPT_THRESHOLD_CONFIG_SEL UINT16_C(0x6000) + +/********************** Static function declarations ************************/ + +/*! + * @brief This internal API is used to validate the device pointer for + * null conditions. + * + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t null_ptr_check(const struct bmm150_dev *dev); + +/*! + * @brief This internal API sets/resets the power control bit of 0x4B register. + * + * @param[in] pwrcntrl_bit : Variable used to select/deselect the suspend mode. + * @param[in,out] dev : Structure instance of bmm150_dev + * + * pwrcntrl_bit | power mode + * -----------------|------------------------- + * 0x00 | Suspend mode + * 0x01 | Sleep/Active modes + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t set_power_control_bit(uint8_t pwrcntrl_bit, struct bmm150_dev *dev); + +/*! + * @brief This internal API reads the trim registers of the sensor and stores + * the trim values in the "trim_data" of device structure. + * + * @param[in,out] dev : Structure instance of bmm150_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t read_trim_registers(struct bmm150_dev *dev); + +/*! + * @brief This internal API writes the op_mode value in the Opmode bits + * (bits 1 and 2) of 0x4C register. + * + * op_mode | Power mode + * ------------|----------------------- + * 0x00 | BMM150_POWERMODE_NORMAL + * 0x01 | BMM150_POWERMODE_FORCED + * 0x03 | BMM150_POWERMODE_SLEEP + * + * @param[in,out] dev : Structure instance of bmm150_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t write_op_mode(uint8_t op_mode, struct bmm150_dev *dev); + +/*! + * @brief This internal API sets the device from suspend to sleep mode + * by setting the power control bit to '1' of 0x4B register + * + * @param[in,out] dev : Structure instance of bmm150_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t suspend_to_sleep_mode(struct bmm150_dev *dev); + +/*! + * @brief This internal API sets the xy repetition value in the 0x51 register. + * + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in,out] dev : Structure instance of bmm150_dev + * + * settings->xy_rep | nXY(XY Repetitions) + * -------------------------|----------------------- + * 0x00 | 1 + * 0x01 | 3 + * 0x02 | 5 + * . | . + * . | . + * 0xFF | 511 + * + * @note number of XY Repetitions nXY = 1+2(settings->xy_rep) + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t set_xy_rep(const struct bmm150_settings *settings, struct bmm150_dev *dev); + +/*! + * @brief This internal API sets the z repetition value in the 0x52 register. + * + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in,out] dev : Structure instance of bmm150_dev + * + * settings->z_rep | nZ(Z Repetitions) + * -------------------------|----------------------- + * 0x00 | 1 + * 0x01 | 2 + * 0x02 | 3 + * . | . + * . | . + * 0xFF | 256 + * + * @note number of Z Repetitions nZ = 1+(settings->z_rep) + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t set_z_rep(const struct bmm150_settings *settings, struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to set the output data rate of the sensor + * + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * settings->data_rate | Data rate (ODR) + * -------------------------|----------------------- + * 0x00 | BMM150_DATA_RATE_10HZ + * 0x01 | BMM150_DATA_RATE_02HZ + * 0x02 | BMM150_DATA_RATE_06HZ + * 0x03 | BMM150_DATA_RATE_08HZ + * 0x04 | BMM150_DATA_RATE_15HZ + * 0x05 | BMM150_DATA_RATE_20HZ + * 0x06 | BMM150_DATA_RATE_25HZ + * 0x07 | BMM150_DATA_RATE_30HZ + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t set_odr(const struct bmm150_settings *settings, struct bmm150_dev *dev); + +/*! + * @brief This internal API sets the preset mode ODR and repetition settings. + * @param[in] settings : Structure instance of bmm150_settings + * @param[in] dev : Structure instance of bmm150_dev + * + * API settings | Representation + * ---------------------|------------------------------ + * settings->data_rate | Output Data Rate (ODR) + * settings->xy_rep | XY repetition value + * settings->z_rep | Z-repetition value + * + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t set_odr_xyz_rep(const struct bmm150_settings *settings, struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to enable or disable the magnetic + * measurement of x,y,z axes based on the value of xyz_axes_control. + * + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * settings->xyz_axes_control | Measurement axes/channel + * ---------------------------|-------------------------- + * Bit 0 | X - Channel + * Bit 1 | Y - Channel + * Bit 2 | Z - Channel + * + * @note Setting 1 - Disables Channel measurement + * @note Setting 0 - Enables Channel measurement + * + * settings->xyz_axes_control | Measurement axes Enabled/disabled + * -------------------------------|------------------------------------ + * 0x01 | Disables X axis (Y,Z axes enabled) + * 0x02 | Disables Y axis (X,Z axes enabled) + * 0x04 | Disables Z axis (X,Y axes enabled) + * 0x07 | Disables all X,Y,Z axes measurement + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t set_control_measurement_xyz(const struct bmm150_settings *settings, struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to identify the settings which the user + * wants to modify in the sensor. + * + * @param[in] sub_settings : Contains the settings subset to identify particular + * group of settings which the user is interested to change. + * @param[in] settings : Contains the user specified settings. + * + * @return Indicates whether user is interested to modify the settings which + * are related to sub_settings. + * @retval True -> User wants to modify this group of settings + * @retval False -> User does not want to modify this group of settings + */ +static uint8_t are_settings_changed(uint16_t sub_settings, uint16_t settings); + +/*! + * @brief This API sets the ODR , measurement axes control , + * repetition values of xy,z. + * + * @param[in] desired_settings : Contains the settings which user wants to + * change. + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t mode_settings(uint16_t desired_settings, const struct bmm150_settings *settings, struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to parse and store the sensor + * settings in the device structure + * + * @param[in] reg_data : Pointer of an array consisting all sensor + * setting data from 0x4B to 0x52 registers. + * @param[in] settings : Structure instance of bmm150_settings. + * + */ +static void parse_setting(const uint8_t *reg_data, struct bmm150_settings *settings); + +/*! + * @brief This API is used to enable the interrupts and map them to the + * corresponding interrupt pins and specify the pin characteristics like the + * polarity , latch settings for the interrupt pins. + * + * @note The other interrupts can be latched or non-latched but, + * Data ready interrupt is always cleared after reading out the data + * + * @param[in] desired_settings : Contains the settings which user wants to + * change. + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t interrupt_pin_settings(uint16_t desired_settings, + const struct bmm150_settings *settings, + struct bmm150_dev *dev); + +/*! + * @brief This API is used to enable data overrun , overflow interrupts and + * enable/disable high/low threshold interrupts for x,y,z axis based on the + * threshold values set by the user in the High threshold (0x50) and + * Low threshold (0x4F) registers. + * + * @param[in] desired_settings : Contains the settings which user wants to + * change. + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t interrupt_config(uint16_t desired_settings, const struct bmm150_settings *settings, + struct bmm150_dev *dev); + +/*! + * @brief This API is used to write the user specified High/Low threshold value + * as a reference to generate the high/low threshold interrupt. + * + * @param[in] desired_settings : Contains the settings which user wants to + * change. + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t interrupt_threshold_settings(uint16_t desired_settings, + const struct bmm150_settings *settings, + struct bmm150_dev *dev); + +#ifdef BMM150_USE_FLOATING_POINT + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer X axis data in float. + * + * @param[in] mag_data_x : The value of raw X data + * @param[in] data_rhall : The value of raw RHALL data + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of compensated X data value in float + */ +static float compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer Y axis data in float. + * + * @param[in] mag_data_y : The value of raw Y data + * @param[in] data_rhall : The value of raw RHALL data + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of compensated Y data value in float + */ +static float compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer Z axis data in float. + * + * @param[in] mag_data_z : The value of raw Z data + * @param[in] data_rhall : The value of raw RHALL data + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of compensated Z data value in float + */ +static float compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev); + +#else + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer X axis data in int16_t. + * + * @param[in] mag_data_x : The value of raw X data + * @param[in] data_rhall : The value of raw RHALL data + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of compensated X data value in int16_t format + */ +static int16_t compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer Y axis data in int16_t. + * + * @param[in] mag_data_y : The value of raw Y data + * @param[in] data_rhall : The value of raw RHALL data + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of compensated Y data value in int16_t format + */ +static int16_t compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer Z axis data in int16_t. + * + * @param[in] mag_data_z : The value of raw Z data + * @param[in] data_rhall : The value of raw RHALL data + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of compensated Z data value in int16_t format + */ +static int16_t compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev); + +#endif + +/*! + * @brief This internal API is used to perform the normal self test + * of the sensor and return the self test result as return value + * + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t perform_normal_self_test(struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to enable the normal self test by setting + * the Self Test bit (bit0) of the 0x4C register, + * which triggers the start of self test + * + * @param[out] self_test_enable : The value of self test bit0 in 0x4C register + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t enable_normal_self_test(uint8_t *self_test_enable, struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to validate the results of normal self test + * by using the self test status available in the bit0 of registers 0x42,0x44 + * and 0x46. + * + * @param[in] dev : Structure instance of bmm150_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t validate_normal_self_test(struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to perform advanced self test for Z axis + * + * @param[in] dev : Structure instance of bmm150_dev + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + * + * Return value | Status of self-test + *----------------------|--------------------------- + * 0 | BMM150_OK + * 8 | BMM150_W_ADV_SELF_TEST_FAIL + */ +static int8_t perform_adv_self_test(struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to set the desired power mode , + * axes control and repetition settings for advanced self test + * + * @param[in] dev : Structure instance of bmm150_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t adv_self_test_settings(struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to set the positive or negative value of + * self-test current and obtain the corresponding magnetometer z axis data + * + * @param[in] self_test_current : Self test current either positive/negative + * @param[out] data_z : Z-axis Magnetometer data + * @param[in] dev : Structure instance of bmm150_dev + * + * self_test_current | Self-test current Direction + *-------------------------|------------------------------ + * 0x03 | BMM150_ENABLE_POSITIVE_CURRENT + * 0x02 | BMM150_ENABLE_NEGATIVE_CURRENT + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t adv_self_test_measurement(uint8_t self_test_current, int16_t *data_z, struct bmm150_dev *dev); + +/*! + * @brief This internal API is used to get the difference between the + * Z axis mag data obtained by positive and negative self-test current + * and validate whether the advanced self test is done successfully or not. + * + * @param[in] positive_data_z : Z-axis Mag data by positive self-test current + * @param[in] negative_data_z : Z-axis Mag data by negative self-test current + * + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + * + * Return value | Status of self-test + *----------------------|--------------------------- + * 0 | BMM150_OK + * 8 | BMM150_W_ADV_SELF_TEST_FAIL + */ +static int8_t validate_adv_self_test(int16_t positive_data_z, int16_t negative_data_z); + +/*! + * @brief This internal API is used to set the self test current value in + * the Adv. ST bits (bit6 and bit7) of 0x4C register + * + * @param[in] self_test_current : Self test current value (+ve/-ve) + * @param[in] dev : Structure instance of bmm150_dev + * + * self_test_current | Self-test current Direction + *-------------------------|------------------------------ + * 0x00 | BMM150_DISABLE_SELF_TEST_CURRENT + * 0x02 | BMM150_ENABLE_NEGATIVE_CURRENT + * 0x03 | BMM150_ENABLE_POSITIVE_CURRENT + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t set_adv_self_test_current(uint8_t self_test_current, struct bmm150_dev *dev); + +/********************** Global function definitions ************************/ + +/*! + * @brief This API is the entry point, Call this API before using other APIs. + * This API reads the chip-id of the sensor which is the first step to + * verify the sensor and updates the trim parameters of the sensor. + */ +int8_t bmm150_init(struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t chip_id = 0; + + /* Power up the sensor from suspend to sleep mode */ + rslt = set_power_control_bit(BMM150_POWER_CNTRL_ENABLE, dev); + + if (rslt == BMM150_OK) + { + /* Start-up time delay of 3ms */ + dev->delay_us(BMM150_START_UP_TIME, dev->intf_ptr); + + /* Chip ID of the sensor is read */ + rslt = bmm150_get_regs(BMM150_REG_CHIP_ID, &chip_id, 1, dev); + + /* Proceed if everything is fine until now */ + if (rslt == BMM150_OK) + { + /* Check for chip id validity */ + if (chip_id == BMM150_CHIP_ID) + { + dev->chip_id = chip_id; + + /* Function to update trim values */ + rslt = read_trim_registers(dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API writes the given data to the register address + * of the sensor. + */ +int8_t bmm150_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if ((rslt == BMM150_OK) && (reg_data != NULL) && (len != 0)) + { + /* Write the data to the reg_addr */ + + /* SPI write requires to set The MSB of reg_addr as 0 + * but in default the MSB is always 0 + */ + dev->intf_rslt = dev->write(reg_addr, reg_data, len, dev->intf_ptr); + } + else + { + rslt = BMM150_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API reads the data from the given register address of the sensor. + */ +int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if ((rslt == BMM150_OK) && (reg_data != NULL)) + { + if (dev->intf != BMM150_I2C_INTF) + { + /* If interface selected is SPI */ + reg_addr = reg_addr | 0x80; + } + + /* Read the data from the reg_addr */ + dev->intf_rslt = dev->read(reg_addr, reg_data, len, dev->intf_ptr); + } + else + { + rslt = BMM150_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API is used to perform soft-reset of the sensor + * where all the registers are reset to their default values except 0x4B. + */ +int8_t bmm150_soft_reset(struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + rslt = bmm150_get_regs(BMM150_REG_POWER_CONTROL, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + reg_data = reg_data | BMM150_SET_SOFT_RESET; + rslt = bmm150_set_regs(BMM150_REG_POWER_CONTROL, ®_data, 1, dev); + dev->delay_us(BMM150_DELAY_SOFT_RESET, dev->intf_ptr); + } + + return rslt; +} + +/*! + * @brief This API is used to set the power mode of the sensor. + */ +int8_t bmm150_set_op_mode(const struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t pwr_mode; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if (rslt == BMM150_OK) + { + pwr_mode = settings->pwr_mode; + + /* Select the power mode to set */ + switch (pwr_mode) + { + case BMM150_POWERMODE_NORMAL: + + /* If the sensor is in suspend mode + * put the device to sleep mode + */ + rslt = suspend_to_sleep_mode(dev); + if (rslt == BMM150_OK) + { + /* write the op mode */ + rslt = write_op_mode(pwr_mode, dev); + } + + break; + case BMM150_POWERMODE_FORCED: + + /* If the sensor is in suspend mode + * put the device to sleep mode + */ + rslt = suspend_to_sleep_mode(dev); + if (rslt == BMM150_OK) + { + /* write the op mode */ + rslt = write_op_mode(pwr_mode, dev); + } + + break; + case BMM150_POWERMODE_SLEEP: + + /* If the sensor is in suspend mode + * put the device to sleep mode + */ + rslt = suspend_to_sleep_mode(dev); + if (rslt == BMM150_OK) + { + /* write the op mode */ + rslt = write_op_mode(pwr_mode, dev); + } + + break; + case BMM150_POWERMODE_SUSPEND: + + /* Set the power control bit to zero */ + rslt = set_power_control_bit(BMM150_POWER_CNTRL_DISABLE, dev); + break; + default: + rslt = BMM150_E_INVALID_CONFIG; + break; + } + } + + return rslt; +} + +/*! + * @brief This API is used to get the power mode of the sensor. + */ +int8_t bmm150_get_op_mode(uint8_t *op_mode, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if (rslt == BMM150_OK) + { + if (dev->pwr_cntrl_bit == BMM150_POWER_CNTRL_DISABLE) + { + /* Power mode set is suspend mode */ + *op_mode = BMM150_POWERMODE_SUSPEND; + } + else + { + /* Power mode set is stored in the op_mode */ + rslt = bmm150_get_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + *op_mode = BMM150_GET_BITS(reg_data, BMM150_OP_MODE); + } + } + + return rslt; +} + +/*! + * @brief This API is used to set the preset mode of the sensor. + */ +int8_t bmm150_set_presetmode(struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t preset_mode; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if (rslt == BMM150_OK) + { + preset_mode = settings->preset_mode; + + switch (preset_mode) + { + case BMM150_PRESETMODE_LOWPOWER: + + /* Set the data rate x,y,z repetition + * for Low Power mode + */ + settings->data_rate = BMM150_DATA_RATE_10HZ; + settings->xy_rep = BMM150_REPXY_LOWPOWER; + settings->z_rep = BMM150_REPZ_LOWPOWER; + rslt = set_odr_xyz_rep(settings, dev); + break; + case BMM150_PRESETMODE_REGULAR: + + /* Set the data rate x,y,z repetition + * for Regular mode + */ + settings->data_rate = BMM150_DATA_RATE_10HZ; + settings->xy_rep = BMM150_REPXY_REGULAR; + settings->z_rep = BMM150_REPZ_REGULAR; + rslt = set_odr_xyz_rep(settings, dev); + break; + case BMM150_PRESETMODE_HIGHACCURACY: + + /* Set the data rate x,y,z repetition + * for High Accuracy mode * + */ + settings->data_rate = BMM150_DATA_RATE_20HZ; + settings->xy_rep = BMM150_REPXY_HIGHACCURACY; + settings->z_rep = BMM150_REPZ_HIGHACCURACY; + rslt = set_odr_xyz_rep(settings, dev); + break; + case BMM150_PRESETMODE_ENHANCED: + + /* Set the data rate x,y,z repetition + * for Enhanced Accuracy mode + */ + settings->data_rate = BMM150_DATA_RATE_10HZ; + settings->xy_rep = BMM150_REPXY_ENHANCED; + settings->z_rep = BMM150_REPZ_ENHANCED; + rslt = set_odr_xyz_rep(settings, dev); + break; + default: + rslt = BMM150_E_INVALID_CONFIG; + break; + } + } + + return rslt; +} + +/*! + * @brief This API sets the sensor settings based on the desired_settings + * and the dev structure configuration + */ +int8_t bmm150_set_sensor_settings(uint16_t desired_settings, + const struct bmm150_settings *settings, + struct bmm150_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if (rslt == BMM150_OK) + { + if (are_settings_changed(MODE_SETTING_SEL, desired_settings)) + { + /* ODR, Control measurement, XY,Z repetition values */ + rslt = mode_settings(desired_settings, settings, dev); + } + + if ((!rslt) && are_settings_changed(INTERRUPT_PIN_SETTING_SEL, desired_settings)) + { + /* Interrupt pin settings */ + rslt = interrupt_pin_settings(desired_settings, settings, dev); + } + + if ((!rslt) && are_settings_changed(INTERRUPT_CONFIG_SEL, desired_settings)) + { + /* Interrupt configuration settings */ + rslt = interrupt_config(desired_settings, settings, dev); + } + + if ((!rslt) && are_settings_changed(INTERRUPT_THRESHOLD_CONFIG_SEL, desired_settings)) + { + /* Interrupt threshold settings */ + rslt = interrupt_threshold_settings(desired_settings, settings, dev); + } + } + + return rslt; +} + +/*! + * @brief This API gets the sensor settings and updates the dev structure + */ +int8_t bmm150_get_sensor_settings(struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t setting[BMM150_LEN_SETTING_DATA] = {0}; + + /* Read the entire sensor settings */ + rslt = bmm150_get_regs(BMM150_REG_POWER_CONTROL, setting, BMM150_LEN_SETTING_DATA, dev); + + if (rslt == BMM150_OK) + { + /* Parse and store the settings */ + parse_setting(setting, settings); + } + + return rslt; +} + +/*! + * @brief This API is used to read the magnetometer data from registers + * 0x42 to 0x49 and update the dev structure with the + * compensated mag data in micro-tesla. + */ +int8_t bmm150_read_mag_data(struct bmm150_mag_data *mag_data, struct bmm150_dev *dev) +{ + int8_t rslt; + int16_t msb_data; + uint8_t reg_data[BMM150_LEN_XYZR_DATA] = {0}; + struct bmm150_raw_mag_data raw_mag_data; + + /* Read the mag data registers */ + rslt = bmm150_get_regs(BMM150_REG_DATA_X_LSB, reg_data, BMM150_LEN_XYZR_DATA, dev); + + if (rslt == BMM150_OK) + { + /* Mag X axis data */ + reg_data[0] = BMM150_GET_BITS(reg_data[0], BMM150_DATA_X); + + /* Shift the MSB data to left by 5 bits */ + /* Multiply by 32 to get the shift left by 5 value */ + msb_data = ((int16_t)((int8_t)reg_data[1])) * 32; + + /* Raw mag X axis data */ + raw_mag_data.raw_datax = (int16_t)(msb_data | reg_data[0]); + + /* Mag Y axis data */ + reg_data[2] = BMM150_GET_BITS(reg_data[2], BMM150_DATA_Y); + + /* Shift the MSB data to left by 5 bits */ + /* Multiply by 32 to get the shift left by 5 value */ + msb_data = ((int16_t)((int8_t)reg_data[3])) * 32; + + /* Raw mag Y axis data */ + raw_mag_data.raw_datay = (int16_t)(msb_data | reg_data[2]); + + /* Mag Z axis data */ + reg_data[4] = BMM150_GET_BITS(reg_data[4], BMM150_DATA_Z); + + /* Shift the MSB data to left by 7 bits */ + /* Multiply by 128 to get the shift left by 7 value */ + msb_data = ((int16_t)((int8_t)reg_data[5])) * 128; + + /* Raw mag Z axis data */ + raw_mag_data.raw_dataz = (int16_t)(msb_data | reg_data[4]); + + /* Mag R-HALL data */ + reg_data[6] = BMM150_GET_BITS(reg_data[6], BMM150_DATA_RHALL); + raw_mag_data.raw_data_r = (uint16_t)(((uint16_t)reg_data[7] << 6) | reg_data[6]); + + /* Compensated Mag X data in int16_t format */ + mag_data->x = compensate_x(raw_mag_data.raw_datax, raw_mag_data.raw_data_r, dev); + + /* Compensated Mag Y data in int16_t format */ + mag_data->y = compensate_y(raw_mag_data.raw_datay, raw_mag_data.raw_data_r, dev); + + /* Compensated Mag Z data in int16_t format */ + mag_data->z = compensate_z(raw_mag_data.raw_dataz, raw_mag_data.raw_data_r, dev); + } + + return rslt; +} + +/*! + * @brief This API is used to perform the complete self test + * (both normal and advanced) for the BMM150 sensor + */ +int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev) +{ + int8_t rslt; + int8_t self_test_rslt = 0; + struct bmm150_settings settings; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if (rslt == BMM150_OK) + { + switch (self_test_mode) + { + case BMM150_SELF_TEST_NORMAL: + + /* Set the sensor in sleep mode */ + settings.pwr_mode = BMM150_POWERMODE_SLEEP; + rslt = bmm150_set_op_mode(&settings, dev); + + if (rslt == BMM150_OK) + { + /* Perform the normal self test */ + rslt = perform_normal_self_test(dev); + } + + break; + case BMM150_SELF_TEST_ADVANCED: + + /* Perform the advanced self test */ + rslt = perform_adv_self_test(dev); + + /* Check to ensure bus error does not occur */ + if (rslt >= BMM150_OK) + { + /* Store the status of self test result */ + self_test_rslt = rslt; + + /* Perform soft reset */ + rslt = bmm150_soft_reset(dev); + } + + /* Check to ensure bus operations are success */ + if (rslt == BMM150_OK) + { + /* Restore self_test_rslt as return value */ + rslt = self_test_rslt; + } + + break; + default: + rslt = BMM150_E_INVALID_CONFIG; + break; + } + } + + return rslt; +} + +/*! + * @brief This API is used to get the status flags of all interrupt + * which is used to check for the assertion of interrupts + */ +int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t interrupt_status; + uint8_t data_ready_status; + + /* Read the data ready status from the register 0x48 */ + rslt = bmm150_get_regs(BMM150_REG_DATA_READY_STATUS, &data_ready_status, 1, dev); + + if (rslt == BMM150_OK) + { + /* Read the interrupt status from the register 0x50 */ + rslt = bmm150_get_regs(BMM150_REG_INTERRUPT_STATUS, &interrupt_status, 1, dev); + + if (rslt == BMM150_OK) + { + /* Mask and store the data ready status bit */ + data_ready_status = BMM150_GET_BITS_POS_0(data_ready_status, BMM150_DRDY_STATUS); + + /* Store the entire interrupt status in dev */ + dev->int_status = (data_ready_status << 8) | interrupt_status; + } + } + + return rslt; +} + +/****************************************************************************/ +/**\name BMM150 as Auxiliary Mag */ + +/*! + * @brief This API is used to compensate the raw mag data + */ +int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_mag_data *mag_data, const struct bmm150_dev *dev) +{ + int8_t rslt; + int16_t msb_data; + struct bmm150_raw_mag_data raw_mag_data; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if ((rslt == BMM150_OK) && (aux_data != NULL)) + { + /* Mag X axis data */ + aux_data[0] = BMM150_GET_BITS(aux_data[0], BMM150_DATA_X); + + /* Shift the MSB data to left by 5 bits */ + /* Multiply by 32 to get the shift left by 5 value */ + msb_data = ((int16_t)((int8_t)aux_data[1])) * 32; + + /* Raw mag X axis data */ + raw_mag_data.raw_datax = (int16_t)(msb_data | aux_data[0]); + + /* Mag Y axis data */ + aux_data[2] = BMM150_GET_BITS(aux_data[2], BMM150_DATA_Y); + + /* Shift the MSB data to left by 5 bits */ + /* Multiply by 32 to get the shift left by 5 value */ + msb_data = ((int16_t)((int8_t)aux_data[3])) * 32; + + /* Raw mag Y axis data */ + raw_mag_data.raw_datay = (int16_t)(msb_data | aux_data[2]); + + /* Mag Z axis data */ + aux_data[4] = BMM150_GET_BITS(aux_data[4], BMM150_DATA_Z); + + /* Shift the MSB data to left by 7 bits */ + /* Multiply by 128 to get the shift left by 7 value */ + msb_data = ((int16_t)((int8_t)aux_data[5])) * 128; + + /* Raw mag Z axis data */ + raw_mag_data.raw_dataz = (int16_t)(msb_data | aux_data[4]); + + /* Mag R-HALL data */ + aux_data[6] = BMM150_GET_BITS(aux_data[6], BMM150_DATA_RHALL); + raw_mag_data.raw_data_r = (uint16_t)(((uint16_t)aux_data[7] << 6) | aux_data[6]); + + /* Compensated Mag X data in int16_t format */ + mag_data->x = compensate_x(raw_mag_data.raw_datax, raw_mag_data.raw_data_r, dev); + + /* Compensated Mag Y data in int16_t format */ + mag_data->y = compensate_y(raw_mag_data.raw_datay, raw_mag_data.raw_data_r, dev); + + /* Compensated Mag Z data in int16_t format */ + mag_data->z = compensate_z(raw_mag_data.raw_dataz, raw_mag_data.raw_data_r, dev); + } + + return rslt; +} + +/****************************************************************************/ +/**\name INTERNAL APIs */ + +/*! + * @brief This internal API is used to validate the device structure pointer for + * null conditions. + */ +static int8_t null_ptr_check(const struct bmm150_dev *dev) +{ + int8_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL) || + (dev->intf_ptr == NULL)) + { + /* Device structure pointer is not valid */ + rslt = BMM150_E_NULL_PTR; + } + else + { + /* Device structure is fine */ + rslt = BMM150_OK; + } + + return rslt; +} + +/*! + * @brief This internal API sets/resets the power control bit of 0x4B register. + */ +static int8_t set_power_control_bit(uint8_t pwrcntrl_bit, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data = 0; + + /* Power control register 0x4B is read */ + rslt = bmm150_get_regs(BMM150_REG_POWER_CONTROL, ®_data, 1, dev); + + /* Proceed if everything is fine until now */ + if (rslt == BMM150_OK) + { + /* Sets the value of power control bit */ + reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_PWR_CNTRL, pwrcntrl_bit); + rslt = bmm150_set_regs(BMM150_REG_POWER_CONTROL, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + /* Store the power control bit + * value in dev structure + */ + dev->pwr_cntrl_bit = pwrcntrl_bit; + } + } + + return rslt; +} + +/*! + * @brief This internal API reads the trim registers of the sensor and stores + * the trim values in the "trim_data" of device structure. + */ +static int8_t read_trim_registers(struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t trim_x1y1[2] = {0}; + uint8_t trim_xyz_data[4] = {0}; + uint8_t trim_xy1xy2[10] = {0}; + uint16_t temp_msb = 0; + + /* Trim register value is read */ + rslt = bmm150_get_regs(BMM150_DIG_X1, trim_x1y1, 2, dev); + + if (rslt == BMM150_OK) + { + rslt = bmm150_get_regs(BMM150_DIG_Z4_LSB, trim_xyz_data, 4, dev); + + if (rslt == BMM150_OK) + { + rslt = bmm150_get_regs(BMM150_DIG_Z2_LSB, trim_xy1xy2, 10, dev); + + if (rslt == BMM150_OK) + { + /* Trim data which is read is updated + * in the device structure + */ + dev->trim_data.dig_x1 = (int8_t)trim_x1y1[0]; + dev->trim_data.dig_y1 = (int8_t)trim_x1y1[1]; + dev->trim_data.dig_x2 = (int8_t)trim_xyz_data[2]; + dev->trim_data.dig_y2 = (int8_t)trim_xyz_data[3]; + temp_msb = ((uint16_t)trim_xy1xy2[3]) << 8; + dev->trim_data.dig_z1 = (uint16_t)(temp_msb | trim_xy1xy2[2]); + temp_msb = ((uint16_t)trim_xy1xy2[1]) << 8; + dev->trim_data.dig_z2 = (int16_t)(temp_msb | trim_xy1xy2[0]); + temp_msb = ((uint16_t)trim_xy1xy2[7]) << 8; + dev->trim_data.dig_z3 = (int16_t)(temp_msb | trim_xy1xy2[6]); + temp_msb = ((uint16_t)trim_xyz_data[1]) << 8; + dev->trim_data.dig_z4 = (int16_t)(temp_msb | trim_xyz_data[0]); + dev->trim_data.dig_xy1 = trim_xy1xy2[9]; + dev->trim_data.dig_xy2 = (int8_t)trim_xy1xy2[8]; + temp_msb = ((uint16_t)(trim_xy1xy2[5] & 0x7F)) << 8; + dev->trim_data.dig_xyz1 = (uint16_t)(temp_msb | trim_xy1xy2[4]); + } + } + } + + return rslt; +} + +/*! + * @brief This internal API writes the op_mode value in the Opmode bits + * (bits 1 and 2) of 0x4C register. + */ +static int8_t write_op_mode(uint8_t op_mode, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Read the 0x4C register */ + rslt = bmm150_get_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + /* Set the op_mode value in Opmode bits of 0x4C */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_OP_MODE, op_mode); + rslt = bmm150_set_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API sets the device from suspend to sleep mode + * by setting the power control bit to '1' of 0x4B register + */ +static int8_t suspend_to_sleep_mode(struct bmm150_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + + /* Proceed if null check is fine */ + if (rslt == BMM150_OK) + { + if (dev->pwr_cntrl_bit == BMM150_POWER_CNTRL_DISABLE) + { + rslt = set_power_control_bit(BMM150_POWER_CNTRL_ENABLE, dev); + + /* Start-up time delay of 3ms */ + dev->delay_us(BMM150_START_UP_TIME, dev->intf_ptr); + } + } + + return rslt; +} + +/*! + * @brief This internal API sets the xy repetition value in the 0x51 register. + */ +static int8_t set_xy_rep(const struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t rep_xy; + + /* Set the xy repetition */ + rep_xy = settings->xy_rep; + rslt = bmm150_set_regs(BMM150_REG_REP_XY, &rep_xy, 1, dev); + + return rslt; +} + +/*! + * @brief This internal API sets the z repetition value in the 0x52 register. + */ +static int8_t set_z_rep(const struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t rep_z; + + /* Set the z repetition */ + rep_z = settings->z_rep; + rslt = bmm150_set_regs(BMM150_REG_REP_Z, &rep_z, 1, dev); + + return rslt; +} + +/*! + * @brief This internal API is used to set the output data rate of the sensor. + */ +static int8_t set_odr(const struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Read the 0x4C register */ + rslt = bmm150_get_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + /* Set the ODR value */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_ODR, settings->data_rate); + rslt = bmm150_set_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API sets the preset mode ODR and repetition settings. + */ +static int8_t set_odr_xyz_rep(const struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + + /* Set the ODR */ + rslt = set_odr(settings, dev); + + if (rslt == BMM150_OK) + { + /* Set the XY-repetitions number */ + rslt = set_xy_rep(settings, dev); + + if (rslt == BMM150_OK) + { + /* Set the Z-repetitions number */ + rslt = set_z_rep(settings, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable or disable the magnetic + * measurement of x,y,z axes based on the value of xyz_axes_control. + */ +static int8_t set_control_measurement_xyz(const struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + rslt = bmm150_get_regs(BMM150_REG_AXES_ENABLE, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + /* Set the axes to be enabled/disabled */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_CONTROL_MEASURE, settings->xyz_axes_control); + rslt = bmm150_set_regs(BMM150_REG_AXES_ENABLE, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to identify the settings which the user + * wants to modify in the sensor. + */ +static uint8_t are_settings_changed(uint16_t sub_settings, uint16_t desired_settings) +{ + uint8_t settings_changed; + + if (sub_settings & desired_settings) + { + /* User wants to modify this particular settings */ + settings_changed = BMM150_TRUE; + } + else + { + /* User don't want to modify this particular settings */ + settings_changed = BMM150_FALSE; + } + + return settings_changed; +} + +/*! + * @brief This API sets the ODR , measurement axes control , + * repetition values of xy,z. + */ +static int8_t mode_settings(uint16_t desired_settings, const struct bmm150_settings *settings, struct bmm150_dev *dev) +{ + int8_t rslt = BMM150_E_INVALID_CONFIG; + + if (desired_settings & BMM150_SEL_DATA_RATE) + { + /* Sets the ODR */ + rslt = set_odr(settings, dev); + } + + if (desired_settings & BMM150_SEL_CONTROL_MEASURE) + { + /* Enables/Disables the control measurement axes */ + rslt = set_control_measurement_xyz(settings, dev); + } + + if (desired_settings & BMM150_SEL_XY_REP) + { + /* Sets the XY repetition */ + rslt = set_xy_rep(settings, dev); + } + + if (desired_settings & BMM150_SEL_Z_REP) + { + /* Sets the Z repetition */ + rslt = set_z_rep(settings, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to parse and store the sensor + * settings in the device structure + */ +static void parse_setting(const uint8_t *reg_data, struct bmm150_settings *settings) +{ + /* Parse all the w/r registers and update the + * current sensor settings in the dev structure + */ + settings->z_rep = reg_data[7]; + settings->xy_rep = reg_data[6]; + settings->int_settings.high_threshold = reg_data[5]; + settings->int_settings.low_threshold = reg_data[4]; + settings->xyz_axes_control = BMM150_GET_BITS(reg_data[3], BMM150_CONTROL_MEASURE); + settings->int_settings.drdy_pin_en = BMM150_GET_BITS(reg_data[3], BMM150_DRDY_EN); + settings->int_settings.int_pin_en = BMM150_GET_BITS(reg_data[3], BMM150_INT_PIN_EN); + settings->int_settings.drdy_polarity = BMM150_GET_BITS(reg_data[3], BMM150_DRDY_POLARITY); + settings->int_settings.int_latch = BMM150_GET_BITS(reg_data[3], BMM150_INT_LATCH); + settings->int_settings.int_polarity = BMM150_GET_BITS_POS_0(reg_data[3], BMM150_INT_POLARITY); + settings->int_settings.data_overrun_en = BMM150_GET_BITS(reg_data[2], BMM150_DATA_OVERRUN_INT); + settings->int_settings.overflow_int_en = BMM150_GET_BITS(reg_data[2], BMM150_OVERFLOW_INT); + settings->int_settings.high_int_en = BMM150_GET_BITS(reg_data[2], BMM150_HIGH_THRESHOLD_INT); + settings->int_settings.low_int_en = BMM150_GET_BITS_POS_0(reg_data[2], BMM150_LOW_THRESHOLD_INT); + settings->data_rate = BMM150_GET_BITS(reg_data[1], BMM150_ODR); +} + +/*! + * @brief This API is used to enable the interrupts and map them to the + * corresponding interrupt pins and specify the pin characteristics like the + * polarity , latch settings for the interrupt pins. + */ +static int8_t interrupt_pin_settings(uint16_t desired_settings, + const struct bmm150_settings *settings, + struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + struct bmm150_int_ctrl_settings int_settings; + + rslt = bmm150_get_regs(BMM150_REG_AXES_ENABLE, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + int_settings = settings->int_settings; + if (desired_settings & BMM150_SEL_DRDY_PIN_EN) + { + /* Enables the Data ready interrupt and + * maps it to the DRDY pin of the sensor + */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_DRDY_EN, int_settings.drdy_pin_en); + } + + if (desired_settings & BMM150_SEL_INT_PIN_EN) + { + /* Sets interrupt pin enable */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_INT_PIN_EN, int_settings.int_pin_en); + } + + if (desired_settings & BMM150_SEL_DRDY_POLARITY) + { + /* Sets Data ready pin's polarity */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_DRDY_POLARITY, int_settings.drdy_polarity); + } + + if (desired_settings & BMM150_SEL_INT_LATCH) + { + /* Sets Interrupt in latched or non-latched mode */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_INT_LATCH, int_settings.int_latch); + } + + if (desired_settings & BMM150_SEL_INT_POLARITY) + { + /* Sets Interrupt pin's polarity */ + reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_INT_POLARITY, int_settings.int_polarity); + } + + /* Set the interrupt configurations in the 0x4E register */ + rslt = bmm150_set_regs(BMM150_REG_AXES_ENABLE, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API is used to enable data overrun , overflow interrupts and + * enable/disable high/low threshold interrupts for x,y,z axis based on the + * threshold values set by the user in the High threshold (0x50) and + * Low threshold (0x4F) registers. + */ +static int8_t interrupt_config(uint16_t desired_settings, const struct bmm150_settings *settings, + struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + struct bmm150_int_ctrl_settings int_settings; + + rslt = bmm150_get_regs(BMM150_REG_INT_CONFIG, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + int_settings = settings->int_settings; + if (desired_settings & BMM150_SEL_DATA_OVERRUN_INT) + { + /* Sets Data overrun interrupt */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_DATA_OVERRUN_INT, int_settings.data_overrun_en); + } + + if (desired_settings & BMM150_SEL_OVERFLOW_INT) + { + /* Sets Data overflow interrupt */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_OVERFLOW_INT, int_settings.overflow_int_en); + } + + if (desired_settings & BMM150_SEL_HIGH_THRESHOLD_INT) + { + /* Sets high threshold interrupt */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_HIGH_THRESHOLD_INT, int_settings.high_int_en); + } + + if (desired_settings & BMM150_SEL_LOW_THRESHOLD_INT) + { + /* Sets low threshold interrupt */ + reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_LOW_THRESHOLD_INT, int_settings.low_int_en); + } + + /* Set the interrupt configurations in the 0x4D register */ + rslt = bmm150_set_regs(BMM150_REG_INT_CONFIG, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API is used to write the user specified High/Low threshold value + * as a reference to generate the high/low threshold interrupt. + */ +static int8_t interrupt_threshold_settings(uint16_t desired_settings, + const struct bmm150_settings *settings, + struct bmm150_dev *dev) +{ + int8_t rslt = BMM150_E_INVALID_CONFIG; + uint8_t reg_data; + + if (desired_settings & BMM150_SEL_LOW_THRESHOLD_SETTING) + { + /* Sets the Low threshold value to trigger interrupt */ + reg_data = settings->int_settings.low_threshold; + rslt = bmm150_set_regs(BMM150_REG_LOW_THRESHOLD, ®_data, 1, dev); + } + + if (desired_settings & BMM150_SEL_HIGH_THRESHOLD_SETTING) + { + /* Sets the High threshold value to trigger interrupt */ + reg_data = settings->int_settings.high_threshold; + rslt = bmm150_set_regs(BMM150_REG_HIGH_THRESHOLD, ®_data, 1, dev); + } + + return rslt; +} + +#ifdef BMM150_USE_FLOATING_POINT + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer x axis data(micro-tesla) in float. + */ +static float compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev) +{ + float retval = 0; + float process_comp_x0; + float process_comp_x1; + float process_comp_x2; + float process_comp_x3; + float process_comp_x4; + + /* Overflow condition check */ + if ((mag_data_x != BMM150_OVERFLOW_ADCVAL_XYAXES_FLIP) && (data_rhall != 0) && (dev->trim_data.dig_xyz1 != 0)) + { + /* Processing compensation equations */ + process_comp_x0 = (((float)dev->trim_data.dig_xyz1) * 16384.0f / data_rhall); + retval = (process_comp_x0 - 16384.0f); + process_comp_x1 = ((float)dev->trim_data.dig_xy2) * (retval * retval / 268435456.0f); + process_comp_x2 = process_comp_x1 + retval * ((float)dev->trim_data.dig_xy1) / 16384.0f; + process_comp_x3 = ((float)dev->trim_data.dig_x2) + 160.0f; + process_comp_x4 = mag_data_x * ((process_comp_x2 + 256.0f) * process_comp_x3); + retval = ((process_comp_x4 / 8192.0f) + (((float)dev->trim_data.dig_x1) * 8.0f)) / 16.0f; + } + else + { + /* Overflow, set output to 0.0f */ + retval = BMM150_OVERFLOW_OUTPUT_FLOAT; + } + + return retval; +} + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer y axis data(micro-tesla) in float. + */ +static float compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev) +{ + float retval = 0; + float process_comp_y0; + float process_comp_y1; + float process_comp_y2; + float process_comp_y3; + float process_comp_y4; + + /* Overflow condition check */ + if ((mag_data_y != BMM150_OVERFLOW_ADCVAL_XYAXES_FLIP) && (data_rhall != 0) && (dev->trim_data.dig_xyz1 != 0)) + { + /* Processing compensation equations */ + process_comp_y0 = ((float)dev->trim_data.dig_xyz1) * 16384.0f / data_rhall; + retval = process_comp_y0 - 16384.0f; + process_comp_y1 = ((float)dev->trim_data.dig_xy2) * (retval * retval / 268435456.0f); + process_comp_y2 = process_comp_y1 + retval * ((float)dev->trim_data.dig_xy1) / 16384.0f; + process_comp_y3 = ((float)dev->trim_data.dig_y2) + 160.0f; + process_comp_y4 = mag_data_y * (((process_comp_y2) + 256.0f) * process_comp_y3); + retval = ((process_comp_y4 / 8192.0f) + (((float)dev->trim_data.dig_y1) * 8.0f)) / 16.0f; + } + else + { + /* Overflow, set output to 0.0f */ + retval = BMM150_OVERFLOW_OUTPUT_FLOAT; + } + + return retval; +} + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer z axis data(micro-tesla) in float. + */ +static float compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev) +{ + float retval = 0; + float process_comp_z0; + float process_comp_z1; + float process_comp_z2; + float process_comp_z3; + float process_comp_z4; + float process_comp_z5; + + /* Overflow condition check */ + if ((mag_data_z != BMM150_OVERFLOW_ADCVAL_ZAXIS_HALL) && (dev->trim_data.dig_z2 != 0) && + (dev->trim_data.dig_z1 != 0) && (dev->trim_data.dig_xyz1 != 0) && (data_rhall != 0)) + { + /* Processing compensation equations */ + process_comp_z0 = ((float)mag_data_z) - ((float)dev->trim_data.dig_z4); + process_comp_z1 = ((float)data_rhall) - ((float)dev->trim_data.dig_xyz1); + process_comp_z2 = (((float)dev->trim_data.dig_z3) * process_comp_z1); + process_comp_z3 = ((float)dev->trim_data.dig_z1) * ((float)data_rhall) / 32768.0f; + process_comp_z4 = ((float)dev->trim_data.dig_z2) + process_comp_z3; + process_comp_z5 = (process_comp_z0 * 131072.0f) - process_comp_z2; + retval = (process_comp_z5 / ((process_comp_z4)*4.0f)) / 16.0f; + } + else + { + /* Overflow, set output to 0.0f */ + retval = BMM150_OVERFLOW_OUTPUT_FLOAT; + } + + return retval; +} + +#else + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer X axis data(micro-tesla) in int16_t. + */ +static int16_t compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev) +{ + int16_t retval; + uint16_t process_comp_x0 = 0; + int32_t process_comp_x1; + uint16_t process_comp_x2; + int32_t process_comp_x3; + int32_t process_comp_x4; + int32_t process_comp_x5; + int32_t process_comp_x6; + int32_t process_comp_x7; + int32_t process_comp_x8; + int32_t process_comp_x9; + int32_t process_comp_x10; + + /* Overflow condition check */ + if (mag_data_x != BMM150_OVERFLOW_ADCVAL_XYAXES_FLIP) + { + if (data_rhall != 0) + { + /* Availability of valid data */ + process_comp_x0 = data_rhall; + } + else if (dev->trim_data.dig_xyz1 != 0) + { + process_comp_x0 = dev->trim_data.dig_xyz1; + } + else + { + process_comp_x0 = 0; + } + + if (process_comp_x0 != 0) + { + /* Processing compensation equations */ + process_comp_x1 = ((int32_t)dev->trim_data.dig_xyz1) * 16384; + process_comp_x2 = ((uint16_t)(process_comp_x1 / process_comp_x0)) - ((uint16_t)0x4000); + retval = ((int16_t)process_comp_x2); + process_comp_x3 = (((int32_t)retval) * ((int32_t)retval)); + process_comp_x4 = (((int32_t)dev->trim_data.dig_xy2) * (process_comp_x3 / 128)); + process_comp_x5 = (int32_t)(((int16_t)dev->trim_data.dig_xy1) * 128); + process_comp_x6 = ((int32_t)retval) * process_comp_x5; + process_comp_x7 = (((process_comp_x4 + process_comp_x6) / 512) + ((int32_t)0x100000)); + process_comp_x8 = ((int32_t)(((int16_t)dev->trim_data.dig_x2) + ((int16_t)0xA0))); + process_comp_x9 = ((process_comp_x7 * process_comp_x8) / 4096); + process_comp_x10 = ((int32_t)mag_data_x) * process_comp_x9; + retval = ((int16_t)(process_comp_x10 / 8192)); + retval = (retval + (((int16_t)dev->trim_data.dig_x1) * 8)) / 16; + } + else + { + retval = BMM150_OVERFLOW_OUTPUT; + } + } + else + { + /* Overflow condition */ + retval = BMM150_OVERFLOW_OUTPUT; + } + + return retval; +} + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer Y axis data(micro-tesla) in int16_t. + */ +static int16_t compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev) +{ + int16_t retval; + uint16_t process_comp_y0 = 0; + int32_t process_comp_y1; + uint16_t process_comp_y2; + int32_t process_comp_y3; + int32_t process_comp_y4; + int32_t process_comp_y5; + int32_t process_comp_y6; + int32_t process_comp_y7; + int32_t process_comp_y8; + int32_t process_comp_y9; + + /* Overflow condition check */ + if (mag_data_y != BMM150_OVERFLOW_ADCVAL_XYAXES_FLIP) + { + if (data_rhall != 0) + { + /* Availability of valid data */ + process_comp_y0 = data_rhall; + } + else if (dev->trim_data.dig_xyz1 != 0) + { + process_comp_y0 = dev->trim_data.dig_xyz1; + } + else + { + process_comp_y0 = 0; + } + + if (process_comp_y0 != 0) + { + /* Processing compensation equations */ + process_comp_y1 = (((int32_t)dev->trim_data.dig_xyz1) * 16384) / process_comp_y0; + process_comp_y2 = ((uint16_t)process_comp_y1) - ((uint16_t)0x4000); + retval = ((int16_t)process_comp_y2); + process_comp_y3 = ((int32_t)retval) * ((int32_t)retval); + process_comp_y4 = ((int32_t)dev->trim_data.dig_xy2) * (process_comp_y3 / 128); + process_comp_y5 = ((int32_t)(((int16_t)dev->trim_data.dig_xy1) * 128)); + process_comp_y6 = ((process_comp_y4 + (((int32_t)retval) * process_comp_y5)) / 512); + process_comp_y7 = ((int32_t)(((int16_t)dev->trim_data.dig_y2) + ((int16_t)0xA0))); + process_comp_y8 = (((process_comp_y6 + ((int32_t)0x100000)) * process_comp_y7) / 4096); + process_comp_y9 = (((int32_t)mag_data_y) * process_comp_y8); + retval = (int16_t)(process_comp_y9 / 8192); + retval = (retval + (((int16_t)dev->trim_data.dig_y1) * 8)) / 16; + } + else + { + retval = BMM150_OVERFLOW_OUTPUT; + } + } + else + { + /* Overflow condition */ + retval = BMM150_OVERFLOW_OUTPUT; + } + + return retval; +} + +/*! + * @brief This internal API is used to obtain the compensated + * magnetometer Z axis data(micro-tesla) in int16_t. + */ +static int16_t compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev) +{ + int32_t retval; + int16_t process_comp_z0; + int32_t process_comp_z1; + int32_t process_comp_z2; + int32_t process_comp_z3; + int16_t process_comp_z4; + + if (mag_data_z != BMM150_OVERFLOW_ADCVAL_ZAXIS_HALL) + { + if ((dev->trim_data.dig_z2 != 0) && (dev->trim_data.dig_z1 != 0) && (data_rhall != 0) && + (dev->trim_data.dig_xyz1 != 0)) + { + /*Processing compensation equations */ + process_comp_z0 = ((int16_t)data_rhall) - ((int16_t)dev->trim_data.dig_xyz1); + process_comp_z1 = (((int32_t)dev->trim_data.dig_z3) * ((int32_t)(process_comp_z0))) / 4; + process_comp_z2 = (((int32_t)(mag_data_z - dev->trim_data.dig_z4)) * 32768); + process_comp_z3 = ((int32_t)dev->trim_data.dig_z1) * (((int16_t)data_rhall) * 2); + process_comp_z4 = (int16_t)((process_comp_z3 + (32768)) / 65536); + retval = ((process_comp_z2 - process_comp_z1) / (dev->trim_data.dig_z2 + process_comp_z4)); + + /* Saturate result to +/- 2 micro-tesla */ + if (retval > BMM150_POSITIVE_SATURATION_Z) + { + retval = BMM150_POSITIVE_SATURATION_Z; + } + else if (retval < BMM150_NEGATIVE_SATURATION_Z) + { + retval = BMM150_NEGATIVE_SATURATION_Z; + } + + /* Conversion of LSB to micro-tesla */ + retval = retval / 16; + } + else + { + retval = BMM150_OVERFLOW_OUTPUT; + } + } + else + { + /* Overflow condition */ + retval = BMM150_OVERFLOW_OUTPUT; + } + + return (int16_t)retval; +} + +#endif + +/*! + * @brief This internal API is used to perform the normal self test + * of the sensor and return the self test result as return value + */ +static int8_t perform_normal_self_test(struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t self_test_bit; + + /* Triggers the start of normal self test */ + rslt = enable_normal_self_test(&self_test_bit, dev); + + /* Check for self test completion status */ + if ((rslt == BMM150_OK) && (self_test_bit == 0)) + { + /* Validates the self test results for all 3 axes */ + rslt = validate_normal_self_test(dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable the normal self test by setting + * the Self Test bit (bit0) of the 0x4C register, + * which triggers the start of self test + */ +static int8_t enable_normal_self_test(uint8_t *self_test_enable, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + uint8_t self_test_val; + + /* Read the data from register 0x4C */ + rslt = bmm150_get_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + /* Set the Self Test bit(bit0) of the 0x4C register */ + self_test_val = 1; + reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_SELF_TEST, self_test_val); + + /* Write the data to 0x4C register to trigger self test */ + rslt = bmm150_set_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + dev->delay_us(BMM150_DELAY_NORMAL_SELF_TEST, dev->intf_ptr); + + if (rslt == BMM150_OK) + { + /* Read the data from register 0x4C */ + rslt = bmm150_get_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + + /* Self Test bit(bit0) is stored in self_test_enable, + * It will be reset to zero after the self test is over + */ + *self_test_enable = BMM150_GET_BITS_POS_0(reg_data, BMM150_SELF_TEST); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to validate the results of normal self test + * by using the self test status available in the bit0 of registers 0x42,0x44 + * and 0x46. + */ +static int8_t validate_normal_self_test(struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t status; + uint8_t self_test_rslt[5]; + + /* Read the data from register 0x42 to 0x46 */ + rslt = bmm150_get_regs(BMM150_REG_DATA_X_LSB, self_test_rslt, BMM150_LEN_SELF_TEST, dev); + + if (rslt == BMM150_OK) + { + /* Parse and get the self test status bits */ + /* X-Self-Test (bit0) of 0x42 register is stored */ + self_test_rslt[0] = BMM150_GET_BITS_POS_0(self_test_rslt[0], BMM150_SELF_TEST); + + /* Y-Self-Test (bit0) of 0x44 register is stored */ + self_test_rslt[2] = BMM150_GET_BITS_POS_0(self_test_rslt[2], BMM150_SELF_TEST); + + /* Z-Self-Test (bit0) of 0x46 register is stored */ + self_test_rslt[4] = BMM150_GET_BITS_POS_0(self_test_rslt[4], BMM150_SELF_TEST); + + /* Combine the self test status and store it in the first + * 3 bits of the status variable for processing + */ + status = (uint8_t)((self_test_rslt[4] << 2) | (self_test_rslt[2] << 1) | self_test_rslt[0]); + + /* Validate status and store Self test result in "rslt" */ + if (status == BMM150_SELF_TEST_STATUS_SUCCESS) + { + /* Self test is success when all status bits are set */ + rslt = BMM150_OK; + } + else + { + if (status == BMM150_SELF_TEST_STATUS_XYZ_FAIL) + { + /* Self test - all axis fail condition */ + rslt = BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL; + } + else + { + /* Self test - some axis fail condition */ + rslt = (int8_t)status; + } + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to perform advanced self test for Z axis + */ +static int8_t perform_adv_self_test(struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t self_test_current; + int16_t positive_data_z; + int16_t negative_data_z; + + /* Set the desired power mode ,axes control and repetition settings */ + rslt = adv_self_test_settings(dev); + + if (rslt == BMM150_OK) + { + /* Measure the Z axes data with positive self-test current */ + self_test_current = BMM150_ENABLE_POSITIVE_CURRENT; + rslt = adv_self_test_measurement(self_test_current, &positive_data_z, dev); + + if (rslt == BMM150_OK) + { + /* Measure the Z axes data with + * negative self-test current + */ + self_test_current = BMM150_ENABLE_NEGATIVE_CURRENT; + rslt = adv_self_test_measurement(self_test_current, &negative_data_z, dev); + + if (rslt == BMM150_OK) + { + /* Disable self-test current */ + self_test_current = BMM150_DISABLE_SELF_TEST_CURRENT; + rslt = set_adv_self_test_current(self_test_current, dev); + + if (rslt == BMM150_OK) + { + /* Validate the advanced self test */ + rslt = validate_adv_self_test(positive_data_z, negative_data_z); + } + } + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the desired power mode , + * axes control and repetition settings for advanced self test + */ +static int8_t adv_self_test_settings(struct bmm150_dev *dev) +{ + int8_t rslt; + struct bmm150_settings settings; + + /* Set the power mode as sleep mode */ + settings.pwr_mode = BMM150_POWERMODE_SLEEP; + rslt = bmm150_set_op_mode(&settings, dev); + + if (rslt == BMM150_OK) + { + /* Disable XY-axis measurement */ + settings.xyz_axes_control = BMM150_DISABLE_XY_AXIS; + rslt = set_control_measurement_xyz(&settings, dev); + + if (rslt == BMM150_OK) + { + /* Repetition value is set as 0x04 */ + settings.z_rep = BMM150_SELF_TEST_REP_Z; + rslt = set_z_rep(&settings, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the positive or negative value of + * self-test current and obtain the corresponding magnetometer z axis data + */ +static int8_t adv_self_test_measurement(uint8_t self_test_current, int16_t *data_z, struct bmm150_dev *dev) +{ + int8_t rslt; + struct bmm150_settings settings; + struct bmm150_mag_data mag_data; + + /* Set the advanced self test current as positive or + * negative based on the value of parameter "self_test_current" + */ + rslt = set_adv_self_test_current(self_test_current, dev); + + if (rslt == BMM150_OK) + { + /* Set the device in forced mode */ + settings.pwr_mode = BMM150_POWERMODE_FORCED; + rslt = bmm150_set_op_mode(&settings, dev); + + /* Delay to ensure measurement is complete */ + dev->delay_us(BMM150_DELAY_ADV_SELF_TEST, dev->intf_ptr); + + if (rslt == BMM150_OK) + { + /* Read Mag data and store the value of Z axis data */ + rslt = bmm150_read_mag_data(&mag_data, dev); + + if (rslt == BMM150_OK) + { + /* Mag Z axis data is stored */ + *data_z = mag_data.z; + } + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to get the difference between the + * Z axis mag data obtained by positive and negative self-test current + * and validate whether the advanced self test is done successfully or not. + */ +static int8_t validate_adv_self_test(int16_t positive_data_z, int16_t negative_data_z) +{ + int32_t adv_self_test_rslt; + int8_t rslt; + + /* Advanced self test difference between the Z axis mag data + * obtained by the positive and negative self-test current + */ + adv_self_test_rslt = positive_data_z - negative_data_z; + + /* Advanced self test validation */ + /*Value of adv_self_test_rslt should be in between 180-240 micro-tesla */ + if ((adv_self_test_rslt > 180) && (adv_self_test_rslt < 240)) + { + /* Advanced self test success */ + rslt = BMM150_OK; + } + else + { + /* Advanced self test fail */ + rslt = BMM150_W_ADV_SELF_TEST_FAIL; + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the self test current value in + * the Adv. ST bits (bit6 and bit7) of 0x4C register + */ +static int8_t set_adv_self_test_current(uint8_t self_test_current, struct bmm150_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Read the 0x4C register */ + rslt = bmm150_get_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + + if (rslt == BMM150_OK) + { + /* Set the self test current value in the Adv. ST bits + * (bit6 and bit7) of 0x4c register + */ + reg_data = BMM150_SET_BITS(reg_data, BMM150_ADV_SELF_TEST, self_test_current); + rslt = bmm150_set_regs(BMM150_REG_OP_MODE, ®_data, 1, dev); + } + + return rslt; +} diff --git a/lib/SensorLib/src/bosch/BMM150/bmm150.h b/lib/SensorLib/src/bosch/BMM150/bmm150.h new file mode 100644 index 0000000..01f3aab --- /dev/null +++ b/lib/SensorLib/src/bosch/BMM150/bmm150.h @@ -0,0 +1,479 @@ +/** +* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bmm150.h +* @date 2020-06-03 +* @version v2.0.0 +* +*/ + +/*! + * @defgroup bmm150 BMM150 + */ + +#ifndef _BMM150_H +#define _BMM150_H + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +/********************************************************************/ +/* header files */ + +#include "bmm150_defs.h" + +/********************************************************************/ +/* (extern) variable declarations */ +/********************************************************************/ +/* function prototype declarations */ + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiInit Initialization + * @brief Initialize the sensor and device structure + */ + +/*! + * \ingroup bmm150ApiInit + * \page bmm150_api_bmm150_init bmm150_init + * \code + * int8_t bmm150_init(struct bmm150_dev *dev); + * \endcode + * @details This API is the entry point, Call this API before using other APIs. + * This API reads the chip-id of the sensor which is the first step to + * verify the sensor and also it configures the read mechanism of SPI and + * I2C interface. + * + * @param[in,out] dev : Structure instance of bmm150_dev + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_init(struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiRegs Registers + * @brief Read / Write data to the given register address of the sensor + */ + +/*! + * \ingroup bmm150ApiRegs + * \page bmm150_api_bmm150_set_regs bmm150_set_regs + * \code + * int8_t bmm150_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev); + * \endcode + * @details This API writes the given data to the register address + * of the sensor. + * + * @param[in] reg_addr : Register address from where the data to be written. + * @param[in] reg_data : Pointer to data buffer which is to be written + * in the reg_addr of sensor. + * @param[in] len : No of bytes of data to write.. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev); + +/*! + * \ingroup bmm150ApiRegs + * \page bmm150_api_bmm150_get_regs bmm150_get_regs + * \code + * int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev) + * \endcode + * @details This API reads the data from the given register address of sensor. + * + * @param[in] reg_addr : Register address from where the data to be read + * @param[out] reg_data : Pointer to data buffer to store the read data. + * @param[in] len : No of bytes of data to be read. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiSoftreset Soft reset + * @brief Perform soft reset of the sensor + */ + +/*! + * \ingroup bmm150ApiSoftreset + * \page bmm150_api_bmm150_soft_reset bmm150_soft_reset + * \code + * int8_t bmm150_soft_reset(struct bmm150_dev *dev); + * \endcode + * @details This API is used to perform soft-reset of the sensor + * where all the registers are reset to their default values except 0x4B. + * + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_soft_reset(struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiPowermode Power mode + * @brief Set / Get power mode of the sensor + */ + +/*! + * \ingroup bmm150ApiPowermode + * \page bmm150_api_bmm150_set_op_mode bmm150_set_op_mode + * \code + * int8_t bmm150_set_op_mode(const struct bmm150_settings *settings, struct bmm150_dev *dev); + * \endcode + * @details This API is used to set the power mode of the sensor. + * + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + *@verbatim + * settings->pwr_mode | Power mode + * ------------------------|----------------------- + * 0x00 | BMM150_POWERMODE_NORMAL + * 0x01 | BMM150_POWERMODE_FORCED + * 0x03 | BMM150_POWERMODE_SLEEP + * 0x04 | BMM150_POWERMODE_SUSPEND + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_set_op_mode(const struct bmm150_settings *settings, struct bmm150_dev *dev); + +/*! + * \ingroup bmm150ApiPowermode + * \page bmm150_api_bmm150_get_op_mode bmm150_get_op_mode + * \code + * int8_t bmm150_get_op_mode(uint8_t *op_mode, struct bmm150_dev *dev); + * \endcode + * @details This API is used to get the power mode of the sensor. + * + * @param[out] op_mode : power mode of the sensor. + * @param[in] dev : Structure instance of bmm150_dev. + * + *@verbatim + * op_mode | Power mode + * -------------|----------------------- + * 0x00 | BMM150_POWERMODE_NORMAL + * 0x01 | BMM150_POWERMODE_FORCED + * 0x03 | BMM150_POWERMODE_SLEEP + * 0x04 | BMM150_POWERMODE_SUSPEND + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_get_op_mode(uint8_t *op_mode, struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiPresetmode Preset mode + * @brief Set preset mode of the sensor + */ + +/*! + * \ingroup bmm150ApiPresetmode + * \page bmm150_api_bmm150_set_presetmode bmm150_set_presetmode + * \code + * int8_t bmm150_set_presetmode(struct bmm150_settings *settings, struct bmm150_dev *dev); + * \endcode + * @details This API is used to set the preset mode of the sensor. + * + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + *@verbatim + * settings->preset_mode | Preset mode + * ---------------------------|---------------------------------- + * 0x01 | BMM150_PRESETMODE_LOWPOWER + * 0x02 | BMM150_PRESETMODE_REGULAR + * 0x03 | BMM150_PRESETMODE_HIGHACCURACY + * 0x04 | BMM150_PRESETMODE_ENHANCED + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_set_presetmode(struct bmm150_settings *settings, struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiSensorSettings Sensor Settings + * @brief Set / Get sensor settings of the sensor + */ + +/*! + * \ingroup bmm150ApiSensorSettings + * \page bmm150_api_bmm150_set_sensor_settings bmm150_set_sensor_settings + * \code + * int8_t bmm150_set_sensor_settings(uint16_t desired_settings, const struct bmm150_settings *settings, struct bmm150_dev *dev); + * \endcode + * @details This API sets the sensor settings based on the desired_settings + * and the dev structure configuration + * + * @param[in] desired_settings : Selection macro for selecting the setting. + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @note Assign the sensor setting macros (multiple macros can be + * set by doing a bitwise-OR operation) to the desired_settings parameter + * of this API to perform the corresponding setting. + * + * @note threshold interrupt for each axes are set by using bitwise AND + * operation of the following macros + * - BMM150_THRESHOLD_X + * - BMM150_THRESHOLD_Y + * - BMM150_THRESHOLD_Z + * + *@verbatim + * desired_settings | Selected sensor setting macros + * -------------------|-------------------------------- + * 0x0001 | BMM150_SEL_DATA_RATE + * 0x0002 | BMM150_SEL_CONTROL_MEASURE + * 0x0004 | BMM150_SEL_XY_REP + * 0x0008 | BMM150_SEL_Z_REP + * 0x0010 | BMM150_SEL_DRDY_PIN_EN + * 0x0020 | BMM150_SEL_INT_PIN_EN + * 0x0040 | BMM150_SEL_DRDY_POLARITY + * 0x0080 | BMM150_SEL_INT_LATCH + * 0x0100 | BMM150_SEL_INT_POLARITY + * 0x0200 | BMM150_SEL_DATA_OVERRUN_INT + * 0x0400 | BMM150_SEL_OVERFLOW_INT + * 0x0800 | BMM150_SEL_HIGH_THRESHOLD_INT + * 0x1000 | BMM150_SEL_LOW_THRESHOLD_INT + * 0x2000 | BMM150_SEL_LOW_THRESHOLD_SETTING + * 0x4000 | BMM150_SEL_HIGH_THRESHOLD_SETTING + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_set_sensor_settings(uint16_t desired_settings, + const struct bmm150_settings *settings, + struct bmm150_dev *dev); + +/*! + * \ingroup bmm150ApiSensorSettings + * \page bmm150_api_bmm150_get_sensor_settings bmm150_get_sensor_settings + * \code + * int8_t bmm150_get_sensor_settings(struct bmm150_settings *settings, struct bmm150_dev *dev); + * \endcode + * @details This API gets all the sensor settings and updates the dev structure + * + * @param[in] settings : Structure instance of bmm150_settings. + * @param[in] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_get_sensor_settings(struct bmm150_settings *settings, struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiMagData Read magnetometer data + * @brief Read magnetometer data + */ + +/*! + * \ingroup bmm150ApiMagData + * \page bmm150_api_bmm150_read_mag_data bmm150_read_mag_data + * \code + * int8_t bbmm150_read_mag_data(struct bmm150_mag_data *mag_data, struct bmm150_dev *dev); + * \endcode + * @details This API reads the magnetometer data from registers 0x42 to 0x49 + * and updates the dev structure with compensated mag data in micro-tesla + * + * @param[in] mag_data : Structure instance of bmm150_mag_data. + * @param[in,out] dev : Structure instance of bmm150_dev. + * + * @note The output mag data can be obtained either in int16_t or float format + * using this API. + * @note Enable the macro "BMM150_USE_FLOATING_POINT" in the bmm150_defs.h + * file and call this API to get the mag data in float, + * disable this macro to get the mag data in int16_t format + * + *@verbatim + * Mag data output(micro-tesla) | Mag data in dev structure(int16_t/float) + * --------------------------------|------------------------------------------ + * X-axis data | mag_data->x + * Y-axis data | mag_data->y + * Z-axis data | mag_data->z + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_read_mag_data(struct bmm150_mag_data *mag_data, struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiSelftest Self test + * @brief Perform self test + */ + +/*! + * \ingroup bmm150ApiSelftest + * \page bmm150_api_bmm150_perform_self_test bmm150_perform_self_test + * \code + * int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev); + * \endcode + * @details This API is used to perform the complete self test + * (both normal and advanced) for the BMM150 sensor + * + * @param[in] self_test_mode : The type of self test to be performed + * @param[in] dev : Structure instance of bmm150_dev. + * + *@verbatim + * self_test_mode | Self test enabled + * --------------------|-------------------------- + * 0 | BMM150_SELF_TEST_NORMAL + * 1 | BMM150_SELF_TEST_ADVANCED + *@endverbatim + * + * @note The return value of this API gives us the result of self test. + * + * @note Performing advanced self test does soft reset of the sensor, User can + * set the desired settings after performing the advanced self test. + * + * @return Result of API execution status and self test result. + * @retval 0 BMM150_OK + * @retval 1 BMM150_W_NORMAL_SELF_TEST_YZ_FAIL + * @retval 2 BMM150_W_NORMAL_SELF_TEST_XZ_FAIL + * @retval 3 BMM150_W_NORMAL_SELF_TEST_Z_FAIL + * @retval 4 BMM150_W_NORMAL_SELF_TEST_XY_FAIL + * @retval 5 BMM150_W_NORMAL_SELF_TEST_Y_FAIL + * @retval 6 BMM150_W_NORMAL_SELF_TEST_X_FAIL + * @retval 7 BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL + * @retval 8 BMM150_W_ADV_SELF_TEST_FAIL + */ +int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiInt Interrupt status + * @brief Obtain interrupt staus flags + */ + +/*! + * \ingroup bmm150ApiInt + * \page bmm150_api_bmm150_get_interrupt_status bmm150_get_interrupt_status + * \code + * int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev); + * \endcode + * @details This API obtains the status flags of all interrupt + * which is used to check for the assertion of interrupts + * + * @param[in,out] dev : Structure instance of bmm150_dev. + * + * @note The status flags of all the interrupts are stored in the + * dev->int_status. + * + * @note The value of dev->int_status is performed a bitwise AND operation + * with predefined interrupt status macros to find the interrupt status + * which is either set or reset. + * + * Ex. + * if (dev->int_status & BMM150_INT_ASSERTED_DRDY) + * { + * Occurrence of data ready interrupt + * } else { + * No interrupt occurred + * } + * + * @return Result of API execution status and self test result. + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev); + +/** + * \ingroup bmm150 + * \defgroup bmm150ApiAux Compensate magnetometer data + * @brief Compensation of magnetometer data + */ + +/*! + * \ingroup bmm150ApiAux + * \page bmm150_api_bmm150_aux_mag_data bmm150_aux_mag_data + * \code + * int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_mag_data *mag_data, const struct bmm150_dev *dev); + * \endcode + * @details This API is used to compensate the raw mag data + * + * @param[in] aux_data : Raw mag data obtained from BMI160 registers + * @param[in] mag_data : Structure instance of bmm150_mag_data. + * @param[in,out] dev : Structure instance of bmm150_dev. + * + * @return Result of API execution status and self test result. + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_mag_data *mag_data, const struct bmm150_dev *dev); + +#ifdef __cplusplus +} +#endif /* End of CPP guard */ + +#endif /* _BMM150_H */ diff --git a/lib/SensorLib/src/bosch/BMM150/bmm150_defs.h b/lib/SensorLib/src/bosch/BMM150/bmm150_defs.h new file mode 100644 index 0000000..897edb9 --- /dev/null +++ b/lib/SensorLib/src/bosch/BMM150/bmm150_defs.h @@ -0,0 +1,643 @@ +/** +* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bmm150_defs.h +* @date 2020-06-03 +* @version v2.0.0 +* +*/ + +/*! \file bmm150_defs.h */ + +#ifndef _BMM150_DEFS_H +#define _BMM150_DEFS_H + +/******************************************************************************/ +/*! @name Header includes */ +/******************************************************************************/ +#ifdef __KERNEL__ +#include +#else +#include +#include +#endif + +/******************************************************************************/ +/*! @name Common macros */ +/******************************************************************************/ +#ifdef __KERNEL__ +#if (LONG_MAX) > 0x7fffffff +#define __have_long64 1 +#elif (LONG_MAX) == 0x7fffffff +#define __have_long32 1 +#endif +#endif + +#if !defined(UINT8_C) +#define INT8_C(x) x +#if (INT_MAX) > 0x7f +#define UINT8_C(x) x +#else +#define UINT8_C(x) x##U +#endif +#endif + +#if !defined(UINT16_C) +#define INT16_C(x) x +#if (INT_MAX) > 0x7fff +#define UINT16_C(x) x +#else +#define UINT16_C(x) x##U +#endif +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#if __have_long32 +#define INT32_C(x) x##L +#define UINT32_C(x) x##UL +#else +#define INT32_C(x) x +#define UINT32_C(x) x##U +#endif +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#if __have_long64 +#define INT64_C(x) x##L +#define UINT64_C(x) x##UL +#else +#define INT64_C(x) x##LL +#define UINT64_C(x) x##ULL +#endif +#endif + +/*! @name C standard macros */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +/******************************************************************************/ +/*! @name Compiler switch macros Definitions */ +/******************************************************************************/ +#ifndef BMM150_USE_FLOATING_POINT /*< Check if floating point (using BMM150_USE_FLOATING_POINT) is enabled */ +#ifndef BMM150_USE_FIXED_POINT /*< If floating point is not enabled then enable BMM150_USE_FIXED_POINT */ +#define BMM150_USE_FIXED_POINT +#endif +#endif + +/******************************************************************************/ +/*! @name General Macro Definitions */ +/******************************************************************************/ +/*! @name API success code */ +#define BMM150_OK INT8_C(0) + +/*! @name To define TRUE or FALSE */ +#define BMM150_TRUE UINT8_C(1) +#define BMM150_FALSE UINT8_C(0) + +/*! @name API error codes */ +#define BMM150_E_NULL_PTR INT8_C(-1) +#define BMM150_E_DEV_NOT_FOUND INT8_C(-2) +#define BMM150_E_INVALID_CONFIG INT8_C(-3) +#define BMM150_E_COM_FAIL INT8_C(-4) + +/*! @name API warning codes */ +#define BMM150_W_NORMAL_SELF_TEST_YZ_FAIL INT8_C(1) +#define BMM150_W_NORMAL_SELF_TEST_XZ_FAIL INT8_C(2) +#define BMM150_W_NORMAL_SELF_TEST_Z_FAIL INT8_C(3) +#define BMM150_W_NORMAL_SELF_TEST_XY_FAIL INT8_C(4) +#define BMM150_W_NORMAL_SELF_TEST_Y_FAIL INT8_C(5) +#define BMM150_W_NORMAL_SELF_TEST_X_FAIL INT8_C(6) +#define BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL INT8_C(7) +#define BMM150_W_ADV_SELF_TEST_FAIL INT8_C(8) + +/*! @name CHIP ID & SOFT RESET VALUES */ +#define BMM150_CHIP_ID UINT8_C(0x32) +#define BMM150_SET_SOFT_RESET UINT8_C(0x82) + +/*! @name POWER MODE DEFINTIONS */ +#define BMM150_POWERMODE_NORMAL UINT8_C(0x00) +#define BMM150_POWERMODE_FORCED UINT8_C(0x01) +#define BMM150_POWERMODE_SLEEP UINT8_C(0x03) +#define BMM150_POWERMODE_SUSPEND UINT8_C(0x04) + +/*! @name Power mode settings */ +#define BMM150_POWER_CNTRL_DISABLE UINT8_C(0x00) +#define BMM150_POWER_CNTRL_ENABLE UINT8_C(0x01) + +/*! @name Sensor delay time settings */ +#define BMM150_DELAY_SOFT_RESET UINT8_C(1000) +#define BMM150_DELAY_NORMAL_SELF_TEST UINT8_C(2000) +#define BMM150_START_UP_TIME UINT8_C(3000) +#define BMM150_DELAY_ADV_SELF_TEST UINT8_C(4000) + +/*! @name ENABLE/DISABLE DEFINITIONS */ +#define BMM150_XYZ_CHANNEL_ENABLE UINT8_C(0x00) +#define BMM150_XYZ_CHANNEL_DISABLE UINT8_C(0x07) + +/*! @name Register Address */ +#define BMM150_REG_CHIP_ID UINT8_C(0x40) +#define BMM150_REG_DATA_X_LSB UINT8_C(0x42) +#define BMM150_REG_DATA_READY_STATUS UINT8_C(0x48) +#define BMM150_REG_INTERRUPT_STATUS UINT8_C(0x4A) +#define BMM150_REG_POWER_CONTROL UINT8_C(0x4B) +#define BMM150_REG_OP_MODE UINT8_C(0x4C) +#define BMM150_REG_INT_CONFIG UINT8_C(0x4D) +#define BMM150_REG_AXES_ENABLE UINT8_C(0x4E) +#define BMM150_REG_LOW_THRESHOLD UINT8_C(0x4F) +#define BMM150_REG_HIGH_THRESHOLD UINT8_C(0x50) +#define BMM150_REG_REP_XY UINT8_C(0x51) +#define BMM150_REG_REP_Z UINT8_C(0x52) + +/*! @name Macros to select the sensor settings to be set by the user + * These values are internal for API implementation. Don't relate this to + * data sheet. + */ +#define BMM150_SEL_DATA_RATE UINT16_C(1) +#define BMM150_SEL_CONTROL_MEASURE UINT16_C(1 << 1) +#define BMM150_SEL_XY_REP UINT16_C(1 << 2) +#define BMM150_SEL_Z_REP UINT16_C(1 << 3) +#define BMM150_SEL_DRDY_PIN_EN UINT16_C(1 << 4) +#define BMM150_SEL_INT_PIN_EN UINT16_C(1 << 5) +#define BMM150_SEL_DRDY_POLARITY UINT16_C(1 << 6) +#define BMM150_SEL_INT_LATCH UINT16_C(1 << 7) +#define BMM150_SEL_INT_POLARITY UINT16_C(1 << 8) +#define BMM150_SEL_DATA_OVERRUN_INT UINT16_C(1 << 9) +#define BMM150_SEL_OVERFLOW_INT UINT16_C(1 << 10) +#define BMM150_SEL_HIGH_THRESHOLD_INT UINT16_C(1 << 11) +#define BMM150_SEL_LOW_THRESHOLD_INT UINT16_C(1 << 12) +#define BMM150_SEL_LOW_THRESHOLD_SETTING UINT16_C(1 << 13) +#define BMM150_SEL_HIGH_THRESHOLD_SETTING UINT16_C(1 << 14) + +/*! @name DATA RATE DEFINITIONS */ +#define BMM150_DATA_RATE_10HZ UINT8_C(0x00) +#define BMM150_DATA_RATE_02HZ UINT8_C(0x01) +#define BMM150_DATA_RATE_06HZ UINT8_C(0x02) +#define BMM150_DATA_RATE_08HZ UINT8_C(0x03) +#define BMM150_DATA_RATE_15HZ UINT8_C(0x04) +#define BMM150_DATA_RATE_20HZ UINT8_C(0x05) +#define BMM150_DATA_RATE_25HZ UINT8_C(0x06) +#define BMM150_DATA_RATE_30HZ UINT8_C(0x07) +#define BMM150_ODR_MAX UINT8_C(0x07) +#define BMM150_ODR_MSK UINT8_C(0x38) +#define BMM150_ODR_POS UINT8_C(0x03) + +/*! @name TRIM REGISTERS */ +/* Trim Extended Registers */ +#define BMM150_DIG_X1 UINT8_C(0x5D) +#define BMM150_DIG_Y1 UINT8_C(0x5E) +#define BMM150_DIG_Z4_LSB UINT8_C(0x62) +#define BMM150_DIG_Z4_MSB UINT8_C(0x63) +#define BMM150_DIG_X2 UINT8_C(0x64) +#define BMM150_DIG_Y2 UINT8_C(0x65) +#define BMM150_DIG_Z2_LSB UINT8_C(0x68) +#define BMM150_DIG_Z2_MSB UINT8_C(0x69) +#define BMM150_DIG_Z1_LSB UINT8_C(0x6A) +#define BMM150_DIG_Z1_MSB UINT8_C(0x6B) +#define BMM150_DIG_XYZ1_LSB UINT8_C(0x6C) +#define BMM150_DIG_XYZ1_MSB UINT8_C(0x6D) +#define BMM150_DIG_Z3_LSB UINT8_C(0x6E) +#define BMM150_DIG_Z3_MSB UINT8_C(0x6F) +#define BMM150_DIG_XY2 UINT8_C(0x70) +#define BMM150_DIG_XY1 UINT8_C(0x71) + +/*! @name Threshold interrupt setting macros for x,y,z axes selection */ +#define BMM150_THRESHOLD_X UINT8_C(0x06) +#define BMM150_THRESHOLD_Y UINT8_C(0x05) +#define BMM150_THRESHOLD_Z UINT8_C(0x03) + +#define BMM150_HIGH_THRESHOLD_INT_MSK UINT8_C(0x38) +#define BMM150_HIGH_THRESHOLD_INT_POS UINT8_C(0x03) +#define BMM150_LOW_THRESHOLD_INT_MSK UINT8_C(0x07) + +/*! @name User configurable interrupt setting macros */ +#define BMM150_INT_ENABLE UINT8_C(0x01) +#define BMM150_INT_DISABLE UINT8_C(0x00) +#define BMM150_ACTIVE_HIGH_POLARITY UINT8_C(0x01) +#define BMM150_ACTIVE_LOW_POLARITY UINT8_C(0x00) +#define BMM150_LATCHED UINT8_C(0x01) +#define BMM150_NON_LATCHED UINT8_C(0x00) + +/*! @name Interrupt status */ +#define BMM150_INT_THRESHOLD_X_LOW UINT16_C(0x0001) +#define BMM150_INT_THRESHOLD_Y_LOW UINT16_C(0x0002) +#define BMM150_INT_THRESHOLD_Z_LOW UINT16_C(0x0004) +#define BMM150_INT_THRESHOLD_X_HIGH UINT16_C(0x0008) +#define BMM150_INT_THRESHOLD_Y_HIGH UINT16_C(0x0010) +#define BMM150_INT_THRESHOLD_Z_HIGH UINT16_C(0x0020) +#define BMM150_INT_DATA_OVERFLOW UINT16_C(0x0040) +#define BMM150_INT_DATA_OVERRUN UINT16_C(0x0080) +#define BMM150_INT_DATA_READY UINT16_C(0x0100) + +#define BMM150_DRDY_EN_MSK UINT8_C(0x80) +#define BMM150_DRDY_EN_POS UINT8_C(0x07) +#define BMM150_DRDY_POLARITY_MSK UINT8_C(0x04) +#define BMM150_DRDY_POLARITY_POS UINT8_C(0x02) +#define BMM150_INT_PIN_EN_MSK UINT8_C(0x40) +#define BMM150_INT_PIN_EN_POS UINT8_C(0x06) +#define BMM150_INT_LATCH_MSK UINT8_C(0x02) +#define BMM150_INT_LATCH_POS UINT8_C(0x01) +#define BMM150_INT_POLARITY_MSK UINT8_C(0x01) +#define BMM150_DRDY_STATUS_MSK UINT8_C(0x01) + +/*! @name Interrupt status macros */ +#define BMM150_INT_ASSERTED_DRDY UINT16_C(0x0100) +#define BMM150_INT_ASSERTED_LOW_THRES UINT16_C(0x0007) +#define BMM150_INT_ASSERTED_HIGH_THRES UINT16_C(0x0380) + +/*! @name Power control bit macros */ +#define BMM150_PWR_CNTRL_MSK UINT8_C(0x01) +#define BMM150_CONTROL_MEASURE_MSK UINT8_C(0x38) +#define BMM150_CONTROL_MEASURE_POS UINT8_C(0x03) +#define BMM150_POWER_CONTROL_BIT_MSK UINT8_C(0x01) +#define BMM150_POWER_CONTROL_BIT_POS UINT8_C(0x00) + +/*! @name Data macros */ +#define BMM150_DATA_X_MSK UINT8_C(0xF8) +#define BMM150_DATA_X_POS UINT8_C(0x03) + +#define BMM150_DATA_Y_MSK UINT8_C(0xF8) +#define BMM150_DATA_Y_POS UINT8_C(0x03) + +#define BMM150_DATA_Z_MSK UINT8_C(0xFE) +#define BMM150_DATA_Z_POS UINT8_C(0x01) + +#define BMM150_DATA_RHALL_MSK UINT8_C(0xFC) +#define BMM150_DATA_RHALL_POS UINT8_C(0x02) + +#define BMM150_DATA_OVERRUN_INT_MSK UINT8_C(0x80) +#define BMM150_DATA_OVERRUN_INT_POS UINT8_C(0x07) + +#define BMM150_OVERFLOW_INT_MSK UINT8_C(0x40) +#define BMM150_OVERFLOW_INT_POS UINT8_C(0x06) + +/*! @name OVERFLOW DEFINITIONS */ +#define BMM150_OVERFLOW_ADCVAL_XYAXES_FLIP INT16_C(-4096) +#define BMM150_OVERFLOW_ADCVAL_ZAXIS_HALL INT16_C(-16384) +#define BMM150_OVERFLOW_OUTPUT INT16_C(-32768) +#define BMM150_NEGATIVE_SATURATION_Z INT16_C(-32767) +#define BMM150_POSITIVE_SATURATION_Z INT16_C(32767) +#ifdef BMM150_USE_FLOATING_POINT +#define BMM150_OVERFLOW_OUTPUT_FLOAT 0.0f +#endif + +/*! @name PRESET MODE DEFINITIONS */ +#define BMM150_PRESETMODE_LOWPOWER UINT8_C(0x01) +#define BMM150_PRESETMODE_REGULAR UINT8_C(0x02) +#define BMM150_PRESETMODE_HIGHACCURACY UINT8_C(0x03) +#define BMM150_PRESETMODE_ENHANCED UINT8_C(0x04) + +#define BMM150_OP_MODE_MSK UINT8_C(0x06) +#define BMM150_OP_MODE_POS UINT8_C(0x01) + +/*! @name PRESET MODES - REPETITIONS-XY RATES */ +#define BMM150_REPXY_LOWPOWER UINT8_C(0x01) +#define BMM150_REPXY_REGULAR UINT8_C(0x04) +#define BMM150_REPXY_ENHANCED UINT8_C(0x07) +#define BMM150_REPXY_HIGHACCURACY UINT8_C(0x17) + +/*! @name PRESET MODES - REPETITIONS-Z RATES */ +#define BMM150_REPZ_LOWPOWER UINT8_C(0x01) +#define BMM150_REPZ_REGULAR UINT8_C(0x07) +#define BMM150_REPZ_ENHANCED UINT8_C(0x0D) +#define BMM150_REPZ_HIGHACCURACY UINT8_C(0x29) + +/*! @name Self test settings */ +#define BMM150_DISABLE_XY_AXIS UINT8_C(0x03) +#define BMM150_SELF_TEST_REP_Z UINT8_C(0x04) + +/*! @name Self test selection macros */ +#define BMM150_SELF_TEST_NORMAL UINT8_C(0) +#define BMM150_SELF_TEST_ADVANCED UINT8_C(1) + +/*! @name Advanced self-test current settings */ +#define BMM150_DISABLE_SELF_TEST_CURRENT UINT8_C(0x00) +#define BMM150_ENABLE_NEGATIVE_CURRENT UINT8_C(0x02) +#define BMM150_ENABLE_POSITIVE_CURRENT UINT8_C(0x03) + +/*! @name Normal self-test status */ +#define BMM150_SELF_TEST_STATUS_XYZ_FAIL UINT8_C(0x00) +#define BMM150_SELF_TEST_STATUS_SUCCESS UINT8_C(0x07) + +#define BMM150_SELF_TEST_MSK UINT8_C(0x01) +#define BMM150_ADV_SELF_TEST_MSK UINT8_C(0xC0) +#define BMM150_ADV_SELF_TEST_POS UINT8_C(0x06) + +/*! @name Register read lengths */ +#define BMM150_LEN_SELF_TEST UINT8_C(5) +#define BMM150_LEN_SETTING_DATA UINT8_C(8) +#define BMM150_LEN_XYZR_DATA UINT8_C(8) + +/*! @name Boundary check macros */ +#define BMM150_BOUNDARY_MAXIMUM UINT8_C(0) +#define BMM150_BOUNDARY_MINIMUM UINT8_C(1) + +/*! @name Macro to SET and GET BITS of a register*/ +#define BMM150_SET_BITS(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + ((data << bitname##_POS) & bitname##_MSK)) + +#define BMM150_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \ + (bitname##_POS)) + +#define BMM150_SET_BITS_POS_0(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + (data & bitname##_MSK)) + +#define BMM150_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) + +/********************************************************/ + +/*! + * @brief Interface selection Enums + */ +enum bmm150_intf { + /*! SPI interface */ + BMM150_SPI_INTF, + /*! I2C interface */ + BMM150_I2C_INTF +}; + +/******************************************************************************/ +/*! @name Function Pointers */ +/******************************************************************************/ +#ifndef BMM150_INTF_RET_TYPE +#define BMM150_INTF_RET_TYPE int8_t +#endif + +#ifndef BMM150_INTF_RET_SUCCESS +#define BMM150_INTF_RET_SUCCESS INT8_C(0) +#endif + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific read functions of the user + * + * @param[in] reg_addr : 8bit register address of the sensor + * @param[out] reg_data : Data from the specified address + * @param[in] length : Length of the reg_data array + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + * @retval 0 for Success + * @retval Non-zero for Failure + */ +typedef BMM150_INTF_RET_TYPE (*bmm150_read_fptr_t)(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, + void *intf_ptr); + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific write functions of the user + * + * @param[in] reg_addr : 8bit register address of the sensor + * @param[out] reg_data : Data to the specified address + * @param[in] length : Length of the reg_data array + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + * @retval 0 for Success + * @retval Non-zero for Failure + * + */ +typedef BMM150_INTF_RET_TYPE (*bmm150_write_fptr_t)(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, + void *intf_ptr); + +/*! + * @brief Delay function pointer which should be mapped to + * delay function of the user + * + * @param period : The time period in microseconds + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + */ +typedef void (*bmm150_delay_us_fptr_t)(uint32_t period, void *intf_ptr); + +/******************************************************************************/ +/*! @name Structure Declarations */ +/******************************************************************************/ + +/*! + * @brief bmm150 trim data structure + */ +struct bmm150_trim_registers { + /*! trim x1 data */ + int8_t dig_x1; + + /*! trim y1 data */ + int8_t dig_y1; + + /*! trim x2 data */ + int8_t dig_x2; + + /*! trim y2 data */ + int8_t dig_y2; + + /*! trim z1 data */ + uint16_t dig_z1; + + /*! trim z2 data */ + int16_t dig_z2; + + /*! trim z3 data */ + int16_t dig_z3; + + /*! trim z4 data */ + int16_t dig_z4; + + /*! trim xy1 data */ + uint8_t dig_xy1; + + /*! trim xy2 data */ + int8_t dig_xy2; + + /*! trim xyz1 data */ + uint16_t dig_xyz1; +}; + +/*! + * @brief bmm150 interrupt pin settings + */ +struct bmm150_int_ctrl_settings { + /*! Data ready interrupt enable */ + uint8_t drdy_pin_en; + + /*! Threshold and overflow interrupts enable */ + uint8_t int_pin_en; + + /*! Data ready interrupt polarity Active high/low */ + uint8_t drdy_polarity; + + /*! Interrupt pin - Latched or Non-latched */ + uint8_t int_latch; + + /*! Interrupt polarity Active high/low */ + uint8_t int_polarity; + + /*! Data overrun interrupt enable */ + uint8_t data_overrun_en; + + /*! Overflow interrupt enable */ + uint8_t overflow_int_en; + + /*! high interrupt enable/disable axis selection */ + uint8_t high_int_en; + + /*! low interrupt enable/disable axis selection */ + uint8_t low_int_en; + + /*! low threshold limit */ + uint8_t low_threshold; + + /*! high threshold limit */ + uint8_t high_threshold; +}; + +/*! + * @brief bmm150 sensor settings + */ +struct bmm150_settings { + /*! Control measurement of XYZ axes */ + uint8_t xyz_axes_control; + + /*! Power mode of sensor */ + uint8_t pwr_mode; + + /*! Data rate value (ODR) */ + uint8_t data_rate; + + /*! XY Repetitions */ + uint8_t xy_rep; + + /*! Z Repetitions */ + uint8_t z_rep; + + /*! Preset mode of sensor */ + uint8_t preset_mode; + + /*! Interrupt configuration settings */ + struct bmm150_int_ctrl_settings int_settings; +}; + +/*! + * @brief bmm150 un-compensated (raw) magnetometer data + */ +struct bmm150_raw_mag_data { + /*! Raw mag X data */ + int16_t raw_datax; + + /*! Raw mag Y data */ + int16_t raw_datay; + + /*! Raw mag Z data */ + int16_t raw_dataz; + + /*! Raw mag resistance value */ + uint16_t raw_data_r; +}; + +#ifdef BMM150_USE_FLOATING_POINT + +/*! + * @brief bmm150 compensated magnetometer data in float + */ +struct bmm150_mag_data { + /*! compensated mag X data */ + float x; + + /*! compensated mag Y data */ + float y; + + /*! compensated mag Z data */ + float z; +}; + +#else + +/*! + * @brief bmm150 compensated magnetometer data in int16_t format + */ +struct bmm150_mag_data { + /*! compensated mag X data */ + int16_t x; + + /*! compensated mag Y data */ + int16_t y; + + /*! compensated mag Z data */ + int16_t z; +}; + +#endif + +/*! + * @brief bmm150 device structure + */ +struct bmm150_dev { + /*! Chip Id */ + uint8_t chip_id; + + /*! SPI/I2C Interface */ + enum bmm150_intf intf; + + /*! + * The interface pointer is used to enable the user + * to link their interface descriptors for reference during the + * implementation of the read and write interfaces to the + * hardware. + */ + void *intf_ptr; + + /*! Variable that holds result of read/write function */ + BMM150_INTF_RET_TYPE intf_rslt; + + /*! Bus read function pointer */ + bmm150_read_fptr_t read; + + /*! Bus write function pointer */ + bmm150_write_fptr_t write; + + /*! delay(in us) function pointer */ + bmm150_delay_us_fptr_t delay_us; + + /*! Trim registers */ + struct bmm150_trim_registers trim_data; + + /*! Interrupt status */ + uint16_t int_status; + + /*! Power control bit value */ + uint8_t pwr_cntrl_bit; +}; + +#endif /* BMM150_DEFS_H_ */ diff --git a/lib/SensorLib/src/bosch/BoschParse.cpp b/lib/SensorLib/src/bosch/BoschParse.cpp new file mode 100644 index 0000000..288471d --- /dev/null +++ b/lib/SensorLib/src/bosch/BoschParse.cpp @@ -0,0 +1,177 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file BoschParse.cpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-30 + * + */ +#include "BoschParse.h" + +std::vector BoschParse::bhyEventVector; +std::vector BoschParse::bhyParseEventVector; +uint8_t SensorEventCbList::current_id = 1; +uint8_t ParseCallBackList::current_id = 1; + +void BoschParse::parseData(const struct bhy2_fifo_parse_data_info *fifo, void *user_data) +{ + int8_t size = fifo->data_size - 1; + +#ifdef LOG_PORT + LOG_PORT.print("Sensor: "); + LOG_PORT.print(fifo->sensor_id); + LOG_PORT.print(" size: "); + LOG_PORT.print(fifo->data_size); + LOG_PORT.print(" value:"); + for (uint8_t i = 0; i < size; i++) { + LOG_PORT.printf("%04x", fifo->data_ptr[i]); + LOG_PORT.print(" "); + } + LOG_PORT.println(); +#endif + + for (uint32_t i = 0; i < bhyParseEventVector.size(); i++) { + ParseCallBackList_t entry = bhyParseEventVector[i]; + if (entry.cb ) { + if (entry.id == fifo->sensor_id) { + if (entry.cb) { + entry.cb(fifo->sensor_id, fifo->data_ptr, size); + } + } + } + } +} + +void BoschParse::parseMetaEvent(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data) +{ + (void)user_data; + + uint8_t meta_event_type = callback_info->data_ptr[0]; + uint8_t byte1 = callback_info->data_ptr[1]; + uint8_t byte2 = callback_info->data_ptr[2]; + const char *event_text; + // Remove warning + (void)byte1; + (void)byte2; + (void)event_text; + + if (callback_info->sensor_id == BHY2_SYS_ID_META_EVENT) { + event_text = "[META EVENT]"; + } else if (callback_info->sensor_id == BHY2_SYS_ID_META_EVENT_WU) { + event_text = "[META EVENT WAKE UP]"; + } else { + return; + } + + switch (meta_event_type) { + case BHY2_META_EVENT_FLUSH_COMPLETE: + log_i("%s Flush complete for sensor id %u\r\n", event_text, byte1); + break; + case BHY2_META_EVENT_SAMPLE_RATE_CHANGED: + log_i("%s Sample rate changed for sensor id %u\r\n", event_text, byte1); + break; + case BHY2_META_EVENT_POWER_MODE_CHANGED: + log_i("%s Power mode changed for sensor id %u\r\n", event_text, byte1); + break; + case BHY2_META_EVENT_ALGORITHM_EVENTS: + log_i("%s Algorithm event\r\n", event_text); + break; + case BHY2_META_EVENT_SENSOR_STATUS: + log_i("%s Accuracy for sensor id %u changed to %u\r\n", event_text, byte1, byte2); + break; + case BHY2_META_EVENT_BSX_DO_STEPS_MAIN: + log_i("%s BSX event (do steps main)\r\n", event_text); + break; + case BHY2_META_EVENT_BSX_DO_STEPS_CALIB: + log_i("%s BSX event (do steps calib)\r\n", event_text); + break; + case BHY2_META_EVENT_BSX_GET_OUTPUT_SIGNAL: + log_i("%s BSX event (get output signal)\r\n", event_text); + break; + case BHY2_META_EVENT_SENSOR_ERROR: + log_i("%s Sensor id %u reported error 0x%02X\r\n", event_text, byte1, byte2); + break; + case BHY2_META_EVENT_FIFO_OVERFLOW: + log_i("%s FIFO overflow\r\n", event_text); + break; + case BHY2_META_EVENT_DYNAMIC_RANGE_CHANGED: + log_i("%s Dynamic range changed for sensor id %u\r\n", event_text, byte1); + break; + case BHY2_META_EVENT_FIFO_WATERMARK: + log_i("%s FIFO watermark reached\r\n", event_text); + break; + case BHY2_META_EVENT_INITIALIZED: + log_i("%s Firmware initialized. Firmware version %u\r\n", event_text, ((uint16_t)byte2 << 8) | byte1); + break; + case BHY2_META_TRANSFER_CAUSE: + log_i("%s Transfer cause for sensor id %u\r\n", event_text, byte1); + break; + case BHY2_META_EVENT_SENSOR_FRAMEWORK: + log_i("%s Sensor framework event for sensor id %u\r\n", event_text, byte1); + break; + case BHY2_META_EVENT_RESET: + log_i("%s Reset event\r\n", event_text); + break; + case BHY2_META_EVENT_SPACER: + return; + default: + log_i("%s Unknown meta event with id: %u\r\n", event_text, meta_event_type); + break; + } + + for (uint32_t i = 0; i < bhyEventVector.size(); i++) { + SensorEventCbList_t entry = bhyEventVector[i]; + if (entry.cb ) { + if (entry.event == meta_event_type) { + if (entry.cb) { + entry.cb(meta_event_type, callback_info->data_ptr, callback_info->data_size); + } + } + } + } +} + + +void BoschParse::parseDebugMessage(const struct bhy2_fifo_parse_data_info *callback_info, void *callback_ref) +{ + uint32_t s, ns; + uint64_t tns; + uint8_t msg_length = 0; + uint8_t debug_msg[17] = { 0 }; /* Max payload size is 16 bytes, adds a trailing zero if the payload is full */ + + if (!callback_info) { + log_i("Null reference\r\n"); + + return; + } + + time_to_s_ns(*callback_info->time_stamp, &s, &ns, &tns); + + msg_length = callback_info->data_ptr[0]; + + memcpy(debug_msg, &callback_info->data_ptr[1], msg_length); + debug_msg[msg_length] = '\0'; /* Terminate the string */ + + log_i("[DEBUG MSG]; T: %lu.%09lu; %s\r\n", s, ns, debug_msg); +} \ No newline at end of file diff --git a/lib/SensorLib/src/bosch/BoschParse.h b/lib/SensorLib/src/bosch/BoschParse.h new file mode 100644 index 0000000..6b5f107 --- /dev/null +++ b/lib/SensorLib/src/bosch/BoschParse.h @@ -0,0 +1,58 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file BoschParse.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-30 + * + */ +#pragma once + +#include "SensorCommon.tpp" +#include "SensorBhy2Define.h" +#include "bosch/bhy2_parse.h" +#include "bosch/common/common.h" +#include +#include + + +enum BoschOrientation { + BHY2_DIRECTION_TOP_RIGHT, + BHY2_DIRECTION_TOP_LEFT, + BHY2_DIRECTION_BOTTOM_LEFT, + BHY2_DIRECTION_BOTTOM_RIGHT, +}; + +class BoschParse +{ +public: + static std::vector bhyEventVector; + static std::vector bhyParseEventVector; + + static void parseData(const struct bhy2_fifo_parse_data_info *fifo, void *user_data); + + static void parseMetaEvent(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data); + + static void parseDebugMessage(const struct bhy2_fifo_parse_data_info *callback_info, void *callback_ref); +}; diff --git a/lib/SensorLib/src/bosch/SensorBhy2Define.h b/lib/SensorLib/src/bosch/SensorBhy2Define.h new file mode 100644 index 0000000..9051010 --- /dev/null +++ b/lib/SensorLib/src/bosch/SensorBhy2Define.h @@ -0,0 +1,202 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file SensorBhy2Define.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-09-30 + * + */ +#pragma once + +#include +#include + +#define BHI260AP_SLAVE_ADDRESS_L 0x28 +#define BHI260AP_SLAVE_ADDRESS_H 0x29 +#define BHY_PROCESS_BUFFER_SZIE 512 + +#define BHY2_RLST_CHECK(ret, str, val) \ + do \ + { \ + if (ret) \ + { \ + log_e(str); \ + return val; \ + } \ + } while (0) + +typedef void (*BhyEventCb)(uint8_t event, uint8_t *data, uint32_t size); +typedef void (*BhyParseDataCallback)(uint8_t sensor_id, uint8_t *data, uint32_t size); + + + +typedef struct SensorEventCbList { + static uint8_t current_id; + uint8_t id; + BhyEventCb cb; + uint8_t event; + uint8_t *data; + SensorEventCbList() : id(current_id++), cb(NULL), event(0), data(NULL) + { + } +} SensorEventCbList_t; + + +typedef struct ParseCallBackList { + static uint8_t current_id; + uint8_t id; + BhyParseDataCallback cb; + uint32_t data_length; + uint8_t *data; + ParseCallBackList() : id(current_id++), cb(NULL), data_length(0), data(NULL) + { + } +} ParseCallBackList_t; + +enum BhySensorEvent { + BHY2_EVENT_FLUSH_COMPLETE = 1, + BHY2_EVENT_SAMPLE_RATE_CHANGED, + BHY2_EVENT_POWER_MODE_CHANGED, + BHY2_EVENT_ALGORITHM_EVENTS = 5, + BHY2_EVENT_SENSOR_STATUS, + BHY2_EVENT_BSX_DO_STEPS_MAIN, + BHY2_EVENT_BSX_DO_STEPS_CALIB, + BHY2_EVENT_BSX_GET_OUTPUT_SIGNAL, + BHY2_EVENT_SENSOR_ERROR = 11, + BHY2_EVENT_FIFO_OVERFLOW, + BHY2_EVENT_DYNAMIC_RANGE_CHANGED, + BHY2_EVENT_FIFO_WATERMARK, + BHY2_EVENT_INITIALIZED = 16, + BHY2_EVENT_TRANSFER_CAUSE, + BHY2_EVENT_SENSOR_FRAMEWORK, + BHY2_EVENT_RESET, +}; + + +enum BhySensorID { + SENSOR_ID_ACC_PASS = 1, /* Accelerometer passthrough */ + SENSOR_ID_ACC_RAW = 3, /* Accelerometer uncalibrated */ + SENSOR_ID_ACC = 4, /* Accelerometer corrected */ + SENSOR_ID_ACC_BIAS = 5, /* Accelerometer offset */ + SENSOR_ID_ACC_WU = 6, /* Accelerometer corrected wake up */ + SENSOR_ID_ACC_RAW_WU = 7, /* Accelerometer uncalibrated wake up */ + SENSOR_ID_GYRO_PASS = 10, /* Gyroscope passthrough */ + SENSOR_ID_GYRO_RAW = 12, /* Gyroscope uncalibrated */ + SENSOR_ID_GYRO = 13, /* Gyroscope corrected */ + SENSOR_ID_GYRO_BIAS = 14, /* Gyroscope offset */ + SENSOR_ID_GYRO_WU = 15, /* Gyroscope wake up */ + SENSOR_ID_GYRO_RAW_WU = 16, /* Gyroscope uncalibrated wake up */ + SENSOR_ID_MAG_PASS = 19, /* Magnetometer passthrough */ + SENSOR_ID_MAG_RAW = 21, /* Magnetometer uncalibrated */ + SENSOR_ID_MAG = 22, /* Magnetometer corrected */ + SENSOR_ID_MAG_BIAS = 23, /* Magnetometer offset */ + SENSOR_ID_MAG_WU = 24, /* Magnetometer wake up */ + SENSOR_ID_MAG_RAW_WU = 25, /* Magnetometer uncalibrated wake up */ + SENSOR_ID_GRA = 28, /* Gravity vector */ + SENSOR_ID_GRA_WU = 29, /* Gravity vector wake up */ + SENSOR_ID_LACC = 31, /* Linear acceleration */ + SENSOR_ID_LACC_WU = 32, /* Linear acceleration wake up */ + SENSOR_ID_RV = 34, /* Rotation vector */ + SENSOR_ID_RV_WU = 35, /* Rotation vector wake up */ + SENSOR_ID_GAMERV = 37, /* Game rotation vector */ + SENSOR_ID_GAMERV_WU = 38, /* Game rotation vector wake up */ + SENSOR_ID_GEORV = 40, /* Geo-magnetic rotation vector */ + SENSOR_ID_GEORV_WU = 41, /* Geo-magnetic rotation vector wake up */ + SENSOR_ID_ORI = 43, /* Orientation */ + SENSOR_ID_ORI_WU = 44, /* Orientation wake up */ + SENSOR_ID_TILT_DETECTOR = 48, /* Tilt detector */ + SENSOR_ID_STD = 50, /* Step detector */ + SENSOR_ID_STC = 52, /* Step counter */ + SENSOR_ID_STC_WU = 53, /* Step counter wake up */ + SENSOR_ID_SIG = 55, /* Significant motion */ + SENSOR_ID_WAKE_GESTURE = 57, /* Wake gesture */ + SENSOR_ID_GLANCE_GESTURE = 59, /* Glance gesture */ + SENSOR_ID_PICKUP_GESTURE = 61, /* Pickup gesture */ + SENSOR_ID_AR = 63, /* Activity recognition */ + SENSOR_ID_WRIST_TILT_GESTURE = 67, /* Wrist tilt gesture */ + SENSOR_ID_DEVICE_ORI = 69, /* Device orientation */ + SENSOR_ID_DEVICE_ORI_WU = 70, /* Device orientation wake up */ + SENSOR_ID_STATIONARY_DET = 75, /* Stationary detect */ + SENSOR_ID_MOTION_DET = 77, /* Motion detect */ + SENSOR_ID_ACC_BIAS_WU = 91, /* Accelerometer offset wake up */ + SENSOR_ID_GYRO_BIAS_WU = 92, /* Gyroscope offset wake up */ + SENSOR_ID_MAG_BIAS_WU = 93, /* Magnetometer offset wake up */ + SENSOR_ID_STD_WU = 94, /* Step detector wake up */ + SENSOR_ID_BSEC = 115, /* BSEC 1.x output */ + SENSOR_ID_TEMP = 128, /* Temperature */ + SENSOR_ID_BARO = 129, /* Barometer */ + SENSOR_ID_HUM = 130, /* Humidity */ + SENSOR_ID_GAS = 131, /* Gas */ + SENSOR_ID_TEMP_WU = 132, /* Temperature wake up */ + SENSOR_ID_BARO_WU = 133, /* Barometer wake up */ + SENSOR_ID_HUM_WU = 134, /* Humidity wake up */ + SENSOR_ID_GAS_WU = 135, /* Gas wake up */ + SENSOR_ID_STC_HW = 136, /* Hardware Step counter */ + SENSOR_ID_STD_HW = 137, /* Hardware Step detector */ + SENSOR_ID_SIG_HW = 138, /* Hardware Significant motion */ + SENSOR_ID_STC_HW_WU = 139, /* Hardware Step counter wake up */ + SENSOR_ID_STD_HW_WU = 140, /* Hardware Step detector wake up */ + SENSOR_ID_SIG_HW_WU = 141, /* Hardware Significant motion wake up */ + SENSOR_ID_ANY_MOTION = 142, /* Any motion */ + SENSOR_ID_ANY_MOTION_WU = 143, /* Any motion wake up */ + SENSOR_ID_EXCAMERA = 144, /* External camera trigger */ + SENSOR_ID_GPS = 145, /* GPS */ + SENSOR_ID_LIGHT = 146, /* Light */ + SENSOR_ID_PROX = 147, /* Proximity */ + SENSOR_ID_LIGHT_WU = 148, /* Light wake up */ + SENSOR_ID_PROX_WU = 149, /* Proximity wake up */ + SENSOR_ID_BSEC_LEGACY = 171, /* BSEC 1.x output (legacy, deprecated) */ + SENSOR_DEBUG_DATA_EVENT = 250, /* Binary or string debug data */ + SENSOR_TIMESTAMP_SMALL_DELTA = 251, /* Incremental time change from previous read */ + SENSOR_TIMESTAMP_SMALL_DELTA_WU = 245, /* Incremental time change from previous read wake up */ + SENSOR_TIMESTAMP_LARGE_DELTA = 252, /* Incremental time change from previous read */ + SENSOR_TIMESTAMP_LARGE_DELTA_WU = 246, /* Incremental time change from previous read wake up */ + SENSOR_TIMESTAMP_FULL = 253, /* Incremental time change from previous read */ + SENSOR_TIMESTAMP_FULL_WU = 247, /* Incremental time change from previous read wake up */ + SENSOR_ALL_ID = 255 /* All Sensor parse event*/ +}; + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/SensorLib/src/bosch/bhi3.c b/lib/SensorLib/src/bosch/bhi3.c new file mode 100644 index 0000000..2670151 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhi3.c @@ -0,0 +1,730 @@ +/** + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file bhi3.c + * @date 2023-03-24 + * @version v1.6.0 + * + */ + +/*********************************************************************/ +/* system header files */ +#include +#include +#include + +/*********************************************************************/ +/* BHI3 SensorAPI header files */ +#include "bhi3.h" + +/*************************Private Functions***************************/ + +/*! + * @brief To set the Physical Sensor Control Parameters + */ +int8_t bhi3_physical_sensor_control_set_config(uint8_t sensor_id, + const uint8_t *payload, + uint16_t len, + uint8_t control_code, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + uint16_t cmnd_len = BHY2_LE24MUL(len + 1); /*1 byte added for control code */ + uint8_t cmnd[cmnd_len]; + + memset(cmnd, 0, cmnd_len); + cmnd[0] = BHI3_PHY_SENSOR_CTRL_CODE(BHI3_PHY_SENSOR_CTRL_WRITE, control_code); + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + if (payload == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + for (int i = 0; i < len; i++) + { + cmnd[i + 1] = *(payload + i); + } + + rslt = bhy2_set_parameter(BHI3_PHY_SENSOR_CTRL_PARAM(sensor_id), cmnd, cmnd_len, dev); + } + } + + return rslt; +} + +/*! + * @brief To get the Physical Sensor Control Parameters + */ +int8_t bhi3_physical_sensor_control_get_config(uint8_t sensor_id, + uint8_t *payload, + uint32_t len, + uint8_t control_code, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t ret_len = 0; + + uint8_t cmnd[BHY2_COMMAND_HEADER_LEN] = {0}; + uint8_t rdbck[BHY2_LE24MUL(len)]; + + cmnd[0] = BHI3_PHY_SENSOR_CTRL_CODE(BHI3_PHY_SENSOR_CTRL_READ, control_code); + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_set_parameter(BHI3_PHY_SENSOR_CTRL_PARAM(sensor_id), cmnd, BHY2_COMMAND_HEADER_LEN, dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + rslt = bhy2_get_parameter(BHI3_PHY_SENSOR_CTRL_PARAM(sensor_id), rdbck, BHY2_LE24MUL(len), &ret_len, dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + memcpy(payload, &rdbck[1], len); /*0th element holds control code */ + } + + return rslt; +} + +/**************************Public Functions***************************/ + +/*! + * @brief To parse Wrist Gesture Detection Data + */ +int8_t bhi3_wrist_gesture_detect_parse_data(const uint8_t *data, bhi3_wrist_gesture_detect_t *output) +{ + int8_t rslt = BHY2_OK; + + if ((data == NULL) || (output == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + output->wrist_gesture = (enum bhi3_wrist_gesture_activity) * (data); + } + + return rslt; +} + +/*! + * @brief To set the Accelerometer Fast Offset Calibration + */ +int8_t bhi3_set_acc_foc(const struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, + (uint8_t *)acc_foc, + BHI3_PHY_ACC_FOC_CTRL_LEN, + BHI3_PHY_ACC_FOC_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Accelerometer Fast Offset Calibration + */ +int8_t bhi3_get_acc_foc(struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, + (uint8_t *)acc_foc, + BHI3_PHY_ACC_FOC_CTRL_LEN, + BHI3_PHY_ACC_FOC_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Accelerometer Power Mode + */ +int8_t bhi3_set_acc_power_mode(const uint8_t *acc_pwm, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, + acc_pwm, + BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_LEN, + BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Accelerometer Power Mode + */ +int8_t bhi3_get_acc_power_mode(uint8_t *acc_pwm, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, + acc_pwm, + BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_LEN, + BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Gyroscope Fast Offset Calibration + */ +int8_t bhi3_set_gyro_foc(const struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + (uint8_t *)gyro_foc, + BHI3_PHY_GYRO_FOC_CTRL_LEN, + BHI3_PHY_GYRO_FOC_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Gyroscope Fast Offset Calibration + */ +int8_t bhi3_get_gyro_foc(struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + (uint8_t *)gyro_foc, + BHI3_PHY_GYRO_FOC_CTRL_LEN, + BHI3_PHY_GYRO_FOC_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Gyroscope OIS + */ +int8_t bhi3_set_gyro_ois(const uint8_t *gyro_ois, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_ois, + BHI3_PHY_GYRO_OIS_CTRL_LEN, + BHI3_PHY_GYRO_OIS_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Gyroscope OIS + */ +int8_t bhi3_get_gyro_ois(uint8_t *gyro_ois, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_ois, + BHI3_PHY_GYRO_OIS_CTRL_LEN, + BHI3_PHY_GYRO_OIS_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Gyroscope Fast Startup + */ +int8_t bhi3_set_gyro_fast_startup(const uint8_t *gyro_fs, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_fs, + BHI3_PHY_GYRO_FAST_STARTUP_CTRL_LEN, + BHI3_PHY_GYRO_FAST_STARTUP_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Gyroscope Fast Startup + */ +int8_t bhi3_get_gyro_fast_startup(uint8_t *gyro_fs, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_fs, + BHI3_PHY_GYRO_FAST_STARTUP_CTRL_LEN, + BHI3_PHY_GYRO_FAST_STARTUP_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Gyroscope CRT + */ +int8_t bhi3_set_gyro_crt(const uint8_t *gyro_crt, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_crt, + BHI3_PHY_GYRO_CRT_CTRL_LEN, + BHI3_PHY_GYRO_CRT_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Gyroscope CRT + */ + +/*lint -e506, -e778 */ +int8_t bhi3_get_gyro_crt(uint8_t *gyro_crt, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = + bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_crt, + BHY2_LE24MUL(BHI3_PHY_GYRO_CRT_CTRL_LEN), + BHI3_PHY_GYRO_CRT_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Gyroscope Power Mode + */ +int8_t bhi3_set_gyro_power_mode(const uint8_t *gyro_pwm, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_pwm, + BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_LEN, + BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Gyroscope Power Mode + */ +int8_t bhi3_get_gyro_power_mode(uint8_t *gyro_pwm, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_pwm, + BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_LEN, + BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Gyroscope Timer Auto Trim state + */ +int8_t bhi3_set_gyro_timer_auto_trim(const uint8_t *gyro_tat, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_tat, + BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_LEN, + BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Gyroscope Timer Auto Trim Status + */ +int8_t bhi3_get_gyro_timer_auto_trim(uint8_t *gyro_tat, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE, + gyro_tat, + BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_LEN, + BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Wrist Wear Wakeup Configuration + */ +int8_t bhi3_set_wrist_wear_wakeup_config(const uint8_t *www_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_WRIST_WEAR_WAKEUP, + www_cnfg, + BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_LEN, + BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Wrist Wear Wakeup Configuration + */ +int8_t bhi3_get_wrist_wear_wakeup_config(uint8_t *www_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_WRIST_WEAR_WAKEUP, + www_cnfg, + BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_LEN, + BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Any Motion Configuration + */ +int8_t bhi3_set_anymotion_config(const uint8_t *any_motion_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_PHYS_ANY_MOTION, + any_motion_cnfg, + BHI3_PHY_ANY_MOTION_CTRL_LEN, + BHI3_PHY_ANY_MOTION_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Any Motion Configuration + */ +int8_t bhi3_get_anymotion_config(uint8_t *any_motion_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_PHYS_ANY_MOTION, + any_motion_cnfg, + BHI3_PHY_ANY_MOTION_CTRL_LEN, + BHI3_PHY_ANY_MOTION_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the No Motion Configuration + */ +int8_t bhi3_set_nomotion_config(const uint8_t *no_motion_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_PHYS_NO_MOTION, + no_motion_cnfg, + BHI3_PHY_NO_MOTION_CTRL_LEN, + BHI3_PHY_NO_MOTION_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the No Motion Configuration + */ +int8_t bhi3_get_nomotion_config(uint8_t *no_motion_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the configuration parameter */ + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_PHYS_NO_MOTION, + no_motion_cnfg, + BHI3_PHY_NO_MOTION_CTRL_LEN, + BHI3_PHY_NO_MOTION_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To set the Wrist Gesture Detect Configuration + */ +int8_t bhi3_set_wrist_gesture_detect_config(const uint8_t *wgd_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the configuration parameter */ + rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_WRIST_GESTURE_DETECT, + wgd_cnfg, + BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_LEN, + BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_CODE, + dev); + } + + return rslt; +} + +/*! + * @brief To get the Wrist Gesture Detect Configuration + */ +int8_t bhi3_get_wrist_gesture_detect_config(uint8_t *wgd_cnfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_WRIST_GESTURE_DETECT, + wgd_cnfg, + BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_LEN, + BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_CODE, + dev); + } + + return rslt; +} diff --git a/lib/SensorLib/src/bosch/bhi3.h b/lib/SensorLib/src/bosch/bhi3.h new file mode 100644 index 0000000..e1879a9 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhi3.h @@ -0,0 +1,330 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhi3.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef __BHI3_H__ +#define __BHI3_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include "bhy2.h" +#include "bhi3_defs.h" + +/*! + * @brief To parse Wrist Gesture Detection Data + * + * @param[in] Wrist Gesture Detection Data + * @param[in] Wrist Gesture Detection Output Structure + * + * @return API error codes + * + */ +int8_t bhi3_wrist_gesture_detect_parse_data(const uint8_t *data, bhi3_wrist_gesture_detect_t *output); + +/*! + * @brief To set the Accelerometer Fast Offset Calibration + * + * @param[in] Physical Accelerometer FOC data + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_set_acc_foc(const struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev); + +/*! + * @brief To get the Accelerometer Fast Offset Calibration + * + * @param[out] Physical Accelerometer FOC data + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_get_acc_foc(struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev); + +/*! + * @brief To set the Accelerometer Power Mode + * + * @param[in] Physical Accelerometer Power Mode data + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_set_acc_power_mode(const uint8_t *acc_pwm, struct bhy2_dev *dev); + +/*! + * @brief To get the Accelerometer Power Mode + * + * @param[out] Physical Accelerometer Power Mode data + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_get_acc_power_mode(uint8_t *acc_pwm, struct bhy2_dev *dev); + +/*! +* @brief To set the Gyroscope Fast Offset Calibration +* +* @param[in] Physical Gyroscope FOC data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_set_gyro_foc(const struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev); + +/*! +* @brief To get the Gyroscope Fast Offset Calibration +* +* @param[out] Physical Gyroscope FOC data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_get_gyro_foc(struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev); + +/*! +* @brief To set the Gyroscope OIS +* +* @param[in] Physical Gyroscope OIS data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_set_gyro_ois(const uint8_t *gyro_ois, struct bhy2_dev *dev); + +/*! +* @brief To get the Gyroscope OIS +* +* @param[out] Physical Gyroscope OIS data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_get_gyro_ois(uint8_t *gyro_ois, struct bhy2_dev *dev); + +/*! +* @brief To set the Gyroscope Fast Startup +* +* @param[in] Physical Gyroscope Fast Startup data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_set_gyro_fast_startup(const uint8_t *gyro_fs, struct bhy2_dev *dev); + +/*! +* @brief To get the Gyroscope Fast Startup +* +* @param[out] Physical Gyroscope Fast Startup data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_get_gyro_fast_startup(uint8_t *gyro_fs, struct bhy2_dev *dev); + +/*! +* @brief To set the Gyroscope CRT +* +* @param[in] Physical Gyroscope CRT data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_set_gyro_crt(const uint8_t *gyro_crt, struct bhy2_dev *dev); + +/*! +* @brief To get the Gyroscope CRT +* +* @param[out] Physical Gyroscope CRT data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_get_gyro_crt(uint8_t *gyro_crt, struct bhy2_dev *dev); + +/*! +* @brief To set the Gyroscope Power Mode +* +* @param[in] Physical Gyroscope Power Mode data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_set_gyro_power_mode(const uint8_t *gyro_pwm, struct bhy2_dev *dev); + +/*! +* @brief To get the Gyroscope Power Mode +* +* @param[out] Physical Gyroscope Power Mode data +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_get_gyro_power_mode(uint8_t *gyro_pwm, struct bhy2_dev *dev); + +/*! +* @brief To set the Gyroscope Timer Auto Trim state +* +* @param[in] Physical Gyroscope Timer Auto Trim state +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_set_gyro_timer_auto_trim(const uint8_t *gyro_tat, struct bhy2_dev *dev); + +/*! +* @brief To get the Gyroscope Timer Auto Trim status +* +* @param[out] Physical Gyroscope Timer Auto Trim state +* @param[in] dev hub handle +* +* @return API error codes +* +*/ +int8_t bhi3_get_gyro_timer_auto_trim(uint8_t *gyro_tat, struct bhy2_dev *dev); + +/*! + * @brief To set the Wrist Wear Wakeup Configuration + * + * @param[in] Wrist Wear Wakeup Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_set_wrist_wear_wakeup_config(const uint8_t *www_cnfg, struct bhy2_dev *dev); + +/*! + * @brief To get the Wrist Wear Wakeup Configuration + * + * @param[out] Wrist Wear Wakeup Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_get_wrist_wear_wakeup_config(uint8_t *www_cnfg, struct bhy2_dev *dev); + +/*! + * @brief To set the Any Motion Configuration + * + * @param[in] Any Motion Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_set_anymotion_config(const uint8_t *any_motion_cnfg, struct bhy2_dev *dev); + +/*! + * @brief To get the Any Motion Configuration + * + * @param[out] Any Motion Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_get_anymotion_config(uint8_t *any_motion_cnfg, struct bhy2_dev *dev); + +/*! + * @brief To set the No Motion Configuration + * + * @param[in] No Motion Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_set_nomotion_config(const uint8_t *no_motion_cnfg, struct bhy2_dev *dev); + +/*! + * @brief To get the No Motion Configuration + * + * @param[out] No Motion Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_get_nomotion_config(uint8_t *no_motion_cnfg, struct bhy2_dev *dev); + +/*! + * @brief To set the Wrist Gesture Detection Configuration + * + * @param[in] Wrist Gesture Detection Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_set_wrist_gesture_detect_config(const uint8_t *wgd_cnfg, struct bhy2_dev *dev); + +/*! + * @brief To get the Wrist Gesture Detection Configuration + * + * @param[out] Wrist Gesture Detection Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhi3_get_wrist_gesture_detect_config(uint8_t *wgd_cnfg, struct bhy2_dev *dev); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* __BHI3_H__ */ diff --git a/lib/SensorLib/src/bosch/bhi3_defs.h b/lib/SensorLib/src/bosch/bhi3_defs.h new file mode 100644 index 0000000..a88ce30 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhi3_defs.h @@ -0,0 +1,204 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhi3_defs.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef __BHI3_DEFS_H__ +#define __BHI3_DEFS_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include "bhy2_defs.h" + +/*! The Product ID needs to be replaced with Chip ID for explicit HW specific Identification*/ +#define BHI3_PRODUCT_ID BHY2_PRODUCT_ID + +/*! Firmware header identifier */ +/*#define BHY2_FW_MAGIC UINT16_C(0x662B) */ + +/*! BHI3 Variant IDs */ +#define BHI3_VARIANT_ID_BHI360 UINT32_C(0x18BC5434) +#define BHI3_VARIANT_ID_BHI380 UINT32_C(0x6E6D6CA6) + +/*! BHI3 Specifc Sensor IDs */ +#define BHI3_SENSOR_ID_AR_WEAR_WU UINT8_C(154) /* Activity Recognition (wear/hear) */ +#define BHI3_SENSOR_ID_WRIST_GEST_DETECT_LP_WU UINT8_C(156) /* Wrist Gesture Detector Low Power Wakeup*/ +#define BHI3_SENSOR_ID_WRIST_WEAR_LP_WU UINT8_C(158) /* Wrist Wear Low Power Wakeup */ +#define BHI3_SENSOR_ID_NO_MOTION_LP_WU UINT8_C(159) /* No motion Low Power */ + +/*! Physical Sensor Control Parameter Page Base Address*/ +#define BHI3_PHY_SENSOR_CTRL_PAGE UINT16_C(0x0E) + +/*! Physical Sensor Control pages + * Here the 'id' refers to the Sensor ID of requisite Physical Sensors (Acc/Gyro) + * */ +#define BHI3_PHY_SENSOR_CTRL_PARAM(id) (((BHI3_PHY_SENSOR_CTRL_PAGE) << 8) | (id)) +#define BHI3_PHY_SENSOR_CTRL_CODE(dir, code) ((dir << 7) | (code)) + +#define BHI3_PHY_SENSOR_CTRL_WRITE UINT8_C(0x00) +#define BHI3_PHY_SENSOR_CTRL_READ UINT8_C(0x01) + +#define BHI3_PHY_ACC_FOC_CTRL_CODE UINT8_C(0x01) +#define BHI3_PHY_ACC_FOC_CTRL_LEN 6 + +#define BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_CODE UINT8_C(0x05) +#define BHI3_PHY_ACC_NORMAL_POWER_MODE UINT8_C(0x00) +#define BHI3_PHY_ACC_LOW_POWER_MODE UINT8_C(0x02) +#define BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_LEN 1 + +#define BHI3_PHY_GYRO_FOC_CTRL_CODE UINT8_C(0x01) +#define BHI3_PHY_GYRO_FOC_CTRL_LEN 6 + +#define BHI3_PHY_GYRO_OIS_CTRL_CODE UINT8_C(0x02) +#define BHI3_PHY_GYRO_DISABLE_OIS UINT8_C(0x00) +#define BHI3_PHY_GYRO_ENABLE_OIS UINT8_C(0x01) +#define BHI3_PHY_GYRO_OIS_CTRL_LEN 1 + +#define BHI3_PHY_GYRO_FAST_STARTUP_CTRL_CODE UINT8_C(0x03) +#define BHI3_PHY_GYRO_DISABLE_FAST_STARTUP UINT8_C(0x00) +#define BHI3_PHY_GYRO_ENABLE_FAST_STARTUP UINT8_C(0x01) +#define BHI3_PHY_GYRO_FAST_STARTUP_CTRL_LEN 1 + +#define BHI3_PHY_GYRO_CRT_CTRL_CODE UINT8_C(0x04) +#define BHI3_PHY_GYRO_CRT_STATUS_SUCCESS UINT8_C(0x00) +#define BHI3_PHY_GYRO_ENABLE_CRT UINT8_C(0x01) +#define BHI3_PHY_GYRO_CRT_CTRL_LEN 1 + +#define BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_CODE UINT8_C(0x05) +#define BHI3_PHY_GYRO_NORMAL_POWER_MODE UINT8_C(0x00) +#define BHI3_PHY_GYRO_PERFORMANCE_POWER_MODE UINT8_C(0x01) +#define BHI3_PHY_GYRO_LOW_POWER_MODE UINT8_C(0x02) +#define BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_LEN 1 + +#define BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_CODE UINT8_C(0x06) +#define BHI3_PHY_GYRO_DISABLE_TIMER_AUTO_TRIM UINT8_C(0x00) +#define BHI3_PHY_GYRO_ENABLE_TIMER_AUTO_TRIM UINT8_C(0x01) +#define BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_LEN 1 + +#define BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_CODE UINT8_C(0x01) +#define BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_LEN 10 + +#define BHI3_PHY_ANY_MOTION_CTRL_CODE UINT8_C(0x01) +#define BHI3_PHY_ANY_MOTION_CTRL_LEN 4 + +#define BHI3_PHY_NO_MOTION_CTRL_CODE UINT8_C(0x01) +#define BHI3_PHY_NO_MOTION_CTRL_LEN 4 + +#define BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_CODE UINT8_C(0x07) +#define BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_LEN 19 + +typedef struct bhi3_wrist_wear_wakeup_config_param { + uint16_t min_angle_focus; + uint16_t min_angle_nonfocus; + uint8_t angle_landscape_right; + uint8_t angle_landscape_left; + uint8_t angle_portrait_down; + uint8_t angle_portrait_up; + uint8_t min_dur_moved; + uint8_t min_dur_quite; +} __attribute__ ((packed)) bhi3_wrist_wear_wakeup_config_param_t; + +typedef struct bhi3_any_no_motion_config_param { + uint16_t duration; + uint8_t axis; + uint16_t threshold; +} __attribute__ ((packed)) bhi3_any_no_motion_config_param_t; + +typedef struct bhi3_wrist_gesture_detect_config_param { + uint16_t min_flick_peak_y_threshold; + uint16_t min_flick_peak_z_threshold; + uint16_t gravity_bounds_x_pos; + uint16_t gravity_bounds_x_neg; + uint16_t gravity_bounds_y_neg; + uint16_t gravity_bounds_z_neg; + uint16_t flick_peak_decay_coeff; + uint16_t lp_mean_filter_coeff; + uint16_t max_duration_jiggle_peaks; + uint8_t device_position; +} __attribute__ ((packed)) bhi3_wrist_gesture_detect_config_param_t; + +enum bhi3_wrist_gesture_activity { + NO_GESTURE, + WRIST_SHAKE_JIGGLE = 0x03, + FLICK_IN, + FLICK_OUT +}; + +typedef struct bhi3_wrist_gesture_detect { + enum bhi3_wrist_gesture_activity wrist_gesture; +} __attribute__ ((packed)) bhi3_wrist_gesture_detect_t; + +static const char *const bhi3_wrist_gesture_detect_output[] = { + [NO_GESTURE] = "NO_GESTURE", + [1] = "", + [2] = "", + [WRIST_SHAKE_JIGGLE] = "WRIST_SHAKE_JIGGLE", + [FLICK_IN] = "FLICK_IN", + [FLICK_OUT] = "FLICK_OUT" +}; /*lint -e528 */ + +enum bhi3_phy_sensor_acc_power_mode { + ACC_NORMAL, + ACC_LOW_POWER = 0x02 +}; + +enum bhi3_phy_sensor_gyro_power_mode { + GYRO_NORMAL, + GYRO_PERFORMANCE, + GYRO_LOW_POWER +}; + +static const char *const bhi3_phy_sensor_acc_pwm_output[] = { + [ACC_NORMAL] = "NORMAL", + [1] = "", + [ACC_LOW_POWER] = "LOW POWER" +}; /*lint -e528 */ + +static const char *const bhi3_phy_sensor_gyro_pwm_output[] = { + [GYRO_NORMAL] = "NORMAL", + [GYRO_PERFORMANCE] = "PERFORMANCE", + [GYRO_LOW_POWER] = "LOW POWER" +}; /*lint -e528 */ + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* __BHI3_DEFS_H__ */ diff --git a/lib/SensorLib/src/bosch/bhi3_multi_tap.c b/lib/SensorLib/src/bosch/bhi3_multi_tap.c new file mode 100644 index 0000000..2f17ca9 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhi3_multi_tap.c @@ -0,0 +1,211 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhi3_multi_tap.c +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include + +/*********************************************************************/ +/* BHI3 SensorAPI header files */ +/*********************************************************************/ +#include "bhi3.h" + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "bhi3_multi_tap.h" + +/*lint -e506, -e778*/ + +/*! + * @brief This API writes to the configuration parameter + * + * @param[in] buffer to store Multi Tap configuration + * @param[out] dev hub handle. + * + * @return rslt execution result. + */ +int8_t bhi3_multi_tap_set_config(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the Multi Tap configuration parameter */ + rslt = bhy2_set_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_ENABLE_PARAM), + (uint8_t*)buffer, + BHI3_MULTI_TAP_ENABLE_LENGTH, + dev); + } + + return rslt; +} + +/*! + * @brief To get the MULTI-TAP configuration parameters + * + * @param[out] buffer to store Multi Tap configuration + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhi3_multi_tap_get_config(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t ret_length; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the Multi Tap configuration from the parameter page*/ + rslt = + bhy2_get_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_ENABLE_PARAM), + (uint8_t *)buffer, + BHY2_LE24MUL(BHI3_MULTI_TAP_ENABLE_LENGTH), + &ret_length, + dev); + + if (rslt != BHY2_OK) + { + /*! Invalid number of parameters readout */ + rslt = BHY2_E_INVALID_EVENT_SIZE; + } + } + + return rslt; +} + +/*! + * @brief This API writes to the tap detector configuration parameter + * + * @param[in] buffer to store Multi Tap Detector configuration + * @param[out] dev hub handle. + * + * @return rslt execution result. + */ +int8_t bhi3_multi_tap_detector_set_config(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the Multi Tap configuration parameter */ + rslt = bhy2_set_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_DETECTOR_CONFIG_PARAM), + (uint8_t*)buffer, + BHI3_MULTI_TAP_DETECTOR_CONFIG_LENGTH, + dev); + } + + return rslt; +} + +/*! + * @brief To get the MULTI-TAP Detector configuration parameters + * + * @param[out] buffer to store Multi Tap Detector configuration + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhi3_multi_tap_detector_get_config(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t ret_length; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the Multi Tap configuration from the parameter page*/ + rslt = bhy2_get_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_DETECTOR_CONFIG_PARAM), + (uint8_t *)buffer, + BHY2_LE24MUL(BHI3_MULTI_TAP_DETECTOR_CONFIG_LENGTH), + &ret_length, + dev); + + if (rslt != BHY2_OK) + { + /*! Invalid number of parameters readout */ + rslt = BHY2_E_INVALID_EVENT_SIZE; + } + } + + return rslt; +} + +/*! + * @brief Parsing the fifo data to Multi Tap output format + * + * @param[in] Multi Tap data + * @param[out] buffer to store parameter data + * + * @return API error codes + * + */ +int8_t bhi3_multi_tap_parse_data(const uint8_t *data, uint8_t* output) +{ + int8_t rslt = BHY2_OK; + + if ((data == NULL) || (output == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + *output = *data; + } + + return rslt; +} diff --git a/lib/SensorLib/src/bosch/bhi3_multi_tap.h b/lib/SensorLib/src/bosch/bhi3_multi_tap.h new file mode 100644 index 0000000..d8df9bb --- /dev/null +++ b/lib/SensorLib/src/bosch/bhi3_multi_tap.h @@ -0,0 +1,111 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhi3_multi_tap.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef _BHY2_MULTI_TAP_H_ +#define _BHY2_MULTI_TAP_H_ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include +#include + +#include "bhi3.h" +#include "bhi3_multi_tap_defs.h" + +/*! + * @brief Parsing the fifo data to MULTI_TAP output structure format + * + * @param[in] Multi Tap data + * @param[out] buffer to store parameter data + * + * @return API error codes + * + */ +int8_t bhi3_multi_tap_parse_data(const uint8_t *data, uint8_t *output); + +/*! + * @brief To set the MULTI_TAP configuration parameters + * @param[out] buffer to store parameter data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhi3_multi_tap_set_config(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the MULTI_TAP configuration parameters + * + * @param[out] buffer to store parameter data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhi3_multi_tap_get_config(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To set the MULTI_TAP Detector configuration parameters + * @param[out] buffer to store parameter data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhi3_multi_tap_detector_set_config(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the MULTI_TAP Detector configuration parameters + * + * @param[out] buffer to store parameter data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhi3_multi_tap_detector_get_config(const void *buffer, struct bhy2_dev *dev); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* _BHY2_MULTI_TAP_H_ */ diff --git a/lib/SensorLib/src/bosch/bhi3_multi_tap_defs.h b/lib/SensorLib/src/bosch/bhi3_multi_tap_defs.h new file mode 100644 index 0000000..e6f9137 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhi3_multi_tap_defs.h @@ -0,0 +1,189 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhi3_multi_tap_defs.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef _BHI3_MULTI_TAP_DEFS_H_ +#define _BHI3_MULTI_TAP_DEFS_H_ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include +#include + +/*! Sensor ID for Multi-Tap */ +#define BHI3_SENSOR_ID_MULTI_TAP UINT8_C(153) + +/*! Multi-Tap Parameter Page Base Address*/ +#define BHI3_MULTI_TAP_PAGE UINT16_C(0x0D) + +/*! Multi-Tap Configuration pages */ +#define BHI3_MULTI_TAP_ENABLE_PARAM 0x01 +#define BHI3_MULTI_TAP_DETECTOR_CONFIG_PARAM 0x02 +#define BHI3_MULTI_TAP_PARAM(id) (((BHI3_MULTI_TAP_PAGE) << 8) | (id)) + +#define BHI3_MULTI_TAP_ENABLE_LENGTH UINT8_C(4) +#define BHI3_MULTI_TAP_DETECTOR_CONFIG_LENGTH UINT8_C(6) + +#define BHI3_MULTI_TAP_AXIS_SEL_X UINT8_C(0) +#define BHI3_MULTI_TAP_AXIS_SEL_Y UINT8_C(1) +#define BHI3_MULTI_TAP_AXIS_SEL_Z UINT8_C(2) + +#define BHI3_MULTI_TAP_WAIT_TIMEOUT_DISABLE UINT8_C(0) +#define BHI3_MULTI_TAP_WAIT_TIMEOUT_ENABLE UINT8_C(1) + +#define BHI3_MULTI_TAP_FILTER_MODE_SENSITIVE UINT8_C(0) +#define BHI3_MULTI_TAP_FILTER_MODE_NORMAL UINT8_C(1) +#define BHI3_MULTI_TAP_FILTER_MODE_ROBUST UINT8_C(2) + +#define BHI3_SINGLE_TAP_AXIS_SEL_MASK 0x03 +#define BHI3_SINGLE_TAP_WAIT_TIMEOUT_MASK 0x04 +#define BHI3_SINGLE_TAP_MAX_PEAKS_FOR_TAP_MASK 0x38 +#define BHI3_SINGLE_TAP_FILTER_MODE_MASK 0xC0 + +#define BHI3_DOUBLE_TAP_TAP_PEAK_DUR_MASK 0x03FF +#define BHI3_DOUBLE_TAP_MAX_GES_DUR_MASK 0xFC00 + +#define BHI3_TRIPLE_TAP_MAX_DUR_BW_PEAKS_MASK 0x0F +#define BHI3_TRIPLE_TAP_TAP_SHOCK_SETL_DUR_MASK 0xF0 +#define BHI3_TRIPLE_TAP_MIN_QT_DUR_BW_PEAKS_MASK 0x0F +#define BHI3_TRIPLE_TAP_QT_TM_AFTER_GESTURE_MASK 0xF0 + +#define BHI3_SINGLE_TAP_AXIS_SEL_SHIFT UINT8_C(0) +#define BHI3_SINGLE_TAP_WAIT_TIMEOUT_SHIFT UINT8_C(2) +#define BHI3_SINGLE_TAP_MAX_PEAKS_FOR_TAP_SHIFT UINT8_C(3) +#define BHI3_SINGLE_TAP_FILTER_MODE_SHIFT UINT8_C(6) + +#define BHI3_DOUBLE_TAP_TAP_PEAK_DUR_SHIFT UINT8_C(0) +#define BHI3_DOUBLE_TAP_MAX_GES_DUR_SHIFT UINT8_C(10) + +#define BHI3_TRIPLE_TAP_MAX_DUR_BW_PEAKS_SHIFT UINT8_C(0) +#define BHI3_TRIPLE_TAP_TAP_SHOCK_SETL_DUR_SHIFT UINT8_C(4) +#define BHI3_TRIPLE_TAP_MIN_QT_DUR_BW_PEAKS_SHIFT UINT8_C(0) +#define BHI3_TRIPLE_TAP_QT_TM_AFTER_GESTURE_SHIFT UINT8_C(4) + +/*! + * Single Tap Configuration. + */ +typedef union bhi3_singletap_detector_settings +{ + uint16_t as_uint16; + struct + { + uint16_t axis_sel : 2; /* Tap axis selection */ + uint16_t wait_for_timeout : 1; /* Wait for gesture confirmation */ + uint16_t max_peaks_for_tap : 3; /* Maximum number of peaks that can occur when a tap is done + * */ + uint16_t mode : 2; /* Filter configuration for various detection mode: SENSITIVE, NORMAL and + * ROBUST */ + uint16_t reserved8 : 8; + } as_s; +} __attribute__ ((packed)) bhi3_singletap_detector_settings_t; + +/*! + * Double Tap Configuration. + */ +typedef union bhi3_doubletap_detector_settings +{ + uint16_t as_uint16; + struct + { + uint16_t tap_peak_thres : 10; /* Minimum threshold for peak detection */ + uint16_t max_gesture_dur : 6; /* Maximum time duration from first tap within which matching + * tap/s should happen to be detected as double/triple tap */ + } as_s; +} __attribute__ ((packed)) bhi3_doubletap_detector_settings_t; + +/*! + * Triple Tap Configuration. + */ +typedef union bhi3_tripletap_detector_settings +{ + uint16_t as_uint16; + struct + { + uint16_t max_dur_between_peaks : 4; /* Maximum time duration within which matching peaks of tap + * should occur */ + uint16_t tap_shock_settling_dur : 4; /* Maximum duration to wait for tap shock settling */ + uint16_t min_quite_dur_between_taps : 4; /* Minimum quite time between detection of consecutive taps + * of double/triple taps*/ + uint16_t quite_time_after_gesture : 4; /* Minimum quite time between detection of 2 consecutive + * selected gesture */ + } as_s; +} __attribute__ ((packed)) bhi3_tripletap_detector_settings_t; + +/*! + * Multi Tap Configuration. + */ +typedef struct bhi3_multi_tap_detector +{ + bhi3_singletap_detector_settings_t stap_setting; + bhi3_doubletap_detector_settings_t dtap_setting; + bhi3_tripletap_detector_settings_t ttap_setting; +} __attribute__ ((packed)) bhi3_multi_tap_detector_t; + +/*! + * Multi Tap Setting. + */ +enum bhi3_multi_tap_val { + NO_TAP, + SINGLE_TAP, + DOUBLE_TAP, + DOUBLE_SINGLE_TAP, + TRIPLE_TAP, + TRIPLE_SINGLE_TAP, + TRIPLE_DOUBLE_TAP, + TRIPLE_DOUBLE_SINGLE_TAP +}; + +/*! + * Multi Tap Output. + */ +static const char * const bhi3_multi_tap_string_out[] = { + [NO_TAP] = "NO_TAP", [SINGLE_TAP] = "SINGLE_TAP", [DOUBLE_TAP] = "DOUBLE_TAP", + [DOUBLE_SINGLE_TAP] = "DOUBLE_SINGLE_TAP", [TRIPLE_TAP] = "TRIPLE_TAP", [TRIPLE_SINGLE_TAP] = "TRIPLE_SINGLE_TAP", + [TRIPLE_DOUBLE_TAP] = "TRIPLE_DOUBLE_TAP", [TRIPLE_DOUBLE_SINGLE_TAP] = "TRIPLE_DOUBLE_SINGLE_TAP" +}; /*lint -e528 */ + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* _BHI3_MULTI_TAP_DEFS_H_ */ diff --git a/lib/SensorLib/src/bosch/bhy2.c b/lib/SensorLib/src/bosch/bhy2.c new file mode 100644 index 0000000..bbd4d97 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2.c @@ -0,0 +1,1785 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2.c +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#include "bhy2.h" +#include "bhy2_hif.h" +#include "bhy2_defs.h" + +typedef enum +{ + BHY2_BUFFER_STATUS_OK, + BHY2_BUFFER_STATUS_RELOAD +} buffer_status_t; + +union bhy2_float_u32 +{ + bhy2_float as_float; + uint32_t reg; +}; + +/* + * Array base address "0" corresponds to virtual sensor id 245 + * Debug Data: 250 : event size : 18 + * 245 & 251 : Timestamp small Delta : event size : 2 + * 252 & 246 : Timestamp Large Delta : event size : 3 + * 253 & 247 : Full timestamp: event size: 6 + * 254 & 248 : Meta event: event size: 4 + * Filler: 255 : event size : 1 + */ +static const uint8_t bhy2_sysid_event_size[11] = { 2, 3, 6, 4, 0, 18, 2, 3, 6, 4, 1 }; + +static int8_t parse_fifo(enum bhy2_fifo_type source, struct bhy2_fifo_buffer *fifo_p, struct bhy2_dev *dev); +static int8_t get_buffer_status(const struct bhy2_fifo_buffer *fifo_p, uint8_t event_size, buffer_status_t *status); +static int8_t get_time_stamp(enum bhy2_fifo_type source, uint64_t **time_stamp, struct bhy2_dev *dev); +static int8_t get_callback_info(uint8_t sensor_id, struct bhy2_fifo_parse_callback_table *info, struct bhy2_dev *dev); + +/*function to check the return values in parse_fifo function*/ +static inline int8_t check_return_value(int8_t result) +{ + + if (result != BHY2_OK) + { + return result; + } + + return BHY2_OK; +} + +int8_t bhy2_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t length, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_regs(reg_addr, reg_data, length, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint16_t length, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_set_regs(reg_addr, reg_data, length, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +static int8_t bhy2_get_and_process_fifo_support(uint8_t *int_status, + int8_t *rslt, + struct bhy2_fifo_buffer *fifo_temp, + struct bhy2_dev *dev) +{ + uint32_t bytes_read = 0; + int8_t temp_rslt = BHY2_OK; + + while ((*int_status || fifo_temp->remain_length) && (*rslt == BHY2_OK)) + { + if (((BHY2_IS_INT_FIFO_W(*int_status)) == BHY2_IST_FIFO_W_DRDY) || + ((BHY2_IS_INT_FIFO_W(*int_status)) == BHY2_IST_FIFO_W_LTCY) || + ((BHY2_IS_INT_FIFO_W(*int_status)) == BHY2_IST_FIFO_W_WM) || (fifo_temp->remain_length)) + { + + /* Reset read_pos to the start of the buffer */ + fifo_temp->read_pos = 0; + + /* Append data into the work_buffer linked through fifos */ + *rslt = + bhy2_hif_get_wakeup_fifo(&fifo_temp->buffer[fifo_temp->read_length], + (fifo_temp->buffer_size - fifo_temp->read_length), + &bytes_read, + &fifo_temp->remain_length, + &dev->hif); + if (*rslt != BHY2_OK) + { + return *rslt; + } + + fifo_temp->read_length += bytes_read; + } + + *rslt = parse_fifo(BHY2_FIFO_TYPE_WAKEUP, fifo_temp, dev); + *int_status = 0; + } + + return temp_rslt; + +} + +int8_t bhy2_get_and_process_fifo(uint8_t *work_buffer, uint32_t buffer_size, struct bhy2_dev *dev) +{ + uint8_t int_status, int_status_bak; + uint32_t bytes_read = 0; + int8_t rslt; + struct bhy2_fifo_buffer fifos; + + if ((dev == NULL) || (work_buffer == NULL)) + { + return BHY2_E_NULL_PTR; + } + + if (buffer_size == 0) + { + return BHY2_E_BUFFER; + } + + memset(work_buffer, 0, buffer_size); + memset(&fifos, 0, sizeof(struct bhy2_fifo_buffer)); + + fifos.buffer = work_buffer; + fifos.buffer_size = buffer_size; + + rslt = bhy2_hif_get_interrupt_status(&int_status_bak, &dev->hif); + if (rslt != BHY2_OK) + { + return rslt; + } + + /* Get and process the Wake up FIFO */ + fifos.read_length = 0; + int_status = int_status_bak; + + rslt = bhy2_get_and_process_fifo_support(&int_status, &rslt, &fifos, dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + /* Get and process the Non Wake-up FIFO */ + fifos.read_length = 0; + int_status = int_status_bak; + while ((int_status || fifos.remain_length) && (rslt == BHY2_OK)) + { + if (((BHY2_IS_INT_FIFO_NW(int_status)) == BHY2_IST_FIFO_NW_DRDY) || + ((BHY2_IS_INT_FIFO_NW(int_status)) == BHY2_IST_FIFO_NW_LTCY) || + ((BHY2_IS_INT_FIFO_NW(int_status)) == BHY2_IST_FIFO_NW_WM) || (fifos.remain_length)) + { + /* Reset read_pos to the start of the buffer */ + fifos.read_pos = 0; + + /* Append data into the work_buffer linked through fifos */ + rslt = bhy2_hif_get_nonwakeup_fifo(&fifos.buffer[fifos.read_length], + (fifos.buffer_size - fifos.read_length), + &bytes_read, + &fifos.remain_length, + &dev->hif); + if (rslt != BHY2_OK) + { + return rslt; + } + + fifos.read_length += bytes_read; + } + + rslt = parse_fifo(BHY2_FIFO_TYPE_NON_WAKEUP, &fifos, dev); + int_status = 0; + } + + /* Get and process the Status fifo */ + fifos.read_length = 0; + int_status = int_status_bak; + while ((int_status || fifos.remain_length) && (rslt == BHY2_OK)) + { + if ((((BHY2_IS_INT_ASYNC_STATUS(int_status)) == BHY2_IST_MASK_DEBUG) || (fifos.remain_length))) + { + fifos.read_pos = 0; + rslt = + bhy2_hif_get_status_fifo_async(&fifos.buffer[fifos.read_length], + (fifos.buffer_size - fifos.read_length), + &bytes_read, + &fifos.remain_length, + &dev->hif); + if (rslt != BHY2_OK) + { + return rslt; + } + + fifos.read_length += bytes_read; + } + + rslt = parse_fifo(BHY2_FIFO_TYPE_STATUS, &fifos, dev); + int_status = 0; + } + + return rslt; +} + +int8_t bhy2_get_virt_sensor_cfg(uint8_t sensor_id, struct bhy2_virt_sensor_conf *virt_sensor_conf, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t bytes_read = 0; + union bhy2_float_u32 sample_rate; + uint8_t buffer[12]; /* Size of parameter to get sensor config */ + + if ((dev != NULL) && (virt_sensor_conf != NULL)) + { + rslt = bhy2_hif_get_parameter((uint16_t)(BHY2_PARAM_SENSOR_CONF_0 + sensor_id), + buffer, + 12, + &bytes_read, + &dev->hif); + sample_rate.reg = BHY2_LE2U32(buffer); + virt_sensor_conf->sample_rate = sample_rate.as_float; + virt_sensor_conf->latency = BHY2_LE2U32(&buffer[4]); + virt_sensor_conf->sensitivity = BHY2_LE2U16(&buffer[8]); + virt_sensor_conf->range = BHY2_LE2U16(&buffer[10]); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_set_virt_sensor_cfg(uint8_t sensor_id, bhy2_float sample_rate, uint32_t latency, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_exec_sensor_conf_cmd(sensor_id, sample_rate, latency, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_set_virt_sensor_range(uint8_t sensor_id, uint16_t range, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t buffer[4] = { 0 }; + + if (dev != NULL) + { + buffer[0] = sensor_id; + buffer[1] = (uint8_t)(range & 0xFF); + buffer[2] = (uint8_t)((range >> 8) & 0xFF); + buffer[3] = 0x00; /* Reserved */ + rslt = bhy2_hif_exec_cmd(BHY2_CMD_CHANGE_RANGE, buffer, 4, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_fifo_ctrl(uint32_t *fifo_ctrl, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t bytes_read = 0; + uint8_t buffer[16] = { 0 }; + + if ((dev == NULL) || (fifo_ctrl == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_parameter(BHY2_PARAM_FIFO_CTRL, buffer, 16, &bytes_read, &dev->hif); + + fifo_ctrl[0] = BHY2_LE2U32(buffer); /* Wake up FIFO watermark */ + fifo_ctrl[1] = BHY2_LE2U32(&buffer[4]); /* Wake up FIFO size */ + fifo_ctrl[2] = BHY2_LE2U32(&buffer[8]); /* Non wake up FIFO watermark */ + fifo_ctrl[3] = BHY2_LE2U32(&buffer[12]); /* Non wake up FIFO size */ + } + + return rslt; +} + +int8_t bhy2_set_fifo_wmark_wkup(uint32_t watermark, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t bytes_read = 0; + uint8_t buffer[20] = { 0 }; + uint32_t read_watermark = 0; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &bytes_read, &dev->hif); + if (rslt != BHY2_OK) + { + return rslt; + } + + buffer[0] = (uint8_t)((watermark & 0xFF)); + buffer[1] = (uint8_t)(((watermark >> 8) & 0xFF)); + buffer[2] = (uint8_t)(((watermark >> 16) & 0xFF)); + buffer[3] = (uint8_t)(((watermark >> 24) & 0xFF)); + rslt = bhy2_hif_set_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &dev->hif); + if (rslt != BHY2_OK) + { + return rslt; + } + + rslt = bhy2_hif_get_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &bytes_read, &dev->hif); + if (rslt != BHY2_OK) + { + return rslt; + } + + read_watermark = BHY2_LE2U32(buffer); + if (read_watermark != watermark) + { + rslt = BHY2_E_PARAM_NOT_SET; + } + } + + return rslt; +} + +int8_t bhy2_get_fifo_wmark_wkup(uint32_t *watermark, struct bhy2_dev *dev) +{ + int8_t rslt = 0; + uint32_t bytes_read = 0; + uint8_t buffer[20] = { 0 }; + + if ((dev == NULL) || (watermark == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &bytes_read, &dev->hif); + *watermark = BHY2_LE2U32(buffer); + } + + return rslt; +} + +int8_t bhy2_set_fifo_wmark_nonwkup(uint32_t watermark, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t bytes_read = 0; + uint8_t buffer[20] = { 0 }; + uint32_t read_watermark = 0; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &bytes_read, &dev->hif); + if (rslt < 0) + { + return rslt; + } + + buffer[8] = (uint8_t)((watermark & 0xFF)); + buffer[9] = (uint8_t)(((watermark >> 8) & 0xFF)); + buffer[10] = (uint8_t)(((watermark >> 16) & 0xFF)); + buffer[11] = (uint8_t)(((watermark >> 24) & 0xFF)); + rslt = bhy2_hif_set_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &dev->hif); + if (rslt < 0) + { + return rslt; + } + + rslt = bhy2_hif_get_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &bytes_read, &dev->hif); + if (rslt < 0) + { + return rslt; + } + + read_watermark = BHY2_LE2U32(&buffer[8]); + if (read_watermark != watermark) + { + rslt = BHY2_E_PARAM_NOT_SET; + } + } + + return rslt; +} + +int8_t bhy2_get_fifo_wmark_nonwkup(uint32_t *watermark, struct bhy2_dev *dev) +{ + int8_t rslt = 0; + uint32_t bytes_read = 0; + uint8_t buffer[20] = { 0 }; + + if ((dev == NULL) || (watermark == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_parameter(BHY2_PARAM_FIFO_CTRL, buffer, sizeof(buffer), &bytes_read, &dev->hif); + *watermark = BHY2_LE2U32(&buffer[8]); + } + + return rslt; +} + +int8_t bhy2_get_product_id(uint8_t *product_id, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_product_id(product_id, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_chip_id(uint8_t *chip_id, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_chip_id(chip_id, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_revision_id(uint8_t *revision_id, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev != NULL) && (revision_id != NULL)) + { + rslt = bhy2_hif_get_regs(BHY2_REG_REVISION_ID, revision_id, 1, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_rom_version(uint16_t *rom_version, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev != NULL) && (rom_version != NULL)) + { + rslt = bhy2_hif_get_rom_version(rom_version, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_kernel_version(uint16_t *kernel_version, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_kernel_version(kernel_version, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_user_version(uint16_t *user_version, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_user_version(user_version, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_boot_status(uint8_t *boot_status, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_boot_status(boot_status, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_host_status(uint8_t *host_status, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_host_status(host_status, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_feature_status(uint8_t *feat_status, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_get_feature_status(feat_status, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_get_virt_sensor_list(struct bhy2_dev *dev) +{ + uint32_t bytes_read = 0; + int8_t rslt = 0; + + if (dev != NULL) + { + rslt = + bhy2_hif_get_parameter(BHY2_PARAM_SYS_VIRT_SENSOR_PRESENT, dev->present_buff, 32, &bytes_read, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_upload_firmware_to_ram(const uint8_t *firmware, uint32_t length, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (firmware == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_upload_firmware_to_ram(firmware, length, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_upload_firmware_to_ram_partly(const uint8_t *firmware, + uint32_t total_size, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (firmware == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_upload_firmware_to_ram_partly(firmware, total_size, cur_pos, packet_len, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_boot_from_ram(struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_boot_program_ram(&dev->hif); + } + + return rslt; +} + +int8_t bhy2_erase_flash(uint32_t start_address, uint32_t end_addr, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_erase_flash(start_address, end_addr, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_upload_firmware_to_flash(const uint8_t *firmware, uint32_t length, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t buffer[20] = { 0 }; + uint32_t bytes_read = 0; + + if ((dev == NULL) || (firmware == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_upload_to_flash(firmware, length, buffer, sizeof(buffer), &bytes_read, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_upload_firmware_to_flash_partly(const uint8_t *firmware, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (firmware == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_upload_to_flash_partly(firmware, cur_pos, packet_len, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_boot_from_flash(struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_boot_from_flash(&dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_host_interrupt_ctrl(uint8_t hintr_ctrl, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERRUPT_CTRL, &hintr_ctrl, 1, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_host_interrupt_ctrl(uint8_t *hintr_ctrl, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERRUPT_CTRL, hintr_ctrl, 1, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_interrupt_status(uint8_t *int_status, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_interrupt_status(int_status, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_host_intf_ctrl(uint8_t hintf_ctrl, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &hintf_ctrl, 1, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_host_intf_ctrl(uint8_t *hintf_ctrl, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, hintf_ctrl, 1, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_fifo_format_ctrl(uint8_t param, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t buffer[4] = { 0 }; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + buffer[0] = param & BHY2_FIFO_FORMAT_CTRL_MASK; + rslt = bhy2_hif_exec_cmd(BHY2_CMD_FIFO_FORMAT_CTRL, buffer, 4, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_timestamp_event_req(uint8_t ts_ev_req, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t buffer; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + if (ts_ev_req) + { + buffer = 0x01; + } + else + { + buffer = 0x00; + } + + rslt = bhy2_hif_set_regs(BHY2_REG_TIME_EV_REQ, &buffer, 1, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_hw_timestamp_ns(uint64_t *timestamp_ns, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (timestamp_ns == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_hw_timestamp(timestamp_ns, &dev->hif); + *timestamp_ns *= UINT64_C(15625); + } + + return rslt; +} + +int8_t bhy2_set_host_ctrl(uint8_t host_ctrl, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_CTRL, &host_ctrl, 1, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_host_ctrl(uint8_t *host_ctrl, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (host_ctrl == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_CTRL, host_ctrl, 1, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_soft_passthrough_transfer(union bhy2_soft_passthrough_conf *conf, + uint8_t reg_addr, + uint8_t length, + uint8_t *reg_data, + struct bhy2_dev *dev) +{ + uint32_t bytes_read = 0; + int8_t rslt = BHY2_OK; + uint8_t cmd[BHY2_COMMAND_PACKET_LEN] = { 0 }; + uint8_t tmp_rd_buf[BHY2_SPASS_WRITE_RESP_PACKET_LEN] = { 0 }; + uint16_t buffer_size = 0; + + if ((dev == NULL) || (conf == NULL) || (reg_data == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + conf->conf.trans_count = length; + conf->conf.reg = reg_addr; + if (conf->conf.direction == BHY2_SPASS_READ) + { + if ((BHY2_SPASS_READ_PACKET_LEN + length) % 4) + { + buffer_size = (uint16_t)(((BHY2_SPASS_READ_PACKET_LEN + length) / 4 + 1) * 4); + } + else + { + buffer_size = (uint16_t)(BHY2_SPASS_READ_PACKET_LEN + length); + } + + if (buffer_size <= BHY2_COMMAND_PACKET_LEN) + { + rslt = bhy2_hif_exec_soft_passthrough(conf->data, 8, cmd, buffer_size, &bytes_read, &dev->hif); + memcpy(reg_data, &cmd[9], length); + } + else + { + rslt = BHY2_E_BUFFER; + } + } + else + { + if ((8 + length) % 4) + { + buffer_size = (uint16_t)(((8 + length) / 4 + 1) * 4); + } + else + { + buffer_size = (uint16_t)(8 + length); + } + + if (buffer_size <= BHY2_COMMAND_PACKET_LEN) + { + memcpy(&cmd[0], conf->data, 8); + memcpy(&cmd[8], reg_data, length); + rslt = bhy2_hif_exec_soft_passthrough(&cmd[0], + buffer_size, + tmp_rd_buf, + sizeof(tmp_rd_buf), + &bytes_read, + &dev->hif); + } + else + { + rslt = BHY2_E_BUFFER; + } + } + } + + return rslt; +} + +int8_t bhy2_flush_fifo(uint8_t sensor_id, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_set_fifo_flush(sensor_id, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_soft_reset(struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_reset(&dev->hif); + } + + return rslt; +} + +int8_t bhy2_perform_self_test(uint8_t phys_sensor_id, struct bhy2_self_test_resp *self_test_resp, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (self_test_resp == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_do_self_test(phys_sensor_id, self_test_resp, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_perform_foc(uint8_t phys_sensor_id, struct bhy2_foc_resp *foc_status, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (foc_status == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_do_foc(phys_sensor_id, foc_status, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_orientation_matrix(uint8_t phys_sensor_id, struct bhy2_orient_matrix orient_matrix, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_set_orientation_matrix(phys_sensor_id, orient_matrix, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_phys_sensor_info(uint8_t phys_sensor_id, + struct bhy2_phys_sensor_info *phy_sen_info, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (phy_sen_info == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_phys_sensor_info(phys_sensor_id, phy_sen_info, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_orientation_matrix(uint8_t phys_sensor_id, + struct bhy2_orient_matrix *orient_matrix, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + struct bhy2_phys_sensor_info phy_sen_info; + + if ((dev == NULL) || (orient_matrix == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_phys_sensor_info(phys_sensor_id, &phy_sen_info, &dev->hif); + + /*lint -e702 Info 702: Shift right of signed quantity (int) */ + orient_matrix->c[0] = (int8_t)((phy_sen_info.orientation_matrix[0] & 0x0F) << 4) >> 4; + orient_matrix->c[1] = (int8_t)(phy_sen_info.orientation_matrix[0] & 0xF0) >> 4; + orient_matrix->c[2] = (int8_t)((phy_sen_info.orientation_matrix[1] & 0x0F) << 4) >> 4; + orient_matrix->c[3] = (int8_t)(phy_sen_info.orientation_matrix[1] & 0xF0) >> 4; + orient_matrix->c[4] = (int8_t)((phy_sen_info.orientation_matrix[2] & 0x0F) << 4) >> 4; + orient_matrix->c[5] = (int8_t)(phy_sen_info.orientation_matrix[2] & 0xF0) >> 4; + orient_matrix->c[6] = (int8_t)((phy_sen_info.orientation_matrix[3] & 0x0F) << 4) >> 4; + orient_matrix->c[7] = (int8_t)(phy_sen_info.orientation_matrix[3] & 0xF0) >> 4; + orient_matrix->c[8] = (int8_t)((phy_sen_info.orientation_matrix[4] & 0x0F) << 4) >> 4; + + /*lint +e702 */ + } + + return rslt; +} + +int8_t bhy2_get_sic_matrix(uint8_t *sic_matrix, uint16_t matrix_len, uint32_t *actual_len, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (sic_matrix == NULL) || (actual_len == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_bsx_state(BHY2_PARAM_BSX_SIC, sic_matrix, matrix_len, actual_len, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_sic_matrix(const uint8_t *sic_matrix, uint16_t matrix_len, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (sic_matrix == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_set_bsx_state(BHY2_PARAM_BSX_SIC, sic_matrix, matrix_len, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_calibration_profile(uint8_t phy_sensor_id, + uint8_t *calib_prof, + uint16_t prof_len, + uint32_t *actual_len, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (calib_prof == NULL) || (actual_len == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_bsx_state((uint16_t)(BHY2_PARAM_BSX_CALIB_STATE_BASE | phy_sensor_id), + calib_prof, + prof_len, + actual_len, + &dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_calibration_profile(uint8_t phy_sensor_id, + const uint8_t *calib_prof, + uint16_t prof_len, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (calib_prof == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_set_bsx_state((uint16_t)(BHY2_PARAM_BSX_CALIB_STATE_BASE | phy_sensor_id), + calib_prof, + prof_len, + &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_post_mortem_data(uint8_t *post_mortem, uint32_t buffer_len, uint32_t *actual_len, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint16_t crash_dump_status_code = 0; + + if ((dev == NULL) || (post_mortem == NULL) || (actual_len == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_post_mortem(&crash_dump_status_code, actual_len, post_mortem, buffer_len, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_init(enum bhy2_intf intf, + bhy2_read_fptr_t read, + bhy2_write_fptr_t write, + bhy2_delay_us_fptr_t delay_us, + uint32_t read_write_len, + void *intf_ptr, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + memset(dev, 0, sizeof(struct bhy2_dev)); + + rslt = bhy2_hif_init(intf, read, write, delay_us, read_write_len, intf_ptr, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_register_fifo_parse_callback(uint8_t sensor_id, + bhy2_fifo_parse_callback_t callback, + void *callback_ref, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t i = 0; + + if ((dev == NULL) || (callback == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + for (i = 0; i < BHY2_MAX_SIMUL_SENSORS; i++) + { + if (dev->table[i].sensor_id == 0) + { + dev->table[i].sensor_id = sensor_id; + dev->table[i].callback = callback; + dev->table[i].callback_ref = callback_ref; + break; + } + } + + if (i == BHY2_MAX_SIMUL_SENSORS) + { + rslt = BHy2_E_INSUFFICIENT_MAX_SIMUL_SENSORS; + } + } + + return rslt; +} + +int8_t bhy2_deregister_fifo_parse_callback(uint8_t sensor_id, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t i = 0; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + for (i = 0; i < BHY2_MAX_SIMUL_SENSORS; i++) + { + if (dev->table[i].sensor_id == sensor_id) + { + dev->table[i].sensor_id = 0; + dev->table[i].callback = NULL; + dev->table[i].callback_ref = NULL; + break; + } + } + } + + return rslt; +} + +int8_t bhy2_update_virtual_sensor_list(struct bhy2_dev *dev) +{ + int8_t rslt; + uint8_t sensor_id; + struct bhy2_sensor_info info; + uint8_t sensor_index; + uint8_t bit_mask; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /* Each bit corresponds to presence of Virtual sensor */ + rslt = bhy2_get_virt_sensor_list(dev); + if (rslt == BHY2_OK) + { + /* Padding: Sensor id*/ + dev->event_size[0] = 1; + + for (sensor_id = 1; (sensor_id < BHY2_SPECIAL_SENSOR_ID_OFFSET) && (rslt == BHY2_OK); sensor_id++) + { + sensor_index = (uint8_t)(sensor_id / 8); + bit_mask = (uint8_t)(0x01 << (sensor_id % 8)); + + if (dev->present_buff[sensor_index] & bit_mask) + { + rslt = bhy2_hif_get_sensor_info(sensor_id, &info, &dev->hif); + if (rslt == BHY2_OK) + { + if (info.event_size == 0) + { + rslt = BHY2_E_INVALID_EVENT_SIZE; + break; + } + else + { + dev->event_size[sensor_id] = info.event_size; + } + } + } + } + + for (sensor_id = BHY2_N_VIRTUAL_SENSOR_MAX - 1; sensor_id >= BHY2_SPECIAL_SENSOR_ID_OFFSET; sensor_id--) + { + dev->event_size[sensor_id] = bhy2_sysid_event_size[sensor_id - BHY2_SPECIAL_SENSOR_ID_OFFSET]; + } + } + } + + return rslt; +} + +int8_t bhy2_get_sensor_info(uint8_t sensor_id, struct bhy2_sensor_info *info, struct bhy2_dev *dev) +{ + int8_t rslt; + + if ((dev == NULL) || (info == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_sensor_info(sensor_id, info, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_set_parameter(uint16_t param, const uint8_t *buffer, uint32_t length, struct bhy2_dev *dev) +{ + int8_t rslt; + + if ((dev == NULL) || (buffer == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_exec_cmd(param, buffer, length, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_parameter(uint16_t param, uint8_t *buffer, uint32_t length, uint32_t *actual_len, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (buffer == NULL) || (actual_len == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_hif_get_parameter(param, buffer, length, actual_len, &dev->hif); + } + + return rslt; +} + +int8_t bhy2_get_error_value(uint8_t *error_value, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if ((dev == NULL) || (error_value == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + rslt = bhy2_get_regs(BHY2_REG_ERROR_VALUE, error_value, 1, dev); + } + + return rslt; +} + +int8_t bhy2_set_data_injection_mode(enum bhy2_data_inj_mode mode, struct bhy2_dev *dev) +{ + uint8_t data_inj_payload[8] = { 0 }; + int8_t rslt = BHY2_OK; + uint8_t work_buffer[256] = { 0 }; + uint32_t actual_len = 0; + uint16_t cmd = BHY2_CMD_SET_INJECT_MODE; + + data_inj_payload[0] = (uint8_t)(cmd & 0xFF); + data_inj_payload[1] = (uint8_t)((cmd >> 8) & 0xFF); + data_inj_payload[2] = BHY2_DATA_INJECT_MODE_PAYLOAD_LEN; + + if (dev != NULL) + { + + switch (mode) + { + case BHY2_NORMAL_MODE: + data_inj_payload[4] = 0; + break; + case BHY2_REAL_TIME_INJECTION: + data_inj_payload[4] = 1; + break; + case BHY2_STEP_BY_STEP_INJECTION: + data_inj_payload[4] = 2; + break; + default: + rslt = BHY2_E_INVALID_PARAM; + } + + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_set_inject_data_mode(data_inj_payload, + sizeof (data_inj_payload), + work_buffer, + 256, + &actual_len, + &dev->hif); + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_inject_data(const uint8_t *payload, uint32_t payload_len, struct bhy2_dev *dev) +{ + return bhy2_hif_inject_data(payload, payload_len, &dev->hif); +} + +uint8_t bhy2_is_sensor_available(uint8_t sensor_id, const struct bhy2_dev *dev) +{ + uint8_t offset = sensor_id / 8; + uint8_t mask = 1U << (sensor_id & 0x7); + uint8_t sensor_present = 0; + + if (dev != NULL) + { + sensor_present = (dev->present_buff[offset] & mask); + } + + return sensor_present; +} + +/** + * @brief Function to get the BHy260 variant ID + */ +int8_t bhy2_get_variant_id(uint32_t *variant_id, struct bhy2_dev *dev) +{ + int8_t rslt; + uint8_t cfg_read_command[] = { 0x16, 0x00, 0x00, 0x00 }; + uint8_t buffer[118] = { 0 }; + + rslt = bhy2_soft_reset(dev); + if (rslt == BHY2_OK) + { + rslt = bhy2_set_regs(BHY2_REG_CHAN_CMD, cfg_read_command, sizeof(cfg_read_command), dev); + + /* Give the device some time to prepare data */ + dev->hif.delay_us(10000, NULL); + } + + if (rslt == BHY2_OK) + { + /* Read status FIFO. First check if response is correct */ + rslt = bhy2_get_regs(BHY2_REG_CHAN_STATUS, buffer, 4, dev); + } + + if (rslt == BHY2_OK) + { + if (!((buffer[0] == 0x10) && (buffer[1] == 0x00) && (buffer[2] == sizeof(buffer)) && (buffer[3] == 0))) + { + rslt = BHY2_E_INVALID_PARAM; + } + } + + if (rslt == BHY2_OK) + { + /* Read out the configuration */ + rslt = bhy2_get_regs(BHY2_REG_CHAN_STATUS, buffer, sizeof(buffer), dev); + if (rslt == BHY2_OK) + { + *variant_id = ((uint32_t)buffer[40] << 24) | ((uint32_t)buffer[41] << 16) | ((uint32_t)buffer[42] << 8) | + buffer[43]; + } + } + + return rslt; +} + +static int8_t get_callback_info(uint8_t sensor_id, struct bhy2_fifo_parse_callback_table *info, struct bhy2_dev *dev) +{ + + int8_t rslt = BHY2_OK; + uint8_t i = 0, j; + + if ((dev != NULL) && (info != NULL)) + { + for (j = 0; j < BHY2_MAX_SIMUL_SENSORS; j++) + { + if (sensor_id == dev->table[j].sensor_id) + { + *info = dev->table[j]; + i = j; + break; + } + } + + if (i == BHY2_MAX_SIMUL_SENSORS) + { + rslt = BHy2_E_INSUFFICIENT_MAX_SIMUL_SENSORS; + } + else + { + if ((sensor_id >= BHY2_SPECIAL_SENSOR_ID_OFFSET) && (dev->event_size[sensor_id] == 0)) + { + dev->event_size[sensor_id] = bhy2_sysid_event_size[sensor_id - BHY2_SPECIAL_SENSOR_ID_OFFSET]; + } + + if ((sensor_id == 0) && (dev->event_size[sensor_id] == 0)) + { + dev->event_size[sensor_id] = 1; + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +static int8_t get_buffer_status(const struct bhy2_fifo_buffer *fifo_p, uint8_t event_size, buffer_status_t *status) +{ + if ((fifo_p->read_pos + event_size) <= fifo_p->read_length) + { + *status = BHY2_BUFFER_STATUS_OK; + } + else + { + *status = BHY2_BUFFER_STATUS_RELOAD; + } + + return BHY2_OK; +} + +static int8_t get_time_stamp(enum bhy2_fifo_type source, uint64_t **time_stamp, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (source < BHY2_FIFO_TYPE_MAX) + { + *time_stamp = &dev->last_time_stamp[source]; + } + else + { + rslt = BHY2_E_INVALID_FIFO_TYPE; + } + + return rslt; +} + +static int8_t parse_fifo_support(struct bhy2_fifo_buffer *fifo_buf) +{ + uint8_t i; + + if (fifo_buf->read_length) + { + if (fifo_buf->read_length < fifo_buf->read_pos) + { + return BHY2_E_INVALID_PARAM; + } + + fifo_buf->read_length -= fifo_buf->read_pos; + if (fifo_buf->read_length) + { + for (i = 0; i < fifo_buf->read_length; i++) + { + fifo_buf->buffer[i] = fifo_buf->buffer[fifo_buf->read_pos + i]; + } + } + } + + return BHY2_OK; +} + +static int8_t parse_fifo(enum bhy2_fifo_type source, struct bhy2_fifo_buffer *fifo_p, struct bhy2_dev *dev) +{ + uint8_t tmp_sensor_id = 0; + int8_t rslt = BHY2_OK; + uint32_t tmp_read_pos; + struct bhy2_fifo_parse_data_info data_info; + uint64_t *time_stamp; + struct bhy2_fifo_parse_callback_table info = { 0 }; + buffer_status_t status = BHY2_BUFFER_STATUS_OK; + + for (; (fifo_p->read_pos < fifo_p->read_length) && (status == BHY2_BUFFER_STATUS_OK);) + { + tmp_read_pos = fifo_p->read_pos; + tmp_sensor_id = fifo_p->buffer[tmp_read_pos]; + + rslt = get_time_stamp(source, &time_stamp, dev); + rslt = check_return_value(rslt); + switch (tmp_sensor_id) + { + case BHY2_SYS_ID_FILLER: + case BHY2_SYS_ID_PADDING: + fifo_p->read_pos += 1; + break; + case BHY2_SYS_ID_TS_SMALL_DELTA_WU: + case BHY2_SYS_ID_TS_SMALL_DELTA: + rslt = get_buffer_status(fifo_p, 2, &status); + rslt = check_return_value(rslt); + if (status != BHY2_BUFFER_STATUS_OK) + { + break; + } + + *time_stamp += fifo_p->buffer[tmp_read_pos + 1]; + fifo_p->read_pos += 2; + break; + case BHY2_SYS_ID_TS_LARGE_DELTA: + case BHY2_SYS_ID_TS_LARGE_DELTA_WU: + rslt = get_buffer_status(fifo_p, 3, &status); + rslt = check_return_value(rslt); + + if (status != BHY2_BUFFER_STATUS_OK) + { + break; + } + + *time_stamp += BHY2_LE2U16(fifo_p->buffer + tmp_read_pos + 1); + fifo_p->read_pos += 3; + break; + case BHY2_SYS_ID_BHY2_LOG_DOSTEP: + rslt = get_buffer_status(fifo_p, 23, &status); + rslt = check_return_value(rslt); + + if (status != BHY2_BUFFER_STATUS_OK) + { + break; + } + + fifo_p->read_pos += 23; + + break; + case BHY2_SYS_ID_TS_FULL: + case BHY2_SYS_ID_TS_FULL_WU: + rslt = get_buffer_status(fifo_p, 6, &status); + rslt = check_return_value(rslt); + + if (status != BHY2_BUFFER_STATUS_OK) + { + break; + } + + *time_stamp = BHY2_LE2U40(fifo_p->buffer + tmp_read_pos + UINT8_C(1)); + fifo_p->read_pos += 6; + break; + default: + rslt = get_callback_info(tmp_sensor_id, &info, dev); + rslt = check_return_value(rslt); + rslt = get_buffer_status(fifo_p, dev->event_size[tmp_sensor_id], &status); /*lint !e838 suppressing + * previously assigned value + * not used info */ + rslt = check_return_value(rslt); + if (status != BHY2_BUFFER_STATUS_OK) + { + break; + } + + if (info.callback != NULL) + { + /* Read position is incremented by 1 to exclude sensor id */ + data_info.data_ptr = &fifo_p->buffer[tmp_read_pos + 1]; + data_info.fifo_type = source; + data_info.time_stamp = time_stamp; + data_info.sensor_id = tmp_sensor_id; + data_info.data_size = dev->event_size[tmp_sensor_id]; + info.callback(&data_info, info.callback_ref); + } + + fifo_p->read_pos += dev->event_size[tmp_sensor_id]; + break; + } + } + + rslt = parse_fifo_support(fifo_p); + + return rslt; +} + +int8_t bhy2_clear_fifo(uint8_t flush_cfg, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t buffer[4] = { 0 }; + + if (dev != NULL) + { + buffer[0] = flush_cfg; + rslt = bhy2_hif_exec_cmd(BHY2_CMD_FIFO_FLUSH, buffer, 4, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_read_status(uint16_t *status_code, + uint8_t *status_buff, + uint32_t status_len, + uint32_t *actual_len, + struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev != NULL) + { + rslt = bhy2_hif_wait_status_ready(&dev->hif); + if (rslt != BHY2_OK) + { + return rslt; + } + + rslt = bhy2_hif_get_status_fifo(status_code, status_buff, status_len, actual_len, &dev->hif); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} diff --git a/lib/SensorLib/src/bosch/bhy2.h b/lib/SensorLib/src/bosch/bhy2.h new file mode 100644 index 0000000..c86bcec --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2.h @@ -0,0 +1,664 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef __BHY2_H__ +#define __BHY2_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include "bhy2_defs.h" + +/** + * @brief Function to link the callback interfaces + * @param[in] intf : Physical communication interface + * @param[in] read : Read function pointer + * @param[in] write : Write function pointer + * @param[in] delay_us : Microsecond delay function pointer + * @param[in] read_write_len : Maximum read/write lengths supported + * @param[in] intf_ptr : Reference to the interface. Can be NULL + * @param[out] dev : Device reference + * @return API error codes + */ +int8_t bhy2_init(enum bhy2_intf intf, + bhy2_read_fptr_t read, + bhy2_write_fptr_t write, + bhy2_delay_us_fptr_t delay_us, + uint32_t read_write_len, + void *intf_ptr, + struct bhy2_dev *dev); + +/** + * @brief Function to get data from registers + * @param[in] reg_addr : Register address to be read from + * @param[out] reg_data : Reference to the data buffer + * @param[in] length : Length of the data buffer + * @param[in] dev : Device reference + * @return API Error codes + */ +int8_t bhy2_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t length, struct bhy2_dev *dev); + +/** + * @brief Function to set data to registers + * @param[in] reg_addr : Register address to write to + * @param[in] reg_data : Reference to the data buffer + * @param[in] length : Length of the data buffer + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint16_t length, struct bhy2_dev *dev); + +/** + * @brief Function to get the product ID + * @param[out] product_id : Reference to data buffer to store the product ID + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_product_id(uint8_t *product_id, struct bhy2_dev *dev); + +/** + * @brief Function to get the chip ID + * @param[out] chip_id : Reference to data buffer to store the chip ID + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_chip_id(uint8_t *chip_id, struct bhy2_dev *dev); + +/** + * @brief Function to get the revision ID + * @param[out] revision_id : Reference to data buffer to store the revision ID + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_revision_id(uint8_t *revision_id, struct bhy2_dev *dev); + +/** + * @brief Function to get the ROM version + * @param[out] rom_version : Reference to the data buffer to store the ROM version + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_rom_version(uint16_t *rom_version, struct bhy2_dev *dev); + +/** + * @brief Function to get the kernel version + * @param[out] kernel_version : Reference to the data buffer to store the kernel version + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_kernel_version(uint16_t *kernel_version, struct bhy2_dev *dev); + +/** + * @brief Function to get the user version + * @param[out] user_version : Reference to the data buffer to store the user version + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_user_version(uint16_t *user_version, struct bhy2_dev *dev); + +/** + * @brief Function to get the boot status + * @param[out] boot_status : Reference to the data buffer to store the boot status + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_boot_status(uint8_t *boot_status, struct bhy2_dev *dev); + +/** + * @brief Function to get the host status + * @param[out] host_status : Reference to the data buffer to store the host status + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_host_status(uint8_t *host_status, struct bhy2_dev *dev); + +/** + * @brief Function to get the feature status + * @param[out] feat_status : Reference to the data buffer to store the feature status + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_feature_status(uint8_t *feat_status, struct bhy2_dev *dev); + +/** + * @brief Function to get the virtual sensor list and store in the device structure + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_virt_sensor_list(struct bhy2_dev *dev); + +/** + * @brief Function to get the virtual sensor configuration + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[out] virt_sensor_conf : Reference to the data buffer to store the virtual sensor configuration + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_virt_sensor_cfg(uint8_t sensor_id, struct bhy2_virt_sensor_conf *virt_sensor_conf, + struct bhy2_dev *dev); + +/** + * @brief Function to set the sample rate and latency of the virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] sample_rate : Sample rate in Hz + * @param[in] latency : Report latency in milliseconds + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_virt_sensor_cfg(uint8_t sensor_id, bhy2_float sample_rate, uint32_t latency, struct bhy2_dev *dev); + +/** + * @brief Function set the range of the virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] range : Range of the virtual sensor + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_virt_sensor_range(uint8_t sensor_id, uint16_t range, struct bhy2_dev *dev); + +/** + * @brief Function to get and process the FIFOs + * @param[in] work_buffer : Reference to the data buffer where the FIFO data is copied to before parsing + * @param[in] buffer_size : Size of the data buffer + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_and_process_fifo(uint8_t *work_buffer, uint32_t buffer_size, struct bhy2_dev *dev); + +/** + * @brief Function get the FIFO control register + * @param[out] fifo_ctrl : Reference to the data buffer to store the FIFO control + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_fifo_ctrl(uint32_t *fifo_ctrl, struct bhy2_dev *dev); + +/** + * @brief Function to set the Wake up FIFO watermark + * @param[in] watermark : Size of the watermark + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_fifo_wmark_wkup(uint32_t watermark, struct bhy2_dev *dev); + +/** + * @brief Function to get the Wake up FIFO watermark + * @param[out] watermark : Reference to the data buffer to store the FIFO watermark size + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_fifo_wmark_wkup(uint32_t *watermark, struct bhy2_dev *dev); + +/** + * @brief Function to set the Non wake up FIFO watermark + * @param[in] watermark : Size of the watermark + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_fifo_wmark_nonwkup(uint32_t watermark, struct bhy2_dev *dev); + +/** + * @brief Function to get the Non wake up FIFO watermark + * @param[out] watermark : Reference to the data buffer to store the FIFO watermark size + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_fifo_wmark_nonwkup(uint32_t *watermark, struct bhy2_dev *dev); + +/** + * @brief Function to flush data of a virtual sensor from the FIFOs + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_flush_fifo(uint8_t sensor_id, struct bhy2_dev *dev); + +/** + * @brief Function to set the FIFO format + * @param[in] param : FIFO format settings + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_fifo_format_ctrl(uint8_t param, struct bhy2_dev *dev); + +/** + * @brief Function to upload firmware to RAM + * @param[in] firmware : Reference to the data buffer containing the firmware + * @param[in] length : Size of the firmware + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_upload_firmware_to_ram(const uint8_t *firmware, uint32_t length, struct bhy2_dev *dev); + +/** + * @brief Function to upload part of the firmware to RAM + * @param[in] firmware : Reference to the data buffer containing the current firmware section + * @param[in] total_size : Total size of the firmware + * @param[in] cur_pos : Current position of the part being loaded + * @param[in] packet_len : Size of the part being loaded + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_upload_firmware_to_ram_partly(const uint8_t *firmware, + uint32_t total_size, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_dev *dev); + +/** + * @brief Function to boot firmware from RAM + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_boot_from_ram(struct bhy2_dev *dev); + +/** + * @brief Function to erase the flash + * @param[in] start_addr : Start address + * @param[in] end_addr : End address + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_erase_flash(uint32_t start_address, uint32_t end_addr, struct bhy2_dev *dev); + +/** + * @brief Function to upload firmware to Flash + * @param[in] firmware : Reference to the data buffer containing the firmware + * @param[in] length : Size of the firwmare + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_upload_firmware_to_flash(const uint8_t *firmware, uint32_t length, struct bhy2_dev *dev); + +/** + * @brief Function to upload part of the firmware to Flash + * @param[in] firmware : Reference to the data buffer containing the current firmware section + * @param[in] cur_pos : Current position of the part being loaded + * @param[in] packet_len : Size of the part being loaded + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_upload_firmware_to_flash_partly(const uint8_t *firmware, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_dev *dev); + +/** + * @brief Function to boot from Flash + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_boot_from_flash(struct bhy2_dev *dev); + +/** + * @brief Function to set the host interrupt control register + * @param[in] hintr_ctrl : Host interrupt control configuration + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_host_interrupt_ctrl(uint8_t hintr_ctrl, struct bhy2_dev *dev); + +/** + * @brief Function to get the host interrupt control register + * @param[out] hintr_ctrl : Reference to the data buffer to store the configuration + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_host_interrupt_ctrl(uint8_t *hintr_ctrl, struct bhy2_dev *dev); + +/** + * @brief Function to get the interrupt status register + * @param[out] int_status : Reference to the data buffer to store the interrupt status + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_interrupt_status(uint8_t *int_status, struct bhy2_dev *dev); + +/** + * @brief Function to set the host interface control register + * @param[in] hintf_ctrl : Host interface control configuration + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_host_intf_ctrl(uint8_t hintf_ctrl, struct bhy2_dev *dev); + +/** + * @brief Function to get the host interface control register + * @param[out] hintf_ctrl : Reference to the data buffer to store the configuration + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_host_intf_ctrl(uint8_t *hintf_ctrl, struct bhy2_dev *dev); + +/** + * @brief Function to trigger a timestamp event + * @param[in] ts_ev_req : Pass a non-zero value to trigger a timestamp event + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_timestamp_event_req(uint8_t ts_ev_req, struct bhy2_dev *dev); + +/** + * @brief Function to get the timestamp of the sensor in nanoseconds + * @param[out] timestamp_ns : Reference to the data buffer to store the timestamp in nanoseconds + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_hw_timestamp_ns(uint64_t *timestamp_ns, struct bhy2_dev *dev); + +/** + * @brief Function to get the host control register + * @param[in] host_ctrl : Host control configuration + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_host_ctrl(uint8_t host_ctrl, struct bhy2_dev *dev); + +/** + * @brief Function to get the host control register + * @param[out] host_ctrl : Reference to the data buffer to store the host control configuration + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_host_ctrl(uint8_t *host_ctrl, struct bhy2_dev *dev); + +/** + * @brief Function to trigger a soft reset + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_soft_reset(struct bhy2_dev *dev); + +/** + * @brief Function to perform a self test of a virtual sensor + * @param[in] phys_sensor_id : Physical sensor ID of the virtual sensor + * @param[out] self_test_resp : Reference to the data buffer to store the self test response from the virtual sensor + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_perform_self_test(uint8_t phys_sensor_id, struct bhy2_self_test_resp *self_test_resp, struct bhy2_dev *dev); + +/** + * @brief Function to perform a fast offset compensation of a virtual sensor + * @param[in] phys_sensor_id : Physical Sensor ID of the virtual sensor + * @param[out] self_test_resp : Reference to the data buffer to store the FOC response from the virtual sensor + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_perform_foc(uint8_t phys_sensor_id, struct bhy2_foc_resp *foc_resp, struct bhy2_dev *dev); + +/** + * @brief Function to set the orientation matrix of a physical sensor + * @param[in] phys_sensor_id : Sensor ID of the virtual sensor + * @param[in] orient_matrix : Orientation matrix + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_orientation_matrix(uint8_t phys_sensor_id, struct bhy2_orient_matrix orient_matrix, + struct bhy2_dev *dev); + +/** + * @brief Function to get the physical sensor information + * @param[in] phys_sensor_id : Sensor ID of the physical sensor + * @param[out] phy_sen_info : Reference to the data buffer to the store the physical sensor information + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_phys_sensor_info(uint8_t phys_sensor_id, + struct bhy2_phys_sensor_info *phy_sen_info, + struct bhy2_dev *dev); + +/** + * @brief Function to get the orientation matrix of a physical sensor + * @param[in] phys_sensor_id : Sensor ID of the virtual sensor + * @param[out] orient_matrix : Reference to the data buffer to the store the orientation matrix + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_orientation_matrix(uint8_t phys_sensor_id, + struct bhy2_orient_matrix *orient_matrix, + struct bhy2_dev *dev); + +/** + * @brief Function to set the Soft Iron Correction matrix + * @param[in] sic_matrix : Reference to the data buffer storing the Soft Iron Correction matrix + * @param[in] matrix_len : Length of the matrix + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_sic_matrix(const uint8_t *sic_matrix, uint16_t matrix_len, struct bhy2_dev *dev); + +/** + * @brief Function to get the Soft Iron Correction matrix + * @param[out] sic_matrix : Reference to the data buffer to store the Soft Iron Correction matrix + * @param[in] matrix_len : Length of data buffer + * @param[out] actual_len : Actual length of the Soft Iron Correction matrix + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_sic_matrix(uint8_t *sic_matrix, uint16_t matrix_len, uint32_t *actual_len, struct bhy2_dev *dev); + +/** + * @brief Function to get the calibration profile of a BSX virtual sensor + * @param[in] phys_sensor_id: Physical Sensor ID of the virtual sensor + * @param[out] calib_prof : Reference to the data buffer to store the calibration profile + * @param[in] prof_len : Length of the data buffer + * @param[out] actual_len : Actual length of the calibration profile + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_calibration_profile(uint8_t phys_sensor_id, + uint8_t *calib_prof, + uint16_t prof_len, + uint32_t *actual_len, + struct bhy2_dev *dev); + +/** + * @brief Function to set the calibration profile of a BSX virtual sensor + * @param[in] phys_sensor_id: Physical Sensor ID of the virtual sensor + * @param[in] calib_prof : Reference to the data buffer storing the calibration profile + * @param[in] prof_len : Length of the profil + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_calibration_profile(uint8_t phys_sensor_idv, + const uint8_t *calib_prof, + uint16_t prof_len, + struct bhy2_dev *dev); + +/** + * @brief Function to get the post mortem data + * @param[out] post_mortem : Reference to the data buffer to store the post mortem data + * @param[in] buffer_len : Length of the data buffer + * @param[out] actual_len : Actual length of the post mortem data + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_post_mortem_data(uint8_t *post_mortem, uint32_t buffer_len, uint32_t *actual_len, struct bhy2_dev *dev); + +/** + * @brief Function to link a callback and relevant reference when the sensor event is available in the FIFO + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] callback : Reference of the callback function + * @param[in] callback_ref : Reference needed inside the callback function. Can be NULL + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_register_fifo_parse_callback(uint8_t sensor_id, + bhy2_fifo_parse_callback_t callback, + void *callback_ref, + struct bhy2_dev *dev); + +/** + * @brief Function to unlink a callback and relevant reference + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_deregister_fifo_parse_callback(uint8_t sensor_id, struct bhy2_dev *dev); + +/** + * @brief Function to update the callback table's information + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_update_virtual_sensor_list(struct bhy2_dev *dev); + +/** + * @brief Function to get information of a virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[out] info : Reference to the data buffer to store the virtual sensor information + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_sensor_info(uint8_t sensor_id, struct bhy2_sensor_info *info, struct bhy2_dev *dev); + +/** + * @brief Function to set a parameter + * @param[in] param : Parameter ID + * @param[in] payload : Reference to the data buffer storing the parameter's payload + * @param[in] length : Length of the payload + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_parameter(uint16_t param, const uint8_t *payload, uint32_t length, struct bhy2_dev *dev); + +/** + * @brief Function to get a parameter + * @param[in] param : Parameter ID + * @param[out] payload : Reference to the data buffer to store the parameter's payload + * @param[in] payload_len : Length of the data buffer + * @param[out] actual_len : Actual length of the payload + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_parameter(uint16_t param, + uint8_t *payload, + uint32_t payload_len, + uint32_t *actual_len, + struct bhy2_dev *dev); + +/** + * @brief Function to get the error value register + * @param[out] error_value : Reference to the data buffer to store the error value + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_get_error_value(uint8_t *error_value, struct bhy2_dev *dev); + +/** + * @brief Function to directly communicate with the sensor + * @param[in] conf : The configuration of the transfer + * @param[in] reg_addr : Register address to write to + * @param[in] length : Length of the data buffer to be transferred + * @param[in/out] reg_data : Reference to the data buffer + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_soft_passthrough_transfer(union bhy2_soft_passthrough_conf *conf, + uint8_t reg_addr, + uint8_t length, + uint8_t *reg_data, + struct bhy2_dev *dev); + +/** + * @brief Function to check if a virtual sensor is available + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] dev : Device reference + * @return 1 if the sensor is available. 0 otherwise + */ +uint8_t bhy2_is_sensor_available(uint8_t sensor_id, const struct bhy2_dev *dev); + +/** + * @brief Function to get the BHy260 variant ID + * + * @param[in] variant_id : Reference to store the variant ID + * @param[in] dev : Device reference + * @return int8_t API error codes + */ +int8_t bhy2_get_variant_id(uint32_t *variant_id, struct bhy2_dev *dev); + +/** + * @brief Function to inject data + * @param[in] payload : Reference to the data buffer + * @param[in] payload_len : Length of the data buffer + * @param[in] dev : Device reference + * @return API error codes + */ + +int8_t bhy2_inject_data(const uint8_t *payload, uint32_t payload_len, struct bhy2_dev *dev); + +/** + * @brief Function to set inject mode + * @param[in] mode : Type of data inject mode + * @param[in] dev : Device reference + * @return API error codes + */ +int8_t bhy2_set_data_injection_mode(enum bhy2_data_inj_mode mode, struct bhy2_dev *dev); + +/** +* @brief Function to clear the FIFO +* @param[in] flush_cfg : Type of FIFO Flush +* @param[in] dev : Device reference +* @return API error codes +*/ +int8_t bhy2_clear_fifo(uint8_t flush_cfg, struct bhy2_dev *dev); + +/** +* @brief Function to read the status FIFO +* @param[out] status_code : Status Code +* @param[in] status_buff : Buffer for reading Status Response +* @param[in] status_len : Length of the Response +* @param[out] actual_len : Length of Data read +* @param[in] dev : Device reference +* @return API error codes +*/ +int8_t bhy2_read_status(uint16_t *status_code, + uint8_t *status_buff, + uint32_t status_len, + uint32_t *actual_len, + struct bhy2_dev *dev); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* __BHY2_H__ */ diff --git a/lib/SensorLib/src/bosch/bhy2_bsec.c b/lib/SensorLib/src/bosch/bhy2_bsec.c new file mode 100644 index 0000000..e32f708 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_bsec.c @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file bhy2_bsec.c + * @date 2023-03-24 + * @version v1.6.0 + * + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include + +/*********************************************************************/ +/* BHY2 SensorAPI header files */ +/*********************************************************************/ +#include "bhy2.h" + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "bhy2_bsec.h" + +void bhy2_bsec_parse_air_quality(const uint8_t *payload, struct bhy2_bsec_air_quality *data) +{ + uint8_t i = 0; + + if ((payload != NULL) && (data != NULL)) + { + data->comp_temp = BHY2_LE2U32(payload + i); + i += 4; + data->comp_hum = BHY2_LE2U32(payload + i); + i += 4; + data->comp_gas = BHY2_LE2U32(payload + i); + i += 4; + data->iaq = BHY2_LE2U32(payload + i); + i += 4; + data->static_iaq = BHY2_LE2U32(payload + i); + i += 4; + data->e_co2 = BHY2_LE2U32(payload + i); + i += 4; + data->voc = BHY2_LE2U32(payload + i); + i += 4; + data->iaq_accuracy = payload[i]; + } +} diff --git a/lib/SensorLib/src/bosch/bhy2_bsec.h b/lib/SensorLib/src/bosch/bhy2_bsec.h new file mode 100644 index 0000000..2d018fe --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_bsec.h @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file bhy2_bsec.h + * @date 2023-03-24 + * @version v1.6.0 + * + */ + +#ifndef _BHY2_BSEC_H_ +#define _BHY2_BSEC_H_ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include +#include +#include + +#include "bhy2.h" + +#define BHY2_SENSOR_ID_AIR_QUALITY UINT8_C(115) + +struct bhy2_bsec_air_quality +{ + float comp_temp; /* Sensor heat compensated temperature (deg C) */ + float comp_hum; /* Sensor heat compensated humidity (%rH) */ + float comp_gas; /* Compensated gas resistance (ohms) */ + float iaq; /* Indoor Air Quality index */ + float static_iaq; /* Static IAQ index */ + float e_co2; /* Equivalent CO2 (ppm) */ + float voc; /* Volatile organic compounds (ppb) */ + uint8_t iaq_accuracy; /* IAQ index accuracy (0-3) */ +}; + +void bhy2_bsec_parse_air_quality(const uint8_t *payload, struct bhy2_bsec_air_quality *data); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* _BHY2_BSEC_H_ */ diff --git a/lib/SensorLib/src/bosch/bhy2_defs.h b/lib/SensorLib/src/bosch/bhy2_defs.h new file mode 100644 index 0000000..4d76c41 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_defs.h @@ -0,0 +1,789 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_defs.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef __BHY2_DEFS_H__ +#define __BHY2_DEFS_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#ifdef __KERNEL__ +#include +#include +#include +#else +#include +#include +#endif /*~ __KERNEL__ */ + +#ifndef UNUSED +#define UNUSED(__x__) ((void)(__x__)) +#endif /*~ UNUSED */ + +#ifdef __KERNEL__ +#define bhy2_float u32 +#else +#define bhy2_float float +#endif /*~ __KERNEL__ */ + +#ifdef __KERNEL__ + +#if !defined(UINT8_C) && !defined(INT8_C) +#define INT8_C(x) S8_C(x) +#define UINT8_C(x) U8_C(x) +#endif + +#if !defined(UINT16_C) && !defined(INT16_C) +#define INT16_C(x) S16_C(x) +#define UINT16_C(x) U16_C(x) +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#define INT32_C(x) S32_C(x) +#define UINT32_C(x) U32_C(x) +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#define INT64_C(x) S64_C(x) +#define UINT64_C(x) U64_C(x) +#endif + +#else /* __KERNEL__ */ + +#if !defined(UINT8_C) && !defined(INT8_C) +#define INT8_C(x) (x) +#define UINT8_C(x) (x##U) +#endif + +#if !defined(UINT16_C) && !defined(INT16_C) +#define INT16_C(x) (x) +#define UINT16_C(x) (x##U) +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#define INT32_C(x) (x) +#define UINT32_C(x) (x##U) +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#define INT64_C(x) (x##LL) +#define UINT64_C(x) (x##ULL) +#endif + +#endif /* __KERNEL__ */ + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +#ifndef BHY2_PACKED +#define BHY2_PACKED __attribute__ ((__packed__)) +#endif + +/** API error codes */ +#define BHY2_OK INT8_C(0) +#define BHY2_E_NULL_PTR INT8_C(-1) +#define BHY2_E_INVALID_PARAM INT8_C(-2) +#define BHY2_E_IO INT8_C(-3) +#define BHY2_E_MAGIC INT8_C(-4) +#define BHY2_E_TIMEOUT INT8_C(-5) +#define BHY2_E_BUFFER INT8_C(-6) +#define BHY2_E_INVALID_FIFO_TYPE INT8_C(-7) +#define BHY2_E_INVALID_EVENT_SIZE INT8_C(-8) +#define BHY2_E_PARAM_NOT_SET INT8_C(-9) +#define BHy2_E_INSUFFICIENT_MAX_SIMUL_SENSORS INT8_C(-10) + +#ifndef BHY2_COMMAND_PACKET_LEN +#define BHY2_COMMAND_PACKET_LEN UINT16_C(256) +#endif + +#ifndef BHY2_COMMAND_HEADER_LEN +#define BHY2_COMMAND_HEADER_LEN UINT16_C(4) +#endif + +#if (BHY2_COMMAND_PACKET_LEN < BHY2_COMMAND_HEADER_LEN) +#error "BHY2_COMMAND_PACKET_LEN should be at least 4 bytes" +#endif + +#define BHY2_PRODUCT_ID UINT8_C(0x89) + +/*! Register map */ +#define BHY2_REG_CHAN_CMD UINT8_C(0x00) +#define BHY2_REG_CHAN_FIFO_W UINT8_C(0x01) +#define BHY2_REG_CHAN_FIFO_NW UINT8_C(0x02) +#define BHY2_REG_CHAN_STATUS UINT8_C(0x03) +#define BHY2_REG_CHIP_CTRL UINT8_C(0x05) +#define BHY2_REG_HOST_INTERFACE_CTRL UINT8_C(0x06) +#define BHY2_REG_HOST_INTERRUPT_CTRL UINT8_C(0x07) +#define BHY2_REG_RESET_REQ UINT8_C(0x14) +#define BHY2_REG_TIME_EV_REQ UINT8_C(0x15) +#define BHY2_REG_HOST_CTRL UINT8_C(0x16) +#define BHY2_REG_HOST_STATUS UINT8_C(0x17) +#define BHY2_REG_CRC_0 UINT8_C(0x18) /* Totally 4 */ +#define BHY2_REG_PRODUCT_ID UINT8_C(0x1C) +#define BHY2_REG_REVISION_ID UINT8_C(0x1D) +#define BHY2_REG_ROM_VERSION_0 UINT8_C(0x1E) /* Totally 2 */ +#define BHY2_REG_KERNEL_VERSION_0 UINT8_C(0x20) /* Totally 2 */ +#define BHY2_REG_USER_VERSION_0 UINT8_C(0x22) /* Totally 2 */ +#define BHY2_REG_FEATURE_STATUS UINT8_C(0x24) +#define BHY2_REG_BOOT_STATUS UINT8_C(0x25) +#define BHY2_REG_HOST_INTR_TIME_0 UINT8_C(0x26) /* Totally 5 */ +#define BHY2_REG_CHIP_ID UINT8_C(0x2B) +#define BHY2_REG_INT_STATUS UINT8_C(0x2D) +#define BHY2_REG_ERROR_VALUE UINT8_C(0x2E) +#define BHY2_REG_ERROR_AUX UINT8_C(0x2F) +#define BHY2_REG_DEBUG_VALUE UINT8_C(0x30) +#define BHY2_REG_DEBUG_STATE UINT8_C(0x31) +#define BHY2_REG_GP_5 UINT8_C(0x32) +#define BHY2_REG_GP_6 UINT8_C(0x36) +#define BHY2_REG_GP_7 UINT8_C(0x3A) + +/*! Command packets */ +#define BHY2_CMD_REQ_POST_MORTEM_DATA UINT16_C(0x0001) +#define BHY2_CMD_UPLOAD_TO_PROGRAM_RAM UINT16_C(0x0002) +#define BHY2_CMD_BOOT_PROGRAM_RAM UINT16_C(0x0003) +#define BHY2_CMD_ERASE_FLASH UINT16_C(0x0004) +#define BHY2_CMD_WRITE_FLASH UINT16_C(0x0005) +#define BHY2_CMD_BOOT_FLASH UINT16_C(0x0006) +#define BHY2_CMD_SET_INJECT_MODE UINT16_C(0x0007) +#define BHY2_CMD_INJECT_DATA UINT16_C(0x0008) +#define BHY2_CMD_FIFO_FLUSH UINT16_C(0x0009) +#define BHY2_CMD_SW_PASSTHROUGH UINT16_C(0x000A) +#define BHY2_CMD_REQ_SELF_TEST UINT16_C(0x000B) +#define BHY2_CMD_REQ_FOC UINT16_C(0x000C) +#define BHY2_CMD_CONFIG_SENSOR UINT16_C(0x000D) +#define BHY2_CMD_CHANGE_RANGE UINT16_C(0x000E) +#define BHY2_CMD_FIFO_FORMAT_CTRL UINT16_C(0x0015) + +/*! Soft passthrough feature */ +#define BHY2_SPASS_READ UINT8_C(0) +#define BHY2_SPASS_WRITE UINT8_C(1) +#define BHY2_SPASS_SINGLE_TRANS UINT8_C(0) +#define BHY2_SPASS_MULTI_TRANS UINT8_C(1) +#define BHY2_SPASS_DELAY_DIS UINT8_C(0) +#define BHY2_SPASS_DELAY_EN UINT8_C(1) +#define BHY2_SPASS_SIF1 UINT8_C(1) +#define BHY2_SPASS_SIF2 UINT8_C(2) +#define BHY2_SPASS_SIF3 UINT8_C(3) +#define BHY2_SPASS_SPI_4_WIRE UINT8_C(0) +#define BHY2_SPASS_SPI_3_WIRE UINT8_C(1) +#define BHY2_SPASS_SPI_CPOL_0 UINT8_C(0) +#define BHY2_SPASS_SPI_CPOL_1 UINT8_C(1) +#define BHY2_SPASS_SPI_CPHA_0 UINT8_C(0) +#define BHY2_SPASS_SPI_CPHA_1 UINT8_C(1) +#define BHY2_SPASS_SPI_CS_LOW UINT8_C(0) +#define BHY2_SPASS_SPI_CS_HIGH UINT8_C(1) +#define BHY2_SPASS_SPI_LSB_FIRST_DIS UINT8_C(0) +#define BHY2_SPASS_SPI_LSB_FIRST_EN UINT8_C(1) +#define BHY2_SPASS_SPI_READ_BIT_POL_LOW UINT8_C(0) +#define BHY2_SPASS_SPI_READ_BIT_POL_HIGH UINT8_C(1) +#define BHY2_SPASS_SPI_READ_BIT_POS_0 UINT8_C(0) +#define BHY2_SPASS_SPI_READ_BIT_POS_1 UINT8_C(1) +#define BHY2_SPASS_SPI_READ_BIT_POS_2 UINT8_C(2) +#define BHY2_SPASS_SPI_READ_BIT_POS_3 UINT8_C(3) +#define BHY2_SPASS_SPI_READ_BIT_POS_4 UINT8_C(4) +#define BHY2_SPASS_SPI_READ_BIT_POS_5 UINT8_C(5) +#define BHY2_SPASS_SPI_READ_BIT_POS_6 UINT8_C(6) +#define BHY2_SPASS_SPI_READ_BIT_POS_7 UINT8_C(7) +#define BHY2_SPASS_READ_PACKET_LEN UINT8_C(0x13) +#define BHY2_SPASS_WRITE_RESP_PACKET_LEN UINT8_C(16) + +/*! Helper macros */ +#define BHY2_CHK_BIT(data, bit) (((uint32_t)data >> bit) & 0x01) +#define BHY2_ROUND_WORD_LOWER(x) ((x >> 2) << 2) +#define BHY2_ROUND_WORD_HIGHER(x) (((x >> 2) + 1) << 2) + +#define BHY2_COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__))) +#define BHY2_DATA_INJECT_MODE_PAYLOAD_LEN UINT8_C(0x04) + +/*! Firmware header identifier */ +#define BHY2_FW_MAGIC UINT16_C(0x662B) + +/*! BHy260 Variant IDs */ +#define BHY2_VARIANT_ID_BHA260AB UINT32_C(0x2838C2C2) +#define BHY2_VARIANT_ID_BHI260AB UINT32_C(0x266EB6E7) +#define BHY2_VARIANT_ID_BHI260AP UINT32_C(0x98D7A5D1) + +/*! Boot status */ +#define BHY2_BST_FLASH_DETECTED UINT8_C(0x01) +#define BHY2_BST_FLASH_VERIFY_DONE UINT8_C(0x02) +#define BHY2_BST_FLASH_VERIFY_ERROR UINT8_C(0x04) +#define BHY2_BST_NO_FLASH UINT8_C(0x08) +#define BHY2_BST_HOST_INTERFACE_READY UINT8_C(0x10) +#define BHY2_BST_HOST_FW_VERIFY_DONE UINT8_C(0x20) +#define BHY2_BST_HOST_FW_VERIFY_ERROR UINT8_C(0x40) +#define BHY2_BST_HOST_FW_IDLE UINT8_C(0x80) +#define BHY2_BST_CHECK_RETRY UINT8_C(100) + +/*! Host status */ +#define BHY2_HST_POWER_STATE UINT8_C(0x01) +#define BHY2_HST_HOST_PROTOCOL UINT8_C(0x02) +#define BHY2_HST_HOST_CHANNEL_0 UINT8_C(0x10) +#define BHY2_HST_HOST_CHANNEL_1 UINT8_C(0x20) +#define BHY2_HST_HOST_CHANNEL_2 UINT8_C(0x40) +#define BHY2_HST_HOST_CHANNEL_3 UINT8_C(0x80) + +/*! Interrupt status masks */ +#define BHY2_IST_MASK_ASSERTED (0x1) +#define BHY2_IST_MASK_FIFO_W (0x6) +#define BHY2_IST_MASK_FIFO_NW (0x18) +#define BHY2_IST_MASK_STATUS (0x20) +#define BHY2_IST_MASK_DEBUG (0x40) +#define BHY2_IST_MASK_RESET_FAULT (0x80) +#define BHY2_IST_FIFO_W_DRDY UINT8_C(0x2) +#define BHY2_IST_FIFO_W_LTCY UINT8_C(0x4) +#define BHY2_IST_FIFO_W_WM UINT8_C(0x6) +#define BHY2_IST_FIFO_NW_DRDY UINT8_C(0x8) +#define BHY2_IST_FIFO_NW_LTCY UINT8_C(0x10) +#define BHY2_IST_FIFO_NW_WM UINT8_C(0x18) +#define BHY2_IS_INT_FIFO_W(status) (status & BHY2_IST_MASK_FIFO_W) +#define BHY2_IS_INT_FIFO_NW(status) (status & BHY2_IST_MASK_FIFO_NW) +#define BHY2_IS_INT_STATUS(status) (status & BHY2_IST_MASK_STATUS) +#define BHY2_IS_INT_ASYNC_STATUS(status) (status & BHY2_IST_MASK_DEBUG) +#define BHY2_IS_INT_RESET(status) (status & BHY2_IST_MASK_RESET_FAULT) +#define BHY2_IST_MASK_FIFO (BHY2_IST_MASK_FIFO_W | BHY2_IST_MASK_FIFO_NW) +#define BHY2_IS_INT_FIFO(status) (status & BHY2_IST_MASK_FIFO) + +/*! Chip control bits */ +#define BHY2_CHIP_CTRL_DISABLE UINT8_C(0x00) +#define BHY2_CHIP_CTRL_TURBO_ENABLE UINT8_C(0x01) +#define BHY2_CHIP_CTRL_CLR_ERR_REG UINT8_C(0x02) + +/*! Host interface control bits */ +#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_0 UINT8_C(0x01) +#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_1 UINT8_C(0x02) +#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_2 UINT8_C(0x04) +#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_3 UINT8_C(0x08) +#define BHY2_HIF_CTRL_AP_SUSPENDED UINT8_C(0x10) +#define BHY2_HIF_CTRL_TIMESTAMP_EV_CTRL UINT8_C(0x40) +#define BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL UINT8_C(0x80) + +/*! Interrupt control bits */ +#define BHY2_ICTL_DISABLE_FIFO_W UINT8_C(0x01) +#define BHY2_ICTL_DISABLE_FIFO_NW UINT8_C(0x02) +#define BHY2_ICTL_DISABLE_STATUS_FIFO UINT8_C(0x04) +#define BHY2_ICTL_DISABLE_DEBUG UINT8_C(0x08) +#define BHY2_ICTL_DISABLE_FAULT UINT8_C(0x10) +#define BHY2_ICTL_ACTIVE_LOW UINT8_C(0x20) +#define BHY2_ICTL_EDGE UINT8_C(0x40) +#define BHY2_ICTL_OPEN_DRAIN UINT8_C(0x80) + +/*! Reset command */ +#define BHY2_REQUEST_RESET UINT8_C(0x01) + +/*! FIFO Format bit */ +#define BHY2_FIFO_FORMAT_CTRL_MASK UINT8_C(0x03) +#define BHY2_FIFO_FORMAT_CTRL_DIS_DELTA_TS UINT8_C(0x01) +#define BHY2_FIFO_FORMAT_CTRL_DIS_FULL_TS UINT8_C(0x02) +#define BHY2_FIFO_FORMAT_CTRL_DIS_ALL_TS UINT8_C(0x03) + +/*! System parameters */ +#define BHY2_PARAM_READ_MASK UINT16_C(0x1000) +#define BHY2_PARAM_FIFO_CTRL UINT16_C(0x103) +#define BHY2_PARAM_SYS_VIRT_SENSOR_PRESENT UINT16_C(0x11F) +#define BHY2_PARAM_SYS_PHYS_SENSOR_PRESENT UINT16_C(0x120) +#define BHY2_PARAM_PHYSICAL_SENSOR_BASE UINT16_C(0x120) +#define BHY2_PARAM_BSX_CALIB_STATE_BASE UINT16_C(0x200) +#define BHY2_PARAM_BSX_CALIB_STATE_ACCEL UINT16_C(0x201) +#define BHY2_PARAM_BSX_CALIB_STATE_GYRO UINT16_C(0x203) +#define BHY2_PARAM_BSX_CALIB_STATE_MAG UINT16_C(0x205) +#define BHY2_PARAM_BSX_SIC UINT16_C(0x27D) +#define BHY2_PARAM_BSX_VERSION UINT16_C(0x27E) +#define BHY2_PARAM_SET_SENSOR_CTRL UINT16_C(0x0E00) +#define BHY2_PARAM_GET_SENSOR_CTRL UINT16_C(0x1E00) +#define BHY2_PARAM_SENSOR_CTRL_FOC UINT8_C(0x1) +#define BHY2_PARAM_SENSOR_CTRL_OIS UINT8_C(0x2) +#define BHY2_PARAM_SENSOR_CTRL_FST UINT8_C(0x3) +#define BHY2_PARAM_SENSOR_CTRL_READ UINT8_C(0x80) +#define BHY2_PARAM_SENSOR_INFO_0 UINT16_C(0x300) +#define BHY2_PARAM_SENSOR_CONF_0 UINT16_C(0x500) + +#define BHY2_BSX_STATE_TRANSFER_COMPLETE UINT8_C(0x80) +#define BHY2_BSX_STATE_BLOCK_NUM_MSK UINT8_C(0x7F) +#define BHY2_BSX_STATE_BLOCK_LEN UINT8_C(64) +#define BHY2_BSX_STATE_STRUCT_LEN UINT8_C(68) + +#define BHY2_QUERY_PARAM_STATUS_READY_MAX_RETRY UINT16_C(1000) +#define BHY2_QUERY_FLASH_MAX_RETRY UINT16_C(1200) + +/*! Meta event definitions */ +#define BHY2_META_EVENT_FLUSH_COMPLETE (1) +#define BHY2_META_EVENT_SAMPLE_RATE_CHANGED (2) +#define BHY2_META_EVENT_POWER_MODE_CHANGED (3) +#define BHY2_META_EVENT_ALGORITHM_EVENTS (5) +#define BHY2_META_EVENT_SENSOR_STATUS (6) +#define BHY2_META_EVENT_BSX_DO_STEPS_MAIN (7) +#define BHY2_META_EVENT_BSX_DO_STEPS_CALIB (8) +#define BHY2_META_EVENT_BSX_GET_OUTPUT_SIGNAL (9) +#define BHY2_META_EVENT_RESERVED1 (10) +#define BHY2_META_EVENT_SENSOR_ERROR (11) +#define BHY2_META_EVENT_FIFO_OVERFLOW (12) +#define BHY2_META_EVENT_DYNAMIC_RANGE_CHANGED (13) +#define BHY2_META_EVENT_FIFO_WATERMARK (14) +#define BHY2_META_EVENT_RESERVED2 (15) +#define BHY2_META_EVENT_INITIALIZED (16) +#define BHY2_META_TRANSFER_CAUSE (17) +#define BHY2_META_EVENT_SENSOR_FRAMEWORK (18) +#define BHY2_META_EVENT_RESET (19) +#define BHY2_META_EVENT_SPACER (20) + +/* Flash start address in memory */ +#define BHY2_FLASH_SECTOR_START_ADDR UINT32_C(0x1F84) +#define BHY2_FLASH_BULK_ERASE UINT32_C(0xFFFFFFFF) + +/* End address for common flash sizes */ +#define BHY2_FLASH_SIZE_0_5MB UINT32_C(0x7FFFF) +#define BHY2_FLASH_SIZE_1MB UINT32_C(0xFFFFF) +#define BHY2_FLASH_SIZE_2MB UINT32_C(0x1FFFFF) +#define BHY2_FLASH_SIZE_4MB UINT32_C(0x3FFFFF) +#define BHY2_FLASH_SIZE_8MB UINT32_C(0x7FFFFF) + +/* Sensor IDs */ +#define BHY2_SENSOR_ID_CUSTOM_START UINT8_C(160) +#define BHY2_SENSOR_ID_CUSTOM_END UINT8_C(191) + +#define BHY2_SENSOR_ID_MAX UINT8_C(200) +#define BHY2_SENSOR_ID_TBD UINT8_C(BHY2_SENSOR_ID_MAX - 1) + +/* Virtual Sensor IDs */ +#define BHY2_SENSOR_ID_ACC_PASS UINT8_C(1) /* Accelerometer passthrough */ +#define BHY2_SENSOR_ID_ACC_RAW UINT8_C(3) /* Accelerometer uncalibrated */ +#define BHY2_SENSOR_ID_ACC UINT8_C(4) /* Accelerometer corrected */ +#define BHY2_SENSOR_ID_ACC_BIAS UINT8_C(5) /* Accelerometer offset */ +#define BHY2_SENSOR_ID_ACC_WU UINT8_C(6) /* Accelerometer corrected wake up */ +#define BHY2_SENSOR_ID_ACC_RAW_WU UINT8_C(7) /* Accelerometer uncalibrated wake up */ +#define BHY2_SENSOR_ID_SI_ACCEL UINT8_C(8) /* Virtual Sensor ID for Accelerometer */ +#define BHY2_SENSOR_ID_GYRO_PASS UINT8_C(10) /* Gyroscope passthrough */ +#define BHY2_SENSOR_ID_GYRO_RAW UINT8_C(12) /* Gyroscope uncalibrated */ +#define BHY2_SENSOR_ID_GYRO UINT8_C(13) /* Gyroscope corrected */ +#define BHY2_SENSOR_ID_GYRO_BIAS UINT8_C(14) /* Gyroscope offset */ +#define BHY2_SENSOR_ID_GYRO_WU UINT8_C(15) /* Gyroscope wake up */ +#define BHY2_SENSOR_ID_GYRO_RAW_WU UINT8_C(16) /* Gyroscope uncalibrated wake up */ +#define BHY2_SENSOR_ID_SI_GYROS UINT8_C(17) /* Virtual Sensor ID for Gyroscope */ +#define BHY2_SENSOR_ID_MAG_PASS UINT8_C(19) /* Magnetometer passthrough */ +#define BHY2_SENSOR_ID_MAG_RAW UINT8_C(21) /* Magnetometer uncalibrated */ +#define BHY2_SENSOR_ID_MAG UINT8_C(22) /* Magnetometer corrected */ +#define BHY2_SENSOR_ID_MAG_BIAS UINT8_C(23) /* Magnetometer offset */ +#define BHY2_SENSOR_ID_MAG_WU UINT8_C(24) /* Magnetometer wake up */ +#define BHY2_SENSOR_ID_MAG_RAW_WU UINT8_C(25) /* Magnetometer uncalibrated wake up */ +#define BHY2_SENSOR_ID_GRA UINT8_C(28) /* Gravity vector */ +#define BHY2_SENSOR_ID_GRA_WU UINT8_C(29) /* Gravity vector wake up */ +#define BHY2_SENSOR_ID_LACC UINT8_C(31) /* Linear acceleration */ +#define BHY2_SENSOR_ID_LACC_WU UINT8_C(32) /* Linear acceleration wake up */ +#define BHY2_SENSOR_ID_RV UINT8_C(34) /* Rotation vector */ +#define BHY2_SENSOR_ID_RV_WU UINT8_C(35) /* Rotation vector wake up */ +#define BHY2_SENSOR_ID_GAMERV UINT8_C(37) /* Game rotation vector */ +#define BHY2_SENSOR_ID_GAMERV_WU UINT8_C(38) /* Game rotation vector wake up */ +#define BHY2_SENSOR_ID_GEORV UINT8_C(40) /* Geo-magnetic rotation vector */ +#define BHY2_SENSOR_ID_GEORV_WU UINT8_C(41) /* Geo-magnetic rotation vector wake up */ +#define BHY2_SENSOR_ID_ORI UINT8_C(43) /* Orientation */ +#define BHY2_SENSOR_ID_ORI_WU UINT8_C(44) /* Orientation wake up */ +#define BHY2_SENSOR_ID_TILT_DETECTOR UINT8_C(48) /* Tilt detector */ +#define BHY2_SENSOR_ID_STD UINT8_C(50) /* Step detector */ +#define BHY2_SENSOR_ID_STC UINT8_C(52) /* Step counter */ +#define BHY2_SENSOR_ID_STC_WU UINT8_C(53) /* Step counter wake up */ +#define BHY2_SENSOR_ID_SIG UINT8_C(55) /* Significant motion */ +#define BHY2_SENSOR_ID_WAKE_GESTURE UINT8_C(57) /* Wake gesture */ +#define BHY2_SENSOR_ID_GLANCE_GESTURE UINT8_C(59) /* Glance gesture */ +#define BHY2_SENSOR_ID_PICKUP_GESTURE UINT8_C(61) /* Pickup gesture */ +#define BHY2_SENSOR_ID_AR UINT8_C(63) /* Activity recognition */ +#define BHY2_SENSOR_ID_WRIST_TILT_GESTURE UINT8_C(67) /* Wrist tilt gesture */ +#define BHY2_SENSOR_ID_DEVICE_ORI UINT8_C(69) /* Device orientation */ +#define BHY2_SENSOR_ID_DEVICE_ORI_WU UINT8_C(70) /* Device orientation wake up */ +#define BHY2_SENSOR_ID_STATIONARY_DET UINT8_C(75) /* Stationary detect */ +#define BHY2_SENSOR_ID_MOTION_DET UINT8_C(77) /* Motion detect */ +#define BHY2_SENSOR_ID_ACC_BIAS_WU UINT8_C(91) /* Accelerometer offset wake up */ +#define BHY2_SENSOR_ID_GYRO_BIAS_WU UINT8_C(92) /* Gyroscope offset wake up */ +#define BHY2_SENSOR_ID_MAG_BIAS_WU UINT8_C(93) /* Magnetometer offset wake up */ +#define BHY2_SENSOR_ID_STD_WU UINT8_C(94) /* Step detector wake up */ +#define BHY2_SENSOR_ID_TEMP UINT8_C(128) /* Temperature */ +#define BHY2_SENSOR_ID_BARO UINT8_C(129) /* Barometer */ +#define BHY2_SENSOR_ID_HUM UINT8_C(130) /* Humidity */ +#define BHY2_SENSOR_ID_GAS UINT8_C(131) /* Gas */ +#define BHY2_SENSOR_ID_TEMP_WU UINT8_C(132) /* Temperature wake up */ +#define BHY2_SENSOR_ID_BARO_WU UINT8_C(133) /* Barometer wake up */ +#define BHY2_SENSOR_ID_HUM_WU UINT8_C(134) /* Humidity wake up */ +#define BHY2_SENSOR_ID_GAS_WU UINT8_C(135) /* Gas wake up */ +#define BHY2_SENSOR_ID_STC_LP UINT8_C(136) /* Step counter Low Power */ +#define BHY2_SENSOR_ID_STD_LP UINT8_C(137) /* Step detector Low Power */ +#define BHY2_SENSOR_ID_SIG_LP UINT8_C(138) /* Significant motion Low Power */ +#define BHY2_SENSOR_ID_STC_LP_WU UINT8_C(139) /* Step counter Low Power wake up */ +#define BHY2_SENSOR_ID_STD_LP_WU UINT8_C(140) /* Step detector Low Power wake up */ +#define BHY2_SENSOR_ID_SIG_LP_WU UINT8_C(141) /* Significant motion Low Power wake up */ +#define BHY2_SENSOR_ID_ANY_MOTION_LP UINT8_C(142) /* Any motion Low Power */ +#define BHY2_SENSOR_ID_ANY_MOTION_LP_WU UINT8_C(143) /* Any motion Low Power wake up */ +#define BHY2_SENSOR_ID_EXCAMERA UINT8_C(144) /* External camera trigger */ +#define BHY2_SENSOR_ID_GPS UINT8_C(145) /* GPS */ +#define BHY2_SENSOR_ID_LIGHT UINT8_C(146) /* Light */ +#define BHY2_SENSOR_ID_PROX UINT8_C(147) /* Proximity */ +#define BHY2_SENSOR_ID_LIGHT_WU UINT8_C(148) /* Light wake up */ +#define BHY2_SENSOR_ID_PROX_WU UINT8_C(149) /* Proximity wake up */ + +/*! Physical sensor IDs*/ +#define BHY2_PHYS_SENSOR_ID_ACCELEROMETER UINT8_C(1) +#define BHY2_PHYS_SENSOR_ID_GYROSCOPE UINT8_C(3) +#define BHY2_PHYS_SENSOR_ID_MAGNETOMETER UINT8_C(5) +#define BHY2_PHYS_SENSOR_ID_TEMP_GYRO UINT8_C(7) +#define BHY2_PHYS_SENSOR_ID_ANY_MOTION UINT8_C(9) +#define BHY2_PHYS_SENSOR_ID_PRESSURE UINT8_C(11) +#define BHY2_PHYS_SENSOR_ID_POSITION UINT8_C(13) +#define BHY2_PHYS_SENSOR_ID_HUMIDITY UINT8_C(15) +#define BHY2_PHYS_SENSOR_ID_TEMPERATURE UINT8_C(17) +#define BHY2_PHYS_SENSOR_ID_GAS_RESISTOR UINT8_C(19) +#define BHY2_PHYS_SENSOR_ID_PHYS_STEP_COUNTER UINT8_C(32) +#define BHY2_PHYS_SENSOR_ID_PHYS_STEP_DETECTOR UINT8_C(33) +#define BHY2_PHYS_SENSOR_ID_PHYS_SIGN_MOTION UINT8_C(34) +#define BHY2_PHYS_SENSOR_ID_PHYS_ANY_MOTION UINT8_C(35) +#define BHY2_PHYS_SENSOR_ID_EX_CAMERA_INPUT UINT8_C(36) +#define BHY2_PHYS_SENSOR_ID_GPS UINT8_C(48) +#define BHY2_PHYS_SENSOR_ID_LIGHT UINT8_C(49) +#define BHY2_PHYS_SENSOR_ID_PROXIMITY UINT8_C(50) +#define BHY2_PHYS_SENSOR_ID_PHYS_NO_MOTION UINT8_C(55) +#define BHY2_PHYS_SENSOR_ID_WRIST_GESTURE_DETECT UINT8_C(56) +#define BHY2_PHYS_SENSOR_ID_WRIST_WEAR_WAKEUP UINT8_C(57) + +/*! System data IDs */ +#define BHY2_IS_SYS_ID(sid) ((sid) >= 224) + +#define BHY2_SYS_ID_PADDING UINT8_C(0) +#define BHY2_SYS_ID_TS_SMALL_DELTA UINT8_C(251) +#define BHY2_SYS_ID_TS_LARGE_DELTA UINT8_C(252) +#define BHY2_SYS_ID_TS_FULL UINT8_C(253) +#define BHY2_SYS_ID_META_EVENT UINT8_C(254) +#define BHY2_SYS_ID_TS_SMALL_DELTA_WU UINT8_C(245) +#define BHY2_SYS_ID_TS_LARGE_DELTA_WU UINT8_C(246) +#define BHY2_SYS_ID_TS_FULL_WU UINT8_C(247) +#define BHY2_SYS_ID_META_EVENT_WU UINT8_C(248) +#define BHY2_SYS_ID_FILLER UINT8_C(255) +#define BHY2_SYS_ID_DEBUG_MSG UINT8_C(250) +#define BHY2_SYS_ID_BHY2_LOG_UPDATE_SUB UINT8_C(243) +#define BHY2_SYS_ID_BHY2_LOG_DOSTEP UINT8_C(244) + +/*! Status code definitions */ +#define BHY2_STATUS_INITIALIZED UINT8_C(0x1) +#define BHY2_STATUS_DEBUG_OUTPUT UINT8_C(0x2) +#define BHY2_STATUS_CRASH_DUMP UINT8_C(0x3) +#define BHY2_STATUS_INJECT_SENSOR_CONF_REQ UINT8_C(0x4) +#define BHY2_STATUS_SW_PASS_THRU_RES UINT8_C(0x5) +#define BHY2_STATUS_SELF_TEST_RES UINT8_C(0x6) +#define BHY2_STATUS_FOC_RES UINT8_C(0x7) +#define BHY2_STATUS_SYSTEM_ERROR UINT8_C(0x8) +#define BHY2_STATUS_SENSOR_ERROR UINT8_C(0x9) +#define BHY2_STATUS_FLASH_ERASE_COMPLETE UINT8_C(0xA) +#define BHY2_STATUS_FLASH_WRITE_COMPLETE UINT8_C(0xB) +#define BHY2_STATUS_FLASH_CONTINUE_UPLOAD UINT8_C(0xC) +#define BHY2_STATUS_HOST_EV_TIMESTAMP UINT8_C(0xD) +#define BHY2_STATUS_DUT_TEST_RES UINT8_C(0xE) +#define BHY2_STATUS_CMD_ERR UINT8_C(0xF) + +#define BHY2_IS_STATUS_GET_PARAM_OUTPUT(status) ((status) >= 0x100 && (status) <= 0xFFF) + +/*! Activity bits */ +#define BHY2_STILL_ACTIVITY_ENDED (0x0001) +#define BHY2_WALKING_ACTIVITY_ENDED (0x0002) +#define BHY2_RUNNING_ACTIVITY_ENDED (0x0004) +#define BHY2_ON_BICYCLE_ACTIVITY_ENDED (0x0008) +#define BHY2_IN_VEHICLE_ACTIVITY_ENDED (0x0010) +#define BHY2_TILTING_ACTIVITY_ENDED (0x0020) + +#define BHY2_STILL_ACTIVITY_STARTED (0x0100) +#define BHY2_WALKING_ACTIVITY_STARTED (0x0200) +#define BHY2_RUNNING_ACTIVITY_STARTED (0x0400) +#define BHY2_ON_BICYCLE_ACTIVITY_STARTED (0x0800) +#define BHY2_IN_VEHICLE_ACTIVITY_STARTED (0x1000) +#define BHY2_TILTING_ACTIVITY_STARTED (0x2000) + +/*! Feature status */ +#define BHY2_FEAT_STATUS_FLASH_DESC_MSK UINT8_C(0x01) +#define BHY2_FEAT_STATUS_OPEN_RTOS_MSK UINT8_C(0x02) +#define BHY2_FEAT_STATUS_OPEN_RTOS_POS (1) +#define BHY2_FEAT_STATUS_HOST_ID_MSK UINT8_C(0x1C) +#define BHY2_FEAT_STATUS_HOST_ID_POS (2) +#define BHY2_FEAT_STATUS_ALGO_ID_MSK UINT8_C(0xE0) +#define BHY2_FEAT_STATUS_ALGO_ID_POS (5) + +/*! Fast offset compensation status codes */ +#define BHY2_FOC_PASS UINT8_C(0x00) +#define BHY2_FOC_FAILED UINT8_C(0x65) +#define BHY2_FOC_UNKNOWN_FAILURE UINT8_C(0x23) + +/*! Self test status codes */ +#define BHY2_ST_PASSED UINT8_C(0x00) +#define BHY2_ST_X_AXIS_FAILED UINT8_C(0x01) +#define BHY2_ST_Y_AXIS_FAILED UINT8_C(0x02) +#define BHY2_ST_Z_AXIS_FAILED UINT8_C(0x04) +#define BHY2_ST_MULTI_AXIS_FAILURE UINT8_C(0x07) +#define BHY2_ST_NOT_SUPPORTED UINT8_C(0x08) +#define BHY2_ST_INVALID_PHYS_ID UINT8_C(0x09) + +#define BHY2_LE2U16(x) ((uint16_t)((x)[0] | (x)[1] << 8)) +#define BHY2_LE2S16(x) ((int16_t)BHY2_LE2U16(x)) +#define BHY2_LE2U24(x) ((uint32_t)((x)[0] | (uint32_t)(x)[1] << 8 | (uint32_t)(x)[2] << 16)) +#define BHY2_LE2S24(x) ((int32_t)(BHY2_LE2U24(x) << 8) >> 8) +#define BHY2_LE2U32(x) ((uint32_t)((x)[0] | (uint32_t)(x)[1] << 8 | (uint32_t)(x)[2] << 16 | \ + (uint32_t)(x)[3] << 24)) +#define BHY2_LE2S32(x) ((int32_t)BHY2_LE2U32(x)) +#define BHY2_LE2U40(x) (BHY2_LE2U32(x) | (uint64_t)(x)[4] << 32) +#define BHY2_LE2U64(x) (BHY2_LE2U32(x) | (uint64_t)BHY2_LE2U32(&(x)[4]) << 32) + +#define BHY2_LE24MUL(x) (((x) % 4) ? (uint16_t)((((x) / 4) + 1) * 4) : (uint16_t)((x) + 4)) + +/*! Maximum no of available virtual sensor */ +#define BHY2_N_VIRTUAL_SENSOR_MAX UINT8_C(256) + +#ifndef BHY2_MAX_SIMUL_SENSORS +#define BHY2_MAX_SIMUL_SENSORS 48 +#endif + +/* Special & debug virtual sensor id starts at 245 */ +#define BHY2_SPECIAL_SENSOR_ID_OFFSET UINT8_C(245) + +#ifndef BHY2_INTF_RET_TYPE +#define BHY2_INTF_RET_TYPE int8_t +#endif + +#ifndef BHY2_INTF_RET_SUCCESS +#define BHY2_INTF_RET_SUCCESS 0 +#endif + +/* Type definitions for the function pointers */ +typedef BHY2_INTF_RET_TYPE (*bhy2_read_fptr_t)(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); +typedef BHY2_INTF_RET_TYPE (*bhy2_write_fptr_t)(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, + void *intf_ptr); +typedef void (*bhy2_delay_us_fptr_t)(uint32_t period_us, void *intf_ptr); + +enum bhy2_intf { + BHY2_SPI_INTERFACE = 1, + BHY2_I2C_INTERFACE +}; + +/* HIF device structure */ +struct bhy2_hif_dev { + bhy2_read_fptr_t read; + bhy2_write_fptr_t write; + bhy2_delay_us_fptr_t delay_us; + enum bhy2_intf intf; + void *intf_ptr; + BHY2_INTF_RET_TYPE intf_rslt; + uint32_t read_write_len; +}; + +enum bhy2_fifo_type { + BHY2_FIFO_TYPE_WAKEUP, + BHY2_FIFO_TYPE_NON_WAKEUP, + BHY2_FIFO_TYPE_STATUS, + BHY2_FIFO_TYPE_MAX +}; + +struct BHY2_PACKED bhy2_fifo_parse_data_info { + uint8_t sensor_id; + enum bhy2_fifo_type fifo_type; + uint8_t data_size; + uint8_t *data_ptr; + uint64_t *time_stamp; +}; + +typedef void (*bhy2_fifo_parse_callback_t)(const struct bhy2_fifo_parse_data_info *callback_info, void *private_data); + +struct BHY2_PACKED bhy2_fifo_parse_callback_table { + uint8_t sensor_id; + bhy2_fifo_parse_callback_t callback; + void *callback_ref; +}; + +/* Device structure */ +struct bhy2_dev { + struct bhy2_hif_dev hif; + struct bhy2_fifo_parse_callback_table table[BHY2_MAX_SIMUL_SENSORS]; + uint8_t event_size[BHY2_N_VIRTUAL_SENSOR_MAX]; + uint64_t last_time_stamp[BHY2_FIFO_TYPE_MAX]; + uint8_t present_buff[32]; +}; + +struct bhy2_fifo_buffer { + uint32_t read_pos; + uint32_t read_length; + uint32_t remain_length; + uint32_t buffer_size; + uint8_t *buffer; +}; + +typedef int16_t (*bhy2_frame_parse_func_t)(struct bhy2_fifo_buffer *p_fifo_buffer, struct bhy2_dev *bhy2_p); + +struct bhy2_virt_sensor_conf { + uint16_t sensitivity; + uint16_t range; + uint32_t latency; + bhy2_float sample_rate; +}; + +struct bhy2_data_xyz { + int16_t x; + int16_t y; + int16_t z; +}; + +struct bhy2_data_quaternion { + int16_t x; + int16_t y; + int16_t z; + int16_t w; + uint16_t accuracy; +}; + +struct bhy2_data_orientation { + int16_t heading; + int16_t pitch; + int16_t roll; +}; + +union BHY2_PACKED bhy2_spt_dev_id { + uint8_t slave_address; + uint8_t cs_pin; +}; + +struct BHY2_PACKED bhy2_spt_bits { + /*! byte 1 */ + uint8_t direction : 1; /**< 0: read; 1: write. */ + uint8_t trans_type : 1; /**< 0: single burst; 1:multi single transfers. */ + uint8_t delay_ctrl : 1; /**< 0: none; 1: delay between bytes. */ + uint8_t master_bus : 2; /**< 1: SIF1; 2: SIF2; 3:SIF3. */ + uint8_t spi_mode : 1; /**< 0: 4 wire; 1: 3 wire. */ + uint8_t cpol : 1; /**< spi clock polarity. */ + uint8_t cpha : 1; /**< spi clock phase. */ + /*! byte 2 */ + uint8_t delay_val : 6; /**< multiples of 50us. min is 200us (4LSB) */ + uint8_t cs_level : 1; /**< chip select level. */ + uint8_t lsb_first : 1; /**< least significant byte first. */ + /*! byte 3~4 */ + uint16_t trans_rate; /**< spi clock rate. */ + /*! byte 5 */ + uint8_t address_shift : 4; /**< number of bits to shift register address. */ + uint8_t read_bit_pol : 1; /**< 0: active low; 1: active high. */ + uint8_t read_bit_pos : 3; /**< bit number of read bit in command byte. */ + /*! byte 6 */ + union bhy2_spt_dev_id func_set; + + /*! byte 7 */ + uint8_t trans_count; + + /*! byte 8 */ + uint8_t reg; +}; + +union bhy2_soft_passthrough_conf { + struct bhy2_spt_bits conf; + uint8_t data[8]; +}; + +union bhy2_u16_conv { + uint16_t u16_val; + uint8_t bytes[2]; +}; +union bhy2_u32_conv { + uint32_t u32_val; + uint8_t bytes[4]; +}; +union bhy2_float_conv { + bhy2_float f_val; + uint32_t u32_val; + uint8_t bytes[4]; +}; +struct bhy2_sensor_info { + uint8_t sensor_type; + uint8_t driver_id; + uint8_t driver_version; + uint8_t power; + union bhy2_u16_conv max_range; + union bhy2_u16_conv resolution; + union bhy2_float_conv max_rate; + union bhy2_u32_conv fifo_reserved; + union bhy2_u32_conv fifo_max; + uint8_t event_size; + union bhy2_float_conv min_rate; +}; + +struct bhy2_phys_sensor_info { + uint8_t sensor_type; + uint8_t driver_id; + uint8_t driver_version; + uint8_t power_current; + union bhy2_u16_conv curr_range; + uint8_t flags; + uint8_t slave_address; + uint8_t gpio_assignment; + union bhy2_float_conv curr_rate; + uint8_t num_axis; + uint8_t orientation_matrix[5]; + uint8_t reserved; +}; + +struct bhy2_self_test_resp { + uint8_t test_status; + int16_t x_offset, y_offset, z_offset; +}; + +struct bhy2_foc_resp { + uint8_t foc_status; + int16_t x_offset, y_offset, z_offset; +}; + +struct bhy2_orient_matrix { + int8_t c[9]; +}; + +enum bhy2_data_inj_mode { + BHY2_NORMAL_MODE = 0, + BHY2_REAL_TIME_INJECTION = 1, + BHY2_STEP_BY_STEP_INJECTION = 2 +}; + +#define BHY2_BYTE_TO_NIBBLE(X) (((uint8_t)(X)[0] & 0x0F) | (((uint8_t)(X)[1] << 4) & 0xF0)) + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* __BHY2_DEFS_H__ */ diff --git a/lib/SensorLib/src/bosch/bhy2_head_tracker.c b/lib/SensorLib/src/bosch/bhy2_head_tracker.c new file mode 100644 index 0000000..263cd19 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_head_tracker.c @@ -0,0 +1,353 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_head_tracker.c +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include + +/*********************************************************************/ +/* BHY2 SensorAPI header files */ +/*********************************************************************/ +#include "bhy2.h" + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "bhy2_head_tracker.h" + +/*Parsing callback for Head Orientation Quaternion*/ +void bhy2_head_tracker_quat_parsing(const uint8_t *payload, struct bhy2_head_tracker_quat_data *data) +{ + uint8_t i = 0; + + if ((payload != NULL) && (data != NULL)) + { + data->x = BHY2_LE2S16(&payload[i]); + i += 2; + data->y = BHY2_LE2S16(&payload[i]); + i += 2; + data->z = BHY2_LE2S16(&payload[i]); + i += 2; + data->w = BHY2_LE2S16(&payload[i]); + i += 2; + data->accuracy = payload[i]; + } +} + +/*Parsing callback for Head Orientation Euler*/ +void bhy2_head_tracker_eul_parsing(const uint8_t *payload, struct bhy2_head_tracker_eul_data *data) +{ + uint8_t i = 0; + + if ((payload != NULL) && (data != NULL)) + { + data->heading = BHY2_LE2S16(&payload[i]); + i += 2; + data->pitch = BHY2_LE2S16(&payload[i]); + i += 2; + data->roll = BHY2_LE2S16(&payload[i]); + i += 2; + data->accuracy = payload[i]; + } +} + +/*Callback for triggering Head Misalignment Calibration*/ +int8_t bhy2_head_tracker_trigger_hmc_calibration(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Trigger Head Misalignment Calibration */ + rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_TRIGGER_CALIB), + (uint8_t*)buffer, + BHY2_HEAD_ORI_HMC_TRIGGER_CALIB_LENGTH, + dev); + } + + return rslt; +} + +/*Callback for setting Head Misalignment Calibration Configuration*/ +int8_t bhy2_head_tracker_set_hmc_configuration(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set Head Misalignment Configuration */ + rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_CONFIG), + (uint8_t*)buffer, + BHY2_HEAD_ORI_HMC_CONFIG_LENGTH, + dev); + } + + return rslt; +} + +/*Callback for getting Head Misalignment Calibration Configuration*/ +int8_t bhy2_head_tracker_get_hmc_configuration(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t act_len; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get Head Misalignment Configuration */ + rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_CONFIG), + (uint8_t*)buffer, + BHY2_HEAD_ORI_HMC_CONFIG_LENGTH, + &act_len, + dev); + } + + return rslt; +} + +/*Callback for setting default Head Misalignment Calibration Configuration*/ +int8_t bhy2_head_tracker_set_default_hmc_configuration(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set default Head Misalignment Configuration */ + rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG), + (uint8_t*)buffer, + BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG_LENGTH, + dev); + } + + return rslt; +} + +/*Callback for getting Head Misalignment Calibrator Version*/ +int8_t bhy2_head_tracker_get_hmc_version(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t act_len; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get Head Misalignment Calibrator Version */ + rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_VERSION), + (uint8_t*)buffer, + BHY2_HEAD_ORI_HMC_VERSION_LENGTH, + &act_len, + dev); + } + + return rslt; +} + +/*Callback for setting Head Misalignment Calibration Correction Quaternion Configuration*/ +int8_t bhy2_head_tracker_set_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set Head Misalignment Calibration Correction Quaternion Configuration */ + rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR), + (uint8_t*)buffer, + BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_WLENGTH, + dev); + } + + return rslt; +} + +/*Callback for getting Head Misalignment Calibration Correction Quaternion Configuration*/ +int8_t bhy2_head_tracker_get_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t act_len; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get Head Misalignment Calibration Correction Quaternion Configuration */ + rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR), + (uint8_t*)buffer, + BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_RLENGTH, + &act_len, + dev); + } + + return rslt; +} + +/*Callback for setting Head Orientation Initial Head Correction for Quaternion*/ +int8_t bhy2_head_tracker_set_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set Head Orientation Initial Head Correction for Quaternion */ + rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR), + (uint8_t*)buffer, + BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_LENGTH, + dev); + } + + return rslt; +} + +/*Callback for getting Head Orientation Initial Head Correction for Quaternion*/ +int8_t bhy2_head_tracker_get_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t act_len; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get Head Orientation Initial Head Correction for Quaternion */ + rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR), + (uint8_t*)buffer, + BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_LENGTH, + &act_len, + dev); + } + + return rslt; +} + +/*Callback for getting Head Orientation Version*/ +int8_t bhy2_head_tracker_get_ho_version(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t act_len; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get IMU/NDOF Head Orientation Version */ + rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_VERSION), + (uint8_t*)buffer, + BHY2_HEAD_ORI_VERSION_LENGTH, + &act_len, + dev); + } + + return rslt; +} + +/*Callback for setting Head Orientation Initial Head Correction for Euler*/ +int8_t bhy2_head_tracker_set_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set Head Orientation Initial Head Correction for Euler */ + rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR), + (uint8_t*)buffer, + BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_LENGTH, + dev); + } + + return rslt; +} + +/*Callback for getting Head Orientation Initial Head Correction for Euler*/ +int8_t bhy2_head_tracker_get_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint32_t act_len; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get Head Orientation Initial Head Correction for Euler */ + rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR), + (uint8_t*)buffer, + BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_LENGTH, + &act_len, + dev); + } + + return rslt; +} diff --git a/lib/SensorLib/src/bosch/bhy2_head_tracker.h b/lib/SensorLib/src/bosch/bhy2_head_tracker.h new file mode 100644 index 0000000..94a5f31 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_head_tracker.h @@ -0,0 +1,213 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_head_tracker.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef _BHY2_HEAD_TRACKER_H_ +#define _BHY2_HEAD_TRACKER_H_ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include +#include +#include + +#include "bhy2.h" +#include "bhy2_head_tracker_defs.h" + +/*! + * @brief Parsing callback for Head Orientation Quaternion + * + * @param[in] payload + * @param[out] bhy2_head_tracker_quat_data to store Head Orientation [Quaternion] data + * + * @return API error codes + * + */ +void bhy2_head_tracker_quat_parsing(const uint8_t *payload, struct bhy2_head_tracker_quat_data *data); + +/*! + * @brief Parsing callback for Head Orientation Euler + * + * @param[in] payload + * @param[out] bhy2_head_tracker_eul_data to store Head Orientation [Euler] data + * + * @return API error codes + * + */ +void bhy2_head_tracker_eul_parsing(const uint8_t *payload, struct bhy2_head_tracker_eul_data *data); + +/*! + * @brief To trigger the Head Misalignment Calibration + * + * @param[in] buffer + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_trigger_hmc_calibration(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To set the Head Misalignment Calibration Configuration + * + * @param[in] buffer to hold the Head Misalignment Calibration Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_set_hmc_configuration(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the Head Misalignment Calibration Configuration + * + * @param[out] buffer to hold the Head Misalignment Calibration Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_get_hmc_configuration(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To set the default Head Misalignment Calibration Configuration + * + * @param[in] command buffer + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_set_default_hmc_configuration(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the Head Misalignment Calibrator Version + * + * @param[out] buffer to hold the Head Misalignment Calibrator Version + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_get_hmc_version(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To set the Head Misalignment Quaternion Calibration Correction Configuration + * + * @param[in] buffer to hold the Head Misalignment Quaternion Calibration Correction Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_set_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the Head Misalignment Quaternion Calibration Correction Configuration + * + * @param[out] buffer to hold the Head Misalignment Quaternion Calibration Correction Configuration + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_get_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To set the Head Misalignment Quaternion Initial Head Correction + * + * @param[in] buffer to hold the Head Misalignment Quaternion Initial Head Correction + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_set_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the Head Misalignment Quaternion Initial Head Correction + * + * @param[out] buffer to hold the Head Misalignment Quaternion Initial Head Correction + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_get_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the IMU/NDOF Head Orientation Version + * + * @param[out] buffer to hold the IMU/NDOF Head Orientation Version + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_get_ho_version(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To set the Head Misalignment Euler Initial Head Correction + * + * @param[in] buffer to hold the Head Misalignment Euler Initial Head Correction + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_set_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the Head Misalignment Euler Initial Head Correction + * + * @param[out] buffer to hold the Head Misalignment Euler Initial Head Correction + * @param[in] dev hub handle + * + * @return API error codes + * + */ +int8_t bhy2_head_tracker_get_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* _BHY2_HEAD_TRACKER_H_ */ diff --git a/lib/SensorLib/src/bosch/bhy2_head_tracker_defs.h b/lib/SensorLib/src/bosch/bhy2_head_tracker_defs.h new file mode 100644 index 0000000..3c2c03a --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_head_tracker_defs.h @@ -0,0 +1,138 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_head_tracker_defs.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef _BHY2_HEAD_TRACKER_DEFS_H_ +#define _BHY2_HEAD_TRACKER_DEFS_H_ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include +#include +#include + +#include "bhy2.h" + +/*! Virtual Sensor Macros */ +#define BHY2_SENSOR_ID_HEAD_ORI_MIS_ALG UINT8_C(120) /*Head Orientation Misalignment*/ +#define BHY2_SENSOR_ID_IMU_HEAD_ORI_Q UINT8_C(121) /*IMU Head Orientation Quaternion*/ +#define BHY2_SENSOR_ID_NDOF_HEAD_ORI_Q UINT8_C(122) /*NDOF Head Orientation Quaternion*/ +#define BHY2_SENSOR_ID_IMU_HEAD_ORI_E UINT8_C(123) /*IMU Head Orientation Euler*/ +#define BHY2_SENSOR_ID_NDOF_HEAD_ORI_E UINT8_C(124) /*NDOF Head Orientation Euler*/ + +#define BHY2_HEAD_ORI_PAGE UINT16_C(12) +#define BHY2_HEAD_ORI_PARAM(id) (((BHY2_HEAD_ORI_PAGE) << 8) | (id)) + +#define BHY2_HEAD_ORI_HMC_TRIGGER_CALIB UINT8_C(1) +#define BHY2_HEAD_ORI_HMC_TRIGGER_CALIB_LENGTH UINT8_C(4) +#define BHY2_HEAD_ORI_HMC_TRIGGER_CALIB_SET UINT8_C(1) + +#define BHY2_HEAD_ORI_HMC_CONFIG UINT8_C(2) +#define BHY2_HEAD_ORI_HMC_CONFIG_LENGTH UINT8_C(8) + +#define BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG UINT8_C(3) +#define BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG_LENGTH UINT8_C(4) +#define BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG_SET UINT8_C(1) + +#define BHY2_HEAD_ORI_HMC_VERSION UINT8_C(4) +#define BHY2_HEAD_ORI_HMC_VERSION_LENGTH UINT8_C(4) + +#define BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR UINT8_C(5) +#define BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_WLENGTH UINT8_C(16) +#define BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_RLENGTH UINT8_C(20) + +#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR UINT8_C(10) +#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_LENGTH UINT8_C(4) +#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_DISABLE UINT8_C(0) +#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_ENABLE UINT8_C(1) + +#define BHY2_HEAD_ORI_VERSION UINT8_C(11) +#define BHY2_HEAD_ORI_VERSION_LENGTH UINT8_C(4) + +#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR UINT8_C(12) +#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_LENGTH UINT8_C(4) +#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_DISABLE UINT8_C(0) +#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_ENABLE UINT8_C(1) + +/*! Sensor Structure for Head Orientation Quaternion */ +struct bhy2_head_tracker_quat_data +{ + int16_t x, y, z, w; + uint8_t accuracy; +}; + +/*! Sensor Structure for Head Orientation Euler */ +struct bhy2_head_tracker_eul_data +{ + int16_t heading, pitch, roll; + uint8_t accuracy; +}; + +/*! Structure for Head Misalignment Configuration */ +struct bhy2_head_tracker_misalignment_config +{ + uint8_t still_phase_max_dur; + uint8_t still_phase_min_dur; + uint8_t still_phase_max_samples; + int32_t acc_diff_threshold; +}; + +/*! Structure for Head Orientation /Head Misalignment version */ +struct bhy2_head_tracker_ver +{ + uint8_t major, minor, patch, reserved; +}; + +/*! Structure for Head Misalignment Quaternion Correction */ +struct bhy2_head_tracker_misalignment_quat_corr +{ + int32_t quaternion_x; + int32_t quaternion_y; + int32_t quaternion_z; + int32_t quaternion_w; + int32_t accuracy; +}; + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* _BHY2_HEAD_TRACKER_DEFS_H_ */ diff --git a/lib/SensorLib/src/bosch/bhy2_hif.c b/lib/SensorLib/src/bosch/bhy2_hif.c new file mode 100644 index 0000000..c243936 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_hif.c @@ -0,0 +1,1757 @@ +/** + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file bhy2_hif.c + * @date 2023-03-24 + * @version v1.6.0 + * + */ + +#include "bhy2_hif.h" + +/*! Mask definitions for SPI read/write address */ +#define BHY2_SPI_RD_MASK UINT8_C(0x80) +#define BHY2_SPI_WR_MASK UINT8_C(0x7F) + +union bhy2_hif_float_u32 +{ + bhy2_float as_float; + uint32_t reg; +}; + +static void bhy2_hif_exec_cmd_generic_support(const uint16_t *cmd, + uint8_t *cmd_buf, + uint32_t *temp_length, + uint32_t *total_length, + const uint32_t *len, + const uint32_t *pre_len, + const uint32_t *cmd_len) +{ + *total_length = *pre_len + *len; + + if (*cmd_len) + { + *temp_length = *pre_len + *cmd_len; + } + else + { + *temp_length = *total_length; + } + + /* Align 4 bytes */ + if (*temp_length % 4) + { + + *temp_length = BHY2_ROUND_WORD_HIGHER(*temp_length); + } + + cmd_buf[0] = (uint8_t)(*cmd & 0xFF); + cmd_buf[1] = (uint8_t)((*cmd >> 8) & 0xFF); + + /* Length in word */ + if (*cmd == BHY2_CMD_UPLOAD_TO_PROGRAM_RAM) + { + cmd_buf[2] = (*temp_length / 4) & 0xFF; + cmd_buf[3] = ((*temp_length / 4) >> 8) & 0xFF; + } + /* Length in byte */ + else + { + cmd_buf[2] = *temp_length & 0xFF; + cmd_buf[3] = (*temp_length >> 8) & 0xFF; + } +} + +/* + * If a command need several frames to upload to sensor, + * this command only be used in the first frame. + * + * |------------------------------------------------|---------------| + * |<-- frame one -->|<--frame two-->| + * |------------------------------------------------|---------------| + * | |<--pre_length-->|<--length-->| | + * |------------------|----------------|------------|---------------| + * | cmd | cmd_length | pre_payload | data 1 | data 2 | + * |-----------------------------------|------------|---------------| + * | payload | + * |------------|---------------| + * |<-- cmd_length -->| + * |----------------------------| + */ +static int8_t bhy2_hif_exec_cmd_generic(uint16_t cmd, + const uint8_t *payload, + uint32_t length, + const uint8_t *pre_payload, + uint32_t pre_length, + uint32_t cmd_length, + struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + uint32_t remain, trans_len, copy_len, pos, total_len, temp_total_len, loop_remain_len, max_len; + uint8_t command_buf[BHY2_COMMAND_PACKET_LEN]; + + if ((hif != NULL) && !((length != 0) && (payload == NULL)) && !((pre_length != 0) && (pre_payload == NULL))) + { + if (hif->read_write_len != 0) + { + bhy2_hif_exec_cmd_generic_support(&cmd, + command_buf, + &temp_total_len, + &total_len, + &length, + &pre_length, + &cmd_length); + pos = BHY2_COMMAND_HEADER_LEN; + remain = total_len; + loop_remain_len = remain + pos; + max_len = BHY2_COMMAND_PACKET_LEN - BHY2_COMMAND_HEADER_LEN; + + if (hif->read_write_len < max_len) + { + max_len = hif->read_write_len; + } + + while ((loop_remain_len > 0) && (rslt == BHY2_OK)) + { + if ((remain + pos) > max_len) + { + trans_len = max_len; + copy_len = max_len - pos; + } + else + { + trans_len = remain + pos; + copy_len = remain; + + /* Align to 4 bytes */ + if (trans_len % 4) + { + + trans_len = BHY2_ROUND_WORD_HIGHER(trans_len); + } + + if (trans_len > (BHY2_COMMAND_PACKET_LEN - BHY2_COMMAND_HEADER_LEN)) + { + trans_len = BHY2_COMMAND_PACKET_LEN - BHY2_COMMAND_HEADER_LEN; + } + } + + if (copy_len > 0) + { + if (remain >= (length + copy_len)) + { + memcpy(&command_buf[pos], &pre_payload[total_len - remain], copy_len); + } + else if (remain > length) + { + memcpy(&command_buf[pos], &pre_payload[total_len - remain], remain - length); + memcpy(&command_buf[pos + remain - length], payload, copy_len - (remain - length)); + } + else + { + memcpy(&command_buf[pos], &payload[length - remain], copy_len); + } + } + + if ((trans_len - (pos + copy_len)) > 0) + { + memset(&command_buf[pos + copy_len], 0, BHY2_COMMAND_PACKET_LEN - (pos + copy_len)); + } + + rslt = bhy2_hif_set_regs(BHY2_REG_CHAN_CMD, command_buf, trans_len, hif); + if (rslt != BHY2_OK) + { + break; + } + + pos = 0; + remain -= copy_len; + loop_remain_len = remain; + } + } + else + { + rslt = BHY2_E_INVALID_PARAM; + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_wait_status_ready(struct bhy2_hif_dev *hif) +{ + uint16_t retry; + uint8_t int_status; + int8_t rslt; + + /* Wait status ready */ + for (retry = 0; retry < BHY2_QUERY_PARAM_STATUS_READY_MAX_RETRY; ++retry) + { + rslt = bhy2_hif_get_interrupt_status(&int_status, hif); + if (rslt == BHY2_OK) + { + if (int_status & BHY2_IST_MASK_STATUS) + { + rslt = BHY2_OK; + break; + } + + /* 10ms */ + rslt = bhy2_hif_delay_us(10000, hif); + if (rslt != BHY2_OK) + { + return rslt; + } + } + else + { + return rslt; /*break; */ + } + } + + return rslt; +} + +static int8_t bhy2_hif_check_boot_status_ram(struct bhy2_hif_dev *hif) +{ + int8_t rslt; + uint16_t i; + uint8_t boot_status; + + /* total 5s */ + for (i = 0; i < BHY2_BST_CHECK_RETRY; ++i) + { + /* 50ms */ + rslt = bhy2_hif_delay_us(50000, hif); + if (rslt < 0) + { + return rslt; + } + + rslt = bhy2_hif_get_regs(BHY2_REG_BOOT_STATUS, &boot_status, sizeof(boot_status), hif); + if (rslt < 0) + { + return rslt; + } + + if ((boot_status & BHY2_BST_HOST_INTERFACE_READY) && (boot_status & BHY2_BST_HOST_FW_VERIFY_DONE) && + (!(boot_status & BHY2_BST_HOST_FW_VERIFY_ERROR))) + { + break; + } + } + + if (i == BHY2_BST_CHECK_RETRY) + { + return BHY2_E_TIMEOUT; + } + + return BHY2_OK; +} + +static int8_t bhy2_hif_check_boot_status_flash(struct bhy2_hif_dev *hif) +{ + int8_t rslt; + uint16_t i; + uint8_t boot_status; + + /* total 5s */ + for (i = 0; i < BHY2_BST_CHECK_RETRY; ++i) + { + /* 50ms */ + rslt = bhy2_hif_delay_us(50000, hif); + if (rslt < 0) + { + return rslt; + } + + rslt = bhy2_hif_get_regs(BHY2_REG_BOOT_STATUS, &boot_status, sizeof(boot_status), hif); + if (rslt < 0) + { + return rslt; + } + + if ((boot_status & BHY2_BST_HOST_INTERFACE_READY) && (boot_status & BHY2_BST_FLASH_VERIFY_DONE) && + (!(boot_status & BHY2_BST_FLASH_VERIFY_ERROR))) + { + break; + } + } + + if (i == BHY2_BST_CHECK_RETRY) + { + return BHY2_E_TIMEOUT; + } + + return BHY2_OK; +} + +static int8_t bhy2_hif_get_fifo(uint8_t reg, + uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_read, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + uint8_t n_bytes[2]; + uint32_t read_len; + uint32_t read_write_len; + uint32_t offset; + + if ((hif != NULL) && (fifo != NULL) && (bytes_read != NULL) && (bytes_remain != NULL)) + { + read_write_len = hif->read_write_len; + + if (*bytes_remain == 0) + { + rslt = bhy2_hif_get_regs(reg, n_bytes, 2, hif); /* Read the the available size */ + *bytes_remain = BHY2_LE2U16(n_bytes); + } + + if ((*bytes_remain != 0) && (rslt == BHY2_OK)) + { + if (fifo_len < *bytes_remain) + { + *bytes_read = fifo_len; + } + else + { + *bytes_read = *bytes_remain; + } + + read_len = *bytes_read; + offset = 0; + while (read_len > read_write_len) + { + rslt = bhy2_hif_get_regs(reg, &fifo[offset], read_write_len, hif); + if (rslt != BHY2_OK) + { + break; + } + + read_len -= read_write_len; + offset += read_write_len; + } + + if (read_len != 0) + { + rslt = bhy2_hif_get_regs(reg, &fifo[offset], read_len, hif); + } + + *bytes_remain -= *bytes_read; + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_init(enum bhy2_intf intf, + bhy2_read_fptr_t read, + bhy2_write_fptr_t write, + bhy2_delay_us_fptr_t delay_us, + uint32_t read_write_len, + void *intf_ptr, + struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + + if ((hif != NULL) && (read != NULL) && (write != NULL) && (delay_us != NULL)) + { + hif->read = read; + hif->write = write; + hif->delay_us = delay_us; + hif->intf_ptr = intf_ptr; + hif->intf = intf; + if (read_write_len % 4) + { + + hif->read_write_len = BHY2_ROUND_WORD_LOWER(read_write_len); + } + else + { + hif->read_write_len = read_write_len; + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + + if ((hif != NULL) && (hif->read != NULL) && (reg_data != NULL)) + { + if (hif->intf == BHY2_SPI_INTERFACE) + { + reg_addr |= BHY2_SPI_RD_MASK; + } + + hif->intf_rslt = hif->read(reg_addr, reg_data, length, hif->intf_ptr); + if (hif->intf_rslt != BHY2_INTF_RET_SUCCESS) + { + rslt = BHY2_E_IO; + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + + if ((hif != NULL) && (hif->write != NULL) && (reg_data != NULL)) + { + if (hif->intf == BHY2_SPI_INTERFACE) + { + reg_addr &= BHY2_SPI_WR_MASK; + } + + hif->intf_rslt = hif->write(reg_addr, reg_data, length, hif->intf_ptr); + if (hif->intf_rslt != BHY2_INTF_RET_SUCCESS) + { + rslt = BHY2_E_IO; + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_delay_us(uint32_t period_us, const struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + + if ((hif != NULL) && (hif->delay_us != NULL)) + { + hif->delay_us(period_us, hif->intf_ptr); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_exec_cmd(uint16_t cmd, const uint8_t *payload, uint32_t length, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_exec_cmd_generic(cmd, payload, length, NULL, 0, 0, hif); +} + +int8_t bhy2_hif_get_parameter(uint16_t param, + uint8_t *payload, + uint32_t payload_len, + uint32_t *actual_len, + struct bhy2_hif_dev *hif) +{ + uint16_t code = 0; + uint8_t prev_hif_ctrl, hif_ctrl; + int8_t rslt = BHY2_OK; + + if ((hif != NULL) && (payload != NULL) && (actual_len != NULL)) + { + *actual_len = 0; + + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, &hif_ctrl, 1, hif); + if (rslt == BHY2_OK) + { + prev_hif_ctrl = hif_ctrl; + hif_ctrl &= (uint8_t)(~(BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL)); /* Change the Status FIFO to synchronous mode + * */ + if (hif_ctrl != prev_hif_ctrl) + { + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &hif_ctrl, 1, hif); + } + + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_exec_cmd(param | BHY2_PARAM_READ_MASK, NULL, 0, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_get_status_fifo(&code, payload, payload_len, actual_len, hif); + + if (rslt == BHY2_OK) + { + + if (hif_ctrl != prev_hif_ctrl) + { + hif_ctrl = prev_hif_ctrl; + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &hif_ctrl, 1, hif); + } + + if (rslt == BHY2_OK) + { + if (code != param) + { + rslt = BHY2_E_TIMEOUT; + } + } + } + } + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_set_parameter(uint16_t param, const uint8_t *payload, uint32_t length, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_exec_cmd(param, payload, length, hif); +} + +int8_t bhy2_hif_get_product_id(uint8_t *product_id, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_regs(BHY2_REG_PRODUCT_ID, product_id, 1, hif); +} + +int8_t bhy2_hif_get_chip_id(uint8_t *chip_id, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_regs(BHY2_REG_CHIP_ID, chip_id, 1, hif); +} + +int8_t bhy2_hif_get_rom_version(uint16_t *rom_version, struct bhy2_hif_dev *hif) +{ + uint8_t buffer[2]; + int8_t rslt; + + if (rom_version != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_ROM_VERSION_0, buffer, 2, hif); + *rom_version = BHY2_LE2U16(buffer); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_get_kernel_version(uint16_t *kernel_version, struct bhy2_hif_dev *hif) +{ + uint8_t buffer[2]; + int8_t rslt; + + if (kernel_version != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_KERNEL_VERSION_0, buffer, 2, hif); + *kernel_version = BHY2_LE2U16(buffer); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_get_user_version(uint16_t *user_version, struct bhy2_hif_dev *hif) +{ + uint8_t buffer[2]; + int8_t rslt; + + if (user_version != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_USER_VERSION_0, buffer, 2, hif); + *user_version = BHY2_LE2U16(buffer); + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_get_boot_status(uint8_t *boot_status, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_regs(BHY2_REG_BOOT_STATUS, boot_status, 1, hif); +} + +int8_t bhy2_hif_get_host_status(uint8_t *host_status, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_regs(BHY2_REG_HOST_STATUS, host_status, 1, hif); +} + +int8_t bhy2_hif_get_feature_status(uint8_t *feat_status, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_regs(BHY2_REG_FEATURE_STATUS, feat_status, 1, hif); +} + +int8_t bhy2_hif_get_interrupt_status(uint8_t *int_status, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_regs(BHY2_REG_INT_STATUS, int_status, 1, hif); +} + +int8_t bhy2_hif_get_fw_error(uint8_t *fw_error, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_regs(BHY2_REG_ERROR_VALUE, fw_error, 1, hif); +} + +int8_t bhy2_hif_reset(struct bhy2_hif_dev *hif) +{ + uint8_t reset_req = BHY2_REQUEST_RESET; + uint8_t boot_status = 0; + int8_t rslt; + + /* Timeout at 150ms (15 * 10000 microseconds) */ + uint16_t count = 15; + + rslt = bhy2_hif_set_regs(BHY2_REG_RESET_REQ, &reset_req, 1, hif); + if (rslt == BHY2_OK) + { + while (count--) + { + rslt = bhy2_hif_delay_us(10000, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_get_regs(BHY2_REG_BOOT_STATUS, &boot_status, 1, hif); + if (rslt == BHY2_OK) + { + if (boot_status & BHY2_BST_HOST_INTERFACE_READY) + { + break; + } + } + } + } + + if (!(boot_status & BHY2_BST_HOST_INTERFACE_READY)) + { + rslt = BHY2_E_TIMEOUT; + } + } + + return rslt; +} + +int8_t bhy2_hif_upload_firmware_to_ram(const uint8_t *firmware, uint32_t length, struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + uint16_t magic; + + if ((hif != NULL) && (firmware != NULL)) + { + magic = BHY2_LE2U16(firmware); + if (magic != BHY2_FW_MAGIC) + { + rslt = BHY2_E_MAGIC; + } + else + { + rslt = bhy2_hif_exec_cmd(BHY2_CMD_UPLOAD_TO_PROGRAM_RAM, firmware, length, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_check_boot_status_ram(hif); + + } + + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_upload_firmware_to_ram_partly(const uint8_t *firmware, + uint32_t total_size, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + uint16_t magic; + + if ((hif != NULL) && (firmware != NULL)) + { + if (cur_pos == 0) + { + magic = BHY2_LE2U16(firmware); + if (magic != BHY2_FW_MAGIC) + { + rslt = BHY2_E_MAGIC; + } + + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_exec_cmd_generic(BHY2_CMD_UPLOAD_TO_PROGRAM_RAM, + firmware, + packet_len, + NULL, + 0, + total_size, + hif); + } + } + else + { + rslt = bhy2_hif_set_regs(BHY2_REG_CHAN_CMD, firmware, packet_len, hif); + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_boot_program_ram(struct bhy2_hif_dev *hif) +{ + int8_t rslt; + + rslt = bhy2_hif_exec_cmd(BHY2_CMD_BOOT_PROGRAM_RAM, NULL, 0, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_check_boot_status_ram(hif); + } + + return rslt; +} + +int8_t bhy2_hif_get_wakeup_fifo(uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_read, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_fifo(BHY2_REG_CHAN_FIFO_W, fifo, fifo_len, bytes_read, bytes_remain, hif); +} + +int8_t bhy2_hif_get_nonwakeup_fifo(uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_read, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_fifo(BHY2_REG_CHAN_FIFO_NW, fifo, fifo_len, bytes_read, bytes_remain, hif); +} + +int8_t bhy2_hif_get_status_fifo(uint16_t *status_code, + uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif) +{ + int8_t rslt; + uint8_t tmp_fifo[4]; + + rslt = bhy2_hif_get_regs(BHY2_REG_CHAN_STATUS, tmp_fifo, 4, hif); + if (rslt == BHY2_OK) + { + *status_code = BHY2_LE2U16(&tmp_fifo[0]); + *bytes_remain = BHY2_LE2U16(&tmp_fifo[2]); + + if (*bytes_remain != 0) + { + if (fifo_len < *bytes_remain) + { + rslt = BHY2_E_BUFFER; + } + else + { + rslt = bhy2_hif_get_regs(BHY2_REG_CHAN_STATUS, fifo, *bytes_remain, hif); + } + } + } + + return rslt; +} + +int8_t bhy2_hif_get_status_fifo_async(uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_read, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif) +{ + return bhy2_hif_get_fifo(BHY2_REG_CHAN_STATUS, fifo, fifo_len, bytes_read, bytes_remain, hif); +} + +int8_t bhy2_hif_exec_sensor_conf_cmd(uint8_t sensor_id, + bhy2_float sample_rate, + uint32_t latency, + struct bhy2_hif_dev *hif) +{ + uint8_t tmp_buf[8]; + union bhy2_hif_float_u32 sample_rate_u; + + sample_rate_u.as_float = sample_rate; + + /* Sample rate is 32bits, latency is 24bits */ + tmp_buf[0] = sensor_id; + tmp_buf[1] = (uint8_t)(sample_rate_u.reg & 0xFF); + tmp_buf[2] = (uint8_t)((sample_rate_u.reg >> 8) & 0xFF); + tmp_buf[3] = (uint8_t)((sample_rate_u.reg >> 16) & 0xFF); + tmp_buf[4] = (uint8_t)((sample_rate_u.reg >> 24) & 0xFF); + tmp_buf[5] = (uint8_t)(latency & 0xFF); + tmp_buf[6] = (uint8_t)((latency >> 8) & 0xFF); + tmp_buf[7] = (uint8_t)((latency >> 16) & 0xFF); + + return bhy2_hif_exec_cmd(BHY2_CMD_CONFIG_SENSOR, tmp_buf, 8, hif); +} + +int8_t bhy2_hif_set_fifo_flush(uint8_t sensor_id, struct bhy2_hif_dev *hif) +{ + uint8_t tmp_buf[4] = {sensor_id, 0, 0, 0}; + + return bhy2_hif_exec_cmd(BHY2_CMD_FIFO_FLUSH, tmp_buf, 4, hif); +} + +int8_t bhy2_hif_exec_soft_passthrough(const uint8_t *payload, + uint32_t payload_len, + uint8_t *reg_data, + uint32_t length, + uint32_t *actual_len, + struct bhy2_hif_dev *hif) +{ + uint16_t code = 0; + uint8_t old_status, tmp_buf; + int8_t rslt; + + /* Enter synchronous mode */ + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + old_status = tmp_buf; + tmp_buf &= (uint8_t)(~(BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL)); + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + /* Execute the Software passthrough */ + rslt = bhy2_hif_exec_cmd(BHY2_CMD_SW_PASSTHROUGH, payload, payload_len, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt == BHY2_OK) + { + /* Read back the response */ + rslt = bhy2_hif_get_status_fifo(&code, reg_data, length, actual_len, hif); + if (rslt == BHY2_OK) + { + /* Set back to previous mode */ + tmp_buf = old_status; + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + if (code != BHY2_STATUS_SW_PASS_THRU_RES) + { + rslt = BHY2_E_TIMEOUT; + } + } + } + } + } + } + } + + return rslt; +} + +int8_t bhy2_hif_get_post_mortem(uint16_t *code, + uint32_t *actual_len, + uint8_t *post_mortem, + uint32_t buffer_len, + struct bhy2_hif_dev *hif) +{ + uint8_t old_status, tmp_buf; + int8_t rslt; + + if (code != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + old_status = tmp_buf; + tmp_buf &= (uint8_t)(~(BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL)); + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_exec_cmd(BHY2_CMD_REQ_POST_MORTEM_DATA, NULL, 0, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_get_status_fifo(code, post_mortem, buffer_len, actual_len, hif); + if (rslt == BHY2_OK) + { + tmp_buf = old_status; + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + if (*code != BHY2_STATUS_CRASH_DUMP) + { + rslt = BHY2_E_TIMEOUT; + } + } + } + } + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_do_self_test(uint8_t phys_sensor_id, + struct bhy2_self_test_resp *self_test_resp, + struct bhy2_hif_dev *hif) +{ + uint16_t code = 0; + uint8_t old_status, tmp_buf, req[4], ret_data[16]; + uint32_t ret_len = 0; + int8_t rslt; + + if (self_test_resp != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + old_status = tmp_buf; + tmp_buf &= (uint8_t)(~(BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL)); + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + req[0] = phys_sensor_id; + req[1] = req[2] = req[3] = 0; + rslt = bhy2_hif_exec_cmd(BHY2_CMD_REQ_SELF_TEST, req, 4, hif); + if (rslt == BHY2_OK) + { + /* wait status ready */ + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_get_status_fifo(&code, ret_data, 16, &ret_len, hif); + if (rslt == BHY2_OK) + { + tmp_buf = old_status; + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + if (code != BHY2_STATUS_SELF_TEST_RES) + { + rslt = BHY2_E_TIMEOUT; + } + else + { + if (ret_data[0] != phys_sensor_id) + { + rslt = BHY2_E_INVALID_PARAM; + } + else + { + self_test_resp->test_status = ret_data[1]; + self_test_resp->x_offset = BHY2_LE2S16(&ret_data[2]); + self_test_resp->y_offset = BHY2_LE2S16(&ret_data[4]); + self_test_resp->z_offset = BHY2_LE2S16(&ret_data[6]); + } + } + } + } + } + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_do_foc(uint8_t phys_sensor_id, struct bhy2_foc_resp *foc_resp, struct bhy2_hif_dev *hif) +{ + uint16_t code = 0; + uint8_t old_status, tmp_buf, req[4], ret_data[16]; + uint32_t ret_len = 0; + int8_t rslt; + + if (foc_resp != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + old_status = tmp_buf; + tmp_buf &= (uint8_t)(~(BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL)); + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + req[0] = phys_sensor_id; + req[1] = req[2] = req[3] = 0; + rslt = bhy2_hif_exec_cmd(BHY2_CMD_REQ_FOC, req, 4, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_get_status_fifo(&code, ret_data, 16, &ret_len, hif); + if (rslt == BHY2_OK) + { + tmp_buf = old_status; + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + if (code != BHY2_STATUS_FOC_RES) + { + rslt = BHY2_E_TIMEOUT; + } + else + { + if (ret_data[0] != phys_sensor_id) + { + rslt = BHY2_E_INVALID_PARAM; + } + else + { + foc_resp->foc_status = ret_data[1]; + foc_resp->x_offset = BHY2_LE2S16(&ret_data[2]); + foc_resp->y_offset = BHY2_LE2S16(&ret_data[4]); + foc_resp->z_offset = BHY2_LE2S16(&ret_data[6]); + } + } + } + } + } + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_get_sensor_ctrl(uint8_t sensor_id, + uint8_t ctrl_code, + uint8_t *payload, + uint32_t payload_len, + uint32_t *actual_len, + struct bhy2_hif_dev *hif) +{ + uint16_t code = 0; + uint8_t old_status; + uint8_t tmp_buf[4] = {0}; + uint8_t buf = 0; + uint32_t length; + uint16_t param_num; + int8_t rslt; + + if ((payload != NULL) && (actual_len != NULL)) + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, &buf, 1, hif); + if (rslt == BHY2_OK) + { + old_status = buf; + buf &= (uint8_t)(~(BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL)); + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &buf, 1, hif); + if (rslt == BHY2_OK) + { + /* Set the parameter to request data */ + param_num = (uint16_t)(BHY2_PARAM_SET_SENSOR_CTRL | sensor_id); + tmp_buf[0] = ctrl_code | BHY2_PARAM_SENSOR_CTRL_READ; + length = 4; + rslt = bhy2_hif_set_parameter(param_num, tmp_buf, length, hif); + if (rslt == BHY2_OK) + { + /* Get parameter to read data */ + param_num = (uint16_t)(BHY2_PARAM_GET_SENSOR_CTRL | sensor_id); + length = 0; + rslt = bhy2_hif_set_parameter(param_num, NULL, length, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_get_status_fifo(&code, payload, payload_len, actual_len, hif); + if (rslt == BHY2_OK) + { + buf = old_status; + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &buf, 1, hif); + if (rslt == BHY2_OK) + { + if (code != (BHY2_PARAM_SET_SENSOR_CTRL | sensor_id)) + { + rslt = BHY2_E_INVALID_PARAM; + } + else if (payload[0] != ctrl_code) + { + rslt = BHY2_E_INVALID_PARAM; + } + } + } + } + } + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_set_sensor_ctrl(uint8_t sensor_id, + uint8_t ctrl_code, + const uint8_t *payload, + uint32_t payload_len, + struct bhy2_hif_dev *hif) +{ + uint16_t param_num; + uint8_t command; + + /* Set parameter to send data */ + param_num = (uint16_t)(BHY2_PARAM_SET_SENSOR_CTRL | sensor_id); + command = (uint8_t)(ctrl_code & (~BHY2_PARAM_SENSOR_CTRL_READ)); + + return bhy2_hif_exec_cmd_generic(param_num, payload, payload_len, &command, 1, 0, hif); +} + +int8_t bhy2_hif_get_bsx_state(uint16_t param_id, + uint8_t *bsx_state, + uint32_t state_len, + uint32_t *actual_len, + struct bhy2_hif_dev *hif) +{ + uint8_t complete_flag = 0; + uint16_t tmp_state_len = 0; + uint8_t block_len = 0; + uint32_t read_len; + int8_t rslt; + uint8_t tmp_bsx_state_buf[BHY2_BSX_STATE_STRUCT_LEN]; + uint16_t state_index = 0; + + while (complete_flag == 0) + { + rslt = bhy2_hif_get_parameter(param_id, tmp_bsx_state_buf, BHY2_BSX_STATE_STRUCT_LEN, &read_len, hif); + if (rslt != BHY2_OK) + { + break; + } + + if (read_len > BHY2_BSX_STATE_STRUCT_LEN) + { + rslt = BHY2_E_INVALID_PARAM - 50; + break; + } + + complete_flag = tmp_bsx_state_buf[0] & BHY2_BSX_STATE_TRANSFER_COMPLETE; + block_len = tmp_bsx_state_buf[1]; + tmp_state_len = BHY2_LE2U16(&tmp_bsx_state_buf[2]); + if (tmp_state_len == 0) + { + rslt = BHY2_E_INVALID_PARAM - 70; + break; + } + + *actual_len = tmp_state_len; /* Report actual length, in case of invalid buffer */ + + if (state_len < tmp_state_len) + { + rslt = BHY2_E_BUFFER; + break; + } + + memcpy(&bsx_state[state_index], &tmp_bsx_state_buf[4], tmp_bsx_state_buf[1]); + state_index += block_len; + } + + return rslt; +} + +int8_t bhy2_hif_set_bsx_state(uint16_t param_id, const uint8_t *bsx_state, uint32_t state_len, struct bhy2_hif_dev *hif) +{ + uint32_t pos; + uint16_t num = 0; + int8_t rslt = BHY2_OK; + uint8_t tmp_bsx_state_buf[BHY2_BSX_STATE_STRUCT_LEN]; + uint32_t state_buf_size; + + for (pos = 0; pos < state_len; pos += BHY2_BSX_STATE_BLOCK_LEN, num++) + { + tmp_bsx_state_buf[0] = num & 0x7F; + state_buf_size = state_len - pos; + if (state_buf_size <= BHY2_BSX_STATE_BLOCK_LEN) + { + tmp_bsx_state_buf[0] |= 0x80; + tmp_bsx_state_buf[1] = (uint8_t)state_buf_size; + } + else + { + tmp_bsx_state_buf[1] = BHY2_BSX_STATE_BLOCK_LEN; + } + + tmp_bsx_state_buf[2] = state_len & 0xFF; + tmp_bsx_state_buf[3] = (state_len >> 8) & 0xFF; + memcpy(&tmp_bsx_state_buf[4], &bsx_state[pos], tmp_bsx_state_buf[1]); + rslt = bhy2_hif_set_parameter(param_id, tmp_bsx_state_buf, BHY2_BSX_STATE_STRUCT_LEN, hif); + if (rslt != BHY2_OK) + { + break; + } + } + + return rslt; +} + +int8_t bhy2_hif_erase_flash(uint32_t start_addr, uint32_t end_addr, struct bhy2_hif_dev *hif) +{ + uint8_t buf[8]; + uint8_t int_status = 0; + uint16_t retry; + + /* Variable to get the response code */ + uint16_t code = 0; + int8_t rslt = BHY2_OK; + uint32_t ret_len; + + /* Check for invalid end address */ + if ((end_addr < start_addr) && (start_addr != BHY2_FLASH_BULK_ERASE)) + { + rslt = BHY2_E_INVALID_PARAM; + } + else + { + /* Set start address */ + buf[0] = (uint8_t)(start_addr & 0xFF); + buf[1] = (uint8_t)((start_addr >> 8) & 0xFF); + buf[2] = (uint8_t)((start_addr >> 16) & 0xFF); + buf[3] = (uint8_t)((start_addr >> 24) & 0xFF); + + /* Set the end address */ + buf[4] = (uint8_t)(end_addr & 0xFF); + buf[5] = (uint8_t)((end_addr >> 8) & 0xFF); + buf[6] = (uint8_t)((end_addr >> 16) & 0xFF); + buf[7] = (uint8_t)((end_addr >> 24) & 0xFF); + + /* Erase flash */ + rslt = bhy2_hif_exec_cmd(BHY2_CMD_ERASE_FLASH, buf, 8, hif); + if (rslt == BHY2_OK) + { + /* Check status and wait for at least 0.5 seconds for the erase to complete + * and time out provided for 10 Mins (1200 * 0.5 Seconds = 10 Min) */ + for (retry = 0; retry < BHY2_QUERY_FLASH_MAX_RETRY; retry++) + { + rslt = bhy2_hif_get_interrupt_status(&int_status, hif); + if (rslt != BHY2_OK) + { + break; + } + + if (int_status & BHY2_IST_MASK_STATUS) + { + break; + } + + rslt = bhy2_hif_delay_us(500000, hif); + if (rslt != BHY2_OK) + { + break; + } + } + + if (rslt == BHY2_OK) + { + /* Read status */ + rslt = bhy2_hif_get_status_fifo(&code, NULL, 0, &ret_len, hif); + if (rslt == BHY2_OK) + { + /* Status code */ + if (code != BHY2_STATUS_FLASH_ERASE_COMPLETE) + { + rslt = BHY2_E_TIMEOUT; + } + } + } + } + } + + return rslt; +} + +int8_t bhy2_hif_upload_to_flash(const uint8_t *firmware, + uint32_t length, + uint8_t *work_buffer, + uint32_t work_buf_len, + uint32_t *exp_size, + struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + uint16_t magic; + uint32_t sector_addr = BHY2_FLASH_SECTOR_START_ADDR; + uint8_t addr_buf[4]; + uint32_t remain, trans_len, pos; + uint16_t code; + + if ((hif != NULL) && (firmware != NULL) && (work_buffer != NULL)) + { + magic = BHY2_LE2U16(firmware); + if (magic != BHY2_FW_MAGIC) + { + rslt = BHY2_E_MAGIC; + } + else + { + pos = 0; + remain = length; + if (hif->read_write_len % 4) + { + + hif->read_write_len = BHY2_ROUND_WORD_LOWER(hif->read_write_len); + } + + while (remain > 0) + { + if (remain > hif->read_write_len) + { + trans_len = hif->read_write_len; + } + else + { + trans_len = remain; + } + + /* Set the sector address */ + addr_buf[0] = (uint8_t)(sector_addr & 0xFF); + addr_buf[1] = (uint8_t)((sector_addr >> 8) & 0xFF); + addr_buf[2] = (uint8_t)((sector_addr >> 16) & 0xFF); + addr_buf[3] = (uint8_t)((sector_addr >> 24) & 0xFF); + + /* Transfer firmware to the flash */ + rslt = bhy2_hif_exec_cmd_generic(BHY2_CMD_WRITE_FLASH, &firmware[pos], trans_len, addr_buf, 4, 0, hif); + if (rslt != BHY2_OK) + { + break; + } + + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt != BHY2_OK) + { + break; + } + + rslt = bhy2_hif_get_status_fifo(&code, work_buffer, work_buf_len, exp_size, hif); + if (rslt != BHY2_OK) + { + break; + } + + /* Status code */ + if (code != BHY2_STATUS_FLASH_WRITE_COMPLETE) + { + rslt = BHY2_E_TIMEOUT; + break; + } + + pos += trans_len; + remain -= trans_len; + sector_addr += hif->read_write_len; + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_upload_to_flash_partly(const uint8_t *firmware, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + uint16_t magic; + uint32_t sector_addr = BHY2_FLASH_SECTOR_START_ADDR + cur_pos; + uint8_t addr_buf[4]; + uint16_t code; + uint8_t work_buffer[32]; + uint32_t exp_size, work_buf_len = 32; + + if ((hif != NULL) && (firmware != NULL)) + { + if (cur_pos == 0) + { + magic = BHY2_LE2U16(firmware); + if (magic != BHY2_FW_MAGIC) + { + rslt = BHY2_E_MAGIC; + } + } + + if (rslt == BHY2_OK) + { + /* Set the sector address */ + addr_buf[0] = (uint8_t)(sector_addr & 0xFF); + addr_buf[1] = (uint8_t)((sector_addr >> 8) & 0xFF); + addr_buf[2] = (uint8_t)((sector_addr >> 16) & 0xFF); + addr_buf[3] = (uint8_t)((sector_addr >> 24) & 0xFF); + + /* Transfer firmware to the flash */ + rslt = bhy2_hif_exec_cmd_generic(BHY2_CMD_WRITE_FLASH, firmware, packet_len, addr_buf, 4, 0, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_wait_status_ready(hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_get_status_fifo(&code, work_buffer, work_buf_len, &exp_size, hif); + if (rslt == BHY2_OK) + { + if (code != BHY2_STATUS_FLASH_WRITE_COMPLETE) + { + rslt = BHY2_E_TIMEOUT; + } + } + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_boot_from_flash(struct bhy2_hif_dev *hif) +{ + int8_t rslt; + + rslt = bhy2_hif_exec_cmd(BHY2_CMD_BOOT_FLASH, NULL, 0, hif); + if (rslt == BHY2_OK) + { + rslt = bhy2_hif_check_boot_status_flash(hif); + } + + return rslt; +} + +int8_t bhy2_hif_request_hw_timestamp(struct bhy2_hif_dev *hif) +{ + uint8_t time_ev_req = 1; + + return bhy2_hif_set_regs(BHY2_REG_TIME_EV_REQ, &time_ev_req, 1, hif); +} + +int8_t bhy2_hif_get_hw_timestamp(uint64_t *ts_ticks, struct bhy2_hif_dev *hif) +{ + int8_t rslt = BHY2_OK; + uint8_t ts_regs[5]; + + if (ts_ticks != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTR_TIME_0, ts_regs, 5, hif); + if (rslt == BHY2_OK) + { + *ts_ticks = BHY2_LE2U40(ts_regs); + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_req_and_get_hw_timestamp(uint64_t *ts_ticks, struct bhy2_hif_dev *hif) +{ + int8_t rslt; + uint8_t retry; + uint8_t tmp_buf[5]; + uint64_t ts_old; + + if (ts_ticks != NULL) + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTR_TIME_0, tmp_buf, 5, hif); + if (rslt == BHY2_OK) + { + ts_old = BHY2_LE2U40(tmp_buf); + tmp_buf[0] = 1; + rslt = bhy2_hif_set_regs(BHY2_REG_TIME_EV_REQ, tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + for (retry = 0; retry < 5; retry++) + { + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTR_TIME_0, tmp_buf, 5, hif); + if (rslt == BHY2_OK) + { + *ts_ticks = BHY2_LE2U40(tmp_buf); + if (*ts_ticks != ts_old) + { + break; + } + + rslt = bhy2_hif_delay_us(10, hif); + if (rslt != BHY2_OK) + { + break; + } + } + } + + if ((retry >= 5) && (*ts_ticks == ts_old)) + { + rslt = BHY2_E_TIMEOUT; + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_get_sensor_info(uint8_t sensor_id, struct bhy2_sensor_info *info, struct bhy2_hif_dev *hif) +{ + int8_t rslt; + uint32_t length; + uint8_t bytes[28]; + + if (info != NULL) + { + /* Checking for a valid sensor ID */ + if (sensor_id > BHY2_SPECIAL_SENSOR_ID_OFFSET) + { + rslt = BHY2_E_INVALID_PARAM; + } + else + { + rslt = bhy2_hif_get_parameter((uint16_t)(BHY2_PARAM_SENSOR_INFO_0 + sensor_id), bytes, 28, &length, hif); + if (rslt == BHY2_OK) + { + if (length != 28) + { + rslt = BHY2_E_INVALID_PARAM; + } + else + { + info->sensor_type = bytes[0]; + info->driver_id = bytes[1]; + info->driver_version = bytes[2]; + info->power = bytes[3]; + info->max_range.bytes[0] = bytes[4]; + info->max_range.bytes[1] = bytes[5]; + info->resolution.bytes[0] = bytes[6]; + info->resolution.bytes[1] = bytes[7]; + info->max_rate.bytes[0] = bytes[8]; + info->max_rate.bytes[1] = bytes[9]; + info->max_rate.bytes[2] = bytes[10]; + info->max_rate.bytes[3] = bytes[11]; + info->fifo_reserved.bytes[0] = bytes[12]; + info->fifo_reserved.bytes[1] = bytes[13]; + info->fifo_reserved.bytes[2] = bytes[14]; + info->fifo_reserved.bytes[3] = bytes[15]; + info->fifo_max.bytes[0] = bytes[16]; + info->fifo_max.bytes[1] = bytes[17]; + info->fifo_max.bytes[2] = bytes[18]; + info->fifo_max.bytes[3] = bytes[19]; + info->event_size = bytes[20]; + info->min_rate.bytes[0] = bytes[21]; + info->min_rate.bytes[1] = bytes[22]; + info->min_rate.bytes[2] = bytes[23]; + info->min_rate.bytes[3] = bytes[24]; + info->max_range.u16_val = BHY2_LE2U16(info->max_range.bytes); + info->resolution.u16_val = BHY2_LE2U16(info->resolution.bytes); + info->max_rate.u32_val = BHY2_LE2U32(info->max_rate.bytes); + info->fifo_reserved.u32_val = BHY2_LE2U32(info->fifo_reserved.bytes); + info->fifo_max.u32_val = BHY2_LE2U32(info->fifo_max.bytes); + info->min_rate.u32_val = BHY2_LE2U32(info->min_rate.bytes); + } + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_get_phys_sensor_info(uint8_t sensor_id, struct bhy2_phys_sensor_info *info, struct bhy2_hif_dev *hif) +{ + int8_t rslt; + uint32_t length; + uint8_t bytes[20]; + + if (info != NULL) + { + rslt = bhy2_hif_get_parameter((uint16_t)(BHY2_PARAM_PHYSICAL_SENSOR_BASE + sensor_id), bytes, 20, &length, hif); + if (rslt == BHY2_OK) + { + if (length != 20) + { + rslt = BHY2_E_INVALID_PARAM; + } + else + { + info->sensor_type = bytes[0]; + info->driver_id = bytes[1]; + info->driver_version = bytes[2]; + info->power_current = bytes[3]; + info->curr_range.bytes[0] = bytes[4]; + info->curr_range.bytes[1] = bytes[5]; + info->flags = bytes[6]; + info->slave_address = bytes[7]; + info->gpio_assignment = bytes[8]; + info->curr_rate.bytes[0] = bytes[9]; + info->curr_rate.bytes[1] = bytes[10]; + info->curr_rate.bytes[2] = bytes[11]; + info->curr_rate.bytes[3] = bytes[12]; + info->num_axis = bytes[13]; + info->orientation_matrix[0] = bytes[14]; + info->orientation_matrix[1] = bytes[15]; + info->orientation_matrix[2] = bytes[16]; + info->orientation_matrix[3] = bytes[17]; + info->orientation_matrix[4] = bytes[18]; + + info->curr_range.u16_val = BHY2_LE2U16(info->curr_range.bytes); + info->curr_rate.u32_val = BHY2_LE2U32(info->curr_rate.bytes); + } + } + } + else + { + rslt = BHY2_E_NULL_PTR; + } + + return rslt; +} + +int8_t bhy2_hif_set_orientation_matrix(uint8_t sensor_id, + struct bhy2_orient_matrix orient_matrix, + struct bhy2_hif_dev *hif) +{ + int8_t rslt; + uint8_t tmp_matrix_buf[8]; /* Includes 2 reserved bytes */ + + memset(tmp_matrix_buf, 0, sizeof(tmp_matrix_buf)); + + tmp_matrix_buf[0] = BHY2_BYTE_TO_NIBBLE(&orient_matrix.c[0]); + tmp_matrix_buf[1] = BHY2_BYTE_TO_NIBBLE(&orient_matrix.c[2]); + tmp_matrix_buf[2] = BHY2_BYTE_TO_NIBBLE(&orient_matrix.c[4]); + tmp_matrix_buf[3] = BHY2_BYTE_TO_NIBBLE(&orient_matrix.c[6]); + tmp_matrix_buf[4] = orient_matrix.c[8] & 0x0F; + + rslt = bhy2_hif_set_parameter((uint16_t)(BHY2_PARAM_PHYSICAL_SENSOR_BASE + sensor_id), tmp_matrix_buf, 8, hif); + + return rslt; +} + +/*lint -e{715} suppressed parameters not referenced info as all the calling functions are parsing the valid values to + * all parameters*/ +int8_t bhy2_hif_set_inject_data_mode(const uint8_t *payload, + uint8_t payload_len, + const uint8_t *work_buf, + uint32_t work_buf_len, + const uint32_t *actual_len, + struct bhy2_hif_dev *hif) +{ + uint8_t tmp_buf; + int8_t rslt; + + rslt = bhy2_hif_get_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + tmp_buf &= (uint8_t)(~(BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL)); + rslt = bhy2_hif_set_regs(BHY2_REG_HOST_INTERFACE_CTRL, &tmp_buf, 1, hif); + if (rslt == BHY2_OK) + { + /* Set injection mode */ + rslt = bhy2_hif_set_regs(BHY2_REG_CHAN_CMD, payload, payload_len, hif); + if (rslt != BHY2_OK) + { + rslt = BHY2_E_NULL_PTR; + } + } + } + + return rslt; +} + +int8_t bhy2_hif_inject_data(const uint8_t *payload, uint32_t payload_len, struct bhy2_hif_dev *hif) +{ + return bhy2_hif_exec_cmd(BHY2_CMD_INJECT_DATA, payload, payload_len, hif); +} diff --git a/lib/SensorLib/src/bosch/bhy2_hif.h b/lib/SensorLib/src/bosch/bhy2_hif.h new file mode 100644 index 0000000..a8ac9d4 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_hif.h @@ -0,0 +1,576 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_hif.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef __BHY2_HIF_H__ +#define __BHY2_HIF_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include "bhy2_defs.h" + +/** + * @brief Function to link the callback interfaces + * @param[in] intf : Physical communication interface + * @param[in] read : Read function pointer + * @param[in] write : Write function pointer + * @param[in] delay_us : Microsecond delay function pointer + * @param[in] read_write_len : Maximum read/write lengths supported + * @param[in] intf_ptr : Reference to the interface. Can be NULL + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_init(enum bhy2_intf intf, + bhy2_read_fptr_t read, + bhy2_write_fptr_t write, + bhy2_delay_us_fptr_t delay_us, + uint32_t read_write_len, + void *intf_ptr, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to get data from registers + * @param[in] reg_addr : Register address to be read from + * @param[out] reg_data : Reference to the data buffer + * @param[in] length : Length of the data buffer + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, struct bhy2_hif_dev *hif); + +/** + * @brief Function to set data to registers + * @param[in] reg_addr : Register address to write to + * @param[in] reg_data : Reference to the data buffer + * @param[in] length : Length of the data buffer + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, struct bhy2_hif_dev *hif); + +/** + * @brief Function to delay in microseconds + * @param[in] period_us : Period to delay in microseconds + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_delay_us(uint32_t period_us, const struct bhy2_hif_dev *hif); + +/** + * Function to execute a command + * @param[in] cmd : Command code + * @param[in] payload : Reference to the data buffer containing the command's payload + * @param[in] length : Length of the data buffer + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_exec_cmd(uint16_t cmd, const uint8_t *payload, uint32_t length, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get a parameter + * @param[in] param : Parameter ID + * @param[out] payload : Reference to the data buffer to store the parameter's payload + * @param[in] payload_len : Length of the data buffer + * @param[out] actual_len : Actual length of the payload + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_parameter(uint16_t param, + uint8_t *payload, + uint32_t payload_len, + uint32_t *actual_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to set a parameter + * @param[in] param : Parameter ID + * @param[in] payload : Reference to the data buffer storing the parameter's payload + * @param[in] length : Length of the data buffer + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_set_parameter(uint16_t param, const uint8_t *payload, uint32_t length, struct bhy2_hif_dev *hif); + +/** + * @brief Function to erase the flash + * @param[in] start_addr : Start address + * @param[in] end_addr : End address + * @param[in] hif : HIF device address + * @return API error codes + */ +int8_t bhy2_hif_erase_flash(uint32_t start_addr, uint32_t end_addr, struct bhy2_hif_dev *hif); + +/** + * @brief Function to upload data to flash + * @param[in] firmware : Reference to the data buffer storing the firmware + * @param[in] length : Length of the data buffer + * @param[in/out] work_buffer : Reference to the work buffer + * @param[in] work_buf_len : Length of the work buffer + * @param[out] exp_size : Expected size of the work buffer if insufficient size + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_upload_to_flash(const uint8_t *firmware, + uint32_t length, + uint8_t *work_buffer, + uint32_t work_buf_len, + uint32_t *exp_size, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to upload data to flash partly + * @param[in] firmware : Reference cur_pos of the data buffer storing the firmware + * @param[in] cur_pos : Current position of the firmware + * @param[in] packet_len : Length of the firmware packet to be transferred + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_upload_to_flash_partly(const uint8_t *firmware, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to boot from flash + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_boot_from_flash(struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the product ID + * @param[out] product_id : Reference to the data buffer to store the product ID + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_product_id(uint8_t *product_id, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the chip ID + * @param[out] chip_id : Reference to the data buffer to store the chip ID + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_chip_id(uint8_t *chip_id, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the ROM version + * @param[out] rom_version : Reference to the data buffer to store the ROM version + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_rom_version(uint16_t *rom_version, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the kernel version + * @param[out] kernel_version : Reference to the data buffer to store the kernel version + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_kernel_version(uint16_t *kernel_version, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the user version + * @param[out] user_version : Reference to the data buffer to store the user version + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_user_version(uint16_t *user_version, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the boot status + * @param[out] boot_status : Reference to the data buffer to store the boot status + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_boot_status(uint8_t *boot_status, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the host status + * @param[out] host_status : Reference to the data buffer to store the host status + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_host_status(uint8_t *host_status, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the feature status + * @param[out] feat_status : Reference to the data buffer to store the feature status + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_feature_status(uint8_t *feat_status, struct bhy2_hif_dev *hif); + +/** + * @brief Function get the interrupt status + * @param[out] int_status : Reference to the data buffer to store the interrupt status + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_interrupt_status(uint8_t *int_status, struct bhy2_hif_dev *hif); + +/** + * @brief Function get the firmware error code + * @param[out] fw_error : Reference to the data buffer to store the firmware error code + * @param[in] hif : HIF device reference + * @return API error code + */ +int8_t bhy2_hif_get_fw_error(uint8_t *fw_error, struct bhy2_hif_dev *hif); + +/** + * @brief Function to trigger a soft reset + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_reset(struct bhy2_hif_dev *hif); + +/** + * @brief Function to upload a firmware to RAM + * @param[in] firmware : Reference to the data buffer storing the firmware + * @param[in] length : Length of the firmware + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_upload_firmware_to_ram(const uint8_t *firmware, uint32_t length, struct bhy2_hif_dev *hif); + +/** + * @brief Function to upload a part of the firmware to RAM + * @param[in] firmware : Reference to the data buffer storing the current part of firmware + * @param[in] total_size : Total size of the firmware + * @param[in] cur_pos : Current position of the firmware + * @param[in] packet_len : Size of firmware part to be uploaded + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_upload_firmware_to_ram_partly(const uint8_t *firmware, + uint32_t total_size, + uint32_t cur_pos, + uint32_t packet_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to boot from RAM + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_boot_program_ram(struct bhy2_hif_dev *hif); + +/** + * @brief Function to get data from the Wake-up FIFO + * @param[out] fifo : Reference to the data buffer to store data from the FIFO + * @param[in] fifo_len : Length of the data buffer + * @param[out] bytes_read : Number of bytes read into the data buffer + * @param[out] bytes_remain : Bytes remaining in the sensor FIFO + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_wakeup_fifo(uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_read, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to get data from the Non-wake-up FIFO + * @param[out] fifo : Reference to the data buffer to store data from the FIFO + * @param[in] fifo_len : Length of the data buffer + * @param[out] bytes_read : Number of bytes read into the data buffer + * @param[out] bytes_remain : Bytes remaining in the sensor FIFO + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_nonwakeup_fifo(uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_read, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to get synchronous data from the Status FIFO + * @param[out] status_code : Status code received + * @param[out] fifo : Reference to the data buffer to store the payload of the status code + * @param[in] fifo_len : Length of the data buffer + * @param[out] bytes_remain : Number of bytes in the payload + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_status_fifo(uint16_t *status_code, + uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to get asynchronous data from the Status FIFO + * @param[out] fifo : Reference to the data buffer to store data from the FIFO + * @param[in] fifo_len : Length of the data buffer + * @param[out] bytes_read : Number of bytes read into the data buffer + * @param[out] bytes_remain : Bytes remaining in the sensor FIFO + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_status_fifo_async(uint8_t *fifo, + uint32_t fifo_len, + uint32_t *bytes_read, + uint32_t *bytes_remain, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to configure a virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] sample_rate : Sample rate in Hz + * @param[in] latency : Report latency in milliseconds + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_exec_sensor_conf_cmd(uint8_t sensor_id, + bhy2_float sample_rate, + uint32_t latency, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to flush data of a virtual sensor from the FIFOs + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_set_fifo_flush(uint8_t sensor_id, struct bhy2_hif_dev *hif); + +/** + * @brief Function to perform a self-test for a particular virtual sensor + * @param[in] phys_sensor_id : Physical sensor ID of the virtual sensor + * @param[out] self_test_resp : Reference to the data buffer to store the self-test response + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_do_self_test(uint8_t phys_sensor_id, + struct bhy2_self_test_resp *self_test_resp, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to perform a fast offset compensation for a particular virtual sensor + * @param[in] phys_sensor_id : Physical Sensor ID of the virtual sensor + * @param[out] foc_resp : Reference to the data buffer to store the FOC response + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_do_foc(uint8_t phys_sensor_id, struct bhy2_foc_resp *foc_resp, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the sensor control configuration of a virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] ctrl_code : Sensor control code + * @param[out] payload : Reference to the data buffer to store the sensor control + * @param[in] payload_len : Length of the data buffer + * @param[out] actual_len : Actual length of the sensor control configuration + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_sensor_ctrl(uint8_t sensor_id, + uint8_t ctrl_code, + uint8_t *payload, + uint32_t payload_len, + uint32_t *actual_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to set the sensor control configuration of a virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[in] ctrl_code : Sensor control code + * @param[in] payload : Reference to the data buffer storing the sensor control + * @param[in] payload_len : Length of the sensor control configuration + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_set_sensor_ctrl(uint8_t sensor_id, + uint8_t ctrl_code, + const uint8_t *payload, + uint32_t payload_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the BSX state of a BSX parameter + * @param[in] param_id : Parameter ID of the BSX parameter + * @param[out] bsx_state : Reference to teh data buffer to store the BSX state + * @param[in] state_len : Length of the buffer + * @param[out] actual_len : Actual length of the BSX state + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_bsx_state(uint16_t param_id, + uint8_t *bsx_state, + uint32_t state_len, + uint32_t *actual_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to the BSX state of a BSX parameter + * @param[in] param_id : Parameter ID of the BSX parameter + * @param[in] bsx_state : Reference to the data buffer storing the BSX state + * @param[in] state_len : Length of the BSX state + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_set_bsx_state(uint16_t param_id, const uint8_t *bsx_state, uint32_t state_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to request a timestamp event + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_request_hw_timestamp(struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the hardware timestamp + * @param[out] ts_ticks : Reference to the data buffer to store the timestamp in ticks + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_hw_timestamp(uint64_t *ts_ticks, struct bhy2_hif_dev *hif); + +/** + * @brief Function to request and get the hardware timestamp + * @param[out] ts_ticks : Reference to the data buffer to store the timestamp in ticks + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_req_and_get_hw_timestamp(uint64_t *ts_ticks, struct bhy2_hif_dev *hif); + +/** + * @brief Function to communicate with connected sensors + * @param[in] payload : Command payload + * @param[in] payload_len : Payload length + * @param[in/out] reg_data : Reference to the data buffer storing the register data + * @param[in] length : Length of the data buffer + * @param[out] actual_len : Registers actually read + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_exec_soft_passthrough(const uint8_t *payload, + uint32_t payload_len, + uint8_t *reg_data, + uint32_t length, + uint32_t *actual_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the post-mortem data dump + * @param[out] code : Post-mortem status code + * @param[out] actual_len : Actual length of the post-mortem data dump + * @param[out] post_mortem : Reference to the data buffer to store the data dump + * @param[in] buffer_len : Length of the data buffer + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_post_mortem(uint16_t *code, + uint32_t *actual_len, + uint8_t *post_mortem, + uint32_t buffer_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function get information of a virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[out] info : Reference to the data buffer to store the sensor info + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_sensor_info(uint8_t sensor_id, struct bhy2_sensor_info *info, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the physical sensor information of a virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[out] info : Reference to the data buffer to store the physical sensor info + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_get_phys_sensor_info(uint8_t sensor_id, struct bhy2_phys_sensor_info *info, struct bhy2_hif_dev *hif); + +/** + * @brief Function to get the orientation matrix of a virtual sensor + * @param[in] sensor_id : Sensor ID of the virtual sensor + * @param[out] orient_matrix : Reference to the data buffer to store the orientation matrix + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_set_orientation_matrix(uint8_t sensor_id, + struct bhy2_orient_matrix orient_matrix, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to set the data injection mode + * @param[in] payload : Reference to the data buffer containing the host injection mode + * @param[in] payload_len : Length of the data buffer + * @param[in/out] work_buf : Reference to the work buffer + * @param[in] work_buf_len : Length of the work buffer + * @param[out] actual_len : Expected length of the work buffer + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_set_inject_data_mode(const uint8_t *payload, + uint8_t payload_len, + const uint8_t *work_buf, + uint32_t work_buf_len, + const uint32_t *actual_len, + struct bhy2_hif_dev *hif); + +/** + * @brief Function to inject data + * @param[in] payload : Reference to the data buffer + * @param[in] payload_len : Length of the data buffer + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_inject_data(const uint8_t *payload, uint32_t payload_len, struct bhy2_hif_dev *hif); + +/** + * @brief Function to wait till status is ready + * @param[in] hif : HIF device reference + * @return API error codes + */ +int8_t bhy2_hif_wait_status_ready(struct bhy2_hif_dev *hif); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* __BHY2_HIF_H__ */ diff --git a/lib/SensorLib/src/bosch/bhy2_klio.c b/lib/SensorLib/src/bosch/bhy2_klio.c new file mode 100644 index 0000000..3f3a3a9 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_klio.c @@ -0,0 +1,373 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_klio.c +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +/*********************************************************************/ +/* system header files */ +#include +#include + +/*********************************************************************/ +/* BHY2 SensorAPI header files */ +#include "bhy2.h" + +/*********************************************************************/ +/* own header files */ +#include "bhy2_klio.h" + +int8_t bhy2_klio_read_pattern(const uint8_t id, uint8_t *buffer, uint16_t *length, struct bhy2_dev *dev) +{ + int8_t rslt; + uint32_t ret_len; + bhy2_klio_pattern_transfer_t pattern = { 0 }; + + if (!buffer || !length || !dev) + { + return BHY2_E_NULL_PTR; + } + + if (id != 0 || *length < sizeof(pattern.pattern_data)) + { + return BHY2_E_INVALID_PARAM; + } + + rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN), (uint8_t*)&pattern, sizeof(pattern), &ret_len, dev); + + if (rslt != BHY2_OK) + { + return rslt; + } + + if (ret_len != sizeof(pattern)) + { + return BHY2_E_INVALID_PARAM; + } + + memcpy(buffer, pattern.pattern_data, pattern.full_size); + *length = pattern.full_size; + + return rslt; +} + +int8_t bhy2_klio_read_reset_driver_status(uint32_t *klio_driver_status, struct bhy2_dev *dev) +{ + uint32_t ret_len = 0; + int8_t rslt; + + if (!klio_driver_status || !dev) + { + return BHY2_E_NULL_PTR; + } + + do + { + rslt = + bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_DRIVER_STATUS), + (uint8_t*)klio_driver_status, + sizeof(*klio_driver_status), + &ret_len, + dev); + + if (rslt != BHY2_OK) + { + return rslt; + } + } while (*klio_driver_status == KLIO_DRIVER_ERROR_OPERATION_PENDING); + + return rslt; +} + +int8_t bhy2_klio_write_pattern(const uint8_t idx, const uint8_t *pattern_data, const uint16_t size, + struct bhy2_dev *dev) +{ + bhy2_klio_pattern_transfer_t pattern = { + .block_id = 0, .block_size = (uint8_t)size, .full_size = size, .pattern_id = idx, .pattern_data = { 0 } + }; + + if (!dev || size > sizeof(pattern.pattern_data)) + { + return BHY2_E_INVALID_PARAM; + } + + memcpy(pattern.pattern_data, pattern_data, size); + + return bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN), (const uint8_t*)&pattern, sizeof(pattern), dev); +} + +int8_t bhy2_klio_set_pattern_states(const bhy2_klio_pattern_state_t operation, + const uint8_t *pattern_ids, + const uint16_t count, + struct bhy2_dev *dev) +{ + uint32_t buffer_size = sizeof(bhy2_klio_pattern_state_op_t) + count; + uint8_t buffer[buffer_size]; + + if (!dev || count == 0) + { + return BHY2_E_INVALID_PARAM; + } + + buffer[1] = (uint8_t)count; + buffer[0] = operation; + + for (uint8_t i = 0; i < count; i++) + { + buffer[i + 2] = pattern_ids[i]; + } + + return bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_STATE), buffer, buffer_size, dev); +} + +int8_t bhy2_klio_set_state(const bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + uint8_t buffer[4]; + + if (!dev || !state) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + buffer[0] = state->learning_enabled; + buffer[1] = state->learning_reset; + buffer[2] = state->recognition_enabled; + buffer[3] = state->recognition_reset; + + rslt = bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGORITHM_STATE), buffer, sizeof(buffer), dev); + } + + return rslt; +} + +int8_t bhy2_klio_get_state(bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + if (!dev || !state) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + uint8_t buffer[4]; + uint32_t ret_len; + + rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGORITHM_STATE), buffer, sizeof(buffer), &ret_len, dev); + if (rslt == BHY2_OK && ret_len == sizeof(buffer)) + { + state->learning_enabled = buffer[0]; + state->learning_reset = buffer[1]; + state->recognition_enabled = buffer[2]; + state->recognition_reset = buffer[3]; + } + } + + return rslt; +} + +int8_t bhy2_klio_similarity_score(const uint8_t *first_pattern, + const uint8_t *second_pattern, + const uint16_t size, + float *similarity, + struct bhy2_dev *dev) +{ + uint32_t klio_driver_status = 0; + int8_t rslt; + uint32_t ret_len; + bhy2_klio_pattern_transfer_t pattern1 = { 0 }, pattern2 = { 0 }; + uint8_t buffer[4]; + + if (!dev || size > sizeof(pattern1.pattern_data)) + { + return BHY2_E_INVALID_PARAM; + } + + pattern1.block_size = pattern2.block_size = (uint8_t)size; + pattern1.full_size = pattern2.full_size = size; + memcpy(pattern1.pattern_data, first_pattern, size); + memcpy(pattern2.pattern_data, second_pattern, size); + + rslt = + bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), (uint8_t*)&pattern1, sizeof(pattern1), dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + rslt = + bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), (uint8_t*)&pattern2, sizeof(pattern2), dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + /* Wait for similarity calculation to complete. */ + rslt = bhy2_klio_read_reset_driver_status(&klio_driver_status, dev); + if (rslt != BHY2_OK || klio_driver_status != KLIO_DRIVER_ERROR_NONE) + { + return BHY2_E_INVALID_PARAM; + } + + rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), buffer, sizeof(buffer), &ret_len, dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + if (ret_len != sizeof(buffer)) + { + return BHY2_E_INVALID_PARAM; + } + + memcpy(similarity, buffer, sizeof(*similarity)); + + return BHY2_OK; +} + +int8_t bhy2_klio_similarity_score_multiple(const uint8_t idx, + const uint8_t *indexes, + const uint8_t count, + float *similarity, + struct bhy2_dev *dev) +{ + uint32_t klio_driver_status; + int8_t rslt; + uint32_t ret_len; + uint32_t buffer_size = sizeof(bhy2_klio_similarity_calculation_t) + count; + + buffer_size = BHY2_ROUND_WORD_HIGHER(buffer_size); + uint8_t buffer[256] = { 0 }; + + if (!indexes || !similarity || !dev) + { + return BHY2_E_NULL_PTR; + } + + /* buffer[0-3] values are initialized to zero's to distinguish from regular pattern comparison*/ + buffer[4] = idx; + buffer[5] = count; + for (uint8_t i = 0; i < count; i++) + { + buffer[i + 6] = indexes[i]; + } + + /* Start similarity calculations. */ + rslt = bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), (uint8_t*)buffer, buffer_size, dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + /* Wait for similarity calculation to complete. */ + rslt = bhy2_klio_read_reset_driver_status(&klio_driver_status, dev); + if (rslt != BHY2_OK || klio_driver_status != KLIO_DRIVER_ERROR_NONE) + { + return BHY2_E_INVALID_PARAM; + } + + /* Read similarity results. */ + rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), + (uint8_t *)similarity, + sizeof(float) * count, + &ret_len, + dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + return BHY2_OK; +} + +int8_t bhy2_klio_set_parameter(const bhy2_klio_parameter_t id, + const void *parameter_data, + const uint16_t size, + struct bhy2_dev *dev) +{ + bhy2_klio_parameter_wrapper_t buffer; + + buffer.id = id; + buffer.flags = 0; + buffer.size = (uint8_t)size; + memcpy(buffer.payload.data, parameter_data, size); + + /* Size is 3 bytes header and buffer.size then rounded up to a four byte multiple. */ + return bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER), + (uint8_t*)&buffer, + (3 + buffer.size + 3) & ~3, + dev); +} + +int8_t bhy2_klio_get_parameter(const bhy2_klio_parameter_t id, + uint8_t *parameter_data, + uint16_t *size, + struct bhy2_dev *dev) +{ + uint32_t ret_len; + uint8_t buffer[260] = { 0 }; + + buffer[0] = id; + int8_t rslt; + + /* Size is 3 bytes header and buffer.size then rounded up to a four byte multiple. */ + rslt = bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER), buffer, (3 + buffer[2] + 3) & ~3, dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER), buffer, sizeof(buffer), &ret_len, dev); + if (rslt != BHY2_OK) + { + return rslt; + } + + if (ret_len < 3 || buffer[2] > *size) + { + return BHY2_E_INVALID_PARAM; + } + + for (uint16_t i = 3, j = 0; i < buffer[2] + 3; i++, j++) + { + parameter_data[j] = buffer[i]; + } + + *size = buffer[2]; + + return BHY2_OK; +} diff --git a/lib/SensorLib/src/bosch/bhy2_klio.h b/lib/SensorLib/src/bosch/bhy2_klio.h new file mode 100644 index 0000000..db66a62 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_klio.h @@ -0,0 +1,227 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_klio.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef __BHY2_KLIO_H__ +#define __BHY2_KLIO_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include +#include + +#include "bhy2.h" +#include "bhy2_klio_defs.h" + +/*! + * @brief Reads and resets current driver status. + * + * The driver_status will be set to one of the values in + * @ref bhy2_klio_driver_error_state_t. This function will not return a driver + * status of + * @ref bhy2_klio_driver_error_state_t::KLIO_DRIVER_ERROR_OPERATION_PENDING. + * but will retry until the pending operation is finished. + * + * @param[out] driver_status Pointer to uint32_t + * @param[in] dev Device reference. + * + * @return BHY2 API error codes. + */ +int8_t bhy2_klio_read_reset_driver_status(uint32_t *driver_status, struct bhy2_dev *dev); + +/*! + * @brief Read learnt pattern. + * + * @param[in] id pattern id (only 0 supported now) + * @param[out] buffer buffer big enough to fit complete pattern fingerprint data + * @param[in,out] length size of buffer, return size of actual pattern data + * @param[in] dev Device reference + * + * @return BHY2 API error codes. + * + * After learning of a new pattern has been signaled by a sensor data event, + * call this function to retrieve the learnt pattern. + */ +int8_t bhy2_klio_read_pattern(const uint8_t id, uint8_t *buffer, uint16_t *length, struct bhy2_dev *dev); + +/*! + * @brief Set KLIO algorithm learning and recognition state. + * + * @param[in] state new state for algorithm + * @param[in] dev Device reference + * + * @return BHY2 API error codes. + * + * Writing 1 to the reset fields resets all internal algorithm state and + * removes any patterns loaded for recognition. + */ +int8_t bhy2_klio_set_state(const bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev); + +/*! + * @brief Get KLIO algorithm learning and recognition state. + * + * @param[out] state current state for algorithm + * @param[in] dev Device reference + * + * @return BHY2 API error codes. + * + * The resets are always read as 0. + */ +int8_t bhy2_klio_get_state(bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev); + +/*! + * @brief Write pattern to recognition algorithm. + * + * @param[in] idx pattern index + * @param[in] pattern_data containing pattern + * @param[in] size pattern size + * @param[in] dev Device reference + * + * @return BHY2 API error codes. + * + * Write a pattern to the specified recognition index. The allowed number of + * recognition patterns may be retrieved using the + * @ref bhy2_klio_parameter::KLIO_PARAM_RECOGNITION_MAX_PATTERNS parameter. + * + * After a pattern is written, it is in disabled state and not used. It must + * be enabled using @ref bhy2_klio_set_pattern_states() before it will be used + * by the recognition algorithm. + */ +int8_t bhy2_klio_write_pattern(const uint8_t idx, const uint8_t *pattern_data, const uint16_t size, + struct bhy2_dev *dev); + +/*! + * @brief Sets the specified state for the specified pattern ids. + * + * @param[in] operation operation to perform + * @param[in] pattern_ids ids of pattern(s) to perform operation on + * @param[in] size size of pattern_ids array + * @param[in] dev Device reference + * + * @return BHY2 API error codes. + */ +int8_t bhy2_klio_set_pattern_states(const bhy2_klio_pattern_state_t operation, + const uint8_t *pattern_ids, + const uint16_t size, + struct bhy2_dev *dev); + +/*! + * @brief Calculates similarity score between two patterns. + * + * The similariy between patterns is a meassure of the similarity between the + * performed activities or exercises. If the two patterns represent the same + * excercise the similarity will be close to 1.0, and if they are for very + * different excercises, the similarity will be negative. + * + * @param[in] first_pattern Buffer containing first pattern. + * @param[in] second_pattern Buffer containing second pattern. + * @param[in] size Pattern size. + * @param[out] similarity Similarity score. + * @param[in] dev Device reference. + * + * @return BHY2 API error codes. + */ +int8_t bhy2_klio_similarity_score(const uint8_t *first_pattern, + const uint8_t *second_pattern, + const uint16_t size, + float *similarity, + struct bhy2_dev *dev); + +/*! + * @brief Calculates similarity score between multiple patterns. + * + * This is more efficient than bhy2_klio_similarity_score() since if the patterns + * are already available on the bhy2, they need not be uploaded again to + * perform the comparison. And several comparisons may be performed with one + * API call. + * + * @param[in] idx Reference pattern. + * @param[in] indexes Buffer containing indexes of patterns to compare reference pattern with. + * @param[in] count Number of patterns in indexes buffer. + * @param[out] similarity Similarity scores (one score for each pattern in indexes buffer). + * @param[in] dev Device reference. + * + * @return BHY2 API error codes. + */ +int8_t bhy2_klio_similarity_score_multiple(const uint8_t idx, + const uint8_t *indexes, + const uint8_t count, + float *similarity, + struct bhy2_dev *dev); + +/*! + * @brief Set KLIO algorithm parameter + * + * @param[in] id Parameter to set. + * @param[in] parameter_data Buffer containing new parameter value. + * @param[in] size Parameter size. + * @param[in] dev Device reference. + * + * @return BHY2 API error codes. + */ +int8_t bhy2_klio_set_parameter(const bhy2_klio_parameter_t id, + const void *parameter_data, + const uint16_t size, + struct bhy2_dev *dev); + +/*! + * @brief Get KLIO algorithm parameter + * + * @param[in] id Parameter id. + * @param[out] parameter_data Buffer to store parameter data. + * @param[in,out] size Parameter data size. + * @param[in] dev Device reference. + * + * @return BHY2 API error codes. + * + * The expected type or buffer size of parameter_data for respective parameter + * id is specified in the @ref bhy2_klio_parameter_t enum. + */ +int8_t bhy2_klio_get_parameter(const bhy2_klio_parameter_t id, + uint8_t *parameter_data, + uint16_t *size, + struct bhy2_dev *dev); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif diff --git a/lib/SensorLib/src/bosch/bhy2_klio_defs.h b/lib/SensorLib/src/bosch/bhy2_klio_defs.h new file mode 100644 index 0000000..2d4b05e --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_klio_defs.h @@ -0,0 +1,349 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_klio_defs.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef __BHY2_KLIO_DEFS_H__ +#define __BHY2_KLIO_DEFS_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include + +#define BHY2_SENSOR_ID_KLIO UINT8_C(112) +#define BHY2_SENSOR_ID_KLIO_LOG UINT8_C(127) + +#ifndef BHY2_KLIO_PAGE +#define BHY2_KLIO_PAGE UINT16_C(9) +#endif +#define KLIO_PARAM(id) (((BHY2_KLIO_PAGE) << 8) | (id)) + +/*! + * @enum bhy2_klio_parameter + * + * KLIO algorithm parameters + * + * @var bhy2_klio_parameter::KLIO_PARAM_ALGORITHM_VERSION + * Algorithm version. (read) + * @code{.c} char version[244]; @endcode + * + * @var bhy2_klio_parameter::KLIO_PARAM_RECOGNITION_RESPONSIVNESS + * The approximate number of cycles / repetitions for recognition to recognize + * an activity. (read / write) + * @code{.c} float cycle_fraction; @endcode + * + * @var bhy2_klio_parameter::KLIO_PARAM_PATTERN_BLOB_SIZE + * Pattern blob size in bytes. (read) + * @code{.c} uint16_t pattern_blob_size; @endcode + * + * @var bhy2_klio_parameter::KLIO_PARAM_RECOGNITION_MAX_PATTERNS + * Read Maximum number of patterns. (read) + * @code{.c} uint16_t recognition_max_patterns; @endcode + * + * @var bhy2_klio_parameter::KLIO_PARAM_LEARNING_IGNORE_INSIG_MOVEMENT + * Flag if insignificant movements should be ignored in learning. Value 0 or 1. (read / write) + * @code{.c} uint8_t ignore_insig_movement; @endcode + */ +typedef enum +{ + KLIO_PARAM_ALGORITHM_VERSION = 0, + KLIO_PARAM_RECOGNITION_SENSITIVITY = 1, + KLIO_PARAM_RECOGNITION_RESPONSIVNESS = 2, + KLIO_PARAM_LEARNING_SPEED = 3, + KLIO_PARAM_LEARNING_SIMILARITY_THRESHOLD = 4, + KLIO_PARAM_LEARNING_FREQUENCIES = 5, + KLIO_PARAM_LEARNING_PROGRESS = 6, + KLIO_PARAM_PATTERN_BLOB_SIZE = 7, + KLIO_PARAM_RECOGNITION_MAX_PATTERNS = 8, + KLIO_PARAM_INPUT_SENSORS = 9, + KLIO_PARAM_LEARNING_IGNORE_INSIG_MOVEMENT = 10 +} bhy2_klio_parameter_t; + +/*! + * + * @brief Convenience wrapper used in bhy2_klio.c algo parameter wrapper. + * + */ +typedef struct +{ + uint8_t id; + uint8_t flags; + uint8_t size; + union + { + uint8_t data[244]; + char version[244]; + float cycle_fraction; + uint16_t pattern_blob_size; + uint16_t recognition_max_patterns; + uint8_t ignore_insig_movement; + } BHY2_PACKED payload; +} BHY2_PACKED bhy2_klio_parameter_wrapper_t; + +/*! + * + * @brief bhy2 klio state structure + * + */ +typedef struct +{ + uint8_t learning_enabled; /*!< 0 - disable learning, 1 - enable learning. */ + uint8_t learning_reset; /*!< 0 - nop, 1 - reset learning. Always read as 0. */ + uint8_t recognition_enabled; /*!< 0 - disable recognition, 1 - enable recognition. */ + uint8_t recognition_reset; /*!< 0 - nop, 1 - reset learning. Always read as 0. */ +} BHY2_PACKED bhy2_klio_sensor_state_t; + +typedef struct +{ + uint8_t instance; + + /*! + * A value of -1 means no new learning has occurred. If the value is >= 0, + * then a new pattern has been learnt, and reading of this pattern may be + * performed. + */ + int8_t index; + + /*! + * While learning a new pattern, this field counts from 0 to 100. When 100 is + * reached a new pattern will be learnt. If learning is interrupted, this + * progress will return to 0, and change reason will be set to indicate + * why learning was interrupted. + */ + uint8_t progress; + + /*! + * | Value | Description | + * |:-----:|:-----------------------------------------------------------------------| + * | 0 | Learning is progressing. | + * | 1 | Learning was interrupted by a non-repetitive activity. | + * | 2 | Learning was interrupted because no significant movement was detected. | + */ + uint8_t change_reason; +} BHY2_PACKED bhy2_klio_sensor_frame_learning_t; + +typedef struct +{ + uint8_t instance; + + /*! The index of the recognized activity. 255 means no activity was + * recognized. */ + uint8_t index; + + /*! The current repetition count of the recognized activity. */ + float count; +} BHY2_PACKED bhy2_klio_sensor_frame_recognition_t; + +/*! + * + * @brief bhy2 klio combined data structure + * + * When the algorithm generates a new data frame, it is sent in this structure. + * + */ +typedef struct +{ + bhy2_klio_sensor_frame_learning_t learn; + bhy2_klio_sensor_frame_recognition_t recognize; +} BHY2_PACKED bhy2_klio_sensor_frame_t; + +/*! + * + * @brief bhy2 klio sensor log frame + * + * When the algorithm consumes a new set of samples, it is sent in this structure. + * + */ +typedef struct +{ + float timestamp; + float accel[3]; + float gyro[3]; +} BHY2_PACKED bhy2_klio_log_frame_t; + +/*! + * + * @brief bhy2 klio pattern transfer format + * + */ +typedef struct +{ + uint8_t block_id; /*!< Write as 0. */ + uint8_t block_size; /*!< Write as 0. */ + + /*! Size of pattern_data in bytes. The size of patterns may be obtained + using the @ref bhy2_klio_parameter::KLIO_PARAM_PATTERN_BLOB_SIZE + parameter. */ + uint16_t full_size; + + /*! Id of pattern to write. */ + uint8_t pattern_id; + + /*! Actual pattern data describing the exercise. */ + uint8_t pattern_data[244]; +} BHY2_PACKED bhy2_klio_pattern_transfer_t; + +/*! + * + * @brief Convenience wrapper used by @ref bhy2_klio_similarity_score_multiple(). + * + */ +typedef struct +{ + uint32_t zero; + uint8_t index; + uint8_t count; + uint8_t *indexes; +} BHY2_PACKED bhy2_klio_similarity_calculation_t; + +/*! + * + * @brief Convenience wrapper used by @ref bhy2_klio_set_pattern_states(). + * + */ +typedef struct +{ + uint8_t operation; + uint8_t count; + uint8_t *indexes; +} BHY2_PACKED bhy2_klio_pattern_state_op_t; + +/*! + * KLIO pattern state + */ +typedef enum +{ + /*!< disable pattern */ + KLIO_PATTERN_STATE_DISABLE = 0, + + /*!< enable pattern */ + KLIO_PATTERN_STATE_ENABLE = 1, + + /*!< switch hand */ + KLIO_PATTERN_STATE_SWITCH_HAND = 2, + + /*!< disable adaptive pattern */ + KLIO_PATTERN_STATE_AP_DISABLE = 3 +} bhy2_klio_pattern_state_t; + +/*! + * @brief KLIO host interface parameter identifiers. + * + * The parameter id used when calling the BHY2 functions directly. E.g. to read the driver status this may be used. + * + * ~~~{.c} + * uint32_t klio_driver_status = 0; + * uint32_t ret_len = 0; + * int8_t rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_DRIVER_STATUS), + * (uint8_t*)&klio_driver_status, + * sizeof(klio_driver_status), + * &ret_len, + * dev); + * if (rslt != BHY2_OK) + * { + * return rslt; + * } + * ~~~ + */ +typedef enum +{ + /*!< Read and write algorighm state. */ + KLIO_HIF_PARAM_ALGORITHM_STATE = 0, + + /*!< Read and write patterns. */ + KLIO_HIF_PARAM_PATTERN = 1, + + /*!< Read and write algorithm parameters. */ + KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER = 2, + KLIO_HIF_PARAM_STATISTIC = 3, + KLIO_HIF_PARAM_PATTERN_STATE = 4, + + /*!< Perform pattern similarity. */ + KLIO_HIF_PARAM_PATTERN_SIMILARITY = 5, + KLIO_HIF_PARAM_PATTERN_COMBINING = 6, + + /*!< Read driver status. */ + KLIO_HIF_PARAM_DRIVER_STATUS = 7 +} bhy2_klio_hif_parameter_t; + +/*! + * KLIO driver error codes + */ +typedef enum +{ + /*!< No error. */ + KLIO_DRIVER_ERROR_NONE = 0, + + /*!< Invalid parameter. */ + KLIO_DRIVER_ERROR_INVALID_PARAMETER = 1, + + /*!< Parameter out of range. */ + KLIO_DRIVER_ERROR_PARAMETER_OUT_OF_RANGE = 2, + + /*! + * Invalid pattern operation. E.g. trying to read a learnt pattern when no + * pattern has been learnt, or trying to write an invalid pattern. + */ + KLIO_DRIVER_ERROR_INVALID_PATTERN_OPERATION = 3, + + /*!< Not implemented. */ + KLIO_DRIVER_ERROR_NOT_IMPLEMENTED = 4, + + /*!< Insufficient buffer size */ + KLIO_DRIVER_ERROR_BUFSIZE = 5, + + /*!< Internal error. */ + KLIO_DRIVER_ERROR_INTERNAL = 6, + + /*!< Undefined error */ + KLIO_DRIVER_ERROR_UNDEFINED = 7, + + /*! + * Previous operation is still progressing. Read driver status again until + * operation is finished. + */ + KLIO_DRIVER_ERROR_OPERATION_PENDING = 8 +} bhy2_klio_driver_error_state_t; + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* __BHY2_KLIO_DEFS_H__ */ diff --git a/lib/SensorLib/src/bosch/bhy2_parse.c b/lib/SensorLib/src/bosch/bhy2_parse.c new file mode 100644 index 0000000..8d22313 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_parse.c @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file bhy2_parse.c + * @date 2023-03-24 + * @version v1.6.0 + * + */ + +#include "bhy2.h" +#include "bhy2_parse.h" + +void bhy2_parse_temperature_celsius(const uint8_t *data, bhy2_float *temperature) +{ + /* 1 LSB = 1/100 degC */ + float scale_factor = (float)1 / 100; + + *temperature = BHY2_LE2S16(data) * scale_factor; +} + +void bhy2_parse_humidity(const uint8_t *data, bhy2_float *humidity) +{ + float scale_factor = (float)1; + + *humidity = data[0] * scale_factor; +} + +void bhy2_parse_pressure(const uint8_t *data, bhy2_float *pressure) +{ + /* 1 LSB = 1/128 Pa */ + float scale_factor = (float)1 / 128; + + *pressure = (float)BHY2_LE2U24(data) * scale_factor; +} + +void bhy2_parse_altitude(const uint8_t *data, bhy2_float *altitude) +{ + *altitude = (float)(data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24)); +} + +void bhy2_parse_quaternion(const uint8_t *data, struct bhy2_data_quaternion *quaternion) +{ + quaternion->x = BHY2_LE2S16(data); + quaternion->y = BHY2_LE2S16(data + 2); + quaternion->z = BHY2_LE2S16(data + 4); + quaternion->w = BHY2_LE2S16(data + 6); + quaternion->accuracy = BHY2_LE2U16(data + 8); +} + +void bhy2_parse_xyz(const uint8_t *data, struct bhy2_data_xyz *vector) +{ + vector->x = BHY2_LE2S16(data); + vector->y = BHY2_LE2S16(data + 2); + vector->z = BHY2_LE2S16(data + 4); +} + +void bhy2_parse_orientation(const uint8_t *data, struct bhy2_data_orientation *orientation) +{ + orientation->heading = BHY2_LE2S16(data); + orientation->pitch = BHY2_LE2S16(data + 2); + orientation->roll = BHY2_LE2S16(data + 4); +} + +uint32_t bhy2_parse_step_counter(const uint8_t *data) +{ + return (uint32_t)(data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24)); +} diff --git a/lib/SensorLib/src/bosch/bhy2_parse.h b/lib/SensorLib/src/bosch/bhy2_parse.h new file mode 100644 index 0000000..445ff15 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_parse.h @@ -0,0 +1,109 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_parse.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ +#ifndef __BHY2_PARSE_H__ +#define __BHY2_PARSE_H__ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include "bhy2.h" + +/** + * @brief Function to parse FIFO frame data into temperature + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @param[out] temperature : Reference to the data buffer to store temperature in degree C + */ +void bhy2_parse_temperature_celsius(const uint8_t *data, bhy2_float *temperature); + +/** + * @brief Function to parse FIFO frame data into humidity + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @param[out] humidity : Reference to the data buffer to store humidity in % + */ +void bhy2_parse_humidity(const uint8_t *data, bhy2_float *humidity); + +/** + * @brief Function to parse FIFO frame data into barometric pressure + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @param[out] pressure : Reference to the data buffer to store pressure in Pascals + */ +void bhy2_parse_pressure(const uint8_t *data, bhy2_float *pressure); + +/** + * @brief Function to parse FIFO frame data into altitude + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @param[out] altitude : Reference to the data buffer to store altitude + */ +void bhy2_parse_altitude(const uint8_t *data, bhy2_float *altitude); + +/** + * @brief Function to parse FIFO frame data into quaternion + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @param[out] quaternion : Reference to the data buffer to store quaternion + */ +void bhy2_parse_quaternion(const uint8_t *data, struct bhy2_data_quaternion *quaternion); + +/** + * @brief Function to parse FIFO frame data into orientation + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @param[out] orientation : Reference to the data buffer to store orientation + */ +void bhy2_parse_orientation(const uint8_t *data, struct bhy2_data_orientation *orientation); + +/** + * @brief Function to parse FIFO frame data into 3 axes vector + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @param[out] vector : Reference to the data buffer to store vector + */ +void bhy2_parse_xyz(const uint8_t *data, struct bhy2_data_xyz *vector); + +/** + * @brief Function to parse FIFO frame data into step counter + * @param[in] data : Reference to the data buffer storing data from the FIFO + * @return[out] : Reference to the data buffer to step counter + */ +uint32_t bhy2_parse_step_counter(const uint8_t *data); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* __BHY2_PARSE_H__ */ diff --git a/lib/SensorLib/src/bosch/bhy2_swim.c b/lib/SensorLib/src/bosch/bhy2_swim.c new file mode 100644 index 0000000..4b2aa2c --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_swim.c @@ -0,0 +1,203 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_swim.c +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include + +/*********************************************************************/ +/* BHY2 SensorAPI header files */ +/*********************************************************************/ +#include "bhy2.h" + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "bhy2_swim.h" + +/*! + * @brief This API writes to the configuration parameter + * Config parameters are pool length and handedness + * + * @param[in] buffer to store swim configuration + * @param[out] dev hub handle. + * + * @return rslt execution result. + */ +int8_t bhy2_swim_set_config(const void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + /*! Length of the configuration is 4 bytes */ + uint32_t length = BHY2_SWIM_DATA_LENGTH; + + /*! Swim Parameter page with offset 0 used for swim configuration*/ + uint16_t param = BHY2_SWIM_CONFIG_PARAM; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Set the swim configuration parameter */ + rslt = bhy2_set_parameter(param, (uint8_t *)buffer, length, dev); + } + + return rslt; +} + +/*! + * @brief To get the SWIM configuration parameters like swim length and handedness + * + * @param[out] buffer to store swim configuration + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhy2_swim_get_config(void *buffer, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + /*! Length of the configuration is 4 bytes */ + uint32_t length = BHY2_SWIM_DATA_LENGTH; + uint32_t ret_length; + + /*! Swim Parameter page with offset 0 used to store swim configuration*/ + uint16_t param = BHY2_SWIM_CONFIG_PARAM; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the swim configuration from the parameter page*/ + rslt = bhy2_get_parameter(param, buffer, length, &ret_length, dev); + + if ((rslt == BHY2_OK) && (ret_length != BHY2_SWIM_DATA_LENGTH)) + { + /*! Invalid number of parameters readout */ + rslt = BHY2_E_INVALID_EVENT_SIZE; + } + } + + return rslt; +} + +/*! + * @brief To get the SWIM Algorithm version + * + * @param[out] buffer to store version data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhy2_swim_get_version(bhy2_swim_version_t *version, struct bhy2_dev *dev) +{ + int8_t rslt = BHY2_OK; + + /*! Buffer to store the swim version */ + uint8_t buffer[4]; + + /*! Length of the configuration is 4 */ + uint32_t length = BHY2_SWIM_DATA_LENGTH; + uint32_t ret_length; + + /*! Swim Parameter page with offset 1 used to store swim algorithm version*/ + uint16_t param = BHY2_SWIM_VERSION; + + if (dev == NULL) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + /*! Get the swim version from the parameter page */ + rslt = bhy2_get_parameter(param, buffer, length, &ret_length, dev); + + if ((rslt == BHY2_OK) && (ret_length != BHY2_SWIM_DATA_LENGTH)) + { + /*! Invalid number of parameters readout */ + rslt = BHY2_E_INVALID_EVENT_SIZE; + } + else + { + version->improvement = buffer[0]; + version->platform = buffer[1]; + version->bugfix = buffer[2]; + } + } + + return rslt; +} + +/*! + * @brief Parsing the fifo data to SWIM output structure format + * + * @param[in] Swim data + * @param[out] bhy2_swim_aglo_output to store parameter data + * + * @return API error codes + * + */ +int8_t bhy2_swim_parse_data(const uint8_t *data, struct bhy2_swim_algo_output* output) +{ + int8_t rslt = BHY2_OK; + + if ((data == NULL) || (output == NULL)) + { + rslt = BHY2_E_NULL_PTR; + } + else + { + output->total_distance = BHY2_LE2U16(data); + output->length_count = BHY2_LE2U16(data + 2); + output->lengths_freestyle = BHY2_LE2U16(data + 4); + output->lengths_breaststroke = BHY2_LE2U16(data + 6); + output->lengths_butterfly = BHY2_LE2U16(data + 8); + output->lengths_backstroke = BHY2_LE2U16(data + 10); + output->stroke_count = BHY2_LE2U16(data + 12); + } + + return rslt; +} diff --git a/lib/SensorLib/src/bosch/bhy2_swim.h b/lib/SensorLib/src/bosch/bhy2_swim.h new file mode 100644 index 0000000..ab5b197 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_swim.h @@ -0,0 +1,101 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_swim.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef _BHY2_SWIM_H_ +#define _BHY2_SWIM_H_ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include +#include + +#include "bhy2.h" +#include "bhy2_swim_defs.h" + +/*! + * @brief Parsing the fifo data to SWIM output structure format + * + * @param[in] data parameter + * @param[out] bhy2_swim_aglo_output to store parameter data + * + * @return API error codes + * + */ +int8_t bhy2_swim_parse_data(const uint8_t *data, struct bhy2_swim_algo_output *output); + +/*! + * @brief To get the SWIM configuration parameters like swim length and handedness + * + * @param[out] buffer to store parameter data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhy2_swim_get_config(void *buffer, struct bhy2_dev *dev); + +/*! + * @brief To get the SWIM Algorithm version + * + * @param[out] buffer to store version data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhy2_swim_get_version(bhy2_swim_version_t *buffer, struct bhy2_dev *dev); + +/*! + * @brief To set the SWIM configuration parameters like swim length and handedness + * @param[out] buffer to store parameter data + * @param[in] dev hub handle + * + * @return status code, BHY_HIF_E_SUCCESS in case of success + * + */ +int8_t bhy2_swim_set_config(const void *buffer, struct bhy2_dev *dev); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* _BHY2_SWIM_H_ */ diff --git a/lib/SensorLib/src/bosch/bhy2_swim_defs.h b/lib/SensorLib/src/bosch/bhy2_swim_defs.h new file mode 100644 index 0000000..6811ee8 --- /dev/null +++ b/lib/SensorLib/src/bosch/bhy2_swim_defs.h @@ -0,0 +1,126 @@ +/** +* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bhy2_swim_defs.h +* @date 2023-03-24 +* @version v1.6.0 +* +*/ + +#ifndef _BHY2_SWIM_DEFS_H_ +#define _BHY2_SWIM_DEFS_H_ + +/* Start of CPP Guard */ +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include + +/*! Sensor ID for Swim */ +#define BHY2_SENSOR_ID_SWIM UINT8_C(114) + +/*! Swim Parameter Page Base Address*/ +#define BHY2_SWIM_PAGE UINT16_C(0x0B) + +/*! Swim Configuration pages */ +#define BHY2_SWIM_CONFIG_PARAM (BHY2_SWIM_PAGE << 8) +#define BHY2_SWIM_VERSION ((BHY2_SWIM_PAGE << 8) | 1) + +/*! Swim configurations enable/ disable from parameter page */ +#define BHY2_SWIM_ENABLE_CONFIG UINT8_C(1) +#define BHY2_SWIM_DISABLE_CONFIG UINT8_C(0) + +/*! Device in left/right hand */ +#define BHY2_SWIM_DEVICE_ON_LEFT_HAND UINT8_C(1) +#define BHY2_SWIM_DEVICE_ON_RIGHT_HAND UINT8_C(0) + +/*! Pool length */ +#define BHY2_SWIM_POOL_LENGTH_25M UINT8_C(25) +#define BHY2_SWIM_POOL_LENGTH_50M UINT8_C(50) + +#define BHY2_SWIM_DATA_LENGTH UINT8_C(4) + +/*! + * bhy2 swim algo parameter. + */ +typedef struct bhy2_swim_config_param +{ + uint8_t update_swim_config; + uint8_t dev_on_left_hand; + uint8_t pool_length_integral; + uint8_t pool_length_floating; +} __attribute__ ((packed)) bhy2_swim_config_param_t; + +/*! + * swim output structure + */ +typedef struct bhy2_swim_algo_output +{ + uint16_t total_distance; + uint16_t length_count; + uint16_t lengths_freestyle; + uint16_t lengths_breaststroke; + uint16_t lengths_butterfly; + uint16_t lengths_backstroke; + uint16_t stroke_count; +} __attribute__ ((packed)) bhy2_swim_algo_output_t; + +/*! + * callback data capturing structure + */ +typedef struct bhy2_swim_data_parse +{ + uint8_t sensor_id; + uint8_t data_size; + uint8_t *data_ptr; + uint64_t *time_stamp; +} bhy2_swim_data_parse_t; + +/*! @brief structure definition to hold the version information of the software */ +typedef struct bhy2_swim_version +{ + uint8_t improvement; + uint8_t platform; + uint8_t bugfix; + uint8_t optional; +} bhy2_swim_version_t; + +typedef void (*bhy2_swim_algo_callback)(uint32_t seconds, uint32_t nanoseconds, + const struct bhy2_swim_data_parse *callback_info); + +/* End of CPP Guard */ +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#endif /* _BHY2_SWIM_DEFS_H_ */ diff --git a/lib/SensorLib/src/bosch/common/bosch_interfaces.cpp b/lib/SensorLib/src/bosch/common/bosch_interfaces.cpp new file mode 100644 index 0000000..a4ae361 --- /dev/null +++ b/lib/SensorLib/src/bosch/common/bosch_interfaces.cpp @@ -0,0 +1,157 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file bosch_interfaces.cpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-09 + * + */ +#include "bosch_interfaces.h" + +#if defined(ARDUINO_ARCH_RP2040) +SPISettings SensorInterfaces::__spiSetting = SPISettings(); +#else +SPISettings SensorInterfaces::__spiSetting = SPISettings(4000000, SPI_DATA_ORDER, SPI_MODE0); +#endif + +void SensorInterfaces::close_interfaces(SensorLibConfigure config) +{ + +} + +bool SensorInterfaces::setup_interfaces(SensorLibConfigure config) +{ + if (config.irq != SENSOR_PIN_NONE) { + pinMode(config.irq, INPUT_PULLDOWN); + } + switch (config.intf) { + case SENSORLIB_I2C_INTERFACE: +#if defined(ARDUINO_ARCH_RP2040) + config.u.i2c_dev.wire->end(); + config.u.i2c_dev.wire->setSDA(config.u.i2c_dev.sda); + config.u.i2c_dev.wire->setSCL(config.u.i2c_dev.scl); + config.u.i2c_dev.wire->begin(); +#elif defined(NRF52840_XXAA) || defined(NRF52832_XXAA) + config.u.i2c_dev.wire->end(); + config.u.i2c_dev.wire->setPins(config.u.i2c_dev.sda,config.u.i2c_dev.scl); + config.u.i2c_dev.wire->begin(); +#else + config.u.i2c_dev.wire->begin(config.u.i2c_dev.sda, config.u.i2c_dev.scl); +#endif + config.u.i2c_dev.wire->beginTransmission(config.u.i2c_dev.addr); + if (config.u.i2c_dev.wire->endTransmission() != 0) { + return false; + } + break; + case SENSORLIB_SPI_INTERFACE: + pinMode(config.u.spi_dev.cs, OUTPUT); + digitalWrite(config.u.spi_dev.cs, HIGH); +#if defined(ARDUINO_ARCH_RP2040) + config.u.spi_dev.spi->setSCK(config.u.spi_dev.sck); + config.u.spi_dev.spi->setRX(config.u.spi_dev.miso); + config.u.spi_dev.spi->setTX(config.u.spi_dev.mosi); + config.u.spi_dev.spi->begin(); +#elif defined(NRF52840_XXAA) || defined(NRF52832_XXAA) + config.u.spi_dev.spi->setPins(config.u.spi_dev.miso,config.u.spi_dev.sck, config.u.spi_dev.mosi); + config.u.spi_dev.spi->begin(); +#else + config.u.spi_dev.spi->begin(config.u.spi_dev.sck, config.u.spi_dev.miso, config.u.spi_dev.mosi); +#endif + break; + default: + break; + } + return true; +} + + + + +int8_t SensorInterfaces::bhy2_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + SensorLibConfigure *pConfig = (SensorLibConfigure *)intf_ptr; + if (!pConfig) { + return DEV_WIRE_ERR; + } + digitalWrite(pConfig->u.spi_dev.cs, LOW); + pConfig->u.spi_dev.spi->beginTransaction(__spiSetting); + pConfig->u.spi_dev.spi->transfer((reg_addr)); + for (size_t i = 0; i < length; i++) { + reg_data[i] = pConfig->u.spi_dev.spi->transfer(0x00); + } + pConfig->u.spi_dev.spi->endTransaction(); + digitalWrite(pConfig->u.spi_dev.cs, HIGH); + + return DEV_WIRE_NONE; +} + +int8_t SensorInterfaces::bhy2_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + SensorLibConfigure *pConfig = (SensorLibConfigure *)intf_ptr; + if (!pConfig) { + return DEV_WIRE_ERR; + } + digitalWrite(pConfig->u.spi_dev.cs, LOW); + pConfig->u.spi_dev.spi->beginTransaction(__spiSetting); + pConfig->u.spi_dev.spi->transfer(reg_addr); + pConfig->u.spi_dev.spi->transfer((uint8_t *)reg_data, length); + pConfig->u.spi_dev.spi->endTransaction(); + digitalWrite(pConfig->u.spi_dev.cs, HIGH); + return DEV_WIRE_NONE; +} + +int8_t SensorInterfaces::bhy2_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + SensorLibConfigure *pConfig = (SensorLibConfigure *)intf_ptr; + if (!pConfig) { + return DEV_WIRE_ERR; + } + pConfig->u.i2c_dev.wire->beginTransmission(pConfig->u.i2c_dev.addr); + pConfig->u.i2c_dev.wire->write(reg_addr); + if (pConfig->u.i2c_dev.wire->endTransmission() != 0) { + return DEV_WIRE_ERR; + } + pConfig->u.i2c_dev.wire->requestFrom(pConfig->u.i2c_dev.addr, length); + return pConfig->u.i2c_dev.wire->readBytes(reg_data, length) == length ? DEV_WIRE_NONE : DEV_WIRE_ERR; +} + +int8_t SensorInterfaces::bhy2_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + SensorLibConfigure *pConfig = (SensorLibConfigure *)intf_ptr; + if (!pConfig) { + return DEV_WIRE_ERR; + } + pConfig->u.i2c_dev.wire->beginTransmission(pConfig->u.i2c_dev.addr); + pConfig->u.i2c_dev.wire->write(reg_addr); + pConfig->u.i2c_dev.wire->write(reg_data, length); + return (pConfig->u.i2c_dev.wire->endTransmission() == 0) ? 0 : DEV_WIRE_ERR; + +} + + +void SensorInterfaces::bhy2_delay_us(uint32_t us, void *private_data) +{ + (void)private_data; + delayMicroseconds(us); +} diff --git a/lib/SensorLib/src/bosch/common/bosch_interfaces.h b/lib/SensorLib/src/bosch/common/bosch_interfaces.h new file mode 100644 index 0000000..2987496 --- /dev/null +++ b/lib/SensorLib/src/bosch/common/bosch_interfaces.h @@ -0,0 +1,60 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2022 lewis he + * + * 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. + * + * @file bosch_interfaces.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-09 + * + */ +#pragma once + +#include "SensorLib.h" + +class SensorInterfaces +{ +public: + static bool setup_interfaces(SensorLibConfigure config); + static void close_interfaces(SensorLibConfigure config); + static int8_t bhy2_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + static int8_t bhy2_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + static int8_t bhy2_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + static int8_t bhy2_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + static void bhy2_delay_us(uint32_t us, void *private_data); + +private: + static SPISettings __spiSetting; +}; + + + + + + + + + + + + + diff --git a/lib/SensorLib/src/bosch/common/common.cpp b/lib/SensorLib/src/bosch/common/common.cpp new file mode 100644 index 0000000..bb0a9f5 --- /dev/null +++ b/lib/SensorLib/src/bosch/common/common.cpp @@ -0,0 +1,987 @@ +/** + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file common.c + * @brief Common source file for the BHy260 examples + * @note Adapting Arduino based on BHY2-Sensor-API by lewis + */ + +#include "common.h" +#include "bosch/bhy2_parse.h" +#include "bosch/bhy2.h" + + +void time_to_s_ns(uint64_t time_ticks, uint32_t *s, uint32_t *ns, uint64_t *tns) +{ + *tns = time_ticks * 15625; /* timestamp is now in nanoseconds */ + *s = (uint32_t)(*tns / UINT64_C(1000000000)); + *ns = (uint32_t)(*tns - ((*s) * UINT64_C(1000000000))); +} + +const char *get_api_error(int8_t error_code) +{ + const char *ret; + + switch (error_code) { + case BHY2_OK: + ret = "[API Success]"; + break; + case BHY2_E_NULL_PTR: + ret = "[API Error] Null pointer"; + break; + case BHY2_E_INVALID_PARAM: + ret = "[API Error] Invalid parameter"; + break; + case BHY2_E_IO: + ret = "[API Error] IO error"; + break; + case BHY2_E_MAGIC: + ret = "[API Error] Invalid firmware"; + break; + case BHY2_E_TIMEOUT: + ret = "[API Error] Timed out"; + break; + case BHY2_E_BUFFER: + ret = "[API Error] Invalid buffer"; + break; + case BHY2_E_INVALID_FIFO_TYPE: + ret = "[API Error] Invalid FIFO type"; + break; + case BHY2_E_INVALID_EVENT_SIZE: + ret = "[API Error] Invalid Event size"; + break; + case BHY2_E_PARAM_NOT_SET: + ret = "[API Error] Parameter not set"; + break; + default: + ret = "[API Error] Unknown API error code"; + } + + return ret; +} + +const char *get_sensor_error_text(uint8_t sensor_error) +{ + const char *ret; + + switch (sensor_error) { + case 0x00: + break; + case 0x10: + ret = "[Sensor error] Bootloader reports: Firmware Expected Version Mismatch"; + break; + case 0x11: + ret = "[Sensor error] Bootloader reports: Firmware Upload Failed: Bad Header CRC"; + break; + case 0x12: + ret = "[Sensor error] Bootloader reports: Firmware Upload Failed: SHA Hash Mismatch"; + break; + case 0x13: + ret = "[Sensor error] Bootloader reports: Firmware Upload Failed: Bad Image CRC"; + break; + case 0x14: + ret = "[Sensor error] Bootloader reports: Firmware Upload Failed: ECDSA Signature Verification Failed"; + break; + case 0x15: + ret = "[Sensor error] Bootloader reports: Firmware Upload Failed: Bad Public Key CRC"; + break; + case 0x16: + ret = "[Sensor error] Bootloader reports: Firmware Upload Failed: Signed Firmware Required"; + break; + case 0x17: + ret = "[Sensor error] Bootloader reports: Firmware Upload Failed: FW Header Missing"; + break; + case 0x19: + ret = "[Sensor error] Bootloader reports: Unexpected Watchdog Reset"; + break; + case 0x1A: + ret = "[Sensor error] ROM Version Mismatch"; + break; + case 0x1B: + ret = "[Sensor error] Bootloader reports: Fatal Firmware Error"; + break; + case 0x1C: + ret = "[Sensor error] Chained Firmware Error: Next Payload Not Found"; + break; + case 0x1D: + ret = "[Sensor error] Chained Firmware Error: Payload Not Valid"; + break; + case 0x1E: + ret = "[Sensor error] Chained Firmware Error: Payload Entries Invalid"; + break; + case 0x1F: + ret = "[Sensor error] Bootloader reports: Bootloader Error: OTP CRC Invalid"; + break; + case 0x20: + ret = "[Sensor error] Firmware Init Failed"; + break; + case 0x21: + ret = "[Sensor error] Sensor Init Failed: Unexpected Device ID"; + break; + case 0x22: + ret = "[Sensor error] Sensor Init Failed: No Response from Device"; + break; + case 0x23: + ret = "[Sensor error] Sensor Init Failed: Unknown"; + break; + case 0x24: + ret = "[Sensor error] Sensor Error: No Valid Data"; + break; + case 0x25: + ret = "[Sensor error] Slow Sample Rate"; + break; + case 0x26: + ret = "[Sensor error] Data Overflow (saturated sensor data)"; + break; + case 0x27: + ret = "[Sensor error] Stack Overflow"; + break; + case 0x28: + ret = "[Sensor error] Insufficient Free RAM"; + break; + case 0x29: + ret = "[Sensor error] Sensor Init Failed: Driver Parsing Error"; + break; + case 0x2A: + ret = "[Sensor error] Too Many RAM Banks Required"; + break; + case 0x2B: + ret = "[Sensor error] Invalid Event Specified"; + break; + case 0x2C: + ret = "[Sensor error] More than 32 On Change"; + break; + case 0x2D: + ret = "[Sensor error] Firmware Too Large"; + break; + case 0x2F: + ret = "[Sensor error] Invalid RAM Banks"; + break; + case 0x30: + ret = "[Sensor error] Math Error"; + break; + case 0x40: + ret = "[Sensor error] Memory Error"; + break; + case 0x41: + ret = "[Sensor error] SWI3 Error"; + break; + case 0x42: + ret = "[Sensor error] SWI4 Error"; + break; + case 0x43: + ret = "[Sensor error] Illegal Instruction Error"; + break; + case 0x44: + ret = "[Sensor error] Bootloader reports: Unhandled Interrupt Error / Exception / Postmortem Available"; + break; + case 0x45: + ret = "[Sensor error] Invalid Memory Access"; + break; + case 0x50: + ret = "[Sensor error] Algorithm Error: BSX Init"; + break; + case 0x51: + ret = "[Sensor error] Algorithm Error: BSX Do Step"; + break; + case 0x52: + ret = "[Sensor error] Algorithm Error: Update Sub"; + break; + case 0x53: + ret = "[Sensor error] Algorithm Error: Get Sub"; + break; + case 0x54: + ret = "[Sensor error] Algorithm Error: Get Phys"; + break; + case 0x55: + ret = "[Sensor error] Algorithm Error: Unsupported Phys Rate"; + break; + case 0x56: + ret = "[Sensor error] Algorithm Error: Cannot find BSX Driver"; + break; + case 0x60: + ret = "[Sensor error] Sensor Self-Test Failure"; + break; + case 0x61: + ret = "[Sensor error] Sensor Self-Test X Axis Failure"; + break; + case 0x62: + ret = "[Sensor error] Sensor Self-Test Y Axis Failure"; + break; + case 0x64: + ret = "[Sensor error] Sensor Self-Test Z Axis Failure"; + break; + case 0x65: + ret = "[Sensor error] FOC Failure"; + break; + case 0x66: + ret = "[Sensor error] Sensor Busy"; + break; + case 0x6F: + ret = "[Sensor error] Self-Test or FOC Test Unsupported"; + break; + case 0x72: + ret = "[Sensor error] No Host Interrupt Set"; + break; + case 0x73: + ret = "[Sensor error] Event ID Passed to Host Interface Has No Known Size"; + break; + case 0x75: + ret = "[Sensor error] Host Download Channel Underflow (Host Read Too Fast)"; + break; + case 0x76: + ret = "[Sensor error] Host Upload Channel Overflow (Host Wrote Too Fast)"; + break; + case 0x77: + ret = "[Sensor error] Host Download Channel Empty"; + break; + case 0x78: + ret = "[Sensor error] DMA Error"; + break; + case 0x79: + ret = "[Sensor error] Corrupted Input Block Chain"; + break; + case 0x7A: + ret = "[Sensor error] Corrupted Output Block Chain"; + break; + case 0x7B: + ret = "[Sensor error] Buffer Block Manager Error"; + break; + case 0x7C: + ret = "[Sensor error] Input Channel Not Word Aligned"; + break; + case 0x7D: + ret = "[Sensor error] Too Many Flush Events"; + break; + case 0x7E: + ret = "[Sensor error] Unknown Host Channel Error"; + break; + case 0x81: + ret = "[Sensor error] Decimation Too Large"; + break; + case 0x90: + ret = "[Sensor error] Master SPI/I2C Queue Overflow"; + break; + case 0x91: + ret = "[Sensor error] SPI/I2C Callback Error"; + break; + case 0xA0: + ret = "[Sensor error] Timer Scheduling Error"; + break; + case 0xB0: + ret = "[Sensor error] Invalid GPIO for Host IRQ"; + break; + case 0xB1: + ret = "[Sensor error] Error Sending Initialized Meta Events"; + break; + case 0xC0: + ret = "[Sensor error] Bootloader reports: Command Error"; + break; + case 0xC1: + ret = "[Sensor error] Bootloader reports: Command Too Long"; + break; + case 0xC2: + ret = "[Sensor error] Bootloader reports: Command Buffer Overflow"; + break; + case 0xD0: + ret = "[Sensor error] User Mode Error: Sys Call Invalid"; + break; + case 0xD1: + ret = "[Sensor error] User Mode Error: Trap Invalid"; + break; + case 0xE1: + ret = "[Sensor error] Firmware Upload Failed: Firmware header corrupt"; + break; + case 0xE2: + ret = "[Sensor error] Sensor Data Injection: Invalid input stream"; + break; + default: + ret = "[Sensor error] Unknown error code"; + } + + return ret; +} + +const char *get_sensor_name(uint8_t sensor_id) +{ + const char *ret; + + switch (sensor_id) { + case BHY2_SENSOR_ID_ACC_PASS: + ret = "Accelerometer passthrough"; + break; + case BHY2_SENSOR_ID_ACC_RAW: + ret = "Accelerometer uncalibrated"; + break; + case BHY2_SENSOR_ID_ACC: + ret = "Accelerometer corrected"; + break; + case BHY2_SENSOR_ID_ACC_BIAS: + ret = "Accelerometer offset"; + break; + case BHY2_SENSOR_ID_ACC_WU: + ret = "Accelerometer corrected wake up"; + break; + case BHY2_SENSOR_ID_ACC_RAW_WU: + ret = "Accelerometer uncalibrated wake up"; + break; + case BHY2_SENSOR_ID_GYRO_PASS: + ret = "Gyroscope passthrough"; + break; + case BHY2_SENSOR_ID_GYRO_RAW: + ret = "Gyroscope uncalibrated"; + break; + case BHY2_SENSOR_ID_GYRO: + ret = "Gyroscope corrected"; + break; + case BHY2_SENSOR_ID_GYRO_BIAS: + ret = "Gyroscope offset"; + break; + case BHY2_SENSOR_ID_GYRO_WU: + ret = "Gyroscope wake up"; + break; + case BHY2_SENSOR_ID_GYRO_RAW_WU: + ret = "Gyroscope uncalibrated wake up"; + break; + case BHY2_SENSOR_ID_MAG_PASS: + ret = "Magnetometer passthrough"; + break; + case BHY2_SENSOR_ID_MAG_RAW: + ret = "Magnetometer uncalibrated"; + break; + case BHY2_SENSOR_ID_MAG: + ret = "Magnetometer corrected"; + break; + case BHY2_SENSOR_ID_MAG_BIAS: + ret = "Magnetometer offset"; + break; + case BHY2_SENSOR_ID_MAG_WU: + ret = "Magnetometer wake up"; + break; + case BHY2_SENSOR_ID_MAG_RAW_WU: + ret = "Magnetometer uncalibrated wake up"; + break; + case BHY2_SENSOR_ID_GRA: + ret = "Gravity vector"; + break; + case BHY2_SENSOR_ID_GRA_WU: + ret = "Gravity vector wake up"; + break; + case BHY2_SENSOR_ID_LACC: + ret = "Linear acceleration"; + break; + case BHY2_SENSOR_ID_LACC_WU: + ret = "Linear acceleration wake up"; + break; + case BHY2_SENSOR_ID_RV: + ret = "Rotation vector"; + break; + case BHY2_SENSOR_ID_RV_WU: + ret = "Rotation vector wake up"; + break; + case BHY2_SENSOR_ID_GAMERV: + ret = "Game rotation vector"; + break; + case BHY2_SENSOR_ID_GAMERV_WU: + ret = "Game rotation vector wake up"; + break; + case BHY2_SENSOR_ID_GEORV: + ret = "Geo-magnetic rotation vector"; + break; + case BHY2_SENSOR_ID_GEORV_WU: + ret = "Geo-magnetic rotation vector wake up"; + break; + case BHY2_SENSOR_ID_ORI: + ret = "Orientation"; + break; + case BHY2_SENSOR_ID_ORI_WU: + ret = "Orientation wake up"; + break; + case BHY2_SENSOR_ID_ACC_BIAS_WU: + ret = "Accelerometer offset wake up"; + break; + case BHY2_SENSOR_ID_GYRO_BIAS_WU: + ret = "Gyroscope offset wake up"; + break; + case BHY2_SENSOR_ID_MAG_BIAS_WU: + ret = "Magnetometer offset wake up"; + break; + case BHY2_SENSOR_ID_TEMP: + ret = "Temperature"; + break; + case BHY2_SENSOR_ID_BARO: + ret = "Barometer"; + break; + case BHY2_SENSOR_ID_HUM: + ret = "Humidity"; + break; + case BHY2_SENSOR_ID_GAS: + ret = "Gas"; + break; + case BHY2_SENSOR_ID_TEMP_WU: + ret = "Temperature wake up"; + break; + case BHY2_SENSOR_ID_BARO_WU: + ret = "Barometer wake up"; + break; + case BHY2_SENSOR_ID_HUM_WU: + ret = "Humidity wake up"; + break; + case BHY2_SENSOR_ID_GAS_WU: + ret = "Gas wake up"; + break; + case BHY2_SENSOR_ID_KLIO: + ret = "Klio"; + break; + case BHY2_SENSOR_ID_KLIO_LOG: + ret = "Klio log"; + break; + case BHY2_SENSOR_ID_SWIM: + ret = "Swim recognition"; + break; + case BHY2_SENSOR_ID_SI_ACCEL: + ret = "SI Accel"; + break; + case BHY2_SENSOR_ID_SI_GYROS: + ret = "SI Gyro"; + break; + case BHY2_SENSOR_ID_LIGHT: + ret = "Light"; + break; + case BHY2_SENSOR_ID_LIGHT_WU: + ret = "Light wake up"; + break; + case BHY2_SENSOR_ID_PROX: + ret = "Proximity"; + break; + case BHY2_SENSOR_ID_PROX_WU: + ret = "Proximity wake up"; + break; + case BHY2_SENSOR_ID_STC: + ret = "Step counter"; + break; + case BHY2_SENSOR_ID_STC_WU: + ret = "Step counter wake up"; + break; + case BHY2_SENSOR_ID_STC_LP: + ret = "Low Power Step counter"; + break; + case BHY2_SENSOR_ID_STC_LP_WU: + ret = "Low Power Step counter wake up"; + break; + case BHY2_SENSOR_ID_SIG: + ret = "Significant motion"; + break; + case BHY2_SENSOR_ID_STD: + ret = "Step detector"; + break; + case BHY2_SENSOR_ID_STD_WU: + ret = "Step detector wake up"; + break; + case BHY2_SENSOR_ID_TILT_DETECTOR: + ret = "Tilt detector"; + break; + case BHY2_SENSOR_ID_WAKE_GESTURE: + ret = "Wake gesture"; + break; + case BHY2_SENSOR_ID_GLANCE_GESTURE: + ret = "Glance gesture"; + break; + case BHY2_SENSOR_ID_PICKUP_GESTURE: + ret = "Pickup gesture"; + break; + case BHY2_SENSOR_ID_SIG_LP: + ret = "Low Power Significant motion"; + break; + case BHY2_SENSOR_ID_SIG_LP_WU: + ret = "Low Power Significant motion wake up"; + break; + case BHY2_SENSOR_ID_STD_LP: + ret = "Low Power Step detector"; + break; + case BHY2_SENSOR_ID_STD_LP_WU: + ret = "Low Power Step detector wake up"; + break; + case BHY2_SENSOR_ID_AR: + ret = "Activity recognition"; + break; + case BHY2_SENSOR_ID_EXCAMERA: + ret = "External camera trigger"; + break; + case BHY2_SENSOR_ID_GPS: + ret = "GPS"; + break; + case BHY2_SENSOR_ID_WRIST_TILT_GESTURE: + ret = "Wrist tilt gesture"; + break; + case BHY2_SENSOR_ID_DEVICE_ORI: + ret = "Device orientation"; + break; + case BHY2_SENSOR_ID_DEVICE_ORI_WU: + ret = "Device orientation wake up"; + break; + case BHY2_SENSOR_ID_STATIONARY_DET: + ret = "Stationary detect"; + break; + case BHY2_SENSOR_ID_ANY_MOTION_LP: + ret = "Low Power Any motion"; + break; + case BHY2_SENSOR_ID_ANY_MOTION_LP_WU: + ret = "Low Power Any motion wake up"; + break; + case BHI3_SENSOR_ID_NO_MOTION_LP_WU: + ret = "Low Power No Motion wake up"; + break; + case BHY2_SENSOR_ID_MOTION_DET: + ret = "Motion detect"; + break; + case BHI3_SENSOR_ID_AR_WEAR_WU: + ret = "Activity recognition for Wearables"; + break; + case BHI3_SENSOR_ID_WRIST_WEAR_LP_WU: + ret = "Low Power Wrist Wear wake up"; + break; + case BHI3_SENSOR_ID_WRIST_GEST_DETECT_LP_WU: + ret = "Low Power Wrist Gesture wake up"; + break; + case BHI3_SENSOR_ID_MULTI_TAP: + ret = "Multi Tap Detector"; + break; + case BHY2_SENSOR_ID_AIR_QUALITY: + ret = "Air Quality"; + break; + case BHY2_SENSOR_ID_HEAD_ORI_MIS_ALG: + ret = "Head Misalignment Calibrator"; + break; + case BHY2_SENSOR_ID_IMU_HEAD_ORI_Q: + ret = "IMU Head Orientation Quaternion"; + break; + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_Q: + ret = "NDOF Head Orientation Quaternion"; + break; + case BHY2_SENSOR_ID_IMU_HEAD_ORI_E: + ret = "IMU Head Orientation Euler"; + break; + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_E: + ret = "NDOF Head Orientation Euler"; + break; + default: + if ((sensor_id >= BHY2_SENSOR_ID_CUSTOM_START) && (sensor_id <= BHY2_SENSOR_ID_CUSTOM_END)) { + ret = "Custom sensor ID "; + } else { + ret = "Undefined sensor ID "; + } + } + + return ret; +} + +float get_sensor_default_scaling(uint8_t sensor_id) +{ + float scaling = -1.0f; + + switch (sensor_id) { + case BHY2_SENSOR_ID_ACC_PASS: + case BHY2_SENSOR_ID_ACC_RAW: + case BHY2_SENSOR_ID_ACC: + case BHY2_SENSOR_ID_ACC_BIAS: + case BHY2_SENSOR_ID_ACC_WU: + case BHY2_SENSOR_ID_ACC_RAW_WU: + case BHY2_SENSOR_ID_GRA: + case BHY2_SENSOR_ID_GRA_WU: + case BHY2_SENSOR_ID_LACC: + case BHY2_SENSOR_ID_LACC_WU: + case BHY2_SENSOR_ID_ACC_BIAS_WU: + scaling = 1.0f / 4096.0f; + break; + case BHY2_SENSOR_ID_GYRO_PASS: + case BHY2_SENSOR_ID_GYRO_RAW: + case BHY2_SENSOR_ID_GYRO: + case BHY2_SENSOR_ID_GYRO_BIAS: + case BHY2_SENSOR_ID_GYRO_WU: + case BHY2_SENSOR_ID_GYRO_RAW_WU: + case BHY2_SENSOR_ID_GYRO_BIAS_WU: + scaling = 2000.0f / 32768.0f; + break; + case BHY2_SENSOR_ID_MAG_PASS: + case BHY2_SENSOR_ID_MAG_RAW: + case BHY2_SENSOR_ID_MAG: + case BHY2_SENSOR_ID_MAG_BIAS: + case BHY2_SENSOR_ID_MAG_WU: + case BHY2_SENSOR_ID_MAG_RAW_WU: + case BHY2_SENSOR_ID_MAG_BIAS_WU: + scaling = 2500.0f / 32768.0f; + break; + case BHY2_SENSOR_ID_RV: + case BHY2_SENSOR_ID_RV_WU: + case BHY2_SENSOR_ID_GAMERV: + case BHY2_SENSOR_ID_GAMERV_WU: + case BHY2_SENSOR_ID_GEORV: + case BHY2_SENSOR_ID_GEORV_WU: + scaling = 1.0f / 16384.0f; + break; + case BHY2_SENSOR_ID_ORI: + case BHY2_SENSOR_ID_ORI_WU: + scaling = 360.0f / 32768.0f; + break; + case BHY2_SENSOR_ID_TEMP: + case BHY2_SENSOR_ID_TEMP_WU: + scaling = 1.0f / 100.0f; + break; + case BHY2_SENSOR_ID_BARO: + case BHY2_SENSOR_ID_BARO_WU: + scaling = 100.0f / 128.0f; + break; + case BHY2_SENSOR_ID_HUM: + case BHY2_SENSOR_ID_HUM_WU: + scaling = 1.0f; + break; + case BHY2_SENSOR_ID_GAS: + case BHY2_SENSOR_ID_GAS_WU: + scaling = 1.0f; + break; + case BHY2_SENSOR_ID_LIGHT: + case BHY2_SENSOR_ID_LIGHT_WU: + scaling = 10000.0f / 216.0f; + break; + case BHY2_SENSOR_ID_PROX: + case BHY2_SENSOR_ID_PROX_WU: + scaling = 1.0f; + break; + case BHY2_SENSOR_ID_SI_ACCEL: + case BHY2_SENSOR_ID_SI_GYROS: + + /* Scaling factor already applied in firmware*/ + break; + case BHY2_SENSOR_ID_HEAD_ORI_MIS_ALG: + case BHY2_SENSOR_ID_IMU_HEAD_ORI_Q: + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_Q: + scaling = 1.0f / 16384.0f; /*2^14 -> 16384*/ + break; + case BHY2_SENSOR_ID_IMU_HEAD_ORI_E: + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_E: + scaling = 360.0f / 32768.0f; /*2^15 -> 32768*/ + break; + default: + scaling = -1.0f; /* Do not apply the scaling factor */ + } + + return scaling; +} + +const char *get_sensor_parse_format(uint8_t sensor_id) +{ + const char *ret; + + switch (sensor_id) { + case BHY2_SENSOR_ID_ACC_PASS: + case BHY2_SENSOR_ID_ACC_RAW: + case BHY2_SENSOR_ID_ACC: + case BHY2_SENSOR_ID_ACC_BIAS: + case BHY2_SENSOR_ID_ACC_BIAS_WU: + case BHY2_SENSOR_ID_ACC_WU: + case BHY2_SENSOR_ID_ACC_RAW_WU: + case BHY2_SENSOR_ID_GYRO_PASS: + case BHY2_SENSOR_ID_GYRO_RAW: + case BHY2_SENSOR_ID_GYRO: + case BHY2_SENSOR_ID_GYRO_BIAS: + case BHY2_SENSOR_ID_GYRO_BIAS_WU: + case BHY2_SENSOR_ID_GYRO_WU: + case BHY2_SENSOR_ID_GYRO_RAW_WU: + case BHY2_SENSOR_ID_MAG_PASS: + case BHY2_SENSOR_ID_MAG_RAW: + case BHY2_SENSOR_ID_MAG: + case BHY2_SENSOR_ID_MAG_BIAS: + case BHY2_SENSOR_ID_MAG_BIAS_WU: + case BHY2_SENSOR_ID_MAG_WU: + case BHY2_SENSOR_ID_MAG_RAW_WU: + case BHY2_SENSOR_ID_GRA: + case BHY2_SENSOR_ID_GRA_WU: + case BHY2_SENSOR_ID_LACC: + case BHY2_SENSOR_ID_LACC_WU: + ret = "s16,s16,s16"; + break; + case BHY2_SENSOR_ID_RV: + case BHY2_SENSOR_ID_RV_WU: + case BHY2_SENSOR_ID_GAMERV: + case BHY2_SENSOR_ID_GAMERV_WU: + case BHY2_SENSOR_ID_GEORV: + case BHY2_SENSOR_ID_GEORV_WU: + ret = "s16,s16,s16,s16,u16"; + break; + case BHY2_SENSOR_ID_ORI: + case BHY2_SENSOR_ID_ORI_WU: + ret = "s16,s16,s16"; + break; + case BHY2_SENSOR_ID_DEVICE_ORI: + case BHY2_SENSOR_ID_DEVICE_ORI_WU: + case BHY2_SENSOR_ID_HUM: + case BHY2_SENSOR_ID_HUM_WU: + case BHY2_SENSOR_ID_PROX: + case BHY2_SENSOR_ID_PROX_WU: + case BHY2_SENSOR_ID_EXCAMERA: + case BHI3_SENSOR_ID_MULTI_TAP: + ret = "u8"; + break; + case BHY2_SENSOR_ID_TEMP: + case BHY2_SENSOR_ID_TEMP_WU: + ret = "s16"; + break; + case BHY2_SENSOR_ID_BARO: + case BHY2_SENSOR_ID_BARO_WU: + ret = "u24"; + break; + case BHY2_SENSOR_ID_GAS: + case BHY2_SENSOR_ID_GAS_WU: + case BHY2_SENSOR_ID_STC: + case BHY2_SENSOR_ID_STC_WU: + case BHY2_SENSOR_ID_STC_LP: + case BHY2_SENSOR_ID_STC_LP_WU: + ret = "u32"; + break; + case BHY2_SENSOR_ID_KLIO: + ret = "u8,u8,u8,u8,u8,u8,f"; + break; + case BHY2_SENSOR_ID_SWIM: + ret = "u16,u16,u16,u16,u16,u16,u16"; + break; + case BHY2_SENSOR_ID_SI_ACCEL: + case BHY2_SENSOR_ID_SI_GYROS: + ret = "f,f,f"; + break; + case BHY2_SENSOR_ID_LIGHT: + case BHY2_SENSOR_ID_LIGHT_WU: + ret = "s16"; + break; + case BHY2_SENSOR_ID_SIG: + case BHY2_SENSOR_ID_STD: + case BHY2_SENSOR_ID_STD_WU: + case BHY2_SENSOR_ID_TILT_DETECTOR: + case BHY2_SENSOR_ID_WAKE_GESTURE: + case BHY2_SENSOR_ID_GLANCE_GESTURE: + case BHY2_SENSOR_ID_PICKUP_GESTURE: + case BHY2_SENSOR_ID_SIG_LP: + case BHY2_SENSOR_ID_SIG_LP_WU: + case BHY2_SENSOR_ID_STD_LP: + case BHY2_SENSOR_ID_STD_LP_WU: + case BHY2_SENSOR_ID_WRIST_TILT_GESTURE: + case BHY2_SENSOR_ID_STATIONARY_DET: + case BHY2_SENSOR_ID_ANY_MOTION_LP: + case BHY2_SENSOR_ID_ANY_MOTION_LP_WU: + case BHI3_SENSOR_ID_NO_MOTION_LP_WU: + case BHY2_SENSOR_ID_MOTION_DET: + case BHI3_SENSOR_ID_WRIST_WEAR_LP_WU: + ret = ""; + break; + case BHY2_SENSOR_ID_AR: + case BHI3_SENSOR_ID_AR_WEAR_WU: + ret = "u16"; + break; + case BHY2_SENSOR_ID_GPS: + ret = "st"; + break; + case BHI3_SENSOR_ID_WRIST_GEST_DETECT_LP_WU: + ret = "u8"; + break; + case BHY2_SENSOR_ID_AIR_QUALITY: + ret = "f32,f32,f32,f32,f32,f32,f32,u8"; + break; + case BHY2_SENSOR_ID_HEAD_ORI_MIS_ALG: + case BHY2_SENSOR_ID_IMU_HEAD_ORI_Q: + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_Q: + ret = "s16,s16,s16,s16,u8"; + break; + + case BHY2_SENSOR_ID_IMU_HEAD_ORI_E: + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_E: + ret = "s16,s16,s16,u8"; + break; + default: + ret = ""; + } + + return ret; +} + +const char *get_sensor_axis_names(uint8_t sensor_id) +{ + const char *ret; + + switch (sensor_id) { + case BHY2_SENSOR_ID_ACC_PASS: + case BHY2_SENSOR_ID_ACC_RAW: + case BHY2_SENSOR_ID_ACC: + case BHY2_SENSOR_ID_ACC_BIAS: + case BHY2_SENSOR_ID_ACC_BIAS_WU: + case BHY2_SENSOR_ID_ACC_WU: + case BHY2_SENSOR_ID_ACC_RAW_WU: + case BHY2_SENSOR_ID_GYRO_PASS: + case BHY2_SENSOR_ID_GYRO_RAW: + case BHY2_SENSOR_ID_GYRO: + case BHY2_SENSOR_ID_GYRO_BIAS: + case BHY2_SENSOR_ID_GYRO_BIAS_WU: + case BHY2_SENSOR_ID_GYRO_WU: + case BHY2_SENSOR_ID_GYRO_RAW_WU: + case BHY2_SENSOR_ID_MAG_PASS: + case BHY2_SENSOR_ID_MAG_RAW: + case BHY2_SENSOR_ID_MAG: + case BHY2_SENSOR_ID_MAG_BIAS: + case BHY2_SENSOR_ID_MAG_BIAS_WU: + case BHY2_SENSOR_ID_MAG_WU: + case BHY2_SENSOR_ID_MAG_RAW_WU: + case BHY2_SENSOR_ID_GRA: + case BHY2_SENSOR_ID_GRA_WU: + case BHY2_SENSOR_ID_LACC: + case BHY2_SENSOR_ID_LACC_WU: + case BHY2_SENSOR_ID_SI_ACCEL: + case BHY2_SENSOR_ID_SI_GYROS: + ret = "x,y,z"; + break; + case BHY2_SENSOR_ID_RV: + case BHY2_SENSOR_ID_RV_WU: + case BHY2_SENSOR_ID_GAMERV: + case BHY2_SENSOR_ID_GAMERV_WU: + case BHY2_SENSOR_ID_GEORV: + case BHY2_SENSOR_ID_GEORV_WU: + ret = "x,y,z,w,ar"; + break; + case BHY2_SENSOR_ID_ORI: + case BHY2_SENSOR_ID_ORI_WU: + ret = "h,p,r"; + break; + case BHY2_SENSOR_ID_DEVICE_ORI: + case BHY2_SENSOR_ID_DEVICE_ORI_WU: + ret = "o"; + break; + case BHY2_SENSOR_ID_TEMP: + case BHY2_SENSOR_ID_TEMP_WU: + ret = "t"; + break; + case BHY2_SENSOR_ID_BARO: + case BHY2_SENSOR_ID_BARO_WU: + ret = "p"; + break; + case BHY2_SENSOR_ID_HUM: + case BHY2_SENSOR_ID_HUM_WU: + ret = "h"; + break; + case BHY2_SENSOR_ID_GAS: + case BHY2_SENSOR_ID_GAS_WU: + ret = "g"; + break; + case BHY2_SENSOR_ID_KLIO: + ret = "lin,lid,lpr,lcr,rin,rid,rc"; + break; + case BHY2_SENSOR_ID_SWIM: + ret = "d,lc,f,br,bu,ba,sc"; + break; + case BHY2_SENSOR_ID_LIGHT: + case BHY2_SENSOR_ID_LIGHT_WU: + ret = "l"; + break; + case BHY2_SENSOR_ID_PROX: + case BHY2_SENSOR_ID_PROX_WU: + ret = "p"; + break; + case BHY2_SENSOR_ID_STC: + case BHY2_SENSOR_ID_STC_WU: + case BHY2_SENSOR_ID_STC_LP: + case BHY2_SENSOR_ID_STC_LP_WU: + case BHY2_SENSOR_ID_EXCAMERA: + ret = "c"; + break; + case BHY2_SENSOR_ID_SIG: + case BHY2_SENSOR_ID_STD: + case BHY2_SENSOR_ID_STD_WU: + case BHY2_SENSOR_ID_TILT_DETECTOR: + case BHY2_SENSOR_ID_WAKE_GESTURE: + case BHY2_SENSOR_ID_GLANCE_GESTURE: + case BHY2_SENSOR_ID_PICKUP_GESTURE: + case BHY2_SENSOR_ID_SIG_LP: + case BHY2_SENSOR_ID_SIG_LP_WU: + case BHY2_SENSOR_ID_STD_LP: + case BHY2_SENSOR_ID_STD_LP_WU: + case BHY2_SENSOR_ID_WRIST_TILT_GESTURE: + case BHY2_SENSOR_ID_STATIONARY_DET: + case BHY2_SENSOR_ID_ANY_MOTION_LP: + case BHY2_SENSOR_ID_ANY_MOTION_LP_WU: + case BHI3_SENSOR_ID_NO_MOTION_LP_WU: + case BHY2_SENSOR_ID_MOTION_DET: + case BHI3_SENSOR_ID_WRIST_WEAR_LP_WU: + ret = "e"; + break; + case BHY2_SENSOR_ID_AR: + case BHI3_SENSOR_ID_AR_WEAR_WU: + ret = "a"; + break; + case BHY2_SENSOR_ID_GPS: + ret = "g"; + break; + case BHI3_SENSOR_ID_WRIST_GEST_DETECT_LP_WU: + ret = "wrist_gesture"; + break; + case BHI3_SENSOR_ID_MULTI_TAP: + ret = "taps"; + break; + case BHY2_SENSOR_ID_AIR_QUALITY: + ret = "t,h,g,i,si,c,v,a"; + break; + case BHY2_SENSOR_ID_HEAD_ORI_MIS_ALG: + case BHY2_SENSOR_ID_IMU_HEAD_ORI_Q: + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_Q: + ret = "x,y,z,w,a"; + break; + case BHY2_SENSOR_ID_IMU_HEAD_ORI_E: + case BHY2_SENSOR_ID_NDOF_HEAD_ORI_E: + ret = "h,p,r,a"; + break; + default: + ret = ""; + } + + return ret; +} + +void check_bhy2_api(unsigned int line, const char *func, int8_t val) +{ + int i = 3; + while (i--) { + + Serial.printf("BHI260 API failed at line %u. The function %s returned error code %d. %s\r\n", + line, + func, + val, + get_api_error(val)); + delay(1000); + } +} + diff --git a/lib/SensorLib/src/bosch/common/common.h b/lib/SensorLib/src/bosch/common/common.h new file mode 100644 index 0000000..ed25075 --- /dev/null +++ b/lib/SensorLib/src/bosch/common/common.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file common.h + * @brief Common header file for the BHI260/BHA260 examples + * @note Adapting Arduino based on BHY2-Sensor-API by lewis + */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include "bosch_interfaces.h" +#include "bosch/bhy2.h" +#include "bosch/bhi3.h" +#include "bosch/bhi3_multi_tap.h" +#include "bosch/bhy2_klio.h" +#include "bosch/bhy2_swim.h" +#include "bosch/bhy2_bsec.h" +#include "bosch/bhy2_head_tracker.h" + + +#define BHY2_ASSERT(x) if (x) check_bhy2_api(__LINE__, __FUNCTION__, x) + + + +void check_bhy2_api(unsigned int line, const char *func, int8_t val); +void time_to_s_ns(uint64_t time_ticks, uint32_t *s, uint32_t *ns, uint64_t *tns); +const char *get_api_error(int8_t error_code); +const char *get_sensor_error_text(uint8_t sensor_error); +const char *get_sensor_name(uint8_t sensor_id); +float get_sensor_default_scaling(uint8_t sensor_id); +const char *get_sensor_parse_format(uint8_t sensor_id); +const char *get_sensor_axis_names(uint8_t sensor_id); + + +#endif /* _COMMON_H_ */ diff --git a/lib/SensorLib/src/bosch/firmware/BHI260AP.fw.h b/lib/SensorLib/src/bosch/firmware/BHI260AP.fw.h new file mode 100644 index 0000000..3d90b0c --- /dev/null +++ b/lib/SensorLib/src/bosch/firmware/BHI260AP.fw.h @@ -0,0 +1,8642 @@ +const unsigned char bhy2_firmware_image[] = { + 0x2b, 0x66, 0x00, 0x00, 0x00, 0x00, 0x67, 0x17, 0x8f, 0xfa, 0x20, 0xa5, + 0x64, 0xd4, 0xa3, 0x15, 0x17, 0x8c, 0x09, 0xcb, 0xfa, 0xed, 0xef, 0x7d, + 0x6c, 0x1c, 0xa8, 0xc2, 0x91, 0x52, 0xb0, 0xcb, 0x1d, 0x00, 0xef, 0xe6, + 0x22, 0x62, 0xfc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x53, 0x0d, 0x30, 0xdd, + 0x75, 0x1b, 0x11, 0xbe, 0x74, 0xdd, 0x97, 0xe9, 0x40, 0x5a, 0x28, 0xb7, + 0x8e, 0x5f, 0xc1, 0x62, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0xd9, 0x7a, + 0xc0, 0x7a, 0x98, 0x9f, 0x98, 0x26, 0x49, 0xcc, 0xf2, 0x24, 0x67, 0x01, + 0x26, 0x6c, 0xd9, 0x4d, 0x90, 0x69, 0x01, 0x00, 0x8e, 0x8d, 0xfb, 0x79, + 0x78, 0x51, 0x01, 0x00, 0x2e, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xd1, 0xb9, 0xa4, 0x54, 0x92, 0x13, 0x00, 0xd0, 0x29, 0x10, 0x00, + 0xd0, 0x29, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, + 0xd0, 0x29, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, + 0xd0, 0x29, 0x10, 0x00, 0xdc, 0x9a, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, + 0xd0, 0x29, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, + 0x70, 0x5d, 0x01, 0x00, 0xd0, 0x29, 0x10, 0x00, 0x6c, 0x5f, 0x12, 0x00, + 0x0c, 0xb1, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, 0x68, 0xb3, 0x10, 0x00, + 0x68, 0xb3, 0x10, 0x00, 0x68, 0xb3, 0x10, 0x00, 0x80, 0x4d, 0x12, 0x00, + 0xa4, 0x6d, 0x12, 0x00, 0xa4, 0x6d, 0x12, 0x00, 0x64, 0xb6, 0x10, 0x00, + 0xec, 0xb6, 0x10, 0x00, 0x34, 0xb8, 0x10, 0x00, 0x68, 0x6a, 0x12, 0x00, + 0xd0, 0x29, 0x10, 0x00, 0x2c, 0x1a, 0x10, 0x00, 0xc8, 0xb5, 0x10, 0x00, + 0x10, 0x15, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, 0xd0, 0x29, 0x10, 0x00, + 0xb8, 0x18, 0x10, 0x00, 0x6c, 0x19, 0x10, 0x00, 0x4c, 0x6e, 0x12, 0x00, + 0x4c, 0x6e, 0x12, 0x00, 0x4c, 0x6e, 0x12, 0x00, 0x34, 0xcd, 0x12, 0x00, + 0xc1, 0x02, 0xcf, 0xf2, 0x5d, 0x07, 0x4f, 0xf6, 0x1d, 0x05, 0x00, 0x01, + 0x81, 0x06, 0x00, 0x01, 0x4d, 0x06, 0xcf, 0xf7, 0x69, 0x06, 0xcf, 0xf7, + 0x85, 0x06, 0xcf, 0xf7, 0xd9, 0x07, 0xcf, 0xf7, 0xe5, 0x05, 0xcf, 0xf9, + 0x35, 0x06, 0xcf, 0xf9, 0x11, 0x07, 0xcf, 0xf9, 0xa1, 0x01, 0x0f, 0xfa, + 0xa9, 0x01, 0x0f, 0xfa, 0x95, 0x02, 0x0f, 0xfa, 0x09, 0x06, 0x0f, 0xfa, + 0x51, 0x06, 0x00, 0x08, 0x19, 0x01, 0x4f, 0xfa, 0xb5, 0x04, 0x4f, 0xfa, + 0xf5, 0x04, 0x4f, 0xfa, 0x5d, 0x05, 0x4f, 0xfa, 0x01, 0x04, 0xc0, 0x00, + 0x59, 0x06, 0x4f, 0xfa, 0x71, 0x06, 0x4f, 0xfa, 0x35, 0x06, 0x00, 0x08, + 0xb5, 0x01, 0x8f, 0xfa, 0xd9, 0x01, 0x8f, 0xfa, 0x89, 0x07, 0x00, 0x08, + 0x41, 0x02, 0x8f, 0xfa, 0x65, 0x03, 0x8f, 0xfa, 0xbd, 0x03, 0x8f, 0xfa, + 0x15, 0x04, 0x8f, 0xfa, 0x61, 0x04, 0x8f, 0xfa, 0x79, 0x04, 0x8f, 0xfa, + 0xa5, 0x07, 0x00, 0x08, 0xf9, 0x04, 0x8f, 0xfa, 0x01, 0x06, 0x40, 0x01, + 0x4d, 0x06, 0x8f, 0xfa, 0x81, 0x07, 0x8f, 0xfa, 0xa5, 0x01, 0xcf, 0xfa, + 0xa5, 0x02, 0xcf, 0xfa, 0x6d, 0x03, 0xcf, 0xfa, 0x79, 0x06, 0xcf, 0xfa, + 0xdd, 0x02, 0x40, 0x01, 0x35, 0x00, 0x0f, 0xfb, 0x75, 0x00, 0x0f, 0xfb, + 0xa9, 0x00, 0x0f, 0xfb, 0xd9, 0x00, 0x0f, 0xfb, 0xe1, 0x00, 0x0f, 0xfb, + 0xed, 0x00, 0x0f, 0xfb, 0xf5, 0x00, 0x0f, 0xfb, 0x05, 0x01, 0x0f, 0xfb, + 0x49, 0x02, 0x0f, 0xfb, 0x4d, 0x02, 0x0f, 0xfb, 0x55, 0x02, 0x0f, 0xfb, + 0x65, 0x02, 0x0f, 0xfb, 0x75, 0x02, 0x0f, 0xfb, 0x81, 0x02, 0x0f, 0xfb, + 0x75, 0x03, 0x0f, 0xfb, 0xad, 0x04, 0x0f, 0xfb, 0xd5, 0x04, 0x0f, 0xfb, + 0xed, 0x04, 0x0f, 0xfb, 0xf5, 0x04, 0x0f, 0xfb, 0x19, 0x05, 0x0f, 0xfb, + 0xf1, 0x03, 0x40, 0x01, 0x21, 0x06, 0x0f, 0xfb, 0x29, 0x02, 0x40, 0x08, + 0xd9, 0x06, 0x0f, 0xfb, 0x29, 0x01, 0x4f, 0xfb, 0x05, 0x05, 0xc0, 0x00, + 0x15, 0x02, 0x4f, 0xfb, 0xf1, 0x02, 0x4f, 0xfb, 0xad, 0x00, 0x80, 0x00, + 0x65, 0x00, 0x80, 0x00, 0xf5, 0x07, 0x40, 0x00, 0x39, 0x00, 0x80, 0x00, + 0x11, 0x00, 0x80, 0x00, 0x79, 0x00, 0x80, 0x00, 0xd9, 0x00, 0x80, 0x00, + 0xb5, 0x00, 0x80, 0x00, 0xf5, 0x05, 0x4f, 0xfb, 0xb9, 0x06, 0x4f, 0xfb, + 0xfd, 0x06, 0x4f, 0xfb, 0x91, 0x03, 0x40, 0x01, 0x51, 0x06, 0x8f, 0xfb, + 0x29, 0x02, 0xcf, 0xfb, 0xb5, 0x02, 0x0f, 0xfc, 0x35, 0x04, 0x0f, 0xfc, + 0x81, 0x04, 0x0f, 0xfc, 0x8d, 0x04, 0x0f, 0xfc, 0x61, 0x05, 0x0f, 0xfc, + 0x0d, 0x01, 0x8f, 0xfd, 0xa1, 0x01, 0x8f, 0xfd, 0xb1, 0x01, 0x8f, 0xfd, + 0xc1, 0x01, 0x8f, 0xfd, 0x51, 0x02, 0x40, 0x01, 0x91, 0x03, 0x8f, 0xfd, + 0x09, 0x05, 0x8f, 0xfd, 0x45, 0x04, 0xc0, 0x00, 0x99, 0x00, 0xcf, 0xfd, + 0xd9, 0x03, 0xc0, 0x00, 0x51, 0x02, 0x0f, 0xef, 0xbd, 0x04, 0xcf, 0xfd, + 0x25, 0x05, 0xcf, 0xfd, 0x6d, 0x06, 0xcf, 0xfd, 0xa5, 0x06, 0xcf, 0xfd, + 0x5d, 0x07, 0xcf, 0xfd, 0xf5, 0x07, 0xcf, 0xfd, 0x29, 0x00, 0x0f, 0xfe, + 0xe1, 0x01, 0x40, 0x01, 0x11, 0x02, 0x0f, 0xfe, 0xa1, 0x02, 0x0f, 0xfe, + 0x39, 0x03, 0x0f, 0xfe, 0xc9, 0x03, 0x0f, 0xfe, 0xb1, 0x04, 0x0f, 0xfe, + 0x71, 0x07, 0x0f, 0xfe, 0xb1, 0x02, 0x00, 0x09, 0xfd, 0x07, 0x0f, 0xfe, + 0x0d, 0x00, 0x4f, 0xfe, 0x61, 0x00, 0x4f, 0xfe, 0xb5, 0x00, 0x4f, 0xfe, + 0xb9, 0x00, 0x4f, 0xfe, 0xcd, 0x00, 0x4f, 0xfe, 0xf5, 0x00, 0x4f, 0xfe, + 0x05, 0x02, 0x4f, 0xfe, 0xd9, 0x05, 0x8f, 0xfe, 0x65, 0x06, 0x8f, 0xfe, + 0x7d, 0x06, 0x8f, 0xfe, 0x9d, 0x00, 0x40, 0x01, 0x35, 0x07, 0x8f, 0xfe, + 0x49, 0x07, 0x8f, 0xfe, 0x6d, 0x07, 0x8f, 0xfe, 0xe5, 0x07, 0x8f, 0xfe, + 0x15, 0x00, 0xcf, 0xfe, 0x9d, 0x00, 0xcf, 0xfe, 0xb5, 0x00, 0xcf, 0xfe, + 0xe5, 0x00, 0xcf, 0xfe, 0x59, 0x01, 0xcf, 0xfe, 0x05, 0x02, 0xcf, 0xfe, + 0x1d, 0x02, 0xcf, 0xfe, 0x6d, 0x02, 0x00, 0x09, 0x79, 0x02, 0x00, 0x09, + 0x85, 0x02, 0x00, 0x09, 0x51, 0x03, 0x00, 0x09, 0x4d, 0x02, 0xcf, 0xfe, + 0x9d, 0x02, 0xcf, 0xfe, 0xa5, 0x02, 0xcf, 0xfe, 0x99, 0x03, 0x00, 0x09, + 0x4d, 0x03, 0xcf, 0xfe, 0xb5, 0x03, 0xcf, 0xfe, 0x19, 0x04, 0xcf, 0xfe, + 0x81, 0x04, 0xcf, 0xfe, 0xa9, 0x04, 0xcf, 0xfe, 0xe5, 0x03, 0x00, 0x09, + 0x0d, 0x04, 0x00, 0x09, 0xd9, 0x06, 0x00, 0x01, 0xd9, 0x06, 0xcf, 0xfe, + 0x99, 0x07, 0xcf, 0xfe, 0xb1, 0x04, 0x00, 0x09, 0xe5, 0x04, 0x00, 0x09, + 0x0d, 0x05, 0x00, 0x09, 0x7d, 0x00, 0x0f, 0xff, 0xbd, 0x00, 0x0f, 0xff, + 0xb1, 0x05, 0x00, 0x01, 0x51, 0x06, 0x00, 0x09, 0x81, 0x02, 0x0f, 0xff, + 0x85, 0x02, 0x0f, 0xff, 0xa9, 0x02, 0xc0, 0x00, 0xcd, 0x02, 0x0f, 0xff, + 0x19, 0x03, 0x0f, 0xff, 0x19, 0x03, 0x0f, 0xff, 0x85, 0x05, 0x40, 0x00, + 0x6d, 0x06, 0x4f, 0xff, 0x35, 0x00, 0x8f, 0xff, 0x59, 0x02, 0xcf, 0xef, + 0x0d, 0x03, 0xcf, 0xef, 0xad, 0x03, 0xcf, 0xef, 0x01, 0x04, 0xcf, 0xef, + 0x8d, 0x04, 0xcf, 0xef, 0x9d, 0x04, 0xcf, 0xef, 0x11, 0x05, 0xcf, 0xef, + 0x59, 0x05, 0xcf, 0xef, 0x69, 0x05, 0xcf, 0xef, 0x39, 0x00, 0x00, 0x02, + 0xc5, 0x00, 0x00, 0x02, 0xdd, 0x01, 0x00, 0x02, 0xe1, 0x02, 0x00, 0x02, + 0xa5, 0x03, 0x00, 0x02, 0xf5, 0x03, 0x00, 0x02, 0xf1, 0x04, 0x00, 0x02, + 0x71, 0x05, 0x00, 0x02, 0x7d, 0x03, 0x0f, 0xf0, 0x71, 0x06, 0x00, 0x02, + 0x89, 0x07, 0x00, 0x02, 0xbd, 0x07, 0x00, 0x02, 0x91, 0x00, 0x40, 0x02, + 0x6d, 0x02, 0x40, 0x02, 0x31, 0x00, 0x4f, 0xf0, 0x5d, 0x01, 0x4f, 0xf0, + 0xf1, 0x02, 0x40, 0x02, 0x51, 0x07, 0x8f, 0xf0, 0x21, 0x00, 0xcf, 0xf0, + 0x45, 0x00, 0xcf, 0xf0, 0xb1, 0x01, 0xcf, 0xf0, 0xfd, 0x06, 0xcf, 0xf0, + 0x05, 0x07, 0xcf, 0xf0, 0xdd, 0x00, 0x0f, 0xf1, 0xe9, 0x00, 0x0f, 0xf1, + 0x51, 0x00, 0x80, 0x02, 0x79, 0x05, 0x0f, 0xf1, 0x31, 0x06, 0x0f, 0xf1, + 0x39, 0x06, 0x0f, 0xf1, 0x49, 0x06, 0x0f, 0xf1, 0x2d, 0x00, 0x4f, 0xf1, + 0x81, 0x00, 0x4f, 0xf1, 0x71, 0x01, 0xc0, 0x02, 0xe1, 0x02, 0xc0, 0x02, + 0x65, 0x03, 0xc0, 0x02, 0xed, 0x03, 0xc0, 0x02, 0x0d, 0x04, 0xc0, 0x02, + 0x0d, 0x04, 0xc0, 0x02, 0xdd, 0x02, 0x4f, 0xf1, 0x91, 0x04, 0xc0, 0x02, + 0x85, 0x04, 0x4f, 0xf1, 0x6d, 0x07, 0x4f, 0xf1, 0x71, 0x07, 0x4f, 0xf1, + 0x79, 0x07, 0x4f, 0xf1, 0x7d, 0x07, 0x4f, 0xf1, 0x81, 0x07, 0x4f, 0xf1, + 0x9d, 0x07, 0x4f, 0xf1, 0xad, 0x07, 0x4f, 0xf1, 0xb1, 0x07, 0x4f, 0xf1, + 0xb1, 0x07, 0x4f, 0xf1, 0x49, 0x01, 0x8f, 0xf1, 0xa1, 0x01, 0x8f, 0xf1, + 0xdd, 0x01, 0x8f, 0xf1, 0x7d, 0x02, 0x8f, 0xf1, 0x79, 0x03, 0x8f, 0xf1, + 0x05, 0x04, 0x8f, 0xf1, 0xc9, 0x03, 0x00, 0x03, 0xc9, 0x06, 0x8f, 0xf1, + 0x61, 0x07, 0x8f, 0xf1, 0xf9, 0x07, 0x8f, 0xf1, 0xd5, 0x00, 0xcf, 0xf1, + 0x99, 0x02, 0xcf, 0xf1, 0xa1, 0x02, 0xcf, 0xf1, 0xbd, 0x03, 0xcf, 0xf1, + 0x29, 0x04, 0xcf, 0xf1, 0x89, 0x04, 0xcf, 0xf1, 0xa9, 0x05, 0x00, 0x03, + 0xcd, 0x05, 0xcf, 0xf1, 0x6d, 0x06, 0xcf, 0xf1, 0x15, 0x07, 0xcf, 0xf1, + 0xb1, 0x07, 0xcf, 0xf1, 0x01, 0x02, 0x0f, 0xf2, 0x05, 0x02, 0x0f, 0xf2, + 0x4d, 0x02, 0x0f, 0xf2, 0xd9, 0x02, 0x0f, 0xf2, 0x3d, 0x03, 0x0f, 0xf2, + 0x89, 0x03, 0x0f, 0xf2, 0xf9, 0x03, 0x0f, 0xf2, 0x19, 0x04, 0x0f, 0xf2, + 0x85, 0x06, 0x00, 0x03, 0xc5, 0x07, 0x00, 0x03, 0x39, 0x00, 0x40, 0x03, + 0x91, 0x01, 0x40, 0x03, 0xb5, 0x02, 0x40, 0x03, 0xa9, 0x03, 0x40, 0x03, + 0x85, 0x04, 0x40, 0x03, 0x41, 0x02, 0x80, 0x03, 0x41, 0x02, 0x80, 0x03, + 0x71, 0x02, 0x80, 0x03, 0x39, 0x03, 0x80, 0x03, 0xad, 0x03, 0x80, 0x03, + 0xfd, 0x03, 0x80, 0x03, 0x09, 0x06, 0x8f, 0xf2, 0x21, 0x06, 0x8f, 0xf2, + 0xfd, 0x07, 0xcf, 0xf2, 0xd1, 0x06, 0x80, 0x03, 0x4d, 0x01, 0x0f, 0xf3, + 0x71, 0x01, 0x0f, 0xf3, 0x81, 0x01, 0x0f, 0xf3, 0xb5, 0x01, 0x0f, 0xf3, + 0xb9, 0x01, 0x0f, 0xf3, 0xc5, 0x01, 0x0f, 0xf3, 0x11, 0x02, 0x0f, 0xf3, + 0xbd, 0x07, 0x80, 0x03, 0xe9, 0x07, 0x80, 0x03, 0x9d, 0x00, 0xc0, 0x03, + 0xd5, 0x01, 0xc0, 0x03, 0x55, 0x02, 0xc0, 0x03, 0xc5, 0x02, 0xc0, 0x03, + 0xe5, 0x02, 0xc0, 0x03, 0x09, 0x03, 0xc0, 0x03, 0x31, 0x03, 0xc0, 0x03, + 0x51, 0x05, 0xc0, 0x03, 0x85, 0x06, 0xc0, 0x03, 0x39, 0x01, 0x00, 0x04, + 0x01, 0x02, 0x00, 0x04, 0x79, 0x02, 0x00, 0x04, 0x79, 0x03, 0x00, 0x04, + 0x79, 0x03, 0x00, 0x04, 0x15, 0x06, 0x00, 0x04, 0xdd, 0x04, 0x8f, 0xf3, + 0x59, 0x05, 0x8f, 0xf3, 0x09, 0x06, 0x8f, 0xf3, 0x6d, 0x06, 0x8f, 0xf3, + 0x7d, 0x06, 0x8f, 0xf3, 0xfd, 0x06, 0x8f, 0xf3, 0x11, 0x07, 0x8f, 0xf3, + 0x85, 0x07, 0x8f, 0xf3, 0x55, 0x04, 0x40, 0x04, 0x31, 0x05, 0x40, 0x04, + 0x7d, 0x07, 0x40, 0x04, 0x41, 0x01, 0x80, 0x04, 0xdd, 0x01, 0x80, 0x04, + 0x2d, 0x03, 0x80, 0x04, 0x91, 0x03, 0x80, 0x04, 0xf1, 0x06, 0x80, 0x04, + 0xb1, 0x03, 0xc0, 0x04, 0x5d, 0x04, 0xc0, 0x04, 0x99, 0x05, 0xc0, 0x04, + 0x31, 0x01, 0x4f, 0xf4, 0x69, 0x01, 0x4f, 0xf4, 0x15, 0x03, 0x4f, 0xf4, + 0xe9, 0x04, 0x4f, 0xf4, 0x49, 0x05, 0x4f, 0xf4, 0x85, 0x06, 0x4f, 0xf4, + 0x49, 0x07, 0x4f, 0xf4, 0x81, 0x00, 0x8f, 0xf4, 0x85, 0x00, 0x8f, 0xf4, + 0x1d, 0x01, 0x8f, 0xf4, 0x39, 0x01, 0x8f, 0xf4, 0x31, 0x02, 0x8f, 0xf4, + 0xcd, 0x04, 0x8f, 0xf4, 0x65, 0x05, 0x8f, 0xf4, 0x19, 0x07, 0x8f, 0xf4, + 0x01, 0x01, 0x0f, 0xf5, 0x05, 0x00, 0x00, 0x05, 0xe5, 0x02, 0x0f, 0xf5, + 0x09, 0x03, 0x0f, 0xf5, 0x19, 0x03, 0x0f, 0xf5, 0xcd, 0x03, 0x0f, 0xf5, + 0xd1, 0x03, 0x0f, 0xf5, 0xdd, 0x03, 0x0f, 0xf5, 0xb1, 0x04, 0x0f, 0xf5, + 0xd5, 0x01, 0x00, 0x05, 0x59, 0x02, 0x00, 0x05, 0xf5, 0x02, 0x00, 0x05, + 0x55, 0x03, 0x00, 0x05, 0xb1, 0x04, 0x00, 0x05, 0x1d, 0x05, 0x00, 0x05, + 0x1d, 0x05, 0x00, 0x05, 0x2d, 0x05, 0x00, 0x05, 0xa9, 0x05, 0x00, 0x05, + 0x01, 0x07, 0x00, 0x05, 0xcd, 0x00, 0xcf, 0xf5, 0xe1, 0x00, 0xcf, 0xf5, + 0x31, 0x01, 0xcf, 0xf5, 0xfd, 0x01, 0xcf, 0xf5, 0xed, 0x02, 0xcf, 0xf5, + 0x81, 0x03, 0xcf, 0xf5, 0xe9, 0x03, 0xcf, 0xf5, 0x45, 0x04, 0xcf, 0xf5, + 0x25, 0x05, 0xcf, 0xf5, 0xed, 0x01, 0x0f, 0xf6, 0x09, 0x02, 0x0f, 0xf6, + 0x85, 0x02, 0x0f, 0xf6, 0xc1, 0x02, 0x0f, 0xf6, 0xf9, 0x02, 0x0f, 0xf6, + 0x25, 0x07, 0x4f, 0xf6, 0x7d, 0x07, 0x4f, 0xf6, 0xc1, 0x07, 0x4f, 0xf6, + 0x55, 0x00, 0x8f, 0xf6, 0xc5, 0x01, 0x8f, 0xf6, 0x39, 0x02, 0x8f, 0xf6, + 0x49, 0x02, 0x8f, 0xf6, 0xe9, 0x02, 0x8f, 0xf6, 0xf1, 0x02, 0x8f, 0xf6, + 0xbd, 0x03, 0x8f, 0xf6, 0xc5, 0x05, 0x40, 0x05, 0xc9, 0x06, 0x40, 0x05, + 0xb5, 0x02, 0x80, 0x05, 0x0d, 0x03, 0x80, 0x05, 0x31, 0x03, 0x80, 0x05, + 0x11, 0x05, 0x80, 0x05, 0x5d, 0x06, 0x80, 0x05, 0x41, 0x00, 0xc0, 0x05, + 0xd9, 0x02, 0xcf, 0xf6, 0xa5, 0x03, 0xcf, 0xf6, 0xcd, 0x05, 0xcf, 0xf6, + 0x61, 0x06, 0xcf, 0xf6, 0x71, 0x06, 0xcf, 0xf6, 0x29, 0x07, 0xcf, 0xf6, + 0x31, 0x07, 0xcf, 0xf6, 0x21, 0x00, 0x0f, 0xf7, 0xe1, 0x00, 0x0f, 0xf7, + 0x65, 0x01, 0x0f, 0xf7, 0x21, 0x03, 0x0f, 0xf7, 0x4d, 0x03, 0x0f, 0xf7, + 0xb1, 0x03, 0x0f, 0xf7, 0xc1, 0x03, 0x0f, 0xf7, 0x91, 0x04, 0x0f, 0xf7, + 0xad, 0x04, 0x0f, 0xf7, 0xb1, 0x05, 0x0f, 0xf7, 0x21, 0x06, 0x0f, 0xf7, + 0xfd, 0x07, 0x80, 0x05, 0x91, 0x07, 0x0f, 0xf7, 0xe5, 0x07, 0x0f, 0xf7, + 0x05, 0x00, 0x4f, 0xf7, 0xa1, 0x00, 0x4f, 0xf7, 0xb1, 0x00, 0x4f, 0xf7, + 0x61, 0x01, 0x4f, 0xf7, 0x75, 0x01, 0x4f, 0xf7, 0xa1, 0x01, 0x4f, 0xf7, + 0xc5, 0x01, 0x4f, 0xf7, 0x19, 0x02, 0x4f, 0xf7, 0x89, 0x02, 0x4f, 0xf7, + 0xc1, 0x02, 0x4f, 0xf7, 0xed, 0x00, 0xc0, 0x05, 0xc1, 0x01, 0xc0, 0x05, + 0x7d, 0x04, 0xc0, 0x05, 0x09, 0x05, 0xc0, 0x05, 0x19, 0x05, 0xc0, 0x05, + 0x05, 0x06, 0xc0, 0x05, 0x05, 0x06, 0xc0, 0x05, 0x65, 0x07, 0xc0, 0x05, + 0x65, 0x07, 0xc0, 0x05, 0x7d, 0x07, 0xc0, 0x05, 0x1d, 0x07, 0x8f, 0xf7, + 0x5d, 0x07, 0x8f, 0xf7, 0xdd, 0x00, 0xcf, 0xf7, 0x7d, 0x01, 0xcf, 0xf7, + 0xf1, 0x01, 0x00, 0x06, 0xa5, 0x02, 0x00, 0x06, 0x1d, 0x05, 0xcf, 0xf7, + 0xdd, 0x05, 0xcf, 0xf7, 0x7d, 0x04, 0x00, 0x06, 0x45, 0x07, 0x00, 0x06, + 0x51, 0x00, 0x0f, 0xf8, 0xa1, 0x00, 0x0f, 0xf8, 0x39, 0x01, 0x0f, 0xf8, + 0x11, 0x02, 0x0f, 0xf8, 0x79, 0x02, 0x0f, 0xf8, 0x45, 0x03, 0x0f, 0xf8, + 0x8d, 0x05, 0x0f, 0xf8, 0xe5, 0x05, 0x0f, 0xf8, 0x6d, 0x06, 0x0f, 0xf8, + 0xdd, 0x06, 0x0f, 0xf8, 0xfd, 0x07, 0x00, 0x06, 0x3d, 0x00, 0x4f, 0xf8, + 0x45, 0x00, 0x4f, 0xf8, 0x59, 0x00, 0x4f, 0xf8, 0x41, 0x01, 0x40, 0x06, + 0x51, 0x01, 0x4f, 0xf8, 0x59, 0x03, 0x40, 0x06, 0x55, 0x05, 0x40, 0x06, + 0x01, 0x05, 0x4f, 0xf8, 0x89, 0x00, 0x8f, 0xf8, 0x05, 0x00, 0x80, 0x06, + 0x01, 0x01, 0x8f, 0xf8, 0x61, 0x00, 0x80, 0x06, 0xad, 0x01, 0x8f, 0xf8, + 0x21, 0x02, 0x8f, 0xf8, 0x71, 0x02, 0x8f, 0xf8, 0xc1, 0x02, 0x8f, 0xf8, + 0xdd, 0x02, 0x8f, 0xf8, 0xed, 0x02, 0x8f, 0xf8, 0x35, 0x03, 0x8f, 0xf8, + 0xe1, 0x03, 0x8f, 0xf8, 0xf1, 0x03, 0x8f, 0xf8, 0xf5, 0x03, 0x8f, 0xf8, + 0x21, 0x04, 0x8f, 0xf8, 0x3d, 0x04, 0x8f, 0xf8, 0x05, 0x02, 0x80, 0x06, + 0x79, 0x04, 0x8f, 0xf8, 0xf9, 0x07, 0x00, 0x07, 0xb5, 0x00, 0x40, 0x07, + 0xfd, 0x00, 0x0f, 0xf9, 0xb5, 0x01, 0x0f, 0xf9, 0xd9, 0x00, 0x40, 0x07, + 0x35, 0x06, 0x40, 0x07, 0x71, 0x05, 0x0f, 0xf9, 0x31, 0x06, 0x40, 0x07, + 0xad, 0x07, 0x40, 0x07, 0x19, 0x04, 0x8f, 0xf9, 0xb9, 0x04, 0x8f, 0xf9, + 0xc9, 0x04, 0x8f, 0xf9, 0x81, 0x03, 0xc0, 0x07, 0x09, 0x05, 0x8f, 0xf9, + 0x09, 0x05, 0x8f, 0xf9, 0xad, 0x05, 0x8f, 0xf9, 0xd1, 0x05, 0x8f, 0xf9, + 0xed, 0x06, 0x8f, 0xf9, 0xd5, 0x03, 0xc0, 0x07, 0x55, 0x03, 0xcf, 0xf9, + 0x05, 0x04, 0xc0, 0x07, 0x81, 0x03, 0xcf, 0xf9, 0xed, 0x03, 0xcf, 0xf9, + 0x29, 0x04, 0xcf, 0xf9, 0x39, 0x04, 0xcf, 0xf9, 0xa5, 0x04, 0xc0, 0x07, + 0x69, 0x04, 0xcf, 0xf9, 0xbd, 0x04, 0xc0, 0x07, 0xe9, 0x04, 0xc0, 0x07, + 0xfd, 0x04, 0xcf, 0xf9, 0x19, 0x05, 0xcf, 0xf9, 0x15, 0x05, 0xc0, 0x07, + 0x41, 0x05, 0xcf, 0xf9, 0x29, 0x05, 0xc0, 0x07, 0x65, 0x05, 0xcf, 0xf9, + 0x69, 0x05, 0xc0, 0x07, 0x89, 0x05, 0xcf, 0xf9, 0x9d, 0x05, 0xcf, 0xf9, + 0xc1, 0x05, 0xcf, 0xf9, 0x75, 0x05, 0xc0, 0x07, 0xb9, 0x06, 0xcf, 0xf9, + 0x01, 0x07, 0xcf, 0xf9, 0x19, 0x07, 0xcf, 0xf9, 0x4d, 0x07, 0xcf, 0xf9, + 0x95, 0x07, 0xcf, 0xf9, 0xa9, 0x07, 0xcf, 0xf9, 0x31, 0x06, 0xc0, 0x07, + 0x3d, 0x06, 0x0f, 0xfa, 0x89, 0x07, 0x0f, 0xfa, 0xe1, 0x07, 0x0f, 0xfa, + 0xf9, 0x07, 0x0f, 0xfa, 0x2d, 0x00, 0x4f, 0xfa, 0x2d, 0x00, 0x4f, 0xfa, + 0x55, 0x07, 0xc0, 0x07, 0x6d, 0x07, 0xc0, 0x07, 0xfd, 0x04, 0x8f, 0xfa, + 0x15, 0x05, 0x8f, 0xfa, 0x41, 0x05, 0x8f, 0xfa, 0x35, 0x00, 0x00, 0x08, + 0x4d, 0x00, 0x00, 0x08, 0xd5, 0x05, 0x8f, 0xfa, 0x51, 0x07, 0x8f, 0xfa, + 0x69, 0x07, 0x8f, 0xfa, 0x9d, 0x07, 0x8f, 0xfa, 0x39, 0x02, 0x00, 0x08, + 0x0d, 0x06, 0xcf, 0xfa, 0x25, 0x06, 0xcf, 0xfa, 0x8d, 0x02, 0x00, 0x08, + 0x4d, 0x01, 0x8f, 0xfb, 0x65, 0x01, 0x8f, 0xfb, 0x89, 0x03, 0xcf, 0xfb, + 0x91, 0x03, 0xcf, 0xfb, 0xc5, 0x03, 0xcf, 0xfb, 0x59, 0x06, 0xcf, 0xfb, + 0x71, 0x06, 0xcf, 0xfb, 0xa9, 0x06, 0xcf, 0xfb, 0xc1, 0x06, 0xcf, 0xfb, + 0xfd, 0x06, 0xcf, 0xfb, 0x15, 0x07, 0xcf, 0xfb, 0x49, 0x07, 0xcf, 0xfb, + 0x65, 0x07, 0xcf, 0xfb, 0x05, 0x00, 0x0f, 0xfc, 0x6d, 0x00, 0x0f, 0xfc, + 0x9d, 0x00, 0x0f, 0xfc, 0xed, 0x00, 0x0f, 0xfc, 0xf9, 0x00, 0x0f, 0xfc, + 0x4d, 0x01, 0x0f, 0xfc, 0xb1, 0x01, 0x0f, 0xfc, 0x25, 0x00, 0x40, 0x08, + 0x41, 0x03, 0x0f, 0xfc, 0x45, 0x03, 0x0f, 0xfc, 0x81, 0x03, 0x0f, 0xfc, + 0xcd, 0x03, 0x0f, 0xfc, 0xb5, 0x01, 0x40, 0x08, 0xe9, 0x01, 0x40, 0x08, + 0xc1, 0x03, 0x40, 0x08, 0xb9, 0x06, 0x0f, 0xfc, 0xc9, 0x06, 0x0f, 0xfc, + 0xc1, 0x03, 0x40, 0x08, 0x21, 0x04, 0x40, 0x08, 0x49, 0x07, 0x0f, 0xfc, + 0x59, 0x07, 0x0f, 0xfc, 0x69, 0x01, 0x4f, 0xfc, 0x71, 0x01, 0x4f, 0xfc, + 0x81, 0x01, 0x4f, 0xfc, 0x9d, 0x01, 0x4f, 0xfc, 0x35, 0x04, 0x40, 0x08, + 0xd5, 0x01, 0x4f, 0xfc, 0xd9, 0x01, 0x4f, 0xfc, 0xe9, 0x01, 0x4f, 0xfc, + 0x75, 0x02, 0x4f, 0xfc, 0xf1, 0x02, 0x4f, 0xfc, 0xc9, 0x04, 0x4f, 0xfc, + 0xe1, 0x04, 0x4f, 0xfc, 0x7d, 0x05, 0x4f, 0xfc, 0x25, 0x06, 0x4f, 0xfc, + 0x19, 0x07, 0x4f, 0xfc, 0xdd, 0x00, 0x8f, 0xfc, 0xe5, 0x00, 0x8f, 0xfc, + 0xed, 0x00, 0x8f, 0xfc, 0xf5, 0x00, 0x8f, 0xfc, 0x71, 0x04, 0x40, 0x08, + 0xf5, 0x01, 0x8f, 0xfc, 0x1d, 0x05, 0x40, 0x08, 0xf1, 0x03, 0x8f, 0xfc, + 0x91, 0x04, 0x8f, 0xfc, 0x15, 0x05, 0x8f, 0xfc, 0xb5, 0x07, 0x40, 0x08, + 0x01, 0x07, 0x8f, 0xfc, 0x11, 0x07, 0x8f, 0xfc, 0x21, 0x07, 0x8f, 0xfc, + 0xdd, 0x07, 0x8f, 0xfc, 0xed, 0x02, 0xcf, 0xfc, 0x61, 0x04, 0xcf, 0xfc, + 0x65, 0x04, 0xcf, 0xfc, 0xb5, 0x04, 0xcf, 0xfc, 0xbd, 0x04, 0xcf, 0xfc, + 0xd9, 0x04, 0xcf, 0xfc, 0x15, 0x05, 0xcf, 0xfc, 0x1d, 0x05, 0xcf, 0xfc, + 0x85, 0x06, 0xcf, 0xfc, 0x19, 0x06, 0x80, 0x08, 0x6d, 0x00, 0x0f, 0xfd, + 0x81, 0x00, 0x0f, 0xfd, 0x19, 0x02, 0x0f, 0xfd, 0x31, 0x02, 0x0f, 0xfd, + 0x75, 0x02, 0x0f, 0xfd, 0x8d, 0x02, 0x0f, 0xfd, 0xed, 0x03, 0x0f, 0xfd, + 0x05, 0x04, 0x0f, 0xfd, 0x31, 0x04, 0x0f, 0xfd, 0xa9, 0x05, 0x0f, 0xfd, + 0x55, 0x00, 0x4f, 0xfd, 0x6d, 0x00, 0x4f, 0xfd, 0xe5, 0x00, 0x4f, 0xfd, + 0x95, 0x01, 0x4f, 0xfd, 0x9d, 0x01, 0x4f, 0xfd, 0xb1, 0x01, 0x4f, 0xfd, + 0xc9, 0x01, 0x4f, 0xfd, 0xad, 0x03, 0x4f, 0xfd, 0x49, 0x02, 0x8f, 0xfd, + 0x61, 0x02, 0x8f, 0xfd, 0xed, 0x06, 0x80, 0x08, 0x01, 0x04, 0x8f, 0xfd, + 0x19, 0x04, 0x8f, 0xfd, 0xc9, 0x05, 0x8f, 0xfd, 0xd5, 0x04, 0xcf, 0xfd, + 0xed, 0x04, 0xcf, 0xfd, 0xb5, 0x02, 0x0f, 0xfe, 0x9d, 0x03, 0x8f, 0xfe, + 0xb5, 0x03, 0x8f, 0xfe, 0xd5, 0x06, 0xc0, 0x08, 0xed, 0x06, 0xc0, 0x08, + 0x59, 0x02, 0x0f, 0xff, 0x71, 0x02, 0x0f, 0xff, 0x59, 0x02, 0x8f, 0xff, + 0xb5, 0x02, 0x8f, 0xff, 0x81, 0x03, 0x00, 0x04, 0xf1, 0x06, 0x0f, 0xf6, + 0xf5, 0x01, 0x00, 0x01, 0xfd, 0x00, 0x4f, 0xf6, 0x59, 0x02, 0x00, 0x01, + 0x1d, 0x06, 0xc0, 0x05, 0xdd, 0x05, 0xcf, 0xf8, 0xed, 0x06, 0xcf, 0xf8, + 0x41, 0x02, 0x4f, 0xf9, 0x4d, 0x02, 0x4f, 0xf9, 0xa1, 0x02, 0x80, 0x07, + 0xc1, 0x07, 0x80, 0x00, 0xb5, 0x06, 0x8f, 0xf9, 0xfd, 0x06, 0x8f, 0xf9, + 0x4d, 0x07, 0xcf, 0xfa, 0xf9, 0x04, 0x00, 0x00, 0x39, 0x02, 0x00, 0x01, + 0xc1, 0x02, 0x00, 0x08, 0xa1, 0x01, 0x00, 0x01, 0xed, 0x01, 0x00, 0x01, + 0xb9, 0x01, 0x00, 0x01, 0xdd, 0x02, 0x00, 0x08, 0x79, 0x03, 0x00, 0x08, + 0xa1, 0x00, 0x8f, 0xfb, 0xc9, 0x04, 0x00, 0x08, 0xad, 0x02, 0x8f, 0xfb, + 0xe9, 0x02, 0x0f, 0xfd, 0xf9, 0x02, 0x0f, 0xfd, 0x85, 0x00, 0x80, 0x0a, + 0x05, 0x03, 0x4f, 0xfd, 0x35, 0x01, 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, + 0xfd, 0x03, 0x8f, 0xfd, 0x2d, 0x02, 0xcf, 0xee, 0x65, 0x04, 0x8f, 0xfd, + 0xf5, 0x04, 0x8f, 0xfd, 0xf9, 0x06, 0xcf, 0xfd, 0x99, 0x05, 0x0f, 0xfe, + 0x45, 0x07, 0x4f, 0xfe, 0xfd, 0x01, 0xc0, 0x08, 0x1d, 0x02, 0xc0, 0x08, + 0x09, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0xe2, 0xc2, 0x08, 0x45, + 0x01, 0x80, 0x68, 0x40, 0x84, 0x20, 0x03, 0x0c, 0x19, 0x08, 0x31, 0x04, + 0x48, 0x41, 0x0e, 0x8d, 0x00, 0x15, 0x06, 0x10, 0x21, 0x42, 0x1d, 0x78, + 0x4a, 0x0e, 0x6f, 0xfb, 0x01, 0x43, 0xc2, 0xc6, 0x28, 0x4d, 0x4c, 0x70, + 0x2a, 0x08, 0xe0, 0x00, 0x08, 0x43, 0x00, 0x15, 0x06, 0x10, 0x00, 0x41, + 0x61, 0x40, 0x21, 0x42, 0xfa, 0x0a, 0x2f, 0xf6, 0x01, 0x43, 0xc2, 0xc6, + 0xe2, 0xc2, 0x08, 0x45, 0x01, 0x80, 0x68, 0x40, 0x84, 0x20, 0x03, 0x0c, + 0x19, 0x08, 0x31, 0x04, 0x48, 0x41, 0x0e, 0x8d, 0x00, 0x15, 0x06, 0x10, + 0x21, 0x42, 0x1d, 0x78, 0xee, 0x0d, 0x6f, 0xfb, 0x01, 0x43, 0xc2, 0xc6, + 0x28, 0x4d, 0x4c, 0x70, 0xea, 0x0f, 0xa0, 0x00, 0x08, 0x43, 0x00, 0x15, + 0x06, 0x10, 0x00, 0x41, 0x61, 0x40, 0x21, 0x42, 0xce, 0x0a, 0x2f, 0xf6, + 0x01, 0x43, 0xc2, 0xc6, 0xe2, 0xc2, 0x08, 0x45, 0x01, 0x80, 0x68, 0x40, + 0x84, 0x20, 0x03, 0x0c, 0x19, 0x08, 0x31, 0x04, 0x48, 0x41, 0x0e, 0x8d, + 0x00, 0x15, 0x07, 0x10, 0x21, 0x42, 0x1d, 0x78, 0x1e, 0x0e, 0x6f, 0xfb, + 0x01, 0x43, 0xc2, 0xc6, 0x28, 0x4d, 0x4c, 0x70, 0xaa, 0x0f, 0xa0, 0x00, + 0x08, 0x43, 0x00, 0x15, 0x07, 0x10, 0x00, 0x41, 0x61, 0x40, 0x21, 0x42, + 0xb2, 0x0a, 0xe0, 0x00, 0x01, 0x43, 0xc2, 0xc6, 0xe2, 0xc2, 0x08, 0x45, + 0x01, 0x80, 0x68, 0x40, 0x84, 0x20, 0x03, 0x0c, 0x19, 0x08, 0x31, 0x04, + 0x48, 0x41, 0x0e, 0x8d, 0x00, 0x15, 0x07, 0x10, 0x21, 0x42, 0x1d, 0x78, + 0xa6, 0x0d, 0x6f, 0xfb, 0x01, 0x43, 0xc2, 0xc6, 0x28, 0x4d, 0x4c, 0x70, + 0x6a, 0x0f, 0xa0, 0x00, 0x08, 0x43, 0x00, 0x15, 0x07, 0x10, 0x00, 0x41, + 0x61, 0x40, 0x21, 0x42, 0x8a, 0x0a, 0xe0, 0x00, 0x01, 0x43, 0xc2, 0xc6, + 0xe2, 0xc2, 0x08, 0x45, 0x01, 0x80, 0x68, 0x40, 0x84, 0x20, 0x03, 0x0c, + 0x19, 0x08, 0x31, 0x04, 0x48, 0x41, 0x0e, 0x8d, 0x00, 0x15, 0x06, 0x10, + 0x21, 0x42, 0x1d, 0x78, 0xe2, 0x0a, 0x6f, 0xfb, 0x01, 0x43, 0xc2, 0xc6, + 0x28, 0x4d, 0x4c, 0x71, 0x2a, 0x0f, 0xa0, 0x00, 0x08, 0x43, 0x00, 0x15, + 0x06, 0x10, 0x00, 0x41, 0x61, 0x40, 0x21, 0x42, 0xce, 0x09, 0x2f, 0xf6, + 0x01, 0x43, 0xc2, 0xc6, 0xe2, 0xc2, 0x08, 0x45, 0x01, 0x80, 0x68, 0x40, + 0x84, 0x20, 0x03, 0x0c, 0x19, 0x08, 0x31, 0x04, 0x48, 0x41, 0x0e, 0x8d, + 0x00, 0x15, 0x07, 0x10, 0x21, 0x42, 0x1d, 0x78, 0xbe, 0x0a, 0x6f, 0xfb, + 0x01, 0x43, 0xc2, 0xc6, 0x28, 0x4d, 0x4c, 0x71, 0xea, 0x0e, 0xa0, 0x00, + 0x08, 0x43, 0x00, 0x15, 0x07, 0x10, 0x00, 0x41, 0x61, 0x40, 0x21, 0x42, + 0x22, 0x0a, 0xe0, 0x00, 0x01, 0x43, 0xc2, 0xc6, 0xf1, 0xc0, 0x81, 0x80, + 0x84, 0x24, 0x03, 0x1c, 0x11, 0x0c, 0x31, 0x14, 0x00, 0x10, 0x05, 0x00, + 0x0e, 0x88, 0x1d, 0x78, 0x9e, 0x5a, 0x04, 0xf0, 0x10, 0xe0, 0x8e, 0x5a, + 0xd1, 0xc0, 0xe0, 0x7e, 0xf1, 0xc0, 0x81, 0x80, 0x84, 0x24, 0x03, 0x1c, + 0x11, 0x0c, 0x31, 0x14, 0x00, 0x10, 0x06, 0x00, 0x0e, 0x88, 0x1d, 0x78, + 0xa0, 0x5a, 0x04, 0xf0, 0x10, 0xe0, 0x8f, 0x5a, 0xd1, 0xc0, 0xe0, 0x7e, + 0xf1, 0xc0, 0x81, 0x80, 0x84, 0x24, 0x03, 0x1c, 0x11, 0x0c, 0x31, 0x14, + 0x00, 0x10, 0x06, 0x00, 0x0e, 0x88, 0x1d, 0x78, 0x9f, 0x5a, 0x04, 0xf0, + 0x10, 0xe0, 0x90, 0x5a, 0xd1, 0xc0, 0xe0, 0x7e, 0xf1, 0xc0, 0x81, 0x80, + 0x84, 0x24, 0x03, 0x1c, 0x11, 0x0c, 0x31, 0x14, 0x00, 0x10, 0x06, 0x00, + 0x0e, 0x88, 0x1d, 0x78, 0x9c, 0x5a, 0x04, 0xf0, 0x10, 0xe0, 0x8d, 0x5a, + 0xd1, 0xc0, 0xe0, 0x7e, 0xfc, 0x1c, 0x88, 0xb7, 0xe1, 0xc0, 0xe1, 0xc1, + 0xe1, 0xc2, 0xe1, 0xc3, 0xfc, 0x1c, 0x08, 0xb1, 0xfc, 0x1c, 0x48, 0xb1, + 0xfc, 0x1c, 0x88, 0xb1, 0xfc, 0x1c, 0xc8, 0xb1, 0xfc, 0x1c, 0x08, 0xb2, + 0xfc, 0x1c, 0x48, 0xb2, 0xfc, 0x1c, 0x88, 0xb2, 0xfc, 0x1c, 0xc8, 0xb2, + 0xe1, 0xc4, 0xf1, 0xc0, 0xfc, 0x1c, 0x08, 0xbf, 0x6a, 0x20, 0x80, 0x00, + 0xe1, 0xc0, 0x6a, 0x20, 0xc0, 0x00, 0xe1, 0xc0, 0xc3, 0x40, 0xf0, 0x00, + 0x2d, 0x00, 0x00, 0x88, 0xc1, 0xb8, 0xf0, 0x26, 0x01, 0x70, 0xa0, 0x00, + 0x08, 0x87, 0x03, 0xe9, 0x40, 0x79, 0xc1, 0xc0, 0x6b, 0x20, 0xc0, 0x00, + 0xc1, 0xc0, 0x6b, 0x20, 0x80, 0x00, 0xc1, 0xc0, 0x0a, 0x24, 0x00, 0x70, + 0xd1, 0xc0, 0xc1, 0xc4, 0x04, 0x14, 0x0b, 0x34, 0x04, 0x14, 0x0a, 0x34, + 0x04, 0x14, 0x09, 0x34, 0x04, 0x14, 0x08, 0x34, 0x04, 0x14, 0x07, 0x34, + 0x04, 0x14, 0x06, 0x34, 0x04, 0x14, 0x05, 0x34, 0x04, 0x14, 0x04, 0x34, + 0xc1, 0xc3, 0xc1, 0xc2, 0xc1, 0xc1, 0xc1, 0xc0, 0x04, 0x14, 0x1e, 0x34, + 0x6f, 0x24, 0x3f, 0x00, 0xe4, 0xc2, 0x2f, 0x27, 0xbf, 0x03, 0x6f, 0x23, + 0x3f, 0x00, 0xcb, 0x45, 0xa0, 0x00, 0xa2, 0x42, 0x20, 0x8d, 0x06, 0x21, + 0x00, 0x00, 0x82, 0x0b, 0xaf, 0xee, 0x00, 0xad, 0x20, 0x8d, 0x14, 0x70, + 0xc3, 0x40, 0xf0, 0x00, 0x34, 0x00, 0x05, 0xf2, 0x7b, 0x00, 0x20, 0x00, + 0x33, 0xa8, 0xa0, 0xb9, 0x33, 0xa8, 0x20, 0xad, 0x00, 0x16, 0x80, 0x70, + 0xa0, 0x00, 0xa1, 0x42, 0x14, 0x70, 0x33, 0xf2, 0x00, 0x16, 0xc0, 0x70, + 0xa0, 0x00, 0xb0, 0x42, 0xcb, 0x44, 0xa0, 0x00, 0xa0, 0x42, 0x14, 0x70, + 0xc3, 0x43, 0xf0, 0x00, 0x40, 0x02, 0x26, 0x00, 0x2b, 0x00, 0x40, 0x8c, + 0x6d, 0x71, 0xe5, 0xb8, 0x00, 0x2b, 0x80, 0x10, 0x2f, 0x27, 0xbf, 0x00, + 0x6f, 0x23, 0x3f, 0x00, 0x12, 0xf4, 0x25, 0x83, 0x06, 0x79, 0x25, 0xa3, + 0x2f, 0x26, 0xbf, 0x00, 0x11, 0xf0, 0x2f, 0x27, 0x7f, 0x00, 0x6f, 0x23, + 0x3f, 0x00, 0x07, 0x83, 0x0f, 0x20, 0x80, 0x00, 0x07, 0xa3, 0x2f, 0x26, + 0x7f, 0x00, 0x0b, 0xf0, 0x25, 0x83, 0x25, 0x78, 0x05, 0xa3, 0x2f, 0x26, + 0xbf, 0x00, 0x00, 0x8c, 0x00, 0x2b, 0x00, 0x10, 0x06, 0xa3, 0x2f, 0x26, + 0xbf, 0x03, 0xc4, 0xc6, 0xe6, 0xc1, 0xa3, 0xc1, 0x2f, 0x27, 0x3f, 0x02, + 0x6f, 0x23, 0x3f, 0x00, 0x6f, 0x26, 0x3f, 0x04, 0x37, 0x88, 0x6d, 0x70, + 0x34, 0x70, 0x0c, 0xf2, 0x35, 0x88, 0x83, 0xe9, 0x36, 0x88, 0x44, 0x80, + 0x05, 0xb9, 0x42, 0x21, 0x01, 0x08, 0x3a, 0x62, 0x68, 0x8a, 0x74, 0x70, + 0x8e, 0x00, 0x21, 0x00, 0x80, 0xc4, 0xe7, 0x82, 0xc6, 0x82, 0xff, 0xd9, + 0x5a, 0xdd, 0x18, 0x1a, 0x80, 0x0f, 0x12, 0x00, 0x24, 0xf1, 0x87, 0xa2, + 0x40, 0xc6, 0x41, 0xc7, 0x4f, 0x00, 0x20, 0x00, 0x42, 0xc1, 0xab, 0x25, + 0x08, 0x1e, 0x00, 0x16, 0x81, 0x70, 0xf0, 0x00, 0x35, 0x00, 0xc5, 0xb9, + 0x34, 0x72, 0x10, 0xf4, 0x6f, 0x27, 0x3f, 0x00, 0x6f, 0x23, 0x3f, 0x00, + 0xaa, 0x21, 0x5a, 0x00, 0x4b, 0x21, 0x80, 0x83, 0x0b, 0xf2, 0x2f, 0x21, + 0xbf, 0x0f, 0x00, 0x00, 0x77, 0x00, 0x0b, 0xf0, 0x2f, 0x21, 0xbf, 0x0f, + 0x00, 0x00, 0xb7, 0x00, 0x05, 0xf0, 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, + 0xb7, 0x00, 0x6f, 0x26, 0x3f, 0x04, 0x68, 0x8a, 0x02, 0xc1, 0x08, 0xeb, + 0x8c, 0x21, 0xc3, 0x8f, 0x04, 0xf4, 0x77, 0x88, 0x74, 0x70, 0xd7, 0xf5, + 0x8c, 0x21, 0xc3, 0x8f, 0x6d, 0x71, 0x09, 0xf4, 0x27, 0x82, 0x0f, 0x09, + 0x01, 0x03, 0x01, 0xc1, 0x27, 0xa2, 0x00, 0xc1, 0x26, 0xa2, 0x2f, 0x26, + 0x3f, 0x02, 0x61, 0x40, 0xc6, 0xc5, 0xe0, 0x78, 0x14, 0x70, 0x7c, 0x00, + 0x21, 0x00, 0x00, 0x43, 0x2f, 0x27, 0x3f, 0x03, 0x6f, 0x23, 0x3f, 0x00, + 0x6f, 0x26, 0x3f, 0x04, 0x22, 0xf0, 0x29, 0xf4, 0x00, 0x16, 0x80, 0x70, + 0xf0, 0x00, 0x35, 0x00, 0xc5, 0xb8, 0x14, 0x72, 0x0f, 0xf4, 0x6f, 0x27, + 0x3f, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0xaa, 0x20, 0x5a, 0x00, 0x4b, 0x20, + 0x80, 0x83, 0x0c, 0xf2, 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, 0x77, 0x00, + 0x0a, 0xf0, 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, 0xb7, 0x00, 0x06, 0xf0, + 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, 0xb7, 0x00, 0x6f, 0x26, 0x3f, 0x04, + 0x4c, 0x8b, 0x00, 0x81, 0x54, 0x70, 0xba, 0x07, 0xe2, 0xff, 0x8c, 0x20, + 0xc3, 0x8f, 0x2f, 0x26, 0x3f, 0x03, 0x8c, 0x20, 0xc3, 0x8f, 0x00, 0x41, + 0xca, 0x21, 0xe1, 0x08, 0x54, 0x70, 0xe0, 0x7f, 0xca, 0x20, 0x41, 0x00, + 0xe0, 0x7f, 0x23, 0xd8, 0xe8, 0xc3, 0xa3, 0xc1, 0x2f, 0x27, 0x3f, 0x04, + 0x6f, 0x23, 0x3f, 0x00, 0x6f, 0x26, 0x3f, 0x04, 0x2d, 0x90, 0xad, 0x70, + 0x34, 0x70, 0x0c, 0xf2, 0x2b, 0x90, 0x83, 0xe9, 0x2c, 0x90, 0x24, 0x77, + 0x42, 0x80, 0x5a, 0x21, 0x01, 0x05, 0x3a, 0x62, 0x2c, 0x8a, 0x34, 0x70, + 0x94, 0x00, 0x21, 0x00, 0x80, 0xc3, 0xc4, 0x82, 0xa2, 0x82, 0xff, 0xdc, + 0x08, 0x1a, 0x80, 0x0f, 0x13, 0x00, 0xcc, 0x4d, 0x64, 0xa2, 0x40, 0xc5, + 0x41, 0xc6, 0x51, 0x00, 0x20, 0x00, 0x42, 0xc4, 0xab, 0x21, 0x08, 0x0e, + 0x00, 0x16, 0x81, 0x70, 0xf0, 0x00, 0x35, 0x00, 0xc5, 0xb9, 0x34, 0x72, + 0x0f, 0xf4, 0x6f, 0x27, 0x3f, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0xaa, 0x21, + 0x5a, 0x00, 0x4b, 0x21, 0x80, 0x83, 0x0c, 0xf2, 0x2f, 0x21, 0xbf, 0x0f, + 0x00, 0x00, 0x77, 0x00, 0x0a, 0xf0, 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, + 0xb7, 0x00, 0x06, 0xf0, 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, 0xb7, 0x00, + 0x6f, 0x26, 0x3f, 0x04, 0x2c, 0x8a, 0x02, 0xc4, 0x09, 0xe9, 0x8c, 0x24, + 0xc3, 0x9f, 0x07, 0xf4, 0x2d, 0x90, 0x34, 0x70, 0xac, 0x07, 0xe2, 0xff, + 0x5a, 0xd9, 0x8c, 0x24, 0xc3, 0x9f, 0xad, 0x71, 0x0a, 0xf4, 0x04, 0x82, + 0x11, 0x08, 0xc1, 0x00, 0x01, 0xc0, 0x04, 0xa2, 0x00, 0xc0, 0x02, 0xa2, + 0x91, 0xd8, 0x67, 0x58, 0x2f, 0x26, 0x3f, 0x04, 0xa1, 0x40, 0xc8, 0xc7, + 0x00, 0x16, 0x80, 0x70, 0xf0, 0x00, 0x35, 0x00, 0xc5, 0xb8, 0x14, 0x72, + 0x0f, 0xf4, 0x6f, 0x27, 0x3f, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0xaa, 0x20, + 0x5a, 0x00, 0x4b, 0x20, 0x80, 0x83, 0x0c, 0xf2, 0x2f, 0x21, 0xbf, 0x0f, + 0x00, 0x00, 0x77, 0x00, 0xe0, 0x7e, 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, + 0xb7, 0x00, 0xe0, 0x7e, 0x2f, 0x21, 0xbf, 0x0f, 0x00, 0x00, 0xb7, 0x00, + 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0x02, 0x88, 0x15, 0x08, 0xbf, 0x01, + 0xf6, 0xd8, 0x02, 0x89, 0x0b, 0x08, 0xff, 0x01, 0x0c, 0x70, 0xd1, 0xc0, + 0xe0, 0x7e, 0xf0, 0xd8, 0x92, 0x09, 0xaf, 0xf4, 0x2c, 0x71, 0xe0, 0x78, + 0xe4, 0xc2, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x45, 0xae, 0x0d, 0x6f, 0xf9, 0x08, 0x46, 0x4c, 0x70, + 0x6c, 0x70, 0xc1, 0x40, 0x4e, 0x0f, 0xa0, 0x08, 0xa1, 0x41, 0xc4, 0xc6, + 0xe4, 0xc2, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x45, 0x8a, 0x0d, 0x6f, 0xf9, 0x08, 0x46, 0x4c, 0x71, + 0x6c, 0x70, 0xc1, 0x40, 0x2a, 0x0f, 0xa0, 0x08, 0xa1, 0x41, 0xc4, 0xc6, + 0xe4, 0xc2, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x45, 0x66, 0x0d, 0x6f, 0xf9, 0x08, 0x46, 0x4c, 0x72, + 0x6c, 0x70, 0xc1, 0x40, 0x06, 0x0f, 0xa0, 0x08, 0xa1, 0x41, 0xc4, 0xc6, + 0xe2, 0xc2, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x0d, 0x6f, 0xf9, 0x08, 0x45, 0x4c, 0x73, 0x6c, 0x76, + 0xe6, 0x0e, 0xa0, 0x08, 0xa1, 0x40, 0xc2, 0xc6, 0xe4, 0xc2, 0xc3, 0x42, + 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x28, 0x45, + 0x22, 0x0d, 0x6f, 0xf9, 0x08, 0x46, 0x4c, 0x74, 0x6c, 0x70, 0xc1, 0x40, + 0xc2, 0x0e, 0xa0, 0x08, 0xa1, 0x41, 0xc4, 0xc6, 0xe4, 0xc2, 0xc3, 0x42, + 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x28, 0x45, + 0xfe, 0x0c, 0x6f, 0xf9, 0x08, 0x46, 0x4c, 0x75, 0x6c, 0x70, 0xc1, 0x40, + 0x9e, 0x0e, 0xa0, 0x08, 0xa1, 0x41, 0xc4, 0xc6, 0xe4, 0xc2, 0xc3, 0x42, + 0x13, 0x00, 0x70, 0x91, 0xc3, 0x43, 0x13, 0x00, 0x74, 0x91, 0x28, 0x45, + 0xda, 0x0c, 0x6f, 0xf9, 0x08, 0x46, 0x4c, 0x76, 0x6c, 0x70, 0xc1, 0x40, + 0x7a, 0x0e, 0xa0, 0x08, 0xa1, 0x41, 0xc4, 0xc6, 0xe4, 0xc2, 0xc3, 0x42, + 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x28, 0x45, + 0xb6, 0x0c, 0x6f, 0xf9, 0x08, 0x46, 0x07, 0xda, 0x6c, 0x70, 0xc1, 0x40, + 0x56, 0x0e, 0xa0, 0x08, 0xa1, 0x41, 0xc4, 0xc6, 0xf1, 0xc0, 0xc3, 0x42, + 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x86, 0x0c, + 0x4f, 0xf9, 0x08, 0xda, 0x3a, 0x0e, 0xa0, 0x08, 0x6c, 0x74, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xe4, 0xc2, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, + 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x28, 0x45, 0x72, 0x0c, 0x6f, 0xf9, + 0x08, 0x46, 0x09, 0xda, 0x6c, 0x70, 0xc1, 0x40, 0x12, 0x0e, 0xa0, 0x08, + 0xa1, 0x41, 0xc4, 0xc6, 0xe2, 0xc2, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, + 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x0c, 0x6f, 0xf9, 0x08, 0x45, + 0x0a, 0xda, 0x6c, 0x76, 0xf2, 0x0d, 0xa0, 0x08, 0xa1, 0x40, 0xc2, 0xc6, + 0xe2, 0xc3, 0xa1, 0xc1, 0x3a, 0x0c, 0xef, 0xfa, 0x08, 0x45, 0x40, 0xc0, + 0x40, 0x24, 0x05, 0x30, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x76, 0x72, 0x0b, 0xef, 0xfa, 0xa1, 0x40, + 0x40, 0x24, 0x04, 0x30, 0x0b, 0xda, 0x6c, 0x76, 0xae, 0x0d, 0xa0, 0x08, + 0xa1, 0x40, 0x00, 0xc0, 0xc2, 0xc7, 0xe0, 0x78, 0xe4, 0xc2, 0xad, 0x70, + 0xcb, 0x46, 0x13, 0x00, 0xd4, 0x91, 0x00, 0x86, 0x21, 0x86, 0x02, 0x79, + 0x0b, 0x09, 0x72, 0x01, 0x22, 0xb9, 0x9a, 0x0b, 0xcf, 0xfa, 0xa5, 0x71, + 0xef, 0x0d, 0x34, 0x94, 0x08, 0xe6, 0xc3, 0x42, 0x13, 0x00, 0x74, 0x91, + 0xc3, 0x43, 0x13, 0x00, 0x78, 0x91, 0xca, 0x0b, 0x4f, 0xf9, 0x0c, 0xda, + 0x7e, 0x0d, 0xa0, 0x08, 0x6c, 0x74, 0xc4, 0xc6, 0xf1, 0xc0, 0xc3, 0x42, + 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0xae, 0x0b, + 0x4f, 0xf9, 0x0d, 0xda, 0x62, 0x0d, 0xa0, 0x08, 0x6c, 0x74, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, + 0xc3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x0b, 0x4f, 0xf9, 0x0e, 0xda, + 0x42, 0x0d, 0xa0, 0x08, 0x6c, 0x74, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, + 0xf1, 0xc0, 0xc3, 0x42, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x43, 0x00, 0x00, + 0x00, 0x00, 0x6e, 0x0b, 0x4f, 0xf9, 0x0f, 0xda, 0x22, 0x0d, 0xa0, 0x08, + 0x6c, 0x74, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0xe0, 0x7f, 0x0c, 0x70, + 0xe8, 0xc2, 0x08, 0x45, 0x94, 0xe1, 0x42, 0x01, 0x25, 0x00, 0xed, 0x70, + 0x0e, 0x71, 0xcd, 0x70, 0xe1, 0xad, 0xe0, 0xad, 0xae, 0x09, 0xaf, 0xf5, + 0xcf, 0x78, 0x61, 0x8d, 0x40, 0x8d, 0x2f, 0x21, 0x08, 0x04, 0x08, 0xbb, + 0x14, 0x70, 0xc5, 0x71, 0x65, 0x7a, 0xcf, 0x78, 0xc5, 0x22, 0x42, 0x00, + 0x2f, 0x20, 0x40, 0x20, 0x40, 0xad, 0x28, 0xba, 0xdd, 0x08, 0x74, 0x82, + 0x41, 0xad, 0x09, 0xde, 0x0e, 0x71, 0xe3, 0xad, 0x02, 0x1d, 0xc2, 0x13, + 0x7a, 0x09, 0xaf, 0xf5, 0xcf, 0x78, 0x63, 0x8d, 0x42, 0x8d, 0x2f, 0x21, + 0x08, 0x04, 0x08, 0xbb, 0x14, 0x70, 0xc5, 0x71, 0x65, 0x7a, 0xcf, 0x78, + 0xc5, 0x22, 0x42, 0x00, 0x2f, 0x20, 0x40, 0x20, 0x42, 0xad, 0x28, 0xba, + 0xdd, 0x08, 0xb4, 0x84, 0x43, 0xad, 0xcd, 0x70, 0x0e, 0x71, 0xe5, 0xad, + 0x04, 0x1d, 0xc2, 0x13, 0x6e, 0x08, 0xaf, 0xf5, 0xcf, 0x78, 0x65, 0x8d, + 0x44, 0x8d, 0x2f, 0x21, 0x08, 0x04, 0x08, 0xbb, 0x14, 0x70, 0xc5, 0x71, + 0x65, 0x7a, 0xcf, 0x78, 0xc5, 0x22, 0x42, 0x00, 0x2f, 0x20, 0x40, 0x20, + 0x44, 0xad, 0x28, 0xba, 0xdd, 0x08, 0x74, 0x82, 0x45, 0xad, 0xe7, 0xad, + 0xe6, 0xad, 0x09, 0xdf, 0x4a, 0x26, 0x40, 0x10, 0x3a, 0x08, 0xaf, 0xf5, + 0xef, 0x78, 0x87, 0x8d, 0x46, 0x8d, 0x14, 0x70, 0x40, 0x2c, 0x00, 0x12, + 0xd0, 0x79, 0xe5, 0x71, 0x45, 0x78, 0xef, 0x7b, 0xc5, 0x20, 0x42, 0x00, + 0x3b, 0x7e, 0x06, 0xad, 0x28, 0xb8, 0xe1, 0x0b, 0xb4, 0x84, 0x07, 0xad, + 0xe6, 0x0e, 0x40, 0x00, 0xde, 0x0e, 0x60, 0x00, 0x08, 0xad, 0xb6, 0x0e, + 0x60, 0x00, 0x09, 0xad, 0x92, 0x0e, 0x60, 0x00, 0x0a, 0xad, 0x5e, 0x09, + 0xaf, 0xf5, 0x0b, 0xad, 0xda, 0x09, 0xaf, 0xf5, 0x0c, 0xad, 0x8a, 0x09, + 0xaf, 0xf5, 0x0d, 0xad, 0x0e, 0xad, 0xc3, 0x41, 0xf0, 0x00, 0x00, 0x01, + 0x0d, 0x89, 0x14, 0xdf, 0xc2, 0xb8, 0x0f, 0xad, 0x09, 0x89, 0xc6, 0xb8, + 0x10, 0xad, 0x05, 0x91, 0xc6, 0xb8, 0x11, 0xad, 0x0c, 0x89, 0xc1, 0xb8, + 0x12, 0xad, 0x13, 0x8d, 0x2c, 0x89, 0x00, 0x16, 0x02, 0x70, 0xf0, 0x00, + 0x90, 0x01, 0x6c, 0x20, 0x43, 0x00, 0x24, 0xb9, 0x5b, 0x78, 0x44, 0x21, + 0x42, 0x00, 0x44, 0x20, 0x81, 0x00, 0x05, 0x23, 0x80, 0x00, 0x25, 0x78, + 0x13, 0xad, 0xe1, 0x40, 0xc8, 0xc6, 0xe0, 0x78, 0xe8, 0xc2, 0xf0, 0x26, + 0x4d, 0x70, 0xa0, 0x00, 0xf4, 0x4d, 0x48, 0x47, 0x08, 0x46, 0xb5, 0x70, + 0x66, 0xf2, 0x2f, 0x27, 0x3f, 0x04, 0x6f, 0x23, 0x3f, 0x00, 0x01, 0x85, + 0x00, 0xae, 0x60, 0x85, 0x42, 0x85, 0x28, 0xb8, 0x01, 0xae, 0x20, 0x40, + 0x62, 0xae, 0x6a, 0x08, 0x6f, 0xf8, 0x43, 0xae, 0x82, 0x8e, 0x04, 0xae, + 0x55, 0x27, 0x80, 0x1f, 0x22, 0xb8, 0xc5, 0xb8, 0x40, 0x25, 0x03, 0x15, + 0x98, 0x4e, 0x4c, 0x70, 0x09, 0x24, 0x0b, 0x10, 0x1f, 0xf0, 0x60, 0x83, + 0x20, 0xeb, 0xd4, 0x8b, 0x80, 0x89, 0x44, 0x71, 0xc3, 0xbe, 0x6c, 0x24, + 0xc0, 0x10, 0xc5, 0x78, 0x00, 0xa9, 0x88, 0x8b, 0x84, 0x20, 0xc2, 0x03, + 0x04, 0xbc, 0x84, 0x24, 0x01, 0x1c, 0x85, 0x78, 0x00, 0xa9, 0x15, 0x8b, + 0xc5, 0x7c, 0x07, 0xb8, 0x85, 0x78, 0x00, 0xa9, 0x0c, 0x93, 0x96, 0x8b, + 0x02, 0xa9, 0x28, 0xb8, 0x81, 0xa9, 0x03, 0xa9, 0x24, 0x74, 0x4f, 0x78, + 0xc3, 0x08, 0xc4, 0x82, 0x0c, 0xe5, 0x20, 0xf0, 0xa0, 0x85, 0x21, 0xed, + 0x94, 0x8d, 0x60, 0x89, 0x44, 0x71, 0xc3, 0xbc, 0x6c, 0x23, 0xc0, 0x00, + 0x85, 0x78, 0x00, 0xa9, 0x68, 0x8d, 0x84, 0x20, 0xc2, 0x03, 0x04, 0xbb, + 0x84, 0x23, 0x01, 0x0c, 0x65, 0x78, 0x00, 0xa9, 0x15, 0x8d, 0x85, 0x7b, + 0x07, 0xb8, 0x65, 0x78, 0x00, 0xa9, 0x0c, 0x95, 0x76, 0x8d, 0x02, 0xa9, + 0x28, 0xb8, 0x61, 0xa9, 0x03, 0xa9, 0x24, 0x74, 0x4f, 0x78, 0xc5, 0x08, + 0xc4, 0x82, 0x2f, 0x26, 0x3f, 0x04, 0x08, 0xd9, 0x15, 0x79, 0x03, 0xf0, + 0x2c, 0x70, 0x30, 0x78, 0xc8, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0xcb, 0x44, + 0xa0, 0x00, 0x24, 0x87, 0x80, 0x84, 0x60, 0x7c, 0x48, 0x45, 0xcd, 0x70, + 0x09, 0xe8, 0x00, 0x8d, 0xcd, 0x71, 0x07, 0xe8, 0x3d, 0x58, 0x24, 0x88, + 0x05, 0x88, 0x21, 0xad, 0x02, 0xad, 0xc1, 0x40, 0xc4, 0xc6, 0xe0, 0x78, + 0xea, 0xc2, 0x08, 0x45, 0x7c, 0xb8, 0x70, 0x41, 0x48, 0x46, 0x1d, 0x08, + 0xf5, 0x00, 0x30, 0x40, 0x55, 0x25, 0x40, 0x1e, 0x0f, 0x79, 0xc1, 0x40, + 0x02, 0x42, 0xb7, 0xff, 0x00, 0x19, 0x04, 0x20, 0x0c, 0x71, 0xca, 0xc6, + 0x0f, 0x0d, 0x74, 0x18, 0x1e, 0x4e, 0x2c, 0x70, 0x9a, 0x09, 0xef, 0xfc, + 0x4c, 0x75, 0xcb, 0x47, 0xa0, 0x00, 0x18, 0x87, 0x82, 0x87, 0xa1, 0x40, + 0x02, 0x41, 0xc1, 0x42, 0x60, 0x7c, 0x22, 0x43, 0x07, 0xe8, 0x71, 0x0d, + 0xf0, 0x10, 0x0c, 0x71, 0x31, 0x0d, 0x10, 0x11, 0xe9, 0xf1, 0x25, 0x0d, + 0x32, 0x14, 0x0c, 0x70, 0x87, 0x0d, 0x30, 0x14, 0x02, 0x41, 0xf9, 0xe5, + 0x44, 0xf2, 0xfe, 0xe5, 0xdf, 0xf5, 0x20, 0x8f, 0x03, 0xae, 0x02, 0xae, + 0x01, 0xae, 0x0c, 0x74, 0x20, 0xae, 0x3f, 0xf0, 0x41, 0x0d, 0xd0, 0x10, + 0xab, 0x0d, 0x11, 0x91, 0x46, 0x0d, 0x80, 0x07, 0x08, 0x45, 0x02, 0x6e, + 0xc3, 0x41, 0x13, 0x00, 0x61, 0x90, 0xfa, 0x0a, 0xef, 0xee, 0x4c, 0x76, + 0x18, 0x4e, 0xc3, 0x41, 0xa0, 0x00, 0x4c, 0x88, 0xea, 0x0a, 0xef, 0xee, + 0x4c, 0x76, 0x09, 0xed, 0x80, 0x25, 0x04, 0x1f, 0x1e, 0x4e, 0x4c, 0x76, + 0xda, 0x0a, 0xef, 0xee, 0xa1, 0x41, 0x00, 0x11, 0x00, 0x21, 0xb6, 0xf1, + 0x0d, 0x08, 0x35, 0x25, 0x0c, 0x70, 0x00, 0x19, 0x05, 0x20, 0xca, 0xc6, + 0x0e, 0x0f, 0xef, 0xf9, 0x0c, 0x72, 0x41, 0x28, 0x03, 0x06, 0x41, 0x28, + 0x02, 0x04, 0x41, 0x28, 0x01, 0x02, 0x10, 0xae, 0x14, 0xd8, 0x73, 0xae, + 0x52, 0xae, 0x31, 0xae, 0x09, 0xf0, 0x10, 0xd8, 0x96, 0x0a, 0xa0, 0x00, + 0xc1, 0x42, 0x05, 0xf0, 0xc1, 0x40, 0x02, 0x41, 0x2f, 0xff, 0x31, 0x09, + 0x11, 0xa0, 0x98, 0xf1, 0xe8, 0xc2, 0xcb, 0x46, 0xa0, 0x00, 0x18, 0x87, + 0x64, 0x86, 0x48, 0x45, 0x30, 0x40, 0x60, 0x7b, 0x08, 0x47, 0xb6, 0xe8, + 0xfe, 0xe7, 0x0c, 0x70, 0x33, 0xf4, 0x0d, 0x08, 0x10, 0x20, 0x40, 0x8d, + 0x40, 0xae, 0x03, 0xf0, 0x40, 0x8e, 0xcb, 0x45, 0x13, 0x00, 0x67, 0x90, + 0x05, 0xea, 0x8c, 0x22, 0xc3, 0x8f, 0x23, 0xf2, 0x06, 0xf0, 0xf6, 0x0c, + 0x6f, 0xee, 0xa1, 0x40, 0x40, 0x8e, 0x1a, 0xea, 0x21, 0x86, 0x01, 0x69, + 0x01, 0xa6, 0x3e, 0x0b, 0x6f, 0xee, 0x5a, 0x4d, 0x00, 0x8e, 0x25, 0x08, + 0x94, 0x00, 0x3b, 0x58, 0x00, 0x43, 0x20, 0x44, 0x1d, 0x4d, 0xe1, 0x41, + 0x26, 0x0b, 0x6f, 0xee, 0x02, 0x42, 0x00, 0x8e, 0x0d, 0x08, 0xf4, 0x00, + 0x54, 0x25, 0x40, 0x1a, 0x16, 0x0b, 0x4f, 0xee, 0x04, 0x8e, 0x0d, 0x08, + 0x1e, 0x00, 0x86, 0x0c, 0x6f, 0xee, 0x0a, 0xd8, 0x0c, 0x71, 0xc8, 0xc6, + 0xe2, 0xc2, 0x33, 0x0b, 0xb0, 0x00, 0x28, 0x43, 0x45, 0x0b, 0x50, 0x00, + 0x9b, 0x0b, 0x11, 0x00, 0x80, 0x90, 0x59, 0x0c, 0x13, 0x16, 0x61, 0x0c, + 0xd0, 0x11, 0x9f, 0x0c, 0x10, 0x12, 0x8b, 0x0c, 0x91, 0x12, 0x21, 0x90, + 0x04, 0x69, 0xb1, 0x09, 0x34, 0x02, 0x00, 0xa2, 0x53, 0x21, 0x7e, 0x80, + 0x4b, 0xf0, 0x80, 0x90, 0xc3, 0x41, 0xa0, 0x00, 0x5c, 0xe9, 0x4b, 0x0c, + 0xd0, 0x11, 0x4d, 0x0c, 0x10, 0x12, 0x67, 0x0c, 0x91, 0x12, 0xb6, 0x08, + 0x00, 0x00, 0x4b, 0xf0, 0x80, 0x90, 0xcb, 0x45, 0xa0, 0x00, 0x2c, 0x87, + 0x3b, 0x0c, 0x90, 0x16, 0x45, 0x0c, 0x50, 0x16, 0x4b, 0x0c, 0x11, 0x16, + 0x82, 0x85, 0x23, 0xec, 0x40, 0x7c, 0x3d, 0xf0, 0x65, 0x0c, 0x10, 0x16, + 0x09, 0x0c, 0x50, 0x16, 0x37, 0x0c, 0x91, 0x16, 0x21, 0x90, 0x0c, 0x71, + 0x64, 0x69, 0x5d, 0x09, 0x31, 0x01, 0x60, 0xa2, 0xc2, 0xc6, 0xbe, 0x0b, + 0x00, 0x00, 0x2d, 0xf0, 0xfe, 0x0b, 0x00, 0x00, 0x29, 0xf0, 0x20, 0x85, + 0x0b, 0xe9, 0x43, 0x85, 0x25, 0x88, 0x60, 0x7a, 0x04, 0x88, 0x23, 0xf0, + 0x80, 0x85, 0x05, 0xec, 0x60, 0x7c, 0x04, 0x88, 0x1d, 0xf0, 0xcb, 0x44, + 0xa0, 0x00, 0x30, 0x87, 0xa0, 0x84, 0x17, 0xed, 0x60, 0x7d, 0x61, 0x41, + 0xc2, 0xc6, 0x01, 0x90, 0x2c, 0x68, 0x64, 0x68, 0xf8, 0xe1, 0x60, 0xa2, + 0x0a, 0xf7, 0x53, 0x20, 0x7e, 0x80, 0x0c, 0x71, 0xdc, 0xf3, 0x06, 0xf0, + 0x21, 0x90, 0x04, 0x69, 0x00, 0xa2, 0x07, 0xe9, 0x2c, 0x71, 0x81, 0x40, + 0x70, 0x58, 0x0c, 0x70, 0xc2, 0xc6, 0x0c, 0x71, 0xc2, 0xc6, 0xe0, 0x78, + 0xf1, 0xc0, 0x79, 0x20, 0x00, 0x00, 0x04, 0x71, 0x04, 0xa9, 0x0c, 0x71, + 0x64, 0x58, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0xf8, 0xc2, 0x08, 0x46, + 0x04, 0x88, 0x0d, 0x08, 0x1f, 0x00, 0x01, 0x96, 0xa1, 0x08, 0x11, 0x02, + 0x0b, 0x16, 0x94, 0x10, 0xfa, 0x08, 0x6f, 0xfa, 0x0a, 0x16, 0x93, 0x10, + 0x04, 0xe8, 0x2d, 0x10, 0x92, 0x00, 0x03, 0xf0, 0x4e, 0x71, 0xcb, 0x47, + 0xa0, 0x00, 0x80, 0xea, 0xcb, 0x45, 0xa0, 0x00, 0x60, 0xea, 0x0c, 0x70, + 0x03, 0x1f, 0xc2, 0x14, 0x04, 0x1f, 0x02, 0x15, 0x1c, 0xad, 0x18, 0x1d, + 0x45, 0x11, 0x22, 0x96, 0x08, 0x16, 0x90, 0x10, 0x4b, 0x21, 0x00, 0x86, + 0x30, 0x41, 0x13, 0xf2, 0x41, 0x29, 0xcc, 0x20, 0x53, 0x24, 0x41, 0x10, + 0x5d, 0x09, 0xd0, 0x00, 0x6b, 0x09, 0x90, 0x00, 0x7d, 0x09, 0x51, 0x00, + 0x67, 0x0a, 0x5f, 0x20, 0xc3, 0x41, 0xa0, 0x00, 0xec, 0x40, 0x21, 0xd8, + 0x4d, 0xf0, 0x2e, 0x58, 0x10, 0x45, 0x34, 0x58, 0x00, 0x41, 0x02, 0x40, + 0xa2, 0x42, 0x33, 0x58, 0x16, 0xe8, 0xbc, 0x48, 0x18, 0xda, 0x92, 0x08, + 0xef, 0xee, 0xa1, 0x40, 0x01, 0x85, 0xf0, 0xd9, 0x04, 0x79, 0x63, 0x09, + 0x30, 0x04, 0x91, 0xe0, 0xe5, 0x09, 0x31, 0x08, 0xa2, 0xe0, 0xf7, 0xf2, + 0xa1, 0xe0, 0xc6, 0x21, 0x21, 0x26, 0xcf, 0x21, 0xe1, 0x20, 0xf5, 0xf0, + 0x00, 0x96, 0x2c, 0x76, 0x70, 0x58, 0xd8, 0xc6, 0x08, 0x1d, 0x81, 0x14, + 0x04, 0x1d, 0x81, 0x14, 0x00, 0x1d, 0x80, 0x1f, 0xa0, 0x00, 0x74, 0x40, + 0x0d, 0xf0, 0x3f, 0x0a, 0x51, 0x20, 0x08, 0x1d, 0x41, 0x14, 0x04, 0x1d, + 0x41, 0x14, 0x00, 0x1d, 0x80, 0x1f, 0xa0, 0x00, 0x54, 0x40, 0x03, 0xf0, + 0x01, 0xa5, 0x49, 0x8e, 0x2e, 0x8d, 0x00, 0xaf, 0x5b, 0x7a, 0xc0, 0xb9, + 0x1f, 0xad, 0x19, 0x4e, 0x45, 0x79, 0x2e, 0xad, 0x44, 0xf0, 0x0a, 0x02, + 0x21, 0x00, 0x56, 0x71, 0x92, 0xe0, 0x0f, 0x02, 0x20, 0x00, 0xc5, 0x21, + 0x21, 0x26, 0xc3, 0x41, 0xa0, 0x00, 0x08, 0x41, 0x22, 0xd8, 0x55, 0x8d, + 0xc0, 0xdb, 0x2f, 0x24, 0x02, 0x04, 0x09, 0x16, 0x88, 0x10, 0x06, 0x16, + 0x0b, 0x11, 0x44, 0x24, 0x07, 0x11, 0x41, 0x29, 0x0c, 0x23, 0x53, 0x20, + 0x86, 0x20, 0x02, 0xa5, 0x01, 0xa5, 0x20, 0xa5, 0x04, 0x21, 0xc1, 0x20, + 0x44, 0x24, 0x00, 0x02, 0x44, 0x24, 0x09, 0x12, 0x6c, 0x24, 0xcc, 0x00, + 0x26, 0xb9, 0x05, 0x20, 0x80, 0x01, 0x41, 0x29, 0x85, 0x23, 0x05, 0x21, + 0xc1, 0x01, 0x85, 0x78, 0x84, 0x22, 0x02, 0x00, 0x44, 0x25, 0x43, 0x00, + 0x05, 0x21, 0x41, 0x02, 0x45, 0x78, 0x73, 0xad, 0x34, 0xad, 0x15, 0xad, + 0x03, 0x96, 0x10, 0x1d, 0xc4, 0x12, 0x12, 0x1d, 0x02, 0x12, 0x1f, 0xad, + 0x28, 0xb8, 0x00, 0xaf, 0xfa, 0x09, 0x60, 0x00, 0xa1, 0x40, 0x19, 0x4e, + 0x00, 0x88, 0x02, 0xaf, 0x41, 0x29, 0x00, 0x22, 0x44, 0x21, 0x17, 0xa1, + 0xd3, 0x42, 0xa0, 0x00, 0x44, 0x87, 0x1d, 0x1d, 0x42, 0x14, 0x01, 0x1f, + 0x02, 0x14, 0x1e, 0xad, 0x12, 0xf2, 0xc5, 0xb8, 0xd3, 0x46, 0x4c, 0x3d, + 0xcd, 0xcc, 0x11, 0x08, 0x74, 0x01, 0x63, 0xb8, 0x48, 0x30, 0x80, 0x00, + 0x00, 0x30, 0x96, 0x05, 0x27, 0x09, 0x1f, 0x20, 0xd3, 0x40, 0x12, 0x00, + 0x50, 0x4b, 0x08, 0xf0, 0x23, 0x09, 0x3f, 0x20, 0xce, 0x70, 0xd3, 0x40, + 0x12, 0x00, 0x4c, 0x4b, 0x40, 0x23, 0xc0, 0x24, 0x6c, 0x20, 0x40, 0x00, + 0x00, 0x1a, 0x00, 0x24, 0x10, 0xf0, 0xd3, 0x40, 0x12, 0x00, 0x7c, 0x4b, + 0x04, 0xf0, 0xd3, 0x40, 0x12, 0x00, 0x78, 0x4b, 0x9c, 0x4e, 0x05, 0x6f, + 0x62, 0x42, 0x32, 0x0f, 0xaf, 0xee, 0x00, 0x1a, 0x00, 0x24, 0x10, 0xd8, + 0x40, 0x27, 0x55, 0x11, 0xf6, 0x70, 0xd3, 0x47, 0x12, 0x00, 0x38, 0x58, + 0x0d, 0xb5, 0x0f, 0xf2, 0x40, 0x25, 0x05, 0x16, 0xa1, 0x40, 0x82, 0x41, + 0xa2, 0x42, 0x62, 0x43, 0x0a, 0x24, 0xc0, 0x05, 0x23, 0x20, 0x00, 0x04, + 0x0a, 0x26, 0x80, 0x05, 0xd8, 0xc6, 0x15, 0x09, 0x7f, 0x20, 0x40, 0x25, + 0x05, 0x16, 0xa1, 0x40, 0x82, 0x41, 0xa2, 0x42, 0x62, 0x43, 0x2c, 0xf0, + 0x42, 0x23, 0x51, 0x20, 0x2f, 0x26, 0x47, 0xf4, 0x1f, 0xf2, 0x40, 0x25, + 0x18, 0x16, 0x0a, 0x26, 0x40, 0x24, 0x8a, 0x46, 0xcf, 0x79, 0x6c, 0x71, + 0x8c, 0x70, 0xa1, 0x40, 0xa2, 0x42, 0x23, 0x20, 0x00, 0x04, 0x0a, 0x25, + 0x00, 0x06, 0x00, 0x12, 0x10, 0x20, 0xc6, 0x77, 0xa6, 0x71, 0x2f, 0x26, + 0x87, 0xf5, 0xc5, 0x71, 0xf0, 0xf5, 0x42, 0x23, 0x81, 0x20, 0x06, 0x6f, + 0x2f, 0x7a, 0x00, 0x24, 0x54, 0x24, 0x00, 0x22, 0x15, 0x00, 0x2f, 0x21, + 0x07, 0x05, 0x40, 0x25, 0x05, 0x16, 0x6c, 0x71, 0xa1, 0x40, 0xa2, 0x42, + 0x23, 0x20, 0x00, 0x04, 0x0a, 0x24, 0xc0, 0x05, 0xd8, 0xc6, 0x46, 0x21, + 0x11, 0x26, 0x4f, 0x21, 0x11, 0x21, 0x08, 0x95, 0x52, 0x8d, 0x95, 0x8d, + 0x74, 0x8d, 0x13, 0x15, 0x89, 0x10, 0x8a, 0x23, 0x01, 0x10, 0x1f, 0xad, + 0x42, 0xaf, 0x41, 0x28, 0x02, 0x02, 0x9b, 0x78, 0x36, 0x6b, 0x40, 0x2b, + 0xc8, 0x00, 0x04, 0x21, 0x86, 0x2f, 0x00, 0x00, 0x1f, 0x3f, 0xc2, 0xbc, + 0x44, 0x21, 0x51, 0x10, 0x40, 0xaf, 0x6c, 0x20, 0x09, 0x01, 0x44, 0x20, + 0x02, 0x04, 0x04, 0x21, 0xc0, 0x02, 0x44, 0x20, 0x0b, 0x18, 0x45, 0x7c, + 0x05, 0x26, 0xc2, 0x02, 0x0c, 0xbb, 0x84, 0x21, 0x02, 0x00, 0x45, 0x78, + 0x04, 0x23, 0x83, 0x0f, 0x0f, 0x00, 0x00, 0x80, 0x25, 0x78, 0x40, 0x29, + 0x91, 0x23, 0x65, 0x78, 0x05, 0x24, 0x50, 0x12, 0x05, 0x21, 0x11, 0x20, + 0x42, 0xf1, 0x46, 0x21, 0x11, 0x26, 0xcf, 0x21, 0x21, 0x21, 0xcf, 0x21, + 0xe2, 0x20, 0x0e, 0x8d, 0x0e, 0x70, 0x00, 0x1f, 0x02, 0x14, 0x1f, 0x1d, + 0x02, 0x14, 0x1d, 0x78, 0x33, 0xf1, 0xe0, 0x78, 0xc3, 0x41, 0xa0, 0x00, + 0x54, 0x87, 0x40, 0x81, 0x00, 0x43, 0x07, 0xea, 0x40, 0x40, 0x43, 0x82, + 0xfe, 0xea, 0x63, 0xa0, 0x02, 0xf0, 0x60, 0xa1, 0x0c, 0x70, 0xe0, 0x7f, + 0x0c, 0x1b, 0x01, 0x00, 0xc3, 0x40, 0xa0, 0x00, 0x48, 0x87, 0x21, 0x80, + 0xe0, 0x7f, 0x00, 0x80, 0xe4, 0xc2, 0xcb, 0x45, 0xa0, 0x00, 0x48, 0x87, + 0xc4, 0x88, 0x08, 0x8d, 0x39, 0x0e, 0x00, 0x10, 0x17, 0x0e, 0x91, 0x10, + 0xc2, 0x0a, 0x4f, 0xfa, 0x21, 0xa5, 0x00, 0xa5, 0x3b, 0xd8, 0xc3, 0x41, + 0x12, 0x00, 0x84, 0x5b, 0x07, 0xf0, 0x1f, 0x08, 0xb1, 0x00, 0x3b, 0xd8, + 0xc3, 0x41, 0x11, 0x00, 0x64, 0xa6, 0x9a, 0x0e, 0x00, 0x00, 0x0c, 0x71, + 0x6b, 0x20, 0x00, 0x04, 0xe0, 0x78, 0xe0, 0x78, 0xe0, 0x78, 0xc8, 0xad, + 0xc4, 0xc6, 0xe0, 0x78, 0xea, 0xc2, 0x21, 0x90, 0xa4, 0x68, 0xcb, 0x47, + 0xa0, 0x00, 0x48, 0x87, 0x38, 0x60, 0x8a, 0x20, 0x83, 0x28, 0x40, 0x20, + 0x11, 0x01, 0x00, 0x8d, 0x8c, 0x20, 0x03, 0x8c, 0x48, 0x00, 0x25, 0x00, + 0xc1, 0x6d, 0x28, 0x8f, 0xb5, 0x09, 0xb1, 0x00, 0x00, 0x41, 0x80, 0x21, + 0xfc, 0x02, 0xa5, 0x09, 0x75, 0x02, 0x41, 0xda, 0x77, 0x0a, 0x6f, 0x00, + 0x82, 0xda, 0x7f, 0x0a, 0x6f, 0x00, 0x8a, 0x22, 0x04, 0x01, 0x91, 0x0a, + 0x4e, 0x00, 0x24, 0x8e, 0x21, 0xa7, 0x41, 0x8e, 0x63, 0x8e, 0x20, 0x8e, + 0x82, 0x8e, 0x08, 0xba, 0x08, 0xbb, 0x25, 0x7a, 0x05, 0x23, 0x01, 0x03, + 0x10, 0xb9, 0x45, 0x79, 0x20, 0xa7, 0x3c, 0xf0, 0x7d, 0x08, 0x30, 0x00, + 0xa5, 0x72, 0xa3, 0x87, 0x07, 0x00, 0x00, 0x00, 0xa3, 0x85, 0x77, 0x0d, + 0x10, 0x10, 0x20, 0x85, 0x24, 0x89, 0xf9, 0x09, 0x01, 0x80, 0x08, 0x8f, + 0x0b, 0x08, 0x51, 0x00, 0x3b, 0x58, 0x21, 0xa7, 0x00, 0xa7, 0x48, 0x8d, + 0x01, 0x85, 0xfe, 0x0c, 0xaf, 0xee, 0xc1, 0x41, 0x40, 0x85, 0xa8, 0x8d, + 0xb9, 0x12, 0xc0, 0x00, 0x45, 0x08, 0x33, 0x00, 0xdd, 0x65, 0x21, 0x87, + 0x00, 0x87, 0x72, 0x58, 0x1c, 0xf0, 0x40, 0x8e, 0x20, 0x87, 0x61, 0x87, + 0x00, 0x22, 0x42, 0x80, 0x09, 0xf0, 0x21, 0x8e, 0x40, 0x8e, 0x80, 0x87, + 0x08, 0xb9, 0x61, 0x87, 0x45, 0x79, 0x00, 0x24, 0x42, 0x90, 0x41, 0x23, + 0x01, 0x80, 0x21, 0xa7, 0x40, 0xa7, 0x06, 0xf0, 0x00, 0x1e, 0x02, 0x74, + 0xf0, 0x00, 0x48, 0x00, 0x26, 0x0d, 0x2f, 0xfa, 0x2c, 0x70, 0x1d, 0x65, + 0x37, 0x0d, 0x44, 0x94, 0xca, 0xc6, 0xe2, 0xd8, 0x00, 0x1e, 0x02, 0x70, + 0xf0, 0x00, 0x48, 0x00, 0xca, 0xc6, 0xe0, 0x78, 0xf1, 0xc0, 0xa3, 0xc1, + 0xc3, 0x42, 0xa0, 0x00, 0x50, 0x87, 0x40, 0x8a, 0x0a, 0xea, 0x04, 0x88, + 0x41, 0xc1, 0x2c, 0x74, 0x93, 0xb9, 0x40, 0xc1, 0x62, 0xc0, 0x0c, 0x71, + 0x80, 0xc1, 0x64, 0x58, 0xa3, 0xc0, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, + 0xe6, 0xc2, 0x42, 0x23, 0x3c, 0x80, 0x15, 0xf2, 0xcd, 0x70, 0xad, 0x70, + 0xa8, 0x20, 0x40, 0x04, 0x97, 0x6d, 0x5c, 0x64, 0x2f, 0x27, 0xff, 0x02, + 0x6f, 0x23, 0x3f, 0x00, 0xf3, 0x8c, 0x06, 0xef, 0xd3, 0xac, 0x0e, 0x1c, + 0x43, 0x10, 0xd0, 0xa4, 0x2f, 0x26, 0xff, 0x02, 0xa5, 0x71, 0x8a, 0x09, + 0x8f, 0xf9, 0xc6, 0xc6, 0x00, 0x16, 0x1d, 0x70, 0xa0, 0x00, 0x04, 0x47, + 0x09, 0x24, 0x4c, 0x17, 0xf0, 0x26, 0x1d, 0x73, 0xa0, 0x00, 0x20, 0x6c, + 0xab, 0x25, 0x10, 0x30, 0xaa, 0x25, 0x90, 0x30, 0x35, 0x0d, 0xfe, 0x31, + 0x50, 0x25, 0xdd, 0x31, 0xab, 0x25, 0x90, 0x30, 0x67, 0x24, 0x40, 0x33, + 0xfc, 0x1c, 0xc8, 0xb7, 0xaa, 0x25, 0x09, 0x38, 0xa7, 0x25, 0x09, 0x39, + 0xfc, 0x1c, 0x48, 0xb7, 0xaa, 0x25, 0x49, 0x38, 0xa7, 0x25, 0x49, 0x39, + 0xfc, 0x1c, 0x48, 0xb7, 0x0a, 0x27, 0x80, 0x3f, 0x11, 0x00, 0x3c, 0xc8, + 0x6f, 0x24, 0x3f, 0x00, 0xaa, 0x27, 0x90, 0x30, 0x4f, 0x27, 0xdf, 0x31, + 0xab, 0x27, 0x90, 0x30, 0x04, 0x14, 0x1d, 0x34, 0xab, 0x25, 0x49, 0x39, + 0x04, 0x14, 0x1d, 0x34, 0xab, 0x25, 0x09, 0x39, 0x04, 0x14, 0x1f, 0x34, + 0x67, 0x24, 0x40, 0x33, 0xab, 0x27, 0x10, 0x30, 0x6f, 0x24, 0x3f, 0x00, + 0xc3, 0x42, 0xa0, 0x00, 0x60, 0x87, 0x39, 0xa2, 0xe0, 0x7f, 0x18, 0xa2, + 0xf1, 0xc0, 0x26, 0x0a, 0x0f, 0xfd, 0xc3, 0x40, 0xa0, 0x00, 0x08, 0x47, + 0x40, 0x20, 0x02, 0x0a, 0xcc, 0x48, 0x20, 0xe0, 0x00, 0x1a, 0x80, 0x0f, + 0x12, 0x00, 0x7c, 0x5d, 0x00, 0x19, 0x80, 0x0f, 0x12, 0x00, 0x28, 0x5d, + 0x00, 0x18, 0x80, 0x0f, 0x12, 0x00, 0x62, 0x61, 0xd1, 0xc0, 0xe0, 0x7e, + 0x05, 0xeb, 0x15, 0x22, 0xcc, 0x00, 0xfc, 0x1c, 0xc0, 0x90, 0xf9, 0x07, + 0x0f, 0xfe, 0xe0, 0x78, 0x00, 0x42, 0x06, 0xe8, 0x10, 0x8a, 0xe7, 0xb8, + 0x0c, 0x77, 0xe0, 0x7d, 0x05, 0x02, 0xef, 0xfe, 0x40, 0x40, 0xe0, 0x78, + 0xea, 0xc2, 0x00, 0x10, 0x10, 0x00, 0x08, 0x45, 0x58, 0x20, 0x4e, 0x01, + 0x70, 0xb8, 0x70, 0x41, 0xaa, 0x0d, 0xef, 0xfc, 0x28, 0x47, 0xc3, 0x41, + 0x00, 0x80, 0x1e, 0x40, 0x36, 0x71, 0xd5, 0x21, 0x22, 0x08, 0xe4, 0xa6, + 0x04, 0x1d, 0x50, 0x10, 0x18, 0x25, 0x02, 0x14, 0x07, 0xf4, 0x2c, 0x70, + 0x04, 0x1e, 0x01, 0x10, 0xa3, 0xa6, 0x42, 0xa6, 0x0a, 0xf0, 0xc3, 0x41, + 0xa0, 0x00, 0x60, 0x87, 0x98, 0x81, 0x79, 0x81, 0x40, 0x41, 0xa1, 0xa6, + 0x83, 0xa6, 0x62, 0xa6, 0x20, 0xa6, 0xca, 0xc6, 0x0c, 0x70, 0x54, 0x70, + 0xab, 0x20, 0x50, 0x02, 0xe0, 0x7c, 0xc3, 0x40, 0xa0, 0x00, 0xb8, 0x87, + 0xe0, 0x7f, 0x40, 0xa0, 0xee, 0xc2, 0x4e, 0x70, 0xcb, 0x46, 0xa0, 0x00, + 0x60, 0x87, 0x8a, 0x21, 0x90, 0x28, 0x52, 0x40, 0xa4, 0x6e, 0xab, 0x22, + 0x50, 0x22, 0x00, 0x85, 0x40, 0x21, 0x53, 0x20, 0x0c, 0xe8, 0x20, 0x86, + 0xe1, 0x85, 0x80, 0xb9, 0x2b, 0x21, 0x40, 0x04, 0x2a, 0x0f, 0x0f, 0xfe, + 0xe5, 0x78, 0x2b, 0x20, 0xc0, 0x04, 0x06, 0xf0, 0x2b, 0x22, 0x40, 0x24, + 0x2b, 0x22, 0xc0, 0x24, 0x06, 0x71, 0x0c, 0xe6, 0x26, 0x72, 0xd7, 0x08, + 0x34, 0xa2, 0x0c, 0xe5, 0xce, 0xc6, 0xe0, 0x78, 0xee, 0xc2, 0xd9, 0x88, + 0x08, 0x45, 0x30, 0x43, 0xc1, 0xbe, 0xa2, 0x08, 0x6f, 0xfb, 0xa1, 0x40, + 0x4e, 0x70, 0x0e, 0x71, 0x0a, 0xe8, 0x1f, 0x0e, 0xb5, 0x10, 0xa1, 0x40, + 0x35, 0x58, 0x13, 0x0b, 0x25, 0x20, 0x0c, 0x71, 0x2e, 0x70, 0x40, 0xf0, + 0x0c, 0x71, 0x10, 0x41, 0x3c, 0xf0, 0x0d, 0x8d, 0x03, 0xe8, 0xe0, 0x85, + 0x05, 0xf0, 0x0d, 0x1d, 0x43, 0x10, 0xa9, 0x47, 0x02, 0xf0, 0x1c, 0xef, + 0x6a, 0x08, 0x6f, 0xfb, 0xe1, 0x40, 0x11, 0xe8, 0xe1, 0x40, 0x35, 0x58, + 0x1b, 0x08, 0xc1, 0x04, 0x55, 0x87, 0x05, 0xea, 0x39, 0x87, 0x60, 0x7a, + 0xe1, 0x40, 0x19, 0x0f, 0x60, 0x13, 0xe1, 0x40, 0x5e, 0x0b, 0x0f, 0xf9, + 0x06, 0xf0, 0x46, 0x08, 0x6f, 0xfb, 0xe1, 0x40, 0x02, 0xe8, 0x0e, 0x70, + 0xe0, 0x87, 0xe7, 0xf1, 0x16, 0x70, 0x15, 0xf2, 0x46, 0x0b, 0x2f, 0xf9, + 0xa1, 0x40, 0x0b, 0x0e, 0x90, 0x10, 0x0d, 0x1d, 0x03, 0x10, 0x10, 0x8d, + 0x14, 0x70, 0x0b, 0xf2, 0x10, 0x1d, 0x03, 0x10, 0x9e, 0x78, 0x2c, 0x70, + 0x4c, 0x71, 0xa1, 0x40, 0x91, 0x58, 0xbe, 0x78, 0x4e, 0x71, 0x79, 0x20, + 0x10, 0x20, 0x0c, 0x70, 0x83, 0xe8, 0x56, 0x70, 0xb1, 0xf5, 0x14, 0x70, + 0xca, 0x20, 0x42, 0x24, 0x02, 0x40, 0xce, 0xc6, 0x00, 0x1e, 0x00, 0x70, + 0xa0, 0x00, 0xe0, 0x47, 0x6a, 0x20, 0x80, 0x02, 0xae, 0xb8, 0xbf, 0xb8, + 0x29, 0x20, 0x00, 0x80, 0xaa, 0x20, 0xc1, 0x00, 0x51, 0x20, 0xc0, 0x87, + 0xbf, 0xb8, 0xab, 0x20, 0xc1, 0x00, 0xe7, 0x24, 0x62, 0x33, 0xc7, 0x40, + 0xa0, 0x00, 0xe0, 0x47, 0x64, 0x1c, 0x08, 0xb0, 0xaa, 0x20, 0x49, 0x09, + 0x98, 0x1c, 0x00, 0x30, 0xaa, 0x20, 0x09, 0x09, 0x94, 0x1c, 0x00, 0x30, + 0xaa, 0x20, 0x49, 0x08, 0x90, 0x1c, 0x00, 0x30, 0xaa, 0x20, 0x09, 0x08, + 0x8c, 0x1c, 0x00, 0x30, 0x0a, 0x20, 0x00, 0x0f, 0x88, 0x1c, 0x00, 0x30, + 0x6a, 0x20, 0x80, 0x00, 0x84, 0x1c, 0x00, 0x30, 0x6a, 0x20, 0xc0, 0x00, + 0x80, 0x1c, 0x00, 0x30, 0x7c, 0x1c, 0xc0, 0x37, 0x78, 0x1c, 0x80, 0x37, + 0x74, 0x1c, 0x40, 0x37, 0xaa, 0x20, 0x50, 0x00, 0x5c, 0xc0, 0x6c, 0x1c, + 0xc0, 0x36, 0x68, 0x1c, 0x80, 0x36, 0x64, 0x1c, 0x40, 0x36, 0x60, 0x1c, + 0x00, 0x36, 0x5c, 0x1c, 0xc0, 0x35, 0x58, 0x1c, 0x80, 0x35, 0x54, 0x1c, + 0x40, 0x35, 0x50, 0x1c, 0x00, 0x35, 0x4c, 0x1c, 0xc0, 0x34, 0x48, 0x1c, + 0x80, 0x34, 0x44, 0x1c, 0x40, 0x34, 0x40, 0x1c, 0x00, 0x34, 0x4f, 0xc7, + 0x4e, 0xc6, 0x4d, 0xc5, 0x4c, 0xc4, 0x2c, 0x1c, 0xc0, 0x32, 0x28, 0x1c, + 0x80, 0x32, 0x24, 0x1c, 0x40, 0x32, 0x20, 0x1c, 0x00, 0x32, 0x1c, 0x1c, + 0xc0, 0x31, 0x18, 0x1c, 0x80, 0x31, 0x14, 0x1c, 0x40, 0x31, 0x10, 0x1c, + 0x00, 0x31, 0x43, 0xc3, 0x42, 0xc2, 0x41, 0xc1, 0xaa, 0x20, 0x48, 0x00, + 0x42, 0x20, 0x00, 0x84, 0x1e, 0x00, 0x01, 0x00, 0x6a, 0x21, 0x80, 0x08, + 0x44, 0x21, 0xc1, 0x00, 0x6b, 0x21, 0x80, 0x08, 0x22, 0x20, 0x80, 0x0f, + 0x12, 0x00, 0xd0, 0x39, 0x14, 0x70, 0x2a, 0x00, 0x01, 0x00, 0xab, 0x20, + 0x48, 0x00, 0x00, 0x16, 0x0a, 0x70, 0xa0, 0x00, 0xac, 0x46, 0x00, 0x1a, + 0x00, 0x17, 0x22, 0x20, 0x80, 0x0f, 0x12, 0x00, 0xec, 0x2a, 0x00, 0x16, + 0x0a, 0x70, 0xa0, 0x00, 0xac, 0x46, 0x00, 0x12, 0x1c, 0x10, 0x98, 0x14, + 0x1e, 0x30, 0xab, 0x26, 0x49, 0x39, 0x94, 0x14, 0x1e, 0x30, 0xab, 0x26, + 0x09, 0x39, 0x90, 0x14, 0x1e, 0x30, 0xab, 0x26, 0x49, 0x38, 0x8c, 0x14, + 0x1e, 0x30, 0xab, 0x26, 0x09, 0x38, 0x88, 0x14, 0x1e, 0x30, 0x0a, 0x24, + 0x80, 0x77, 0x84, 0x14, 0x1e, 0x30, 0x6b, 0x26, 0x80, 0x30, 0x80, 0x14, + 0x1e, 0x30, 0x6b, 0x26, 0xc0, 0x30, 0x7c, 0x14, 0x1f, 0x30, 0x78, 0x14, + 0x1e, 0x30, 0x74, 0x14, 0x1d, 0x30, 0x6c, 0x14, 0x1b, 0x30, 0x68, 0x14, + 0x1a, 0x30, 0x64, 0x14, 0x19, 0x30, 0x60, 0x14, 0x18, 0x30, 0x5c, 0x14, + 0x17, 0x30, 0x58, 0x14, 0x16, 0x30, 0x54, 0x14, 0x15, 0x30, 0x50, 0x14, + 0x14, 0x30, 0x4c, 0x14, 0x13, 0x30, 0x48, 0x14, 0x12, 0x30, 0x44, 0x14, + 0x11, 0x30, 0x40, 0x14, 0x10, 0x30, 0x0f, 0xc7, 0x0e, 0xc6, 0x0d, 0xc5, + 0x0c, 0xc4, 0x2c, 0x14, 0x0b, 0x30, 0x28, 0x14, 0x0a, 0x30, 0x24, 0x14, + 0x09, 0x30, 0x20, 0x14, 0x08, 0x30, 0x1c, 0x14, 0x07, 0x30, 0x18, 0x14, + 0x06, 0x30, 0x14, 0x14, 0x05, 0x30, 0x10, 0x14, 0x04, 0x30, 0x03, 0xc3, + 0x02, 0xc2, 0x01, 0xc1, 0x1c, 0xc0, 0xab, 0x20, 0x50, 0x00, 0x9c, 0x14, + 0x00, 0x34, 0x6f, 0x23, 0x3f, 0x00, 0x6f, 0x24, 0x3f, 0x00, 0xe0, 0x78, + 0xfc, 0x1c, 0x08, 0xb0, 0xaa, 0x20, 0x48, 0x00, 0x0b, 0x08, 0x10, 0x00, + 0x0c, 0x70, 0xab, 0x20, 0x48, 0x00, 0x10, 0xd8, 0xab, 0x20, 0x48, 0x00, + 0x04, 0x14, 0x00, 0x34, 0xe0, 0x7e, 0xe2, 0x08, 0x00, 0x00, 0x98, 0x14, + 0x1e, 0x30, 0x6b, 0x26, 0x40, 0x33, 0x98, 0x14, 0x1e, 0x30, 0xab, 0x26, + 0x49, 0x39, 0x94, 0x14, 0x1e, 0x30, 0xab, 0x26, 0x09, 0x39, 0x90, 0x14, + 0x1e, 0x30, 0xab, 0x26, 0x49, 0x38, 0x8c, 0x14, 0x1e, 0x30, 0xab, 0x26, + 0x09, 0x38, 0x88, 0x14, 0x1e, 0x30, 0x0a, 0x24, 0x80, 0x77, 0x84, 0x14, + 0x1e, 0x30, 0x6b, 0x26, 0x80, 0x30, 0x80, 0x14, 0x1e, 0x30, 0x6b, 0x26, + 0xc0, 0x30, 0x7c, 0x14, 0x1f, 0x30, 0x78, 0x14, 0x1e, 0x30, 0x74, 0x14, + 0x1d, 0x30, 0x6c, 0x14, 0x1b, 0x30, 0x68, 0x14, 0x1a, 0x30, 0x64, 0x14, + 0x19, 0x30, 0x60, 0x14, 0x18, 0x30, 0x5c, 0x14, 0x17, 0x30, 0x58, 0x14, + 0x16, 0x30, 0x54, 0x14, 0x15, 0x30, 0x50, 0x14, 0x14, 0x30, 0x4c, 0x14, + 0x13, 0x30, 0x48, 0x14, 0x12, 0x30, 0x44, 0x14, 0x11, 0x30, 0x40, 0x14, + 0x10, 0x30, 0x0f, 0xc7, 0x0e, 0xc6, 0x0d, 0xc5, 0x0c, 0xc4, 0x2c, 0x14, + 0x0b, 0x30, 0x28, 0x14, 0x0a, 0x30, 0x24, 0x14, 0x09, 0x30, 0x20, 0x14, + 0x08, 0x30, 0x1c, 0x14, 0x07, 0x30, 0x18, 0x14, 0x06, 0x30, 0x14, 0x14, + 0x05, 0x30, 0x10, 0x14, 0x04, 0x30, 0x03, 0xc3, 0x02, 0xc2, 0x01, 0xc1, + 0x1c, 0xc0, 0xab, 0x20, 0x50, 0x00, 0x9c, 0x14, 0x00, 0x30, 0xab, 0x20, + 0x10, 0x00, 0xa0, 0x14, 0x00, 0x30, 0xab, 0x20, 0x90, 0x00, 0x51, 0x20, + 0xc0, 0x87, 0xa4, 0x14, 0x00, 0x34, 0x6f, 0x23, 0x3f, 0x00, 0x0a, 0x00, + 0x01, 0x00, 0x67, 0x24, 0x40, 0x33, 0x6f, 0x24, 0x3f, 0x00, 0xe0, 0x78, + 0x00, 0x16, 0x0a, 0x70, 0xa0, 0x00, 0xac, 0x46, 0x00, 0x12, 0x1c, 0x10, + 0xc3, 0x40, 0x00, 0x40, 0x00, 0x00, 0xab, 0x20, 0x50, 0x02, 0xe0, 0x7e, + 0xe2, 0xc0, 0xaa, 0x24, 0x0a, 0x14, 0x15, 0x7c, 0x92, 0x49, 0x8a, 0x20, + 0x9f, 0x0f, 0x44, 0x78, 0x41, 0x2a, 0x43, 0x01, 0x35, 0xba, 0x4f, 0x20, + 0x0d, 0x00, 0x04, 0x23, 0x81, 0x0f, 0x00, 0x00, 0xc0, 0xff, 0x53, 0x22, + 0xc0, 0x00, 0x25, 0x78, 0xa0, 0xb4, 0x01, 0xb4, 0xc2, 0xc4, 0xe0, 0x78, + 0xe8, 0xc2, 0xcb, 0x45, 0xa0, 0x00, 0xec, 0x87, 0x48, 0x46, 0x28, 0x47, + 0x10, 0x40, 0xc3, 0x40, 0xa0, 0x00, 0x94, 0x40, 0x2a, 0xda, 0xc6, 0x0e, + 0x6f, 0xee, 0xa1, 0x41, 0xdc, 0x4d, 0xc3, 0x40, 0xa0, 0x00, 0xc0, 0x40, + 0xb6, 0x0e, 0x6f, 0xee, 0x2a, 0xda, 0x02, 0x40, 0xe1, 0x41, 0x1a, 0x0b, + 0xaf, 0xfa, 0xc1, 0x42, 0xc8, 0xc6, 0xe0, 0x78, 0xcb, 0x44, 0xf0, 0x00, + 0x00, 0x01, 0x14, 0x8c, 0x17, 0x08, 0x9f, 0x01, 0x14, 0x8c, 0x13, 0x08, + 0x5f, 0x01, 0x0b, 0x94, 0x0b, 0x08, 0x1f, 0x00, 0x14, 0x8c, 0xe4, 0xb8, + 0xe0, 0x7c, 0x14, 0x8c, 0xc3, 0x41, 0xf0, 0x00, 0x34, 0x00, 0x45, 0xda, + 0x15, 0xa9, 0x76, 0x8c, 0x70, 0xd8, 0x90, 0xb8, 0x76, 0xa9, 0x54, 0xa9, + 0x05, 0xa4, 0x45, 0xd8, 0xc1, 0x07, 0xef, 0xf3, 0x2c, 0x70, 0xe0, 0x78, + 0xc3, 0x40, 0xf0, 0x00, 0x00, 0x01, 0x2d, 0x88, 0x0c, 0x88, 0xc2, 0xb9, + 0x24, 0xb8, 0xc0, 0xb8, 0x47, 0x20, 0xc0, 0x01, 0x09, 0x20, 0x40, 0x00, + 0xe0, 0x7f, 0x04, 0x71, 0xc3, 0x40, 0xf0, 0x00, 0x00, 0x01, 0x2d, 0x88, + 0x0c, 0x88, 0xc2, 0xb9, 0x24, 0xb8, 0xc0, 0xb8, 0x47, 0x20, 0xc0, 0x01, + 0x09, 0x20, 0x41, 0x00, 0x22, 0x78, 0x04, 0x71, 0xe0, 0x7f, 0x0f, 0x78, + 0x6d, 0x02, 0x0f, 0xf5, 0x55, 0x02, 0x0f, 0xf5, 0x79, 0x02, 0x0f, 0xf5, + 0xf1, 0xc0, 0x8a, 0x09, 0x0f, 0xf5, 0x11, 0x08, 0x74, 0x02, 0x42, 0x20, + 0x41, 0x02, 0x09, 0x09, 0x54, 0x02, 0xff, 0xd8, 0xd1, 0xc0, 0xe0, 0x7e, + 0xf1, 0xc0, 0x52, 0x0f, 0xcf, 0xf1, 0x14, 0x70, 0x0c, 0x70, 0x23, 0xf2, + 0xc3, 0x41, 0xa0, 0x00, 0xe8, 0x42, 0x24, 0x89, 0x2b, 0x09, 0xd0, 0x00, + 0x2d, 0x09, 0x50, 0x00, 0x2f, 0x09, 0x90, 0x00, 0x97, 0xe9, 0xc3, 0x40, + 0xa0, 0x00, 0xc4, 0x45, 0x00, 0x88, 0x44, 0x20, 0x00, 0x02, 0x10, 0xb8, + 0x52, 0x20, 0xc0, 0x04, 0x00, 0x20, 0x80, 0x0f, 0x08, 0x00, 0x00, 0x00, + 0x09, 0xf0, 0x0c, 0x70, 0x97, 0xb8, 0x07, 0xf0, 0x0c, 0x70, 0x95, 0xb8, + 0x03, 0xf0, 0x0c, 0x70, 0x96, 0xb8, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, + 0x55, 0x88, 0x74, 0x88, 0x78, 0xd9, 0x44, 0x79, 0x04, 0xba, 0xc3, 0xbb, + 0x84, 0x22, 0x01, 0x0c, 0x87, 0xb9, 0x65, 0x7a, 0x35, 0xa8, 0xe0, 0x7f, + 0x54, 0xa8, 0xe0, 0x78, 0xe2, 0xc0, 0x64, 0x88, 0x05, 0x88, 0x24, 0xbb, + 0x00, 0x29, 0xcc, 0x00, 0x6c, 0x71, 0x41, 0x28, 0xcd, 0x00, 0x41, 0x28, + 0x01, 0x01, 0x06, 0x23, 0x40, 0x03, 0xc2, 0xb9, 0x47, 0x78, 0x38, 0x78, + 0x05, 0x7c, 0x8f, 0x78, 0xc2, 0xc4, 0xe0, 0x78, 0xee, 0xc3, 0xa1, 0xc1, + 0x08, 0x46, 0x14, 0x88, 0x24, 0x86, 0xf5, 0x68, 0x3f, 0x67, 0x28, 0x8f, + 0x03, 0x86, 0x00, 0x1e, 0x00, 0x70, 0xf0, 0x00, 0x2c, 0x01, 0x1c, 0xe9, + 0x40, 0x87, 0x69, 0x8f, 0x01, 0x86, 0x40, 0x27, 0x11, 0x14, 0x03, 0x12, + 0x8b, 0x00, 0x82, 0x8a, 0x44, 0x23, 0x12, 0x82, 0x0a, 0x20, 0x40, 0x24, + 0x03, 0xf4, 0x00, 0x11, 0x10, 0x20, 0x0d, 0x71, 0x29, 0x0b, 0x3f, 0x00, + 0xad, 0x71, 0x1d, 0x0a, 0x30, 0x20, 0x28, 0x45, 0x1d, 0x09, 0x54, 0x01, + 0xad, 0x74, 0x0c, 0xf0, 0x22, 0x86, 0x00, 0x1c, 0x01, 0x30, 0x00, 0xc0, + 0x00, 0xa1, 0xce, 0xc7, 0x09, 0x09, 0x34, 0x04, 0x28, 0x45, 0x10, 0xdd, + 0x21, 0x87, 0x42, 0x86, 0x40, 0xc1, 0x00, 0xc1, 0x11, 0x08, 0x31, 0x20, + 0x20, 0xa2, 0x2c, 0x70, 0x23, 0xa0, 0x22, 0xa0, 0x21, 0xa0, 0x20, 0xa0, + 0x44, 0x23, 0x13, 0x81, 0x04, 0xf2, 0x4a, 0x8f, 0x22, 0x86, 0x4c, 0xa9, + 0x00, 0x28, 0x02, 0x13, 0x2f, 0x27, 0x3f, 0x03, 0x6f, 0x23, 0x3f, 0x00, + 0xc3, 0x41, 0xf0, 0x00, 0x40, 0x02, 0x13, 0x0b, 0x51, 0x10, 0x65, 0x81, + 0x65, 0x7a, 0x45, 0xa1, 0x2f, 0x26, 0x3f, 0x03, 0x06, 0xf0, 0x65, 0x81, + 0x46, 0x7b, 0x65, 0xa1, 0x2f, 0x26, 0x3f, 0x03, 0x0d, 0x08, 0x30, 0x20, + 0x02, 0x41, 0xb2, 0x0c, 0x6f, 0xee, 0xa1, 0x42, 0x11, 0x0b, 0x31, 0x20, + 0x53, 0x25, 0x01, 0x11, 0x42, 0x86, 0x0c, 0x70, 0x90, 0xb8, 0x06, 0xf0, + 0x42, 0x86, 0xc3, 0x40, 0x01, 0x00, 0x00, 0x01, 0x40, 0xc0, 0x60, 0xc1, + 0x00, 0xc0, 0x2b, 0x08, 0x30, 0x20, 0x01, 0xa2, 0x08, 0x8f, 0x23, 0x0d, + 0x05, 0x10, 0x21, 0x0a, 0x10, 0x20, 0x1b, 0x0d, 0x35, 0x11, 0x4e, 0x25, + 0x3c, 0x11, 0xb2, 0x4f, 0xa8, 0x20, 0xc0, 0x01, 0xb8, 0x67, 0x30, 0x88, + 0xb8, 0x62, 0xa5, 0x71, 0x30, 0xa8, 0xce, 0xc7, 0x02, 0x75, 0x00, 0x19, + 0x40, 0x23, 0xce, 0xc7, 0xee, 0xc3, 0xa3, 0xc1, 0x08, 0x46, 0x14, 0x88, + 0x24, 0x86, 0xf5, 0x68, 0x3f, 0x67, 0x28, 0x8f, 0x03, 0x86, 0x00, 0x1e, + 0x00, 0x70, 0xf0, 0x00, 0x2c, 0x01, 0x18, 0xe9, 0x49, 0x8f, 0x01, 0x86, + 0x40, 0x27, 0x11, 0x14, 0x44, 0x22, 0x13, 0x82, 0x50, 0x42, 0x0a, 0x20, + 0x40, 0x24, 0x04, 0xf4, 0x00, 0x11, 0x10, 0x20, 0x29, 0x0a, 0x3f, 0x20, + 0xad, 0x71, 0x1d, 0x0b, 0x30, 0x20, 0x28, 0x45, 0x1d, 0x09, 0x54, 0x01, + 0xad, 0x74, 0x0c, 0xf0, 0x22, 0x86, 0x08, 0x1c, 0x01, 0x30, 0x02, 0xc0, + 0x00, 0xa1, 0xce, 0xc7, 0x09, 0x09, 0x34, 0x04, 0x28, 0x45, 0x10, 0xdd, + 0x0d, 0x08, 0x30, 0x20, 0x02, 0x41, 0xfa, 0x0b, 0x6f, 0xee, 0xa1, 0x42, + 0x17, 0x0a, 0xbf, 0x20, 0x53, 0x25, 0x01, 0x11, 0x0c, 0x70, 0x90, 0xb8, + 0x42, 0x86, 0x41, 0xc0, 0x61, 0xc1, 0x01, 0xc0, 0x08, 0xf0, 0xc3, 0x40, + 0x01, 0x00, 0x00, 0x01, 0x42, 0x86, 0x40, 0xc0, 0x60, 0xc1, 0x00, 0xc0, + 0x2b, 0x08, 0x30, 0x20, 0x01, 0xa2, 0x08, 0x8f, 0x23, 0x0d, 0x05, 0x10, + 0x21, 0x0b, 0x10, 0x20, 0x1b, 0x0d, 0x35, 0x11, 0x4e, 0x25, 0x3c, 0x11, + 0x02, 0x27, 0x42, 0x13, 0xa8, 0x20, 0xc0, 0x01, 0xb8, 0x67, 0x30, 0x88, + 0xb8, 0x62, 0xa5, 0x71, 0x30, 0xa8, 0xce, 0xc7, 0x02, 0x75, 0x00, 0x19, + 0x40, 0x23, 0xce, 0xc7, 0xf0, 0xc2, 0x08, 0x45, 0x14, 0x88, 0x24, 0x85, + 0x10, 0xdf, 0xd5, 0x68, 0x3e, 0x66, 0x09, 0x8e, 0x20, 0x85, 0x0c, 0x16, + 0x11, 0x10, 0x08, 0x16, 0x90, 0x10, 0x44, 0x20, 0x54, 0x80, 0xca, 0x27, + 0x62, 0x10, 0x0f, 0x08, 0xbe, 0x00, 0x10, 0x42, 0x50, 0x22, 0x80, 0x20, + 0x09, 0xae, 0x13, 0x09, 0x30, 0x20, 0x09, 0x27, 0x13, 0x14, 0x22, 0x40, + 0x62, 0x0b, 0x6f, 0xee, 0x62, 0x42, 0x15, 0x0f, 0x25, 0x14, 0x02, 0x20, + 0xc0, 0x24, 0xc3, 0x41, 0x12, 0x00, 0xd0, 0x66, 0x08, 0xae, 0x27, 0xf0, + 0x14, 0x8d, 0x40, 0x86, 0x76, 0x8d, 0x04, 0x71, 0x0f, 0x79, 0x70, 0x71, + 0x22, 0x8a, 0x8d, 0x71, 0x63, 0x8a, 0xca, 0x20, 0x26, 0x00, 0x00, 0x2c, + 0x42, 0x10, 0x14, 0xad, 0x2f, 0x27, 0x3f, 0x03, 0x6f, 0x23, 0x3f, 0x00, + 0xc3, 0x40, 0xf0, 0x00, 0x40, 0x02, 0xc3, 0x41, 0x12, 0x00, 0xd8, 0x66, + 0x11, 0x0b, 0x51, 0x00, 0x65, 0x80, 0x46, 0x7b, 0x65, 0xa0, 0x2f, 0x26, + 0x3f, 0x03, 0x07, 0xf0, 0x65, 0x80, 0x65, 0x7a, 0x45, 0xa0, 0x2f, 0x26, + 0x3f, 0x03, 0x0d, 0x09, 0x30, 0x20, 0x00, 0x21, 0xc0, 0x24, 0x03, 0xa6, + 0x51, 0x22, 0x40, 0xa0, 0x2e, 0x70, 0x1f, 0xf2, 0x3d, 0x27, 0x02, 0x14, + 0x79, 0x24, 0x00, 0x20, 0x05, 0x20, 0xbe, 0x80, 0x17, 0xf2, 0x05, 0x86, + 0x04, 0x30, 0x40, 0x84, 0x26, 0x00, 0x2c, 0x00, 0xa1, 0x42, 0x0a, 0x0c, + 0x8f, 0xfd, 0x14, 0x70, 0x1a, 0x00, 0x2b, 0x00, 0x4a, 0x21, 0xc0, 0x28, + 0x03, 0x85, 0x00, 0x1e, 0x00, 0x70, 0xf0, 0x00, 0x2c, 0x01, 0x1f, 0x0f, + 0x25, 0x14, 0x2e, 0x70, 0x10, 0xf0, 0x0d, 0x0f, 0x25, 0x14, 0xa1, 0x40, + 0x95, 0xff, 0xd0, 0xc6, 0xa1, 0x40, 0x50, 0xff, 0x17, 0x8d, 0x04, 0x77, + 0x17, 0xad, 0x46, 0x86, 0x04, 0xea, 0x27, 0x86, 0x60, 0x7a, 0x22, 0x40, + 0xd0, 0xc6, 0xe0, 0x78, 0x39, 0x06, 0xef, 0xff, 0x20, 0x40, 0xe0, 0x78, + 0xe2, 0xc2, 0x20, 0x40, 0x28, 0x45, 0x47, 0xff, 0x17, 0x8d, 0x04, 0x77, + 0x17, 0xad, 0xc2, 0xc6, 0xf1, 0xc0, 0xc8, 0x44, 0x4a, 0x26, 0xc0, 0x01, + 0xf8, 0x1c, 0xc8, 0xb1, 0xe2, 0x0b, 0x6f, 0xf5, 0x81, 0x47, 0xa2, 0xc0, + 0xd1, 0xc0, 0xe0, 0x7e, 0xf1, 0xc0, 0xc8, 0x44, 0x4a, 0x26, 0xc0, 0x03, + 0xf8, 0x1c, 0xc8, 0xb1, 0xca, 0x0b, 0x6f, 0xf5, 0x81, 0x47, 0xa2, 0xc0, + 0xd1, 0xc0, 0xe0, 0x7e, 0xf1, 0xc0, 0xc8, 0x44, 0x4a, 0x26, 0xc0, 0x01, + 0xf8, 0x1c, 0xc8, 0xb1, 0xe2, 0x0a, 0x6f, 0xf5, 0x81, 0x47, 0xa2, 0xc0, + 0xd1, 0xc0, 0xe0, 0x7e, 0xf2, 0xc3, 0xa1, 0xc1, 0x00, 0x10, 0x15, 0x01, + 0x08, 0x47, 0x0a, 0x21, 0xc0, 0x21, 0x0a, 0x22, 0x80, 0x21, 0x0a, 0x23, + 0x40, 0x21, 0x0a, 0x20, 0x00, 0x21, 0x70, 0x44, 0x2f, 0x27, 0x3f, 0x00, + 0x6f, 0x23, 0x3f, 0x00, 0x0d, 0xc6, 0x16, 0x8e, 0x77, 0x8e, 0x04, 0x77, + 0x1d, 0x0b, 0x03, 0x00, 0x75, 0x8e, 0x04, 0x86, 0xb5, 0x6b, 0x1d, 0x65, + 0x2a, 0xad, 0x19, 0x09, 0xff, 0x20, 0xe0, 0xa5, 0x78, 0x22, 0x03, 0x00, + 0x44, 0xa5, 0x0f, 0xf0, 0x6f, 0x26, 0x3f, 0x00, 0x0c, 0x70, 0xd2, 0xc7, + 0x20, 0xea, 0x49, 0x20, 0x10, 0x21, 0x28, 0x4d, 0x40, 0x41, 0xda, 0x09, + 0x6f, 0xee, 0x02, 0x42, 0x6c, 0x70, 0x0c, 0xc0, 0x08, 0x1d, 0x02, 0x14, + 0x0c, 0x1d, 0x00, 0x15, 0x18, 0x1d, 0xc0, 0x14, 0x1c, 0x1d, 0x80, 0x14, + 0x09, 0x1d, 0x42, 0x14, 0x05, 0xa5, 0x80, 0xc0, 0xe1, 0x41, 0x22, 0x08, + 0x6f, 0xf5, 0xa2, 0x42, 0x00, 0xc0, 0x01, 0xa5, 0xc1, 0x40, 0x04, 0xf8, + 0x0c, 0x71, 0xd2, 0xc7, 0x6f, 0x26, 0x3f, 0x00, 0xdc, 0xf1, 0xe0, 0x78, + 0xe2, 0xc2, 0x08, 0x45, 0x17, 0x88, 0x84, 0xe8, 0xa1, 0x40, 0x0a, 0xff, + 0x7e, 0x09, 0x6f, 0xf5, 0xa1, 0x40, 0x6f, 0x26, 0x3f, 0x00, 0xc2, 0xc6, + 0xf6, 0xc2, 0x30, 0x45, 0x08, 0x45, 0x77, 0x58, 0x78, 0x20, 0x13, 0x00, + 0x8c, 0xd8, 0x1f, 0x23, 0x0f, 0x20, 0xcb, 0x46, 0xa0, 0x00, 0xcc, 0x49, + 0xa1, 0x40, 0x2e, 0x0e, 0xef, 0xf9, 0xdf, 0x67, 0x2f, 0x87, 0x10, 0x47, + 0x30, 0x41, 0x05, 0xe9, 0x62, 0x40, 0x20, 0x58, 0x10, 0x42, 0xeb, 0x85, + 0x2a, 0x85, 0x2f, 0x27, 0xbf, 0x05, 0x6f, 0x23, 0x3f, 0x00, 0x6f, 0x26, + 0x3f, 0x04, 0x62, 0x40, 0xe1, 0x42, 0xde, 0x0c, 0xef, 0xfc, 0x30, 0x40, + 0x8e, 0x71, 0x0d, 0xe8, 0x38, 0x8d, 0x6c, 0x70, 0xa2, 0x42, 0x62, 0x40, + 0x0a, 0x24, 0x00, 0x04, 0xe1, 0x45, 0xa1, 0x46, 0x26, 0x58, 0x83, 0xe8, + 0x8e, 0x70, 0x4c, 0x71, 0xe2, 0x41, 0x62, 0x40, 0x99, 0x58, 0x2f, 0x26, + 0xbf, 0x05, 0x41, 0x09, 0x30, 0x20, 0x62, 0x40, 0x20, 0x58, 0x39, 0x08, + 0x64, 0x04, 0x62, 0x40, 0x9f, 0x20, 0x02, 0x03, 0xc8, 0x4e, 0x1e, 0x66, + 0x1d, 0x0a, 0x64, 0x24, 0x3a, 0x60, 0x21, 0x82, 0x08, 0x86, 0x05, 0x20, + 0x7e, 0x80, 0x0e, 0xf2, 0x07, 0x20, 0x00, 0x04, 0xe7, 0x79, 0x05, 0x20, + 0x7e, 0x80, 0x08, 0xf2, 0x40, 0x23, 0x40, 0x22, 0x20, 0x1e, 0x00, 0x14, + 0xe1, 0xa2, 0x8d, 0x58, 0x82, 0x40, 0xd6, 0xc6, 0xea, 0xc2, 0xf2, 0x69, + 0x50, 0x41, 0x30, 0x40, 0x5c, 0xd9, 0xe1, 0x42, 0x68, 0x46, 0x0a, 0x0f, + 0x2f, 0xfc, 0x08, 0x45, 0x4a, 0x24, 0x00, 0x72, 0xa2, 0xa6, 0xfd, 0x65, + 0x0c, 0x6d, 0x2c, 0x70, 0xc1, 0x42, 0x03, 0xa6, 0xa8, 0x20, 0xc0, 0x02, + 0x01, 0x11, 0x80, 0x24, 0x14, 0x70, 0xca, 0x21, 0x61, 0x00, 0x34, 0x70, + 0xc0, 0x78, 0x01, 0x1a, 0x12, 0x00, 0xc3, 0x40, 0xa0, 0x00, 0x44, 0x88, + 0x20, 0x80, 0x10, 0x1e, 0x00, 0x14, 0xc0, 0xa0, 0x25, 0xa6, 0xca, 0xc6, + 0xea, 0xc2, 0x00, 0x16, 0x03, 0x70, 0xa0, 0x00, 0xcc, 0x87, 0x48, 0x47, + 0x30, 0x40, 0xce, 0x6b, 0xc3, 0x43, 0xa1, 0x00, 0x7c, 0x09, 0x40, 0x23, + 0x0d, 0x06, 0x10, 0x41, 0xc3, 0x42, 0x13, 0x00, 0x44, 0x91, 0xc1, 0x41, + 0xa1, 0x40, 0xe4, 0xff, 0x00, 0x19, 0x80, 0x2f, 0xa0, 0x00, 0x64, 0x88, + 0xc0, 0xa7, 0x00, 0x18, 0x40, 0x23, 0xca, 0xc6, 0xee, 0xc2, 0xc8, 0x47, + 0x0a, 0x21, 0x00, 0x21, 0x70, 0x42, 0x48, 0x45, 0x30, 0x40, 0x1d, 0x0d, + 0x30, 0x00, 0x10, 0x43, 0x0a, 0xef, 0x40, 0x25, 0x0e, 0x06, 0x66, 0xbd, + 0x02, 0x42, 0xa0, 0x43, 0xc1, 0x40, 0xa1, 0x41, 0xd6, 0xff, 0x03, 0xf0, + 0xa8, 0x46, 0x62, 0x40, 0x02, 0x41, 0xa1, 0x42, 0x42, 0x43, 0x0a, 0x24, + 0x40, 0x04, 0xc1, 0x45, 0xee, 0x0e, 0x6f, 0xfe, 0xe1, 0x46, 0xce, 0xc6, + 0xee, 0xc2, 0xc3, 0x40, 0xa0, 0x00, 0x44, 0x88, 0xe0, 0x80, 0x50, 0x42, + 0x30, 0x43, 0x6a, 0x20, 0x80, 0x02, 0xae, 0xb8, 0x29, 0x20, 0x00, 0x80, + 0x2e, 0x70, 0x32, 0xf0, 0x40, 0x20, 0x11, 0x04, 0x63, 0x0b, 0x44, 0x24, + 0x62, 0x87, 0x43, 0x87, 0x60, 0x41, 0x70, 0x40, 0x13, 0x09, 0xa5, 0x00, + 0x28, 0x46, 0x20, 0x86, 0xd3, 0x71, 0x5c, 0x5c, 0x5c, 0x5c, 0x24, 0x6e, + 0xf8, 0xf3, 0x00, 0x22, 0x0d, 0x20, 0x08, 0xda, 0xa1, 0x40, 0xe1, 0x41, + 0xc6, 0x0f, 0x2f, 0xee, 0xc3, 0xa7, 0x02, 0x26, 0x00, 0x14, 0x41, 0x28, + 0x02, 0x04, 0x41, 0x28, 0x01, 0x02, 0x0c, 0xad, 0x4e, 0xad, 0x2d, 0xad, + 0x24, 0x87, 0x38, 0xb8, 0x0f, 0xad, 0x41, 0x29, 0x83, 0x03, 0x41, 0x29, + 0x82, 0x01, 0x12, 0x69, 0x6a, 0xad, 0x49, 0xad, 0x08, 0xad, 0xe5, 0x87, + 0x36, 0xb9, 0x2b, 0xad, 0x2f, 0x20, 0x48, 0x04, 0xce, 0xef, 0x6a, 0x21, + 0x80, 0x02, 0x8e, 0xb9, 0x29, 0x20, 0x40, 0x80, 0xce, 0xc6, 0xe0, 0x78, + 0xea, 0xc2, 0x08, 0x47, 0xcd, 0x70, 0xad, 0x70, 0x37, 0xf0, 0x00, 0x16, + 0x01, 0x70, 0xa0, 0x00, 0x4c, 0x40, 0x5a, 0x25, 0x00, 0x16, 0x1a, 0x61, + 0x00, 0x12, 0x0b, 0x01, 0x59, 0x0b, 0x7e, 0x10, 0x50, 0x40, 0x16, 0x40, + 0x02, 0x20, 0xd1, 0x83, 0x43, 0x26, 0x01, 0x90, 0x07, 0xd8, 0x3c, 0x20, + 0x42, 0x04, 0x7f, 0x21, 0x00, 0x00, 0x34, 0x70, 0xca, 0x20, 0x81, 0x00, + 0x9a, 0xe8, 0x0e, 0x40, 0x40, 0x20, 0x4c, 0x80, 0x41, 0x26, 0x03, 0x90, + 0x00, 0x21, 0x11, 0xa3, 0x01, 0x21, 0xc1, 0x80, 0x7c, 0x21, 0x02, 0x22, + 0x7a, 0x21, 0x00, 0x00, 0x34, 0x70, 0xca, 0x20, 0x81, 0x00, 0xf6, 0xe8, + 0x4f, 0x23, 0x80, 0x10, 0x0d, 0x0b, 0xfe, 0x10, 0x00, 0x18, 0x04, 0x20, + 0x02, 0x40, 0x7e, 0x58, 0x08, 0x18, 0x40, 0x24, 0xa5, 0x71, 0x00, 0x16, + 0xc0, 0x70, 0xa0, 0x00, 0x50, 0x40, 0x8f, 0x0d, 0x02, 0x90, 0xca, 0xc6, + 0xe4, 0xc2, 0xe1, 0xc4, 0xfc, 0x1c, 0xc8, 0xb2, 0xfc, 0x1c, 0x88, 0xb2, + 0xfc, 0x1c, 0x48, 0xb2, 0xfc, 0x1c, 0x08, 0xb2, 0xfc, 0x1c, 0xc8, 0xb1, + 0xfc, 0x1c, 0x88, 0xb1, 0xfc, 0x1c, 0x48, 0xb1, 0xfc, 0x1c, 0x08, 0xb1, + 0xe1, 0xc3, 0xe1, 0xc2, 0xe1, 0xc1, 0xe1, 0xc0, 0xfc, 0x1c, 0x88, 0xb7, + 0x6a, 0x25, 0xc0, 0x10, 0xe1, 0xc5, 0x6a, 0x25, 0x80, 0x10, 0xe1, 0xc5, + 0xfc, 0x1c, 0x08, 0xbf, 0xcb, 0x45, 0xf0, 0x00, 0xa0, 0x01, 0x00, 0x85, + 0xa0, 0xb8, 0x00, 0xa5, 0x04, 0x15, 0x02, 0x10, 0x22, 0x85, 0x02, 0x85, + 0xe0, 0x78, 0xfd, 0x09, 0x01, 0x80, 0xcb, 0x46, 0xa0, 0x00, 0x48, 0x88, + 0x00, 0x8e, 0x59, 0x61, 0x38, 0x60, 0x9a, 0x58, 0x00, 0x1e, 0xc3, 0x11, + 0x00, 0x85, 0x81, 0xb8, 0x00, 0xa5, 0xa1, 0x58, 0x40, 0xd9, 0xc3, 0x40, + 0xf0, 0x00, 0x2c, 0x01, 0x20, 0xa0, 0x02, 0x09, 0x4f, 0xfc, 0x05, 0xe8, + 0x00, 0x85, 0x80, 0xb8, 0x00, 0xa5, 0x09, 0x58, 0xc1, 0xc5, 0x0a, 0x24, + 0x40, 0x73, 0xc1, 0xc5, 0x6b, 0x25, 0x80, 0x10, 0xc1, 0xc5, 0x6b, 0x25, + 0xc0, 0x10, 0x04, 0x14, 0x1e, 0x34, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc2, + 0xc1, 0xc3, 0x04, 0x14, 0x04, 0x34, 0x04, 0x14, 0x05, 0x34, 0x04, 0x14, + 0x06, 0x34, 0x04, 0x14, 0x07, 0x34, 0x04, 0x14, 0x08, 0x34, 0x04, 0x14, + 0x09, 0x34, 0x04, 0x14, 0x0a, 0x34, 0x04, 0x14, 0x0b, 0x34, 0xc1, 0xc4, + 0xc4, 0xc2, 0x6f, 0x24, 0x3f, 0x00, 0xe0, 0x78, 0xee, 0xc2, 0x81, 0x58, + 0x14, 0x70, 0xa0, 0x00, 0x21, 0x00, 0x08, 0x45, 0x2f, 0x27, 0xff, 0x04, + 0x6f, 0x23, 0x3f, 0x00, 0x6f, 0x26, 0x3f, 0x04, 0x00, 0x8d, 0xe1, 0xb8, + 0x42, 0xf4, 0xcb, 0x46, 0xf0, 0x00, 0xa0, 0x01, 0x00, 0x86, 0xa0, 0xb8, + 0x00, 0x1e, 0x00, 0x10, 0x22, 0x86, 0x02, 0x86, 0xe0, 0x78, 0xfd, 0x09, + 0x21, 0x80, 0x30, 0x41, 0x72, 0x08, 0x6f, 0xfc, 0x04, 0x16, 0x12, 0x10, + 0xd3, 0x40, 0xa0, 0x00, 0x48, 0x88, 0xcb, 0x47, 0xf0, 0x00, 0x20, 0x01, + 0x14, 0xe8, 0x02, 0x85, 0x42, 0x20, 0xc0, 0x81, 0xca, 0x20, 0x6e, 0x00, + 0x02, 0xa5, 0x24, 0x87, 0x1f, 0x09, 0xbf, 0x01, 0x42, 0x70, 0x40, 0x21, + 0x80, 0x21, 0x9a, 0x58, 0x00, 0x10, 0x80, 0x20, 0x04, 0x71, 0x00, 0x18, + 0x02, 0x20, 0x06, 0xf0, 0x00, 0x18, 0xc3, 0x21, 0x04, 0xf0, 0x02, 0xa5, + 0xa1, 0x40, 0x7c, 0x58, 0x00, 0x95, 0x81, 0xb8, 0x00, 0xb5, 0x40, 0xd8, + 0x00, 0xa7, 0x06, 0xa7, 0x00, 0x86, 0x81, 0xb8, 0x00, 0xa6, 0x04, 0x87, + 0x0d, 0x08, 0x9f, 0x01, 0xa1, 0x58, 0x00, 0x86, 0x80, 0xb8, 0x00, 0xa6, + 0x2f, 0x26, 0xff, 0x04, 0xce, 0xc6, 0xe0, 0x78, 0x05, 0xe8, 0x00, 0x18, + 0x84, 0x0f, 0x00, 0x00, 0xe6, 0x07, 0x06, 0xe9, 0x00, 0x19, 0x82, 0x0f, + 0x00, 0x00, 0x08, 0x00, 0x05, 0xea, 0x00, 0x1a, 0x82, 0x0f, 0x00, 0x00, + 0x09, 0x00, 0x06, 0xeb, 0x00, 0x1b, 0x82, 0x0f, 0x00, 0x00, 0x0a, 0x00, + 0x0d, 0x0c, 0x10, 0x00, 0x00, 0x1c, 0x82, 0x0f, 0x00, 0x00, 0x30, 0x00, + 0xb4, 0x70, 0xe0, 0x7c, 0x00, 0x1d, 0x82, 0x0f, 0x00, 0x00, 0x26, 0x00, + 0xe0, 0x7e, 0xe0, 0x78, 0xa8, 0x10, 0x00, 0x01, 0x14, 0x70, 0xe0, 0x7f, + 0xca, 0x20, 0x61, 0x00, 0xe2, 0xc2, 0xe6, 0xe1, 0x17, 0xf4, 0x8d, 0x76, + 0x66, 0xdd, 0x93, 0xbc, 0xc3, 0x41, 0xa1, 0x00, 0x7c, 0x27, 0x00, 0x1e, + 0x42, 0x73, 0xf0, 0x00, 0x48, 0x00, 0x80, 0xa1, 0x05, 0x19, 0x83, 0x02, + 0x43, 0xb1, 0x18, 0x88, 0x64, 0xb1, 0x0a, 0x19, 0x04, 0x01, 0x04, 0xa9, + 0x0c, 0x71, 0x64, 0x58, 0xc2, 0xc6, 0xde, 0x0e, 0x8f, 0xfc, 0xc2, 0xc6, + 0xe4, 0xc3, 0xa7, 0xc1, 0x08, 0x46, 0x34, 0x58, 0x08, 0x45, 0x2e, 0x58, + 0x00, 0x42, 0xc1, 0x40, 0xa1, 0x41, 0x33, 0x58, 0x08, 0x45, 0x0f, 0xe8, + 0x2f, 0x85, 0x60, 0x79, 0xa1, 0x40, 0x25, 0x08, 0xb5, 0x00, 0x10, 0xd8, + 0x4e, 0x85, 0x60, 0x7a, 0xa1, 0x41, 0x25, 0x08, 0x30, 0x04, 0x6f, 0xd9, + 0x09, 0xf0, 0x4c, 0x70, 0x80, 0xc0, 0x22, 0xd9, 0x6c, 0x70, 0x40, 0x44, + 0x66, 0xc6, 0x07, 0xf0, 0x66, 0xd9, 0x4c, 0x70, 0x6c, 0x70, 0x40, 0x44, + 0xa1, 0x40, 0x6c, 0x58, 0xc4, 0xc7, 0xe0, 0x78, 0xf1, 0xc0, 0x08, 0xb8, + 0x0a, 0x27, 0x40, 0x01, 0x98, 0xb8, 0x4a, 0x25, 0x00, 0x02, 0x53, 0x58, + 0xd1, 0xc0, 0xe0, 0x7e, 0x0a, 0x27, 0x40, 0x01, 0x8d, 0x06, 0x2f, 0xf5, + 0x4a, 0x25, 0x00, 0x02, 0xf1, 0xc0, 0x00, 0x35, 0x8c, 0x0f, 0x80, 0x42, + 0x00, 0x00, 0x0a, 0x27, 0x80, 0x01, 0x48, 0x34, 0x46, 0x12, 0x08, 0xb8, + 0x2f, 0x24, 0x88, 0x11, 0x0f, 0x0c, 0x34, 0x11, 0x98, 0xb8, 0x00, 0x24, + 0x86, 0x1f, 0x00, 0x00, 0xfc, 0xff, 0xac, 0x72, 0x53, 0x58, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0x00, 0x35, 0x8c, 0x0f, 0x80, 0x42, + 0x00, 0x00, 0x0a, 0x27, 0x80, 0x01, 0x48, 0x34, 0x46, 0x12, 0x08, 0xb8, + 0x2f, 0x24, 0x88, 0x11, 0x0f, 0x0c, 0x34, 0x11, 0x98, 0xb8, 0x00, 0x24, + 0x86, 0x1f, 0x00, 0x00, 0xfc, 0xff, 0x4a, 0x25, 0x80, 0x02, 0x53, 0x58, + 0xd1, 0xc0, 0xe0, 0x7e, 0x0a, 0x27, 0x80, 0x01, 0x0a, 0x26, 0x40, 0x01, + 0x1d, 0x06, 0x2f, 0xf5, 0x4a, 0x25, 0xc0, 0x02, 0xf1, 0xc0, 0x00, 0x35, + 0x8c, 0x0f, 0x80, 0x42, 0x00, 0x00, 0x0a, 0x27, 0x80, 0x01, 0x48, 0x34, + 0x46, 0x12, 0x08, 0xb8, 0x2f, 0x24, 0x88, 0x11, 0x8f, 0xb8, 0x11, 0x0c, + 0x34, 0x11, 0x98, 0xb8, 0x00, 0x24, 0x86, 0x1f, 0x00, 0x00, 0xfc, 0xff, + 0xac, 0x72, 0x53, 0x58, 0xd1, 0xc0, 0xe0, 0x7e, 0xf1, 0xc0, 0xfc, 0x1c, + 0x88, 0xb7, 0x82, 0x08, 0x4f, 0xfa, 0x04, 0x14, 0x1e, 0x34, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0xfc, 0x1c, 0x88, 0xb7, 0x3a, 0x0a, + 0x8f, 0xed, 0x04, 0x14, 0x1e, 0x34, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, + 0xfc, 0x1c, 0x88, 0xb7, 0xe1, 0xc0, 0xe1, 0xc1, 0xe1, 0xc2, 0xe1, 0xc3, + 0xfc, 0x1c, 0x08, 0xb1, 0xfc, 0x1c, 0x48, 0xb1, 0xfc, 0x1c, 0x88, 0xb1, + 0xfc, 0x1c, 0xc8, 0xb1, 0xfc, 0x1c, 0x08, 0xb2, 0xfc, 0x1c, 0x48, 0xb2, + 0xfc, 0x1c, 0x88, 0xb2, 0xfc, 0x1c, 0xc8, 0xb2, 0xe1, 0xc4, 0xf1, 0xc0, + 0xfc, 0x1c, 0x08, 0xbf, 0x6a, 0x20, 0x80, 0x00, 0xe1, 0xc0, 0x6a, 0x20, + 0xc0, 0x00, 0xe1, 0xc0, 0xaa, 0x20, 0x90, 0x02, 0x77, 0xb8, 0x0f, 0x78, + 0x0f, 0x08, 0x50, 0x00, 0x8a, 0xe8, 0xc3, 0x40, 0xa0, 0x00, 0xec, 0x40, + 0x04, 0xf0, 0xc3, 0x40, 0xa0, 0x00, 0x08, 0x41, 0xca, 0x0f, 0x8f, 0xff, + 0xc1, 0xc0, 0x6b, 0x20, 0xc0, 0x00, 0xc1, 0xc0, 0x6b, 0x20, 0x80, 0x00, + 0xc1, 0xc0, 0x0a, 0x24, 0x00, 0x70, 0xd1, 0xc0, 0xc1, 0xc4, 0x04, 0x14, + 0x0b, 0x34, 0x04, 0x14, 0x0a, 0x34, 0x04, 0x14, 0x09, 0x34, 0x04, 0x14, + 0x08, 0x34, 0x04, 0x14, 0x07, 0x34, 0x04, 0x14, 0x06, 0x34, 0x04, 0x14, + 0x05, 0x34, 0x04, 0x14, 0x04, 0x34, 0xc1, 0xc3, 0xc1, 0xc2, 0xc1, 0xc1, + 0xc1, 0xc0, 0x04, 0x14, 0x1e, 0x34, 0x6f, 0x24, 0x3f, 0x00, 0xe0, 0x78, + 0xe8, 0xc2, 0xe1, 0xc4, 0xfc, 0x1c, 0xc8, 0xb2, 0xfc, 0x1c, 0x88, 0xb2, + 0xfc, 0x1c, 0x48, 0xb2, 0xfc, 0x1c, 0x08, 0xb2, 0xfc, 0x1c, 0xc8, 0xb1, + 0xfc, 0x1c, 0x88, 0xb1, 0xfc, 0x1c, 0x48, 0xb1, 0xfc, 0x1c, 0x08, 0xb1, + 0xe1, 0xc3, 0xe1, 0xc2, 0xe1, 0xc1, 0xe1, 0xc0, 0xfc, 0x1c, 0x88, 0xb7, + 0x6a, 0x25, 0xc0, 0x10, 0xe1, 0xc5, 0x6a, 0x25, 0x80, 0x10, 0xe1, 0xc5, + 0xfc, 0x1c, 0x08, 0xbf, 0xaa, 0x20, 0x90, 0x02, 0x42, 0x20, 0xc1, 0x08, + 0x42, 0x20, 0x40, 0x09, 0x2f, 0x7c, 0x4c, 0x73, 0x91, 0x40, 0x11, 0x0c, + 0xb5, 0x11, 0x0f, 0x7b, 0x48, 0x20, 0x82, 0x20, 0x80, 0x22, 0x83, 0x0f, + 0xb3, 0x6a, 0xcd, 0x71, 0xc3, 0x40, 0xa0, 0x00, 0x74, 0x49, 0x84, 0x25, + 0x1f, 0x1e, 0xcb, 0x47, 0xf0, 0x00, 0x20, 0x01, 0x78, 0x7e, 0x1d, 0x65, + 0x2f, 0x27, 0x3f, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0xc9, 0xa7, 0x41, 0x85, + 0x20, 0x85, 0x04, 0x1d, 0x01, 0x10, 0x00, 0x1d, 0x01, 0x10, 0x2f, 0x26, + 0x3f, 0x00, 0x02, 0x40, 0x45, 0x58, 0x0a, 0x87, 0xc4, 0x78, 0xd1, 0x70, + 0xee, 0xf3, 0xc1, 0xc5, 0x0a, 0x24, 0x40, 0x73, 0xc1, 0xc5, 0x6b, 0x25, + 0x80, 0x10, 0xc1, 0xc5, 0x6b, 0x25, 0xc0, 0x10, 0x04, 0x14, 0x1e, 0x34, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc2, 0xc1, 0xc3, 0x04, 0x14, 0x04, 0x34, + 0x04, 0x14, 0x05, 0x34, 0x04, 0x14, 0x06, 0x34, 0x04, 0x14, 0x07, 0x34, + 0x04, 0x14, 0x08, 0x34, 0x04, 0x14, 0x09, 0x34, 0x04, 0x14, 0x0a, 0x34, + 0x04, 0x14, 0x0b, 0x34, 0xc1, 0xc4, 0xc8, 0xc2, 0x6f, 0x24, 0x3f, 0x00, + 0xf0, 0xc2, 0x08, 0x45, 0xc3, 0x43, 0xa0, 0x00, 0xd3, 0x4d, 0xd3, 0x40, + 0xa0, 0x00, 0xa0, 0x4d, 0xc3, 0x40, 0xa0, 0x00, 0xe0, 0x4d, 0x8a, 0x21, + 0x87, 0x0d, 0x76, 0xda, 0x8e, 0x70, 0x00, 0x1b, 0x43, 0x00, 0x17, 0x18, + 0x03, 0x20, 0x0f, 0x18, 0x83, 0x00, 0x08, 0x18, 0x40, 0x20, 0x24, 0x18, + 0x40, 0x20, 0x40, 0xa0, 0x5d, 0x58, 0x1d, 0x08, 0x85, 0x0f, 0x00, 0x00, + 0xf8, 0x13, 0xc3, 0x40, 0xf0, 0x00, 0x34, 0x00, 0x28, 0xd9, 0x4c, 0x70, + 0x34, 0xa8, 0x15, 0x18, 0x03, 0x00, 0x6d, 0xf0, 0x89, 0x25, 0x01, 0x19, + 0x64, 0xd8, 0x88, 0x25, 0x3e, 0x17, 0xa2, 0x78, 0xc8, 0xd9, 0x0f, 0x7e, + 0xd7, 0x49, 0xd1, 0x41, 0xd1, 0x77, 0x0c, 0x72, 0x8a, 0x21, 0x0a, 0x0c, + 0x8a, 0x0f, 0x2f, 0xf9, 0xca, 0x21, 0xc5, 0x23, 0x10, 0x43, 0x5d, 0x58, + 0x08, 0x45, 0x5b, 0x58, 0x10, 0x42, 0x6e, 0x08, 0xaf, 0xf7, 0x16, 0x40, + 0x0c, 0x22, 0x00, 0xa0, 0xc2, 0x25, 0x85, 0x14, 0x1a, 0x25, 0x51, 0x14, + 0x3d, 0x27, 0x8d, 0x13, 0x5f, 0x25, 0x00, 0x17, 0x85, 0x29, 0x03, 0x22, + 0x02, 0x70, 0x02, 0x80, 0x04, 0x21, 0x91, 0x2f, 0xff, 0x01, 0xfc, 0xff, + 0x42, 0x08, 0xaf, 0xf7, 0x20, 0xe0, 0x14, 0x78, 0x20, 0xe0, 0x32, 0x70, + 0xca, 0x21, 0x0d, 0x20, 0xa1, 0x40, 0x3e, 0x0f, 0x2f, 0xf9, 0x22, 0x41, + 0x10, 0x41, 0x3c, 0x27, 0x8f, 0x13, 0x5b, 0x58, 0x08, 0x45, 0x5c, 0x58, + 0x17, 0x08, 0x35, 0x08, 0x08, 0x46, 0x1f, 0xd8, 0xa0, 0xe5, 0x3c, 0x20, + 0x54, 0x03, 0xca, 0x26, 0x25, 0x10, 0xca, 0x25, 0x25, 0x10, 0x5f, 0x27, + 0x00, 0x17, 0x04, 0x21, 0xd1, 0x24, 0x00, 0x20, 0x10, 0x20, 0xfe, 0x0f, + 0x6f, 0xf7, 0x16, 0x40, 0x15, 0x0c, 0x30, 0x20, 0x42, 0x25, 0x01, 0x18, + 0x09, 0x29, 0x01, 0x00, 0x09, 0x2e, 0x02, 0x10, 0x48, 0x49, 0x09, 0xf0, + 0x42, 0x26, 0x01, 0x18, 0x09, 0x29, 0x02, 0x00, 0x09, 0x2d, 0x00, 0x10, + 0x20, 0xe2, 0xdd, 0x65, 0x10, 0x4d, 0x51, 0x48, 0xda, 0x0e, 0x2f, 0xf9, + 0xe1, 0x40, 0x04, 0x21, 0x02, 0x20, 0x40, 0x40, 0xd0, 0xc6, 0xe0, 0x78, + 0x50, 0x20, 0xc1, 0x07, 0x00, 0x42, 0x3f, 0xb8, 0x21, 0x09, 0x84, 0x0f, + 0xb1, 0x42, 0x18, 0x72, 0xcb, 0x44, 0x13, 0x00, 0x4c, 0x91, 0x41, 0x09, + 0x84, 0x0f, 0x80, 0x7f, 0x01, 0x00, 0x81, 0x40, 0x2c, 0x71, 0xd1, 0x04, + 0x20, 0x00, 0x6c, 0x70, 0x41, 0x09, 0x84, 0x0f, 0xb1, 0x3e, 0x19, 0x72, + 0x97, 0x09, 0x85, 0x0f, 0x85, 0x3f, 0x92, 0x15, 0xc3, 0x41, 0x13, 0x00, + 0x5c, 0x91, 0x15, 0x21, 0x03, 0x00, 0x08, 0x13, 0x0b, 0x00, 0x03, 0x49, + 0x52, 0x20, 0x01, 0x00, 0xa7, 0x00, 0x20, 0x00, 0x02, 0x21, 0x0c, 0x00, + 0x41, 0x09, 0x81, 0x0f, 0x80, 0x7f, 0x00, 0x00, 0x14, 0x70, 0xe1, 0x20, + 0xc2, 0x07, 0x0c, 0x70, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x32, 0x80, 0x0f, + 0x49, 0x71, 0xca, 0xf2, 0x7f, 0xdb, 0x17, 0xbb, 0x04, 0x30, 0xc0, 0x80, + 0x14, 0x00, 0x2c, 0x00, 0x8d, 0x70, 0x11, 0x09, 0x85, 0x0f, 0x80, 0x31, + 0x00, 0x00, 0xe0, 0x7f, 0x01, 0x32, 0xc0, 0x00, 0x6d, 0x70, 0x6f, 0x00, + 0x20, 0x00, 0x6c, 0x70, 0x04, 0x32, 0x80, 0x8f, 0xb1, 0x42, 0x80, 0x71, + 0x10, 0x00, 0x0c, 0x00, 0x2c, 0x71, 0x6c, 0x70, 0x91, 0x03, 0x20, 0x00, + 0x0a, 0x20, 0x00, 0x03, 0x04, 0x32, 0x80, 0x8f, 0xcf, 0xc2, 0xb5, 0xf1, + 0x12, 0x00, 0x26, 0x00, 0x2c, 0x71, 0x4a, 0x23, 0x00, 0x00, 0xd9, 0x03, + 0x20, 0x00, 0x0a, 0x20, 0x00, 0x03, 0xf0, 0x26, 0x01, 0x70, 0x13, 0x00, + 0x54, 0x91, 0x00, 0x32, 0x80, 0x0f, 0xb8, 0x3f, 0x3b, 0xaa, 0x01, 0x30, + 0x40, 0x00, 0x48, 0x30, 0xcc, 0x02, 0x48, 0x34, 0x80, 0x10, 0x00, 0x30, + 0x8b, 0x0f, 0x17, 0x37, 0xd1, 0xf7, 0x00, 0x30, 0x83, 0x0f, 0x31, 0x3f, + 0x80, 0x71, 0x02, 0x32, 0xc3, 0x00, 0x02, 0x33, 0xc2, 0x02, 0x00, 0x32, + 0x80, 0x00, 0x00, 0x30, 0x81, 0x0f, 0x31, 0x33, 0x4c, 0xbb, 0x01, 0x31, + 0x81, 0x0f, 0xdd, 0xb5, 0x0e, 0xea, 0x00, 0x30, 0x41, 0x00, 0x01, 0x31, + 0x81, 0x0f, 0x8a, 0x38, 0x55, 0xb3, 0x00, 0x30, 0x41, 0x00, 0x01, 0x31, + 0x81, 0x0f, 0x36, 0xbb, 0x61, 0x0b, 0x00, 0x30, 0x41, 0x00, 0x01, 0x31, + 0x81, 0x0f, 0x2a, 0x3e, 0xab, 0xaa, 0x00, 0x30, 0x40, 0x00, 0x02, 0x32, + 0x00, 0x00, 0x49, 0x0c, 0x30, 0x10, 0x00, 0x32, 0x01, 0x00, 0x02, 0x36, + 0x00, 0x70, 0x00, 0x40, 0x00, 0x00, 0x40, 0x2c, 0xc2, 0x15, 0x07, 0x31, + 0x00, 0x00, 0x8c, 0x24, 0xfe, 0x90, 0x02, 0x33, 0x00, 0x10, 0x02, 0x33, + 0x00, 0x00, 0x01, 0x30, 0x80, 0x0f, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x20, + 0x80, 0x00, 0xe0, 0x20, 0xca, 0x07, 0x00, 0x20, 0x80, 0x0f, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x30, 0x80, 0x0f, 0x80, 0x0d, 0x00, 0x00, 0xe0, 0x7e, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xc0, 0x00, 0x00, 0x07, 0x31, 0x00, 0x00, + 0x02, 0x32, 0x00, 0x00, 0x01, 0x30, 0x80, 0x0f, 0x80, 0x3f, 0x00, 0x00, + 0xe0, 0x7e, 0xe0, 0x78, 0xe4, 0x1c, 0x48, 0xb3, 0x41, 0xc6, 0x42, 0xc7, + 0x0c, 0x1c, 0x00, 0x34, 0x10, 0x1c, 0x40, 0x34, 0x08, 0x45, 0x1b, 0x78, + 0xd3, 0x70, 0x00, 0xff, 0x00, 0x00, 0x10, 0x01, 0x26, 0x00, 0x14, 0x1c, + 0xc0, 0x37, 0x44, 0x35, 0x00, 0x90, 0x40, 0x00, 0x2e, 0x00, 0x86, 0xc1, + 0x4a, 0x0c, 0x20, 0x00, 0xa1, 0x40, 0x00, 0x16, 0x03, 0x70, 0x10, 0x00, + 0x64, 0x0b, 0xbf, 0xda, 0x40, 0x2a, 0x02, 0x06, 0x18, 0x14, 0x11, 0x30, + 0x01, 0x30, 0x81, 0x00, 0x04, 0x30, 0xc0, 0x80, 0x38, 0x00, 0x2c, 0x00, + 0x50, 0x22, 0xc3, 0x07, 0x01, 0x31, 0x81, 0x00, 0x00, 0x30, 0xc0, 0x00, + 0x39, 0x00, 0x20, 0x00, 0x01, 0x30, 0xc0, 0x00, 0x50, 0x25, 0xfe, 0x97, + 0xc3, 0x40, 0x13, 0x00, 0x6c, 0x91, 0x2c, 0x71, 0x6c, 0x70, 0x88, 0x00, + 0x22, 0x00, 0xa1, 0x42, 0x22, 0x0a, 0x00, 0x00, 0x95, 0x00, 0x20, 0x00, + 0x52, 0x20, 0xcd, 0x07, 0x00, 0x31, 0xc0, 0x00, 0x42, 0x21, 0x51, 0x20, + 0x01, 0x30, 0xc0, 0x00, 0x18, 0x1c, 0x40, 0x34, 0x07, 0x31, 0x0f, 0x00, + 0xd3, 0x40, 0xa0, 0x00, 0x54, 0x88, 0x00, 0x37, 0xcd, 0x13, 0x4c, 0x71, + 0x0a, 0x20, 0x40, 0x03, 0x76, 0x0b, 0x20, 0x00, 0x02, 0x41, 0x08, 0x46, + 0x40, 0x20, 0x01, 0x21, 0x4a, 0x22, 0x80, 0x00, 0x66, 0x0b, 0x20, 0x00, + 0x0a, 0x20, 0x40, 0x03, 0x07, 0x36, 0x00, 0x10, 0x00, 0x35, 0x00, 0x10, + 0x00, 0x37, 0x00, 0x10, 0x45, 0x09, 0x30, 0x20, 0x01, 0x37, 0x0d, 0x10, + 0x48, 0x31, 0x81, 0x20, 0x00, 0x16, 0x00, 0x70, 0x10, 0x00, 0x78, 0x0b, + 0x00, 0x31, 0x82, 0x0f, 0x5e, 0xb9, 0x83, 0x80, 0x01, 0x35, 0x82, 0x10, + 0x00, 0x30, 0x40, 0x00, 0x21, 0x00, 0x20, 0x00, 0x01, 0x32, 0x0d, 0x00, + 0x5e, 0x0a, 0x00, 0x00, 0x4e, 0x0b, 0x2f, 0xf6, 0x08, 0x45, 0x00, 0x80, + 0xc3, 0x41, 0x80, 0xff, 0x00, 0x00, 0xa1, 0xe0, 0xca, 0x25, 0x41, 0x10, + 0xa1, 0x40, 0x14, 0x14, 0x1f, 0x30, 0x10, 0x14, 0x11, 0x30, 0x0c, 0x14, + 0x10, 0x30, 0x02, 0xc7, 0x01, 0xc6, 0xe0, 0x7f, 0x1c, 0x14, 0x0d, 0x34, + 0x76, 0x0b, 0x20, 0x00, 0xa1, 0x40, 0xe5, 0x08, 0x30, 0x80, 0x2c, 0x71, + 0xc3, 0x40, 0x13, 0x00, 0x6c, 0x91, 0x6c, 0x70, 0x5e, 0x09, 0x20, 0x00, + 0xa1, 0x42, 0xd1, 0x07, 0xef, 0xff, 0x08, 0x45, 0xd0, 0x1c, 0x48, 0xb3, + 0x41, 0xc6, 0x42, 0xc7, 0x0c, 0x1c, 0xc0, 0x37, 0xe8, 0x46, 0xc8, 0x45, + 0x44, 0xc0, 0x84, 0xc0, 0x4b, 0xc6, 0x4a, 0xc5, 0x24, 0x1c, 0x40, 0x31, + 0x20, 0x1c, 0x00, 0x31, 0x47, 0xc3, 0x46, 0xc2, 0x5a, 0x0b, 0x20, 0x00, + 0x45, 0xc1, 0x06, 0xe8, 0x0b, 0xc6, 0x11, 0x00, 0x20, 0x00, 0x0a, 0xc5, + 0xce, 0x0a, 0x2f, 0xf6, 0x0d, 0xc7, 0xe0, 0xa0, 0xa1, 0x40, 0xc1, 0x41, + 0x0c, 0x14, 0x1f, 0x30, 0x02, 0xc7, 0x01, 0xc6, 0xe0, 0x7f, 0x30, 0x14, + 0x0d, 0x34, 0xe0, 0x78, 0xd4, 0x1c, 0x48, 0xb3, 0x41, 0xc6, 0x08, 0x1c, + 0xc0, 0x37, 0xcb, 0x46, 0xf0, 0x7f, 0x00, 0x00, 0x44, 0xc0, 0x83, 0xc0, + 0x20, 0x1c, 0x40, 0x31, 0x1c, 0x1c, 0x00, 0x31, 0x46, 0xc3, 0x45, 0xc2, + 0x28, 0x1c, 0x80, 0x33, 0x24, 0x1c, 0x01, 0x30, 0x06, 0x0b, 0x20, 0x00, + 0x0c, 0x1c, 0xc1, 0x30, 0x11, 0x08, 0x30, 0x00, 0xad, 0x70, 0x0a, 0xc6, + 0x11, 0x00, 0x20, 0x00, 0x24, 0x14, 0x0d, 0x30, 0x72, 0x0a, 0x0f, 0xf6, + 0x22, 0xd9, 0x20, 0xa0, 0xa1, 0x40, 0xc1, 0x41, 0x08, 0x14, 0x1f, 0x30, + 0x01, 0xc6, 0xe0, 0x7f, 0x2c, 0x14, 0x0d, 0x34, 0xd8, 0x1c, 0x48, 0xb3, + 0x04, 0x1c, 0xc0, 0x37, 0x43, 0xc0, 0x82, 0xc0, 0x1c, 0x1c, 0x40, 0x31, + 0x18, 0x1c, 0x00, 0x31, 0x45, 0xc3, 0x44, 0xc2, 0x24, 0x1c, 0x01, 0x30, + 0x20, 0x1c, 0x01, 0x30, 0xb6, 0x0a, 0x20, 0x00, 0x08, 0x1c, 0x01, 0x31, + 0x11, 0x08, 0x30, 0x00, 0xad, 0x70, 0x09, 0xc1, 0x15, 0x00, 0x20, 0x00, + 0x20, 0x14, 0x0d, 0x30, 0x22, 0x0a, 0x0f, 0xf6, 0x22, 0xd9, 0x20, 0xa0, + 0x4a, 0x21, 0x00, 0x00, 0xa1, 0x40, 0x04, 0x14, 0x1f, 0x30, 0xe0, 0x7f, + 0x28, 0x14, 0x0d, 0x34, 0xd4, 0x1c, 0x48, 0xb3, 0x41, 0xc6, 0x08, 0x1c, + 0xc0, 0x37, 0xcb, 0x46, 0xf8, 0x7f, 0x00, 0x00, 0x44, 0xc0, 0x83, 0xc0, + 0x20, 0x1c, 0x40, 0x31, 0x1c, 0x1c, 0x00, 0x31, 0x46, 0xc3, 0x45, 0xc2, + 0x28, 0x1c, 0x80, 0x33, 0x24, 0x1c, 0x01, 0x30, 0x5e, 0x0a, 0x20, 0x00, + 0x0c, 0x1c, 0x41, 0x30, 0x11, 0x08, 0x30, 0x00, 0xad, 0x70, 0x0a, 0xc6, + 0x11, 0x00, 0x20, 0x00, 0x24, 0x14, 0x0d, 0x30, 0xca, 0x09, 0x0f, 0xf6, + 0x21, 0xd9, 0x20, 0xa0, 0xa1, 0x40, 0xc1, 0x41, 0x08, 0x14, 0x1f, 0x30, + 0x01, 0xc6, 0xe0, 0x7f, 0x2c, 0x14, 0x0d, 0x34, 0xd8, 0x1c, 0x48, 0xb3, + 0x04, 0x1c, 0xc0, 0x37, 0x24, 0x1c, 0x80, 0x3f, 0xf0, 0x7f, 0x00, 0x00, + 0x43, 0xc0, 0x60, 0x40, 0x0a, 0x25, 0x80, 0x10, 0x20, 0x1c, 0x01, 0x30, + 0x26, 0x0a, 0x20, 0x00, 0x08, 0x1c, 0xc1, 0x30, 0x46, 0xc0, 0xa1, 0x40, + 0x1a, 0x0a, 0x20, 0x00, 0x47, 0xc1, 0x10, 0x1c, 0x00, 0x30, 0x82, 0xc0, + 0xfa, 0x09, 0x20, 0x00, 0x45, 0xc1, 0x08, 0xe8, 0x20, 0x14, 0x00, 0x30, + 0x72, 0x0a, 0x20, 0x00, 0x09, 0xc1, 0x08, 0xf0, 0x6a, 0x09, 0x0f, 0xf6, + 0x22, 0xd9, 0x20, 0xa0, 0xff, 0xd8, 0x17, 0xb8, 0x04, 0x14, 0x1f, 0x30, + 0xe0, 0x7f, 0x28, 0x14, 0x0d, 0x34, 0xe0, 0x78, 0xd8, 0x1c, 0x48, 0xb3, + 0x04, 0x1c, 0xc0, 0x37, 0x43, 0xc0, 0x60, 0x40, 0x0a, 0x25, 0x80, 0x10, + 0x24, 0x1c, 0x01, 0x30, 0x20, 0x1c, 0x01, 0x30, 0xca, 0x09, 0x20, 0x00, + 0x08, 0x1c, 0x01, 0x31, 0x46, 0xc0, 0xa1, 0x40, 0xbe, 0x09, 0x20, 0x00, + 0x47, 0xc1, 0x10, 0x1c, 0x00, 0x30, 0x82, 0xc0, 0x9e, 0x09, 0x20, 0x00, + 0x45, 0xc1, 0x08, 0xe8, 0x20, 0x14, 0x00, 0x30, 0x16, 0x0a, 0x20, 0x00, + 0x09, 0xc1, 0x08, 0xf0, 0x0e, 0x09, 0x0f, 0xf6, 0x22, 0xd9, 0x20, 0xa0, + 0x4a, 0x20, 0x00, 0x00, 0x04, 0x14, 0x1f, 0x30, 0xe0, 0x7f, 0x28, 0x14, + 0x0d, 0x34, 0xe0, 0x78, 0xd8, 0x1c, 0x48, 0xb3, 0x04, 0x1c, 0xc0, 0x37, + 0x24, 0x1c, 0x80, 0x3f, 0xf8, 0x7f, 0x00, 0x00, 0x43, 0xc0, 0x60, 0x40, + 0x0a, 0x25, 0x80, 0x10, 0x20, 0x1c, 0x01, 0x30, 0x6a, 0x09, 0x20, 0x00, + 0x08, 0x1c, 0x41, 0x30, 0x46, 0xc0, 0xa1, 0x40, 0x5e, 0x09, 0x20, 0x00, + 0x47, 0xc1, 0x10, 0x1c, 0x00, 0x30, 0x82, 0xc0, 0x3e, 0x09, 0x20, 0x00, + 0x45, 0xc1, 0x08, 0xe8, 0x20, 0x14, 0x00, 0x30, 0xb6, 0x09, 0x20, 0x00, + 0x09, 0xc1, 0x0a, 0xf0, 0xae, 0x08, 0x0f, 0xf6, 0x21, 0xd9, 0x20, 0xa0, + 0x0a, 0x20, 0x80, 0x0f, 0xc0, 0x7f, 0x00, 0x00, 0x04, 0x14, 0x1f, 0x30, + 0xe0, 0x7f, 0x28, 0x14, 0x0d, 0x34, 0xe0, 0x78, 0xe8, 0x1c, 0x48, 0xb3, + 0x41, 0xc6, 0x42, 0xc7, 0x0c, 0x1c, 0x00, 0x34, 0x10, 0x1c, 0x40, 0x34, + 0x14, 0x1c, 0xc0, 0x37, 0x68, 0x46, 0x48, 0x47, 0x61, 0x82, 0x31, 0x0e, + 0xb2, 0x10, 0x40, 0x82, 0x30, 0x40, 0x10, 0x41, 0x4a, 0x25, 0x40, 0x10, + 0x0a, 0x20, 0x40, 0x04, 0x0e, 0x0a, 0x20, 0x00, 0x0a, 0x21, 0x00, 0x04, + 0x08, 0x17, 0x02, 0x12, 0x96, 0x0e, 0x20, 0x00, 0x61, 0x87, 0xa5, 0x71, + 0x00, 0x42, 0xe9, 0x0d, 0xa2, 0x93, 0x20, 0x43, 0x40, 0x40, 0x60, 0x41, + 0x14, 0x14, 0x1f, 0x30, 0x10, 0x14, 0x11, 0x30, 0x0c, 0x14, 0x10, 0x30, + 0x02, 0xc7, 0x01, 0xc6, 0xe0, 0x7f, 0x18, 0x14, 0x0d, 0x34, 0xe0, 0x78, + 0x48, 0x43, 0x20, 0x42, 0x35, 0x0b, 0x70, 0x10, 0x20, 0x81, 0x31, 0x09, + 0x81, 0x0f, 0x80, 0x3f, 0x00, 0x00, 0x21, 0x82, 0x41, 0x0b, 0xf2, 0x10, + 0x01, 0x31, 0x01, 0x00, 0x40, 0x22, 0x0c, 0x02, 0x4a, 0x23, 0x80, 0x00, + 0x04, 0x14, 0x02, 0x14, 0x64, 0x71, 0x00, 0x31, 0x01, 0x00, 0xf9, 0x0b, + 0xe2, 0x82, 0x01, 0x31, 0x81, 0x00, 0x10, 0xf0, 0x1d, 0x0b, 0xb2, 0x10, + 0x4a, 0x23, 0x40, 0x00, 0x04, 0x12, 0x0c, 0x02, 0x40, 0x23, 0x43, 0x00, + 0x00, 0x31, 0x01, 0x00, 0xf5, 0x0b, 0xe2, 0x82, 0x01, 0x31, 0x01, 0x03, + 0xe0, 0x7f, 0x20, 0x40, 0x50, 0x20, 0xfe, 0x87, 0x00, 0x19, 0x01, 0x00, + 0xe0, 0x7c, 0x41, 0x28, 0xc2, 0x05, 0x04, 0x20, 0x80, 0x0f, 0x7f, 0x80, + 0xff, 0xff, 0x4f, 0x7a, 0x05, 0x20, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x80, 0x22, 0xbe, 0x00, 0xe0, 0x7f, 0x40, 0xa1, 0xff, 0xd9, 0x17, 0xb9, + 0x04, 0x20, 0x42, 0x00, 0x30, 0x72, 0x2c, 0x70, 0x04, 0xf4, 0xd6, 0xb8, + 0x78, 0x20, 0x01, 0x00, 0xe0, 0x7f, 0x20, 0x40, 0xc3, 0x41, 0xa0, 0x00, + 0x60, 0x88, 0x40, 0x81, 0x00, 0xa1, 0xe0, 0x7f, 0x40, 0x40, 0xe0, 0x78, + 0xc3, 0x41, 0xa0, 0x00, 0x60, 0x88, 0x20, 0x81, 0x02, 0xe9, 0x00, 0x79, + 0xe0, 0x7f, 0x0c, 0x70, 0xe0, 0x7f, 0x0c, 0x70, 0x2f, 0x23, 0x00, 0x80, + 0xca, 0x21, 0x01, 0x00, 0xe1, 0x20, 0xc1, 0x07, 0xc2, 0x20, 0x01, 0x00, + 0x41, 0x2b, 0xc2, 0x00, 0xc3, 0x72, 0x00, 0x70, 0x00, 0x00, 0x2f, 0x21, + 0x84, 0x00, 0x41, 0x2b, 0x0c, 0x06, 0x61, 0xbc, 0x8c, 0x24, 0x83, 0x9f, + 0xe1, 0x20, 0xc5, 0x07, 0x40, 0x2b, 0x00, 0x07, 0xc5, 0x21, 0x81, 0x0f, + 0x00, 0x7f, 0x00, 0x00, 0xe1, 0x20, 0xc1, 0x07, 0x41, 0x2a, 0x42, 0x05, + 0x2f, 0x2c, 0xc1, 0x90, 0xc2, 0x24, 0x04, 0x13, 0xc0, 0x24, 0x63, 0x10, + 0x85, 0x71, 0x00, 0x2b, 0x03, 0x03, 0x69, 0xbc, 0x82, 0x7a, 0x40, 0x2a, + 0x42, 0x05, 0x2f, 0x21, 0x40, 0x80, 0x2f, 0x21, 0x84, 0x00, 0x41, 0x2b, + 0x0c, 0x03, 0x85, 0x79, 0xe0, 0x7f, 0x40, 0x2b, 0x00, 0x05, 0xe0, 0x78, + 0x2f, 0x24, 0x40, 0x90, 0x02, 0x24, 0x83, 0x1f, 0x00, 0x70, 0x00, 0x00, + 0x40, 0x2b, 0xc2, 0x00, 0x2f, 0x22, 0x84, 0x00, 0x02, 0x23, 0x83, 0x0f, + 0x20, 0x00, 0x00, 0x00, 0xd3, 0x73, 0xc0, 0x1f, 0x00, 0x00, 0x40, 0x28, + 0x03, 0x01, 0x20, 0x00, 0x26, 0x00, 0x41, 0x28, 0x40, 0x87, 0x45, 0x78, + 0x44, 0x20, 0x41, 0x00, 0x05, 0x21, 0xc1, 0x80, 0xe0, 0x7f, 0xc1, 0x20, + 0x22, 0x00, 0xe0, 0x7f, 0x6c, 0x21, 0x80, 0x07, 0x2f, 0x23, 0xc4, 0x00, + 0x45, 0x78, 0x41, 0x2c, 0x4c, 0x15, 0x82, 0x24, 0x0d, 0x9a, 0xb7, 0xf6, + 0x42, 0x24, 0x0c, 0x96, 0x53, 0x20, 0x81, 0x05, 0x22, 0x00, 0x2c, 0x00, + 0x2f, 0x20, 0x00, 0x80, 0x05, 0x21, 0xc1, 0x80, 0x2f, 0x20, 0x84, 0x0f, + 0x80, 0xff, 0x00, 0x00, 0xd0, 0x20, 0xa1, 0x05, 0x8c, 0x24, 0xd1, 0x9f, + 0xe0, 0x7f, 0xd0, 0x20, 0xa2, 0x05, 0x4e, 0x24, 0x02, 0x10, 0x97, 0xb9, + 0x01, 0x29, 0x80, 0x00, 0x2f, 0x20, 0x04, 0x80, 0xe1, 0x20, 0xc6, 0x07, + 0x4e, 0x22, 0xcc, 0x07, 0x13, 0x21, 0x01, 0x03, 0x05, 0x21, 0xc1, 0x80, + 0xd1, 0x20, 0x21, 0x80, 0xe0, 0x7f, 0xc0, 0x20, 0x62, 0x00, 0xe0, 0x78, + 0xcb, 0x44, 0xe0, 0xff, 0x00, 0x00, 0x14, 0x24, 0x44, 0x10, 0x14, 0x24, + 0xc5, 0x10, 0xb5, 0xbc, 0x0c, 0x24, 0x00, 0x83, 0xe0, 0x00, 0x06, 0x00, + 0x0c, 0x25, 0x00, 0x83, 0xd8, 0x00, 0x06, 0x00, 0x41, 0x2c, 0x44, 0x05, + 0x41, 0x2d, 0x45, 0x05, 0x00, 0x25, 0x05, 0x01, 0x82, 0x25, 0x8f, 0x0f, + 0x8c, 0x25, 0xdf, 0x8e, 0xc0, 0x00, 0x26, 0x00, 0x07, 0x21, 0xcc, 0x80, + 0x40, 0x25, 0x47, 0x00, 0x94, 0xb9, 0xd4, 0xb9, 0x94, 0xbb, 0xcf, 0x27, + 0xe4, 0x02, 0x40, 0x2b, 0xc3, 0x02, 0x41, 0x2a, 0x45, 0x05, 0x40, 0x2a, + 0xc2, 0x82, 0x05, 0x23, 0x43, 0x01, 0x1d, 0x20, 0x84, 0x00, 0x1c, 0x20, + 0x8c, 0x00, 0x94, 0x70, 0xcf, 0x27, 0xe2, 0x07, 0x1d, 0x20, 0xc4, 0x00, + 0x1c, 0x20, 0xc5, 0x00, 0x00, 0x24, 0x0c, 0x91, 0x41, 0x25, 0x00, 0x00, + 0x1d, 0x21, 0x84, 0x00, 0x1c, 0x21, 0x85, 0x00, 0x00, 0x24, 0x0c, 0x91, + 0x01, 0x20, 0x40, 0x81, 0x1d, 0x21, 0xc4, 0x00, 0x1c, 0x21, 0xc5, 0x00, + 0x41, 0x26, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x81, + 0x01, 0x21, 0x41, 0x01, 0x19, 0x09, 0x3f, 0x05, 0x00, 0x24, 0x0c, 0x93, + 0x42, 0x27, 0x47, 0x00, 0x01, 0x20, 0x00, 0x80, 0x01, 0x21, 0x41, 0x00, + 0x00, 0x24, 0x0c, 0x93, 0x40, 0x2f, 0x04, 0x05, 0x41, 0x2f, 0xc7, 0x07, + 0x08, 0x00, 0x05, 0x00, 0xe0, 0x7f, 0x80, 0x71, 0xc5, 0x24, 0xc1, 0x91, + 0x44, 0x20, 0x45, 0x00, 0xc5, 0x25, 0x62, 0x00, 0x00, 0x20, 0x40, 0x81, + 0x41, 0x21, 0x01, 0x00, 0x15, 0x09, 0x5e, 0x05, 0x00, 0x24, 0x84, 0x0f, + 0x10, 0x00, 0x00, 0x00, 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, + 0xe0, 0x7f, 0x80, 0x71, 0x2f, 0x25, 0xc0, 0x80, 0x41, 0x26, 0x04, 0x70, + 0x00, 0x00, 0x00, 0x00, 0xcc, 0x22, 0x21, 0x80, 0x60, 0x03, 0x21, 0x00, + 0x2f, 0x21, 0x40, 0x90, 0xc7, 0x24, 0x65, 0x00, 0xcc, 0x20, 0x21, 0x80, + 0x2c, 0x03, 0x01, 0x00, 0x41, 0x29, 0x46, 0x95, 0x06, 0x21, 0x81, 0x0f, + 0xf0, 0xff, 0x00, 0x00, 0xc5, 0x21, 0x82, 0x0f, 0x10, 0x00, 0x00, 0x00, + 0x5a, 0x00, 0x22, 0x00, 0x00, 0x40, 0x34, 0x70, 0x0c, 0x00, 0x01, 0x00, + 0x1b, 0x00, 0x20, 0x00, 0x2f, 0x2a, 0x41, 0x10, 0x14, 0x70, 0x4a, 0x22, + 0xc0, 0x17, 0x0e, 0x00, 0x04, 0x00, 0x2f, 0x2a, 0x01, 0x10, 0x40, 0x22, + 0x0a, 0x18, 0x42, 0x22, 0x8a, 0x12, 0x02, 0x26, 0x86, 0x02, 0xc4, 0x71, + 0x02, 0x26, 0x8b, 0xf2, 0x00, 0x00, 0x20, 0x00, 0x01, 0x28, 0xcb, 0x02, + 0x12, 0x00, 0x09, 0x00, 0x42, 0x22, 0x0b, 0x18, 0x00, 0x28, 0xc1, 0x02, + 0x13, 0x00, 0x20, 0x00, 0x0c, 0x70, 0x00, 0x28, 0x80, 0x02, 0x00, 0x29, + 0x8a, 0x02, 0x05, 0x23, 0x81, 0x12, 0x41, 0x2d, 0x47, 0x85, 0x06, 0x23, + 0x88, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0xc5, 0x20, 0x82, 0x1f, 0x10, 0x00, + 0x00, 0x00, 0x5c, 0x00, 0x22, 0x00, 0x40, 0x42, 0x15, 0x70, 0x0e, 0x00, + 0x01, 0x00, 0x1d, 0x00, 0x20, 0x00, 0x2f, 0x2a, 0x01, 0x12, 0x54, 0x70, + 0x4a, 0x22, 0xc0, 0x17, 0x0c, 0x00, 0x04, 0x00, 0x2f, 0x2a, 0x81, 0x10, + 0x40, 0x22, 0x0a, 0x18, 0x42, 0x22, 0x8a, 0x12, 0x02, 0x27, 0x87, 0x02, + 0xe4, 0x71, 0x02, 0x26, 0x8b, 0xf2, 0x00, 0x00, 0x20, 0x00, 0x01, 0x2a, + 0xcb, 0x02, 0x14, 0x00, 0x09, 0x00, 0x42, 0x22, 0x0b, 0x18, 0x00, 0x2a, + 0xc8, 0x02, 0x15, 0x00, 0x20, 0x00, 0x4c, 0x70, 0x00, 0x2a, 0x82, 0x02, + 0x00, 0x28, 0x8a, 0x12, 0x05, 0x23, 0x88, 0x12, 0x8c, 0x26, 0xdf, 0x8f, + 0xf2, 0x01, 0x01, 0x00, 0x8c, 0x27, 0xdf, 0x8f, 0x1c, 0x02, 0x21, 0x00, + 0x00, 0x26, 0xc6, 0x01, 0x1d, 0x20, 0x8a, 0x00, 0x1c, 0x20, 0x8b, 0x00, + 0x82, 0x26, 0xcf, 0x0f, 0x1d, 0x21, 0x87, 0x00, 0x1c, 0x21, 0x8c, 0x00, + 0x00, 0x23, 0xcb, 0x91, 0x41, 0x24, 0x02, 0x10, 0x1d, 0x20, 0x07, 0x02, + 0x1c, 0x20, 0x0c, 0x02, 0x00, 0x23, 0xcb, 0x91, 0x01, 0x22, 0x02, 0x03, + 0x1d, 0x21, 0x07, 0x02, 0x1c, 0x21, 0x0c, 0x02, 0x00, 0x22, 0xc2, 0x81, + 0x41, 0x24, 0x09, 0x10, 0x40, 0x29, 0x01, 0x13, 0x41, 0x2a, 0x03, 0x05, + 0x65, 0x79, 0x40, 0x2a, 0x07, 0x03, 0x40, 0x2a, 0x00, 0x03, 0x41, 0x2b, + 0x03, 0x15, 0x65, 0x78, 0x40, 0x2b, 0x0c, 0x13, 0x55, 0x70, 0xc5, 0x24, + 0xa2, 0x10, 0xd4, 0x70, 0x1e, 0x00, 0x0c, 0x00, 0x04, 0x21, 0xbe, 0x8f, + 0x20, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0xc4, 0x71, 0x2f, 0x21, + 0x42, 0x80, 0x2f, 0x20, 0x04, 0x80, 0x2f, 0x24, 0x04, 0x13, 0x95, 0x70, + 0x36, 0x00, 0x0a, 0x00, 0x04, 0x24, 0xbe, 0x9f, 0xff, 0x7f, 0xff, 0xff, + 0x0c, 0x00, 0x02, 0x00, 0x44, 0x20, 0x7e, 0x80, 0x22, 0x00, 0x01, 0x00, + 0x40, 0x20, 0x40, 0x80, 0x41, 0x21, 0x01, 0x00, 0x04, 0x21, 0xbe, 0x8f, + 0x20, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00, 0xc4, 0x71, 0x2f, 0x21, + 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, 0x8c, 0x26, 0xdf, 0x8f, 0x0e, 0x01, + 0x0a, 0x00, 0xd4, 0x70, 0x1a, 0x00, 0x0c, 0x00, 0x06, 0x21, 0x81, 0x0f, + 0x10, 0x00, 0x00, 0x00, 0x40, 0x2e, 0x02, 0x05, 0x45, 0x79, 0x2f, 0x22, + 0x03, 0x01, 0x45, 0x79, 0xe0, 0x7e, 0x8c, 0x26, 0xff, 0x82, 0xfa, 0x00, + 0x0b, 0x00, 0x02, 0x26, 0x8a, 0x71, 0x00, 0x00, 0x00, 0x00, 0x42, 0x22, + 0x4a, 0x90, 0x4a, 0x26, 0x00, 0x70, 0x88, 0x00, 0x0b, 0x00, 0x8c, 0x00, + 0x01, 0x00, 0x4c, 0x22, 0x00, 0x98, 0x4a, 0x26, 0x00, 0x70, 0x2a, 0x00, + 0x0b, 0x00, 0x42, 0x22, 0x0a, 0x18, 0x05, 0x24, 0x0c, 0x90, 0x6d, 0x77, + 0x10, 0x00, 0x02, 0x00, 0x00, 0x2b, 0x8b, 0x12, 0x87, 0x23, 0xff, 0x1f, + 0x04, 0x21, 0xcc, 0x02, 0x01, 0x29, 0x80, 0x02, 0x5d, 0x00, 0x20, 0x00, + 0x2c, 0x70, 0x95, 0x70, 0x6d, 0x77, 0x1e, 0x00, 0x02, 0x00, 0x4c, 0x22, + 0x00, 0x98, 0xc2, 0x23, 0xca, 0x12, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x2b, + 0x8b, 0x12, 0x87, 0x23, 0xff, 0x1f, 0x04, 0x20, 0xcc, 0x02, 0x02, 0x26, + 0x8b, 0xf2, 0x00, 0x00, 0x20, 0x00, 0x00, 0x29, 0xcb, 0x02, 0x14, 0x00, + 0x09, 0x00, 0x40, 0x22, 0x0b, 0x18, 0x01, 0x29, 0xc0, 0x02, 0x15, 0x00, + 0x20, 0x00, 0x2c, 0x70, 0x01, 0x28, 0x80, 0x02, 0x01, 0x29, 0x81, 0x02, + 0x05, 0x20, 0xc0, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x2f, 0x20, 0x00, 0x80, + 0x2f, 0x21, 0x4b, 0x00, 0x44, 0x20, 0xbe, 0x80, 0x4a, 0x26, 0x00, 0x70, + 0x1c, 0x00, 0x01, 0x00, 0x44, 0x20, 0x4a, 0x01, 0x05, 0x22, 0x3e, 0x93, + 0x4a, 0x26, 0x00, 0x70, 0x0c, 0x00, 0x01, 0x00, 0x40, 0x20, 0x80, 0x80, + 0x41, 0x21, 0x01, 0x00, 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, + 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, 0x02, 0x26, 0x86, 0x01, + 0x04, 0x21, 0xbe, 0x8f, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x26, 0x62, 0x00, + 0x80, 0xf1, 0x8a, 0x26, 0xdf, 0x0f, 0xc3, 0x41, 0x10, 0x00, 0x00, 0x00, + 0xf5, 0x06, 0xef, 0xff, 0x0c, 0x70, 0x02, 0x26, 0x86, 0x01, 0x2c, 0x70, + 0xe9, 0x06, 0xef, 0xff, 0x0c, 0x70, 0xd3, 0x71, 0x10, 0x00, 0x00, 0x00, + 0xcc, 0x20, 0x21, 0x80, 0x2f, 0x21, 0x03, 0x01, 0xc5, 0x21, 0x82, 0x0f, + 0xf8, 0x7f, 0x00, 0x00, 0xc0, 0x78, 0x70, 0xf5, 0x8c, 0x27, 0xdf, 0x8f, + 0x14, 0x00, 0x01, 0x00, 0x2f, 0x21, 0x03, 0x01, 0x05, 0x21, 0x81, 0x0f, + 0xf0, 0x7f, 0x00, 0x00, 0x0c, 0x70, 0x64, 0xf1, 0x0c, 0x20, 0x80, 0x9f, + 0x10, 0x00, 0x00, 0x00, 0xcc, 0x22, 0x21, 0x80, 0x2f, 0x21, 0x03, 0x01, + 0xc5, 0x21, 0x82, 0x0f, 0xf8, 0x7f, 0x00, 0x00, 0xc5, 0x21, 0x81, 0x0f, + 0xf0, 0x7f, 0x00, 0x00, 0x0c, 0x70, 0x52, 0xf1, 0x0c, 0x25, 0x80, 0x8f, + 0xe0, 0xff, 0x00, 0x00, 0x4a, 0x26, 0x00, 0x70, 0x2a, 0x00, 0x06, 0x00, + 0x4a, 0x26, 0x00, 0x70, 0x0c, 0x70, 0x2c, 0x70, 0x94, 0x70, 0xc5, 0x21, + 0x82, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf1, 0xc7, 0x24, 0x65, 0x00, + 0x0c, 0x21, 0x80, 0x9f, 0xe0, 0xff, 0x00, 0x00, 0xb2, 0xf7, 0x4a, 0x26, + 0x00, 0x70, 0xc3, 0x41, 0xf8, 0x7f, 0x00, 0x00, 0x0c, 0x70, 0x32, 0xf1, + 0x07, 0x21, 0x81, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x07, 0x23, 0x83, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x21, 0x44, 0x00, + 0x00, 0x23, 0xc5, 0x00, 0x0c, 0x24, 0x40, 0x81, 0xcc, 0x20, 0x81, 0x80, + 0x10, 0x00, 0x06, 0x00, 0x08, 0x44, 0x40, 0x40, 0x81, 0x42, 0x28, 0x44, + 0x60, 0x41, 0x81, 0x43, 0x8a, 0x24, 0xdf, 0x1f, 0x40, 0x2c, 0x4c, 0x15, + 0x14, 0x24, 0x44, 0x10, 0x14, 0x24, 0xc5, 0x10, 0x40, 0x2c, 0x8c, 0x10, + 0x0c, 0x24, 0x00, 0x83, 0xcc, 0x25, 0x05, 0x83, 0xc6, 0x01, 0x06, 0x00, + 0x41, 0x29, 0x04, 0x05, 0x41, 0x2b, 0x05, 0x05, 0x02, 0x24, 0x46, 0x01, + 0x53, 0x26, 0x86, 0x02, 0x07, 0x21, 0xc7, 0x00, 0x40, 0x29, 0xc1, 0x02, + 0x41, 0x28, 0x4c, 0x05, 0x85, 0x79, 0x40, 0x28, 0xc0, 0x02, 0x40, 0x2b, + 0xc3, 0x02, 0x41, 0x2a, 0x4c, 0x05, 0x85, 0x7b, 0x40, 0x2a, 0xc2, 0x02, + 0x9f, 0xbb, 0x4e, 0x26, 0x0c, 0x88, 0x1c, 0x00, 0x2d, 0x00, 0x01, 0x2a, + 0x85, 0x01, 0x8c, 0x26, 0x01, 0x80, 0x01, 0x2b, 0x85, 0x01, 0xca, 0x25, + 0x26, 0x00, 0x17, 0x00, 0x20, 0x00, 0x8d, 0x70, 0xd4, 0x70, 0x00, 0x2b, + 0x0c, 0x03, 0xc5, 0x25, 0x02, 0x03, 0x01, 0x2b, 0x8c, 0x01, 0x41, 0x2f, + 0xc7, 0x87, 0x62, 0x00, 0x22, 0x00, 0x9f, 0xb9, 0x00, 0x25, 0x05, 0x80, + 0x01, 0x24, 0x4c, 0x90, 0x10, 0x00, 0x26, 0x00, 0xc2, 0x24, 0x66, 0x00, + 0x2f, 0x24, 0x04, 0x93, 0x2f, 0x25, 0x44, 0x01, 0x41, 0x2d, 0xc0, 0x82, + 0x40, 0x2c, 0x41, 0x15, 0x25, 0x78, 0x41, 0x2c, 0xc1, 0x12, 0x40, 0x2c, + 0x04, 0x05, 0xe1, 0x20, 0xc6, 0x07, 0x80, 0x71, 0x4c, 0x26, 0x00, 0x88, + 0xca, 0x23, 0x85, 0x00, 0xca, 0x22, 0x25, 0x00, 0x13, 0x23, 0x83, 0x01, + 0x05, 0x23, 0x83, 0x80, 0xd3, 0x25, 0x61, 0x82, 0xd1, 0x20, 0x21, 0x80, + 0xca, 0x27, 0x62, 0x00, 0x00, 0x20, 0xc0, 0x81, 0xe0, 0x7f, 0x41, 0x21, + 0x01, 0x00, 0x0e, 0x25, 0x05, 0x80, 0x03, 0x21, 0x0c, 0x83, 0x52, 0x00, + 0x23, 0x00, 0x0c, 0x70, 0x41, 0x2d, 0xc0, 0x82, 0x40, 0x2c, 0x41, 0x15, + 0x25, 0x78, 0x41, 0x2c, 0xc1, 0x12, 0x42, 0x24, 0x44, 0x00, 0x40, 0x2c, + 0x04, 0x05, 0xe1, 0x20, 0xc6, 0x07, 0x80, 0x71, 0x4c, 0x26, 0x00, 0x88, + 0xca, 0x23, 0x85, 0x00, 0xca, 0x22, 0x25, 0x00, 0x13, 0x23, 0x83, 0x01, + 0x05, 0x23, 0x83, 0x80, 0xca, 0x27, 0x22, 0x00, 0x04, 0x27, 0x07, 0x80, + 0xd3, 0x25, 0x61, 0x82, 0xca, 0x27, 0x62, 0x00, 0x00, 0x20, 0xc0, 0x81, + 0xe0, 0x7f, 0x41, 0x21, 0x01, 0x00, 0xcc, 0x25, 0x21, 0x80, 0xe1, 0x20, + 0xc1, 0x07, 0x2c, 0x70, 0x2f, 0x28, 0x01, 0x03, 0x9f, 0xe0, 0x14, 0x00, + 0x25, 0x00, 0x04, 0x71, 0x2f, 0x28, 0x41, 0x81, 0xca, 0x20, 0x24, 0x08, + 0xc0, 0x20, 0x63, 0x08, 0x4e, 0x20, 0x01, 0x88, 0x18, 0x00, 0x2d, 0x00, + 0x00, 0x2c, 0x0c, 0x10, 0xc0, 0xe0, 0x00, 0x2d, 0x0c, 0x00, 0xca, 0x24, + 0x26, 0x10, 0x17, 0x00, 0x20, 0x00, 0xac, 0x70, 0x14, 0x70, 0x01, 0x2d, + 0x41, 0x00, 0xc5, 0x24, 0x42, 0x10, 0x00, 0x2d, 0x05, 0x00, 0x53, 0x24, + 0x81, 0x02, 0x0e, 0x20, 0x40, 0x80, 0x04, 0x24, 0x84, 0x0f, 0x00, 0x00, + 0x00, 0x08, 0x12, 0x00, 0x22, 0x00, 0xc0, 0x20, 0x61, 0x00, 0x2f, 0x24, + 0x02, 0x93, 0x2f, 0x25, 0x44, 0x01, 0x4c, 0x07, 0xe6, 0xff, 0xc5, 0x24, + 0x06, 0x00, 0x4e, 0x20, 0x40, 0x00, 0x4e, 0x20, 0x01, 0x88, 0x1a, 0x00, + 0x2d, 0x00, 0x01, 0x2d, 0x05, 0x00, 0xc0, 0xe0, 0x01, 0x2c, 0x05, 0x10, + 0xca, 0x25, 0x26, 0x00, 0x15, 0x00, 0x20, 0x00, 0x8d, 0x70, 0x14, 0x70, + 0x00, 0x2c, 0x41, 0x10, 0xc5, 0x25, 0x42, 0x00, 0x01, 0x2c, 0x0c, 0x10, + 0x15, 0x07, 0xef, 0xff, 0x84, 0x71, 0x2f, 0x22, 0x40, 0x90, 0x41, 0x26, + 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x01, 0x00, 0x2f, 0x23, + 0xc0, 0x90, 0x41, 0x26, 0x05, 0x70, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x02, + 0x01, 0x00, 0x0c, 0x23, 0x80, 0x92, 0xcc, 0x22, 0x01, 0x80, 0xcc, 0x21, + 0xc1, 0x80, 0x08, 0x42, 0x14, 0x00, 0x0e, 0x00, 0x40, 0x40, 0x41, 0x42, + 0x28, 0x42, 0x60, 0x41, 0x41, 0x43, 0x88, 0x42, 0xa0, 0x44, 0x41, 0x45, + 0x2f, 0x26, 0x40, 0x00, 0x41, 0x2e, 0x46, 0x85, 0x06, 0x21, 0x81, 0x0f, + 0xf0, 0xff, 0x00, 0x00, 0xc5, 0x21, 0x82, 0x0f, 0x10, 0x00, 0x00, 0x00, + 0x5a, 0x00, 0x22, 0x00, 0x00, 0x40, 0x34, 0x70, 0x0c, 0x00, 0x01, 0x00, + 0x1b, 0x00, 0x20, 0x00, 0x2f, 0x2a, 0x41, 0x10, 0x14, 0x70, 0x4a, 0x22, + 0xc0, 0x17, 0x0e, 0x00, 0x04, 0x00, 0x2f, 0x2a, 0x01, 0x10, 0x40, 0x22, + 0x0a, 0x18, 0x42, 0x22, 0x8a, 0x12, 0x02, 0x26, 0x86, 0x02, 0xc4, 0x71, + 0x02, 0x26, 0x8b, 0xf2, 0x00, 0x00, 0x20, 0x00, 0x01, 0x28, 0xcb, 0x02, + 0x12, 0x00, 0x09, 0x00, 0x42, 0x22, 0x0b, 0x18, 0x00, 0x28, 0xc1, 0x02, + 0x13, 0x00, 0x20, 0x00, 0x0c, 0x70, 0x00, 0x28, 0x80, 0x02, 0x00, 0x29, + 0x8a, 0x02, 0x05, 0x23, 0x81, 0x12, 0x2f, 0x27, 0xc0, 0x00, 0x41, 0x2f, + 0x47, 0x85, 0x06, 0x23, 0x88, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0xc5, 0x20, + 0x82, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x22, 0x00, 0x40, 0x42, + 0x15, 0x70, 0x0e, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x20, 0x00, 0x2f, 0x2a, + 0x01, 0x12, 0x54, 0x70, 0x4a, 0x22, 0xc0, 0x17, 0x0c, 0x00, 0x04, 0x00, + 0x2f, 0x2a, 0x81, 0x10, 0x40, 0x22, 0x0a, 0x18, 0x42, 0x22, 0x8a, 0x12, + 0x02, 0x27, 0x87, 0x02, 0xe4, 0x71, 0x02, 0x26, 0x8b, 0xf2, 0x00, 0x00, + 0x20, 0x00, 0x01, 0x2a, 0xcb, 0x02, 0x14, 0x00, 0x09, 0x00, 0x42, 0x22, + 0x0b, 0x18, 0x00, 0x2a, 0xc8, 0x02, 0x15, 0x00, 0x20, 0x00, 0x4c, 0x70, + 0x00, 0x2a, 0x82, 0x02, 0x00, 0x28, 0x8a, 0x12, 0x05, 0x23, 0x88, 0x12, + 0x8c, 0x26, 0xdf, 0x8f, 0x4a, 0x26, 0x00, 0x70, 0xa6, 0x03, 0x01, 0x00, + 0x8c, 0x27, 0xdf, 0x8f, 0x4a, 0x26, 0x00, 0x70, 0xf4, 0x03, 0x21, 0x00, + 0x02, 0x26, 0xcb, 0x01, 0x4c, 0x23, 0x80, 0x9d, 0x02, 0x21, 0x49, 0x12, + 0x3a, 0x01, 0x09, 0x00, 0x42, 0x23, 0x8a, 0x90, 0x4a, 0x26, 0x00, 0x70, + 0x8a, 0x00, 0x01, 0x00, 0x24, 0x00, 0x09, 0x00, 0x2f, 0x22, 0x80, 0x80, + 0x2f, 0x20, 0x0b, 0x12, 0x40, 0x22, 0x4a, 0x90, 0x4a, 0x26, 0x00, 0x70, + 0x72, 0x00, 0x01, 0x00, 0x2f, 0x22, 0x80, 0x80, 0x6b, 0x00, 0x20, 0x00, + 0x2f, 0x20, 0x0b, 0x12, 0x4c, 0x22, 0x00, 0x98, 0x6d, 0x70, 0x28, 0x00, + 0x2b, 0x00, 0x42, 0x22, 0x0a, 0x18, 0x0a, 0x21, 0x80, 0x90, 0x12, 0x00, + 0x02, 0x00, 0x02, 0x26, 0x8b, 0x72, 0x00, 0x00, 0x20, 0x00, 0x00, 0x28, + 0xc9, 0x12, 0x01, 0x28, 0x82, 0x12, 0x3f, 0x00, 0x20, 0x00, 0x0d, 0x70, + 0x02, 0x26, 0x8b, 0x72, 0x00, 0x00, 0x20, 0x00, 0x00, 0x2a, 0xc9, 0x02, + 0x02, 0x26, 0x8b, 0xf2, 0x00, 0x00, 0x20, 0x00, 0x00, 0x28, 0xcb, 0x12, + 0x12, 0x00, 0x09, 0x00, 0x40, 0x22, 0x0b, 0x18, 0x01, 0x28, 0xc2, 0x12, + 0x13, 0x00, 0x20, 0x00, 0x0d, 0x70, 0x01, 0x2a, 0x82, 0x02, 0x01, 0x28, + 0x88, 0x12, 0x05, 0x22, 0xc2, 0x02, 0x2f, 0x20, 0x00, 0x80, 0x2f, 0x21, + 0x4b, 0x00, 0x2f, 0x20, 0x00, 0x80, 0x2f, 0x21, 0x4b, 0x00, 0x0c, 0x24, + 0x40, 0x81, 0x4a, 0x26, 0x00, 0x70, 0xe0, 0x01, 0x02, 0x00, 0x00, 0x20, + 0x80, 0x80, 0x01, 0x21, 0x01, 0x02, 0x04, 0x21, 0xbe, 0x8f, 0x80, 0x00, + 0x00, 0x00, 0x4a, 0x26, 0x00, 0x70, 0x14, 0x00, 0x01, 0x00, 0xc4, 0x71, + 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x80, 0xc5, 0x21, 0x65, 0x10, + 0x44, 0x20, 0xbe, 0x80, 0x4a, 0x26, 0x00, 0x70, 0x34, 0x00, 0x21, 0x00, + 0x35, 0x70, 0xcb, 0x20, 0x61, 0x81, 0x4a, 0x26, 0x00, 0x70, 0x28, 0x00, + 0x01, 0x00, 0x40, 0x20, 0x80, 0x80, 0xc0, 0x21, 0x65, 0x00, 0x04, 0x21, + 0xbe, 0x8f, 0x80, 0x00, 0x00, 0x00, 0x4a, 0x26, 0x00, 0x70, 0x10, 0x00, + 0x01, 0x00, 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, 0xc4, 0x71, + 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, 0x2f, 0x21, 0x42, 0x80, + 0x2f, 0x20, 0x04, 0x00, 0xd4, 0x70, 0x4a, 0x26, 0x00, 0x70, 0x66, 0x00, + 0x0c, 0x00, 0x8c, 0x26, 0xdf, 0x8f, 0x4a, 0x26, 0x00, 0x70, 0x3e, 0x01, + 0x0a, 0x00, 0x06, 0x21, 0x81, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x40, 0x2e, + 0x02, 0x05, 0x45, 0x79, 0x2f, 0x22, 0x03, 0x01, 0x45, 0x79, 0xe0, 0x7e, + 0x14, 0x70, 0x4a, 0x26, 0x00, 0x70, 0x72, 0x05, 0xc2, 0xff, 0xd3, 0x73, + 0x00, 0x80, 0x00, 0x00, 0x4a, 0x26, 0x00, 0x70, 0x7c, 0x71, 0x12, 0x00, + 0x02, 0x00, 0x54, 0x70, 0x4a, 0x26, 0x00, 0x70, 0x7c, 0x71, 0xca, 0x21, + 0x41, 0x00, 0x40, 0x40, 0xe0, 0x7e, 0x54, 0x70, 0x4a, 0x26, 0x00, 0x70, + 0x56, 0x05, 0xc2, 0xff, 0x4a, 0x26, 0x00, 0x70, 0xe0, 0x7e, 0x4a, 0x26, + 0x00, 0x70, 0x02, 0x26, 0x8a, 0x71, 0x00, 0x00, 0x00, 0x00, 0x42, 0x22, + 0x4a, 0x90, 0x4a, 0x26, 0x00, 0x70, 0x88, 0x00, 0x0b, 0x00, 0x8c, 0x00, + 0x01, 0x00, 0x4c, 0x22, 0x00, 0x98, 0x4a, 0x26, 0x00, 0x70, 0x2a, 0x00, + 0x0b, 0x00, 0x42, 0x22, 0x0a, 0x18, 0x05, 0x21, 0x09, 0x90, 0x6d, 0x77, + 0x10, 0x00, 0x02, 0x00, 0x00, 0x2b, 0x8b, 0x12, 0x87, 0x23, 0xff, 0x1f, + 0x04, 0x21, 0xc9, 0x02, 0x01, 0x29, 0x80, 0x02, 0x5d, 0x00, 0x20, 0x00, + 0x2c, 0x70, 0x35, 0x70, 0x6d, 0x77, 0x1e, 0x00, 0x02, 0x00, 0x4c, 0x22, + 0x00, 0x98, 0xc2, 0x23, 0xca, 0x12, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x2b, + 0x8b, 0x12, 0x87, 0x23, 0xff, 0x1f, 0x04, 0x20, 0xc9, 0x02, 0x02, 0x26, + 0x8b, 0xf2, 0x00, 0x00, 0x20, 0x00, 0x00, 0x29, 0xcb, 0x02, 0x14, 0x00, + 0x09, 0x00, 0x40, 0x22, 0x0b, 0x18, 0x01, 0x29, 0xc0, 0x02, 0x15, 0x00, + 0x20, 0x00, 0x2c, 0x70, 0x01, 0x28, 0x80, 0x02, 0x01, 0x29, 0x81, 0x02, + 0x05, 0x20, 0xc0, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x2f, 0x20, 0x00, 0x80, + 0x2f, 0x21, 0x4b, 0x00, 0x44, 0x20, 0xbe, 0x80, 0x4a, 0x26, 0x00, 0x70, + 0x1c, 0x00, 0x01, 0x00, 0x44, 0x20, 0x4a, 0x01, 0x05, 0x22, 0x7e, 0x92, + 0x4a, 0x26, 0x00, 0x70, 0x0c, 0x00, 0x01, 0x00, 0x40, 0x20, 0x80, 0x80, + 0x41, 0x21, 0x01, 0x00, 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, + 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, 0x02, 0x26, 0x86, 0x01, + 0x04, 0x21, 0xbe, 0x8f, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x26, 0x62, 0x00, + 0x65, 0xf1, 0x8a, 0x26, 0xdf, 0x0f, 0xc3, 0x41, 0x10, 0x00, 0x00, 0x00, + 0x0c, 0x70, 0x5f, 0xf1, 0x02, 0x26, 0x86, 0x01, 0x2c, 0x70, 0xb7, 0x06, + 0xef, 0xff, 0x0c, 0x70, 0x02, 0x20, 0x80, 0x80, 0x03, 0x21, 0x01, 0x02, + 0x04, 0x21, 0xbe, 0x8f, 0x40, 0x00, 0x00, 0x00, 0x4a, 0x26, 0x00, 0x70, + 0x20, 0x00, 0x02, 0x00, 0x2f, 0x20, 0x00, 0x80, 0x2f, 0x21, 0x4b, 0x00, + 0x42, 0x26, 0x46, 0x00, 0x04, 0x21, 0xbe, 0x8f, 0x40, 0x00, 0x00, 0x00, + 0x4a, 0x26, 0x00, 0x70, 0x52, 0x00, 0x01, 0x00, 0x44, 0x20, 0xbe, 0x80, + 0x4a, 0x26, 0x00, 0x70, 0x46, 0x00, 0x21, 0x00, 0x44, 0x20, 0x7e, 0x80, + 0x4a, 0x26, 0x00, 0x70, 0x1a, 0x00, 0x02, 0x00, 0x35, 0x70, 0x4a, 0x26, + 0x00, 0x70, 0x32, 0x00, 0x02, 0x00, 0x44, 0x20, 0x3e, 0x81, 0x4a, 0x26, + 0x00, 0x70, 0x26, 0x00, 0x01, 0x00, 0x40, 0x20, 0x80, 0x80, 0x41, 0x21, + 0x01, 0x00, 0x04, 0x21, 0xbe, 0x8f, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x26, + 0x62, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, + 0x04, 0x00, 0x2f, 0x21, 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, 0x2f, 0x21, + 0x42, 0x80, 0x2f, 0x20, 0x04, 0x00, 0xd3, 0x71, 0x10, 0x00, 0x00, 0x00, + 0x4a, 0x26, 0x00, 0x70, 0xfc, 0x05, 0xca, 0xff, 0x34, 0x70, 0x0e, 0x00, + 0x01, 0x00, 0x2f, 0x2a, 0x41, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x14, 0x70, + 0x08, 0x00, 0x0c, 0x00, 0x2f, 0x2a, 0x01, 0x00, 0xc0, 0x22, 0x29, 0x08, + 0x9c, 0xf3, 0xca, 0x22, 0xeb, 0x07, 0x6a, 0xba, 0x02, 0x26, 0x8b, 0xf0, + 0x00, 0x00, 0x20, 0x00, 0x01, 0x28, 0xcb, 0x02, 0x12, 0x00, 0x09, 0x00, + 0x42, 0x22, 0x0b, 0x08, 0x00, 0x28, 0xc1, 0x02, 0x13, 0x00, 0x20, 0x00, + 0x0c, 0x70, 0x00, 0x29, 0x81, 0x00, 0x05, 0x21, 0xc1, 0x02, 0x00, 0x28, + 0x80, 0x00, 0x02, 0x26, 0x86, 0x80, 0x4a, 0x26, 0x00, 0x70, 0x0e, 0x06, + 0xcc, 0xff, 0xb7, 0x05, 0xcf, 0xff, 0xd3, 0x71, 0x10, 0x00, 0x00, 0x00, + 0xcc, 0x20, 0x21, 0x80, 0x2f, 0x21, 0x03, 0x01, 0x02, 0x78, 0x10, 0x00, + 0x01, 0x00, 0x05, 0x21, 0x81, 0x0f, 0xf8, 0x7f, 0x00, 0x00, 0xe0, 0x7e, + 0x8c, 0x27, 0xdf, 0x8f, 0x4a, 0x26, 0x00, 0x70, 0x28, 0x00, 0x02, 0x00, + 0x0c, 0x20, 0x80, 0x9f, 0x10, 0x00, 0x00, 0x00, 0xcc, 0x22, 0x21, 0x80, + 0x4a, 0x26, 0x00, 0x70, 0x0a, 0x00, 0x01, 0x00, 0x2f, 0x21, 0x43, 0x01, + 0xe9, 0xf1, 0x0c, 0x24, 0x40, 0x81, 0x4a, 0x26, 0x00, 0x70, 0xe5, 0xf5, + 0x05, 0x21, 0x81, 0x0f, 0xf0, 0x7f, 0x00, 0x00, 0x0c, 0x70, 0xe0, 0x7e, + 0x60, 0x41, 0x40, 0x40, 0xe0, 0x7e, 0xe0, 0x78, 0xe2, 0xc2, 0x48, 0x31, + 0x01, 0x00, 0x08, 0x45, 0x07, 0x36, 0x4c, 0x70, 0x48, 0x47, 0x00, 0x00, + 0x09, 0x90, 0xc3, 0x43, 0x83, 0x3a, 0x6f, 0x12, 0x2c, 0x70, 0x48, 0x30, + 0x00, 0x00, 0x00, 0x34, 0x00, 0x10, 0x00, 0x30, 0xc0, 0x00, 0x04, 0x30, + 0x40, 0x80, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, + 0xc0, 0x02, 0x30, 0x8d, 0x10, 0x7a, 0x8b, 0xe2, 0x48, 0x31, 0x01, 0x00, + 0xca, 0x20, 0xa6, 0x02, 0x10, 0x78, 0x00, 0x34, 0x41, 0x10, 0x48, 0x20, + 0xc0, 0x00, 0x0c, 0xb5, 0x86, 0x0b, 0xef, 0xf7, 0x00, 0x31, 0xc0, 0x00, + 0x2c, 0x70, 0x04, 0x30, 0x40, 0x80, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, + 0x00, 0x00, 0x48, 0x30, 0xc0, 0x02, 0x48, 0x30, 0x80, 0x00, 0x48, 0x30, + 0xc0, 0x02, 0x05, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0xea, 0xc3, 0x82, 0x24, + 0x0d, 0x34, 0x50, 0x41, 0x08, 0x45, 0x94, 0xc0, 0x8a, 0x22, 0x0c, 0x00, + 0x0e, 0x0d, 0x6f, 0xed, 0x28, 0x46, 0x00, 0x85, 0x40, 0x24, 0x83, 0x30, + 0x40, 0x24, 0x04, 0x32, 0x54, 0x24, 0x85, 0x39, 0x40, 0x24, 0x06, 0x31, + 0x40, 0x24, 0xc7, 0x30, 0xc1, 0x41, 0x22, 0x42, 0x1a, 0x09, 0xaf, 0xf4, + 0x02, 0x1c, 0x43, 0x32, 0x02, 0xc7, 0xe1, 0x0f, 0x31, 0x10, 0x56, 0x25, + 0x10, 0x1d, 0x03, 0x14, 0x8e, 0x30, 0x2c, 0x70, 0xed, 0x70, 0xd1, 0x09, + 0x31, 0x00, 0xcf, 0x78, 0x02, 0x14, 0x81, 0x30, 0xc5, 0x09, 0x24, 0x00, + 0x04, 0x77, 0xa9, 0x08, 0x55, 0x02, 0x25, 0x20, 0x00, 0x00, 0x0a, 0xf0, + 0x13, 0xf0, 0x1a, 0xf0, 0x1e, 0xf0, 0x26, 0xf0, 0x2e, 0xf0, 0x38, 0xf0, + 0x3c, 0xf0, 0x42, 0xf0, 0x94, 0xc0, 0x81, 0xc1, 0xfa, 0x0b, 0x6f, 0xf8, + 0x83, 0xc2, 0x83, 0xc1, 0x40, 0xda, 0x9e, 0x0c, 0x6f, 0xed, 0x02, 0x40, + 0x3c, 0xf0, 0x94, 0xc0, 0x1a, 0x09, 0xef, 0xf8, 0x81, 0xc1, 0x78, 0x1d, + 0x18, 0x10, 0x36, 0xf0, 0x94, 0xc0, 0x1a, 0x0e, 0xaf, 0xf0, 0x81, 0xc1, + 0x01, 0xa5, 0x30, 0xf0, 0x94, 0xc0, 0x02, 0x09, 0xef, 0xf8, 0x81, 0xc1, + 0x00, 0x30, 0x00, 0x00, 0x04, 0xa5, 0x28, 0xf0, 0x94, 0xc0, 0xf2, 0x08, + 0xef, 0xf8, 0x81, 0xc1, 0x00, 0x30, 0x01, 0x00, 0x89, 0x1d, 0x18, 0x10, + 0x25, 0xa5, 0x1e, 0xf0, 0x94, 0xc0, 0xde, 0x08, 0xef, 0xf8, 0x81, 0xc1, + 0x00, 0x30, 0x01, 0x00, 0x8a, 0x1d, 0x18, 0x10, 0x26, 0xa5, 0x14, 0xf0, + 0x94, 0xc0, 0xca, 0x08, 0xef, 0xf8, 0x81, 0xc1, 0x07, 0xa5, 0x0e, 0xf0, + 0x94, 0xc0, 0xc6, 0x0f, 0xaf, 0xf7, 0x81, 0xc1, 0x10, 0xb5, 0x08, 0xf0, + 0x94, 0xc0, 0xb2, 0x08, 0xef, 0xf8, 0x81, 0xc1, 0x8b, 0x1d, 0x18, 0x10, + 0x01, 0xc0, 0x8a, 0x21, 0x3e, 0x06, 0x32, 0x70, 0xca, 0x27, 0x4d, 0x10, + 0x3c, 0x21, 0x01, 0x20, 0x3d, 0x21, 0x00, 0x20, 0x1e, 0x66, 0x9b, 0xf1, + 0xe1, 0x40, 0xca, 0xc7, 0xec, 0xc3, 0xa7, 0xc1, 0x0a, 0x21, 0x00, 0x21, + 0x70, 0x40, 0x50, 0x42, 0x28, 0x46, 0x08, 0x45, 0x1a, 0x0b, 0x20, 0x00, + 0x55, 0x20, 0x8f, 0x09, 0x22, 0x85, 0xf6, 0x0a, 0xef, 0xfb, 0x03, 0x85, + 0x4a, 0x24, 0xc0, 0x70, 0x41, 0x68, 0x14, 0x20, 0x01, 0x00, 0x0c, 0x70, + 0x0c, 0x1d, 0x80, 0x10, 0xa8, 0x20, 0x00, 0x02, 0x02, 0x4e, 0x15, 0x25, + 0x43, 0x10, 0x04, 0x71, 0x24, 0x71, 0x4b, 0xa3, 0x72, 0x0c, 0x20, 0x00, + 0xa1, 0x40, 0x00, 0x19, 0x00, 0x20, 0xa1, 0x40, 0x82, 0x0d, 0x20, 0x00, + 0xc1, 0x41, 0x00, 0x41, 0xa1, 0x40, 0xb2, 0x0d, 0x20, 0x00, 0x30, 0x41, + 0x00, 0x41, 0xa1, 0x40, 0x36, 0x0c, 0x20, 0x00, 0x22, 0x42, 0xcd, 0x70, + 0x00, 0x18, 0x82, 0x23, 0x39, 0xe8, 0x21, 0x87, 0x02, 0x87, 0x40, 0x87, + 0x44, 0xc1, 0x45, 0xc0, 0x56, 0x25, 0x80, 0x1a, 0x83, 0xc1, 0x46, 0xc6, + 0x5a, 0x0c, 0x2f, 0xef, 0x43, 0xc2, 0x00, 0x18, 0x43, 0x20, 0xb8, 0x17, + 0x02, 0x10, 0xbc, 0x17, 0x01, 0x10, 0xc0, 0x17, 0x00, 0x10, 0x40, 0xc2, + 0x4a, 0x24, 0xc0, 0x70, 0x3f, 0xda, 0x40, 0x2a, 0x02, 0x06, 0x41, 0xc1, + 0x80, 0xc1, 0x4f, 0x22, 0xc3, 0x07, 0x42, 0xc0, 0xa8, 0x20, 0x40, 0x04, + 0x00, 0x81, 0x04, 0x30, 0x80, 0x83, 0xc5, 0xf6, 0x01, 0x30, 0x80, 0x00, + 0x03, 0xf0, 0x01, 0x30, 0xc0, 0x00, 0x48, 0x30, 0xc0, 0x02, 0x48, 0x30, + 0x80, 0x00, 0x04, 0x19, 0x10, 0x00, 0x02, 0xc2, 0x01, 0xc1, 0x00, 0xc0, + 0x45, 0xa7, 0x24, 0xa7, 0x03, 0xa7, 0x00, 0x10, 0x8e, 0x20, 0xa1, 0x40, + 0xc1, 0x41, 0xca, 0x0a, 0x20, 0x00, 0x22, 0x42, 0x4a, 0x24, 0xc0, 0x70, + 0x55, 0x25, 0x40, 0x1a, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x01, 0x04, + 0x04, 0x1a, 0x50, 0x20, 0x00, 0x88, 0x48, 0x30, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x20, 0xcc, 0xc7, 0xe8, 0xc3, 0xb2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, 0x6a, 0x0f, 0x6f, 0xf4, 0x03, 0x1c, + 0x43, 0x32, 0x02, 0x14, 0x80, 0x30, 0x56, 0x26, 0x10, 0x1d, 0x03, 0x14, + 0x81, 0x30, 0x0f, 0x78, 0x8d, 0x09, 0x24, 0x00, 0x04, 0x77, 0x7d, 0x08, + 0x55, 0x02, 0x25, 0x20, 0x00, 0x00, 0x0a, 0xf0, 0x14, 0xf0, 0x17, 0xf0, + 0x1c, 0xf0, 0x20, 0xf0, 0x21, 0xf0, 0x24, 0xf0, 0x24, 0xf0, 0x2b, 0xf0, + 0x82, 0xc0, 0x40, 0xda, 0xa6, 0x0a, 0x6f, 0xed, 0x02, 0x41, 0x82, 0xc0, + 0x81, 0xc3, 0xa1, 0x41, 0x0a, 0x0a, 0x6f, 0xf8, 0xe1, 0x42, 0x26, 0xf0, + 0x78, 0x16, 0x00, 0x16, 0x1d, 0xf0, 0x01, 0x86, 0x81, 0xc3, 0xa1, 0x41, + 0x36, 0x0c, 0xaf, 0xf0, 0xe1, 0x42, 0x1c, 0xf0, 0x04, 0x86, 0x2f, 0x30, + 0x00, 0x00, 0x13, 0xf0, 0x89, 0x16, 0x00, 0x16, 0x0f, 0xf0, 0x8a, 0x16, + 0x00, 0x16, 0x0d, 0xf0, 0x07, 0x86, 0x0b, 0xf0, 0x10, 0x96, 0x81, 0xc3, + 0xa1, 0x41, 0x06, 0x0e, 0xaf, 0xf7, 0xe1, 0x42, 0x08, 0xf0, 0x8b, 0x16, + 0x00, 0x16, 0x81, 0xc3, 0xa1, 0x41, 0xf6, 0x0e, 0xaf, 0xf8, 0xe1, 0x42, + 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xb9, 0xf1, + 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xc8, 0xc7, + 0xe8, 0xc3, 0xa1, 0xc1, 0x50, 0x40, 0x28, 0x45, 0x2c, 0x70, 0x10, 0xda, + 0x60, 0x40, 0x88, 0x46, 0x66, 0x08, 0x6f, 0xfb, 0x68, 0x47, 0xb5, 0x70, + 0xad, 0x70, 0x1b, 0xf4, 0x4a, 0x24, 0x00, 0x71, 0xc3, 0x42, 0x13, 0x00, + 0x24, 0x6b, 0x0c, 0x70, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x03, 0x04, + 0x80, 0xc1, 0x1c, 0x61, 0x04, 0x71, 0x38, 0x23, 0x01, 0x04, 0x20, 0xac, + 0x6e, 0x0b, 0xaf, 0xf6, 0x80, 0xc0, 0x07, 0xe8, 0xad, 0x72, 0x01, 0x1f, + 0x03, 0x11, 0x00, 0x1f, 0x43, 0x10, 0xa0, 0xa6, 0xc8, 0xc7, 0xe0, 0x78, + 0xf2, 0xc3, 0xb2, 0xc1, 0x10, 0x45, 0x00, 0x80, 0x60, 0x44, 0x40, 0x24, + 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x45, + 0x30, 0x44, 0x4e, 0x0e, 0x6f, 0xf4, 0x03, 0x1c, 0xc3, 0x32, 0x02, 0x14, + 0x80, 0x30, 0x56, 0x25, 0x0e, 0x2b, 0x55, 0x25, 0x4f, 0x2a, 0x55, 0x25, + 0xd0, 0x28, 0x55, 0x25, 0x91, 0x29, 0x55, 0x25, 0x13, 0x2d, 0x40, 0x25, + 0x12, 0x2b, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0xad, 0x09, 0x24, 0x00, + 0x04, 0x77, 0x9d, 0x08, 0xd5, 0x02, 0x25, 0x20, 0x00, 0x00, 0x0c, 0xf0, + 0x0d, 0xf0, 0x19, 0xf0, 0x19, 0xf0, 0x21, 0xf0, 0x22, 0xf0, 0x29, 0xf0, + 0x2a, 0xf0, 0x31, 0xf0, 0x36, 0xf0, 0x39, 0xf0, 0x81, 0xc3, 0xe1, 0x40, + 0x1c, 0xf0, 0x82, 0xc0, 0x40, 0xda, 0x6e, 0x09, 0x6f, 0xed, 0xc1, 0x41, + 0x82, 0xc0, 0x81, 0xc3, 0x82, 0x41, 0xd2, 0x08, 0x6f, 0xf8, 0xa1, 0x42, + 0x30, 0xf0, 0xbe, 0x40, 0x29, 0xf0, 0xb0, 0x15, 0x80, 0x20, 0x81, 0xc3, + 0x82, 0x41, 0xde, 0x0f, 0x2f, 0xf6, 0xa1, 0x42, 0x26, 0xf0, 0x81, 0xc3, + 0x02, 0x40, 0x04, 0xf0, 0x81, 0xc3, 0x22, 0x40, 0x82, 0x41, 0x4a, 0x08, + 0xef, 0xf8, 0xa1, 0x42, 0x1c, 0xf0, 0x28, 0x15, 0x00, 0x20, 0x15, 0xf0, + 0x81, 0xc3, 0x42, 0x40, 0x82, 0x41, 0x02, 0x0f, 0xef, 0xf8, 0xa1, 0x42, + 0x12, 0xf0, 0x81, 0xc3, 0x62, 0x40, 0x82, 0x41, 0x5e, 0x0f, 0xef, 0xf9, + 0xa1, 0x42, 0x0c, 0xf0, 0xcc, 0x15, 0x00, 0x20, 0x03, 0xf0, 0x53, 0x15, + 0x00, 0x26, 0x81, 0xc3, 0x82, 0x41, 0xb2, 0x0a, 0xaf, 0xf0, 0xa1, 0x42, + 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xa9, 0xf1, + 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0x1c, 0x02, 0x20, 0x01, 0x1c, + 0x42, 0x20, 0xd2, 0xc7, 0x89, 0x01, 0x00, 0x04, 0xe8, 0xc3, 0xb4, 0xc1, + 0x10, 0x40, 0xb1, 0x10, 0x80, 0x00, 0x3a, 0xe8, 0x55, 0x20, 0x4d, 0x2a, + 0x2c, 0x8d, 0x2f, 0x09, 0x70, 0x00, 0xb1, 0x18, 0x03, 0x20, 0xc3, 0x40, + 0x13, 0x00, 0xb8, 0x6b, 0x0b, 0x09, 0x90, 0x00, 0x09, 0x09, 0xd0, 0x00, + 0x14, 0xf0, 0x10, 0xe0, 0x56, 0x0e, 0x2f, 0xf8, 0x84, 0xc1, 0x56, 0x20, + 0x00, 0x2b, 0x84, 0xc1, 0xa2, 0x08, 0x6f, 0xed, 0x40, 0xda, 0x40, 0x85, + 0x21, 0x85, 0x02, 0x85, 0xac, 0x1d, 0x80, 0x10, 0xb0, 0x1d, 0x40, 0x10, + 0xb4, 0x1d, 0x00, 0x10, 0x56, 0x20, 0x01, 0x2b, 0x84, 0xc0, 0x40, 0xda, + 0x82, 0x08, 0x6f, 0xed, 0x84, 0xc5, 0x4a, 0x24, 0x00, 0x71, 0x80, 0xc0, + 0xa8, 0x20, 0x80, 0x01, 0x14, 0x15, 0x01, 0x14, 0x04, 0x18, 0x50, 0x00, + 0x55, 0x20, 0x40, 0x2b, 0x80, 0xc1, 0x66, 0x08, 0x6f, 0xed, 0x10, 0xda, + 0xc8, 0xc7, 0xe0, 0x78, 0xe4, 0xc3, 0xa7, 0xc1, 0x08, 0x45, 0x32, 0xe9, + 0xb0, 0xea, 0x4a, 0x24, 0xc0, 0x70, 0x2c, 0x70, 0xa8, 0x20, 0x80, 0x03, + 0x15, 0x25, 0x40, 0x10, 0xa4, 0x10, 0x0c, 0x00, 0x98, 0x10, 0x03, 0x00, + 0x84, 0xc2, 0x35, 0x7a, 0x02, 0x33, 0x00, 0x03, 0x24, 0x71, 0x00, 0xa2, + 0x2a, 0x0a, 0x6f, 0xfb, 0x84, 0xc0, 0xb0, 0x15, 0x81, 0x10, 0x37, 0x09, + 0x94, 0x00, 0x32, 0x21, 0x83, 0x0f, 0x13, 0x00, 0xb3, 0x6b, 0x01, 0x30, + 0x82, 0x0f, 0xfa, 0xc4, 0x00, 0x00, 0x6a, 0x7b, 0x00, 0x30, 0x80, 0x00, + 0x01, 0x30, 0x81, 0x0f, 0x74, 0x49, 0x00, 0x24, 0x48, 0x33, 0x80, 0x00, + 0x04, 0x31, 0x00, 0x80, 0xc5, 0xf6, 0xbe, 0x09, 0x20, 0x04, 0xa1, 0x40, + 0xc4, 0xc7, 0x56, 0x25, 0x00, 0x1b, 0x80, 0xc1, 0x6e, 0x08, 0xa0, 0x04, + 0x80, 0xc6, 0x4a, 0x24, 0x00, 0x71, 0x55, 0x25, 0x41, 0x1b, 0x20, 0x42, + 0xa8, 0x20, 0xc0, 0x02, 0x60, 0x82, 0x04, 0x16, 0x00, 0x14, 0x04, 0x33, + 0x00, 0x80, 0xca, 0x20, 0xc5, 0x00, 0x04, 0x1a, 0x10, 0x00, 0x80, 0xc0, + 0xc2, 0x0f, 0x2f, 0xed, 0x4a, 0x22, 0x00, 0x04, 0x00, 0xc0, 0x4a, 0x24, + 0xc0, 0x70, 0x81, 0xc1, 0xa8, 0x20, 0x00, 0x02, 0x04, 0x11, 0x02, 0x04, + 0x04, 0x32, 0x00, 0x80, 0xca, 0x20, 0x89, 0x00, 0x04, 0x30, 0x80, 0x8f, + 0xc9, 0x36, 0x9c, 0x53, 0x44, 0xf7, 0xb0, 0x1d, 0xc3, 0x10, 0xc4, 0xc7, + 0x04, 0x30, 0x80, 0x8f, 0x38, 0x37, 0xa4, 0x8c, 0x44, 0xf7, 0xb0, 0x1d, + 0x83, 0x10, 0xc4, 0xc7, 0x04, 0x30, 0x80, 0x8f, 0xd3, 0x38, 0xf6, 0xcf, + 0x6f, 0x20, 0x0b, 0x00, 0xb0, 0x1d, 0x02, 0x10, 0xc4, 0xc7, 0xe0, 0x78, + 0xf1, 0xc0, 0x00, 0x43, 0x0c, 0x70, 0x09, 0xe9, 0x87, 0xea, 0x55, 0x23, + 0x40, 0x0c, 0x5e, 0x0f, 0xef, 0xee, 0x55, 0x23, 0x81, 0x09, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xec, 0xc3, 0xac, 0xc1, 0x08, 0x47, 0x2b, 0x80, + 0x0c, 0x80, 0x42, 0x87, 0x43, 0xc1, 0x44, 0xc0, 0x09, 0x6a, 0x2d, 0x87, + 0x7f, 0xdc, 0x48, 0x32, 0x88, 0x00, 0x48, 0x30, 0x8b, 0x00, 0x17, 0xbc, + 0x50, 0x40, 0x2d, 0x0a, 0xb2, 0x00, 0x45, 0xc1, 0x40, 0x27, 0x02, 0x1e, + 0x2c, 0x72, 0x4a, 0x24, 0xc0, 0x70, 0x83, 0xc0, 0xa8, 0x20, 0x40, 0x02, + 0xa0, 0x80, 0x04, 0x12, 0x03, 0x04, 0x01, 0x33, 0x43, 0x03, 0x04, 0x18, + 0xd0, 0x00, 0x12, 0x71, 0x24, 0x71, 0xb3, 0xf6, 0x4a, 0x24, 0xc0, 0x70, + 0x07, 0x34, 0x08, 0x12, 0x07, 0x34, 0xd1, 0x12, 0x4a, 0x21, 0x00, 0x00, + 0xa8, 0x20, 0x40, 0x04, 0x83, 0xc3, 0x35, 0x7b, 0x00, 0x83, 0x15, 0x27, + 0x4c, 0x10, 0x4b, 0x84, 0x00, 0x30, 0x00, 0x10, 0x89, 0xc5, 0x02, 0x32, + 0x02, 0x00, 0x35, 0x7d, 0x24, 0x71, 0x00, 0xa3, 0x40, 0xa5, 0x89, 0xc0, + 0x80, 0xc1, 0xaa, 0x0b, 0x6f, 0xfb, 0x80, 0xc6, 0x5d, 0x08, 0xb2, 0x20, + 0xad, 0x72, 0x4a, 0x24, 0xc0, 0x70, 0x14, 0x25, 0x40, 0x13, 0x4b, 0x68, + 0x4a, 0x20, 0x00, 0x00, 0xa8, 0x20, 0x80, 0x03, 0x83, 0xc1, 0x15, 0x27, + 0x83, 0x10, 0x01, 0x49, 0x8b, 0x83, 0x89, 0xc3, 0x15, 0x7b, 0x02, 0x34, + 0x41, 0x10, 0x04, 0x71, 0x44, 0x71, 0x20, 0xa3, 0x89, 0xc0, 0x86, 0xc1, + 0x6e, 0x0b, 0x6f, 0xfb, 0x40, 0x24, 0x12, 0x36, 0x4a, 0x24, 0xc0, 0x70, + 0x80, 0xc0, 0xa8, 0x20, 0x80, 0x02, 0x40, 0x80, 0x04, 0x12, 0x01, 0x24, + 0x01, 0x31, 0x81, 0x00, 0x04, 0x18, 0x50, 0x00, 0x12, 0x75, 0xb2, 0x07, + 0xeb, 0xff, 0xa5, 0x71, 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0xc0, 0x01, + 0x00, 0x86, 0x00, 0x31, 0x00, 0x20, 0x04, 0x1e, 0x10, 0x10, 0x00, 0xc4, + 0x01, 0xc3, 0x02, 0xc1, 0x00, 0xc0, 0x4c, 0x71, 0x8c, 0x1f, 0x00, 0x13, + 0x90, 0x1f, 0xc0, 0x10, 0x94, 0x1f, 0x40, 0x10, 0x80, 0xc1, 0x41, 0x49, + 0x54, 0x72, 0x4c, 0x72, 0x01, 0x30, 0x40, 0x00, 0xba, 0xf7, 0xcc, 0xc7, + 0xe4, 0xc3, 0xa3, 0xc1, 0x20, 0x42, 0x08, 0x45, 0x80, 0xc1, 0x40, 0x40, + 0x02, 0x0b, 0x6f, 0xfb, 0x80, 0xc6, 0x00, 0xc2, 0x0c, 0x71, 0x2c, 0x71, + 0x23, 0x4e, 0x34, 0x72, 0x2c, 0x72, 0x01, 0x32, 0xc2, 0x00, 0xbc, 0xf7, + 0x25, 0x85, 0x04, 0x32, 0x40, 0x80, 0x47, 0xf7, 0x26, 0x85, 0x04, 0x32, + 0x40, 0x80, 0xc3, 0xf6, 0x0c, 0x70, 0xc4, 0xc7, 0xe6, 0xc3, 0xaa, 0xc1, + 0x84, 0x80, 0x4a, 0x24, 0xc0, 0x70, 0x08, 0x45, 0x28, 0x47, 0x55, 0x20, + 0xce, 0x08, 0x0c, 0x70, 0xa8, 0x20, 0x40, 0x03, 0x04, 0x16, 0x03, 0x14, + 0x40, 0x24, 0x41, 0x39, 0x1a, 0x61, 0x04, 0x33, 0x00, 0x83, 0x04, 0x71, + 0x6f, 0x21, 0x0b, 0x00, 0x20, 0xaa, 0x26, 0x0b, 0xaf, 0xf5, 0x40, 0x24, + 0x40, 0x39, 0x9d, 0x0f, 0x11, 0x10, 0x99, 0x08, 0x30, 0x00, 0x0c, 0x70, + 0x49, 0x85, 0x2a, 0x85, 0x50, 0x71, 0x61, 0x69, 0x40, 0x41, 0xca, 0x21, + 0xcb, 0x00, 0x83, 0x09, 0xa2, 0x00, 0x2a, 0xa5, 0x5c, 0x4d, 0x83, 0xc1, + 0x86, 0x08, 0xaf, 0xf6, 0x83, 0xc7, 0x02, 0x85, 0x4a, 0x24, 0xc0, 0x70, + 0x48, 0x30, 0x81, 0x00, 0xa8, 0x20, 0xc0, 0x01, 0x00, 0x87, 0x07, 0x30, + 0x40, 0x00, 0x04, 0x1f, 0x10, 0x10, 0x4a, 0x24, 0xc0, 0x70, 0x2c, 0x70, + 0xa8, 0x20, 0x80, 0x03, 0x15, 0x25, 0x40, 0x10, 0x83, 0xc2, 0x98, 0x10, + 0x0c, 0x00, 0x23, 0x4a, 0x86, 0xc2, 0x35, 0x7a, 0x02, 0x33, 0x00, 0x03, + 0x24, 0x71, 0x00, 0xa2, 0x86, 0xc0, 0xca, 0x0e, 0x6f, 0xf6, 0x80, 0xc1, + 0x01, 0xc1, 0x00, 0xc0, 0x47, 0x85, 0x02, 0xc3, 0x01, 0x30, 0x40, 0x00, + 0x00, 0x32, 0x81, 0x0f, 0x40, 0x40, 0x00, 0x00, 0x01, 0x30, 0xc0, 0x00, + 0x04, 0x31, 0x00, 0x80, 0x0c, 0x70, 0x49, 0xf7, 0x03, 0xc3, 0x04, 0xc2, + 0x05, 0xc1, 0x0c, 0x71, 0x60, 0xa6, 0x41, 0xa6, 0x22, 0xa6, 0xc6, 0xc7, + 0x0c, 0x70, 0x28, 0x1d, 0x01, 0x10, 0xc6, 0xc7, 0xf6, 0xc3, 0x82, 0x24, + 0x11, 0x31, 0x50, 0x42, 0x10, 0x40, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, + 0x44, 0x01, 0x8a, 0x22, 0x0c, 0x00, 0x12, 0x0d, 0x2f, 0xed, 0x28, 0x45, + 0x06, 0x40, 0x40, 0x24, 0x83, 0x37, 0x40, 0x24, 0x04, 0x39, 0x56, 0x24, + 0x05, 0x3a, 0x40, 0x24, 0x06, 0x38, 0x40, 0x24, 0xc7, 0x37, 0xa1, 0x41, + 0x42, 0x42, 0x1e, 0x09, 0x6f, 0xf4, 0x1e, 0x1c, 0xc3, 0x32, 0x24, 0x14, + 0x11, 0x30, 0x36, 0x70, 0xcb, 0xf4, 0x1f, 0x14, 0x8d, 0x30, 0x56, 0x20, + 0x97, 0x2a, 0x55, 0x20, 0x53, 0x2a, 0x56, 0x20, 0x16, 0x2b, 0x55, 0x20, + 0xce, 0x28, 0x55, 0x20, 0x8f, 0x29, 0x55, 0x20, 0x15, 0x2d, 0x40, 0x20, + 0x14, 0x2b, 0x2e, 0x70, 0x2c, 0x70, 0x34, 0x70, 0xb7, 0xf4, 0x1e, 0x14, + 0x81, 0x30, 0xaf, 0x78, 0x30, 0x70, 0x66, 0x01, 0x2d, 0x00, 0x04, 0x77, + 0x8a, 0xe0, 0x1e, 0x01, 0x0d, 0x00, 0x25, 0x20, 0x00, 0x00, 0x0c, 0xf0, + 0x26, 0xf0, 0x32, 0xf0, 0x3a, 0xf0, 0x44, 0xf0, 0x51, 0xf0, 0x60, 0xf0, + 0x68, 0xf0, 0x76, 0xf0, 0x8d, 0xf0, 0x97, 0xf0, 0x00, 0x24, 0x80, 0x3f, + 0x00, 0x00, 0x44, 0x01, 0x88, 0xc1, 0x76, 0x0b, 0xaf, 0xf8, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0xc3, 0x43, 0x7a, 0x44, 0x00, 0x00, + 0x46, 0xc3, 0x00, 0x1b, 0x80, 0x20, 0x04, 0x1b, 0x40, 0x20, 0x08, 0x1b, + 0x00, 0x20, 0x43, 0xc2, 0x44, 0xc1, 0x45, 0xc0, 0x83, 0xc1, 0x10, 0xda, + 0xe2, 0x40, 0x63, 0xf0, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0x44, 0x01, + 0x88, 0xc1, 0x9e, 0x0b, 0x2f, 0xf8, 0x8a, 0xc2, 0x8a, 0xc1, 0x40, 0xda, + 0xc2, 0x40, 0x57, 0xf0, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0x44, 0x01, + 0xc6, 0x0d, 0x6f, 0xf0, 0x88, 0xc1, 0x0c, 0x18, 0x00, 0x20, 0x4f, 0xf0, + 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0x44, 0x01, 0xa2, 0x0a, 0x2f, 0xf6, + 0x88, 0xc1, 0xb0, 0x18, 0x02, 0x20, 0x45, 0xf0, 0x00, 0x24, 0x80, 0x3f, + 0x00, 0x00, 0x44, 0x01, 0x88, 0xc1, 0xfe, 0x0a, 0xaf, 0xf8, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x40, 0xa6, 0x21, 0xa6, 0x02, 0xa6, + 0x35, 0xf0, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0x44, 0x01, 0x88, 0xc1, + 0xde, 0x0a, 0xaf, 0xf8, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, + 0x40, 0xa7, 0x21, 0xa7, 0x02, 0xa7, 0x27, 0xf0, 0x00, 0x24, 0x80, 0x3f, + 0x00, 0x00, 0x44, 0x01, 0x62, 0x0d, 0x6f, 0xf0, 0x88, 0xc1, 0x28, 0x18, + 0x00, 0x20, 0x1d, 0xf0, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0x44, 0x01, + 0x88, 0xc1, 0x7a, 0x09, 0xef, 0xf8, 0x55, 0x24, 0x02, 0x3e, 0x55, 0x24, + 0x01, 0x3e, 0x60, 0xda, 0x82, 0x40, 0x0d, 0xf0, 0x00, 0x24, 0x80, 0x3f, + 0x00, 0x00, 0x44, 0x01, 0x88, 0xc1, 0xca, 0x09, 0xef, 0xf9, 0x9a, 0xc2, + 0x9a, 0xc1, 0x78, 0xda, 0xa2, 0x40, 0x92, 0x0b, 0x0f, 0xed, 0x08, 0xc0, + 0x8a, 0x21, 0x3e, 0x06, 0x52, 0x70, 0xca, 0x21, 0x4d, 0x20, 0x3c, 0x22, + 0x01, 0x20, 0x3d, 0x22, 0x00, 0x20, 0x1d, 0x65, 0x5d, 0xf1, 0x00, 0x24, + 0x80, 0x3f, 0x00, 0x00, 0x44, 0x01, 0x02, 0x0d, 0x6f, 0xf0, 0x88, 0xc1, + 0xcc, 0x18, 0x00, 0x20, 0xeb, 0xf1, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, + 0x44, 0x01, 0xee, 0x0c, 0x6f, 0xf0, 0x88, 0xc1, 0x53, 0x18, 0x18, 0x20, + 0xe1, 0xf1, 0x22, 0x40, 0xd6, 0xc7, 0xe0, 0x78, 0x48, 0x31, 0x01, 0x00, + 0xcb, 0x44, 0x83, 0x3a, 0x6f, 0x12, 0x07, 0x36, 0x48, 0x70, 0x48, 0x47, + 0x00, 0x00, 0x21, 0x80, 0x6d, 0x70, 0x48, 0x31, 0x81, 0x00, 0x00, 0x30, + 0x41, 0x10, 0x00, 0x31, 0x01, 0x03, 0x04, 0x31, 0xc0, 0x82, 0xc7, 0xf6, + 0x01, 0x31, 0x81, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x31, + 0x81, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x50, 0x90, 0x48, 0x31, 0xc1, 0x02, + 0x48, 0x31, 0x83, 0x00, 0x48, 0x32, 0x01, 0x00, 0x00, 0x30, 0x41, 0x10, + 0x48, 0x33, 0xc2, 0x02, 0x00, 0x31, 0x01, 0x03, 0x49, 0x22, 0x02, 0x02, + 0x48, 0x22, 0x02, 0x01, 0x04, 0x31, 0xc0, 0x82, 0x42, 0xa0, 0xc7, 0xf6, + 0x01, 0x31, 0x81, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x31, + 0x81, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x31, 0xc1, 0x02, 0x48, 0x31, + 0x81, 0x00, 0x48, 0x31, 0xc1, 0x02, 0x49, 0x21, 0x41, 0x06, 0x48, 0x21, + 0x01, 0x01, 0xe0, 0x7f, 0x29, 0xa0, 0xe0, 0x78, 0xf4, 0xc3, 0x82, 0x24, + 0x02, 0x3a, 0x50, 0x46, 0x08, 0x45, 0x55, 0x20, 0x0e, 0x08, 0x55, 0x24, + 0x80, 0x39, 0x10, 0xda, 0x0a, 0x23, 0x80, 0x21, 0x0a, 0x25, 0x40, 0x21, + 0x0a, 0x22, 0x00, 0x21, 0x70, 0x41, 0x30, 0x40, 0x92, 0x0a, 0x2f, 0xed, + 0x55, 0x24, 0x8f, 0x39, 0x4a, 0x24, 0xc0, 0x70, 0x0a, 0x21, 0x80, 0x0f, + 0xfa, 0x44, 0x00, 0x00, 0x4f, 0x21, 0xc3, 0x07, 0xa8, 0x20, 0x00, 0x04, + 0x04, 0x10, 0x0c, 0x24, 0x20, 0x40, 0x60, 0x42, 0x04, 0x34, 0x40, 0x90, + 0xca, 0x20, 0x05, 0x03, 0x04, 0x30, 0xc0, 0x80, 0xca, 0x22, 0x09, 0x00, + 0x04, 0x1f, 0x90, 0x10, 0x2c, 0x70, 0x47, 0xc0, 0x94, 0xc0, 0x18, 0xda, + 0x28, 0x47, 0x00, 0x1b, 0x42, 0x20, 0x00, 0x1a, 0x40, 0x20, 0x8e, 0x08, + 0x2f, 0xfb, 0x00, 0x1d, 0x40, 0x20, 0x4a, 0x24, 0xc0, 0x70, 0x55, 0x24, + 0x81, 0x39, 0x8e, 0xc0, 0x51, 0xc7, 0xa8, 0x20, 0xc0, 0x02, 0x04, 0x11, + 0x02, 0x04, 0x00, 0x32, 0x94, 0x0f, 0x20, 0x3c, 0x12, 0xac, 0x04, 0x18, + 0x10, 0x05, 0x10, 0x86, 0x3c, 0x16, 0x81, 0x10, 0x38, 0x14, 0x10, 0x30, + 0x04, 0x71, 0x05, 0x21, 0x41, 0x04, 0x0f, 0xc7, 0x10, 0xa6, 0x79, 0x21, + 0x00, 0x00, 0x3c, 0x1e, 0x02, 0x10, 0x6a, 0x0d, 0xaf, 0xee, 0x8e, 0xc0, + 0x4a, 0x24, 0xc0, 0x70, 0x00, 0x34, 0x08, 0x25, 0x00, 0x37, 0xcc, 0x13, + 0x00, 0x30, 0x03, 0x24, 0x40, 0x24, 0x0b, 0x3e, 0x8e, 0xc1, 0x47, 0xc0, + 0xa8, 0x20, 0xc0, 0x01, 0x40, 0x81, 0x00, 0x30, 0x82, 0x00, 0x04, 0x19, + 0x90, 0x00, 0x01, 0x33, 0x00, 0x03, 0x8e, 0x86, 0x01, 0x30, 0x00, 0x02, + 0x46, 0x85, 0x2f, 0x31, 0x00, 0x20, 0x07, 0x85, 0x28, 0x85, 0x4a, 0x24, + 0xc0, 0x70, 0x02, 0x36, 0x03, 0x73, 0x80, 0x3f, 0x00, 0x00, 0x42, 0xc0, + 0x0d, 0x70, 0x4a, 0x20, 0x00, 0x00, 0x41, 0xc2, 0x43, 0xc1, 0x47, 0xc3, + 0xa8, 0x20, 0x00, 0x04, 0x81, 0xc7, 0x01, 0x4f, 0xf0, 0x23, 0x02, 0x10, + 0x00, 0x33, 0x49, 0x00, 0x00, 0x34, 0x81, 0x10, 0x15, 0x25, 0x02, 0x10, + 0x01, 0x31, 0x41, 0x02, 0x04, 0x71, 0x26, 0xa2, 0x46, 0x85, 0x27, 0x85, + 0x08, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x1c, 0x1c, 0x00, 0x32, 0x41, 0xc2, + 0x42, 0xc1, 0x43, 0xc0, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x17, 0x01, 0x14, + 0x04, 0x13, 0x00, 0x14, 0x00, 0x30, 0x40, 0x00, 0x01, 0x30, 0x08, 0x10, + 0x27, 0x85, 0x08, 0x85, 0x46, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x0e, 0x70, + 0x42, 0xc1, 0x43, 0xc0, 0x45, 0xc1, 0x46, 0xc0, 0x84, 0xc4, 0x8e, 0xc7, + 0x8e, 0xc1, 0x84, 0xc0, 0x0a, 0x23, 0x00, 0x14, 0x1c, 0x1c, 0x00, 0x32, + 0x41, 0xc2, 0x44, 0xc2, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x10, 0x03, 0x04, + 0x04, 0x11, 0x02, 0x04, 0x00, 0x32, 0xc2, 0x00, 0x01, 0x33, 0x8b, 0x10, + 0x08, 0x85, 0x46, 0x85, 0x27, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x46, 0xc0, + 0x4a, 0x20, 0x00, 0x00, 0x28, 0x1c, 0x00, 0x34, 0x44, 0xc2, 0x45, 0xc1, + 0xa8, 0x20, 0xc0, 0x04, 0x81, 0xc1, 0x03, 0x4c, 0x02, 0x49, 0x01, 0x4f, + 0x00, 0x33, 0xc3, 0x10, 0x04, 0x71, 0x00, 0x30, 0x82, 0x10, 0x02, 0x31, + 0xc3, 0x00, 0x02, 0x31, 0x81, 0x00, 0x00, 0x31, 0xc1, 0x00, 0x01, 0x30, + 0x50, 0x20, 0x5f, 0x85, 0x20, 0x86, 0x01, 0x86, 0x9e, 0x85, 0x61, 0x85, + 0x49, 0xc2, 0x4c, 0xc1, 0x4d, 0xc0, 0x88, 0xc0, 0x8c, 0xc1, 0x40, 0x24, + 0x04, 0x3b, 0x40, 0x24, 0x05, 0x3a, 0x22, 0x42, 0x48, 0xc4, 0x3e, 0x0e, + 0x6f, 0xf8, 0x28, 0x1c, 0x00, 0x34, 0x28, 0x14, 0x0b, 0x30, 0x64, 0x86, + 0x45, 0x86, 0x26, 0x86, 0x07, 0x86, 0xe2, 0x86, 0x83, 0x86, 0x04, 0x1d, + 0xc0, 0x12, 0x43, 0xc3, 0x44, 0xc2, 0x45, 0xc1, 0x46, 0xc0, 0x40, 0x25, + 0x03, 0x12, 0x81, 0xc0, 0x84, 0xc1, 0x54, 0x24, 0x84, 0x39, 0x40, 0x24, + 0x05, 0x38, 0x22, 0x42, 0x41, 0xc7, 0x56, 0x0a, 0x6f, 0xf6, 0x42, 0xc4, + 0x20, 0x14, 0x08, 0x30, 0x24, 0x14, 0x0b, 0x30, 0x6a, 0x86, 0x4b, 0x86, + 0x2c, 0x86, 0x0d, 0x86, 0xe8, 0x86, 0x89, 0x86, 0x08, 0x1d, 0x00, 0x12, + 0x0c, 0x1d, 0xc0, 0x12, 0x43, 0xc3, 0x44, 0xc2, 0x45, 0xc1, 0x46, 0xc0, + 0x40, 0x25, 0x03, 0x14, 0x81, 0xc0, 0x84, 0xc1, 0x54, 0x24, 0x04, 0x39, + 0x40, 0x24, 0x05, 0x38, 0x22, 0x42, 0x41, 0xc7, 0x16, 0x0a, 0x6f, 0xf6, + 0x42, 0xc4, 0x2f, 0x30, 0x00, 0x14, 0x08, 0xc2, 0x0b, 0x85, 0x09, 0xc1, + 0x8d, 0x70, 0x4a, 0x24, 0xc0, 0x70, 0x04, 0x30, 0x00, 0xa3, 0x01, 0x1c, + 0x43, 0x30, 0x44, 0xa5, 0x7d, 0x20, 0xc3, 0x00, 0x7d, 0x20, 0x82, 0x00, + 0x68, 0x4d, 0x25, 0xa5, 0x03, 0x1c, 0xc2, 0x30, 0xca, 0x20, 0x05, 0x14, + 0x02, 0x1c, 0x82, 0x30, 0xa8, 0x20, 0x40, 0x04, 0x40, 0x24, 0x49, 0x30, + 0x33, 0x21, 0x01, 0x13, 0x85, 0x71, 0x48, 0x31, 0x8b, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x30, 0xcb, 0x12, 0x01, 0x31, 0xc1, 0x02, 0x18, 0x18, + 0x50, 0x00, 0x13, 0xc0, 0x4a, 0x24, 0xc0, 0x70, 0x03, 0x1c, 0xc2, 0x30, + 0x00, 0x30, 0x0b, 0x00, 0x54, 0x25, 0x00, 0x18, 0x02, 0x1c, 0x82, 0x30, + 0x01, 0x1c, 0x43, 0x30, 0xa8, 0x20, 0x40, 0x03, 0x01, 0x11, 0xc1, 0x14, + 0x48, 0x31, 0x8c, 0x00, 0x20, 0x80, 0x00, 0x33, 0x0c, 0x13, 0x01, 0x31, + 0x01, 0x03, 0x18, 0x18, 0x50, 0x00, 0x12, 0xc0, 0x4a, 0x24, 0xc0, 0x70, + 0x8d, 0x70, 0x00, 0x30, 0x08, 0x00, 0x7c, 0x4d, 0x03, 0x1c, 0xc2, 0x30, + 0x02, 0x1c, 0x82, 0x30, 0x01, 0x1c, 0x43, 0x30, 0xa8, 0x20, 0x00, 0x04, + 0x40, 0x24, 0x49, 0x30, 0x33, 0x21, 0x01, 0x13, 0x85, 0x71, 0x48, 0x31, + 0x8b, 0x00, 0x20, 0x80, 0x00, 0x30, 0xcb, 0x12, 0x01, 0x31, 0xc1, 0x02, + 0x18, 0x18, 0x50, 0x00, 0x0b, 0xc4, 0x4a, 0x24, 0xc0, 0x70, 0x78, 0x4d, + 0x00, 0x34, 0x08, 0x13, 0x03, 0x1c, 0xc2, 0x30, 0x02, 0x1c, 0x82, 0x30, + 0x01, 0x1c, 0x43, 0x30, 0xa8, 0x20, 0x40, 0x03, 0x01, 0x11, 0xc1, 0x14, + 0x48, 0x31, 0x8b, 0x00, 0x20, 0x80, 0x00, 0x30, 0xcb, 0x12, 0x01, 0x31, + 0xc1, 0x02, 0x18, 0x18, 0x50, 0x00, 0x0a, 0x85, 0x30, 0x86, 0x02, 0x1c, + 0x82, 0x30, 0x02, 0x31, 0x02, 0x20, 0x4a, 0x24, 0xc0, 0x70, 0x7d, 0x21, + 0x80, 0x00, 0x00, 0x32, 0x8b, 0x00, 0x01, 0x1c, 0x02, 0x30, 0x54, 0x25, + 0x80, 0x18, 0x4c, 0x70, 0x03, 0x1c, 0xc2, 0x30, 0xa8, 0x20, 0x00, 0x04, + 0x40, 0x24, 0x41, 0x30, 0x33, 0x21, 0x81, 0x00, 0x44, 0x71, 0x48, 0x31, + 0x83, 0x00, 0x20, 0x80, 0x00, 0x33, 0xc3, 0x10, 0x01, 0x31, 0xc1, 0x00, + 0x18, 0x18, 0x50, 0x00, 0x8a, 0xc0, 0xd2, 0x09, 0x6f, 0xf6, 0x4a, 0xc4, + 0x09, 0x85, 0x47, 0xc0, 0xc6, 0x09, 0x6f, 0xf6, 0x87, 0xc0, 0x07, 0xc1, + 0x0a, 0xc0, 0x2c, 0x15, 0x10, 0x10, 0xf0, 0x86, 0x02, 0x30, 0x40, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0x7d, 0x20, 0xc3, 0x20, 0x7d, 0x20, 0x82, 0x20, + 0x7d, 0x27, 0x8c, 0x10, 0x03, 0x1c, 0xc2, 0x30, 0x02, 0x1c, 0x82, 0x30, + 0x50, 0x20, 0xc2, 0x07, 0x6c, 0x4d, 0x6c, 0x70, 0x01, 0x1c, 0x02, 0x33, + 0xa8, 0x20, 0x00, 0x04, 0x40, 0x24, 0x41, 0x30, 0x33, 0x21, 0xc1, 0x00, + 0x64, 0x71, 0x48, 0x31, 0x8c, 0x00, 0x20, 0x80, 0x00, 0x32, 0x0c, 0x03, + 0x01, 0x31, 0x01, 0x03, 0x18, 0x18, 0x50, 0x00, 0x48, 0x37, 0x00, 0x10, + 0xc3, 0x41, 0x48, 0x42, 0x00, 0x00, 0xda, 0x0c, 0x6f, 0xf8, 0x47, 0xc0, + 0x50, 0x20, 0xfe, 0x87, 0x57, 0xf4, 0x40, 0x20, 0x40, 0x20, 0xa7, 0x08, + 0x34, 0x01, 0x0b, 0xa5, 0x16, 0x09, 0x4f, 0xf6, 0x19, 0x08, 0xf5, 0x00, + 0xed, 0x70, 0x03, 0xb8, 0x04, 0x20, 0x80, 0x0f, 0xff, 0x00, 0xf8, 0xff, + 0x01, 0x2e, 0x0f, 0x70, 0x0c, 0x00, 0x12, 0x06, 0x18, 0xda, 0x40, 0x40, + 0xf5, 0x78, 0x0f, 0x79, 0xb9, 0x61, 0x55, 0x24, 0x00, 0x38, 0x66, 0x0e, + 0xef, 0xec, 0x55, 0x24, 0x10, 0x38, 0x4a, 0x24, 0x80, 0x71, 0x2f, 0x27, + 0xc7, 0x13, 0x9a, 0xc0, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x10, 0x01, 0x24, + 0x00, 0x31, 0x81, 0x0f, 0xda, 0x3b, 0x0e, 0x74, 0x04, 0x18, 0x50, 0x00, + 0x9a, 0xc0, 0x94, 0xc1, 0xee, 0x09, 0xef, 0xed, 0x54, 0x24, 0x10, 0x3a, + 0x3c, 0x16, 0x80, 0x10, 0x10, 0xe8, 0x4a, 0x24, 0x80, 0x71, 0x0c, 0x70, + 0xa8, 0x20, 0xc0, 0x02, 0x33, 0x20, 0x81, 0x0f, 0x13, 0x00, 0xd8, 0x6b, + 0x04, 0x71, 0x48, 0x31, 0x81, 0x00, 0x04, 0x18, 0x50, 0x20, 0x04, 0xf0, + 0x64, 0x1c, 0x01, 0x30, 0x94, 0xc1, 0x91, 0xc3, 0x42, 0x42, 0x22, 0x0a, + 0x6f, 0xee, 0xa1, 0x40, 0x15, 0x25, 0xc0, 0x13, 0x18, 0xe0, 0x2c, 0x70, + 0x3a, 0x0c, 0xef, 0xfa, 0x18, 0xda, 0xbc, 0x1d, 0x03, 0x10, 0x0b, 0xc0, + 0x28, 0x1d, 0x40, 0x14, 0x09, 0xa5, 0xd2, 0x09, 0x6f, 0xf7, 0x46, 0x40, + 0x27, 0xe8, 0x80, 0xd8, 0x00, 0x1b, 0x02, 0x20, 0x11, 0xc0, 0xf0, 0x16, + 0x02, 0x10, 0x2c, 0x70, 0x48, 0x30, 0x80, 0x00, 0x47, 0xc2, 0x00, 0x30, + 0x80, 0x0f, 0x74, 0x49, 0x00, 0x24, 0x07, 0x30, 0x80, 0x00, 0x04, 0x30, + 0x40, 0x80, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, + 0xc0, 0x02, 0x48, 0x30, 0x80, 0x00, 0x48, 0x30, 0xc0, 0x02, 0xc2, 0x70, + 0x00, 0x1d, 0x00, 0x20, 0xd4, 0xc7, 0x00, 0x13, 0xc0, 0x20, 0xb9, 0x08, + 0x12, 0x80, 0xd4, 0xc7, 0xe2, 0xc0, 0x47, 0xdd, 0x4a, 0x24, 0xc0, 0x70, + 0x18, 0xbd, 0xcb, 0x44, 0xa3, 0x42, 0x0b, 0xd7, 0xc3, 0x43, 0xd3, 0x3e, + 0x98, 0xdd, 0xc3, 0x42, 0x3b, 0x4a, 0xc1, 0xbf, 0xc3, 0x41, 0xdc, 0x44, + 0x30, 0x4e, 0x35, 0x18, 0x03, 0x02, 0xac, 0xa0, 0x8b, 0xa0, 0x6a, 0xa0, + 0x47, 0xa0, 0x26, 0xa0, 0x0a, 0x21, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x19, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x19, 0x11, 0x00, 0x34, 0x18, 0x03, 0x00, 0x20, 0x18, 0x03, 0x00, + 0xc2, 0xc4, 0xe0, 0x78, 0xea, 0xc3, 0xa7, 0xc1, 0x4a, 0x24, 0xc0, 0x70, + 0x68, 0x40, 0x48, 0x46, 0x28, 0x43, 0x08, 0x45, 0x0c, 0x70, 0x84, 0xc4, + 0xa8, 0x20, 0xc0, 0x02, 0x02, 0x4d, 0xf0, 0x23, 0x01, 0x10, 0x15, 0x24, + 0x03, 0x10, 0x04, 0x71, 0x02, 0x31, 0x81, 0x00, 0x20, 0xa3, 0x49, 0x85, + 0x4a, 0x24, 0xc0, 0x70, 0x81, 0xc3, 0x81, 0xc0, 0xa8, 0x20, 0x00, 0x02, + 0x04, 0x14, 0x01, 0x14, 0x00, 0x32, 0x41, 0x00, 0x04, 0x18, 0x50, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0x0a, 0x20, 0x40, 0x03, 0xa8, 0x20, 0x40, 0x02, + 0x40, 0x80, 0x04, 0x13, 0x01, 0x04, 0x01, 0x31, 0x81, 0x00, 0x04, 0x18, + 0x50, 0x00, 0x09, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x2d, 0x70, 0x02, 0x36, + 0x06, 0x70, 0x80, 0x3f, 0x00, 0x00, 0x0c, 0x70, 0xa8, 0x20, 0x40, 0x04, + 0x84, 0xc1, 0x81, 0xc3, 0x15, 0x23, 0x02, 0x00, 0x07, 0x49, 0x15, 0x25, + 0x01, 0x10, 0x80, 0x82, 0x23, 0x81, 0x04, 0x71, 0x00, 0x34, 0xcc, 0x13, + 0x01, 0x31, 0x01, 0x03, 0x20, 0xa2, 0x4a, 0x24, 0xc0, 0x70, 0x0c, 0x70, + 0xa8, 0x20, 0x80, 0x02, 0x01, 0x4b, 0x15, 0x25, 0x02, 0x10, 0x04, 0x71, + 0x00, 0x36, 0x41, 0x00, 0x0c, 0x1a, 0x40, 0x00, 0x4a, 0x24, 0xc0, 0x70, + 0xa8, 0x20, 0x40, 0x02, 0x15, 0x25, 0x40, 0x12, 0x03, 0x80, 0x15, 0x20, + 0x41, 0x12, 0x25, 0x71, 0x00, 0xa1, 0x84, 0xc1, 0x61, 0x40, 0xd2, 0x0d, + 0x2f, 0xf6, 0x84, 0xc7, 0x8c, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x0c, 0x70, + 0xa8, 0x20, 0x80, 0x03, 0x04, 0x17, 0x03, 0x14, 0x2c, 0x70, 0x40, 0x24, + 0x42, 0x30, 0x04, 0x33, 0x00, 0x83, 0x1a, 0x62, 0x04, 0x71, 0xca, 0x21, + 0x69, 0x00, 0x20, 0xaa, 0x1a, 0x0b, 0x6f, 0xf5, 0x40, 0x24, 0x40, 0x30, + 0x67, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x10, 0x40, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0xc0, 0x03, 0x15, 0x25, 0x02, 0x10, 0xe3, 0x82, 0x2c, 0x70, + 0x40, 0x24, 0x4c, 0x30, 0x04, 0x37, 0xc0, 0x90, 0x1a, 0x64, 0x04, 0x71, + 0xca, 0x21, 0x6a, 0x00, 0x20, 0xaa, 0xea, 0x0a, 0x6f, 0xf5, 0x40, 0x24, + 0x40, 0x30, 0x66, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x08, 0x47, 0x0c, 0x70, + 0xa8, 0x20, 0x00, 0x04, 0x15, 0x25, 0x02, 0x10, 0x0c, 0x12, 0x0b, 0x00, + 0x2c, 0x70, 0x40, 0x24, 0x4c, 0x30, 0x04, 0x33, 0xc0, 0x90, 0x1a, 0x64, + 0x04, 0x71, 0xca, 0x21, 0x69, 0x00, 0x20, 0xaa, 0xb6, 0x0a, 0x6f, 0xf5, + 0x40, 0x24, 0x40, 0x30, 0x04, 0xe8, 0x34, 0x1d, 0x03, 0x10, 0x0f, 0xf0, + 0x34, 0x15, 0x80, 0x10, 0x35, 0x15, 0x81, 0x10, 0x04, 0x71, 0x0f, 0x7a, + 0x0b, 0x09, 0x85, 0x00, 0x34, 0x1d, 0x42, 0x10, 0x03, 0xf0, 0x34, 0x1d, + 0x02, 0x10, 0x84, 0xc1, 0xa1, 0x40, 0x79, 0x27, 0x0f, 0x10, 0x12, 0x0d, + 0x2f, 0xf6, 0x40, 0x24, 0x11, 0x34, 0x8b, 0x85, 0x4a, 0x24, 0xc0, 0x70, + 0x4a, 0x20, 0x00, 0x00, 0xa8, 0x20, 0x80, 0x03, 0x04, 0x11, 0x03, 0x24, + 0x2c, 0x70, 0x40, 0x24, 0x42, 0x30, 0x04, 0x33, 0x00, 0x83, 0x1a, 0x62, + 0x04, 0x71, 0xca, 0x21, 0x69, 0x00, 0x20, 0xaa, 0x56, 0x0a, 0x6f, 0xf5, + 0x40, 0x24, 0x40, 0x30, 0x05, 0x20, 0x3e, 0x84, 0x07, 0xf4, 0x35, 0x15, + 0x81, 0x10, 0x34, 0x15, 0x80, 0x10, 0x09, 0x08, 0x45, 0x00, 0x82, 0xbf, + 0x50, 0x27, 0x40, 0x10, 0x16, 0x70, 0xcf, 0x20, 0x62, 0x00, 0x00, 0xae, + 0x20, 0x15, 0x81, 0x10, 0x0f, 0x09, 0x00, 0x00, 0x20, 0x1d, 0x02, 0x10, + 0x00, 0x8e, 0x87, 0xb8, 0x00, 0xae, 0xca, 0xc7, 0x4a, 0x24, 0xc0, 0x70, + 0x0a, 0x21, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x19, 0x11, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x19, 0x11, 0x00, + 0x34, 0x18, 0x03, 0x00, 0xe0, 0x7f, 0x20, 0x18, 0x03, 0x00, 0xe0, 0x78, + 0xc3, 0x40, 0xa0, 0x00, 0xe0, 0x86, 0x00, 0x80, 0x2c, 0x70, 0x4c, 0x70, + 0x05, 0x07, 0xef, 0xfc, 0x6c, 0x70, 0xe0, 0x78, 0xe2, 0xc2, 0xcb, 0x45, + 0xa0, 0x00, 0xbc, 0x86, 0x21, 0x85, 0xc3, 0x40, 0xa0, 0x00, 0x7c, 0x6e, + 0x00, 0x80, 0x24, 0x77, 0x1a, 0x0c, 0x2f, 0xfd, 0x21, 0xa5, 0x00, 0x1d, + 0x03, 0x10, 0xc2, 0xc6, 0xe4, 0xc2, 0xcb, 0x45, 0xa0, 0x00, 0xf4, 0xc7, + 0x08, 0x46, 0x58, 0x25, 0xc3, 0x19, 0x0c, 0xd8, 0x1c, 0xd9, 0x8c, 0x70, + 0x4a, 0x0d, 0xef, 0xfc, 0xa1, 0x42, 0xc3, 0x41, 0xa0, 0x00, 0xc4, 0x86, + 0x00, 0xa1, 0x56, 0x25, 0x85, 0x1a, 0x57, 0x25, 0x86, 0x1a, 0xc3, 0x40, + 0x12, 0x00, 0x3c, 0x97, 0xc3, 0x41, 0x13, 0x00, 0x28, 0x90, 0x8a, 0x22, + 0x18, 0x00, 0x8a, 0x24, 0x42, 0x00, 0x5e, 0x0a, 0xaf, 0xfe, 0xc1, 0x43, + 0xc3, 0x41, 0xa0, 0x00, 0x7c, 0x6e, 0x00, 0xa1, 0xc4, 0xc6, 0xe0, 0x78, + 0xe4, 0xc3, 0xa1, 0xc1, 0x2c, 0x77, 0x80, 0xc2, 0x0c, 0x70, 0xda, 0x0b, + 0x2f, 0xfd, 0x20, 0x43, 0x14, 0xe8, 0xcb, 0x45, 0xa0, 0x00, 0xe0, 0x86, + 0x00, 0x85, 0x2c, 0x70, 0x4c, 0x77, 0x16, 0x0d, 0xef, 0xfc, 0x6c, 0x70, + 0x7a, 0xe8, 0xc3, 0x41, 0xa0, 0x00, 0xbc, 0x86, 0x00, 0x89, 0x08, 0xe8, + 0x00, 0xc6, 0x00, 0x19, 0x03, 0x00, 0x0b, 0xf0, 0xcd, 0x70, 0x09, 0xf0, + 0x00, 0x85, 0x2c, 0x70, 0x4c, 0x70, 0x6c, 0x70, 0x4a, 0x0e, 0xef, 0xfc, + 0xcd, 0x70, 0xc1, 0x40, 0xc4, 0xc7, 0xe0, 0x78, 0x50, 0x21, 0xcc, 0x07, + 0x02, 0x21, 0x03, 0x83, 0x15, 0x0c, 0x23, 0x10, 0x43, 0x22, 0x01, 0x80, + 0x00, 0x23, 0x83, 0x8f, 0x00, 0x80, 0x00, 0x00, 0x81, 0x21, 0xff, 0x8f, + 0xe0, 0x7f, 0x65, 0x78, 0xe2, 0xc3, 0xa1, 0xc1, 0x8e, 0x0f, 0xcf, 0xff, + 0x7e, 0xe8, 0xb4, 0xd9, 0xc3, 0x40, 0xf0, 0x00, 0x4b, 0x00, 0xc3, 0x42, + 0xa0, 0x00, 0xd4, 0xc1, 0x20, 0xa8, 0x00, 0x8a, 0x05, 0xe8, 0x01, 0x82, + 0x04, 0x71, 0x01, 0xa2, 0xf0, 0xf1, 0xc3, 0x40, 0xa0, 0x00, 0x8c, 0x86, + 0x2c, 0x72, 0x4c, 0x70, 0x6c, 0x70, 0xdb, 0x59, 0xda, 0x0e, 0xef, 0xff, + 0x08, 0x45, 0x00, 0x16, 0x80, 0x70, 0xa0, 0x00, 0xb8, 0x86, 0xc5, 0x08, + 0x9e, 0x80, 0x03, 0x1c, 0x03, 0x30, 0x02, 0x1c, 0x42, 0x33, 0x01, 0x1c, + 0x03, 0x32, 0x3b, 0x58, 0x00, 0x42, 0x20, 0x43, 0x40, 0x24, 0x41, 0x30, + 0xfe, 0xd8, 0xe2, 0x0a, 0x6f, 0xfb, 0x8c, 0x70, 0xd0, 0xf1, 0xe0, 0x78, + 0xf1, 0xc0, 0xa1, 0xc1, 0x09, 0xe8, 0x22, 0x81, 0x20, 0x81, 0x60, 0xc1, + 0x3a, 0x09, 0x6f, 0xfb, 0x80, 0xc1, 0x0c, 0x70, 0x02, 0xf0, 0x23, 0xd8, + 0x87, 0x74, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0xa1, 0xc1, + 0x08, 0xe8, 0x3a, 0x80, 0x60, 0xc1, 0x1e, 0x09, 0x6f, 0xfb, 0x80, 0xc1, + 0x0c, 0x70, 0x03, 0xf0, 0x23, 0xd8, 0x87, 0x74, 0xd1, 0xc0, 0xe0, 0x7e, + 0xf1, 0xc0, 0x6e, 0x08, 0x00, 0x00, 0xd1, 0xc0, 0xe0, 0x7f, 0x0c, 0x70, + 0xe2, 0xc0, 0x4a, 0x24, 0x00, 0x77, 0x8d, 0x70, 0xcb, 0x45, 0xa0, 0x00, + 0x08, 0xc2, 0x89, 0x43, 0x0a, 0x23, 0x80, 0x0f, 0xa0, 0x00, 0xa0, 0xc4, + 0xa8, 0x20, 0x00, 0x04, 0x5a, 0x23, 0x01, 0x16, 0xc3, 0x42, 0x06, 0x01, + 0xff, 0x00, 0x65, 0x71, 0x38, 0x65, 0x42, 0xa0, 0x04, 0x18, 0xc1, 0x02, + 0x38, 0x4b, 0x1a, 0x61, 0xb8, 0x61, 0x40, 0xa0, 0x4a, 0x24, 0x80, 0x71, + 0xc3, 0x40, 0xa0, 0x00, 0xa8, 0x86, 0x82, 0xb0, 0x80, 0xa0, 0x60, 0x40, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, 0x0c, 0x1b, 0xc1, 0x00, + 0x14, 0x1b, 0x41, 0x00, 0x0c, 0x70, 0x04, 0x1b, 0x81, 0x00, 0xc2, 0xc4, + 0xc3, 0x43, 0xa0, 0x00, 0xd4, 0xc1, 0x00, 0x8b, 0x08, 0xe8, 0x02, 0x83, + 0x24, 0x83, 0x41, 0x68, 0x01, 0x69, 0x42, 0xa3, 0xe0, 0x7f, 0x04, 0xa3, + 0x24, 0x83, 0x08, 0xe9, 0x03, 0x83, 0x09, 0x08, 0x45, 0x00, 0x23, 0xa3, + 0x10, 0x1b, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0xfa, 0xc3, 0x82, 0x24, + 0x02, 0x39, 0xcb, 0x46, 0xa0, 0x00, 0x88, 0x86, 0x2a, 0x86, 0x02, 0x86, + 0x6b, 0x86, 0x43, 0x86, 0xed, 0x70, 0x00, 0x21, 0x01, 0x80, 0xf1, 0x44, + 0xf1, 0x40, 0xf1, 0x45, 0x01, 0x22, 0xc0, 0x80, 0xd3, 0x46, 0xa0, 0x00, + 0x68, 0xc1, 0x4c, 0xc7, 0x4b, 0xc7, 0x4a, 0xc7, 0x22, 0xa6, 0x03, 0xa6, + 0x5a, 0x24, 0x03, 0x27, 0x00, 0x26, 0xcd, 0x20, 0x05, 0x85, 0x14, 0x70, + 0x10, 0x42, 0x61, 0xf2, 0x03, 0x85, 0x22, 0x86, 0x84, 0x85, 0x43, 0x86, + 0x08, 0x15, 0x0b, 0x10, 0x04, 0x15, 0x08, 0x10, 0x02, 0x21, 0x09, 0x80, + 0x03, 0x22, 0x00, 0x83, 0x3c, 0x21, 0x08, 0x12, 0x3c, 0x20, 0xcc, 0x02, + 0x71, 0x70, 0xca, 0x24, 0x01, 0x12, 0x95, 0x70, 0x4b, 0xf4, 0x98, 0x8d, + 0x32, 0x23, 0x93, 0x05, 0x40, 0x26, 0x00, 0x23, 0x78, 0x60, 0x23, 0xa5, + 0x41, 0xa0, 0x88, 0xec, 0x1e, 0x0b, 0x60, 0x06, 0x42, 0x40, 0x14, 0x70, + 0x18, 0xad, 0x3d, 0xf2, 0x10, 0x8e, 0x09, 0xe8, 0x07, 0x86, 0x0f, 0x08, + 0xc1, 0x04, 0xbe, 0x0a, 0x00, 0x00, 0x10, 0x1e, 0x03, 0x10, 0x50, 0x12, + 0x01, 0x20, 0x42, 0x40, 0x60, 0x79, 0x1c, 0x1c, 0xc2, 0x34, 0x80, 0x12, + 0x11, 0x20, 0x78, 0x12, 0x01, 0x20, 0xef, 0x7a, 0x8a, 0xc3, 0x55, 0x7b, + 0x48, 0xc0, 0x00, 0x1b, 0x40, 0x04, 0x18, 0x1c, 0x40, 0x34, 0x2f, 0x27, + 0x3f, 0x03, 0x6f, 0x23, 0x3f, 0x00, 0x00, 0x81, 0x61, 0x81, 0x22, 0x81, + 0x2f, 0x26, 0x3f, 0x03, 0x44, 0xc1, 0x5f, 0x22, 0x01, 0x06, 0x5f, 0x22, + 0x02, 0x03, 0x43, 0xc3, 0x42, 0xc0, 0x97, 0xc0, 0x8e, 0xc3, 0x19, 0x61, + 0x7a, 0x62, 0x26, 0x0d, 0x6f, 0xee, 0x82, 0xc0, 0x0b, 0x0d, 0x10, 0x20, + 0x00, 0x86, 0x0d, 0x0b, 0x01, 0x20, 0x50, 0x21, 0xd0, 0x27, 0xae, 0x71, + 0xe5, 0x71, 0x86, 0x71, 0x96, 0x73, 0x30, 0x07, 0xc5, 0xff, 0x05, 0x86, + 0x13, 0x08, 0x22, 0x04, 0x02, 0x20, 0x00, 0x04, 0xd3, 0x70, 0x00, 0x00, + 0x00, 0x19, 0x24, 0x01, 0x0b, 0x00, 0x2f, 0x27, 0xc7, 0x93, 0x14, 0x1e, + 0x00, 0x14, 0x8c, 0xf2, 0xad, 0x70, 0xd3, 0x41, 0xa0, 0x00, 0xb8, 0x86, + 0x00, 0x11, 0x80, 0x20, 0x5a, 0x25, 0x02, 0x16, 0x97, 0xc1, 0x59, 0x61, + 0x2d, 0x08, 0x3e, 0x00, 0x04, 0x19, 0x00, 0x04, 0x10, 0x89, 0x22, 0x81, + 0x8a, 0xc2, 0x11, 0x16, 0x86, 0x10, 0xf0, 0x22, 0x47, 0x03, 0x62, 0x81, + 0x41, 0x81, 0x20, 0x81, 0x42, 0x28, 0xc5, 0x27, 0x0a, 0x24, 0x00, 0x04, + 0x72, 0x0b, 0xaf, 0xfa, 0x00, 0x1c, 0x01, 0x30, 0xa5, 0x71, 0xc9, 0x0d, + 0xc4, 0x93, 0x11, 0x8e, 0x97, 0xc2, 0x2c, 0x71, 0x04, 0x71, 0x11, 0xae, + 0xc5, 0x74, 0xe1, 0x43, 0xc1, 0x40, 0x34, 0x1c, 0x01, 0x37, 0xd9, 0x41, + 0xdb, 0x59, 0x14, 0x70, 0xb6, 0x00, 0x2b, 0x00, 0x08, 0x45, 0x58, 0xf4, + 0x55, 0x26, 0x8f, 0x29, 0x8d, 0xc2, 0x23, 0x40, 0xe1, 0x41, 0xdd, 0x59, + 0x21, 0x87, 0x10, 0x44, 0x42, 0x21, 0x55, 0x00, 0x3b, 0x58, 0x0e, 0x70, + 0x18, 0x40, 0x30, 0x47, 0x12, 0x43, 0x12, 0x42, 0x0d, 0xc0, 0x5f, 0x08, + 0x05, 0x20, 0x5a, 0x20, 0x0e, 0x26, 0xc3, 0x40, 0xa0, 0x00, 0x04, 0xc2, + 0xd9, 0x60, 0x02, 0x66, 0xa6, 0x91, 0x2f, 0x0a, 0x60, 0x05, 0x48, 0x43, + 0xfe, 0xe5, 0x0a, 0xf4, 0x7e, 0xdd, 0x0a, 0x25, 0xc0, 0x22, 0x0a, 0x23, + 0x00, 0x26, 0x0a, 0x22, 0xc0, 0x25, 0x0b, 0xf0, 0x61, 0x40, 0x03, 0x41, + 0xc2, 0x0c, 0xef, 0xff, 0xe2, 0x42, 0x10, 0x43, 0x30, 0x42, 0x0a, 0x25, + 0xc0, 0x22, 0x26, 0x0c, 0x6f, 0xf8, 0xbd, 0x78, 0x09, 0xe8, 0x55, 0x80, + 0x07, 0xea, 0xf9, 0x66, 0x28, 0x18, 0xc0, 0x04, 0x60, 0x7a, 0x2c, 0x18, + 0x80, 0x04, 0x06, 0x71, 0xd2, 0xf1, 0x2d, 0x0c, 0x50, 0x20, 0x00, 0x11, + 0x81, 0x20, 0x25, 0x09, 0x1e, 0x00, 0x27, 0x1c, 0x02, 0x30, 0x26, 0x1c, + 0x02, 0x35, 0x25, 0x1c, 0xc3, 0x31, 0x3b, 0x58, 0x00, 0x42, 0x20, 0x43, + 0x40, 0x24, 0x41, 0x39, 0xfe, 0xd8, 0xd2, 0x0f, 0x2f, 0xfb, 0x8c, 0x70, + 0x5d, 0x0c, 0xd0, 0xa0, 0xda, 0xc7, 0xfa, 0x0d, 0x2f, 0xfb, 0x51, 0xd8, + 0xb3, 0x79, 0xc3, 0x40, 0xf0, 0x00, 0x4c, 0x00, 0x20, 0xb0, 0xda, 0xc7, + 0xf8, 0xc3, 0xfa, 0x08, 0x6f, 0xf8, 0xa2, 0xc1, 0x66, 0x0f, 0x2f, 0xf8, + 0x10, 0x43, 0x2e, 0x70, 0xcd, 0x70, 0x10, 0x44, 0xcb, 0x47, 0xa0, 0x00, + 0xbc, 0xc1, 0x32, 0x42, 0x32, 0x40, 0x3a, 0x40, 0xd1, 0x47, 0xd1, 0x45, + 0x04, 0x1c, 0x44, 0x34, 0x00, 0x1c, 0x40, 0x34, 0x0a, 0x0b, 0x20, 0x04, + 0x01, 0x87, 0x04, 0x30, 0x40, 0x84, 0x72, 0x00, 0x2e, 0x00, 0x10, 0x46, + 0xa0, 0x87, 0x35, 0xed, 0xa1, 0x40, 0x62, 0x41, 0xae, 0x08, 0x6f, 0xf8, + 0x82, 0x42, 0x2c, 0xe8, 0x9e, 0x0f, 0x8f, 0xf7, 0x80, 0xc0, 0x4e, 0x71, + 0x04, 0x36, 0x00, 0xa6, 0xb8, 0x60, 0x00, 0x18, 0x82, 0x04, 0x0b, 0xf6, + 0x0c, 0xf4, 0xc3, 0x40, 0xa0, 0x00, 0xa0, 0xc4, 0xf0, 0x20, 0x01, 0x04, + 0xa0, 0x48, 0x0d, 0x09, 0x03, 0x00, 0x0a, 0x20, 0x80, 0x35, 0xb1, 0x40, + 0x32, 0x25, 0x80, 0x1f, 0xa0, 0x00, 0xa8, 0x86, 0x13, 0xe8, 0x04, 0x36, + 0x40, 0xa5, 0x0a, 0xf6, 0x0f, 0xf4, 0xc3, 0x40, 0xa0, 0x00, 0xa0, 0xc4, + 0xc1, 0x48, 0xa0, 0x48, 0x13, 0x09, 0x03, 0x00, 0x0a, 0x25, 0x80, 0x25, + 0xa9, 0x46, 0x05, 0xf0, 0x46, 0x0d, 0x2f, 0xfb, 0x54, 0xd8, 0xe6, 0x71, + 0x85, 0x0f, 0xf4, 0xa0, 0x08, 0xe7, 0xcb, 0x45, 0xa0, 0x00, 0x88, 0x86, + 0x33, 0x0a, 0x10, 0x20, 0x1a, 0x08, 0x80, 0x05, 0x1d, 0xe8, 0x2e, 0x0f, + 0x8f, 0xf7, 0x00, 0x85, 0x50, 0x25, 0xfe, 0xa7, 0xca, 0x26, 0x01, 0x14, + 0x0d, 0x08, 0xa0, 0x03, 0xc1, 0x40, 0x32, 0x08, 0x00, 0x00, 0xc0, 0x85, + 0x13, 0x0e, 0x00, 0x14, 0x1c, 0x1d, 0x00, 0x14, 0x10, 0x1d, 0x43, 0x10, + 0x03, 0xf0, 0x14, 0x1d, 0xc1, 0x1f, 0x00, 0xc1, 0x04, 0x14, 0x00, 0x31, + 0x28, 0xa5, 0x12, 0xb5, 0xd8, 0xc7, 0xf2, 0x0c, 0x2f, 0xfb, 0x56, 0xd8, + 0xd8, 0xc7, 0xe0, 0x78, 0xe4, 0xc2, 0xfa, 0x0f, 0x2f, 0xf8, 0x08, 0x45, + 0x66, 0x0e, 0x2f, 0xf8, 0x08, 0x46, 0x00, 0x42, 0xa1, 0x40, 0xe2, 0x0f, + 0x2f, 0xf8, 0xc1, 0x41, 0x08, 0x46, 0x10, 0xe8, 0xb6, 0x0f, 0x40, 0x05, + 0x0e, 0xe8, 0x27, 0x80, 0x03, 0xe9, 0x00, 0x19, 0x01, 0x00, 0xc3, 0x41, + 0xa0, 0x00, 0x88, 0x86, 0x00, 0xa6, 0xc7, 0xa0, 0xa0, 0xa1, 0xc4, 0xc6, + 0x54, 0xd8, 0x03, 0xf0, 0x56, 0xd8, 0xaa, 0x0c, 0x0f, 0xfb, 0xc4, 0xc6, + 0xea, 0xc2, 0xa0, 0x80, 0x08, 0x46, 0x30, 0x41, 0x08, 0x18, 0x43, 0x00, + 0x26, 0xed, 0x42, 0x0b, 0x6f, 0xf9, 0xa1, 0x40, 0x20, 0xe8, 0x1a, 0x0a, + 0x6f, 0xf8, 0xa1, 0x40, 0x3a, 0x0b, 0x4f, 0xf9, 0x1a, 0xe8, 0x1d, 0x95, + 0x3c, 0x95, 0xe1, 0x68, 0x2b, 0x0f, 0x44, 0x10, 0x15, 0x85, 0xed, 0x70, + 0x00, 0x1e, 0x41, 0x70, 0xa0, 0x00, 0x34, 0x41, 0x10, 0x40, 0x08, 0x1d, + 0x43, 0x10, 0x0b, 0xe8, 0x0b, 0x86, 0x2a, 0x86, 0x0b, 0xa5, 0x2a, 0xa5, + 0xa1, 0x40, 0x23, 0x20, 0x00, 0x04, 0x22, 0x41, 0xe8, 0xad, 0xfd, 0xb5, + 0xa0, 0x85, 0xdd, 0xed, 0x0c, 0x70, 0x08, 0x1e, 0x03, 0x10, 0xca, 0xc6, + 0xfa, 0xc2, 0xfc, 0x1c, 0xc8, 0xb6, 0x30, 0x45, 0x4e, 0x0f, 0x2f, 0xf8, + 0x18, 0x43, 0xbe, 0x0d, 0x2f, 0xf8, 0x18, 0x41, 0x18, 0x40, 0xcd, 0x70, + 0xc5, 0x0d, 0x30, 0x20, 0x8e, 0x77, 0x4e, 0x70, 0x2e, 0x77, 0x52, 0x46, + 0x52, 0x43, 0xd3, 0x40, 0xa0, 0x00, 0x68, 0xc1, 0x16, 0x23, 0x97, 0x34, + 0xee, 0x40, 0x5a, 0x22, 0x0f, 0x27, 0x00, 0x20, 0xcd, 0x23, 0x04, 0x30, + 0x80, 0x83, 0xc4, 0xa5, 0x68, 0x00, 0x2c, 0x00, 0xc3, 0xa5, 0x04, 0x30, + 0x80, 0x8f, 0x7f, 0x47, 0x00, 0xff, 0x5c, 0x00, 0x06, 0x00, 0x07, 0x36, + 0x00, 0x70, 0x6e, 0x4e, 0x28, 0x6b, 0xfe, 0x0b, 0x8f, 0xec, 0x00, 0x42, + 0x3c, 0x26, 0x88, 0x20, 0x3c, 0x23, 0x4c, 0x20, 0x0c, 0x23, 0x40, 0xa0, + 0xca, 0x24, 0x01, 0x12, 0x95, 0x70, 0x3c, 0x22, 0x0b, 0x05, 0x3c, 0x21, + 0x43, 0x04, 0xca, 0x23, 0x42, 0x20, 0xca, 0x26, 0x82, 0x20, 0x0c, 0x21, + 0x40, 0xa0, 0xe6, 0x40, 0xca, 0x23, 0xc1, 0x02, 0x74, 0x70, 0x22, 0xa5, + 0x41, 0xa5, 0x02, 0x77, 0xca, 0x21, 0x42, 0x20, 0xca, 0x24, 0x82, 0x20, + 0x23, 0x41, 0x03, 0x42, 0xae, 0x0e, 0x2f, 0xf8, 0x00, 0xa7, 0x04, 0xf0, + 0x0c, 0x70, 0xd8, 0xad, 0x46, 0x71, 0x81, 0x0a, 0x64, 0xa5, 0x05, 0xa5, + 0x0a, 0x24, 0x40, 0x75, 0xa8, 0x20, 0x00, 0x04, 0x5a, 0x26, 0x00, 0x17, + 0x02, 0x70, 0x25, 0x80, 0x09, 0xe9, 0x41, 0x80, 0x22, 0x80, 0x0e, 0x22, + 0x82, 0x85, 0x03, 0x23, 0x41, 0xa0, 0x43, 0xa0, 0x24, 0xa0, 0xc5, 0x71, + 0xca, 0x46, 0x04, 0xf0, 0x2e, 0x77, 0x6e, 0x70, 0x02, 0x26, 0x02, 0x95, + 0xc3, 0x41, 0xa0, 0x00, 0x88, 0x86, 0x03, 0x23, 0x40, 0xa4, 0x28, 0x19, + 0x00, 0x05, 0x2c, 0x19, 0x40, 0x04, 0x42, 0xa1, 0x03, 0xa1, 0x04, 0x14, + 0x1b, 0x34, 0xda, 0xc6, 0xf4, 0xc3, 0x82, 0x24, 0x0c, 0x3f, 0x68, 0x46, + 0x50, 0x43, 0x28, 0x45, 0x10, 0x40, 0x8a, 0x27, 0x8e, 0x10, 0x07, 0xea, + 0x2c, 0x70, 0xa1, 0x40, 0x22, 0x0a, 0xaf, 0xfa, 0x62, 0x42, 0x4a, 0x24, + 0xc0, 0x73, 0xfe, 0xd9, 0x02, 0x77, 0x0c, 0x74, 0x00, 0x1c, 0x01, 0x31, + 0x22, 0xad, 0x4a, 0x21, 0x00, 0x00, 0x81, 0xc2, 0xa8, 0x20, 0x40, 0x01, + 0x24, 0x71, 0x01, 0x1a, 0x52, 0x00, 0x09, 0xee, 0x8f, 0xe6, 0x32, 0x01, + 0x2d, 0x00, 0x61, 0xc6, 0xc3, 0xad, 0x4e, 0x71, 0x05, 0xf0, 0x4a, 0x22, + 0xc0, 0x23, 0x03, 0x1d, 0x03, 0x10, 0x8a, 0x26, 0x07, 0x1d, 0x54, 0x20, + 0x15, 0x29, 0x54, 0x20, 0x94, 0x2b, 0x2e, 0x70, 0x40, 0x24, 0x16, 0x31, + 0x02, 0x76, 0x01, 0x16, 0x80, 0x24, 0x04, 0x77, 0xf3, 0x08, 0xd5, 0x03, + 0x25, 0x20, 0x00, 0x00, 0x0f, 0xf0, 0x1d, 0xf0, 0x2d, 0xf0, 0x3a, 0xf0, + 0x4c, 0xf0, 0x4f, 0xf0, 0x50, 0xf0, 0x53, 0xf0, 0x54, 0xf0, 0x5c, 0xf0, + 0x5d, 0xf0, 0x5f, 0xf0, 0x5f, 0xf0, 0x61, 0xf0, 0x61, 0xf0, 0x56, 0x24, + 0x40, 0x3d, 0x14, 0xda, 0x5a, 0x0b, 0xaf, 0xec, 0xa2, 0x41, 0x56, 0x24, + 0x40, 0x3d, 0x80, 0xc3, 0xa1, 0x41, 0x1a, 0x0e, 0x20, 0x05, 0x62, 0x42, + 0x59, 0xf0, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0x94, 0x01, 0x14, 0xda, + 0x3a, 0x0b, 0xaf, 0xec, 0x82, 0x41, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, + 0x94, 0x01, 0x80, 0xc3, 0xa1, 0x41, 0xc2, 0x08, 0x60, 0x05, 0x62, 0x42, + 0x47, 0xf0, 0x85, 0xc0, 0x8a, 0x22, 0x06, 0x00, 0x1a, 0x0b, 0xaf, 0xec, + 0xc1, 0x41, 0x85, 0xc0, 0x80, 0xc3, 0xa1, 0x41, 0x02, 0x0a, 0x60, 0x05, + 0x62, 0x42, 0x3b, 0xf0, 0x70, 0x10, 0x82, 0x20, 0x00, 0x24, 0x81, 0x3f, + 0x00, 0x00, 0xbc, 0x01, 0xf6, 0x0f, 0xa0, 0x04, 0xdf, 0x10, 0x00, 0x26, + 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0xbc, 0x01, 0x80, 0xc3, 0xa1, 0x41, + 0xce, 0x0a, 0x60, 0x05, 0x62, 0x42, 0x27, 0xf0, 0x28, 0x10, 0x00, 0x20, + 0x0c, 0xf0, 0x2c, 0x10, 0x00, 0x20, 0x0a, 0xf0, 0x30, 0x10, 0x00, 0x20, + 0x06, 0xf0, 0xdd, 0x10, 0x00, 0x26, 0x04, 0xf0, 0xde, 0x10, 0x00, 0x26, + 0x80, 0xc3, 0xa1, 0x41, 0xc6, 0x0c, 0x60, 0x05, 0x62, 0x42, 0x13, 0xf0, + 0xff, 0x17, 0x80, 0x90, 0x0a, 0xf0, 0x00, 0x8f, 0x08, 0xf0, 0x01, 0x8f, + 0x06, 0xf0, 0x02, 0x8f, 0x04, 0xf0, 0x03, 0x8f, 0x02, 0xf0, 0x04, 0x8f, + 0x80, 0xc3, 0xa1, 0x41, 0x66, 0x0d, 0x60, 0x05, 0x62, 0x42, 0x26, 0x71, + 0x07, 0x09, 0x84, 0xa4, 0x00, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, + 0x21, 0xad, 0xd4, 0xc7, 0xf0, 0xc3, 0xa2, 0xc1, 0x50, 0x42, 0x68, 0x45, + 0x28, 0x46, 0x10, 0x40, 0x06, 0xea, 0x2c, 0x70, 0xc1, 0x40, 0xb6, 0x08, + 0xaf, 0xfa, 0x42, 0x42, 0xfe, 0xd9, 0xed, 0x71, 0x04, 0x1c, 0x01, 0x31, + 0x03, 0x1c, 0x83, 0x30, 0x22, 0xae, 0x02, 0x1c, 0xc2, 0x33, 0x0a, 0xed, + 0x0c, 0x74, 0x5b, 0x0d, 0xf5, 0x10, 0x02, 0x1c, 0x42, 0x33, 0xa3, 0xae, + 0x8e, 0x71, 0x06, 0xf0, 0x8e, 0x72, 0xad, 0x71, 0x03, 0x1e, 0x03, 0x10, + 0x8a, 0x21, 0x0e, 0x20, 0x40, 0x24, 0xd3, 0x30, 0x19, 0x0d, 0xb0, 0x10, + 0x81, 0xc3, 0x21, 0x0d, 0x71, 0x10, 0x81, 0xc3, 0x42, 0x42, 0x02, 0x40, + 0x32, 0x0f, 0x60, 0x05, 0xc1, 0x41, 0x08, 0xf0, 0x32, 0x20, 0x40, 0x24, + 0xc1, 0x41, 0xe6, 0x0c, 0x60, 0x05, 0x42, 0x42, 0x0d, 0x0f, 0x05, 0x15, + 0x01, 0x13, 0x8d, 0x24, 0xe5, 0x71, 0xea, 0xf1, 0x01, 0xc0, 0x41, 0x28, + 0x01, 0x02, 0x00, 0xae, 0x21, 0xae, 0xd0, 0xc7, 0xe8, 0xc2, 0x48, 0x46, + 0x28, 0x47, 0x2c, 0x70, 0x10, 0xda, 0x60, 0x40, 0x0a, 0x20, 0x00, 0x21, + 0x2e, 0x08, 0xaf, 0xfa, 0x68, 0x45, 0x0c, 0x70, 0x36, 0xef, 0x29, 0x6e, + 0x21, 0x09, 0xf5, 0x00, 0x42, 0x26, 0x41, 0x1e, 0x04, 0x1d, 0x83, 0x12, + 0x03, 0x1d, 0x03, 0x11, 0x02, 0x1d, 0xc3, 0x10, 0x01, 0x1d, 0x83, 0x10, + 0x00, 0x1d, 0x43, 0x10, 0x0c, 0x75, 0x26, 0xf0, 0x49, 0x09, 0xd5, 0x02, + 0x25, 0x20, 0x40, 0x00, 0x0b, 0xf0, 0x0e, 0xf0, 0x0f, 0xf0, 0x12, 0xf0, + 0x1c, 0xf0, 0x1c, 0xf0, 0x1a, 0xf0, 0x17, 0xf0, 0x0f, 0xf0, 0x18, 0xf0, + 0x10, 0xf0, 0x00, 0x1d, 0xc3, 0x11, 0x13, 0xf0, 0x00, 0x1d, 0x83, 0x12, + 0x0f, 0xf0, 0x00, 0x1d, 0xc3, 0x12, 0x0d, 0xf0, 0x00, 0x1d, 0x03, 0x13, + 0x09, 0xf0, 0x00, 0x1d, 0x83, 0x13, 0x07, 0xf0, 0x00, 0x1d, 0xc3, 0x13, + 0x03, 0xf0, 0x00, 0x1d, 0x43, 0x13, 0x0c, 0x71, 0x00, 0x18, 0x00, 0x20, + 0xc8, 0xc6, 0xe0, 0x78, 0xe2, 0xc2, 0xfe, 0x0b, 0x60, 0x03, 0x08, 0x45, + 0x4a, 0x24, 0x40, 0x71, 0x2c, 0x70, 0xa1, 0x40, 0xa8, 0x20, 0x40, 0x01, + 0x21, 0xa0, 0x08, 0x18, 0x11, 0x00, 0x80, 0x25, 0x0e, 0x10, 0x00, 0x1d, + 0x03, 0x10, 0xc2, 0xc6, 0xfd, 0x01, 0x00, 0x05, 0xea, 0xc3, 0x82, 0x24, + 0x0e, 0x34, 0x10, 0x41, 0x8c, 0xc0, 0x8a, 0x22, 0x0d, 0x08, 0x3a, 0x09, + 0xaf, 0xec, 0x28, 0x45, 0x02, 0x8d, 0x8c, 0x20, 0x83, 0x8f, 0x8a, 0x20, + 0x3e, 0x07, 0x36, 0xf4, 0x23, 0x8d, 0x0e, 0x72, 0xad, 0x71, 0x4c, 0x71, + 0x03, 0x1c, 0x83, 0x30, 0x02, 0x1c, 0x42, 0x33, 0x09, 0xe9, 0x8a, 0x20, + 0xfe, 0x06, 0x20, 0x42, 0x0e, 0x71, 0x51, 0x09, 0xf5, 0x00, 0x02, 0x1c, + 0x42, 0x30, 0x8a, 0x26, 0x0e, 0x10, 0x40, 0x24, 0xcf, 0x30, 0x22, 0x76, + 0x04, 0x1c, 0x01, 0x31, 0x23, 0x0a, 0xb0, 0x00, 0x8c, 0xc0, 0x4d, 0x78, + 0x23, 0x08, 0x71, 0x00, 0x8c, 0xc0, 0x81, 0xc1, 0xea, 0x08, 0xa0, 0x05, + 0x82, 0xc2, 0x82, 0xc1, 0x28, 0xda, 0xde, 0x08, 0xaf, 0xec, 0x22, 0x40, + 0x05, 0xf0, 0xfa, 0x0f, 0xe0, 0x05, 0x81, 0xc1, 0x00, 0xae, 0x0f, 0x0d, + 0x05, 0x14, 0x01, 0x17, 0x82, 0x14, 0xa5, 0x71, 0xe6, 0xf1, 0x0c, 0x70, + 0xca, 0xc7, 0xe0, 0x78, 0xe8, 0xc2, 0x00, 0x20, 0x8d, 0x0f, 0x00, 0x00, + 0x24, 0x02, 0x36, 0x0f, 0x2f, 0xef, 0x10, 0x40, 0x4a, 0x24, 0x00, 0x71, + 0xc3, 0x43, 0x13, 0x00, 0xe0, 0x6b, 0x55, 0x20, 0x80, 0x2a, 0x60, 0x41, + 0xa8, 0x20, 0x00, 0x02, 0x01, 0x11, 0xc2, 0x04, 0x48, 0x32, 0x82, 0x00, + 0x04, 0x18, 0x90, 0x00, 0x4a, 0x24, 0x00, 0x71, 0x55, 0x20, 0x80, 0x2b, + 0x0a, 0x21, 0xc0, 0x00, 0xa8, 0x20, 0x00, 0x02, 0x01, 0x11, 0xc2, 0x04, + 0x48, 0x32, 0x82, 0x00, 0x04, 0x18, 0x90, 0x00, 0x4a, 0x24, 0x00, 0x71, + 0x40, 0x20, 0x00, 0x2b, 0x0a, 0x21, 0xc0, 0x00, 0x28, 0x18, 0x01, 0x20, + 0xa8, 0x20, 0x00, 0x02, 0x01, 0x11, 0xc2, 0x04, 0x48, 0x32, 0x82, 0x00, + 0x04, 0x18, 0x90, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x55, 0x20, 0x00, 0x2d, + 0x4a, 0x27, 0x00, 0x10, 0xcc, 0x18, 0x43, 0x20, 0xa0, 0x18, 0x43, 0x20, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, 0x4a, 0x24, 0x00, 0x71, + 0xc3, 0x40, 0xa3, 0x3b, 0x0a, 0xd7, 0xa0, 0x1d, 0xd8, 0x93, 0x78, 0x18, + 0x00, 0x20, 0x55, 0x20, 0x00, 0x29, 0x60, 0x41, 0xa8, 0x20, 0x00, 0x02, + 0x01, 0x11, 0xc2, 0x04, 0x48, 0x32, 0x82, 0x00, 0x04, 0x18, 0x90, 0x00, + 0xc2, 0x83, 0x81, 0x83, 0x63, 0x83, 0xc3, 0x40, 0x49, 0x40, 0xdb, 0x0f, + 0x8a, 0x21, 0x09, 0x0d, 0xfe, 0xa5, 0xfa, 0xa5, 0xc3, 0x42, 0xac, 0x3b, + 0x00, 0x5f, 0x8c, 0x18, 0x43, 0x20, 0x15, 0xa5, 0x18, 0xa5, 0x17, 0xa5, + 0x16, 0xa5, 0x02, 0x71, 0x02, 0x40, 0x5f, 0xa5, 0xf4, 0xa9, 0x00, 0x19, + 0x43, 0x00, 0x9b, 0xa5, 0x7d, 0xa5, 0x8e, 0x0d, 0xa0, 0x00, 0xdc, 0xa5, + 0xc8, 0xc6, 0xe0, 0x78, 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x34, 0x50, 0x40, + 0x08, 0x47, 0x84, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0xba, 0x0f, 0x6f, 0xec, + 0x28, 0x45, 0x00, 0x87, 0x40, 0x24, 0x83, 0x30, 0x40, 0x24, 0x04, 0x32, + 0x40, 0x24, 0x05, 0x33, 0x40, 0x24, 0x06, 0x31, 0x40, 0x24, 0xc7, 0x30, + 0xa1, 0x41, 0x02, 0x42, 0xc6, 0x0b, 0xaf, 0xf3, 0x02, 0x1c, 0x43, 0x31, + 0x02, 0xc5, 0x81, 0x0d, 0x31, 0x10, 0x2c, 0x70, 0x03, 0x14, 0x8e, 0x30, + 0xad, 0x70, 0xba, 0xe9, 0x02, 0x14, 0x81, 0x30, 0xcf, 0x78, 0x6d, 0x09, + 0x24, 0x00, 0x04, 0x77, 0x4d, 0x08, 0x55, 0x01, 0x25, 0x20, 0x00, 0x00, + 0x05, 0xf0, 0x0b, 0xf0, 0x0f, 0xf0, 0x15, 0xf0, 0x19, 0xf0, 0x84, 0xc0, + 0xe6, 0x0d, 0x6f, 0xf5, 0x81, 0xc1, 0x15, 0xaf, 0x18, 0xf0, 0x84, 0xc0, + 0xda, 0x0d, 0x6f, 0xf5, 0x81, 0xc1, 0x17, 0xaf, 0x12, 0xf0, 0x84, 0xc0, + 0xf6, 0x0f, 0xa0, 0x03, 0x81, 0xc1, 0x0c, 0xb7, 0x0c, 0xf0, 0x84, 0xc0, + 0xc2, 0x0d, 0x6f, 0xf5, 0x81, 0xc1, 0x1a, 0xaf, 0x06, 0xf0, 0x84, 0xc0, + 0xc2, 0x0a, 0xef, 0xf6, 0x81, 0xc1, 0x0e, 0xb7, 0x01, 0xc0, 0x8a, 0x21, + 0x3e, 0x06, 0x12, 0x70, 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, 0x01, 0x20, + 0x3d, 0x20, 0x00, 0x20, 0x1e, 0x66, 0xc9, 0xf1, 0xa1, 0x40, 0xc8, 0xc7, + 0xe8, 0xc3, 0xa3, 0xc1, 0x4a, 0x24, 0xc0, 0x70, 0x08, 0x45, 0x80, 0xc2, + 0x6c, 0x70, 0xa8, 0x20, 0x80, 0x06, 0x04, 0x11, 0x00, 0x04, 0x48, 0x47, + 0x00, 0x30, 0x80, 0x0f, 0x03, 0x40, 0x6f, 0x12, 0x04, 0x30, 0xc0, 0x80, + 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc0, 0x02, + 0x42, 0x6f, 0x00, 0xb7, 0x80, 0xc0, 0xa6, 0x0b, 0x20, 0x05, 0x82, 0xc1, + 0x4c, 0x95, 0x08, 0x14, 0x01, 0x31, 0x15, 0x8d, 0x42, 0x79, 0x2e, 0x79, + 0x06, 0x0c, 0x20, 0x00, 0x4c, 0x77, 0x9a, 0x0e, 0x20, 0x03, 0x2c, 0x71, + 0x10, 0x40, 0x08, 0x14, 0x41, 0x31, 0x15, 0x8d, 0xf2, 0x0b, 0x20, 0x00, + 0x4c, 0x77, 0x86, 0x0e, 0x20, 0x03, 0x2c, 0x71, 0x0a, 0x14, 0x4e, 0x31, + 0x2f, 0x21, 0x06, 0x04, 0x15, 0x0e, 0x63, 0x10, 0x00, 0x42, 0x00, 0x14, + 0x40, 0x31, 0x39, 0x08, 0x12, 0x00, 0x08, 0x1d, 0x45, 0x10, 0x1d, 0xf0, + 0x2c, 0x9d, 0xc2, 0x0b, 0x20, 0x00, 0x4e, 0x78, 0x13, 0x08, 0x83, 0x03, + 0x02, 0x14, 0x40, 0x31, 0x23, 0x08, 0x12, 0x00, 0x08, 0x1d, 0x05, 0x10, + 0x0f, 0xf0, 0x04, 0x8d, 0x0d, 0xe8, 0x32, 0x0b, 0x60, 0x05, 0x80, 0xc0, + 0x09, 0xe8, 0x08, 0x1d, 0xc5, 0x1f, 0x07, 0xf0, 0x08, 0x1d, 0xc5, 0x10, + 0x03, 0xf0, 0x08, 0x1d, 0x85, 0x10, 0x17, 0x8d, 0x18, 0xe8, 0x20, 0x9f, + 0x09, 0x09, 0x33, 0x00, 0x20, 0x40, 0x33, 0x78, 0x10, 0x78, 0x8c, 0x20, + 0xc6, 0x86, 0x88, 0xf7, 0x04, 0x21, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x80, + 0x2f, 0xb8, 0x08, 0xf0, 0x03, 0x9d, 0x11, 0x08, 0x32, 0x00, 0x2c, 0x72, + 0x02, 0x0e, 0x00, 0x03, 0x05, 0xb5, 0x05, 0xf0, 0x0c, 0x70, 0x0a, 0x1d, + 0x05, 0x10, 0x24, 0x9d, 0x34, 0x77, 0x07, 0xf2, 0x0e, 0x78, 0xc2, 0xb9, + 0xd2, 0x68, 0x25, 0x7e, 0x04, 0xf0, 0xcb, 0x46, 0x00, 0x00, 0xff, 0xff, + 0x03, 0x95, 0xd0, 0x7a, 0xed, 0x70, 0x50, 0x70, 0x0c, 0x70, 0x23, 0xf2, + 0x7a, 0x8d, 0x0c, 0x70, 0x1f, 0xeb, 0x1b, 0x0b, 0xf1, 0x00, 0x0c, 0x71, + 0x36, 0x8d, 0x89, 0x95, 0x24, 0x71, 0x31, 0x0c, 0xa1, 0x10, 0x36, 0xad, + 0x2f, 0x79, 0x2b, 0x09, 0x94, 0x02, 0x40, 0x25, 0x02, 0x13, 0x80, 0xc1, + 0x6a, 0x0a, 0x20, 0x00, 0x60, 0x40, 0x8d, 0xe8, 0x74, 0x8d, 0x2e, 0x95, + 0x80, 0xc0, 0x86, 0x08, 0x20, 0x00, 0x4c, 0x70, 0x14, 0xad, 0x78, 0x20, + 0x40, 0x00, 0x03, 0xf0, 0xf6, 0xad, 0x24, 0x8d, 0x0f, 0x78, 0x0f, 0x08, + 0x71, 0x00, 0xc9, 0xb5, 0x83, 0xe9, 0xc3, 0x95, 0x2c, 0x70, 0x16, 0xe9, + 0x43, 0x9d, 0x83, 0x40, 0x60, 0x90, 0x21, 0x90, 0x02, 0x90, 0x66, 0xb5, + 0x27, 0xb5, 0x25, 0x0a, 0x32, 0x00, 0x08, 0xb5, 0xd0, 0x79, 0xc3, 0x40, + 0x00, 0x00, 0xff, 0xff, 0x11, 0x09, 0x00, 0x00, 0x48, 0x47, 0x85, 0x27, + 0x3e, 0x10, 0x06, 0xf0, 0x43, 0x95, 0x06, 0xf0, 0x00, 0x42, 0x03, 0xb5, + 0x04, 0x1d, 0x03, 0x10, 0x83, 0x40, 0x80, 0x90, 0x61, 0x90, 0x02, 0x90, + 0xd0, 0x79, 0x86, 0xb5, 0x67, 0xb5, 0x08, 0xb5, 0x17, 0x09, 0x80, 0x0f, + 0x00, 0x00, 0xff, 0xff, 0x50, 0x78, 0x0f, 0x08, 0x40, 0x00, 0xc3, 0xb5, + 0x85, 0x26, 0x3e, 0x10, 0xc9, 0x47, 0xef, 0x78, 0xc8, 0xc7, 0xe0, 0x78, + 0xe6, 0xc0, 0x80, 0x98, 0xcd, 0x70, 0x8c, 0xbe, 0x17, 0x0e, 0x22, 0x13, + 0xc9, 0x45, 0x89, 0x45, 0x0f, 0x0c, 0x83, 0x1f, 0xff, 0xff, 0xff, 0xef, + 0xcb, 0x45, 0x00, 0x00, 0xff, 0xef, 0x81, 0x98, 0x17, 0x0e, 0x22, 0x13, + 0xc9, 0x47, 0x89, 0x47, 0x0f, 0x0c, 0x83, 0x1f, 0xff, 0xff, 0xff, 0xef, + 0xcb, 0x47, 0x00, 0x00, 0xff, 0xef, 0x02, 0x98, 0x15, 0x0e, 0x02, 0x10, + 0x08, 0x46, 0x11, 0x08, 0x83, 0x0f, 0xff, 0xff, 0xff, 0xef, 0xcb, 0x46, + 0x00, 0x00, 0xff, 0xef, 0xce, 0x7c, 0xae, 0x7d, 0xee, 0x78, 0x1a, 0x24, + 0x4e, 0x10, 0x1e, 0x25, 0x41, 0x13, 0x09, 0x78, 0x8c, 0x7e, 0x40, 0x2a, + 0x0d, 0x05, 0x38, 0x60, 0x36, 0x68, 0xb8, 0x61, 0x10, 0x76, 0xc1, 0x42, + 0x0c, 0x71, 0x0d, 0xf7, 0xb8, 0x62, 0x30, 0x70, 0x60, 0x40, 0x49, 0xf7, + 0x0b, 0x0c, 0x33, 0x10, 0x81, 0x40, 0x93, 0x78, 0x0e, 0x78, 0xbf, 0x20, + 0x1f, 0x04, 0xc6, 0xc4, 0xe6, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, 0x22, 0x09, 0xaf, 0xf3, 0x03, 0x1c, + 0x43, 0x31, 0x02, 0x14, 0x80, 0x30, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, + 0x55, 0x09, 0x24, 0x00, 0x04, 0x77, 0x45, 0x08, 0x55, 0x01, 0x25, 0x20, + 0x00, 0x00, 0x06, 0xf0, 0x06, 0xf0, 0x08, 0xf0, 0x0d, 0xf0, 0x14, 0xf0, + 0x15, 0x8e, 0x0c, 0xf0, 0x17, 0x8e, 0x0a, 0xf0, 0x0c, 0x9e, 0x81, 0xc3, + 0xa1, 0x41, 0xce, 0x09, 0x20, 0x03, 0xe1, 0x42, 0x0e, 0xf0, 0x1a, 0x8e, + 0x81, 0xc3, 0xa1, 0x41, 0xe2, 0x0a, 0x6f, 0xf5, 0xe1, 0x42, 0x08, 0xf0, + 0x0e, 0x96, 0x81, 0xc3, 0xa1, 0x41, 0xea, 0x0f, 0xaf, 0xf6, 0xe1, 0x42, + 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xd5, 0xf1, + 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xc6, 0xc7, + 0xe8, 0xc2, 0x50, 0x40, 0x28, 0x46, 0x2c, 0x70, 0x10, 0xda, 0x60, 0x40, + 0x88, 0x47, 0x5e, 0x0a, 0x6f, 0xfa, 0x68, 0x45, 0x0c, 0x70, 0x07, 0xee, + 0x0b, 0x08, 0x91, 0x2f, 0x0c, 0x71, 0x00, 0x1d, 0x83, 0x10, 0x00, 0xa7, + 0xc8, 0xc6, 0xe0, 0x78, 0xe8, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, 0x6e, 0x08, 0xaf, 0xf3, 0x03, 0x1c, + 0xc3, 0x31, 0x02, 0x14, 0x80, 0x30, 0x40, 0x26, 0x10, 0x13, 0x03, 0x14, + 0x81, 0x30, 0x0f, 0x78, 0x61, 0x09, 0x24, 0x00, 0x04, 0x77, 0x51, 0x08, + 0xd5, 0x01, 0x25, 0x20, 0x00, 0x00, 0x08, 0xf0, 0x0e, 0xf0, 0x08, 0xf0, + 0x08, 0xf0, 0x0a, 0xf0, 0x11, 0xf0, 0x18, 0xf0, 0x16, 0x8e, 0x10, 0xf0, + 0x04, 0x9e, 0x07, 0xf0, 0x05, 0x9e, 0x05, 0xf0, 0x09, 0x9e, 0x03, 0xf0, + 0x03, 0x9e, 0x81, 0xc3, 0xa1, 0x41, 0x0a, 0x09, 0x20, 0x03, 0xe1, 0x42, + 0x0e, 0xf0, 0x14, 0x8e, 0x81, 0xc3, 0xa1, 0x41, 0x1e, 0x0a, 0x6f, 0xf5, + 0xe1, 0x42, 0x08, 0xf0, 0x81, 0xc3, 0x02, 0x40, 0xa1, 0x41, 0x72, 0x0d, + 0xe0, 0x05, 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, + 0x02, 0x30, 0xcf, 0xf1, 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, + 0x21, 0xad, 0xc8, 0xc7, 0xe4, 0xc3, 0xa5, 0xc1, 0x28, 0x40, 0x2a, 0x68, + 0x34, 0x72, 0x60, 0x00, 0x26, 0x00, 0x2c, 0x70, 0x0d, 0x08, 0xf0, 0x00, + 0x4a, 0x25, 0x00, 0x10, 0x09, 0x08, 0x91, 0x00, 0x8a, 0x25, 0x86, 0x16, + 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x24, 0x0b, 0x30, 0xa8, 0x20, 0xc0, 0x02, + 0xf4, 0x22, 0x43, 0x00, 0xf4, 0x20, 0x40, 0x10, 0x14, 0x23, 0x4c, 0x10, + 0x24, 0x71, 0x62, 0x78, 0x00, 0xb4, 0x80, 0xc0, 0x83, 0xc1, 0x82, 0x0d, + 0xe0, 0x04, 0x83, 0xc6, 0x4a, 0x24, 0xc0, 0x70, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0xc0, 0x02, 0x02, 0x16, 0x02, 0x15, 0x40, 0x24, 0x41, 0x32, + 0x1b, 0x61, 0x04, 0x71, 0x3c, 0x25, 0x81, 0x10, 0x20, 0xab, 0x17, 0xf0, + 0x35, 0x08, 0x71, 0x00, 0x01, 0x40, 0x83, 0xc1, 0x52, 0x0d, 0xe0, 0x04, + 0x83, 0xc5, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x24, 0x41, 0x32, 0xa8, 0x20, + 0xc0, 0x02, 0x02, 0x15, 0x00, 0x15, 0x3c, 0x26, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x0c, 0x01, 0x19, 0x12, 0x00, 0xaa, 0x09, 0xef, 0xf4, 0x40, 0x24, + 0x40, 0x32, 0x00, 0x41, 0x20, 0x40, 0xc4, 0xc7, 0xcd, 0x00, 0x40, 0x03, + 0x38, 0x60, 0xe0, 0x7f, 0x0e, 0x78, 0xe0, 0x78, 0xe8, 0xc2, 0x48, 0x45, + 0x10, 0x40, 0x29, 0x78, 0x54, 0x77, 0xca, 0x25, 0x21, 0x10, 0x15, 0x0d, + 0x32, 0x10, 0x28, 0x47, 0x21, 0x0d, 0x33, 0x18, 0xcd, 0x70, 0x00, 0x28, + 0x4e, 0x03, 0x0c, 0xf0, 0x8c, 0x25, 0x7f, 0x98, 0x86, 0xf6, 0x76, 0x0a, + 0x20, 0x03, 0xb3, 0x79, 0x08, 0x46, 0x04, 0xf0, 0x42, 0x28, 0xce, 0x07, + 0x29, 0x6d, 0x0c, 0x71, 0x38, 0x78, 0x30, 0x79, 0xa0, 0xe1, 0xca, 0x20, + 0x26, 0x00, 0x0b, 0x7e, 0xc0, 0x26, 0x62, 0x10, 0x10, 0xd9, 0x52, 0x0a, + 0x20, 0x03, 0xc1, 0x40, 0x08, 0x45, 0xce, 0x78, 0x46, 0x0a, 0x20, 0x03, + 0x0f, 0xd9, 0x19, 0x0d, 0x20, 0x10, 0x07, 0x27, 0x00, 0x14, 0x3a, 0x0a, + 0x20, 0x03, 0x0f, 0xd9, 0x00, 0x20, 0x8e, 0x0f, 0x00, 0x00, 0xff, 0x7f, + 0xce, 0x78, 0xc8, 0xc6, 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x35, 0x50, 0x40, + 0x08, 0x47, 0x85, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0x32, 0x0a, 0x6f, 0xec, + 0x28, 0x45, 0x00, 0x87, 0x40, 0x24, 0x83, 0x31, 0x40, 0x24, 0x04, 0x33, + 0x40, 0x24, 0x05, 0x34, 0x40, 0x24, 0x06, 0x32, 0x40, 0x24, 0xc7, 0x31, + 0xa1, 0x41, 0x02, 0x42, 0x3e, 0x0e, 0x6f, 0xf3, 0x06, 0x1c, 0xc3, 0x31, + 0x03, 0xc5, 0xad, 0x0d, 0x31, 0x10, 0x2c, 0x70, 0x07, 0x14, 0x8e, 0x30, + 0xad, 0x70, 0xa1, 0x09, 0x31, 0x00, 0xcf, 0x78, 0x06, 0x14, 0x81, 0x30, + 0x95, 0x09, 0x24, 0x00, 0x04, 0x77, 0x79, 0x08, 0xd5, 0x01, 0x25, 0x20, + 0x00, 0x00, 0x08, 0xf0, 0x0c, 0xf0, 0x12, 0xf0, 0x16, 0xf0, 0x1c, 0xf0, + 0x20, 0xf0, 0x26, 0xf0, 0x85, 0xc0, 0x5a, 0x08, 0x6f, 0xf5, 0x82, 0xc1, + 0x16, 0xaf, 0x2c, 0xf0, 0x85, 0xc0, 0x76, 0x0a, 0xa0, 0x03, 0x82, 0xc1, + 0x03, 0xb7, 0x26, 0xf0, 0x85, 0xc0, 0x6a, 0x0a, 0xa0, 0x03, 0x82, 0xc1, + 0x04, 0xb7, 0x20, 0xf0, 0x85, 0xc0, 0x5e, 0x0a, 0xa0, 0x03, 0x82, 0xc1, + 0x05, 0xb7, 0x1a, 0xf0, 0x85, 0xc0, 0x52, 0x0a, 0xa0, 0x03, 0x82, 0xc1, + 0x09, 0xb7, 0x14, 0xf0, 0x85, 0xc0, 0x1e, 0x08, 0x6f, 0xf5, 0x82, 0xc1, + 0x14, 0xaf, 0x0e, 0xf0, 0x85, 0xc0, 0x82, 0xc1, 0x5e, 0x0b, 0xe0, 0x05, + 0x80, 0xc2, 0x83, 0x40, 0x40, 0x90, 0x21, 0x90, 0x02, 0x90, 0x46, 0xb7, + 0x27, 0xb7, 0x08, 0xb7, 0x02, 0xc0, 0x8a, 0x21, 0x3e, 0x06, 0x12, 0x70, + 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, 0x01, 0x20, 0x3d, 0x20, 0x00, 0x20, + 0x1e, 0x66, 0xb3, 0xf1, 0xa1, 0x40, 0xc8, 0xc7, 0x48, 0x31, 0x01, 0x00, + 0x07, 0x36, 0x42, 0x70, 0x48, 0x47, 0x00, 0x00, 0x28, 0x80, 0x04, 0x31, + 0x80, 0x80, 0xe0, 0x7c, 0x04, 0x18, 0x43, 0x00, 0xe0, 0x7f, 0x48, 0xa0, + 0xfa, 0xc2, 0xfc, 0x1c, 0xc8, 0xb6, 0x82, 0x24, 0x03, 0x38, 0x04, 0x15, + 0x0c, 0x00, 0x6d, 0x70, 0x0a, 0x21, 0x40, 0x21, 0x04, 0x34, 0xc0, 0x92, + 0x0a, 0x20, 0xc0, 0x21, 0x0a, 0x25, 0x80, 0x21, 0x0a, 0x21, 0x00, 0x31, + 0x70, 0x42, 0x58, 0x43, 0x08, 0x46, 0xc8, 0xf6, 0x01, 0x34, 0x8d, 0x1f, + 0x00, 0x3f, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x34, 0x8d, 0x1f, + 0x00, 0xbf, 0x00, 0x00, 0x47, 0x14, 0x0f, 0x36, 0x4a, 0x24, 0xc0, 0x70, + 0x55, 0x24, 0x40, 0x3d, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x11, 0x02, 0x04, + 0x00, 0x32, 0x82, 0x0f, 0x83, 0x3a, 0x6f, 0x12, 0x04, 0x18, 0x90, 0x00, + 0x55, 0x24, 0x41, 0x3d, 0x55, 0x24, 0x82, 0x3c, 0xc1, 0x40, 0x9e, 0x0d, + 0x6f, 0xee, 0x55, 0x24, 0x93, 0x3c, 0x48, 0x35, 0xc0, 0x12, 0x55, 0x24, + 0x44, 0x3d, 0x1d, 0x78, 0x55, 0x24, 0xc5, 0x3b, 0x44, 0x20, 0x43, 0x00, + 0xc1, 0x40, 0x42, 0x41, 0x23, 0x42, 0x55, 0x24, 0xcd, 0x3b, 0x92, 0x0c, + 0xaf, 0xee, 0x70, 0x44, 0x4a, 0x24, 0xc0, 0x70, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0x80, 0x03, 0x01, 0x4d, 0xf0, 0x23, 0x03, 0x20, 0x55, 0x24, + 0x02, 0x3b, 0x00, 0x31, 0x41, 0x05, 0x15, 0x7a, 0x01, 0x33, 0x41, 0x00, + 0x04, 0x71, 0x20, 0xa2, 0x61, 0x86, 0x49, 0x86, 0x28, 0x4e, 0x55, 0x24, + 0x01, 0x3b, 0x55, 0x24, 0x04, 0x3a, 0x8e, 0x0a, 0xef, 0xf2, 0x10, 0x46, + 0x55, 0x24, 0x01, 0x3a, 0x10, 0xda, 0x6e, 0x08, 0x6f, 0xec, 0xc2, 0x40, + 0x55, 0x24, 0x01, 0x3a, 0x32, 0x09, 0xef, 0xf2, 0xc2, 0x40, 0x55, 0x24, + 0x01, 0x3a, 0x10, 0xda, 0x56, 0x08, 0x6f, 0xec, 0xc2, 0x40, 0x3c, 0x86, + 0xc1, 0x40, 0xba, 0x0e, 0x6f, 0xee, 0x82, 0x42, 0x8a, 0x23, 0x44, 0x2b, + 0x32, 0x26, 0xd4, 0x14, 0x5d, 0x0c, 0x30, 0x20, 0x10, 0x45, 0x55, 0x26, + 0x57, 0x18, 0x4a, 0x20, 0x00, 0x30, 0x80, 0xc5, 0x10, 0xda, 0xa1, 0x40, + 0x2a, 0x08, 0x6f, 0xec, 0xe2, 0x41, 0x07, 0x71, 0x10, 0xe5, 0xf5, 0x08, + 0x74, 0xb2, 0x40, 0x27, 0x17, 0x24, 0x10, 0xda, 0xa1, 0x40, 0x16, 0x08, + 0x6f, 0xec, 0xc2, 0x41, 0x54, 0x26, 0x8d, 0x1e, 0x4a, 0x20, 0x00, 0x30, + 0x40, 0x24, 0x17, 0x30, 0x10, 0xda, 0xa1, 0x40, 0xfe, 0x0f, 0x2f, 0xec, + 0xe2, 0x41, 0x07, 0x71, 0x10, 0xe5, 0xf5, 0x08, 0xb4, 0xb2, 0x40, 0x27, + 0x17, 0x24, 0x00, 0x8d, 0x09, 0x08, 0xb5, 0x02, 0x04, 0x71, 0x00, 0xad, + 0x41, 0x09, 0x11, 0x30, 0x3d, 0x0c, 0x30, 0x20, 0x55, 0x24, 0x43, 0x3d, + 0x36, 0x40, 0x2f, 0x31, 0xc0, 0x06, 0x2f, 0x32, 0x00, 0x00, 0xc1, 0x40, + 0x36, 0x0d, 0x6f, 0xee, 0x55, 0x24, 0x4d, 0x3d, 0x4a, 0x24, 0xc0, 0x70, + 0x56, 0x26, 0xc1, 0x18, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x15, 0x00, 0x14, + 0x00, 0x30, 0x80, 0x0f, 0x6a, 0x44, 0xfb, 0xae, 0x04, 0x19, 0x10, 0x00, + 0x5e, 0x40, 0x00, 0xa1, 0x4a, 0x24, 0x00, 0x71, 0x0a, 0x20, 0x00, 0x04, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x16, 0x01, 0x24, 0x04, 0x18, 0x50, 0x00, + 0x00, 0x18, 0x40, 0x05, 0x8a, 0x20, 0x04, 0x0b, 0x08, 0x66, 0x0f, 0xe8, + 0x0c, 0x70, 0x04, 0x31, 0x00, 0x80, 0x4b, 0xf7, 0x4a, 0x24, 0x00, 0x71, + 0xa8, 0x20, 0xc0, 0x01, 0x06, 0x40, 0x52, 0x20, 0xc0, 0x07, 0x04, 0x18, + 0x10, 0x20, 0x32, 0x26, 0xc0, 0x14, 0x0d, 0xe8, 0x4a, 0x24, 0x00, 0x71, + 0x56, 0x26, 0xc0, 0x18, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x01, 0x04, + 0x04, 0x1f, 0x50, 0x10, 0x06, 0xf0, 0x0c, 0x70, 0x03, 0xa7, 0x02, 0xa7, + 0x01, 0xa7, 0x00, 0xa7, 0x80, 0x24, 0x03, 0x38, 0x04, 0x14, 0x1b, 0x34, + 0xda, 0xc6, 0xe0, 0x78, 0xea, 0xc3, 0xb0, 0xc1, 0x4a, 0x24, 0xc0, 0x70, + 0xc8, 0x46, 0x0a, 0x21, 0x40, 0x21, 0x70, 0x40, 0x48, 0x40, 0x08, 0x45, + 0x4a, 0x20, 0x00, 0x00, 0x40, 0x24, 0x06, 0x3d, 0x40, 0x24, 0x09, 0x3a, + 0xa8, 0x20, 0x40, 0x05, 0x03, 0x49, 0xf0, 0x20, 0x0c, 0x10, 0x15, 0x26, + 0x02, 0x00, 0x00, 0x33, 0x8b, 0x0f, 0x83, 0x3a, 0x6f, 0x12, 0x15, 0x21, + 0x0f, 0x10, 0x00, 0x34, 0x83, 0x1f, 0x7a, 0x3d, 0x00, 0x00, 0x04, 0x71, + 0x00, 0x1a, 0xc0, 0x02, 0x60, 0xa7, 0x8d, 0xc1, 0x8a, 0xc2, 0x40, 0x24, + 0x05, 0x37, 0xa1, 0x40, 0x02, 0x43, 0xc6, 0x09, 0xef, 0xee, 0x87, 0xc7, + 0x4a, 0x24, 0xc0, 0x70, 0x4a, 0x20, 0x00, 0x00, 0xa8, 0x20, 0x40, 0x03, + 0x8a, 0xc1, 0x02, 0x4f, 0x04, 0x49, 0x80, 0xc3, 0x00, 0x32, 0x41, 0x04, + 0x15, 0x7b, 0x01, 0x34, 0x41, 0x10, 0x04, 0x71, 0x20, 0xa3, 0x80, 0xc1, + 0x83, 0xc2, 0xfe, 0x0d, 0xef, 0xee, 0xa1, 0x40, 0x40, 0x25, 0x0f, 0x1b, + 0x83, 0xc1, 0x10, 0xda, 0xa6, 0x0e, 0x2f, 0xec, 0xe1, 0x40, 0x1d, 0x08, + 0x31, 0x20, 0x8d, 0xc0, 0x80, 0xc2, 0xde, 0x0d, 0xaf, 0xee, 0xe1, 0x41, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x53, 0xa5, 0x34, 0xa5, 0x15, 0xa5, + 0x4a, 0x24, 0x00, 0x71, 0x0a, 0x21, 0x80, 0x03, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x17, 0x02, 0x14, 0x04, 0x19, 0x90, 0x00, 0x00, 0x8f, 0x48, 0x30, + 0x00, 0x00, 0x00, 0xa1, 0x0c, 0x8d, 0x0f, 0xe8, 0x0c, 0x70, 0x04, 0x32, + 0x00, 0x80, 0x4b, 0xf7, 0x4a, 0x24, 0x00, 0x71, 0xa8, 0x20, 0xc0, 0x01, + 0x00, 0x86, 0x52, 0x20, 0xc0, 0x07, 0x04, 0x1e, 0x10, 0x10, 0xca, 0xc7, + 0x08, 0x44, 0x6c, 0x70, 0x0c, 0x70, 0x62, 0x4c, 0x04, 0x32, 0x40, 0x80, + 0x4c, 0x70, 0xca, 0x22, 0x6c, 0x00, 0x5b, 0x63, 0xca, 0x20, 0x69, 0x00, + 0x74, 0x73, 0xe0, 0x20, 0xcd, 0x07, 0xf5, 0xea, 0xe0, 0x7e, 0xe0, 0x78, + 0xe6, 0xc0, 0x76, 0x10, 0x8b, 0x00, 0x7f, 0xdd, 0x28, 0x40, 0x48, 0x33, + 0x0b, 0x10, 0x8a, 0x27, 0x09, 0x1d, 0x50, 0x21, 0xfe, 0x87, 0x17, 0xbd, + 0x00, 0x20, 0x8c, 0x0f, 0x00, 0x00, 0x24, 0x02, 0xca, 0x20, 0x41, 0x13, + 0x04, 0x33, 0xc0, 0x90, 0x1f, 0x67, 0x0e, 0xf7, 0x32, 0x24, 0x8b, 0x1f, + 0xff, 0xff, 0xd4, 0xfe, 0x11, 0x0b, 0x31, 0x10, 0x8a, 0x26, 0x04, 0x15, + 0xce, 0x60, 0xdb, 0x0e, 0x30, 0x10, 0xcd, 0x70, 0x60, 0x8f, 0x06, 0xeb, + 0xc3, 0x42, 0x49, 0x40, 0xdb, 0x0f, 0x4d, 0xf0, 0x32, 0x24, 0x83, 0x1f, + 0xff, 0xff, 0xa8, 0xfe, 0x0f, 0xeb, 0x50, 0x22, 0xfe, 0x87, 0xca, 0x22, + 0x41, 0x03, 0x48, 0x32, 0xc2, 0x02, 0x3e, 0x84, 0x15, 0x20, 0x82, 0x00, + 0xa3, 0x12, 0x02, 0x06, 0x01, 0x32, 0x42, 0x00, 0x5e, 0xa4, 0x54, 0x8f, + 0x0e, 0xea, 0x32, 0x24, 0x82, 0x1f, 0xff, 0xff, 0xd4, 0xfe, 0x86, 0xea, + 0x80, 0x20, 0x04, 0x05, 0x00, 0x88, 0x06, 0xe8, 0xc3, 0x40, 0xb2, 0x3d, + 0xc2, 0xb8, 0x1a, 0xa4, 0x48, 0x30, 0xc0, 0x12, 0x35, 0x84, 0x04, 0x77, + 0x48, 0x30, 0x80, 0x00, 0xdf, 0x84, 0x00, 0x30, 0x80, 0x0f, 0x32, 0xbe, + 0xc2, 0xb8, 0x5a, 0x84, 0x01, 0x30, 0x80, 0x0f, 0xb2, 0x3e, 0xc2, 0xb8, + 0x77, 0x84, 0x01, 0x30, 0x40, 0x00, 0x02, 0x35, 0x81, 0x13, 0x01, 0x30, + 0x80, 0x00, 0xc3, 0x42, 0x49, 0x40, 0xdb, 0x0f, 0x00, 0x31, 0xc3, 0x00, + 0x04, 0x30, 0x80, 0x80, 0xca, 0x22, 0x05, 0x00, 0x3e, 0x84, 0x00, 0x36, + 0x80, 0x10, 0x56, 0xa4, 0x01, 0x33, 0x00, 0x00, 0x01, 0x30, 0x42, 0x00, + 0x17, 0xa4, 0xc3, 0x43, 0xb2, 0x3d, 0xc2, 0xb8, 0xc3, 0x41, 0x49, 0x40, + 0xdb, 0x0f, 0x04, 0x32, 0xc0, 0x80, 0x20, 0x40, 0xca, 0x20, 0xc5, 0x00, + 0x04, 0x32, 0x40, 0x80, 0xca, 0x21, 0x05, 0x00, 0x20, 0x40, 0xca, 0x20, + 0x85, 0x00, 0x04, 0x32, 0xc0, 0x80, 0xca, 0x20, 0x45, 0x00, 0x18, 0xa4, + 0xc6, 0xc4, 0x48, 0x33, 0xc2, 0x02, 0x20, 0x8f, 0x14, 0x1f, 0x43, 0x10, + 0xde, 0xa4, 0xf0, 0x26, 0x82, 0x70, 0x13, 0x00, 0xf8, 0x6b, 0xda, 0xa4, + 0x0f, 0x09, 0x71, 0x00, 0x55, 0xa4, 0x80, 0x20, 0x09, 0x0d, 0x2c, 0x70, + 0xc0, 0xa8, 0x18, 0x84, 0x0d, 0x09, 0x31, 0x80, 0x17, 0xa4, 0xaa, 0xf1, + 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x34, 0x50, 0x40, 0x08, 0x47, 0x84, 0xc0, + 0x8a, 0x22, 0x0c, 0x00, 0xd2, 0x0c, 0x2f, 0xec, 0x28, 0x45, 0x00, 0x87, + 0x40, 0x24, 0x83, 0x30, 0x40, 0x24, 0x04, 0x32, 0x40, 0x24, 0x05, 0x33, + 0x40, 0x24, 0x06, 0x31, 0x40, 0x24, 0xc7, 0x30, 0xa1, 0x41, 0x02, 0x42, + 0xde, 0x08, 0x6f, 0xf3, 0x02, 0x1c, 0x43, 0x35, 0x02, 0xc5, 0x9d, 0xed, + 0x03, 0x14, 0x8e, 0x30, 0xad, 0x70, 0x2c, 0x70, 0x97, 0xe9, 0x02, 0x14, + 0x80, 0x30, 0xcf, 0x79, 0x27, 0x08, 0x64, 0x00, 0x84, 0xc2, 0x81, 0xc3, + 0x7a, 0x0a, 0x60, 0x00, 0xe1, 0x40, 0x01, 0xc0, 0x8a, 0x21, 0x3e, 0x06, + 0x12, 0x70, 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, 0x01, 0x20, 0x3d, 0x20, + 0x00, 0x20, 0x1e, 0x66, 0xea, 0xf1, 0xa1, 0x40, 0xc8, 0xc7, 0xe0, 0x78, + 0xf2, 0xc3, 0xb3, 0xc1, 0x0a, 0x25, 0x80, 0x21, 0x0a, 0x26, 0x40, 0x01, + 0x0a, 0x22, 0x00, 0x21, 0x70, 0x41, 0x48, 0x47, 0x30, 0x40, 0x11, 0x0f, + 0xfe, 0x01, 0x08, 0x45, 0x44, 0x27, 0x40, 0x00, 0xcc, 0x1d, 0x02, 0x10, + 0x80, 0x14, 0x0e, 0x30, 0x78, 0x14, 0x13, 0x30, 0x4a, 0x24, 0xc0, 0x70, + 0x4a, 0x20, 0x00, 0x00, 0x54, 0x24, 0x09, 0x38, 0x40, 0x24, 0x08, 0x3d, + 0xa8, 0x20, 0x40, 0x05, 0xf0, 0x20, 0x01, 0x20, 0x02, 0x4f, 0x15, 0x21, + 0x0b, 0x10, 0x00, 0x31, 0x8c, 0x0f, 0x83, 0x3a, 0x6f, 0x12, 0x15, 0x20, + 0x03, 0x10, 0x00, 0x32, 0x81, 0x0f, 0x7a, 0x3d, 0x00, 0x00, 0x04, 0x71, + 0x00, 0x1b, 0x00, 0x13, 0x20, 0xa3, 0x90, 0xc1, 0x8d, 0xc2, 0x40, 0x24, + 0x05, 0x3a, 0x0a, 0x24, 0x80, 0x01, 0xa1, 0x40, 0x42, 0x43, 0x6a, 0x0d, + 0xef, 0xf4, 0x40, 0x24, 0x14, 0x3a, 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, + 0x00, 0x02, 0x86, 0x40, 0x00, 0x30, 0xc0, 0x04, 0x04, 0x1c, 0x10, 0x20, + 0x8d, 0xc1, 0x40, 0x24, 0x04, 0x37, 0xa2, 0x43, 0xa1, 0x40, 0x22, 0x42, + 0x40, 0x24, 0x13, 0x3d, 0xbe, 0x0b, 0x20, 0x00, 0x40, 0x24, 0x14, 0x37, + 0x1e, 0x85, 0x36, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x00, 0x30, 0x80, 0x0f, + 0x74, 0x49, 0x00, 0x24, 0x07, 0x30, 0x4b, 0x00, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0x80, 0x04, 0x8a, 0xc1, 0xf0, 0x23, 0x02, 0x20, 0x01, 0x49, + 0xf0, 0x24, 0x03, 0x20, 0x01, 0x32, 0x4c, 0x00, 0x80, 0xc2, 0x00, 0x33, + 0xc1, 0x10, 0x15, 0x7a, 0x01, 0x34, 0x41, 0x10, 0x04, 0x71, 0x20, 0xa2, + 0x80, 0xc1, 0x83, 0xc2, 0x9e, 0x08, 0x2f, 0xf5, 0xa1, 0x40, 0x5c, 0x4d, + 0x83, 0xc1, 0x10, 0xda, 0x76, 0x0b, 0x2f, 0xec, 0x10, 0x43, 0x1d, 0x0a, + 0x31, 0x20, 0x90, 0xc0, 0x80, 0xc2, 0xae, 0x0a, 0xaf, 0xee, 0x62, 0x41, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x53, 0xa5, 0x34, 0xa5, 0x15, 0xa5, + 0x3e, 0x43, 0x43, 0x87, 0x1e, 0x41, 0x2e, 0x0d, 0xef, 0xff, 0xa1, 0x40, + 0x4a, 0x24, 0x00, 0x71, 0x0a, 0x21, 0x80, 0x03, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x13, 0x02, 0x24, 0x04, 0x19, 0x90, 0x00, 0xa1, 0x15, 0x00, 0x16, + 0x00, 0xa1, 0x0c, 0x8d, 0x0f, 0xe8, 0x4a, 0x20, 0x00, 0x00, 0x04, 0x32, + 0x00, 0x80, 0x4b, 0xf7, 0x4a, 0x24, 0x00, 0x71, 0xa8, 0x20, 0xc0, 0x01, + 0x00, 0x86, 0x52, 0x20, 0xc0, 0x07, 0x04, 0x1e, 0x10, 0x10, 0xd2, 0xc7, + 0xe8, 0xc3, 0xa2, 0xc1, 0x08, 0x45, 0x00, 0x80, 0x60, 0x44, 0x40, 0x24, + 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x50, 0x40, + 0x28, 0x46, 0x55, 0x25, 0x0f, 0x18, 0x7a, 0x0f, 0x2f, 0xf3, 0x03, 0x1c, + 0x43, 0x35, 0x02, 0x14, 0x80, 0x30, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, + 0xed, 0x09, 0x24, 0x00, 0x04, 0x77, 0x67, 0x08, 0x95, 0x02, 0x25, 0x20, + 0x00, 0x00, 0x0b, 0xf0, 0x0b, 0xf0, 0x0d, 0xf0, 0x0d, 0xf0, 0x0f, 0xf0, + 0x0f, 0xf0, 0x17, 0xf0, 0x1d, 0xf0, 0x1f, 0xf0, 0x1f, 0xf0, 0x0c, 0x8d, + 0x0b, 0xf0, 0x05, 0x85, 0x1c, 0xf0, 0x06, 0x85, 0x1a, 0xf0, 0x07, 0x85, + 0x18, 0xf0, 0x08, 0x85, 0x16, 0xf0, 0x24, 0x15, 0x80, 0x10, 0x81, 0xc3, + 0xc1, 0x41, 0x5e, 0x0d, 0x2f, 0xfa, 0x02, 0x42, 0x13, 0xf0, 0x25, 0x15, + 0x80, 0x10, 0x81, 0xc3, 0xc1, 0x41, 0x22, 0x09, 0x2f, 0xf5, 0x02, 0x42, + 0x0b, 0xf0, 0x18, 0x85, 0x04, 0xf0, 0x19, 0x85, 0x02, 0xf0, 0x04, 0x85, + 0x81, 0xc3, 0xc1, 0x41, 0x1e, 0x0f, 0x6f, 0xf7, 0x02, 0x42, 0x02, 0x14, + 0x80, 0x30, 0x6b, 0xb8, 0x71, 0x08, 0xd5, 0x02, 0x25, 0x20, 0x00, 0x00, + 0x0b, 0xf0, 0x0e, 0xf0, 0x0f, 0xf0, 0x12, 0xf0, 0x18, 0xf0, 0x20, 0xf0, + 0x20, 0xf0, 0x22, 0xf0, 0x22, 0xf0, 0x24, 0xf0, 0x24, 0xf0, 0x68, 0x15, + 0x80, 0x10, 0x12, 0xf0, 0x69, 0x15, 0x80, 0x10, 0x06, 0xf0, 0x74, 0x15, + 0x80, 0x10, 0x04, 0xf0, 0x75, 0x15, 0x80, 0x10, 0x81, 0xc3, 0xc1, 0x41, + 0xf2, 0x0c, 0x2f, 0xfa, 0x02, 0x42, 0x1a, 0xf0, 0x76, 0x15, 0x80, 0x10, + 0x81, 0xc3, 0xc1, 0x41, 0xb6, 0x08, 0x2f, 0xf5, 0x02, 0x42, 0x12, 0xf0, + 0x1b, 0x85, 0x0b, 0xf0, 0x01, 0x87, 0x09, 0xf0, 0x02, 0x87, 0x07, 0xf0, + 0x1c, 0x85, 0x05, 0xf0, 0x00, 0x87, 0x03, 0xf0, 0x12, 0x87, 0x81, 0xc3, + 0xc1, 0x41, 0xaa, 0x0e, 0x6f, 0xf7, 0x02, 0x42, 0x02, 0x14, 0x80, 0x30, + 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0x89, 0xf1, 0x01, 0xc0, 0x41, 0x28, + 0x01, 0x02, 0x00, 0xae, 0x21, 0xae, 0xc8, 0xc7, 0xe8, 0xc3, 0xa3, 0xc1, + 0x48, 0x47, 0x28, 0x45, 0x2c, 0x70, 0x10, 0xda, 0x60, 0x40, 0x0a, 0x20, + 0x00, 0x21, 0x1a, 0x08, 0x2f, 0xfa, 0x68, 0x46, 0x2c, 0x70, 0x0a, 0x22, + 0x80, 0x0f, 0x13, 0x00, 0x08, 0x6c, 0x33, 0xed, 0x4a, 0x24, 0x00, 0x71, + 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x03, 0x04, 0x80, 0xc0, 0x3c, 0x60, + 0x24, 0x71, 0x38, 0x23, 0xc0, 0x03, 0x00, 0xac, 0x22, 0x0b, 0x6f, 0xf5, + 0x80, 0xc0, 0x38, 0xe8, 0x0f, 0xdd, 0x0e, 0x1e, 0x43, 0x15, 0x0d, 0x1e, + 0x03, 0x15, 0x0c, 0x1e, 0xc3, 0x14, 0x0b, 0x1e, 0x83, 0x13, 0x0a, 0x1e, + 0x43, 0x13, 0x09, 0x1e, 0xc3, 0x12, 0x08, 0x1e, 0x43, 0x12, 0x07, 0x1e, + 0x03, 0x12, 0x06, 0x1e, 0xc3, 0x11, 0x05, 0x1e, 0x83, 0x11, 0x04, 0x1e, + 0x43, 0x11, 0x03, 0x1e, 0x03, 0x11, 0x02, 0x1e, 0xc3, 0x10, 0x01, 0x1e, + 0x83, 0x10, 0x00, 0x1e, 0x43, 0x10, 0x33, 0x00, 0x00, 0x00, 0x4a, 0x24, + 0x40, 0x71, 0x10, 0xe2, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x03, 0x04, + 0x81, 0xc0, 0x3c, 0x60, 0x24, 0x71, 0x38, 0x23, 0xc0, 0x03, 0x00, 0xac, + 0x1a, 0x0e, 0x6f, 0xf7, 0x81, 0xc0, 0x26, 0xe8, 0xad, 0x71, 0x00, 0x1e, + 0xc3, 0x11, 0x23, 0xf0, 0xad, 0x70, 0x1b, 0x0f, 0xb0, 0x19, 0xb8, 0x66, + 0x19, 0x0f, 0x71, 0x1c, 0xb8, 0x66, 0xa5, 0x72, 0x01, 0x18, 0x83, 0x03, + 0x00, 0x18, 0x43, 0x03, 0x04, 0xf0, 0xa5, 0x71, 0x00, 0x18, 0xc3, 0x02, + 0xbe, 0x08, 0x2f, 0xf7, 0x78, 0x27, 0x00, 0x1c, 0x05, 0xe8, 0xb8, 0x66, + 0xa5, 0x71, 0x00, 0x18, 0x83, 0x01, 0x13, 0x0f, 0x71, 0x1e, 0xbe, 0x66, + 0xa5, 0x71, 0x00, 0x1e, 0x83, 0x12, 0x03, 0xf0, 0xad, 0x70, 0x00, 0x18, + 0x40, 0x23, 0xc8, 0xc7, 0xf0, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x50, 0x44, 0x28, 0x45, 0x5e, 0x0d, 0x2f, 0xf3, 0x03, 0x1c, + 0x03, 0x32, 0x02, 0x14, 0x80, 0x30, 0x55, 0x26, 0x93, 0x1b, 0x55, 0x26, + 0x12, 0x19, 0x54, 0x26, 0x10, 0x18, 0x54, 0x26, 0x8f, 0x19, 0x40, 0x26, + 0x11, 0x1b, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0x95, 0x09, 0x24, 0x00, + 0x04, 0x77, 0x53, 0x08, 0x55, 0x01, 0x25, 0x20, 0x00, 0x00, 0x06, 0xf0, + 0x0b, 0xf0, 0x12, 0xf0, 0x18, 0xf0, 0x1b, 0xf0, 0x81, 0xc3, 0x22, 0x40, + 0xa1, 0x41, 0x26, 0x0c, 0x6f, 0xfa, 0x82, 0x42, 0x19, 0xf0, 0x0a, 0x86, + 0x81, 0xc3, 0xa1, 0x41, 0x32, 0x0a, 0x6f, 0xef, 0x82, 0x42, 0x13, 0xf0, + 0x3c, 0x16, 0x80, 0x10, 0x81, 0xc3, 0xa1, 0x41, 0x2e, 0x0b, 0x2f, 0xfa, + 0x82, 0x42, 0x0b, 0xf0, 0x81, 0xc3, 0x02, 0x40, 0x03, 0xf0, 0x81, 0xc3, + 0xe1, 0x40, 0xa1, 0x41, 0x6e, 0x0f, 0x6f, 0xf7, 0x82, 0x42, 0x02, 0x14, + 0x80, 0x30, 0x27, 0x08, 0x30, 0x02, 0x81, 0xc3, 0x11, 0x08, 0xf0, 0x01, + 0x81, 0xc3, 0x25, 0x08, 0xb1, 0x01, 0x81, 0xc3, 0x62, 0x40, 0x0a, 0xf0, + 0x8c, 0x16, 0x80, 0x10, 0xa1, 0x41, 0xf6, 0x0a, 0x2f, 0xfa, 0x82, 0x42, + 0x06, 0xf0, 0x42, 0x40, 0xa1, 0x41, 0xc2, 0x0b, 0x6f, 0xfa, 0x82, 0x42, + 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xb5, 0xf1, + 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xd0, 0xc7, + 0xec, 0xc3, 0xb3, 0xc1, 0x88, 0x47, 0x48, 0x45, 0x30, 0x42, 0x10, 0x41, + 0x2c, 0x70, 0x74, 0x70, 0x22, 0xa7, 0x21, 0xa7, 0x20, 0xa7, 0x26, 0xf4, + 0x4a, 0x24, 0xc0, 0x70, 0x55, 0x21, 0x4e, 0x28, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0xc0, 0x02, 0x02, 0x4d, 0x90, 0xc3, 0x15, 0x7b, 0x00, 0x32, + 0x82, 0x0f, 0xcc, 0x3d, 0xcd, 0xcc, 0x04, 0x71, 0x40, 0xa3, 0x69, 0x11, + 0x80, 0x20, 0x14, 0x70, 0x0c, 0x70, 0x0e, 0xf2, 0x48, 0x16, 0x82, 0x10, + 0x90, 0xc1, 0xc2, 0x0b, 0x20, 0x00, 0x22, 0x40, 0x8a, 0x21, 0x04, 0x05, + 0x74, 0x16, 0x80, 0x10, 0x32, 0x21, 0x41, 0x20, 0x05, 0x20, 0x7e, 0x80, + 0x6a, 0x03, 0x22, 0x00, 0x2c, 0x70, 0x03, 0x85, 0x04, 0x30, 0x40, 0x80, + 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x76, 0x11, 0x81, 0x20, + 0x48, 0x30, 0xc0, 0x02, 0x0f, 0x78, 0x30, 0x70, 0x3e, 0x03, 0x05, 0x00, + 0x08, 0x8e, 0x0f, 0xe8, 0x68, 0x11, 0x80, 0x20, 0x31, 0x08, 0xb1, 0x00, + 0x08, 0x1e, 0x03, 0x10, 0x40, 0x21, 0x00, 0x2b, 0x90, 0xc1, 0x9a, 0x08, + 0xaf, 0xf2, 0x80, 0xc2, 0x20, 0xf0, 0x75, 0x11, 0x80, 0x20, 0xed, 0x08, + 0x30, 0x00, 0x40, 0x21, 0x0d, 0x2b, 0x55, 0x21, 0x00, 0x29, 0x84, 0xc2, + 0x1a, 0x0f, 0x6f, 0xf2, 0xa1, 0x41, 0x71, 0xf0, 0x55, 0x21, 0x8d, 0x2b, + 0x90, 0xc1, 0x80, 0xc2, 0x6e, 0x08, 0xaf, 0xf2, 0x0a, 0x20, 0x40, 0x03, + 0x4a, 0x24, 0x00, 0x71, 0x40, 0x21, 0x00, 0x2b, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x10, 0x01, 0x04, 0x04, 0x1d, 0x50, 0x10, 0xad, 0x70, 0x80, 0xc0, + 0x6a, 0x0f, 0xef, 0xf3, 0x42, 0xc5, 0x01, 0xc1, 0x7f, 0xda, 0x17, 0xba, + 0x4f, 0x22, 0xcc, 0x07, 0x89, 0x43, 0x04, 0x31, 0x80, 0x80, 0x40, 0x43, + 0xca, 0x24, 0x89, 0x10, 0x04, 0x31, 0xc0, 0x82, 0x20, 0x40, 0xca, 0x23, + 0x05, 0x03, 0x04, 0x31, 0x80, 0x80, 0xca, 0x20, 0xc9, 0x00, 0x04, 0x31, + 0xc0, 0x82, 0x32, 0x0b, 0x6f, 0xf4, 0xca, 0x20, 0xc5, 0x00, 0x08, 0x46, + 0xc3, 0x40, 0x49, 0x40, 0xdb, 0x0f, 0x04, 0x36, 0x00, 0x90, 0x84, 0xf6, + 0x02, 0x30, 0x8e, 0x03, 0x00, 0xc0, 0x43, 0xc0, 0x8e, 0x09, 0x6f, 0xf5, + 0x83, 0xc0, 0x00, 0x36, 0x8e, 0x1f, 0x00, 0x3f, 0x00, 0x00, 0x45, 0xc5, + 0xc1, 0x40, 0x92, 0x0c, 0xaf, 0xf6, 0x44, 0xc5, 0x47, 0xc0, 0xda, 0x09, + 0xef, 0xfa, 0xc1, 0x40, 0x03, 0xc1, 0x75, 0x11, 0x82, 0x20, 0x00, 0x30, + 0x40, 0x00, 0x46, 0xc0, 0x06, 0xea, 0x55, 0x21, 0x00, 0x29, 0x84, 0xc1, + 0x10, 0xda, 0x10, 0xf0, 0x40, 0x21, 0x0d, 0x2b, 0x84, 0xc0, 0x88, 0xc2, + 0x5a, 0x0e, 0x6f, 0xf2, 0xa1, 0x41, 0x88, 0xc0, 0x56, 0x0f, 0x6f, 0xf2, + 0x8c, 0xc1, 0x8c, 0xc1, 0x10, 0xda, 0xa1, 0x40, 0x7a, 0x0e, 0xcf, 0xeb, + 0x29, 0x02, 0x00, 0x00, 0x84, 0xc0, 0x10, 0xda, 0x6e, 0x0e, 0xef, 0xeb, + 0xa1, 0x41, 0x68, 0x11, 0x90, 0x20, 0x84, 0xc0, 0x90, 0xc1, 0x92, 0x0f, + 0x6f, 0xf2, 0x80, 0xc2, 0x19, 0x08, 0xb0, 0x20, 0x4a, 0x24, 0x00, 0x71, + 0x55, 0x21, 0x80, 0x2b, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x15, 0x01, 0x14, + 0x04, 0x18, 0x50, 0x00, 0x80, 0xc0, 0xad, 0x70, 0x8a, 0x0e, 0xef, 0xf3, + 0x08, 0x1c, 0x01, 0x30, 0x01, 0xc0, 0x00, 0xc1, 0x04, 0x30, 0x40, 0x83, + 0x48, 0xc1, 0x45, 0xf7, 0xea, 0x08, 0x6f, 0xf5, 0x88, 0xc0, 0x40, 0x21, + 0x00, 0x2b, 0xbe, 0x0b, 0x6f, 0xf2, 0x84, 0xc1, 0x84, 0xc0, 0xce, 0x0b, + 0x6f, 0xf2, 0xe1, 0x41, 0x08, 0xc2, 0x4a, 0x24, 0xc0, 0x70, 0xe1, 0x40, + 0xa8, 0x20, 0xc0, 0x01, 0x20, 0x80, 0x00, 0x32, 0x41, 0x00, 0x04, 0x18, + 0x50, 0x00, 0x74, 0x11, 0x80, 0x20, 0x30, 0xe8, 0x4a, 0x24, 0xc0, 0x70, + 0x4c, 0x70, 0x42, 0x43, 0x0c, 0x70, 0x43, 0xc2, 0xa8, 0x20, 0x00, 0x02, + 0x04, 0x13, 0x01, 0x04, 0x00, 0x31, 0x41, 0x00, 0x01, 0x30, 0x40, 0x00, + 0x04, 0x30, 0x80, 0x8f, 0x61, 0x44, 0x00, 0x00, 0x43, 0xc0, 0xc6, 0xf6, + 0x00, 0x30, 0x82, 0x0f, 0xbc, 0x38, 0x62, 0xbe, 0x7f, 0xd8, 0x17, 0xb8, + 0x04, 0x32, 0x00, 0x80, 0x6c, 0x11, 0x03, 0x20, 0xca, 0x20, 0x85, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0x00, 0x30, 0x01, 0x00, 0xa8, 0x20, 0x40, 0x02, + 0x00, 0x87, 0x00, 0x33, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x04, 0x1f, + 0x10, 0x10, 0xa8, 0xf0, 0x4a, 0x24, 0xc0, 0x70, 0x55, 0x21, 0x0d, 0x2d, + 0xa1, 0x40, 0xe1, 0x42, 0xa8, 0x20, 0x40, 0x02, 0x60, 0x80, 0x04, 0x12, + 0x01, 0x04, 0x01, 0x31, 0xc1, 0x00, 0x04, 0x18, 0x50, 0x00, 0x7a, 0x0f, + 0xef, 0xf9, 0xa1, 0x40, 0xd3, 0x40, 0xc8, 0x42, 0x00, 0x00, 0x04, 0x30, + 0x00, 0x84, 0xda, 0xf6, 0x02, 0x85, 0x40, 0x85, 0x21, 0x85, 0x42, 0xc0, + 0xa1, 0x40, 0x40, 0xc2, 0x5a, 0x0f, 0xef, 0xf9, 0x41, 0xc1, 0x4a, 0x24, + 0xc0, 0x70, 0x80, 0xc1, 0xa1, 0x42, 0x43, 0xc0, 0xa8, 0x20, 0x80, 0x02, + 0x04, 0x11, 0x03, 0x04, 0x07, 0x33, 0x03, 0x00, 0x00, 0x33, 0x03, 0x04, + 0x04, 0x1a, 0xd0, 0x00, 0x7c, 0x11, 0x00, 0x20, 0x08, 0xc1, 0x48, 0x86, + 0x7c, 0x8e, 0x00, 0x30, 0x41, 0x00, 0x02, 0x36, 0x00, 0x70, 0x80, 0x3f, + 0x00, 0x00, 0x00, 0x30, 0x80, 0x00, 0x01, 0x30, 0x42, 0x00, 0x48, 0xa6, + 0x08, 0xeb, 0x00, 0x86, 0x50, 0x22, 0xc1, 0x07, 0x43, 0xc2, 0x04, 0x31, + 0x00, 0x80, 0x16, 0xf6, 0x4a, 0x24, 0xc0, 0x70, 0x0c, 0x70, 0x4a, 0x44, + 0x0c, 0x1c, 0x01, 0x30, 0xa8, 0x20, 0x00, 0x02, 0x04, 0x14, 0x01, 0x14, + 0x00, 0x31, 0x41, 0x00, 0x01, 0x30, 0x40, 0x00, 0x31, 0x86, 0x43, 0xc0, + 0x04, 0x30, 0x40, 0x80, 0x3e, 0x00, 0x0c, 0x00, 0x21, 0x85, 0x70, 0x11, + 0x0c, 0x20, 0x40, 0x85, 0x08, 0x15, 0x00, 0x10, 0x6c, 0x11, 0x0b, 0x20, + 0x4a, 0x24, 0xc0, 0x70, 0x41, 0xc1, 0x80, 0xc1, 0x43, 0xc4, 0x40, 0xc2, + 0x42, 0xc0, 0xa8, 0x20, 0x80, 0x03, 0x04, 0x11, 0x00, 0x04, 0x40, 0x87, + 0x00, 0x30, 0x03, 0x03, 0x00, 0x33, 0x80, 0x10, 0x01, 0x30, 0xc0, 0x00, + 0x04, 0x1f, 0x10, 0x10, 0x2e, 0xf0, 0xa9, 0xeb, 0x01, 0x86, 0x50, 0x22, + 0xc1, 0x07, 0x04, 0x31, 0x00, 0x80, 0x46, 0x00, 0x2c, 0x00, 0x43, 0xc2, + 0x21, 0x85, 0x70, 0x11, 0x0c, 0x20, 0x40, 0x85, 0x08, 0x15, 0x00, 0x10, + 0x6c, 0x11, 0x0b, 0x20, 0x4a, 0x24, 0xc0, 0x70, 0xa0, 0x19, 0x43, 0x20, + 0x41, 0xc1, 0x80, 0xc1, 0x43, 0xc4, 0x40, 0xc2, 0x42, 0xc0, 0xa8, 0x20, + 0x80, 0x03, 0x04, 0x11, 0x00, 0x04, 0x40, 0x87, 0x00, 0x30, 0x03, 0x03, + 0x00, 0x33, 0x80, 0x10, 0x01, 0x30, 0xc0, 0x00, 0x04, 0x1f, 0x10, 0x10, + 0x06, 0xf0, 0x0c, 0x70, 0x1c, 0xae, 0x02, 0xa7, 0x01, 0xa7, 0x00, 0xa7, + 0xf9, 0x11, 0x80, 0x20, 0x83, 0xe8, 0xf9, 0x19, 0x43, 0x20, 0x68, 0x11, + 0x80, 0x20, 0x39, 0x08, 0xb0, 0x00, 0x55, 0x21, 0x8d, 0x2a, 0x36, 0x43, + 0x58, 0x11, 0x02, 0x20, 0x40, 0x24, 0x04, 0x3c, 0x42, 0x41, 0x42, 0x0e, + 0x6f, 0xf2, 0xa1, 0x40, 0x8c, 0xc1, 0x10, 0xda, 0x22, 0x0c, 0xef, 0xeb, + 0xa1, 0x40, 0x8c, 0xc1, 0xea, 0x0c, 0x6f, 0xf2, 0xa1, 0x40, 0x8c, 0xc1, + 0x10, 0xda, 0x12, 0x0c, 0xef, 0xeb, 0xa1, 0x40, 0xcc, 0xc7, 0xe0, 0x78, + 0xf0, 0xc3, 0xa4, 0xc1, 0x55, 0x20, 0xce, 0x0d, 0x30, 0x40, 0x10, 0x41, + 0x32, 0x86, 0x65, 0x16, 0x00, 0x16, 0x50, 0x42, 0xad, 0x71, 0xfe, 0x0a, + 0x6f, 0xfa, 0x1c, 0x1e, 0x43, 0x10, 0x04, 0x71, 0x65, 0x1e, 0x18, 0x10, + 0x80, 0xc1, 0x02, 0x40, 0xb6, 0x08, 0x2f, 0xfa, 0x80, 0xc7, 0x00, 0xc1, + 0xa0, 0x4f, 0xb5, 0x72, 0xad, 0x72, 0x01, 0x31, 0x01, 0x00, 0xbc, 0xf7, + 0x65, 0x16, 0x0f, 0x16, 0x4a, 0x24, 0xc0, 0x70, 0x0c, 0x70, 0x52, 0x6f, + 0x42, 0x22, 0x03, 0x01, 0xa8, 0x20, 0x80, 0x02, 0xf0, 0x20, 0x0c, 0x20, + 0x15, 0x21, 0xcb, 0x20, 0x04, 0x71, 0x64, 0x71, 0x4a, 0x1b, 0x18, 0x13, + 0x2f, 0x34, 0x40, 0x10, 0x8a, 0x23, 0x09, 0x0b, 0x22, 0x73, 0x20, 0x8b, + 0x15, 0x21, 0x80, 0x20, 0x49, 0x18, 0x18, 0x03, 0x8e, 0xe9, 0x63, 0x16, + 0x00, 0x16, 0x32, 0x86, 0x0d, 0x09, 0x23, 0x00, 0x2c, 0x71, 0x00, 0x1b, + 0x43, 0x00, 0x06, 0xf0, 0x04, 0x71, 0x2c, 0x70, 0x63, 0x1e, 0x18, 0x10, + 0x34, 0x70, 0x92, 0xf2, 0xb2, 0x86, 0x10, 0x86, 0x09, 0x20, 0x50, 0x03, + 0x17, 0x0f, 0x23, 0x14, 0x42, 0x20, 0x54, 0x20, 0x29, 0x0f, 0x21, 0x15, + 0x2c, 0x71, 0xf1, 0x44, 0xb1, 0x43, 0xa1, 0x43, 0x18, 0xf0, 0xbf, 0x67, + 0x02, 0x27, 0x00, 0x14, 0x04, 0x71, 0xa1, 0x41, 0x56, 0x0a, 0x6f, 0xfa, + 0x6e, 0x71, 0x65, 0x16, 0x0f, 0x16, 0x00, 0x41, 0x6c, 0x72, 0x0c, 0xf0, + 0xb8, 0x67, 0x02, 0x20, 0x00, 0x04, 0x04, 0x71, 0x3e, 0x0a, 0x6f, 0xfa, + 0xa1, 0x41, 0x00, 0x43, 0x2c, 0x71, 0xb1, 0x43, 0x48, 0x30, 0x90, 0x20, + 0x48, 0x34, 0x82, 0x20, 0x7f, 0xd8, 0x17, 0xb8, 0x07, 0x30, 0x05, 0x04, + 0x07, 0x30, 0x86, 0x00, 0x56, 0x21, 0x40, 0x29, 0x40, 0x24, 0x07, 0x30, + 0x0a, 0x24, 0xc0, 0x04, 0x02, 0x0c, 0x20, 0x00, 0xe1, 0x42, 0x0b, 0x0a, + 0x10, 0x20, 0x20, 0x86, 0x02, 0xf0, 0x21, 0x86, 0xae, 0x0c, 0xaf, 0xff, + 0x80, 0xc0, 0x65, 0x16, 0x01, 0x16, 0x62, 0x86, 0x8d, 0x70, 0x04, 0xb9, + 0x22, 0x71, 0x49, 0x11, 0x02, 0x06, 0x89, 0x43, 0x04, 0x32, 0xc0, 0x80, + 0x87, 0xf7, 0x23, 0x86, 0x6d, 0x70, 0x04, 0x32, 0x40, 0x80, 0x03, 0xf6, + 0x6d, 0x71, 0x8b, 0xe8, 0x13, 0x0b, 0x10, 0x10, 0x06, 0x86, 0xe1, 0x68, + 0xe4, 0xe7, 0xc3, 0xf6, 0x64, 0xdf, 0xe6, 0xa6, 0x03, 0xf0, 0x86, 0xa6, + 0xed, 0x70, 0xf9, 0x11, 0x80, 0x20, 0x06, 0xe8, 0x13, 0x0a, 0x10, 0x20, + 0x28, 0x86, 0x08, 0xf0, 0x22, 0x40, 0x80, 0x20, 0x04, 0x05, 0x80, 0xa8, + 0x21, 0xf0, 0x29, 0x86, 0x52, 0x0c, 0xaf, 0xff, 0x80, 0xc0, 0x07, 0xe8, + 0x22, 0x40, 0x80, 0x20, 0x04, 0x05, 0x00, 0x18, 0x43, 0x00, 0x2d, 0x0b, + 0x30, 0x10, 0xad, 0x70, 0x2a, 0x86, 0x3a, 0x0c, 0xaf, 0xff, 0x80, 0xc0, + 0x14, 0x70, 0x0c, 0x70, 0x03, 0xf4, 0x0d, 0x86, 0x04, 0x71, 0x2c, 0x86, + 0x13, 0x08, 0x62, 0x00, 0x0d, 0xa6, 0x22, 0x40, 0x80, 0x20, 0x04, 0x05, + 0xa0, 0xa8, 0x03, 0xf0, 0xad, 0xa6, 0x05, 0x86, 0x09, 0x0f, 0x02, 0x10, + 0xf8, 0x19, 0x03, 0x20, 0xd0, 0xc7, 0xe0, 0x78, 0x8d, 0x00, 0xc0, 0x02, + 0x8a, 0x24, 0x01, 0x74, 0x8a, 0x23, 0x04, 0x05, 0x55, 0x20, 0x42, 0x0f, + 0x2c, 0x70, 0x56, 0x20, 0x4c, 0x09, 0x1b, 0x63, 0x20, 0xa2, 0x27, 0xa2, + 0x22, 0xb2, 0x20, 0xab, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1c, 0x11, 0x10, + 0x80, 0x20, 0x09, 0x0b, 0x5f, 0x1a, 0x58, 0x00, 0x20, 0xa4, 0xe0, 0x7f, + 0x20, 0xa8, 0xe0, 0x78, 0xe8, 0xc2, 0x68, 0x45, 0x48, 0x46, 0x30, 0x40, + 0x2a, 0x0e, 0xaf, 0xf4, 0x08, 0x47, 0x42, 0x20, 0xc0, 0x22, 0x31, 0x08, + 0xf5, 0x02, 0x55, 0x27, 0x10, 0x18, 0x25, 0x20, 0x00, 0x00, 0x0c, 0xf0, + 0x11, 0xf0, 0x18, 0xf0, 0x1d, 0xf0, 0x24, 0xf0, 0x29, 0xf0, 0x2f, 0xf0, + 0x34, 0xf0, 0x3b, 0xf0, 0x3f, 0xf0, 0x46, 0xf0, 0xc1, 0x40, 0x66, 0x08, + 0xef, 0xf4, 0xa1, 0x41, 0x68, 0x1f, 0x02, 0x10, 0xc8, 0xc6, 0xc1, 0x40, + 0x82, 0x0c, 0xef, 0xf9, 0xa1, 0x41, 0x69, 0x1f, 0x02, 0x10, 0xc8, 0xc6, + 0xc1, 0x40, 0x76, 0x0c, 0xef, 0xf9, 0xa1, 0x41, 0x74, 0x1f, 0x02, 0x10, + 0xc8, 0xc6, 0xc1, 0x40, 0x66, 0x0c, 0xef, 0xf9, 0xa1, 0x41, 0x75, 0x1f, + 0x02, 0x10, 0xc8, 0xc6, 0xc1, 0x40, 0x2e, 0x08, 0xef, 0xf4, 0xa1, 0x41, + 0x76, 0x1f, 0x02, 0x10, 0xc8, 0xc6, 0xc1, 0x40, 0x22, 0x0e, 0x2f, 0xf7, + 0xa1, 0x41, 0x1b, 0xa7, 0xc8, 0xc6, 0xc1, 0x40, 0x16, 0x0e, 0x2f, 0xf7, + 0xa1, 0x41, 0x04, 0x18, 0x00, 0x20, 0xc8, 0xc6, 0xc1, 0x40, 0x0a, 0x0e, + 0x2f, 0xf7, 0xa1, 0x41, 0x08, 0x18, 0x00, 0x20, 0xc8, 0xc6, 0xc1, 0x40, + 0xfa, 0x0d, 0x2f, 0xf7, 0xa1, 0x41, 0x1c, 0xa7, 0xc8, 0xc6, 0xc1, 0x40, + 0xee, 0x0d, 0x2f, 0xf7, 0xa1, 0x41, 0x00, 0x18, 0x00, 0x20, 0xc8, 0xc6, + 0xc1, 0x40, 0xe2, 0x0d, 0x2f, 0xf7, 0xa1, 0x41, 0x48, 0x18, 0x00, 0x20, + 0xc8, 0xc6, 0xe0, 0x78, 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x34, 0x50, 0x40, + 0x08, 0x47, 0x84, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0x3a, 0x09, 0xef, 0xeb, + 0x28, 0x45, 0x00, 0x87, 0x40, 0x24, 0x83, 0x30, 0x40, 0x24, 0x04, 0x32, + 0x40, 0x24, 0x05, 0x33, 0x40, 0x24, 0x06, 0x31, 0x40, 0x24, 0xc7, 0x30, + 0xa1, 0x41, 0x02, 0x42, 0x46, 0x0d, 0xef, 0xf2, 0x02, 0x1c, 0x03, 0x32, + 0x02, 0xc5, 0x9d, 0xed, 0x03, 0x14, 0x8e, 0x30, 0xad, 0x70, 0x2c, 0x70, + 0x97, 0xe9, 0x02, 0x14, 0x80, 0x30, 0xcf, 0x79, 0x27, 0x08, 0x64, 0x00, + 0x84, 0xc2, 0x81, 0xc3, 0x26, 0x08, 0x20, 0x00, 0xe1, 0x40, 0x01, 0xc0, + 0x8a, 0x21, 0x3e, 0x06, 0x12, 0x70, 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, + 0x01, 0x20, 0x3d, 0x20, 0x00, 0x20, 0x1e, 0x66, 0xea, 0xf1, 0xa1, 0x40, + 0xc8, 0xc7, 0xe0, 0x78, 0xe8, 0xc3, 0xa4, 0xc1, 0x68, 0x45, 0x48, 0x46, + 0x28, 0x47, 0x72, 0x0d, 0xaf, 0xf4, 0x10, 0x40, 0x21, 0x0f, 0x30, 0x12, + 0x80, 0xc2, 0x33, 0x0f, 0xf0, 0x11, 0xc1, 0x40, 0x29, 0x0f, 0xb1, 0x11, + 0x80, 0xc2, 0xc1, 0x40, 0x26, 0x0c, 0x2f, 0xfa, 0xa1, 0x41, 0x55, 0x20, + 0x80, 0x2b, 0x08, 0xf0, 0xc1, 0x40, 0x1a, 0x0c, 0x2f, 0xfa, 0xa1, 0x41, + 0x55, 0x20, 0x00, 0x29, 0x80, 0xc1, 0x96, 0x08, 0xef, 0xeb, 0x10, 0xda, + 0xc8, 0xc7, 0x3e, 0x0b, 0xef, 0xf9, 0xa1, 0x41, 0x8c, 0x18, 0x02, 0x20, + 0xc8, 0xc7, 0xe0, 0x78, 0xe6, 0xc2, 0x48, 0x31, 0x03, 0x00, 0x22, 0x92, + 0xc3, 0x42, 0x48, 0x47, 0x00, 0x00, 0x07, 0x32, 0xcb, 0x00, 0x55, 0x20, + 0x8d, 0x0a, 0x48, 0x31, 0x01, 0x00, 0x08, 0x46, 0x07, 0x32, 0x4c, 0x00, + 0xd8, 0x15, 0x00, 0x90, 0x7f, 0xdf, 0x17, 0xbf, 0x00, 0x30, 0x80, 0x0f, + 0xc8, 0x42, 0x00, 0x00, 0xc3, 0x43, 0x83, 0x3a, 0x6f, 0x12, 0x2d, 0x70, + 0x07, 0x36, 0xc8, 0x72, 0xf4, 0x49, 0x00, 0x24, 0x07, 0x37, 0x02, 0x13, + 0x07, 0x30, 0x01, 0x03, 0x11, 0x85, 0x3c, 0x1e, 0x43, 0x10, 0xe4, 0x1d, + 0x43, 0x90, 0x48, 0x30, 0x80, 0x00, 0x00, 0x34, 0x00, 0x10, 0x00, 0x30, + 0xc0, 0x00, 0x04, 0x1e, 0x00, 0x12, 0x04, 0x30, 0x40, 0x82, 0x5e, 0xa6, + 0x3f, 0xa6, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x38, 0x85, + 0x48, 0x30, 0xc2, 0x02, 0x48, 0x31, 0x81, 0x00, 0x00, 0x34, 0x40, 0x10, + 0x48, 0x32, 0x81, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x48, 0x31, 0xc1, 0x02, + 0x04, 0x30, 0x40, 0x82, 0x32, 0xa5, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, + 0x00, 0x00, 0x3e, 0x85, 0x48, 0x30, 0xc2, 0x02, 0x0d, 0x70, 0x48, 0x31, + 0x81, 0x00, 0x00, 0x34, 0x40, 0x10, 0x48, 0x32, 0x81, 0x00, 0x00, 0x30, + 0xc0, 0x00, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x30, 0x00, 0x82, 0x39, 0xa5, + 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x3c, 0x85, 0x48, 0x30, + 0xc2, 0x02, 0x48, 0x31, 0x81, 0x00, 0x00, 0x34, 0x40, 0x10, 0x48, 0x32, + 0x81, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x30, + 0x00, 0x82, 0x3d, 0xa5, 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, + 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, + 0x48, 0x30, 0xc0, 0x02, 0x4a, 0x24, 0xc0, 0x70, 0x48, 0x30, 0x80, 0x00, + 0xc3, 0x41, 0x13, 0x00, 0x2c, 0x6c, 0x48, 0x30, 0xc0, 0x02, 0x49, 0x20, + 0x00, 0x05, 0x48, 0x20, 0x80, 0x00, 0x1f, 0xa5, 0x0a, 0x20, 0x80, 0x03, + 0x80, 0x20, 0x0a, 0x04, 0xa8, 0x20, 0x00, 0x02, 0x04, 0x11, 0x02, 0x04, + 0x07, 0x32, 0xc2, 0x02, 0x04, 0x18, 0x90, 0x00, 0x07, 0x36, 0xc0, 0x72, + 0x80, 0xbf, 0x00, 0x00, 0x07, 0x30, 0x80, 0x0f, 0x72, 0x3f, 0x22, 0xb0, + 0x16, 0x0e, 0x8f, 0xfd, 0x02, 0x37, 0x00, 0x10, 0x7e, 0x1d, 0x18, 0x10, + 0xc6, 0x0c, 0xef, 0xff, 0xc1, 0x40, 0xc6, 0xc6, 0xf4, 0xc3, 0xa4, 0xc1, + 0x40, 0x29, 0x96, 0x00, 0x42, 0x26, 0x13, 0x21, 0x50, 0x41, 0x28, 0x47, + 0x08, 0x45, 0x15, 0x20, 0xc1, 0x04, 0x80, 0xc0, 0x10, 0xda, 0x0a, 0x20, + 0xc0, 0x21, 0x0a, 0x25, 0x80, 0x21, 0x0a, 0x24, 0x40, 0x21, 0x0a, 0x22, + 0x00, 0x21, 0xde, 0x0e, 0xaf, 0xeb, 0x68, 0x46, 0x2f, 0x0f, 0x63, 0x14, + 0x15, 0x25, 0x82, 0x15, 0xe1, 0x41, 0x4a, 0x24, 0x00, 0x71, 0x0a, 0x24, + 0x80, 0x10, 0x80, 0xc0, 0xa8, 0x20, 0x40, 0x02, 0x60, 0x80, 0x04, 0x14, + 0x0b, 0x14, 0x01, 0x33, 0xc3, 0x10, 0x04, 0x18, 0xd0, 0x00, 0x24, 0x71, + 0xe3, 0x09, 0x62, 0x84, 0x10, 0xe2, 0x33, 0x0a, 0xa2, 0x23, 0x34, 0x6e, + 0xb9, 0x61, 0xc1, 0x42, 0x70, 0xb9, 0x4a, 0x24, 0x00, 0x71, 0x80, 0xc0, + 0x0a, 0x24, 0x40, 0x10, 0xa8, 0x20, 0x40, 0x02, 0x60, 0x80, 0x04, 0x14, + 0x0b, 0x14, 0x01, 0x33, 0xc3, 0x10, 0x04, 0x18, 0xd0, 0x00, 0x10, 0xe1, + 0x52, 0x72, 0x44, 0x71, 0xaf, 0xf6, 0x4a, 0x24, 0x00, 0x71, 0x8d, 0x70, + 0x40, 0x24, 0x0b, 0x30, 0xa8, 0x20, 0xc0, 0x04, 0x15, 0x23, 0x01, 0x13, + 0x00, 0x81, 0xf0, 0x25, 0xc2, 0x14, 0x15, 0x20, 0x03, 0x23, 0x00, 0x30, + 0x00, 0x05, 0x85, 0x71, 0x02, 0x32, 0x02, 0x00, 0x66, 0x71, 0x00, 0x32, + 0x82, 0x00, 0x00, 0xa1, 0x40, 0xa3, 0x37, 0x0f, 0x63, 0x14, 0x4a, 0x24, + 0x00, 0x71, 0x0c, 0x70, 0x15, 0x20, 0xc2, 0x03, 0xa8, 0x20, 0x40, 0x04, + 0x80, 0xc1, 0x43, 0x4d, 0x01, 0x49, 0x15, 0x20, 0x0c, 0x20, 0x04, 0x71, + 0x02, 0x33, 0x41, 0x00, 0x60, 0x84, 0x00, 0x31, 0x41, 0x00, 0x44, 0x71, + 0x01, 0x33, 0x41, 0x00, 0x20, 0xa4, 0xe5, 0x71, 0xe7, 0xf1, 0x39, 0x0a, + 0x82, 0x23, 0x4a, 0x24, 0x00, 0x71, 0x12, 0x6e, 0x6c, 0x68, 0x2c, 0x70, + 0xa8, 0x20, 0x40, 0x04, 0x80, 0xc0, 0x62, 0x4d, 0x20, 0x48, 0x15, 0x20, + 0x4c, 0x20, 0x24, 0x71, 0x02, 0x32, 0x00, 0x00, 0x40, 0x84, 0x00, 0x30, + 0x00, 0x00, 0x64, 0x71, 0x01, 0x32, 0x00, 0x00, 0x00, 0xa4, 0x52, 0x76, + 0xc5, 0x71, 0xa9, 0xf6, 0x4a, 0x24, 0x00, 0x71, 0xa8, 0x20, 0xc0, 0x01, + 0x06, 0x40, 0x00, 0x30, 0x40, 0x05, 0x04, 0x18, 0x10, 0x20, 0xd4, 0xc7, + 0xe4, 0xc2, 0x49, 0x68, 0x4f, 0x7d, 0x9f, 0x25, 0x02, 0x13, 0xcb, 0x44, + 0xa0, 0x00, 0xcc, 0x49, 0x20, 0x43, 0xba, 0x64, 0xd1, 0x82, 0x54, 0x24, + 0x82, 0x1a, 0x59, 0x65, 0x42, 0x6e, 0x40, 0xb1, 0x0f, 0x78, 0xc3, 0x44, + 0x13, 0x00, 0xfc, 0x4c, 0x6a, 0x0b, 0x2f, 0xf8, 0x4c, 0x74, 0xc4, 0xc6, + 0xe6, 0xc2, 0x42, 0x81, 0x08, 0x45, 0x04, 0x80, 0x00, 0x32, 0x82, 0x0f, + 0x4c, 0x3d, 0xd0, 0xcc, 0x00, 0x30, 0x80, 0x0f, 0x73, 0x3f, 0x33, 0x33, + 0x01, 0x30, 0x80, 0x00, 0x01, 0x30, 0x82, 0x0f, 0x7a, 0xc4, 0x00, 0x00, + 0x04, 0xa5, 0xbf, 0xba, 0x00, 0x81, 0x04, 0x32, 0x80, 0x8f, 0x37, 0x42, + 0x86, 0x8c, 0x43, 0x85, 0x61, 0x81, 0x82, 0x85, 0x02, 0xa5, 0x02, 0x33, + 0x8e, 0x00, 0x02, 0x30, 0x0f, 0x03, 0x01, 0x81, 0xbf, 0xbe, 0xbf, 0xbf, + 0x03, 0xa5, 0x85, 0xf7, 0xb2, 0x0a, 0x6f, 0xef, 0xa1, 0x40, 0x04, 0x8d, + 0x01, 0x37, 0x82, 0x13, 0x33, 0x08, 0xb0, 0x00, 0xcd, 0x70, 0x4b, 0x08, + 0x50, 0x00, 0xa7, 0x08, 0x11, 0x00, 0x14, 0x8d, 0x04, 0x32, 0x80, 0x8f, + 0xf4, 0x41, 0x5d, 0xbb, 0x04, 0x71, 0x0f, 0x78, 0x49, 0x20, 0x81, 0x0c, + 0x8e, 0x00, 0x2c, 0x00, 0x34, 0xad, 0x85, 0x08, 0x94, 0x0c, 0xd4, 0xad, + 0x04, 0x1d, 0x43, 0x10, 0x3f, 0xf0, 0x17, 0x8d, 0x04, 0x71, 0x0f, 0x79, + 0x31, 0x09, 0xf4, 0x02, 0x17, 0xad, 0x19, 0x8d, 0x69, 0x08, 0x95, 0x01, + 0xd9, 0xad, 0xd7, 0xad, 0xc4, 0xad, 0x81, 0xde, 0x31, 0xf0, 0x15, 0x8d, + 0x04, 0x32, 0x80, 0x8f, 0xf4, 0x41, 0x5d, 0xbb, 0x41, 0x68, 0x55, 0xad, + 0xd0, 0xf6, 0x18, 0x8d, 0xd6, 0xad, 0x04, 0x71, 0x18, 0xad, 0x1f, 0xf0, + 0x04, 0x32, 0x80, 0x8f, 0xf4, 0x41, 0x5d, 0xbb, 0x3e, 0x00, 0x0c, 0x00, + 0x19, 0x8d, 0x04, 0x71, 0x19, 0xad, 0x1b, 0xf0, 0x16, 0x8d, 0x04, 0x71, + 0x0f, 0x79, 0x23, 0x09, 0xb4, 0x01, 0x16, 0xad, 0x18, 0x8d, 0x15, 0x08, + 0xf4, 0x02, 0xa1, 0x40, 0xd8, 0xad, 0xd5, 0xad, 0x04, 0x1d, 0x83, 0x10, + 0xd6, 0xad, 0x0b, 0xf0, 0x0a, 0x0a, 0x4f, 0xef, 0x55, 0x8d, 0x4f, 0x78, + 0xe5, 0xe0, 0x85, 0xf7, 0xfe, 0x09, 0x6f, 0xef, 0xa1, 0x40, 0xc1, 0x40, + 0xc6, 0xc6, 0xe0, 0x78, 0x00, 0x42, 0x02, 0x80, 0x04, 0x30, 0x40, 0x80, + 0x0c, 0x70, 0xe0, 0x20, 0xce, 0x07, 0x03, 0x82, 0x04, 0x30, 0x40, 0x80, + 0xca, 0xf7, 0x44, 0x82, 0xc3, 0x40, 0x40, 0x40, 0x00, 0x00, 0x04, 0x32, + 0x40, 0x80, 0xe0, 0x7f, 0xd0, 0x20, 0xae, 0x05, 0x7f, 0xd8, 0xe0, 0x7f, + 0x17, 0xb8, 0xe0, 0x78, 0xea, 0xc3, 0x82, 0x24, 0x0c, 0x37, 0x50, 0x40, + 0x08, 0x47, 0x87, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0x4e, 0x0c, 0xaf, 0xeb, + 0x28, 0x45, 0x00, 0x87, 0x40, 0x24, 0x83, 0x33, 0x40, 0x24, 0x04, 0x35, + 0x40, 0x24, 0x05, 0x36, 0x40, 0x24, 0x06, 0x34, 0x40, 0x24, 0xc7, 0x33, + 0xa1, 0x41, 0x02, 0x42, 0x5a, 0x08, 0xef, 0xf2, 0x0e, 0x1c, 0x03, 0x31, + 0x05, 0xc5, 0xbd, 0xed, 0x0f, 0x14, 0x8e, 0x30, 0xad, 0x70, 0x8a, 0x21, + 0x3e, 0x26, 0x2c, 0x70, 0xb5, 0xe9, 0x0e, 0x14, 0x81, 0x30, 0xcf, 0x78, + 0x63, 0x09, 0x04, 0x00, 0x23, 0x08, 0x30, 0x01, 0x84, 0xc1, 0x29, 0x08, + 0xb0, 0x00, 0x84, 0xc1, 0x37, 0x08, 0xf0, 0x00, 0x84, 0xc1, 0x3b, 0x08, + 0x71, 0x00, 0x87, 0xc0, 0x76, 0x0a, 0xaf, 0xf4, 0x84, 0xc1, 0x04, 0xaf, + 0x15, 0xf0, 0x6e, 0x0a, 0xaf, 0xf4, 0x87, 0xc0, 0x15, 0xaf, 0x11, 0xf0, + 0x87, 0xc0, 0x62, 0x0a, 0x6f, 0xf8, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, + 0x02, 0xc0, 0x42, 0xa7, 0x23, 0xa7, 0x04, 0xa7, 0x05, 0xf0, 0x4e, 0x0a, + 0xaf, 0xf4, 0x87, 0xc0, 0x14, 0xaf, 0x04, 0xc0, 0x12, 0x70, 0x3c, 0x20, + 0x01, 0x20, 0x3d, 0x20, 0x00, 0x20, 0xca, 0x25, 0x4d, 0x14, 0x1e, 0x66, + 0xcc, 0xf1, 0xa1, 0x40, 0xca, 0xc7, 0xe0, 0x78, 0xf2, 0xc3, 0xac, 0xc1, + 0x17, 0xc7, 0x50, 0x45, 0x30, 0x42, 0x08, 0x46, 0x2c, 0x70, 0x24, 0xda, + 0xe1, 0x40, 0xe8, 0x45, 0x0a, 0x20, 0x80, 0x21, 0x0a, 0x21, 0x40, 0x21, + 0x0a, 0x23, 0x00, 0x21, 0xca, 0x09, 0xaf, 0xf9, 0x70, 0x44, 0x04, 0x8e, + 0x13, 0x08, 0x3f, 0x00, 0x14, 0xda, 0x15, 0x08, 0x7f, 0x00, 0x80, 0xc0, + 0x14, 0xda, 0x62, 0x41, 0x07, 0xf0, 0x80, 0xc0, 0xa2, 0x41, 0x05, 0xf0, + 0x80, 0xc0, 0x14, 0xda, 0x82, 0x41, 0x62, 0x0b, 0x8f, 0xeb, 0x04, 0xc1, + 0xce, 0x0e, 0xef, 0xff, 0xc1, 0x40, 0x44, 0xc0, 0x80, 0xc0, 0xee, 0x08, + 0x2f, 0xf2, 0x88, 0xc1, 0x88, 0xc0, 0xfe, 0x08, 0x2f, 0xf2, 0x85, 0xc1, + 0x04, 0x8e, 0x23, 0x08, 0x3f, 0x01, 0x4a, 0x24, 0x40, 0x71, 0x2b, 0x08, + 0x7f, 0x01, 0x4a, 0x24, 0x40, 0x71, 0x33, 0x08, 0xbf, 0x01, 0x80, 0xc1, + 0x14, 0xda, 0x2a, 0x0b, 0xaf, 0xeb, 0xa1, 0x40, 0x21, 0xf0, 0xa1, 0x40, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x15, 0x01, 0x24, 0x04, 0x18, 0x50, 0x00, + 0x14, 0xf0, 0xa1, 0x40, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x14, 0x01, 0x24, + 0x04, 0x18, 0x50, 0x00, 0x0c, 0xf0, 0x4a, 0x24, 0x40, 0x71, 0x62, 0x41, + 0x0a, 0x20, 0x40, 0x03, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x02, 0x04, + 0x04, 0x18, 0x90, 0x00, 0x24, 0x85, 0x5e, 0x0e, 0xef, 0xff, 0xc1, 0x40, + 0x04, 0xa5, 0x18, 0xc1, 0x4a, 0x24, 0x40, 0x71, 0x0a, 0x20, 0x40, 0x03, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x02, 0x04, 0x04, 0x1f, 0x90, 0x10, + 0x15, 0x8e, 0x4a, 0x24, 0x40, 0x71, 0x0a, 0xe8, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x13, 0x00, 0x24, 0x04, 0x19, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x15, 0x00, 0x14, 0x04, 0x19, 0x10, 0x00, + 0x04, 0xc2, 0x4a, 0x24, 0xc0, 0x70, 0x4a, 0x20, 0x00, 0x00, 0x85, 0xc3, + 0x0c, 0x19, 0x80, 0x20, 0xa8, 0x20, 0x80, 0x04, 0x01, 0x4b, 0x15, 0x21, + 0x0c, 0x20, 0x20, 0xa4, 0xf0, 0x22, 0x0c, 0x20, 0x00, 0x31, 0x8b, 0x0f, + 0x7a, 0xc4, 0x00, 0x00, 0x15, 0x20, 0x01, 0x20, 0x01, 0x34, 0xcc, 0x12, + 0x04, 0x71, 0x80, 0xa1, 0x0c, 0x18, 0x80, 0x20, 0xd2, 0xc7, 0xe0, 0x78, + 0xe8, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, 0x60, 0x44, 0x40, 0x24, + 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x47, + 0x28, 0x45, 0xda, 0x0e, 0xaf, 0xf2, 0x03, 0x1c, 0x03, 0x31, 0x02, 0x14, + 0x80, 0x30, 0x40, 0x26, 0x10, 0x12, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, + 0x49, 0x09, 0x04, 0x00, 0x1d, 0x08, 0x10, 0x01, 0x1d, 0x08, 0xb0, 0x00, + 0x81, 0xc3, 0x25, 0x08, 0xd0, 0x00, 0x2d, 0x08, 0x71, 0x00, 0x81, 0xc3, + 0x04, 0x8e, 0xe1, 0x42, 0xa1, 0x41, 0x0e, 0xf0, 0x15, 0x8e, 0x09, 0xf0, + 0x02, 0x40, 0xa1, 0x41, 0xb2, 0x08, 0x6f, 0xf8, 0xe1, 0x42, 0x08, 0xf0, + 0x14, 0x8e, 0x81, 0xc3, 0xa1, 0x41, 0xe1, 0x42, 0x92, 0x08, 0x8f, 0xf4, + 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xdb, 0xf1, + 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xc8, 0xc7, + 0xe8, 0xc3, 0xa1, 0xc1, 0x60, 0x40, 0x48, 0x45, 0x28, 0x46, 0x2c, 0x70, + 0x10, 0xda, 0x88, 0x47, 0x1a, 0x08, 0xaf, 0xf9, 0x70, 0x40, 0xd5, 0x70, + 0xcd, 0x70, 0x2b, 0xf2, 0x4a, 0x24, 0xc0, 0x70, 0xc3, 0x42, 0x13, 0x00, + 0x44, 0x6c, 0x0c, 0x70, 0xa8, 0x20, 0xc0, 0x02, 0x04, 0x12, 0x03, 0x04, + 0x40, 0x24, 0x41, 0x30, 0x1c, 0x61, 0x04, 0x71, 0x38, 0x23, 0x41, 0x03, + 0x20, 0xac, 0x52, 0x08, 0x6f, 0xf6, 0x40, 0x24, 0x40, 0x30, 0x06, 0xe8, + 0xcd, 0x71, 0x00, 0x18, 0x43, 0x20, 0x11, 0xf0, 0x13, 0x0d, 0x10, 0x1f, + 0x15, 0x0d, 0xd0, 0x1e, 0x17, 0x0d, 0x91, 0x1b, 0x00, 0x18, 0x83, 0x20, + 0x06, 0xf0, 0x00, 0x18, 0x03, 0x21, 0x04, 0xf0, 0x00, 0x18, 0xc3, 0x20, + 0xcd, 0x71, 0xc0, 0xa7, 0xc8, 0xc7, 0xe0, 0x78, 0xf1, 0xc0, 0xa3, 0xc1, + 0x00, 0x80, 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, + 0x40, 0x24, 0xc6, 0x32, 0xe6, 0x0d, 0xaf, 0xf2, 0x03, 0x1c, 0x03, 0x30, + 0x01, 0xc0, 0xa3, 0xc0, 0xd1, 0xc0, 0xe0, 0x7e, 0x4a, 0x24, 0xc0, 0x70, + 0x98, 0x48, 0xc3, 0x42, 0x13, 0x00, 0x38, 0x6c, 0x04, 0x18, 0x43, 0x00, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x12, 0x03, 0x04, 0x04, 0x19, 0xd0, 0x00, + 0x15, 0x18, 0x03, 0x00, 0xe0, 0x7f, 0x00, 0x19, 0x03, 0x00, 0xe0, 0x78, + 0xf1, 0xc0, 0xa4, 0xc1, 0x00, 0x80, 0x40, 0x24, 0x83, 0x31, 0x40, 0x24, + 0x04, 0x30, 0x40, 0x24, 0x05, 0x33, 0x40, 0x24, 0x06, 0x32, 0x40, 0x24, + 0xc7, 0x31, 0x3a, 0x0d, 0xaf, 0xf2, 0x06, 0x1c, 0x03, 0x30, 0x00, 0xc0, + 0xa4, 0xc0, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0xe0, 0x7e, 0xe0, 0x78, + 0xe6, 0xc0, 0x34, 0x10, 0x8c, 0x00, 0x55, 0x20, 0x8d, 0x0e, 0x0c, 0xea, + 0x0d, 0x0c, 0xd1, 0x10, 0x40, 0x8d, 0x25, 0x0a, 0xb5, 0x00, 0xc9, 0x6a, + 0xcd, 0x70, 0x00, 0x1d, 0x03, 0x10, 0x0d, 0xf0, 0x40, 0x8d, 0xea, 0x10, + 0x8e, 0x00, 0x44, 0x71, 0x4f, 0x7f, 0x0d, 0x0f, 0x85, 0x13, 0x48, 0x46, + 0x40, 0xad, 0x03, 0xf0, 0xc0, 0xad, 0xe9, 0x10, 0x82, 0x00, 0x08, 0xe9, + 0x21, 0x0a, 0xb5, 0x00, 0xad, 0x70, 0xe9, 0x18, 0x03, 0x00, 0x0f, 0xf0, + 0xea, 0x10, 0x8d, 0x00, 0x21, 0x6a, 0x2f, 0x7a, 0x0f, 0x0a, 0x45, 0x03, + 0x28, 0x45, 0xe9, 0x18, 0x42, 0x00, 0x05, 0xf0, 0xa9, 0x6a, 0xe9, 0x18, + 0x42, 0x03, 0xea, 0x10, 0x8b, 0x00, 0xcf, 0x79, 0x31, 0x09, 0xc5, 0x02, + 0x0d, 0x0c, 0xd1, 0x10, 0xeb, 0x10, 0x82, 0x00, 0x25, 0x09, 0x85, 0x00, + 0xaf, 0x7a, 0x2f, 0x0a, 0xc5, 0x02, 0x0f, 0x0c, 0x94, 0x10, 0xeb, 0x10, + 0x81, 0x00, 0x23, 0x0a, 0x45, 0x00, 0x29, 0x6c, 0x15, 0x09, 0x53, 0x00, + 0x2c, 0x71, 0x34, 0x18, 0x43, 0x00, 0x12, 0xf0, 0x21, 0x6c, 0x2f, 0x7a, + 0x11, 0x0b, 0x84, 0x00, 0x34, 0x18, 0x42, 0x00, 0x0a, 0xf0, 0x11, 0x0b, + 0xf5, 0x00, 0x2c, 0x72, 0x34, 0x18, 0xc2, 0x00, 0x60, 0x41, 0x04, 0xf0, + 0x34, 0x18, 0x83, 0x00, 0x2f, 0x79, 0x13, 0x09, 0x05, 0x03, 0x11, 0x0c, + 0x90, 0x10, 0x0b, 0x0c, 0xd1, 0x10, 0xe8, 0x18, 0x03, 0x00, 0xc6, 0xc4, + 0xe8, 0x18, 0x05, 0x00, 0xc6, 0xc4, 0xe0, 0x78, 0xec, 0xc3, 0xa1, 0xc1, + 0x55, 0x20, 0x4e, 0x09, 0xfc, 0x80, 0x83, 0x86, 0x4a, 0x24, 0xc0, 0x70, + 0x08, 0x45, 0x20, 0x40, 0x70, 0x41, 0x50, 0x40, 0x40, 0x24, 0x41, 0x30, + 0x0a, 0x22, 0x00, 0x20, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x10, 0x02, 0x04, + 0x04, 0x32, 0x00, 0x83, 0x6f, 0x22, 0x0b, 0x00, 0x01, 0x19, 0x92, 0x00, + 0x42, 0x0d, 0xef, 0xf3, 0x40, 0x24, 0x40, 0x30, 0x33, 0xe8, 0x64, 0x86, + 0xfd, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x0c, 0x70, 0x0a, 0x21, 0x80, 0x04, + 0xa8, 0x20, 0x40, 0x03, 0x04, 0x11, 0x0b, 0x04, 0x40, 0x24, 0x42, 0x30, + 0x1c, 0x62, 0x04, 0x33, 0xc0, 0x90, 0x04, 0x71, 0x6f, 0x22, 0x0b, 0x00, + 0x40, 0xac, 0x12, 0x0d, 0xef, 0xf3, 0x40, 0x24, 0x40, 0x30, 0x1b, 0xe8, + 0x45, 0x86, 0xfe, 0x85, 0x4a, 0x24, 0xc0, 0x70, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0x40, 0x03, 0x04, 0x12, 0x0c, 0x24, 0x40, 0x24, 0x41, 0x30, + 0x1b, 0x61, 0x04, 0x34, 0x80, 0x90, 0x04, 0x71, 0x6f, 0x21, 0x0b, 0x00, + 0x20, 0xab, 0xe2, 0x0c, 0xef, 0xf3, 0x40, 0x24, 0x40, 0x30, 0x03, 0xe8, + 0xff, 0x85, 0x41, 0x86, 0x16, 0x86, 0x7d, 0x85, 0x02, 0x37, 0x81, 0x10, + 0x00, 0x30, 0x41, 0x00, 0x17, 0x86, 0x01, 0x32, 0x41, 0x00, 0x5c, 0x85, + 0x00, 0x30, 0xcc, 0x00, 0x04, 0x37, 0x40, 0x90, 0x21, 0xa6, 0xca, 0x21, + 0xc5, 0x03, 0x04, 0x31, 0x00, 0x83, 0x48, 0x43, 0xd0, 0xf6, 0x9e, 0x85, + 0x00, 0x30, 0x0b, 0x03, 0x04, 0x31, 0xc0, 0x82, 0x68, 0x43, 0xca, 0xf6, + 0x7f, 0x85, 0x89, 0x43, 0x00, 0x30, 0xc0, 0x00, 0x04, 0x31, 0x00, 0x80, + 0xc2, 0xf6, 0x68, 0x43, 0x02, 0x86, 0x7f, 0xdb, 0x17, 0xbb, 0x07, 0x30, + 0x80, 0x00, 0x07, 0x33, 0x81, 0x00, 0x01, 0x30, 0xc0, 0x00, 0x04, 0x30, + 0x40, 0x80, 0xca, 0x21, 0x05, 0x00, 0x07, 0x33, 0x42, 0x00, 0x61, 0x40, + 0x20, 0xa6, 0x04, 0x32, 0xc0, 0x82, 0xca, 0x20, 0x89, 0x00, 0x00, 0x18, + 0x00, 0x20, 0x02, 0x86, 0x01, 0x33, 0x00, 0x10, 0x04, 0x30, 0xc0, 0x80, + 0xca, 0x20, 0xc9, 0x00, 0x04, 0x30, 0xc0, 0x80, 0x02, 0xa6, 0x05, 0xf4, + 0x00, 0x19, 0xc3, 0x20, 0xcc, 0xc7, 0x04, 0x30, 0x80, 0x8f, 0x00, 0x3f, + 0x00, 0x00, 0x45, 0xf6, 0x00, 0x19, 0x43, 0x20, 0xcc, 0xc7, 0x00, 0x19, + 0x83, 0x20, 0xcc, 0xc7, 0xea, 0xc3, 0x82, 0x24, 0x0c, 0x38, 0x50, 0x40, + 0x08, 0x45, 0x88, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0xc6, 0x0e, 0x6f, 0xeb, + 0x28, 0x46, 0x00, 0x85, 0x40, 0x24, 0x83, 0x30, 0x40, 0x24, 0x04, 0x32, + 0x40, 0x24, 0x05, 0x37, 0x40, 0x24, 0x06, 0x31, 0x40, 0x24, 0xc7, 0x30, + 0xc1, 0x41, 0x02, 0x42, 0xd2, 0x0a, 0xaf, 0xf2, 0x02, 0x1c, 0x03, 0x33, + 0x02, 0xc6, 0xd5, 0x70, 0x7b, 0xf4, 0x03, 0x14, 0x8f, 0x30, 0x55, 0x25, + 0x11, 0x18, 0xcd, 0x70, 0x2c, 0x70, 0xeb, 0x09, 0x31, 0x00, 0xef, 0x78, + 0x02, 0x14, 0x81, 0x30, 0xdf, 0x09, 0x24, 0x00, 0x04, 0x77, 0xc3, 0x08, + 0x15, 0x03, 0x25, 0x20, 0x00, 0x00, 0x0d, 0xf0, 0x12, 0xf0, 0x18, 0xf0, + 0x1c, 0xf0, 0x22, 0xf0, 0x26, 0xf0, 0x2c, 0xf0, 0x30, 0xf0, 0x3b, 0xf0, + 0x40, 0xf0, 0x47, 0xf0, 0x4c, 0xf0, 0x88, 0xc0, 0xea, 0x09, 0xef, 0xf5, + 0x81, 0xc1, 0x90, 0x1d, 0x04, 0x10, 0x4b, 0xf0, 0x88, 0xc0, 0xd6, 0x0a, + 0xef, 0xf6, 0x81, 0xc1, 0x0c, 0xa5, 0x45, 0xf0, 0x88, 0xc0, 0xca, 0x0a, + 0xef, 0xf6, 0x81, 0xc1, 0x14, 0xa5, 0x3f, 0xf0, 0x88, 0xc0, 0xbe, 0x0a, + 0xef, 0xf6, 0x81, 0xc1, 0x15, 0xa5, 0x39, 0xf0, 0x88, 0xc0, 0xb2, 0x0a, + 0xef, 0xf6, 0x81, 0xc1, 0x18, 0xa5, 0x33, 0xf0, 0x88, 0xc0, 0xa6, 0x0a, + 0xef, 0xf6, 0x81, 0xc1, 0x19, 0xa5, 0x2d, 0xf0, 0x88, 0xc0, 0x9a, 0x0a, + 0xef, 0xf6, 0x81, 0xc1, 0x1a, 0xa5, 0x27, 0xf0, 0x88, 0xc0, 0x81, 0xc1, + 0x32, 0x0e, 0x20, 0x05, 0x83, 0xc2, 0x83, 0xc1, 0x10, 0xda, 0xfa, 0x0d, + 0x6f, 0xeb, 0x22, 0x40, 0x1b, 0xf0, 0x88, 0xc0, 0x76, 0x0a, 0xef, 0xf6, + 0x81, 0xc1, 0xac, 0x1d, 0x00, 0x10, 0x15, 0xf0, 0x88, 0xc0, 0x66, 0x0c, + 0x6f, 0xf4, 0x81, 0xc1, 0x6d, 0x1d, 0x02, 0x10, 0x0d, 0xf0, 0x88, 0xc0, + 0x5a, 0x0a, 0xef, 0xf6, 0x81, 0xc1, 0xcc, 0x1d, 0x00, 0x10, 0x07, 0xf0, + 0x88, 0xc0, 0x4e, 0x0a, 0xef, 0xf6, 0x81, 0xc1, 0x0b, 0xa5, 0x01, 0xc0, + 0x8a, 0x21, 0x3e, 0x06, 0x12, 0x70, 0xca, 0x26, 0x4d, 0x10, 0x3c, 0x20, + 0x01, 0x20, 0x3d, 0x20, 0x00, 0x20, 0x1f, 0x67, 0x8d, 0xf1, 0xc1, 0x40, + 0xca, 0xc7, 0xe0, 0x78, 0xee, 0xc3, 0xad, 0xc1, 0xa8, 0x47, 0x0a, 0x20, + 0x00, 0x21, 0x30, 0x41, 0x08, 0x46, 0x13, 0x0a, 0xfe, 0x01, 0x00, 0x1d, + 0x03, 0x00, 0x0c, 0x71, 0x46, 0x78, 0x36, 0x1e, 0x02, 0x10, 0x0f, 0x0b, + 0xfe, 0x01, 0x0c, 0x71, 0x66, 0x78, 0x35, 0x1e, 0x02, 0x10, 0x78, 0x4e, + 0x40, 0x24, 0xc2, 0x32, 0x8a, 0xc3, 0x3e, 0x08, 0xaf, 0xfe, 0x22, 0x41, + 0x36, 0x16, 0x80, 0x10, 0x08, 0xe8, 0x35, 0x16, 0x80, 0x10, 0x06, 0xe8, + 0x0b, 0x14, 0x80, 0x30, 0x6e, 0x71, 0x03, 0xe8, 0x6e, 0x70, 0x40, 0x26, + 0x0d, 0x17, 0x87, 0xc1, 0xa1, 0x40, 0xae, 0x0e, 0xaf, 0xf4, 0x40, 0x24, + 0x12, 0x37, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x24, 0x41, 0x36, 0xa8, 0x20, + 0x80, 0x03, 0x04, 0x12, 0x02, 0x24, 0x0c, 0x70, 0x04, 0x32, 0x80, 0x8f, + 0x00, 0x47, 0x00, 0x00, 0xca, 0x20, 0x69, 0x00, 0x01, 0x19, 0x12, 0x00, + 0xf6, 0x0b, 0xef, 0xf3, 0x40, 0x24, 0x40, 0x36, 0x07, 0xe8, 0x0c, 0x70, + 0x02, 0xa5, 0x01, 0xa5, 0x00, 0xa5, 0x34, 0x1e, 0x02, 0x10, 0x76, 0x70, + 0x00, 0x02, 0x21, 0x00, 0x8a, 0xc1, 0x81, 0xc2, 0x40, 0x24, 0x83, 0x32, + 0xc1, 0x40, 0xda, 0x0c, 0xef, 0xff, 0x40, 0x24, 0x12, 0x3a, 0x4a, 0x24, + 0xc0, 0x70, 0x0c, 0x70, 0xa8, 0x20, 0x40, 0x03, 0x15, 0x26, 0x01, 0x10, + 0xf0, 0x21, 0x03, 0x20, 0x21, 0x81, 0x15, 0x22, 0x02, 0x20, 0x04, 0x71, + 0x02, 0x33, 0x41, 0x00, 0x20, 0xa2, 0x01, 0xc4, 0x4a, 0x24, 0xc0, 0x70, + 0x04, 0x6e, 0x8a, 0xc2, 0xa8, 0x20, 0xc0, 0x02, 0x04, 0x12, 0x01, 0x04, + 0x60, 0x80, 0x00, 0x34, 0x41, 0x10, 0x01, 0x33, 0x41, 0x00, 0x04, 0x18, + 0x50, 0x00, 0x2a, 0x16, 0x80, 0x10, 0x54, 0x96, 0x04, 0x71, 0x0f, 0x79, + 0x50, 0x71, 0xa0, 0x01, 0x25, 0x00, 0x2a, 0x1e, 0x02, 0x10, 0x4a, 0x24, + 0xc0, 0x70, 0x2c, 0x70, 0x2a, 0x1e, 0x03, 0x10, 0xa8, 0x20, 0x00, 0x03, + 0x15, 0x26, 0x40, 0x10, 0x44, 0x80, 0x01, 0x80, 0x8a, 0xc3, 0x35, 0x7b, + 0x02, 0x30, 0x80, 0x00, 0x24, 0x71, 0x00, 0xa3, 0x8a, 0xc0, 0x87, 0xc1, + 0xda, 0x0d, 0xaf, 0xf4, 0x40, 0x24, 0x11, 0x37, 0x3f, 0x86, 0x01, 0xc0, + 0x4a, 0x24, 0xc0, 0x70, 0x4c, 0x70, 0x07, 0x30, 0x41, 0x00, 0x0c, 0x86, + 0x02, 0x1c, 0x82, 0x30, 0x03, 0x1c, 0x82, 0x30, 0x00, 0x31, 0x0c, 0x00, + 0xa8, 0x20, 0x80, 0x03, 0x04, 0x11, 0x03, 0x24, 0x0c, 0x70, 0x40, 0x24, + 0x41, 0x36, 0x04, 0x33, 0x00, 0x83, 0x59, 0x61, 0x44, 0x71, 0xca, 0x20, + 0x6a, 0x00, 0x00, 0xa9, 0x0e, 0x0b, 0xef, 0xf3, 0x40, 0x24, 0x40, 0x36, + 0xbb, 0x08, 0x30, 0x00, 0x4c, 0x70, 0xb0, 0x16, 0x00, 0x10, 0x7f, 0xdc, + 0x17, 0xbc, 0x01, 0x30, 0x01, 0x03, 0x2c, 0x16, 0x0b, 0x10, 0xc3, 0x40, + 0x20, 0x41, 0x00, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x04, 0x31, 0x00, 0x80, + 0xca, 0x20, 0x45, 0x00, 0x40, 0x24, 0x08, 0x37, 0xb0, 0x1e, 0x00, 0x10, + 0xa8, 0x20, 0x80, 0x03, 0x04, 0x10, 0x09, 0x14, 0x2c, 0x70, 0x40, 0x24, + 0x43, 0x36, 0x04, 0x31, 0xc0, 0x92, 0x5b, 0x63, 0x44, 0x71, 0xca, 0x21, + 0x69, 0x00, 0x20, 0xab, 0x07, 0x34, 0x11, 0x10, 0xc3, 0x40, 0xcc, 0x3e, + 0xcd, 0xcc, 0x04, 0x31, 0x00, 0xa0, 0xca, 0x21, 0x05, 0x20, 0xaa, 0x0a, + 0xef, 0xf3, 0x40, 0x24, 0x40, 0x36, 0x8a, 0xc2, 0x2b, 0xe8, 0x5e, 0x08, + 0xef, 0xf5, 0x8a, 0xc0, 0x6b, 0x86, 0x4a, 0x24, 0xc0, 0x70, 0x83, 0xc4, + 0x87, 0xc2, 0x83, 0xc1, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x00, 0x04, + 0x04, 0x33, 0x00, 0x80, 0xca, 0x20, 0xc5, 0x00, 0x04, 0x19, 0x10, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0x4a, 0x20, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x04, + 0x8a, 0xc1, 0x01, 0x49, 0x15, 0x26, 0x02, 0x10, 0x03, 0x4c, 0x00, 0x31, + 0x4b, 0x20, 0x24, 0x82, 0x00, 0x33, 0xc3, 0x10, 0x04, 0x71, 0x01, 0x31, + 0xc1, 0x00, 0x24, 0xa2, 0x11, 0xf0, 0x2c, 0x70, 0x25, 0xf0, 0x4a, 0x24, + 0xc0, 0x70, 0x28, 0x4e, 0xa8, 0x20, 0xc0, 0x02, 0x04, 0x12, 0x01, 0x04, + 0x60, 0x80, 0x00, 0x31, 0x41, 0x20, 0x01, 0x33, 0x41, 0x00, 0x04, 0x18, + 0x50, 0x00, 0x40, 0x24, 0x81, 0x30, 0x40, 0x24, 0xc2, 0x30, 0x92, 0x0c, + 0x20, 0x00, 0xc1, 0x40, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x26, 0x00, 0x14, + 0xa8, 0x20, 0x40, 0x01, 0x04, 0x10, 0x01, 0x04, 0x22, 0xa0, 0x03, 0x14, + 0x82, 0x30, 0x02, 0x14, 0x81, 0x30, 0x80, 0xd8, 0x00, 0xaf, 0x0a, 0x14, + 0x83, 0x30, 0x34, 0x16, 0x91, 0x10, 0x2e, 0x0a, 0xef, 0xff, 0xc1, 0x40, + 0x34, 0x16, 0x80, 0x10, 0x0d, 0x09, 0x00, 0x20, 0x00, 0x8f, 0x87, 0xb8, + 0x00, 0x1f, 0x02, 0x10, 0x2a, 0x1e, 0x03, 0x10, 0x4a, 0x24, 0xc0, 0x70, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x15, 0x00, 0x14, 0x04, 0x18, 0x10, 0x20, + 0x34, 0x16, 0x80, 0x10, 0x48, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x20, + 0xce, 0xc7, 0xe0, 0x78, 0xe8, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, 0x56, 0x0f, 0x6f, 0xf2, 0x03, 0x1c, + 0x03, 0x33, 0x02, 0x14, 0x80, 0x30, 0x55, 0x26, 0x10, 0x18, 0x03, 0x14, + 0x81, 0x30, 0x0f, 0x78, 0x91, 0x09, 0x24, 0x00, 0x04, 0x77, 0x81, 0x08, + 0x15, 0x03, 0x25, 0x20, 0x00, 0x00, 0x0d, 0xf0, 0x13, 0xf0, 0x15, 0xf0, + 0x15, 0xf0, 0x17, 0xf0, 0x17, 0xf0, 0x19, 0xf0, 0x19, 0xf0, 0x20, 0xf0, + 0x21, 0xf0, 0x29, 0xf0, 0x2a, 0xf0, 0x90, 0x16, 0x00, 0x11, 0x81, 0xc3, + 0xa1, 0x41, 0x2e, 0x0e, 0xaf, 0xf5, 0xe1, 0x42, 0x28, 0xf0, 0x0c, 0x86, + 0x21, 0xf0, 0x14, 0x86, 0x1f, 0xf0, 0x15, 0x86, 0x1d, 0xf0, 0x18, 0x86, + 0x1b, 0xf0, 0x19, 0x86, 0x19, 0xf0, 0x1a, 0x86, 0x17, 0xf0, 0x81, 0xc3, + 0x02, 0x40, 0xa1, 0x41, 0xae, 0x0a, 0x20, 0x05, 0xe1, 0x42, 0x16, 0xf0, + 0xac, 0x16, 0x00, 0x10, 0x0d, 0xf0, 0x6d, 0x16, 0x80, 0x10, 0x81, 0xc3, + 0xa1, 0x41, 0xde, 0x08, 0x6f, 0xf4, 0xe1, 0x42, 0x0a, 0xf0, 0xcc, 0x16, + 0x00, 0x10, 0x03, 0xf0, 0x0b, 0x86, 0x81, 0xc3, 0xa1, 0x41, 0xde, 0x0e, + 0xaf, 0xf6, 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, + 0x02, 0x30, 0xb7, 0xf1, 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, + 0x21, 0xad, 0xc8, 0xc7, 0xe8, 0xc3, 0xa1, 0xc1, 0x50, 0x40, 0x28, 0x45, + 0x2c, 0x70, 0x10, 0xda, 0x60, 0x40, 0x88, 0x46, 0x4e, 0x08, 0x6f, 0xf9, + 0x68, 0x47, 0xb5, 0x70, 0xad, 0x70, 0x2f, 0xf4, 0x4a, 0x24, 0x00, 0x71, + 0xc3, 0x42, 0x13, 0x00, 0x50, 0x6c, 0x0c, 0x70, 0xa8, 0x20, 0x80, 0x02, + 0x04, 0x12, 0x03, 0x04, 0x80, 0xc1, 0x1c, 0x61, 0x04, 0x71, 0x38, 0x23, + 0x01, 0x04, 0x20, 0xac, 0x56, 0x0b, 0xaf, 0xf4, 0x80, 0xc0, 0x1b, 0xe8, + 0x0c, 0xdd, 0x0b, 0x1f, 0xc3, 0x13, 0x0a, 0x1f, 0x83, 0x13, 0x09, 0x1f, + 0x43, 0x13, 0x08, 0x1f, 0x03, 0x13, 0x07, 0x1f, 0xc3, 0x12, 0x06, 0x1f, + 0x83, 0x12, 0x05, 0x1f, 0x43, 0x12, 0x04, 0x1f, 0x03, 0x12, 0x03, 0x1f, + 0xc3, 0x11, 0x02, 0x1f, 0x03, 0x11, 0x01, 0x1f, 0x83, 0x10, 0x00, 0x1f, + 0x43, 0x10, 0xa0, 0xa6, 0xc8, 0xc7, 0xe0, 0x78, 0xf2, 0xc3, 0xa2, 0xc1, + 0x08, 0x45, 0x04, 0x15, 0x00, 0x14, 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, + 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x46, 0x30, 0x45, + 0x0a, 0x0e, 0x6f, 0xf2, 0x03, 0x1c, 0xc3, 0x33, 0x02, 0x14, 0x80, 0x30, + 0x40, 0x25, 0x10, 0x13, 0x55, 0x25, 0x11, 0x1b, 0x55, 0x25, 0xd2, 0x1b, + 0x55, 0x25, 0xd3, 0x1c, 0x55, 0x25, 0x94, 0x1d, 0x40, 0x25, 0x0f, 0x16, + 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0xaf, 0x09, 0x24, 0x00, 0x04, 0x77, + 0x9b, 0x08, 0xd5, 0x03, 0x25, 0x20, 0x00, 0x00, 0x0f, 0xf0, 0x12, 0xf0, + 0x13, 0xf0, 0x16, 0xf0, 0x17, 0xf0, 0x1a, 0xf0, 0x1b, 0xf0, 0x1e, 0xf0, + 0x1f, 0xf0, 0x22, 0xf0, 0x23, 0xf0, 0x26, 0xf0, 0x2b, 0xf0, 0x2e, 0xf0, + 0x34, 0xf0, 0x81, 0xc3, 0xe1, 0x40, 0x22, 0xf0, 0x30, 0x15, 0x80, 0x10, + 0x28, 0xf0, 0x26, 0x15, 0x80, 0x10, 0x26, 0xf0, 0x81, 0xc3, 0xa1, 0x40, + 0x18, 0xf0, 0x31, 0x15, 0x80, 0x10, 0x20, 0xf0, 0x32, 0x15, 0x80, 0x10, + 0x1c, 0xf0, 0x98, 0x15, 0x00, 0x10, 0x22, 0xf0, 0x81, 0xc3, 0x02, 0x40, + 0x0c, 0xf0, 0x81, 0xc3, 0x22, 0x40, 0x0a, 0xf0, 0x81, 0xc3, 0x42, 0x40, + 0x06, 0xf0, 0x81, 0xc3, 0x62, 0x40, 0x04, 0xf0, 0x81, 0xc3, 0x82, 0x40, + 0xa2, 0x41, 0xf6, 0x0f, 0xaf, 0xf6, 0xc1, 0x42, 0x13, 0xf0, 0xe4, 0x15, + 0x80, 0x10, 0x04, 0xf0, 0xe5, 0x15, 0x80, 0x10, 0x81, 0xc3, 0xa2, 0x41, + 0x5e, 0x0f, 0x2f, 0xf4, 0xc1, 0x42, 0x09, 0xf0, 0xac, 0x15, 0x00, 0x10, + 0x81, 0xc3, 0xa2, 0x41, 0x62, 0x0d, 0xaf, 0xf6, 0xc1, 0x42, 0x02, 0x14, + 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xa8, 0xf1, 0x01, 0xc0, + 0x41, 0x28, 0x01, 0x02, 0x00, 0x1d, 0x02, 0x20, 0x01, 0x1d, 0x42, 0x20, + 0xd2, 0xc7, 0xe0, 0x78, 0x2d, 0x00, 0x40, 0x02, 0xf0, 0xc3, 0x82, 0x24, + 0x0c, 0x37, 0x50, 0x42, 0x08, 0x45, 0x87, 0xc0, 0x8a, 0x22, 0x0c, 0x00, + 0x86, 0x08, 0x6f, 0xeb, 0x28, 0x46, 0x00, 0x85, 0x40, 0x24, 0x83, 0x33, + 0x40, 0x24, 0x04, 0x35, 0x40, 0x24, 0x05, 0x36, 0x40, 0x24, 0x06, 0x34, + 0x40, 0x24, 0xc7, 0x33, 0xc1, 0x41, 0x42, 0x42, 0x92, 0x0c, 0x6f, 0xf2, + 0x0e, 0x1c, 0xc3, 0x33, 0x14, 0x14, 0x11, 0x30, 0x36, 0x70, 0xcb, 0xf4, + 0x0f, 0x14, 0x8e, 0x30, 0x55, 0x25, 0x54, 0x1b, 0x55, 0x25, 0x13, 0x1c, + 0x55, 0x25, 0x10, 0x1d, 0x55, 0x25, 0xcf, 0x1d, 0x2e, 0x70, 0x2c, 0x70, + 0x34, 0x70, 0xbd, 0xf4, 0x0e, 0x14, 0x81, 0x30, 0xcf, 0x78, 0x30, 0x70, + 0x6e, 0x01, 0x2d, 0x00, 0x04, 0x77, 0x8e, 0xe0, 0x4e, 0x01, 0x0d, 0x00, + 0x25, 0x20, 0x00, 0x00, 0x0f, 0xf0, 0x1b, 0xf0, 0x20, 0xf0, 0x27, 0xf0, + 0x31, 0xf0, 0x38, 0xf0, 0x3d, 0xf0, 0x44, 0xf0, 0x4e, 0xf0, 0x5d, 0xf0, + 0x6a, 0xf0, 0x79, 0xf0, 0x83, 0xf0, 0x8a, 0xf0, 0x8f, 0xf0, 0x87, 0xc0, + 0x84, 0xc1, 0xf6, 0x0e, 0xaf, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, + 0x02, 0xc0, 0x47, 0xa5, 0x28, 0xa5, 0x09, 0xa5, 0x89, 0xf0, 0x87, 0xc0, + 0x6e, 0x0e, 0x2f, 0xf4, 0x84, 0xc1, 0x34, 0x1d, 0x02, 0x10, 0x83, 0xf0, + 0x87, 0xc0, 0x62, 0x0e, 0x2f, 0xf4, 0x84, 0xc1, 0x2a, 0x1d, 0x02, 0x10, + 0x7b, 0xf0, 0x87, 0xc0, 0x84, 0xc1, 0xc2, 0x0e, 0xaf, 0xf6, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x41, 0xa5, 0x22, 0xa5, 0x03, 0xa5, + 0x6f, 0xf0, 0x87, 0xc0, 0x3a, 0x0e, 0x2f, 0xf4, 0x84, 0xc1, 0x35, 0x1d, + 0x02, 0x10, 0x69, 0xf0, 0x87, 0xc0, 0x2e, 0x0e, 0x2f, 0xf4, 0x84, 0xc1, + 0x36, 0x1d, 0x02, 0x10, 0x61, 0xf0, 0x87, 0xc0, 0x22, 0x0c, 0xaf, 0xf6, + 0x84, 0xc1, 0x9c, 0x1d, 0x00, 0x10, 0x5b, 0xf0, 0x87, 0xc0, 0x84, 0xc1, + 0x7e, 0x0e, 0xaf, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, + 0x44, 0xa5, 0x25, 0xa5, 0x06, 0xa5, 0x4f, 0xf0, 0x87, 0xc0, 0x84, 0xc1, + 0x66, 0x0e, 0xaf, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, + 0x00, 0x1c, 0x80, 0x20, 0x04, 0x1c, 0x40, 0x20, 0x08, 0x1c, 0x00, 0x20, + 0x3f, 0xf0, 0x87, 0xc0, 0x84, 0xc1, 0x4a, 0x0e, 0xaf, 0xf6, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x00, 0x1b, 0x80, 0x20, 0x04, 0x1b, + 0x40, 0x20, 0x08, 0x1b, 0x00, 0x20, 0x31, 0xf0, 0x87, 0xc0, 0x84, 0xc1, + 0x2a, 0x0e, 0xaf, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, + 0x00, 0x18, 0x80, 0x20, 0x04, 0x18, 0x40, 0x20, 0x08, 0x18, 0x00, 0x20, + 0x21, 0xf0, 0x87, 0xc0, 0x84, 0xc1, 0x0e, 0x0e, 0xaf, 0xf6, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x40, 0xa7, 0x21, 0xa7, 0x02, 0xa7, + 0x15, 0xf0, 0x87, 0xc0, 0x86, 0x0d, 0x2f, 0xf4, 0x84, 0xc1, 0xe8, 0x1d, + 0x02, 0x10, 0x0f, 0xf0, 0x87, 0xc0, 0x7a, 0x0d, 0x2f, 0xf4, 0x84, 0xc1, + 0xe9, 0x1d, 0x02, 0x10, 0x07, 0xf0, 0x87, 0xc0, 0x6e, 0x0b, 0xaf, 0xf6, + 0x84, 0xc1, 0xb0, 0x1d, 0x00, 0x10, 0x04, 0xc0, 0x8a, 0x21, 0x3e, 0x06, + 0x52, 0x70, 0xca, 0x21, 0x4d, 0x20, 0x3c, 0x22, 0x01, 0x20, 0x3d, 0x22, + 0x00, 0x20, 0x1e, 0x66, 0x44, 0xf1, 0x22, 0x40, 0xd0, 0xc7, 0xe0, 0x78, + 0xe6, 0xc0, 0x48, 0x43, 0x08, 0x41, 0x55, 0x20, 0xc2, 0x0c, 0x0c, 0x70, + 0x00, 0x46, 0x00, 0x1b, 0x02, 0x10, 0x5f, 0x0e, 0xf5, 0x00, 0x15, 0x21, + 0x8d, 0x11, 0x55, 0x25, 0x4c, 0x1b, 0x64, 0x85, 0xc3, 0x84, 0x55, 0x25, + 0x0f, 0x1c, 0x04, 0x33, 0x80, 0x83, 0xca, 0xf6, 0x60, 0xa7, 0xa0, 0x82, + 0x01, 0x35, 0x48, 0x13, 0x02, 0x33, 0x03, 0x02, 0x60, 0xa4, 0x0d, 0xf0, + 0xa0, 0x84, 0x04, 0x33, 0x40, 0x83, 0x4c, 0xf7, 0x60, 0xa4, 0x80, 0x82, + 0x01, 0x34, 0x0c, 0x13, 0x01, 0x33, 0x03, 0x03, 0x60, 0xa7, 0x00, 0x1b, + 0x43, 0x10, 0x0b, 0xf0, 0x60, 0x82, 0x01, 0x33, 0xc3, 0x00, 0x01, 0x36, + 0xce, 0x10, 0x02, 0x35, 0xc3, 0x10, 0xca, 0xa4, 0x67, 0xa4, 0xc4, 0x71, + 0xd3, 0xf1, 0x00, 0xa9, 0x55, 0x08, 0xf5, 0x00, 0x15, 0x21, 0x03, 0x10, + 0x55, 0x23, 0x0e, 0x0d, 0xa4, 0x83, 0x83, 0x86, 0x04, 0x35, 0x00, 0x93, + 0x55, 0x23, 0xcc, 0x0d, 0xcd, 0xf6, 0xe0, 0x82, 0xa0, 0xa4, 0x00, 0x37, + 0x8b, 0x1f, 0x80, 0xc0, 0x00, 0x00, 0x01, 0x35, 0xcf, 0x12, 0xe0, 0xa6, + 0x00, 0x19, 0x43, 0x00, 0xa4, 0x83, 0x60, 0x86, 0x04, 0x35, 0xc0, 0x90, + 0x4c, 0xf7, 0x60, 0x82, 0xa0, 0xa6, 0x00, 0x33, 0x83, 0x0f, 0x80, 0x40, + 0x00, 0x00, 0x01, 0x35, 0xc3, 0x10, 0x60, 0xa4, 0x00, 0x19, 0x43, 0x00, + 0x04, 0x71, 0xd8, 0xf1, 0xc6, 0xc4, 0xe0, 0x78, 0xea, 0xc3, 0xa7, 0xc1, + 0x48, 0x31, 0x01, 0x00, 0x08, 0x45, 0x07, 0x36, 0x51, 0x70, 0x48, 0x47, + 0x00, 0x00, 0x18, 0x80, 0x7f, 0xde, 0x17, 0xbe, 0x02, 0x36, 0x00, 0x10, + 0xcb, 0x47, 0xc8, 0x41, 0x00, 0x00, 0x6e, 0x0e, 0x2f, 0xfd, 0x07, 0x37, + 0x50, 0x14, 0xca, 0x0c, 0x2f, 0xfd, 0x00, 0x30, 0x00, 0x20, 0x07, 0x31, + 0xc2, 0x23, 0x90, 0x15, 0x01, 0x11, 0x02, 0x36, 0x03, 0x10, 0x48, 0x31, + 0x01, 0x00, 0x77, 0xa5, 0x00, 0x32, 0x40, 0x00, 0x2c, 0x70, 0x04, 0x30, + 0x40, 0x80, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, + 0xc0, 0x02, 0x14, 0xb5, 0x00, 0x30, 0x80, 0x2f, 0x24, 0xbd, 0xca, 0xa5, + 0x82, 0x0c, 0x0f, 0xfd, 0x4a, 0x24, 0x00, 0x71, 0x02, 0x36, 0x00, 0x10, + 0x4a, 0x21, 0x00, 0x00, 0xec, 0x1d, 0x00, 0x10, 0xa8, 0x20, 0x40, 0x03, + 0x15, 0x25, 0x40, 0x10, 0x80, 0x10, 0x00, 0x00, 0x83, 0xc7, 0x15, 0x27, + 0x42, 0x10, 0x02, 0x36, 0x00, 0x10, 0x24, 0x71, 0x00, 0xa2, 0xd2, 0x0f, + 0xa0, 0x03, 0x83, 0xc0, 0x4a, 0x21, 0x00, 0x20, 0x00, 0x87, 0x4a, 0x0c, + 0x2f, 0xfd, 0x00, 0x30, 0x00, 0x20, 0x26, 0x71, 0xf5, 0x09, 0x34, 0xa1, + 0x04, 0x1f, 0x10, 0x10, 0x4a, 0x24, 0x00, 0x71, 0x54, 0x25, 0x01, 0x1e, + 0x83, 0xc0, 0xa8, 0x20, 0x40, 0x02, 0x04, 0x10, 0x02, 0x04, 0x02, 0x36, + 0x82, 0x10, 0x04, 0x19, 0x90, 0x00, 0x1f, 0x85, 0x5d, 0x85, 0x3e, 0x85, + 0xac, 0x15, 0x0c, 0x10, 0x4a, 0x24, 0xc0, 0x70, 0x55, 0x25, 0x03, 0x1a, + 0x42, 0xc0, 0x80, 0xc0, 0x40, 0xc2, 0x41, 0xc1, 0xa8, 0x20, 0x00, 0x02, + 0x04, 0x10, 0x01, 0x04, 0x07, 0x34, 0x41, 0x10, 0x04, 0x1b, 0x50, 0x00, + 0x36, 0x1d, 0x43, 0x10, 0x2a, 0x1d, 0x03, 0x10, 0x35, 0x1d, 0x43, 0x10, + 0xca, 0xc7, 0xe0, 0x78, 0xe4, 0xc2, 0x08, 0x45, 0x5f, 0x20, 0x02, 0x0f, + 0xc3, 0x40, 0xa0, 0x00, 0x70, 0x4c, 0xc3, 0x41, 0xf0, 0x00, 0x2c, 0x01, + 0x5e, 0x60, 0x00, 0x19, 0x41, 0x00, 0x67, 0x86, 0x1c, 0xeb, 0x00, 0x22, + 0x82, 0x0f, 0xa0, 0x00, 0xa9, 0x4c, 0xc3, 0x40, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x1a, 0x03, 0x00, 0xb5, 0x78, 0xcb, 0x44, 0xa0, 0x00, 0x14, 0x42, + 0x28, 0x90, 0x13, 0x88, 0x40, 0x84, 0xc5, 0xb8, 0x02, 0x79, 0x26, 0xa6, + 0x06, 0xea, 0x60, 0x7a, 0xa1, 0x40, 0x86, 0xe8, 0x67, 0x86, 0x26, 0x86, + 0x07, 0x09, 0xc5, 0x00, 0xc4, 0xc6, 0x00, 0x16, 0x02, 0x70, 0xa0, 0x00, + 0xe8, 0x41, 0x20, 0x1e, 0x01, 0x10, 0x05, 0xea, 0x60, 0x7a, 0xa1, 0x40, + 0xc4, 0xc6, 0x0f, 0x0d, 0xf1, 0x10, 0xa1, 0x40, 0xc2, 0x0e, 0x8f, 0xea, + 0xc4, 0xc6, 0xe6, 0x08, 0x8f, 0xea, 0xc4, 0xc6, 0xe6, 0xc2, 0x08, 0x47, + 0x5f, 0x27, 0x0e, 0x1f, 0xc3, 0x40, 0xf0, 0x00, 0x2c, 0x01, 0xcb, 0x45, + 0xa0, 0x00, 0xa0, 0x4c, 0x00, 0x18, 0x41, 0x00, 0xd8, 0x65, 0x5e, 0x0c, + 0x2f, 0xfb, 0x09, 0x18, 0x03, 0x00, 0xc3, 0x40, 0xa0, 0x00, 0x14, 0x42, + 0x40, 0x80, 0x06, 0xea, 0xa1, 0x66, 0x60, 0x7a, 0xe1, 0x40, 0x84, 0xe8, + 0x0c, 0x70, 0x8b, 0x58, 0xc6, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0xe1, 0xc4, + 0xfc, 0x1c, 0xc8, 0xb2, 0xfc, 0x1c, 0x88, 0xb2, 0xfc, 0x1c, 0x48, 0xb2, + 0xfc, 0x1c, 0x08, 0xb2, 0xfc, 0x1c, 0xc8, 0xb1, 0xfc, 0x1c, 0x88, 0xb1, + 0xfc, 0x1c, 0x48, 0xb1, 0xfc, 0x1c, 0x08, 0xb1, 0xe1, 0xc3, 0xe1, 0xc2, + 0xe1, 0xc1, 0xe1, 0xc0, 0xfc, 0x1c, 0x88, 0xb7, 0x6a, 0x25, 0xc0, 0x10, + 0xe1, 0xc5, 0x6a, 0x25, 0x80, 0x10, 0xe1, 0xc5, 0xfc, 0x1c, 0x08, 0xbf, + 0xa1, 0xc1, 0xc3, 0x40, 0xf0, 0x00, 0x44, 0x01, 0x00, 0x18, 0x01, 0x02, + 0x22, 0x0c, 0x4f, 0xfb, 0x14, 0x71, 0x43, 0xf2, 0xcb, 0x45, 0xa0, 0x00, + 0x78, 0x6e, 0xcd, 0x70, 0xa1, 0x40, 0x00, 0x1c, 0x01, 0x30, 0x2f, 0x26, + 0x0c, 0x10, 0x2f, 0x21, 0x88, 0x83, 0x0c, 0xf2, 0xc3, 0x40, 0xa0, 0x00, + 0x00, 0x87, 0x00, 0x80, 0x4c, 0x71, 0x6c, 0x70, 0x42, 0x0b, 0x6f, 0xfb, + 0x40, 0x24, 0x04, 0x30, 0x04, 0x26, 0x81, 0x9f, 0xff, 0x00, 0x00, 0x00, + 0x0b, 0xf2, 0xc3, 0x40, 0xa0, 0x00, 0xe4, 0x86, 0x00, 0x80, 0x4c, 0x71, + 0x6c, 0x70, 0x26, 0x0b, 0x6f, 0xfb, 0x40, 0x24, 0x04, 0x30, 0x04, 0x26, + 0x81, 0x9f, 0x00, 0x0f, 0x00, 0x00, 0x0a, 0xf2, 0x02, 0x85, 0x08, 0xe8, + 0x4c, 0x71, 0x6c, 0x70, 0x0a, 0x0b, 0x6f, 0xfb, 0x40, 0x24, 0x04, 0x30, + 0x6c, 0x26, 0xc1, 0x96, 0x09, 0xf2, 0x01, 0x85, 0x07, 0xe8, 0x4c, 0x71, + 0x6c, 0x70, 0xf6, 0x0a, 0x6f, 0xfb, 0x40, 0x24, 0x04, 0x30, 0x00, 0xc0, + 0x03, 0xe8, 0x42, 0x0b, 0x8f, 0xfc, 0x87, 0x74, 0xc1, 0xc5, 0x0a, 0x24, + 0x40, 0x73, 0xc1, 0xc5, 0x6b, 0x25, 0x80, 0x10, 0xc1, 0xc5, 0x6b, 0x25, + 0xc0, 0x10, 0x04, 0x14, 0x1e, 0x34, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc2, + 0xc1, 0xc3, 0x04, 0x14, 0x04, 0x34, 0x04, 0x14, 0x05, 0x34, 0x04, 0x14, + 0x06, 0x34, 0x04, 0x14, 0x07, 0x34, 0x04, 0x14, 0x08, 0x34, 0x04, 0x14, + 0x09, 0x34, 0x04, 0x14, 0x0a, 0x34, 0x04, 0x14, 0x0b, 0x34, 0xc1, 0xc4, + 0xc4, 0xc2, 0x6f, 0x24, 0x3f, 0x00, 0xe0, 0x78, 0x41, 0x02, 0x8f, 0xea, + 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x34, 0x50, 0x40, 0x08, 0x47, 0x84, 0xc0, + 0x8a, 0x22, 0x0c, 0x00, 0xfa, 0x0a, 0x2f, 0xeb, 0x28, 0x45, 0x00, 0x87, + 0x40, 0x24, 0x83, 0x30, 0x40, 0x24, 0x04, 0x32, 0x40, 0x24, 0x05, 0x33, + 0x40, 0x24, 0x06, 0x31, 0x40, 0x24, 0xc7, 0x30, 0xa1, 0x41, 0x02, 0x42, + 0x06, 0x0f, 0x2f, 0xf2, 0x02, 0x1c, 0x43, 0x31, 0x02, 0xc5, 0x81, 0x0d, + 0x31, 0x10, 0x2c, 0x70, 0x03, 0x14, 0x8e, 0x30, 0xad, 0x70, 0xba, 0xe9, + 0x02, 0x14, 0x81, 0x30, 0xcf, 0x78, 0x6d, 0x09, 0x24, 0x00, 0x04, 0x77, + 0x4d, 0x08, 0x55, 0x01, 0x25, 0x20, 0x00, 0x00, 0x05, 0xf0, 0x0b, 0xf0, + 0x0f, 0xf0, 0x15, 0xf0, 0x19, 0xf0, 0x84, 0xc0, 0x8e, 0x0f, 0xef, 0xf8, + 0x81, 0xc1, 0x02, 0xa7, 0x18, 0xf0, 0x84, 0xc0, 0x1e, 0x0f, 0x6f, 0xf6, + 0x81, 0xc1, 0x04, 0xa7, 0x12, 0xf0, 0x84, 0xc0, 0x12, 0x0f, 0x6f, 0xf6, + 0x81, 0xc1, 0x05, 0xa7, 0x0c, 0xf0, 0x84, 0xc0, 0x06, 0x0f, 0x6f, 0xf6, + 0x81, 0xc1, 0x0a, 0xa7, 0x06, 0xf0, 0x84, 0xc0, 0x5e, 0x0f, 0xef, 0xf8, + 0x81, 0xc1, 0x03, 0xa7, 0x01, 0xc0, 0x8a, 0x21, 0x3e, 0x06, 0x12, 0x70, + 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, 0x01, 0x20, 0x3d, 0x20, 0x00, 0x20, + 0x1e, 0x66, 0xc9, 0xf1, 0xa1, 0x40, 0xc8, 0xc7, 0xe6, 0xc3, 0xa7, 0xc1, + 0x08, 0x46, 0x04, 0x88, 0x28, 0x47, 0x14, 0xe8, 0x4a, 0x24, 0xc0, 0x70, + 0xb8, 0x4e, 0xe1, 0x40, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x02, 0x04, + 0x04, 0x19, 0x90, 0x00, 0xc3, 0x40, 0x8c, 0x42, 0x00, 0x00, 0x0a, 0xa6, + 0x00, 0x19, 0x01, 0x00, 0x04, 0x1e, 0x03, 0x10, 0x4a, 0x24, 0xc0, 0x70, + 0x0c, 0x70, 0x84, 0xc4, 0xa8, 0x20, 0x00, 0x03, 0x15, 0x26, 0x01, 0x10, + 0x03, 0x4f, 0x26, 0x81, 0x15, 0x24, 0x02, 0x10, 0x04, 0x71, 0x02, 0x33, + 0x41, 0x00, 0x20, 0xa2, 0x84, 0xc0, 0x62, 0x0b, 0x6f, 0xf4, 0x81, 0xc1, + 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x26, 0x0d, 0x16, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x17, 0x00, 0x14, 0x04, 0x1d, 0x10, 0x10, 0x8a, 0x86, 0x4a, 0x24, + 0xc0, 0x70, 0x81, 0xc1, 0x40, 0x24, 0x42, 0x30, 0xa8, 0x20, 0xc0, 0x02, + 0x04, 0x11, 0x03, 0x04, 0x0c, 0x70, 0x04, 0x33, 0x00, 0x83, 0xca, 0x20, + 0x69, 0x00, 0x01, 0x1a, 0x12, 0x00, 0x9a, 0x08, 0xaf, 0xf3, 0x40, 0x24, + 0x40, 0x30, 0x0d, 0xe8, 0x05, 0x86, 0x0a, 0xa6, 0x20, 0x85, 0xc3, 0x40, + 0x01, 0x00, 0x80, 0x51, 0x24, 0x71, 0x17, 0x08, 0x44, 0x00, 0x20, 0xa5, + 0x09, 0xf0, 0x00, 0x1d, 0x01, 0x10, 0x04, 0x86, 0x2c, 0x70, 0x0a, 0xa6, + 0x03, 0xf0, 0x00, 0xa5, 0x00, 0x41, 0x03, 0x86, 0x10, 0x71, 0x0c, 0x70, + 0xc4, 0xf7, 0x81, 0xd8, 0x00, 0x1d, 0x01, 0x10, 0xc6, 0xc7, 0xe0, 0x78, + 0xe6, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, 0x60, 0x44, 0x40, 0x24, + 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x47, + 0x28, 0x45, 0xee, 0x0d, 0x2f, 0xf2, 0x03, 0x1c, 0x43, 0x31, 0x02, 0x14, + 0x80, 0x30, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0x4b, 0x09, 0x24, 0x00, + 0x04, 0x77, 0x3b, 0x08, 0x55, 0x01, 0x25, 0x20, 0x00, 0x00, 0x06, 0xf0, + 0x06, 0xf0, 0x08, 0xf0, 0x08, 0xf0, 0x0f, 0xf0, 0x02, 0x86, 0x0e, 0xf0, + 0x04, 0x86, 0x05, 0xf0, 0x05, 0x86, 0x03, 0xf0, 0x0a, 0x86, 0x81, 0xc3, + 0xa1, 0x41, 0xce, 0x0d, 0x6f, 0xf6, 0xe1, 0x42, 0x07, 0xf0, 0x03, 0x86, + 0x81, 0xc3, 0xa1, 0x41, 0x22, 0x0e, 0xef, 0xf8, 0xe1, 0x42, 0x02, 0x14, + 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xd9, 0xf1, 0x01, 0xc0, + 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xc6, 0xc7, 0xe0, 0x78, + 0xe2, 0xc2, 0x60, 0x40, 0x2c, 0x70, 0x10, 0xda, 0x36, 0x0f, 0xef, 0xf8, + 0x88, 0x45, 0x00, 0x1d, 0x01, 0x10, 0xc2, 0xc6, 0xe6, 0xc3, 0xa2, 0xc1, + 0x08, 0x46, 0x18, 0x16, 0x00, 0x14, 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, + 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, + 0x52, 0x0d, 0x2f, 0xf2, 0x03, 0x1c, 0x83, 0x30, 0x02, 0x14, 0x80, 0x30, + 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0x35, 0x09, 0x04, 0x00, 0x1b, 0x08, + 0xb0, 0x00, 0x81, 0xc3, 0x1d, 0x08, 0x71, 0x00, 0x81, 0xc3, 0xc1, 0x40, + 0xa1, 0x41, 0xb6, 0x0f, 0x6f, 0xf6, 0xe1, 0x42, 0x06, 0xf0, 0x03, 0x86, + 0xa1, 0x41, 0xa2, 0x0d, 0xef, 0xf8, 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, + 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xe6, 0xf1, 0x01, 0xc0, 0x41, 0x28, + 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xc6, 0xc7, 0xf5, 0x01, 0x00, 0x02, + 0xea, 0xc3, 0x82, 0x24, 0x0c, 0x39, 0x50, 0x41, 0x08, 0x46, 0x89, 0xc0, + 0x8a, 0x22, 0x0c, 0x00, 0x66, 0x08, 0x2f, 0xeb, 0x28, 0x45, 0x00, 0x86, + 0x40, 0x24, 0xc3, 0x34, 0x40, 0x24, 0x04, 0x37, 0x40, 0x24, 0x05, 0x38, + 0x40, 0x24, 0x06, 0x33, 0x40, 0x24, 0xc7, 0x36, 0xa1, 0x41, 0x22, 0x42, + 0x72, 0x0c, 0x2f, 0xf2, 0x13, 0x1c, 0x83, 0x30, 0x1c, 0x14, 0x10, 0x30, + 0x67, 0x08, 0x31, 0x20, 0x2c, 0x70, 0x1b, 0x14, 0x8f, 0x30, 0x0e, 0x70, + 0xad, 0xe9, 0x13, 0x14, 0x81, 0x30, 0xef, 0x78, 0x53, 0x09, 0x04, 0x00, + 0x23, 0x08, 0xb0, 0x00, 0x89, 0xc1, 0x33, 0x08, 0x71, 0x00, 0x89, 0xc0, + 0x83, 0xc1, 0x0a, 0x0f, 0x6f, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, + 0x02, 0xc0, 0x46, 0xa6, 0x27, 0xa6, 0x08, 0xa6, 0x0b, 0xf0, 0x03, 0xc5, + 0x85, 0xc0, 0xb9, 0x61, 0xfa, 0x0f, 0xef, 0xea, 0x4c, 0x74, 0x05, 0xc1, + 0x04, 0x6d, 0x43, 0xc0, 0x29, 0xa6, 0x03, 0xc0, 0x8a, 0x21, 0x3e, 0x06, + 0x32, 0x70, 0xca, 0x20, 0x4d, 0x20, 0x3c, 0x21, 0x01, 0x20, 0x3d, 0x21, + 0x00, 0x20, 0x1f, 0x67, 0xd4, 0xf1, 0x02, 0x40, 0xca, 0xc7, 0xe0, 0x78, + 0x48, 0x31, 0x01, 0x00, 0x07, 0x36, 0x42, 0x70, 0x48, 0x47, 0x00, 0x00, + 0x2c, 0x70, 0x04, 0x32, 0x40, 0x80, 0xc7, 0xf6, 0x01, 0x32, 0x81, 0x0f, + 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x32, 0x81, 0x0f, 0x00, 0xbf, + 0x00, 0x00, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x18, 0x43, 0x00, 0x48, 0x31, + 0x81, 0x00, 0x48, 0x31, 0x41, 0x02, 0x35, 0x79, 0xe0, 0x7f, 0x23, 0xa0, + 0xe4, 0xc3, 0xa3, 0xc1, 0x20, 0x42, 0x08, 0x45, 0x80, 0xc1, 0x40, 0x40, + 0xea, 0x08, 0x6f, 0xf4, 0x80, 0xc6, 0x00, 0xc3, 0x8d, 0x71, 0x0c, 0x71, + 0x01, 0x4e, 0x04, 0x31, 0xc0, 0x80, 0xca, 0x23, 0x49, 0x00, 0x14, 0x72, + 0x0c, 0x72, 0xba, 0xf7, 0x26, 0x85, 0x8a, 0x22, 0x4c, 0x07, 0xba, 0x62, + 0x04, 0x33, 0x40, 0x80, 0xce, 0xf7, 0x24, 0x85, 0x04, 0x33, 0x40, 0x80, + 0xdd, 0xf7, 0x05, 0x85, 0x04, 0x33, 0x00, 0x80, 0x56, 0x00, 0x2e, 0x00, + 0x8d, 0x74, 0x14, 0x12, 0xce, 0x00, 0x34, 0xf0, 0xa1, 0x41, 0x80, 0x21, + 0x0c, 0x07, 0x00, 0x89, 0x61, 0x89, 0x04, 0x77, 0xc9, 0x6b, 0x0d, 0x7b, + 0xcd, 0x78, 0x88, 0x23, 0x3e, 0x02, 0x8c, 0x20, 0x3e, 0x82, 0x4c, 0x00, + 0x2a, 0x00, 0x60, 0xa9, 0x88, 0xd9, 0x0c, 0x71, 0x30, 0xf0, 0xa9, 0x44, + 0x80, 0x24, 0x0c, 0x17, 0x20, 0x8c, 0x61, 0x8c, 0x24, 0x77, 0xc9, 0x6b, + 0x2d, 0x7b, 0xcd, 0x79, 0x88, 0x23, 0x3e, 0x02, 0x8c, 0x21, 0x3e, 0x82, + 0x60, 0xac, 0x9e, 0xf6, 0xc0, 0xaa, 0x8d, 0x72, 0x0f, 0xf0, 0xa1, 0x41, + 0x80, 0x21, 0x0c, 0x07, 0x01, 0x89, 0x14, 0x11, 0xc3, 0x00, 0xc9, 0x68, + 0xcd, 0x78, 0x8c, 0x20, 0x3e, 0x82, 0x60, 0xa9, 0x90, 0xf6, 0x8d, 0x73, + 0xc0, 0xaa, 0x2f, 0x26, 0x85, 0xf3, 0x24, 0x00, 0x23, 0x00, 0x0c, 0x74, + 0x80, 0x25, 0x0c, 0x17, 0x00, 0x15, 0xc3, 0x10, 0x81, 0x40, 0x07, 0xf0, + 0x88, 0xd9, 0x04, 0xf0, 0x88, 0xd9, 0x0c, 0x73, 0x20, 0xaa, 0x09, 0x0b, + 0x12, 0x00, 0x0c, 0x73, 0xc4, 0xc7, 0xe0, 0x78, 0xf2, 0xc3, 0x82, 0x24, + 0x0c, 0x3d, 0x50, 0x42, 0x10, 0x41, 0x8d, 0xc0, 0x8a, 0x22, 0x0c, 0x00, + 0xa2, 0x0e, 0xef, 0xea, 0x28, 0x45, 0x26, 0x40, 0x40, 0x24, 0x83, 0x33, + 0x40, 0x24, 0x04, 0x35, 0x40, 0x24, 0x05, 0x3c, 0x40, 0x24, 0x06, 0x34, + 0x40, 0x24, 0xc7, 0x33, 0xa1, 0x41, 0x42, 0x42, 0xae, 0x0a, 0x2f, 0xf2, + 0x0e, 0x1c, 0x43, 0x35, 0x05, 0xc0, 0x03, 0xe8, 0xd2, 0xc7, 0x0f, 0x14, + 0x8e, 0x30, 0x8a, 0x24, 0x04, 0x27, 0x8a, 0x23, 0x04, 0x2d, 0x8a, 0x20, + 0x05, 0x23, 0x8a, 0x27, 0x05, 0x1f, 0x55, 0x21, 0x8d, 0x2e, 0x56, 0x21, + 0x15, 0x28, 0x00, 0x24, 0x54, 0x24, 0x00, 0x23, 0x53, 0x24, 0x00, 0x20, + 0x50, 0x24, 0x22, 0x77, 0x0e, 0x14, 0x81, 0x30, 0xcf, 0x78, 0x30, 0x70, + 0xc8, 0x01, 0x2d, 0x00, 0x8a, 0x21, 0x08, 0x00, 0x04, 0x77, 0x94, 0xe0, + 0x1e, 0x01, 0x0d, 0x00, 0x25, 0x20, 0x00, 0x00, 0x15, 0xf0, 0x1b, 0xf0, + 0x1f, 0xf0, 0x25, 0xf0, 0x29, 0xf0, 0x2f, 0xf0, 0x33, 0xf0, 0x3c, 0xf0, + 0x40, 0xf0, 0x49, 0xf0, 0x50, 0xf0, 0x59, 0xf0, 0x66, 0xf0, 0x75, 0xf0, + 0x83, 0xf0, 0x8a, 0xf0, 0x97, 0xf0, 0x9e, 0xf0, 0xa3, 0xf0, 0xb2, 0xf0, + 0xbf, 0xf0, 0x8d, 0xc0, 0x96, 0x0f, 0x2f, 0xee, 0x84, 0xc1, 0x00, 0xa5, + 0x71, 0xf0, 0x8d, 0xc0, 0x8a, 0x0f, 0x2f, 0xee, 0x84, 0xc1, 0x01, 0xa5, + 0x6b, 0xf0, 0x8d, 0xc0, 0x72, 0x0a, 0x6f, 0xf6, 0x84, 0xc1, 0x02, 0xa5, + 0x65, 0xf0, 0x8d, 0xc0, 0x66, 0x0a, 0x6f, 0xf6, 0x84, 0xc1, 0x03, 0xa5, + 0x5f, 0xf0, 0x8d, 0xc0, 0x5a, 0x0a, 0x6f, 0xf6, 0x84, 0xc1, 0x04, 0xa5, + 0x59, 0xf0, 0x8d, 0xc0, 0x5a, 0x0f, 0x2f, 0xee, 0x84, 0xc1, 0x05, 0xa5, + 0x53, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0xd6, 0x0b, 0xaf, 0xf9, 0x86, 0xc2, + 0x86, 0xc1, 0x18, 0xda, 0xa2, 0x40, 0x49, 0xf0, 0x8d, 0xc0, 0x32, 0x0a, + 0x6f, 0xf6, 0x84, 0xc1, 0x0c, 0xa5, 0x45, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, + 0xb6, 0x0b, 0xaf, 0xf9, 0x86, 0xc2, 0x86, 0xc1, 0x18, 0xda, 0x82, 0x40, + 0x39, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0xa6, 0x0b, 0xaf, 0xf9, 0x86, 0xc2, + 0x86, 0xc1, 0x18, 0xda, 0x62, 0x40, 0x31, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, + 0x92, 0x0b, 0xaf, 0xf9, 0x86, 0xc2, 0x86, 0xc1, 0x18, 0xda, 0x02, 0x40, + 0x27, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0xea, 0x0b, 0xaf, 0xf7, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x59, 0x19, 0x98, 0x20, 0x5a, 0x19, + 0x58, 0x20, 0x5b, 0x19, 0x18, 0x20, 0x1b, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, + 0xca, 0x0b, 0xaf, 0xf7, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, + 0x5c, 0x19, 0x98, 0x20, 0x5d, 0x19, 0x58, 0x20, 0x5e, 0x19, 0x18, 0x20, + 0x0b, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0x46, 0x0b, 0xaf, 0xf9, 0x86, 0xc2, + 0x86, 0xc1, 0x18, 0xda, 0xe1, 0x40, 0x1e, 0x0d, 0xcf, 0xea, 0x04, 0xc0, + 0x52, 0x70, 0xcc, 0x06, 0xee, 0xff, 0xc5, 0x71, 0x52, 0xf0, 0x8d, 0xc0, + 0x92, 0x09, 0x6f, 0xf6, 0x84, 0xc1, 0xac, 0x1d, 0x00, 0x10, 0xf5, 0xf1, + 0x8d, 0xc0, 0x84, 0xc1, 0x7e, 0x0b, 0xaf, 0xf7, 0x80, 0xc2, 0x00, 0xc2, + 0x01, 0xc1, 0x02, 0xc0, 0x66, 0x19, 0x98, 0x20, 0x67, 0x19, 0x58, 0x20, + 0x68, 0x19, 0x18, 0x20, 0xe5, 0xf1, 0x8d, 0xc0, 0x72, 0x0e, 0x2f, 0xee, + 0x84, 0xc1, 0xbc, 0x1d, 0x00, 0x10, 0xdf, 0xf1, 0x8d, 0xc0, 0x66, 0x0e, + 0x2f, 0xee, 0x84, 0xc1, 0xc0, 0x1d, 0x00, 0x10, 0xd7, 0xf1, 0x8d, 0xc0, + 0x84, 0xc1, 0xb6, 0x0b, 0x6f, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, + 0x02, 0xc0, 0x6b, 0x19, 0x98, 0x20, 0x6c, 0x19, 0x58, 0x20, 0x6d, 0x19, + 0x18, 0x20, 0xc9, 0xf1, 0x8d, 0xc0, 0x84, 0xc1, 0x96, 0x0b, 0x6f, 0xf6, + 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x6e, 0x19, 0x98, 0x20, + 0x6f, 0x19, 0x58, 0x20, 0x70, 0x19, 0x18, 0x20, 0xb9, 0xf1, 0x8d, 0xc0, + 0x1a, 0x0e, 0x2f, 0xee, 0x84, 0xc1, 0xdc, 0x1d, 0x00, 0x10, 0xb3, 0xf1, + 0xc3, 0x42, 0x13, 0x00, 0xd8, 0x6c, 0x2a, 0x08, 0x20, 0x02, 0x22, 0x40, + 0x0c, 0x70, 0xd2, 0xc7, 0x8a, 0x20, 0x3e, 0x06, 0xd2, 0xc7, 0xe0, 0x78, + 0xee, 0xc3, 0xad, 0xc1, 0x08, 0x45, 0x04, 0x88, 0x0a, 0x21, 0x80, 0x21, + 0x0a, 0x20, 0x40, 0x21, 0x70, 0x43, 0x48, 0x47, 0x30, 0x42, 0x0a, 0xe8, + 0x8a, 0x20, 0x0c, 0x09, 0x08, 0x65, 0x06, 0xe8, 0xa1, 0x40, 0x32, 0x0c, + 0x60, 0x00, 0x42, 0x41, 0x8a, 0x20, 0x0c, 0x09, 0x4a, 0x24, 0xc0, 0x70, + 0x6d, 0x70, 0xb8, 0x60, 0x00, 0x25, 0x8e, 0x1f, 0x00, 0x00, 0xd4, 0x01, + 0x04, 0x1d, 0xc2, 0x12, 0x00, 0x18, 0x43, 0x00, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0x00, 0x07, 0x01, 0x4f, 0x00, 0x31, 0x81, 0x0f, 0x7a, 0x3d, + 0x00, 0x00, 0x04, 0x31, 0xc0, 0x82, 0xc7, 0xf6, 0x01, 0x31, 0x8c, 0x0f, + 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x31, 0x8c, 0x0f, 0x00, 0xbf, + 0x00, 0x00, 0x80, 0xc3, 0x8b, 0xc2, 0x48, 0x34, 0xcc, 0x12, 0x15, 0x7b, + 0x14, 0x7a, 0x04, 0x71, 0x20, 0xa3, 0x80, 0xb2, 0x8a, 0x27, 0x09, 0x1f, + 0xbf, 0x67, 0x8b, 0xc2, 0x2c, 0x71, 0xda, 0x0a, 0xaf, 0xf1, 0xe1, 0x40, + 0x76, 0x70, 0x6e, 0x70, 0x1c, 0xf4, 0x80, 0xc1, 0x3a, 0x0c, 0xef, 0xff, + 0xa1, 0x40, 0x4a, 0x24, 0xc0, 0x70, 0x0a, 0x23, 0x00, 0x00, 0x88, 0xc0, + 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x01, 0x24, 0x00, 0x31, 0x81, 0x0f, + 0xcc, 0x3d, 0xcd, 0xcc, 0x04, 0x18, 0x50, 0x00, 0xa1, 0x42, 0x88, 0xc1, + 0x80, 0x22, 0x0c, 0x01, 0xc6, 0x0e, 0x20, 0x00, 0xa1, 0x40, 0x10, 0x43, + 0x59, 0x16, 0x01, 0x16, 0x17, 0xe9, 0xa1, 0x40, 0x80, 0x20, 0x0b, 0x04, + 0x00, 0x88, 0x93, 0xe8, 0x8b, 0xc2, 0xe1, 0x40, 0x02, 0x0b, 0xaf, 0xf1, + 0x40, 0x24, 0x12, 0x3b, 0x4a, 0x24, 0xc0, 0x70, 0x80, 0xc0, 0xa8, 0x20, + 0x40, 0x02, 0x02, 0x12, 0x41, 0x25, 0x48, 0x31, 0x81, 0x00, 0x04, 0x18, + 0x50, 0x00, 0x58, 0x16, 0x00, 0x16, 0x8a, 0x27, 0x0c, 0x11, 0xbf, 0x67, + 0x00, 0x30, 0x82, 0x0f, 0x74, 0x49, 0x00, 0x24, 0x80, 0xc1, 0x40, 0x24, + 0x04, 0x34, 0xc3, 0x43, 0x2b, 0x32, 0x77, 0xcc, 0xe1, 0x40, 0x5a, 0x0d, + 0x6f, 0xf1, 0x40, 0x24, 0x12, 0x30, 0x84, 0xc1, 0x10, 0xda, 0x3a, 0x0b, + 0xef, 0xea, 0xe1, 0x40, 0x84, 0xc1, 0x02, 0x0c, 0x6f, 0xf1, 0xe1, 0x40, + 0x84, 0xc1, 0x10, 0xda, 0x26, 0x0b, 0xef, 0xea, 0xe1, 0x40, 0x40, 0x24, + 0xc1, 0x33, 0x40, 0x24, 0x82, 0x33, 0x82, 0x08, 0x20, 0x00, 0xa1, 0x40, + 0x0e, 0x14, 0x80, 0x30, 0x00, 0x19, 0x03, 0x20, 0x05, 0x20, 0xfe, 0x84, + 0x04, 0xf2, 0x80, 0xd8, 0x00, 0x19, 0x02, 0x20, 0x40, 0x86, 0x21, 0x86, + 0x02, 0x86, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0xc2, 0x41, 0xc1, 0x42, 0xc0, + 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x00, 0x24, 0x00, 0x30, 0x80, 0x0f, + 0x20, 0x41, 0x00, 0x00, 0x04, 0x18, 0x10, 0x20, 0x0f, 0x14, 0x80, 0x30, + 0x48, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x20, 0xce, 0xc7, 0xe0, 0x78, + 0xa3, 0xc1, 0x4a, 0x24, 0xc0, 0x70, 0x80, 0xc3, 0x80, 0xc2, 0xa8, 0x20, + 0x00, 0x02, 0x04, 0x10, 0x01, 0x04, 0xbf, 0xb9, 0x04, 0x1a, 0x50, 0x00, + 0x00, 0xc0, 0x2c, 0x71, 0x22, 0x4b, 0x04, 0x32, 0x00, 0x80, 0xca, 0x20, + 0x89, 0x00, 0x34, 0x72, 0x2c, 0x72, 0xba, 0xf7, 0xe0, 0x7f, 0xa3, 0xc0, + 0xe8, 0xc3, 0x82, 0x24, 0x02, 0x3a, 0x48, 0x47, 0x28, 0x46, 0x08, 0x45, + 0x56, 0x20, 0x01, 0x0f, 0x86, 0xc0, 0x90, 0xda, 0x86, 0x0a, 0xef, 0xea, + 0x40, 0x24, 0x10, 0x36, 0x4a, 0x24, 0x80, 0x71, 0x80, 0xc3, 0x80, 0xc0, + 0xa8, 0x20, 0x80, 0x01, 0x1c, 0x10, 0x01, 0x24, 0x04, 0x18, 0x50, 0x00, + 0x03, 0xc2, 0x2c, 0x70, 0x15, 0x23, 0x40, 0x00, 0x04, 0x80, 0x04, 0x30, + 0x80, 0x80, 0xca, 0x22, 0x09, 0x00, 0x34, 0x71, 0x2c, 0x71, 0xf8, 0xf5, + 0xc0, 0x15, 0x00, 0x10, 0x04, 0x32, 0x00, 0x80, 0x44, 0xf7, 0x00, 0x1e, + 0xc3, 0x10, 0x11, 0xf0, 0xbc, 0x15, 0x00, 0x10, 0x04, 0x32, 0x00, 0x80, + 0x44, 0xf7, 0x00, 0x1e, 0x83, 0x10, 0x09, 0xf0, 0xb8, 0x15, 0x00, 0x10, + 0x04, 0x32, 0x00, 0x80, 0x6f, 0x20, 0x0b, 0x00, 0x00, 0xae, 0x8a, 0x20, + 0x4c, 0x05, 0x08, 0x65, 0x09, 0x08, 0x91, 0x01, 0x00, 0x1e, 0x03, 0x10, + 0x00, 0x1f, 0x03, 0x10, 0x80, 0x25, 0x0c, 0x15, 0x20, 0x8d, 0x00, 0x8e, + 0x0d, 0x08, 0x40, 0x00, 0x00, 0x1f, 0x43, 0x10, 0x00, 0x8e, 0x00, 0xad, + 0xc8, 0xc7, 0xe0, 0x78, 0xfa, 0xc3, 0xa2, 0xc1, 0x10, 0x40, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x50, 0x41, 0x28, 0x45, 0x55, 0x20, 0x8e, 0x2e, 0x66, 0x0e, + 0xef, 0xf1, 0x03, 0x1c, 0x43, 0x35, 0x02, 0x14, 0x81, 0x30, 0x8a, 0x20, + 0x06, 0x0b, 0x8a, 0x22, 0x04, 0x07, 0x8a, 0x23, 0x04, 0x0d, 0x8a, 0x27, + 0x05, 0x13, 0x8a, 0x24, 0x05, 0x19, 0x56, 0x20, 0x19, 0x28, 0x56, 0x20, + 0x98, 0x2b, 0x56, 0x20, 0xd7, 0x2c, 0x56, 0x20, 0xd2, 0x2d, 0x00, 0x20, + 0x16, 0x20, 0x00, 0x20, 0x94, 0x20, 0x00, 0x20, 0xd3, 0x20, 0x02, 0x77, + 0x00, 0x20, 0x15, 0x23, 0x80, 0x20, 0x05, 0x2f, 0x03, 0x14, 0x80, 0x30, + 0x2f, 0x79, 0xe1, 0x08, 0x64, 0x00, 0x09, 0x69, 0xcd, 0x08, 0x55, 0x05, + 0x25, 0x20, 0x00, 0x00, 0x15, 0xf0, 0x17, 0xf0, 0x17, 0xf0, 0x19, 0xf0, + 0x19, 0xf0, 0x1b, 0xf0, 0x1b, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x21, 0xf0, + 0x22, 0xf0, 0x25, 0xf0, 0x26, 0xf0, 0x29, 0xf0, 0x2e, 0xf0, 0x36, 0xf0, + 0x3b, 0xf0, 0x3e, 0xf0, 0x3f, 0xf0, 0x42, 0xf0, 0x47, 0xf0, 0x00, 0x86, + 0x47, 0xf0, 0x01, 0x86, 0x45, 0xf0, 0x02, 0x86, 0x24, 0xf0, 0x03, 0x86, + 0x22, 0xf0, 0x04, 0x86, 0x20, 0xf0, 0x05, 0x86, 0x3d, 0xf0, 0x81, 0xc3, + 0x23, 0x40, 0x15, 0xf0, 0x0c, 0x86, 0x1a, 0xf0, 0x81, 0xc3, 0x82, 0x40, + 0x0f, 0xf0, 0x81, 0xc3, 0x62, 0x40, 0x0d, 0xf0, 0x81, 0xc3, 0xe1, 0x40, + 0x09, 0xf0, 0x81, 0xc3, 0xa2, 0x40, 0x16, 0xf0, 0x81, 0xc3, 0x03, 0x40, + 0x12, 0xf0, 0x81, 0xc3, 0x02, 0x40, 0xa1, 0x41, 0x4a, 0x0f, 0x6f, 0xf9, + 0x22, 0x42, 0x28, 0xf0, 0xac, 0x16, 0x00, 0x10, 0x81, 0xc3, 0xa1, 0x41, + 0xa6, 0x0d, 0x2f, 0xf6, 0x22, 0x42, 0x20, 0xf0, 0x81, 0xc3, 0xe2, 0x40, + 0xa1, 0x41, 0x96, 0x0f, 0x6f, 0xf7, 0x22, 0x42, 0x18, 0xf0, 0xbc, 0x16, + 0x00, 0x10, 0x11, 0xf0, 0xc0, 0x16, 0x00, 0x10, 0x0d, 0xf0, 0x81, 0xc3, + 0xc2, 0x40, 0x04, 0xf0, 0x81, 0xc3, 0x42, 0x40, 0xa1, 0x41, 0xe6, 0x0f, + 0x2f, 0xf6, 0x22, 0x42, 0x08, 0xf0, 0xdc, 0x16, 0x00, 0x10, 0x81, 0xc3, + 0xa1, 0x41, 0x76, 0x0a, 0x2f, 0xee, 0x22, 0x42, 0x02, 0x14, 0x80, 0x30, + 0x21, 0x68, 0x02, 0x1c, 0x42, 0x30, 0x90, 0xf1, 0x01, 0xc0, 0x41, 0x28, + 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xda, 0xc7, 0xe8, 0xc3, 0xa1, 0xc1, + 0x60, 0x40, 0x48, 0x45, 0x28, 0x46, 0x2c, 0x70, 0x10, 0xda, 0x88, 0x47, + 0xda, 0x0e, 0xaf, 0xf8, 0x70, 0x40, 0xd5, 0x70, 0xcd, 0x70, 0x08, 0xf2, + 0x47, 0x0d, 0x91, 0x19, 0x00, 0x18, 0x83, 0x21, 0xcd, 0x71, 0x1f, 0xf0, + 0x4a, 0x24, 0x00, 0x71, 0xc3, 0x42, 0x13, 0x00, 0xc8, 0x6c, 0x0c, 0x70, + 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x03, 0x04, 0x80, 0xc1, 0x1c, 0x61, + 0x04, 0x71, 0x38, 0x23, 0x41, 0x03, 0x20, 0xac, 0xd6, 0x09, 0x2f, 0xf4, + 0x80, 0xc0, 0x0b, 0xe8, 0xcd, 0x74, 0x03, 0x18, 0xc3, 0x21, 0x02, 0x18, + 0x43, 0x21, 0x01, 0x18, 0x83, 0x20, 0x00, 0x18, 0x43, 0x20, 0xc0, 0xa7, + 0xc8, 0xc7, 0xe0, 0x78, 0xf4, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x50, 0x43, 0x28, 0x45, 0xae, 0x0c, 0xef, 0xf1, 0x03, 0x1c, + 0xc3, 0x31, 0x02, 0x14, 0x80, 0x30, 0x8a, 0x20, 0x09, 0x2c, 0x8a, 0x27, + 0x0c, 0x11, 0x8a, 0x26, 0x4c, 0x25, 0x8a, 0x22, 0x8c, 0x25, 0x8a, 0x21, + 0x0c, 0x29, 0x56, 0x26, 0x54, 0x1e, 0x56, 0x26, 0x15, 0x1f, 0x00, 0x20, + 0x90, 0x23, 0xdf, 0x67, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0x87, 0x09, + 0x24, 0x00, 0x04, 0x77, 0x73, 0x08, 0xd5, 0x01, 0x25, 0x20, 0x00, 0x00, + 0x07, 0xf0, 0x1f, 0xf0, 0x0c, 0xf0, 0x13, 0xf0, 0x18, 0xf0, 0x22, 0xf0, + 0x28, 0xf0, 0x81, 0xc3, 0x82, 0x40, 0xa1, 0x41, 0x36, 0x0f, 0xaf, 0xf9, + 0x62, 0x42, 0x29, 0xf0, 0x81, 0xc3, 0x02, 0x40, 0xa1, 0x41, 0xd2, 0x0e, + 0x2f, 0xf6, 0x62, 0x42, 0x21, 0xf0, 0x81, 0xc3, 0xe1, 0x40, 0xa1, 0x41, + 0x46, 0x0b, 0x2f, 0xf9, 0x62, 0x42, 0x1b, 0xf0, 0x32, 0x26, 0x80, 0x15, + 0x0a, 0xf0, 0x81, 0xc3, 0xa2, 0x40, 0xa1, 0x41, 0xaa, 0x0c, 0x2f, 0xfa, + 0x62, 0x42, 0x11, 0xf0, 0x32, 0x26, 0x80, 0x14, 0x81, 0xc3, 0xa1, 0x41, + 0x1e, 0x0e, 0xaf, 0xf3, 0x62, 0x42, 0x09, 0xf0, 0x32, 0x26, 0x40, 0x14, + 0x81, 0xc3, 0xa1, 0x41, 0x3a, 0x0a, 0xef, 0xf8, 0x62, 0x42, 0x02, 0x14, + 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xbc, 0xf1, 0x01, 0xc0, + 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xd4, 0xc7, 0xe0, 0x78, + 0xee, 0xc3, 0x82, 0x24, 0x07, 0x35, 0x50, 0x41, 0x28, 0x45, 0x10, 0x40, + 0x56, 0x24, 0x80, 0x3d, 0x2c, 0x70, 0x24, 0xda, 0xa8, 0x46, 0x0a, 0x23, + 0x00, 0x21, 0x70, 0x42, 0x86, 0x0d, 0xaf, 0xf8, 0x56, 0x24, 0x8f, 0x3d, + 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x16, 0x00, 0x14, + 0x10, 0x1f, 0x10, 0x10, 0x8d, 0x70, 0x0a, 0x21, 0x40, 0x14, 0x6c, 0x70, + 0x0a, 0x20, 0x80, 0x14, 0x4c, 0x70, 0x5a, 0x22, 0x80, 0x01, 0x4a, 0x24, + 0x80, 0x71, 0x56, 0x24, 0x4e, 0x3b, 0x79, 0x60, 0x35, 0x7e, 0x0a, 0x23, + 0x00, 0x12, 0x21, 0x41, 0x0c, 0x70, 0x80, 0xa6, 0xa8, 0x20, 0x80, 0x02, + 0x0c, 0x13, 0x07, 0x14, 0x18, 0x11, 0x06, 0x04, 0x00, 0x36, 0xc6, 0x01, + 0x01, 0x30, 0x80, 0x01, 0x44, 0x71, 0x05, 0x74, 0xcf, 0x0a, 0xf4, 0x80, + 0x00, 0xa6, 0x64, 0x71, 0xc1, 0x0b, 0xb4, 0x81, 0x25, 0x74, 0x55, 0x24, + 0xc8, 0x3f, 0x55, 0x24, 0xc9, 0x3f, 0x0a, 0x26, 0x80, 0x04, 0x15, 0x20, + 0x05, 0x13, 0x4c, 0x70, 0x0a, 0x23, 0x40, 0x14, 0x0c, 0x70, 0x4a, 0x24, + 0x80, 0x71, 0x14, 0x20, 0x01, 0x00, 0x15, 0x25, 0x4e, 0x00, 0xc0, 0x43, + 0x2c, 0x70, 0x40, 0xa6, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x13, 0x04, 0x14, + 0x0c, 0x13, 0x07, 0x04, 0x00, 0x37, 0x07, 0x01, 0x01, 0x31, 0xc1, 0x01, + 0x04, 0x71, 0xdb, 0x08, 0xb4, 0x81, 0x20, 0xa6, 0x0a, 0x24, 0x80, 0x04, + 0x4a, 0x24, 0x80, 0x71, 0x6d, 0x70, 0x21, 0x41, 0x0a, 0x20, 0x00, 0x01, + 0xa8, 0x20, 0x80, 0x02, 0x0c, 0x10, 0x07, 0x04, 0x0c, 0x11, 0x03, 0x04, + 0x00, 0x33, 0xc3, 0x01, 0x01, 0x33, 0xcb, 0x10, 0x14, 0x22, 0x80, 0x00, + 0x56, 0x24, 0x81, 0x3d, 0x98, 0x60, 0x01, 0x49, 0x00, 0x24, 0x83, 0x3f, + 0x00, 0x00, 0x44, 0x01, 0x44, 0x71, 0x01, 0x33, 0x41, 0x10, 0x84, 0x74, + 0x15, 0x7b, 0xc5, 0x0a, 0xf4, 0x80, 0x20, 0xa3, 0x85, 0x71, 0x25, 0x74, + 0x7b, 0x0c, 0xf4, 0x90, 0xc4, 0x74, 0x56, 0x24, 0x40, 0x3b, 0x00, 0x24, + 0x81, 0x3f, 0x00, 0x00, 0x44, 0x01, 0x55, 0x24, 0x42, 0x3b, 0xea, 0x0c, + 0xaf, 0xf8, 0x55, 0x24, 0x4e, 0x3b, 0x2c, 0x70, 0x4a, 0x24, 0xc0, 0x70, + 0xc1, 0x42, 0x62, 0x40, 0x4a, 0x23, 0x00, 0x00, 0xa8, 0x20, 0x80, 0x02, + 0x04, 0x10, 0x0b, 0x04, 0x18, 0x12, 0x0c, 0x04, 0x00, 0x34, 0xcc, 0x12, + 0x01, 0x33, 0x03, 0x03, 0x20, 0x4d, 0x15, 0x20, 0x42, 0x20, 0x24, 0x71, + 0x01, 0x33, 0x00, 0x00, 0xc5, 0x74, 0xd5, 0x09, 0xb4, 0x81, 0x72, 0x1a, + 0x18, 0x00, 0x55, 0x24, 0x00, 0x39, 0x2c, 0x70, 0x24, 0xda, 0x32, 0x0c, + 0xaf, 0xf8, 0x55, 0x24, 0x0d, 0x39, 0x4a, 0x24, 0x80, 0x71, 0xa8, 0x20, + 0x40, 0x01, 0x07, 0x1d, 0x53, 0x10, 0xcc, 0x70, 0x55, 0x24, 0x48, 0x3b, + 0x8d, 0x70, 0x0a, 0x21, 0x80, 0x14, 0x6c, 0x70, 0x4a, 0x24, 0xc0, 0x70, + 0x01, 0x40, 0x6d, 0x70, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x11, 0x02, 0x14, + 0x18, 0x10, 0x01, 0x04, 0x00, 0x31, 0x81, 0x00, 0x01, 0x33, 0x4b, 0x10, + 0x5a, 0x23, 0x80, 0x01, 0x40, 0x24, 0x04, 0x30, 0x64, 0x71, 0x99, 0x60, + 0x55, 0x24, 0x00, 0x39, 0x33, 0x20, 0x40, 0x00, 0x15, 0x24, 0x41, 0x00, + 0x48, 0x30, 0x80, 0x00, 0x02, 0x30, 0xc0, 0x02, 0xc5, 0x0b, 0xb4, 0x81, + 0x00, 0xa1, 0x85, 0x71, 0xb7, 0x0c, 0xb4, 0x91, 0x05, 0x74, 0x4c, 0x70, + 0x15, 0x20, 0x87, 0x20, 0x0a, 0x20, 0x40, 0x14, 0x2c, 0x70, 0x5a, 0x21, + 0x80, 0x01, 0x4a, 0x24, 0x80, 0x71, 0x80, 0x43, 0x15, 0x27, 0x0c, 0x00, + 0x4a, 0x20, 0x00, 0x00, 0x78, 0x1c, 0x98, 0x11, 0xa8, 0x20, 0x00, 0x03, + 0x04, 0x10, 0x09, 0x14, 0x18, 0x13, 0x0b, 0x04, 0x00, 0x33, 0x4b, 0x12, + 0x01, 0x30, 0xc0, 0x02, 0x78, 0x1c, 0x18, 0x10, 0x24, 0x71, 0xd3, 0x09, + 0x94, 0x81, 0x44, 0x71, 0xc1, 0x0a, 0xb4, 0x81, 0x84, 0x74, 0xce, 0xc7, + 0xe8, 0xc3, 0x82, 0x24, 0x02, 0x34, 0x4a, 0x24, 0x80, 0x71, 0x50, 0x40, + 0x0a, 0x25, 0x00, 0x10, 0x56, 0x20, 0x4e, 0x0e, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x11, 0x00, 0x04, 0x04, 0x1e, 0x10, 0x10, 0x80, 0xc0, 0x2c, 0x70, + 0x90, 0xda, 0x56, 0x0b, 0xaf, 0xf8, 0x80, 0xc7, 0x4a, 0x24, 0x80, 0x71, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x00, 0x24, 0x1c, 0x1f, 0x10, 0x10, + 0x80, 0xc1, 0x90, 0xda, 0xf6, 0x0c, 0xaf, 0xea, 0x0a, 0x20, 0x80, 0x03, + 0x4a, 0x24, 0xc0, 0x70, 0x80, 0x25, 0x09, 0x1c, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x1d, 0x11, 0x10, 0xc8, 0xc7, 0xe0, 0x78, 0xf0, 0xc3, 0xb5, 0xc1, + 0x30, 0x40, 0x8a, 0x27, 0x4c, 0x15, 0x10, 0x42, 0x00, 0x20, 0x8d, 0x0f, + 0x00, 0x00, 0xbc, 0x02, 0xcd, 0x70, 0x1f, 0x67, 0x92, 0xc1, 0x02, 0x40, + 0x70, 0x43, 0x50, 0x44, 0x41, 0x1c, 0x82, 0x33, 0x1a, 0x0e, 0xef, 0xf3, + 0x54, 0x24, 0x11, 0x39, 0x4a, 0x24, 0xc0, 0x70, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0xc0, 0x04, 0x15, 0x22, 0x03, 0x20, 0xf0, 0x21, 0x01, 0x20, + 0xd8, 0x13, 0x03, 0x00, 0x00, 0x24, 0x82, 0x3f, 0x00, 0x00, 0x45, 0x00, + 0x1a, 0x62, 0x04, 0x31, 0xc0, 0x80, 0x04, 0x71, 0x6f, 0x21, 0x0b, 0x00, + 0x20, 0xaa, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, 0x45, 0x00, 0xce, 0x09, + 0x0f, 0xf3, 0x20, 0x8f, 0x2a, 0xe8, 0x34, 0x76, 0x90, 0x01, 0x0d, 0x00, + 0x25, 0x20, 0x40, 0x00, 0x07, 0xf0, 0xc4, 0xf0, 0x2c, 0xf0, 0xc2, 0xf0, + 0x4b, 0xf0, 0x61, 0xf0, 0x6d, 0xf0, 0x17, 0x85, 0x3f, 0x85, 0x41, 0x68, + 0x30, 0x70, 0x74, 0x01, 0x2b, 0x00, 0x57, 0xa5, 0x84, 0x15, 0x02, 0x96, + 0x85, 0x15, 0x01, 0x96, 0x86, 0x15, 0x00, 0x96, 0xd7, 0xa5, 0x00, 0x1f, + 0x83, 0x10, 0x43, 0xc2, 0x44, 0xc1, 0x45, 0xc0, 0x40, 0x22, 0x02, 0x28, + 0x80, 0xc1, 0x42, 0x40, 0x40, 0xc6, 0x41, 0xc6, 0xf2, 0x0e, 0xef, 0xff, + 0x42, 0xc6, 0xa2, 0xf0, 0x0d, 0x09, 0x70, 0x01, 0x80, 0x22, 0x8c, 0x25, + 0x00, 0x1a, 0x42, 0x20, 0x00, 0x1f, 0x43, 0x11, 0xd7, 0xa5, 0x98, 0xf0, + 0x17, 0x85, 0x54, 0x24, 0x84, 0x38, 0x00, 0x24, 0x85, 0x3f, 0x00, 0x00, + 0x41, 0x00, 0x04, 0x71, 0x17, 0xa5, 0x02, 0x41, 0x82, 0x42, 0x62, 0x43, + 0x56, 0x09, 0x20, 0x00, 0x42, 0x40, 0x54, 0x24, 0x41, 0x38, 0x91, 0xc2, + 0x4e, 0x09, 0xef, 0xff, 0x42, 0x40, 0x42, 0x14, 0x80, 0x30, 0x14, 0x73, + 0x7b, 0xf2, 0x3c, 0x85, 0x17, 0x85, 0x30, 0x70, 0xf4, 0x00, 0x0c, 0x00, + 0xd7, 0xa5, 0xc0, 0xaf, 0x76, 0xf0, 0x00, 0x24, 0x84, 0x3f, 0x00, 0x00, + 0x43, 0x00, 0x00, 0x24, 0x85, 0x3f, 0x00, 0x00, 0x41, 0x00, 0x42, 0x40, + 0x02, 0x41, 0x82, 0x42, 0x16, 0x09, 0x20, 0x00, 0x62, 0x43, 0x43, 0x14, + 0x80, 0x30, 0xcd, 0x08, 0x10, 0x00, 0xd1, 0xa5, 0x00, 0x1f, 0x83, 0x11, + 0x60, 0xf0, 0x17, 0x85, 0x39, 0x85, 0x04, 0x71, 0xb9, 0x08, 0x62, 0x00, + 0x17, 0xa5, 0x80, 0x22, 0x8c, 0x25, 0x00, 0x12, 0x80, 0x20, 0xd7, 0xa5, + 0xff, 0x1a, 0x02, 0xa0, 0x52, 0xf0, 0x37, 0x85, 0x4a, 0x24, 0xc0, 0x70, + 0x01, 0x69, 0x30, 0x43, 0x17, 0xa5, 0x0c, 0x70, 0xa8, 0x20, 0x80, 0x03, + 0x15, 0x22, 0x01, 0x20, 0xf0, 0x20, 0x03, 0x20, 0x9c, 0x11, 0x0c, 0x06, + 0x92, 0xc2, 0x15, 0x7a, 0x02, 0x33, 0x01, 0x03, 0x04, 0x71, 0x20, 0xa2, + 0x8e, 0x08, 0xef, 0xff, 0x92, 0xc0, 0x31, 0x85, 0xe7, 0x17, 0x90, 0x90, + 0x10, 0x44, 0x01, 0x30, 0x40, 0x00, 0x1d, 0x08, 0xb5, 0x22, 0x11, 0xa5, + 0x15, 0x22, 0x00, 0x24, 0xb5, 0x18, 0x18, 0x05, 0x44, 0x15, 0x11, 0x10, + 0x06, 0x71, 0xe7, 0x1f, 0x02, 0x94, 0x17, 0xf0, 0x46, 0x85, 0x8a, 0x21, + 0x0b, 0x06, 0x42, 0x71, 0x02, 0x30, 0x91, 0x00, 0x80, 0xc0, 0x24, 0xda, + 0x1a, 0x0b, 0xaf, 0xea, 0x44, 0x1d, 0x40, 0x14, 0x42, 0x40, 0x80, 0x20, + 0x0b, 0x05, 0x80, 0xc1, 0x28, 0xda, 0x0a, 0x0b, 0xaf, 0xea, 0x24, 0x1c, + 0x00, 0x35, 0x7e, 0x15, 0x01, 0x96, 0x2f, 0x20, 0x07, 0x04, 0x48, 0x30, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x04, 0x31, 0x00, 0xa0, 0x4b, 0xf7, + 0xe7, 0x1f, 0x82, 0x93, 0xd1, 0xa5, 0xd7, 0xa5, 0x00, 0x1f, 0x03, 0x11, + 0x41, 0x14, 0x80, 0x30, 0xd0, 0xc7, 0x1b, 0x85, 0xf9, 0x0b, 0x02, 0xa0, + 0x84, 0x15, 0x02, 0x96, 0x85, 0x15, 0x01, 0x96, 0x86, 0x15, 0x00, 0x96, + 0xe7, 0x1f, 0x82, 0x93, 0xd1, 0xa5, 0xd7, 0xa5, 0x4d, 0xc2, 0x4e, 0xc1, + 0x4f, 0xc0, 0x40, 0x22, 0x02, 0x28, 0x8a, 0xc1, 0x42, 0x40, 0x4a, 0xc6, + 0x4b, 0xc6, 0x7a, 0x0d, 0xef, 0xff, 0x4c, 0xc6, 0x00, 0x1f, 0x83, 0x10, + 0xe2, 0xf1, 0xe0, 0x78, 0xf2, 0xc3, 0x82, 0x24, 0x05, 0x3a, 0x8a, 0x27, + 0x4c, 0x15, 0x0a, 0x24, 0x40, 0x21, 0x0a, 0x21, 0x00, 0x21, 0x70, 0x43, + 0x48, 0x43, 0x30, 0x40, 0x10, 0x42, 0x55, 0x20, 0x4e, 0x08, 0xad, 0x70, + 0x1f, 0x67, 0x00, 0x1d, 0x42, 0x03, 0x59, 0x0b, 0x71, 0x00, 0x00, 0x1c, + 0x42, 0x03, 0x4a, 0x24, 0xc0, 0x70, 0x0c, 0x70, 0xa8, 0x20, 0x40, 0x04, + 0x15, 0x22, 0x02, 0x20, 0xf0, 0x20, 0x01, 0x20, 0x9c, 0x12, 0x03, 0x06, + 0x00, 0x24, 0x82, 0x3f, 0x00, 0x00, 0x5c, 0x01, 0x15, 0x7a, 0x02, 0x31, + 0xc1, 0x00, 0x04, 0x71, 0x20, 0xa2, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, + 0x5c, 0x01, 0x7a, 0x0f, 0x8f, 0xff, 0x2c, 0x86, 0x04, 0x30, 0x40, 0x80, + 0x66, 0x00, 0x0c, 0x00, 0x00, 0x19, 0x43, 0x20, 0x09, 0x8f, 0x14, 0x70, + 0x0c, 0x02, 0x02, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x42, 0x40, 0x80, 0x20, + 0x8c, 0x07, 0x20, 0x88, 0x02, 0xe9, 0xa0, 0xa8, 0x56, 0x24, 0xc1, 0x39, + 0x61, 0x40, 0xea, 0x08, 0x2f, 0xf1, 0x56, 0x24, 0xd5, 0x39, 0x0c, 0x70, + 0x00, 0x24, 0x81, 0x3f, 0x00, 0x00, 0x14, 0x01, 0x4a, 0x24, 0xc0, 0x70, + 0x0a, 0x22, 0x40, 0x05, 0xa8, 0x20, 0x80, 0x01, 0x0c, 0x12, 0x03, 0x04, + 0x04, 0x19, 0xd0, 0x00, 0x04, 0x71, 0xed, 0x08, 0xf4, 0x80, 0xa6, 0x74, + 0x41, 0x0b, 0xf0, 0x20, 0x54, 0x22, 0x81, 0x2d, 0x35, 0x0b, 0x31, 0x21, + 0x54, 0x22, 0x81, 0x2a, 0x18, 0xf0, 0x27, 0x17, 0x81, 0x10, 0x49, 0x8f, + 0x30, 0x72, 0x68, 0x01, 0x06, 0x00, 0x04, 0x30, 0x80, 0x8f, 0x20, 0x41, + 0x00, 0x00, 0xa0, 0x01, 0x2c, 0x00, 0x44, 0x71, 0x9f, 0x16, 0x01, 0x16, + 0x49, 0xaf, 0x01, 0x30, 0x40, 0x00, 0x9f, 0x1e, 0x18, 0x10, 0xd2, 0xc7, + 0x40, 0x22, 0x01, 0x2f, 0x55, 0x24, 0xc0, 0x3f, 0x9e, 0x09, 0xaf, 0xea, + 0x18, 0xda, 0x95, 0xc0, 0x2c, 0x70, 0x90, 0xda, 0xd6, 0x0f, 0x6f, 0xf8, + 0x54, 0x24, 0x95, 0x3a, 0x4a, 0x24, 0x80, 0x71, 0x55, 0x24, 0xc0, 0x3f, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x01, 0x04, 0x1c, 0x1d, 0x50, 0x20, + 0x4a, 0x24, 0x00, 0x79, 0x56, 0x22, 0x01, 0x2f, 0x95, 0xc0, 0xa8, 0x20, + 0x80, 0x02, 0x04, 0x11, 0x03, 0x04, 0x40, 0x80, 0x01, 0x33, 0x82, 0x00, + 0x04, 0x18, 0x90, 0x00, 0x56, 0x22, 0x41, 0x2e, 0x55, 0x24, 0x40, 0x3e, + 0x52, 0x09, 0xaf, 0xea, 0x18, 0xda, 0x0d, 0x70, 0x4a, 0x24, 0x00, 0x10, + 0x4a, 0x24, 0xc0, 0x70, 0x14, 0x24, 0x00, 0x13, 0xa8, 0x20, 0x00, 0x05, + 0x33, 0x20, 0x82, 0x0f, 0x13, 0x00, 0x74, 0x6c, 0x00, 0x24, 0x81, 0x3f, + 0x00, 0x00, 0x14, 0x01, 0x03, 0x49, 0x40, 0x24, 0x09, 0x33, 0x48, 0x32, + 0x82, 0x00, 0x15, 0x21, 0x01, 0x10, 0x04, 0x71, 0x60, 0xa1, 0x49, 0xa1, + 0x85, 0x71, 0xd1, 0x0c, 0xd4, 0x90, 0x2c, 0x70, 0x4a, 0x24, 0x80, 0x71, + 0x15, 0x22, 0x0c, 0x22, 0x55, 0x24, 0x42, 0x3e, 0x21, 0x43, 0x0c, 0x70, + 0x9c, 0x1c, 0x58, 0x13, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x06, 0x04, + 0x0c, 0x13, 0x0b, 0x04, 0x00, 0x33, 0x8b, 0x11, 0x01, 0x30, 0xc0, 0x02, + 0x05, 0x71, 0x25, 0x74, 0xd5, 0x08, 0xf4, 0x90, 0x9c, 0x1c, 0x18, 0x10, + 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0x40, 0x04, 0x15, 0x22, 0x40, 0x20, + 0xf0, 0x20, 0x43, 0x20, 0x9c, 0x10, 0x00, 0x06, 0x00, 0x24, 0x82, 0x3f, + 0x00, 0x00, 0x5c, 0x01, 0x35, 0x7a, 0x02, 0x33, 0x00, 0x00, 0x24, 0x71, + 0x00, 0xa2, 0x23, 0x0b, 0x10, 0x21, 0x00, 0x24, 0x80, 0x3f, 0x00, 0x00, + 0x5c, 0x01, 0xe2, 0x0d, 0x8f, 0xff, 0x2c, 0x86, 0x04, 0x30, 0x40, 0x80, + 0xc5, 0xf6, 0x00, 0x8f, 0x65, 0x08, 0xb1, 0x00, 0x6c, 0x71, 0x40, 0x86, + 0x21, 0x86, 0x02, 0x86, 0x6c, 0x70, 0x40, 0xc2, 0x41, 0xc1, 0x42, 0xc0, + 0x00, 0x19, 0xc2, 0x20, 0x55, 0x24, 0x41, 0x3e, 0x95, 0xc2, 0x83, 0xc3, + 0x00, 0x24, 0x84, 0x3f, 0x00, 0x00, 0x5c, 0x01, 0x40, 0x24, 0x05, 0x30, + 0x12, 0x09, 0xef, 0xff, 0x42, 0x40, 0x00, 0x1c, 0x43, 0x20, 0xd2, 0xc7, + 0x1a, 0xf4, 0x48, 0x32, 0x01, 0x00, 0x00, 0x30, 0x43, 0x00, 0x01, 0x31, + 0x40, 0x00, 0x9f, 0x16, 0x01, 0x16, 0x02, 0x33, 0x0c, 0x00, 0x04, 0x31, + 0x00, 0x83, 0xd6, 0xf6, 0x01, 0x33, 0x00, 0x00, 0x04, 0x31, 0x00, 0x80, + 0x50, 0xf7, 0x01, 0x6a, 0x09, 0xaf, 0x12, 0xf1, 0x43, 0x86, 0x24, 0x86, + 0x05, 0x86, 0xd3, 0xf1, 0x17, 0x09, 0x85, 0x00, 0x04, 0x30, 0x80, 0x8f, + 0x80, 0x3f, 0x00, 0x00, 0x0c, 0x06, 0xc6, 0xff, 0x9f, 0x1e, 0x58, 0x13, + 0xa9, 0xaf, 0xd2, 0xc7, 0xc9, 0x01, 0x80, 0x01, 0xe8, 0xc3, 0xa6, 0xc1, + 0x10, 0x40, 0x8a, 0x20, 0x07, 0x05, 0x02, 0x70, 0x02, 0x0a, 0xaf, 0xf8, + 0x0a, 0x26, 0x40, 0x10, 0x04, 0x30, 0x80, 0x8f, 0x7a, 0x44, 0x00, 0x00, + 0x88, 0x00, 0x26, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x83, 0xc5, 0x83, 0xc0, + 0xa8, 0x20, 0x80, 0x02, 0x04, 0x16, 0x01, 0x14, 0x00, 0x31, 0x81, 0x0f, + 0xcc, 0x3d, 0xcd, 0xcc, 0x04, 0x18, 0x50, 0x00, 0x4a, 0x24, 0xc0, 0x70, + 0x6d, 0x70, 0x0c, 0x70, 0xa8, 0x20, 0x80, 0x03, 0x15, 0x20, 0x01, 0x20, + 0x04, 0x4d, 0x75, 0x11, 0x03, 0x06, 0x80, 0xc2, 0x15, 0x7a, 0x02, 0x34, + 0xc1, 0x10, 0x04, 0x71, 0x00, 0x1a, 0x40, 0x00, 0x00, 0xc5, 0x01, 0xc4, + 0x02, 0xc3, 0x03, 0xc2, 0x04, 0xc1, 0x05, 0xc0, 0x4a, 0x24, 0x00, 0x71, + 0x72, 0x18, 0x58, 0x23, 0x73, 0x18, 0x18, 0x23, 0x74, 0x18, 0xd8, 0x20, + 0x9c, 0x18, 0x98, 0x20, 0x9d, 0x18, 0x58, 0x20, 0x9e, 0x18, 0x18, 0x20, + 0x80, 0x20, 0x0c, 0x21, 0xa8, 0x20, 0xc0, 0x02, 0x33, 0x23, 0x80, 0x1f, + 0x13, 0x00, 0x60, 0x6c, 0x65, 0x71, 0x48, 0x30, 0x80, 0x00, 0x04, 0x18, + 0x10, 0x20, 0xc8, 0xc7, 0x8a, 0x0a, 0xa0, 0x01, 0x02, 0x40, 0xc8, 0xc7, + 0xf4, 0xc3, 0x82, 0x24, 0x0f, 0x35, 0x50, 0x43, 0x10, 0x42, 0x55, 0x24, + 0x40, 0x3d, 0x8a, 0x22, 0x0c, 0x00, 0x56, 0x0f, 0x6f, 0xea, 0x28, 0x45, + 0x46, 0x40, 0x40, 0x24, 0x83, 0x33, 0x40, 0x24, 0x04, 0x35, 0x55, 0x24, + 0x05, 0x3d, 0x40, 0x24, 0x06, 0x34, 0x40, 0x24, 0xc7, 0x33, 0xa1, 0x41, + 0x62, 0x42, 0x62, 0x0b, 0xaf, 0xf1, 0x0e, 0x1c, 0xc3, 0x31, 0x14, 0x14, + 0x11, 0x30, 0x36, 0x70, 0x7d, 0xf4, 0x0f, 0x14, 0x8d, 0x30, 0x8a, 0x24, + 0x0c, 0x21, 0x8a, 0x20, 0x4c, 0x25, 0x8a, 0x27, 0x8c, 0x15, 0x8a, 0x26, + 0x0c, 0x19, 0x56, 0x22, 0x56, 0x2e, 0x56, 0x22, 0x15, 0x2f, 0x2e, 0x70, + 0x2c, 0x70, 0x00, 0x24, 0x94, 0x24, 0x00, 0x20, 0x90, 0x24, 0x42, 0x77, + 0x42, 0x76, 0xcf, 0x09, 0x31, 0x00, 0xaf, 0x78, 0x0e, 0x14, 0x81, 0x30, + 0xc3, 0x09, 0x24, 0x00, 0x04, 0x77, 0xa7, 0x08, 0xd5, 0x01, 0x25, 0x20, + 0x00, 0x00, 0x08, 0xf0, 0x12, 0xf0, 0x1c, 0xf0, 0x2a, 0xf0, 0x36, 0xf0, + 0x3c, 0xf0, 0x43, 0xf0, 0x55, 0x24, 0x40, 0x3d, 0x84, 0xc1, 0x1a, 0x0e, + 0x6f, 0xf9, 0x55, 0x24, 0x82, 0x3b, 0x55, 0x24, 0x81, 0x3b, 0x18, 0xda, + 0xc2, 0x40, 0x25, 0xf0, 0x55, 0x24, 0x40, 0x3d, 0x84, 0xc1, 0xa6, 0x0b, + 0xef, 0xf9, 0x8a, 0xc2, 0x8a, 0xc1, 0x90, 0xda, 0xa2, 0x40, 0x1b, 0xf0, + 0x55, 0x24, 0x40, 0x3d, 0x84, 0xc1, 0x96, 0x0d, 0xef, 0xf5, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x9c, 0x1a, 0x98, 0x20, 0x9d, 0x1a, + 0x58, 0x20, 0x9e, 0x1a, 0x18, 0x20, 0x23, 0xf0, 0x55, 0x24, 0x40, 0x3d, + 0x84, 0xc1, 0xfa, 0x09, 0xef, 0xf8, 0x86, 0xc2, 0x86, 0xc1, 0x10, 0xda, + 0x82, 0x40, 0x76, 0x0e, 0x4f, 0xea, 0x17, 0xf0, 0x55, 0x24, 0x40, 0x3d, + 0xee, 0x0c, 0x6f, 0xf3, 0x84, 0xc1, 0x00, 0x18, 0x02, 0x20, 0x0f, 0xf0, + 0x55, 0x24, 0x40, 0x3d, 0xde, 0x0c, 0x6f, 0xf3, 0x84, 0xc1, 0x00, 0xaf, + 0x07, 0xf0, 0x55, 0x24, 0x40, 0x3d, 0xfe, 0x08, 0xaf, 0xf8, 0x84, 0xc1, + 0x00, 0xae, 0x04, 0xc0, 0x8a, 0x21, 0x3e, 0x06, 0x72, 0x70, 0xca, 0x21, + 0x4d, 0x20, 0x3c, 0x23, 0x01, 0x20, 0x3d, 0x23, 0x00, 0x20, 0x1d, 0x65, + 0x9b, 0xf1, 0x22, 0x40, 0xd4, 0xc7, 0xe0, 0x78, 0xf0, 0xc3, 0xa6, 0xc1, + 0x40, 0x92, 0xc3, 0x43, 0x48, 0x47, 0x00, 0x00, 0x00, 0x20, 0x8d, 0x0f, + 0x00, 0x00, 0xbc, 0x02, 0x48, 0x32, 0x02, 0x00, 0x10, 0x40, 0x07, 0x33, + 0x82, 0x00, 0xbb, 0x15, 0x00, 0x96, 0xcb, 0x46, 0xc8, 0x41, 0x00, 0x00, + 0xd1, 0x41, 0x48, 0x30, 0x80, 0x00, 0xcb, 0x47, 0x83, 0x3a, 0x6f, 0x12, + 0x48, 0x31, 0x0c, 0x00, 0x6d, 0x70, 0x04, 0x32, 0x80, 0x83, 0xca, 0x21, + 0x85, 0x20, 0x00, 0x31, 0x00, 0x20, 0x00, 0x30, 0xc0, 0x03, 0x04, 0x30, + 0xc0, 0x82, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0xba, 0x15, + 0x01, 0x96, 0x48, 0x30, 0xc2, 0x02, 0x07, 0x33, 0x12, 0x03, 0x8a, 0x24, + 0x0c, 0x17, 0x48, 0x31, 0x81, 0x00, 0x00, 0x31, 0x40, 0x20, 0x48, 0x32, + 0x81, 0x00, 0x00, 0x30, 0xc0, 0x03, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x30, + 0xc0, 0x82, 0x3c, 0xa5, 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, + 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, + 0x07, 0x36, 0x8b, 0x74, 0x80, 0x3f, 0x00, 0x00, 0x8b, 0x15, 0x01, 0x96, + 0x48, 0x30, 0xc2, 0x02, 0x6c, 0x70, 0x48, 0x31, 0x80, 0x00, 0x48, 0x32, + 0x82, 0x00, 0x02, 0x74, 0x00, 0x31, 0x00, 0x20, 0x48, 0x32, 0xc2, 0x02, + 0x5b, 0xa5, 0x00, 0x33, 0x00, 0x10, 0x78, 0x1d, 0xc0, 0x12, 0x00, 0x30, + 0xc0, 0x03, 0x04, 0x30, 0xc0, 0x80, 0xc7, 0xf6, 0x01, 0x30, 0x81, 0x0f, + 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x30, 0x81, 0x0f, 0x00, 0xbf, + 0x00, 0x00, 0x8c, 0x15, 0x00, 0x96, 0x48, 0x31, 0xc1, 0x02, 0x48, 0x30, + 0x80, 0x00, 0x34, 0xac, 0x00, 0x31, 0x00, 0x20, 0x00, 0x33, 0x00, 0x10, + 0x00, 0x30, 0xc0, 0x03, 0x04, 0x30, 0xc0, 0x80, 0xc6, 0xf6, 0x01, 0x30, + 0x81, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x81, 0x0f, + 0x00, 0xbf, 0x00, 0x00, 0x90, 0x15, 0x00, 0x96, 0x48, 0x31, 0xc1, 0x02, + 0x4c, 0x70, 0x48, 0x30, 0x80, 0x00, 0x35, 0xac, 0x00, 0x32, 0x00, 0x20, + 0x00, 0x30, 0xc0, 0x03, 0x04, 0x30, 0x80, 0x80, 0xc6, 0xf6, 0x01, 0x30, + 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0xbf, 0x00, 0x00, 0x08, 0x15, 0x01, 0x90, 0x48, 0x30, 0xc3, 0x02, + 0x57, 0xa5, 0x48, 0x31, 0x81, 0x00, 0x40, 0xb4, 0x00, 0x31, 0x40, 0x20, + 0x42, 0xac, 0x48, 0x33, 0x81, 0x00, 0x00, 0x30, 0xc0, 0x03, 0x48, 0x31, + 0xc1, 0x02, 0x04, 0x30, 0x80, 0x80, 0x3f, 0xa5, 0xc6, 0xf6, 0x01, 0x30, + 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc1, 0x02, 0x4c, 0x70, 0x48, 0x31, + 0x81, 0x00, 0x00, 0x31, 0x80, 0x2f, 0xcc, 0x3e, 0xcd, 0xcc, 0x55, 0x20, + 0x8f, 0x2e, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x30, 0x80, 0x80, 0x39, 0xa5, + 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc1, 0x02, + 0x8a, 0x20, 0x09, 0x0f, 0x02, 0x70, 0x22, 0x0c, 0x2f, 0xf1, 0x20, 0x1c, + 0x42, 0x10, 0x8a, 0x20, 0x0b, 0x05, 0x02, 0x70, 0x2c, 0x70, 0x29, 0xda, + 0x92, 0x0a, 0x6f, 0xf8, 0xc0, 0x18, 0x19, 0x20, 0x40, 0x20, 0x00, 0x22, + 0xe0, 0xda, 0x42, 0x0c, 0x6f, 0xea, 0xe1, 0x41, 0x8a, 0x21, 0x04, 0x07, + 0x02, 0x71, 0x80, 0xc0, 0x18, 0xda, 0x32, 0x0c, 0x6f, 0xea, 0x40, 0x24, + 0x14, 0x30, 0x4a, 0x24, 0x80, 0x71, 0x40, 0x20, 0x13, 0x2f, 0xcb, 0x47, + 0xc8, 0x42, 0x00, 0x00, 0xa8, 0x20, 0x80, 0x03, 0x04, 0x14, 0x00, 0x24, + 0x00, 0x30, 0x80, 0x03, 0x07, 0x30, 0x40, 0x04, 0x00, 0x30, 0xc0, 0x03, + 0x07, 0x30, 0x80, 0x04, 0x04, 0x1b, 0x10, 0x20, 0x8a, 0x21, 0x04, 0x0d, + 0x02, 0x71, 0x80, 0xc0, 0x18, 0xda, 0xf6, 0x0b, 0x6f, 0xea, 0x40, 0x24, + 0x14, 0x30, 0x4a, 0x24, 0x80, 0x71, 0xa8, 0x20, 0xc0, 0x03, 0x04, 0x14, + 0x00, 0x24, 0x00, 0x30, 0x80, 0x03, 0x07, 0x30, 0x40, 0x04, 0x00, 0x30, + 0xc0, 0x03, 0x07, 0x30, 0x80, 0x04, 0x04, 0x1b, 0x10, 0x20, 0x8a, 0x21, + 0x05, 0x03, 0x02, 0x71, 0x80, 0xc0, 0x18, 0xda, 0xc2, 0x0b, 0x6f, 0xea, + 0x40, 0x24, 0x14, 0x30, 0x4a, 0x24, 0x80, 0x71, 0xa8, 0x20, 0x80, 0x03, + 0x04, 0x14, 0x00, 0x24, 0x00, 0x30, 0x80, 0x03, 0x07, 0x30, 0x40, 0x04, + 0x00, 0x30, 0xc0, 0x03, 0x07, 0x30, 0x80, 0x04, 0x04, 0x1b, 0x10, 0x20, + 0xb6, 0x15, 0x00, 0x96, 0xc3, 0x41, 0x48, 0x41, 0x00, 0x00, 0x04, 0x31, + 0x40, 0xa0, 0x00, 0x30, 0x80, 0x03, 0xca, 0x21, 0x45, 0x20, 0x07, 0x30, + 0x40, 0x04, 0x04, 0x18, 0x43, 0x20, 0x7e, 0x1d, 0x18, 0x90, 0xd0, 0xc7, + 0xe6, 0xc2, 0x42, 0x81, 0x08, 0x45, 0x05, 0x80, 0x00, 0x32, 0x82, 0x0f, + 0xcc, 0x3d, 0xd0, 0xcc, 0xcb, 0x47, 0x0e, 0x42, 0xa1, 0xc2, 0x00, 0x30, + 0x80, 0x0f, 0x66, 0x3f, 0x66, 0x66, 0x6d, 0x70, 0x01, 0x30, 0x88, 0x00, + 0x61, 0x46, 0x14, 0x1d, 0x00, 0x12, 0x03, 0x85, 0x41, 0x81, 0x64, 0x85, + 0x82, 0x81, 0x02, 0x32, 0x0e, 0x00, 0x42, 0x85, 0x00, 0x81, 0xbf, 0xbe, + 0x69, 0x41, 0x02, 0xa5, 0x02, 0x30, 0x80, 0x00, 0x02, 0x34, 0xc2, 0x10, + 0x50, 0x20, 0xc3, 0x07, 0x01, 0x81, 0x01, 0x33, 0x83, 0x03, 0xbf, 0xba, + 0x03, 0xa5, 0x02, 0x81, 0x01, 0x33, 0x82, 0x00, 0xcb, 0x46, 0x4b, 0x43, + 0x78, 0xf1, 0x04, 0xa5, 0x04, 0x32, 0xc0, 0x83, 0x4f, 0x27, 0x00, 0x16, + 0xe4, 0x8d, 0x61, 0x81, 0x80, 0x81, 0xca, 0x26, 0x69, 0x00, 0x04, 0x32, + 0x00, 0x80, 0xca, 0x21, 0x69, 0x10, 0xf5, 0x70, 0xca, 0x21, 0x81, 0x11, + 0x50, 0x23, 0xc6, 0x07, 0x50, 0x24, 0xc7, 0x17, 0x02, 0x37, 0x80, 0x01, + 0xbf, 0xb8, 0x04, 0x30, 0x80, 0x83, 0x0c, 0x74, 0x93, 0xf7, 0x42, 0x81, + 0x04, 0x32, 0xc0, 0x82, 0x8f, 0xf7, 0x04, 0x37, 0x80, 0x81, 0xc8, 0xf6, + 0x04, 0x34, 0xc0, 0x92, 0x0c, 0x72, 0xca, 0x20, 0xeb, 0x00, 0x07, 0xf0, + 0x04, 0x33, 0xc0, 0x82, 0x0c, 0x70, 0xca, 0x20, 0x6b, 0x00, 0x07, 0x30, + 0x83, 0x1f, 0x7a, 0x44, 0x00, 0x00, 0x7f, 0xda, 0x17, 0xba, 0x04, 0x33, + 0x80, 0x80, 0x07, 0xf6, 0x04, 0x33, 0xc0, 0x82, 0x60, 0x42, 0x43, 0xf7, + 0x4c, 0x70, 0xc2, 0xb8, 0x6a, 0x68, 0x2f, 0x0b, 0xb5, 0x00, 0x8d, 0x70, + 0x04, 0x32, 0x80, 0x8f, 0xa3, 0x3c, 0x0a, 0xd7, 0x0c, 0x70, 0xca, 0x20, + 0x69, 0x00, 0x04, 0x32, 0x80, 0x8f, 0x7a, 0x3f, 0x48, 0xe1, 0x6f, 0x23, + 0x0b, 0x10, 0x6c, 0x71, 0x04, 0x23, 0x0b, 0x10, 0x04, 0x36, 0x80, 0x83, + 0x17, 0xf0, 0x8d, 0x70, 0x6c, 0x70, 0x99, 0xe8, 0x04, 0x32, 0x80, 0x8f, + 0xa3, 0x3c, 0x0a, 0xd7, 0x0c, 0x70, 0xca, 0x20, 0x69, 0x00, 0x04, 0x32, + 0x80, 0x8f, 0x7a, 0x3f, 0x48, 0xe1, 0x6f, 0x23, 0x0b, 0x10, 0x6c, 0x70, + 0x8d, 0x71, 0x04, 0x23, 0x0b, 0x10, 0x04, 0x37, 0x80, 0x83, 0x6f, 0x20, + 0x0b, 0x00, 0x04, 0x23, 0x0b, 0x10, 0x2f, 0x0f, 0x70, 0x10, 0xcd, 0x70, + 0xa7, 0x0f, 0x11, 0x10, 0x41, 0x09, 0x10, 0x10, 0x09, 0x0b, 0x10, 0x10, + 0x1c, 0x8d, 0x1c, 0xe8, 0x19, 0x8d, 0x04, 0x71, 0x0d, 0x79, 0x93, 0x09, + 0x72, 0x02, 0x19, 0xad, 0x1b, 0x1d, 0x43, 0x10, 0x19, 0x1d, 0x03, 0x12, + 0x41, 0xf0, 0x18, 0x8d, 0x04, 0x71, 0x0f, 0x7a, 0x39, 0x0a, 0xf4, 0x02, + 0x18, 0xad, 0x1a, 0x8d, 0x3d, 0x08, 0xf4, 0x02, 0xa1, 0x40, 0x66, 0x0a, + 0x0f, 0xf0, 0x1c, 0x1d, 0x43, 0x10, 0x33, 0xf0, 0x19, 0x8d, 0x04, 0x77, + 0x2f, 0x26, 0x05, 0xf0, 0x5a, 0x00, 0x23, 0x00, 0x19, 0xad, 0x1b, 0x8d, + 0xd9, 0xad, 0x29, 0xe8, 0x4f, 0x0b, 0x30, 0x10, 0xdb, 0xad, 0x04, 0x1d, + 0x43, 0x10, 0x23, 0xf0, 0x43, 0x09, 0x10, 0x10, 0x1a, 0x8d, 0x04, 0x71, + 0x1a, 0xad, 0x1d, 0xf0, 0x31, 0x0b, 0x10, 0x10, 0x06, 0xec, 0x2a, 0x0a, + 0x2f, 0xf0, 0xa1, 0x40, 0x81, 0xde, 0x15, 0xf0, 0x10, 0xeb, 0xc2, 0x81, + 0x1a, 0x0a, 0x2f, 0xf0, 0xa1, 0x40, 0x50, 0x26, 0xc0, 0x17, 0x8a, 0x26, + 0x7e, 0x10, 0x04, 0x30, 0x80, 0x8f, 0x0c, 0x44, 0x02, 0x36, 0xca, 0x26, + 0x26, 0x10, 0x05, 0xf0, 0xfe, 0x09, 0x2f, 0xf0, 0xa1, 0x40, 0xcf, 0x78, + 0xc6, 0xc6, 0xe0, 0x78, 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x34, 0x50, 0x40, + 0x08, 0x45, 0x84, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0x28, 0x47, 0x76, 0x09, + 0x6f, 0xea, 0x84, 0xc6, 0x00, 0x85, 0x40, 0x24, 0x83, 0x31, 0x40, 0x24, + 0x04, 0x32, 0x40, 0x24, 0x05, 0x33, 0x40, 0x24, 0x06, 0x30, 0x40, 0x24, + 0xc7, 0x31, 0xe1, 0x41, 0x02, 0x42, 0x82, 0x0d, 0x6f, 0xf1, 0x06, 0x1c, + 0x83, 0x30, 0x02, 0xc0, 0xa2, 0xe8, 0x07, 0x14, 0x8f, 0x30, 0x0e, 0x71, + 0x06, 0x14, 0x81, 0x30, 0xef, 0x78, 0x35, 0x09, 0x24, 0x00, 0x2f, 0x26, + 0x07, 0xf4, 0x1f, 0x08, 0xb0, 0x00, 0x80, 0xc1, 0x21, 0x08, 0x51, 0x00, + 0x00, 0xc0, 0x09, 0x66, 0x04, 0x71, 0x40, 0xc0, 0xfe, 0x0a, 0x20, 0x00, + 0xa1, 0x40, 0x10, 0x40, 0x06, 0xf0, 0x9e, 0x0f, 0x2f, 0xf3, 0x84, 0xc0, + 0x39, 0x1d, 0x02, 0x10, 0xe5, 0x71, 0xe6, 0xf1, 0x0c, 0x70, 0x03, 0xf2, + 0xc8, 0xc7, 0x8a, 0x20, 0x7e, 0x06, 0xc8, 0xc7, 0xe2, 0xc2, 0x84, 0x88, + 0x06, 0xec, 0x00, 0x1f, 0x03, 0x00, 0x04, 0x18, 0x03, 0x00, 0x04, 0xf0, + 0x00, 0x1f, 0x43, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x20, 0x0c, 0x02, + 0x0a, 0x25, 0x80, 0x11, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x14, 0x0b, 0x14, + 0x04, 0x1d, 0xd0, 0x12, 0x3a, 0x10, 0x8c, 0x00, 0x6d, 0x70, 0x48, 0x34, + 0x0c, 0x10, 0x80, 0xa5, 0x83, 0x83, 0x04, 0x34, 0xc0, 0x92, 0xc7, 0xf6, + 0x01, 0x34, 0x8c, 0x1f, 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x34, + 0x8c, 0x1f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x34, 0xcd, 0x12, 0xaf, 0x7c, + 0x8c, 0x24, 0xc3, 0x9f, 0x1c, 0xf2, 0x39, 0x10, 0x8b, 0x00, 0x21, 0x0c, + 0xe4, 0x12, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x20, 0x0b, 0x02, 0x68, 0x44, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x14, 0x08, 0x14, 0x04, 0x1b, 0x10, 0x12, + 0x3a, 0x18, 0x42, 0x03, 0x4a, 0x24, 0x00, 0x71, 0x00, 0x1f, 0x03, 0x00, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x13, 0x0c, 0x04, 0x04, 0x1e, 0x10, 0x03, + 0x80, 0x43, 0xda, 0x0a, 0x20, 0x00, 0x0a, 0x24, 0x40, 0x01, 0xc2, 0xc6, + 0xe6, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, 0x60, 0x44, 0x40, 0x24, + 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x47, + 0x28, 0x45, 0xce, 0x0c, 0x6f, 0xf1, 0x03, 0x1c, 0x83, 0x30, 0x02, 0x14, + 0x80, 0x30, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0x2d, 0x09, 0x04, 0x00, + 0x0f, 0x08, 0x90, 0x00, 0x19, 0x08, 0x51, 0x00, 0x38, 0x16, 0x80, 0x10, + 0x03, 0xf0, 0x39, 0x16, 0x80, 0x10, 0x81, 0xc3, 0xa1, 0x41, 0xaa, 0x0e, + 0x2f, 0xf3, 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, + 0x02, 0x30, 0xe9, 0xf1, 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, + 0x21, 0xad, 0xc6, 0xc7, 0xee, 0xc3, 0xa2, 0xc1, 0x50, 0x41, 0x28, 0x45, + 0x10, 0x40, 0x2c, 0x70, 0x10, 0xda, 0x60, 0x40, 0x0a, 0x23, 0x00, 0x21, + 0x2a, 0x0e, 0x2f, 0xf8, 0x68, 0x46, 0x4a, 0x27, 0x40, 0x10, 0x4a, 0x24, + 0xc0, 0x70, 0x02, 0x1c, 0x03, 0x35, 0x01, 0x1c, 0x83, 0x30, 0x60, 0xc7, + 0x15, 0xed, 0x40, 0x24, 0x40, 0x31, 0x80, 0xc1, 0xa8, 0x20, 0x00, 0x02, + 0x01, 0x11, 0x82, 0x04, 0x38, 0x22, 0x42, 0x04, 0x01, 0x18, 0x92, 0x00, + 0x5e, 0x0e, 0xef, 0xf4, 0x40, 0x24, 0x40, 0x31, 0xe1, 0x08, 0x30, 0x00, + 0xad, 0x70, 0xad, 0x72, 0x69, 0xf0, 0x0c, 0x70, 0xa8, 0x20, 0xc0, 0x02, + 0x80, 0xc1, 0x09, 0x61, 0x40, 0x24, 0x42, 0x31, 0x1a, 0x62, 0x04, 0x71, + 0x38, 0x21, 0x41, 0x04, 0x20, 0xaa, 0x36, 0x0e, 0xef, 0xf4, 0x40, 0x24, + 0x40, 0x31, 0x4e, 0x70, 0xad, 0x70, 0x06, 0xe8, 0xad, 0x72, 0x01, 0x1e, + 0x83, 0x10, 0xe0, 0xae, 0x06, 0x40, 0x39, 0x08, 0x91, 0x01, 0x0c, 0x70, + 0xf0, 0x26, 0x01, 0x70, 0x13, 0x00, 0xe4, 0x6c, 0x40, 0x24, 0xc2, 0x30, + 0x14, 0x71, 0x1a, 0x62, 0x0c, 0x71, 0x38, 0x21, 0x41, 0x04, 0x20, 0xaa, + 0xf4, 0xf5, 0x9e, 0x0e, 0xaf, 0xf5, 0x40, 0x24, 0xc0, 0x30, 0x07, 0xe8, + 0xb8, 0x66, 0xa5, 0x72, 0x01, 0x18, 0x83, 0x00, 0xe0, 0xa8, 0x06, 0x40, + 0x37, 0x08, 0xf1, 0x01, 0x4a, 0x20, 0x00, 0x00, 0xf0, 0x26, 0x01, 0x70, + 0x13, 0x00, 0xec, 0x6c, 0x40, 0x24, 0xc2, 0x30, 0x14, 0x71, 0x1a, 0x62, + 0x0c, 0x71, 0x38, 0x21, 0x41, 0x04, 0x20, 0xaa, 0xf4, 0xf5, 0x66, 0x0e, + 0xaf, 0xf5, 0x40, 0x24, 0xc0, 0x30, 0x07, 0xe8, 0xb8, 0x66, 0xa5, 0x72, + 0x01, 0x18, 0x83, 0x00, 0xe0, 0xa8, 0x06, 0x40, 0x50, 0x20, 0x00, 0x00, + 0x63, 0x08, 0x11, 0x02, 0xf0, 0x26, 0x81, 0x74, 0x13, 0x00, 0xf4, 0x6c, + 0x40, 0x24, 0xc0, 0x30, 0x56, 0x71, 0x00, 0x20, 0x82, 0x04, 0x4e, 0x71, + 0x38, 0x21, 0x40, 0x04, 0x00, 0xaa, 0xf4, 0xf5, 0x2a, 0x0e, 0xaf, 0xf5, + 0x40, 0x24, 0xc0, 0x30, 0x1d, 0xe8, 0xbe, 0x66, 0xa5, 0x72, 0x01, 0x1e, + 0x83, 0x10, 0x18, 0xf0, 0x11, 0x09, 0x71, 0x25, 0x06, 0x40, 0x0d, 0x08, + 0x91, 0x01, 0xe0, 0xae, 0x06, 0x40, 0xad, 0x71, 0x11, 0x09, 0xd1, 0x25, + 0x0d, 0x08, 0x51, 0x02, 0xb8, 0x66, 0xe0, 0xa8, 0xa5, 0x71, 0x06, 0x40, + 0x0f, 0x09, 0x91, 0x25, 0x0b, 0x08, 0xf1, 0x01, 0xbe, 0x66, 0xa5, 0x71, + 0xe0, 0xae, 0x00, 0x1b, 0x40, 0x23, 0xce, 0xc7, 0xe6, 0xc3, 0xa2, 0xc1, + 0x08, 0x46, 0x08, 0x16, 0x00, 0x14, 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, + 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, + 0x06, 0x0b, 0x6f, 0xf1, 0x03, 0x1c, 0x83, 0x30, 0x02, 0x14, 0x80, 0x30, + 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0x37, 0x09, 0x04, 0x00, 0x1b, 0x08, + 0xb0, 0x00, 0x81, 0xc3, 0x1f, 0x08, 0x71, 0x00, 0x81, 0xc3, 0xc1, 0x40, + 0xa1, 0x41, 0x6a, 0x0d, 0xaf, 0xf5, 0xe1, 0x42, 0x07, 0xf0, 0x32, 0x16, + 0x80, 0x10, 0xa1, 0x41, 0xda, 0x0c, 0x2f, 0xf3, 0xe1, 0x42, 0x02, 0x14, + 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xe4, 0xf1, 0x01, 0xc0, + 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xc6, 0xc7, 0xe0, 0x78, + 0x99, 0x04, 0x40, 0x01, 0x00, 0x42, 0x9f, 0xe1, 0x0c, 0x70, 0xe0, 0x20, + 0xcd, 0x07, 0x0c, 0x71, 0xe0, 0x7f, 0x38, 0x1a, 0x42, 0x00, 0xe0, 0x78, + 0xe6, 0xc3, 0x82, 0x24, 0x0c, 0x37, 0x48, 0x47, 0x08, 0x45, 0x87, 0xc0, + 0x8a, 0x22, 0x0c, 0x00, 0x02, 0x0e, 0x2f, 0xea, 0x28, 0x46, 0x00, 0x85, + 0x40, 0x24, 0x83, 0x34, 0x40, 0x24, 0x04, 0x33, 0x40, 0x24, 0x05, 0x36, + 0x40, 0x24, 0x06, 0x35, 0x40, 0x24, 0xc7, 0x34, 0xc1, 0x41, 0xe1, 0x42, + 0x0e, 0x0a, 0x6f, 0xf1, 0x12, 0x1c, 0x83, 0x30, 0x03, 0xc0, 0x03, 0xe8, + 0xc6, 0xc7, 0x13, 0x14, 0x8e, 0x30, 0x12, 0x14, 0x81, 0x30, 0xcf, 0x78, + 0x35, 0x09, 0x04, 0x00, 0x23, 0x08, 0xb0, 0x00, 0x85, 0xc1, 0x29, 0x08, + 0x71, 0x00, 0x87, 0xc0, 0x85, 0xc1, 0xae, 0x0c, 0xaf, 0xf5, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x42, 0xa5, 0x23, 0xa5, 0x04, 0xa5, + 0x06, 0xf0, 0x2a, 0x0c, 0x2f, 0xf3, 0x87, 0xc0, 0x3a, 0x1d, 0x02, 0x10, + 0xc5, 0x71, 0xe5, 0xf1, 0x03, 0xc0, 0xc6, 0xc7, 0xee, 0xc3, 0xaa, 0xc1, + 0x38, 0x10, 0x8c, 0x00, 0x08, 0x45, 0x88, 0x47, 0x68, 0x46, 0x50, 0x41, + 0x41, 0x0c, 0x3f, 0x10, 0x30, 0x40, 0x4a, 0x24, 0xc0, 0x70, 0x02, 0x40, + 0x0a, 0x21, 0xc0, 0x03, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x02, 0x04, + 0x04, 0x19, 0x90, 0x00, 0x3a, 0x15, 0x80, 0x10, 0x4a, 0x24, 0xc0, 0x70, + 0x48, 0x30, 0x02, 0x00, 0xc1, 0x40, 0x40, 0xa1, 0x0a, 0x21, 0x40, 0x04, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x03, 0x04, 0x04, 0x18, 0xd0, 0x00, + 0x40, 0xa0, 0x68, 0xf0, 0x42, 0x85, 0x23, 0x85, 0x04, 0x85, 0x3a, 0x15, + 0x92, 0x10, 0x43, 0xc2, 0x44, 0xc1, 0x1b, 0x0c, 0xff, 0x10, 0x45, 0xc0, + 0x03, 0xc2, 0x04, 0xc1, 0x05, 0xc0, 0x0a, 0x23, 0x80, 0x24, 0x40, 0xc2, + 0x41, 0xc1, 0x42, 0xc0, 0x13, 0xf0, 0x4f, 0x85, 0x30, 0x85, 0x11, 0x85, + 0x48, 0x15, 0x93, 0x10, 0x40, 0xc2, 0x41, 0xc1, 0x17, 0x0c, 0x3e, 0x11, + 0x42, 0xc0, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x0a, 0x22, 0xc0, 0x24, + 0x43, 0xc2, 0x44, 0xc1, 0x45, 0xc0, 0x4a, 0x24, 0x00, 0x71, 0x22, 0x41, + 0x0a, 0x20, 0x80, 0x03, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x02, 0x04, + 0x04, 0x18, 0x90, 0x00, 0x80, 0xc2, 0x2c, 0x73, 0x22, 0x40, 0x06, 0x0c, + 0x2f, 0xf2, 0xc1, 0x43, 0x60, 0x86, 0x41, 0x86, 0x48, 0x33, 0x00, 0x20, + 0x22, 0x86, 0x4a, 0x24, 0x00, 0x71, 0x49, 0xc0, 0x46, 0xc3, 0x4a, 0x20, + 0x00, 0x00, 0x86, 0xc3, 0x47, 0xc2, 0x48, 0xc1, 0xa8, 0x20, 0x00, 0x03, + 0x01, 0x4b, 0x15, 0x26, 0x02, 0x10, 0x20, 0xa2, 0xf0, 0x20, 0x01, 0x20, + 0x15, 0x27, 0x02, 0x10, 0x04, 0x71, 0x20, 0xa2, 0x83, 0xc2, 0x2c, 0x73, + 0x02, 0x40, 0xc6, 0x0b, 0x2f, 0xf2, 0xe1, 0x43, 0x41, 0x87, 0x22, 0x87, + 0x60, 0x87, 0x48, 0x32, 0x00, 0x20, 0x47, 0xc2, 0x49, 0xc0, 0x48, 0xc1, + 0x86, 0xc1, 0x10, 0xda, 0xe1, 0x40, 0x82, 0x0c, 0x2f, 0xea, 0x46, 0xc3, + 0x38, 0x15, 0x8c, 0x10, 0x27, 0x0c, 0x7f, 0x10, 0x2c, 0x74, 0x21, 0x0c, + 0xbe, 0x10, 0x14, 0xe5, 0x2c, 0x74, 0x02, 0x40, 0xe1, 0x43, 0x56, 0x0d, + 0x6f, 0xf3, 0xa1, 0x42, 0x2c, 0x74, 0x22, 0x40, 0xa1, 0x42, 0x4a, 0x0d, + 0x6f, 0xf3, 0xc1, 0x43, 0xce, 0xc7, 0x14, 0xe5, 0x02, 0x40, 0xe1, 0x43, + 0xa2, 0x0b, 0x2f, 0xf2, 0xa1, 0x42, 0x2c, 0x74, 0x22, 0x40, 0xa1, 0x42, + 0x96, 0x0b, 0x2f, 0xf2, 0xc1, 0x43, 0xce, 0xc7, 0x4a, 0x24, 0xc0, 0x70, + 0x40, 0x20, 0x01, 0x0f, 0x40, 0x20, 0x02, 0x02, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x12, 0x03, 0x04, 0x04, 0x19, 0xd0, 0x00, 0x3a, 0x10, 0x81, 0x00, + 0x04, 0x18, 0x43, 0x00, 0xe0, 0x7f, 0x48, 0x18, 0x42, 0x00, 0xe0, 0x78, + 0xec, 0xc3, 0xa9, 0xc1, 0x30, 0x40, 0x86, 0xc1, 0x48, 0x47, 0xde, 0x08, + 0x6f, 0xf8, 0x08, 0x45, 0x02, 0x08, 0x2f, 0xf9, 0x86, 0xc0, 0xd3, 0x41, + 0xdb, 0x2e, 0xff, 0xe6, 0x04, 0x30, 0x40, 0x84, 0xcd, 0x70, 0xd7, 0xf6, + 0x46, 0x0f, 0x8f, 0xf6, 0x35, 0x08, 0x13, 0x22, 0x53, 0x08, 0x50, 0x20, + 0x65, 0x08, 0x90, 0x20, 0xa5, 0x08, 0x11, 0x21, 0x20, 0x85, 0x62, 0x85, + 0x41, 0x85, 0x52, 0x21, 0xc1, 0x07, 0x41, 0xc6, 0x40, 0xc3, 0x00, 0x30, + 0x8e, 0x00, 0x42, 0xc1, 0x46, 0xf0, 0x40, 0x85, 0x21, 0x85, 0x02, 0x85, + 0x40, 0xc2, 0x41, 0xc1, 0x42, 0xc0, 0x40, 0xf0, 0x4f, 0x08, 0x10, 0x22, + 0x61, 0x08, 0x10, 0x28, 0x75, 0x08, 0x11, 0x24, 0x21, 0x85, 0x60, 0x85, + 0x42, 0x85, 0x52, 0x21, 0xc1, 0x07, 0x42, 0xc6, 0x41, 0xc3, 0x00, 0x30, + 0x8e, 0x00, 0x40, 0xc1, 0x2e, 0xf0, 0x22, 0x85, 0x61, 0x85, 0x40, 0x85, + 0x52, 0x21, 0xc1, 0x07, 0x40, 0xc6, 0x42, 0xc3, 0x00, 0x30, 0x8e, 0x00, + 0x41, 0xc1, 0x24, 0xf0, 0x40, 0x85, 0x21, 0x85, 0x62, 0x85, 0x00, 0x30, + 0x80, 0x00, 0x52, 0x21, 0xc1, 0x07, 0x40, 0xc6, 0x41, 0xc3, 0x42, 0xc1, + 0x16, 0xf0, 0x41, 0x85, 0x22, 0x85, 0x60, 0x85, 0x00, 0x30, 0x80, 0x00, + 0x52, 0x21, 0xc1, 0x07, 0x41, 0xc6, 0x42, 0xc3, 0x40, 0xc1, 0x0c, 0xf0, + 0x42, 0x85, 0x20, 0x85, 0x61, 0x85, 0x00, 0x30, 0x80, 0x00, 0x52, 0x21, + 0xc1, 0x07, 0x42, 0xc6, 0x40, 0xc3, 0x41, 0xc1, 0x52, 0x20, 0xce, 0x07, + 0x80, 0xc0, 0x83, 0xc1, 0x0a, 0x08, 0x6f, 0xf8, 0x40, 0x24, 0x12, 0x30, + 0xd3, 0x40, 0x80, 0x3f, 0x00, 0x00, 0x01, 0x36, 0x01, 0x14, 0x50, 0x20, + 0xc0, 0x25, 0x00, 0x31, 0x00, 0x00, 0x2f, 0x35, 0x00, 0x10, 0x1a, 0x0f, + 0xef, 0xf8, 0x83, 0xc0, 0x04, 0x30, 0x40, 0x84, 0xd9, 0xf6, 0x04, 0x36, + 0x00, 0x94, 0xca, 0x26, 0x09, 0x14, 0x01, 0x30, 0x01, 0x00, 0x4a, 0x24, + 0xc0, 0x70, 0x02, 0x30, 0x80, 0x23, 0x07, 0x30, 0x40, 0x00, 0x2f, 0x31, + 0x00, 0x00, 0xa8, 0x20, 0x40, 0x02, 0x04, 0x12, 0x00, 0x24, 0x00, 0x31, + 0x00, 0x00, 0x04, 0x1f, 0x10, 0x10, 0xa0, 0xa7, 0xcc, 0xc7, 0x0c, 0x70, + 0xa3, 0xa7, 0x02, 0xa7, 0x01, 0xa7, 0x00, 0xa7, 0xcc, 0xc7, 0xe0, 0x78, + 0xf4, 0xc3, 0xb5, 0xc1, 0x28, 0x46, 0x10, 0x45, 0x92, 0xc1, 0xc1, 0x40, + 0x0a, 0x24, 0x40, 0x21, 0x0a, 0x23, 0x00, 0x21, 0x68, 0x47, 0x8e, 0x0f, + 0x2f, 0xf8, 0x48, 0x45, 0x50, 0x14, 0x11, 0x30, 0x4c, 0x14, 0x12, 0x30, + 0x48, 0x14, 0x10, 0x30, 0x01, 0x86, 0x01, 0x32, 0x56, 0x24, 0x22, 0x86, + 0x00, 0x30, 0x82, 0x2f, 0x6b, 0x3c, 0xfa, 0xed, 0x52, 0x20, 0xc0, 0x07, + 0x04, 0x36, 0x80, 0xa0, 0x4c, 0xf7, 0x01, 0x31, 0x02, 0x24, 0x6c, 0x70, + 0x2f, 0x32, 0x80, 0x00, 0x04, 0x31, 0xc0, 0x80, 0x40, 0x41, 0x04, 0xf6, + 0x52, 0x22, 0xc1, 0x07, 0x7a, 0x0a, 0x8f, 0xf2, 0x00, 0xa5, 0x00, 0x86, + 0x72, 0x0a, 0xaf, 0xf2, 0x2f, 0x31, 0x80, 0x05, 0x00, 0xa7, 0x00, 0x85, + 0x8d, 0x70, 0x52, 0x20, 0xc0, 0x07, 0x00, 0xa5, 0x02, 0x86, 0x04, 0x30, + 0x00, 0x83, 0x87, 0xf7, 0x00, 0x87, 0x52, 0x20, 0xc0, 0x07, 0x00, 0xa7, + 0x02, 0x86, 0x01, 0x32, 0x01, 0x24, 0x3f, 0xda, 0x18, 0xba, 0x04, 0x31, + 0x80, 0x80, 0xc4, 0x30, 0x05, 0x83, 0x44, 0xf7, 0x61, 0x86, 0x0d, 0xf0, + 0x01, 0x31, 0x01, 0x24, 0x61, 0x86, 0x04, 0x31, 0x80, 0x80, 0xc4, 0x33, + 0x05, 0x83, 0xde, 0x00, 0x26, 0x00, 0x04, 0x33, 0x00, 0x83, 0x20, 0x86, + 0x4a, 0xc0, 0x88, 0xc0, 0x48, 0xc1, 0x84, 0xc2, 0x20, 0xd9, 0x02, 0x0e, + 0xef, 0xff, 0x49, 0xc3, 0x80, 0xc0, 0x84, 0xc1, 0x02, 0x0a, 0x2f, 0xea, + 0x10, 0xda, 0x00, 0xc1, 0x02, 0xc0, 0x01, 0xc3, 0x03, 0xc2, 0x46, 0xc1, + 0x52, 0x20, 0xc1, 0x07, 0x52, 0x23, 0xc0, 0x07, 0x45, 0xc2, 0x44, 0xc1, + 0x47, 0xc0, 0x84, 0xc1, 0x8b, 0xc2, 0xe6, 0x08, 0x20, 0x00, 0xa2, 0x40, + 0x0e, 0xc1, 0xe2, 0x09, 0xaf, 0xf2, 0x0d, 0xc0, 0x00, 0x30, 0x80, 0x0f, + 0x00, 0xc0, 0x00, 0x00, 0x4c, 0x70, 0x04, 0x30, 0x80, 0x80, 0x46, 0xf7, + 0x01, 0x30, 0x80, 0x0f, 0xc9, 0x40, 0xdb, 0x0f, 0x00, 0x1b, 0x00, 0x20, + 0x00, 0x86, 0x22, 0x86, 0x4f, 0xc0, 0x01, 0x86, 0x04, 0x31, 0x80, 0x80, + 0x84, 0xc2, 0x50, 0xc0, 0x8f, 0xc0, 0x51, 0xc1, 0x56, 0xf7, 0x96, 0x0d, + 0xef, 0xff, 0x20, 0xd9, 0x80, 0xc0, 0x84, 0xc1, 0x96, 0x09, 0x2f, 0xea, + 0x10, 0xda, 0x02, 0xc1, 0x01, 0xc0, 0x00, 0xc3, 0x03, 0xc2, 0x45, 0xc1, + 0x52, 0x20, 0xc1, 0x07, 0x52, 0x23, 0xc0, 0x07, 0x44, 0xc2, 0x46, 0xc1, + 0x47, 0xc0, 0x05, 0xf0, 0x6a, 0x0d, 0xef, 0xff, 0x10, 0xd9, 0x84, 0xc1, + 0x8b, 0xc2, 0x72, 0x08, 0x20, 0x00, 0xa2, 0x40, 0x0e, 0xc1, 0x6e, 0x09, + 0xaf, 0xf2, 0x0d, 0xc0, 0x01, 0x30, 0x01, 0x00, 0x0c, 0x70, 0x04, 0x31, + 0x00, 0x80, 0x46, 0xf7, 0x01, 0x31, 0x81, 0x0f, 0xc9, 0x40, 0xdb, 0x0f, + 0x00, 0x1c, 0x40, 0x20, 0xd4, 0xc7, 0x59, 0xf7, 0xc3, 0x42, 0x35, 0xbf, + 0xf3, 0x04, 0x04, 0x33, 0x80, 0x80, 0xd3, 0xf6, 0x20, 0x86, 0x04, 0x30, + 0x00, 0x83, 0x50, 0xf7, 0x04, 0x30, 0x80, 0x80, 0xcc, 0xf6, 0x04, 0x31, + 0x80, 0x8f, 0x35, 0x3f, 0xf3, 0x04, 0x48, 0xf7, 0x04, 0x31, 0x80, 0x80, + 0x02, 0x07, 0xc9, 0xff, 0x02, 0xf0, 0x20, 0x86, 0x4a, 0xc0, 0x48, 0xc1, + 0x88, 0xc0, 0x84, 0xc2, 0x10, 0xd9, 0xfe, 0x0c, 0xef, 0xff, 0x49, 0xc3, + 0x8f, 0xf1, 0xe0, 0x78, 0xe6, 0xc0, 0x80, 0x81, 0x63, 0x80, 0xc1, 0x81, + 0xa2, 0x80, 0x00, 0x33, 0x0b, 0x03, 0x83, 0x81, 0x60, 0x80, 0x00, 0x33, + 0x03, 0x03, 0x01, 0x33, 0xc3, 0x02, 0x00, 0x35, 0x8c, 0x13, 0xc2, 0x81, + 0xa1, 0x80, 0x02, 0x33, 0x0c, 0x03, 0x00, 0x35, 0x83, 0x13, 0x01, 0x34, + 0xc3, 0x10, 0x60, 0xa2, 0x80, 0x81, 0x62, 0x80, 0xc3, 0x81, 0xa1, 0x80, + 0x00, 0x33, 0x0c, 0x03, 0x00, 0x35, 0x83, 0x13, 0xc2, 0x81, 0x01, 0x33, + 0x0b, 0x03, 0x81, 0x81, 0x63, 0x80, 0xa0, 0x80, 0x00, 0x33, 0x03, 0x03, + 0x01, 0x33, 0xc3, 0x10, 0x00, 0x35, 0x8c, 0x13, 0x02, 0x33, 0x03, 0x03, + 0x61, 0xa2, 0x80, 0x81, 0x61, 0x80, 0xc3, 0x81, 0xa2, 0x80, 0x00, 0x33, + 0x0b, 0x03, 0x80, 0x80, 0x00, 0x35, 0x83, 0x13, 0xa1, 0x81, 0x02, 0x33, + 0xcb, 0x02, 0xc2, 0x81, 0x00, 0x34, 0x43, 0x13, 0xa3, 0x80, 0x01, 0x33, + 0xcc, 0x10, 0x00, 0x35, 0x83, 0x13, 0x01, 0x34, 0xc3, 0x10, 0x62, 0xa2, + 0x80, 0x81, 0x60, 0x80, 0xc3, 0x81, 0xa3, 0x80, 0x04, 0x11, 0x0b, 0x00, + 0xe1, 0x80, 0x00, 0x33, 0x09, 0x03, 0x00, 0x35, 0x88, 0x13, 0x62, 0x81, + 0x22, 0x80, 0x00, 0x37, 0xcc, 0x12, 0x02, 0x30, 0x40, 0x12, 0x00, 0x31, + 0xc1, 0x00, 0x02, 0x30, 0x00, 0x03, 0x02, 0x30, 0x40, 0x00, 0x03, 0xa2, + 0xc6, 0xc4, 0xe0, 0x78, 0x40, 0x81, 0x02, 0xa1, 0x54, 0x70, 0xe0, 0x7c, + 0x21, 0x81, 0x00, 0x7a, 0xee, 0xc3, 0xa5, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x40, 0x24, 0x83, 0x32, 0x40, 0x24, 0x04, 0x33, 0x40, 0x24, 0x05, 0x34, + 0x40, 0x24, 0x06, 0x30, 0x40, 0x24, 0xc7, 0x32, 0x50, 0x43, 0x30, 0x40, + 0x3e, 0x0c, 0x2f, 0xf1, 0x0a, 0x1c, 0x83, 0x30, 0x0c, 0x14, 0x11, 0x30, + 0x63, 0x09, 0x31, 0x20, 0x2c, 0x70, 0x0a, 0x14, 0x92, 0x30, 0x0b, 0x14, + 0x8f, 0x30, 0x2e, 0x70, 0xef, 0x78, 0x53, 0x0a, 0x04, 0x20, 0xa7, 0xe9, + 0x21, 0x08, 0x70, 0x00, 0x00, 0xc5, 0x31, 0x08, 0xb1, 0x00, 0x00, 0x20, + 0x41, 0x23, 0x81, 0xc0, 0xde, 0x0f, 0xef, 0xe9, 0x4c, 0x74, 0x01, 0xc0, + 0xa5, 0x74, 0x40, 0xc5, 0x07, 0xa6, 0x0c, 0xf0, 0x00, 0x20, 0x41, 0x23, + 0x81, 0xc0, 0xca, 0x0f, 0xef, 0xe9, 0x4c, 0x74, 0x01, 0xc0, 0xa5, 0x74, + 0x40, 0xc5, 0x02, 0xa6, 0x72, 0x75, 0x8a, 0x20, 0x3e, 0x06, 0xca, 0x21, + 0x0d, 0x20, 0x3d, 0x23, 0x40, 0x23, 0x3c, 0x23, 0x41, 0x23, 0x1f, 0x67, + 0xd8, 0xf1, 0x22, 0x40, 0xce, 0xc7, 0xe0, 0x78, 0xe4, 0xc3, 0xa7, 0xc1, + 0x4a, 0x24, 0xc0, 0x70, 0x28, 0x46, 0x08, 0x45, 0x0c, 0x70, 0x84, 0xc4, + 0xa8, 0x20, 0x00, 0x03, 0x15, 0x25, 0x01, 0x10, 0x03, 0x4e, 0x24, 0x81, + 0x15, 0x24, 0x02, 0x10, 0x04, 0x71, 0x02, 0x33, 0x41, 0x00, 0x20, 0xa2, + 0x84, 0xc0, 0xda, 0x08, 0x6f, 0xf3, 0x81, 0xc1, 0x04, 0x8d, 0x12, 0xe8, + 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x4d, 0xc1, 0x40, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x10, 0x02, 0x04, 0x04, 0x19, 0x90, 0x00, 0x46, 0xd8, 0x00, 0xa1, + 0x0c, 0x1d, 0x01, 0x10, 0x04, 0x1d, 0x03, 0x10, 0x4a, 0x24, 0xc0, 0x70, + 0x40, 0x25, 0x00, 0x14, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x16, 0x01, 0x14, + 0x04, 0x18, 0x50, 0x00, 0x00, 0x80, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x24, + 0x41, 0x30, 0x48, 0x30, 0x03, 0x00, 0x81, 0xc0, 0xa8, 0x20, 0x80, 0x02, + 0x04, 0x10, 0x02, 0x04, 0x04, 0x32, 0xc0, 0x80, 0x6f, 0x22, 0x0b, 0x00, + 0x01, 0x19, 0x92, 0x00, 0x66, 0x0c, 0x6f, 0xf2, 0x40, 0x24, 0x40, 0x30, + 0x14, 0x70, 0x0c, 0x70, 0x2c, 0x70, 0x04, 0xf2, 0x23, 0x85, 0x24, 0x71, + 0x42, 0x85, 0x0d, 0x0a, 0x65, 0x00, 0x23, 0xa5, 0x03, 0xa5, 0x81, 0xd8, + 0xc4, 0xc7, 0xe0, 0x78, 0xe6, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, 0x5e, 0x0b, 0x2f, 0xf1, 0x03, 0x1c, + 0x83, 0x30, 0x02, 0x14, 0x80, 0x30, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, + 0x29, 0x09, 0x04, 0x00, 0x0d, 0x08, 0x90, 0x00, 0x15, 0x08, 0x51, 0x00, + 0x02, 0x86, 0x03, 0xf0, 0x07, 0x86, 0x81, 0xc3, 0xa1, 0x41, 0xb6, 0x0b, + 0xef, 0xf7, 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, + 0x02, 0x30, 0xeb, 0xf1, 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, + 0x21, 0xad, 0xc6, 0xc7, 0xe2, 0xc2, 0x60, 0x40, 0x2c, 0x70, 0x10, 0xda, + 0xca, 0x0c, 0xef, 0xf7, 0x88, 0x45, 0x00, 0x1d, 0x01, 0x10, 0xc2, 0xc6, + 0xe8, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, 0x60, 0x44, 0x40, 0x24, + 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x47, + 0x28, 0x45, 0xea, 0x0a, 0x2f, 0xf1, 0x03, 0x1c, 0x83, 0x30, 0x02, 0x14, + 0x80, 0x30, 0x40, 0x26, 0x10, 0x14, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, + 0x33, 0x09, 0x04, 0x00, 0x19, 0x08, 0xb0, 0x00, 0x81, 0xc3, 0x1f, 0x08, + 0x71, 0x00, 0x81, 0xc3, 0x03, 0x86, 0xa1, 0x41, 0x3e, 0x0b, 0xef, 0xf7, + 0xe1, 0x42, 0x07, 0xf0, 0x02, 0x40, 0xa1, 0x41, 0x3a, 0x0d, 0x6f, 0xf5, + 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, + 0xe5, 0xf1, 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, + 0xc8, 0xc7, 0xe0, 0x78, 0xfa, 0xdb, 0x46, 0xda, 0x2c, 0x70, 0x04, 0x18, + 0x43, 0x00, 0x62, 0xa0, 0x47, 0xa0, 0x23, 0xa0, 0x24, 0xa0, 0x25, 0xa0, + 0xe0, 0x7f, 0x26, 0xa0, 0xea, 0xc3, 0x82, 0x24, 0x0c, 0x39, 0x50, 0x41, + 0x08, 0x46, 0x89, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0xe2, 0x0d, 0xef, 0xe9, + 0x28, 0x45, 0x00, 0x86, 0x40, 0x24, 0xc3, 0x34, 0x40, 0x24, 0x04, 0x37, + 0x40, 0x24, 0x05, 0x38, 0x40, 0x24, 0x06, 0x33, 0x40, 0x24, 0xc7, 0x36, + 0xa1, 0x41, 0x22, 0x42, 0xee, 0x09, 0x2f, 0xf1, 0x13, 0x1c, 0x83, 0x30, + 0x1c, 0x14, 0x10, 0x30, 0x67, 0x08, 0x31, 0x20, 0x2c, 0x70, 0x1b, 0x14, + 0x8f, 0x30, 0x0e, 0x70, 0xad, 0xe9, 0x13, 0x14, 0x81, 0x30, 0xef, 0x78, + 0x53, 0x09, 0x04, 0x00, 0x23, 0x08, 0xb0, 0x00, 0x83, 0xc1, 0x33, 0x08, + 0x71, 0x00, 0x89, 0xc1, 0x03, 0xc5, 0x85, 0xc0, 0xb9, 0x61, 0x8e, 0x0d, + 0xef, 0xe9, 0x4c, 0x74, 0x05, 0xc1, 0x04, 0x6d, 0x43, 0xc0, 0x23, 0xa6, + 0x0b, 0xf0, 0x89, 0xc0, 0x6e, 0x0c, 0x6f, 0xf5, 0x80, 0xc2, 0x00, 0xc2, + 0x01, 0xc1, 0x02, 0xc0, 0x44, 0xa6, 0x25, 0xa6, 0x06, 0xa6, 0x03, 0xc0, + 0x8a, 0x21, 0x3e, 0x06, 0x32, 0x70, 0xca, 0x20, 0x4d, 0x20, 0x3c, 0x21, + 0x01, 0x20, 0x3d, 0x21, 0x00, 0x20, 0x1f, 0x67, 0xd4, 0xf1, 0x02, 0x40, + 0xca, 0xc7, 0xe0, 0x78, 0x48, 0x31, 0x01, 0x00, 0x07, 0x36, 0x42, 0x70, + 0x48, 0x47, 0x00, 0x00, 0x2c, 0x70, 0x04, 0x32, 0x40, 0x80, 0xc7, 0xf6, + 0x01, 0x32, 0x81, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x32, + 0x81, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x18, + 0x43, 0x00, 0x48, 0x31, 0x81, 0x00, 0x48, 0x31, 0x41, 0x02, 0x35, 0x79, + 0xe0, 0x7f, 0x22, 0xa0, 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x34, 0x48, 0x47, + 0x08, 0x45, 0x84, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0xfe, 0x0c, 0xef, 0xe9, + 0x28, 0x46, 0x00, 0x85, 0x40, 0x24, 0x83, 0x30, 0x40, 0x24, 0x04, 0x32, + 0x40, 0x24, 0x05, 0x33, 0x40, 0x24, 0x06, 0x31, 0x40, 0x24, 0xc7, 0x30, + 0xc1, 0x41, 0xe1, 0x42, 0x0a, 0x09, 0x2f, 0xf1, 0x02, 0x1c, 0x43, 0x30, + 0x02, 0xc6, 0xcb, 0x0e, 0x31, 0x10, 0x55, 0x25, 0x50, 0x18, 0x03, 0x14, + 0x8e, 0x30, 0x02, 0x14, 0x80, 0x30, 0x2b, 0x08, 0x84, 0x03, 0xcf, 0x78, + 0x11, 0x08, 0x71, 0x00, 0x84, 0xc0, 0x7e, 0x08, 0x6f, 0xfa, 0x81, 0xc1, + 0x20, 0x18, 0x02, 0x20, 0x01, 0xc0, 0x9f, 0x0f, 0x24, 0x10, 0xc5, 0x71, + 0x02, 0x14, 0x80, 0x30, 0xcf, 0x79, 0xe3, 0x08, 0x45, 0x80, 0x20, 0x10, + 0x80, 0x20, 0x8f, 0x08, 0x30, 0x00, 0xcd, 0x70, 0xcb, 0x41, 0x32, 0x01, + 0xe6, 0x78, 0xcb, 0x40, 0x00, 0x00, 0x9c, 0x6c, 0xcb, 0x43, 0xef, 0x41, + 0x96, 0xe8, 0xcb, 0x47, 0x5f, 0x05, 0xbe, 0x0a, 0xcb, 0x44, 0x64, 0x75, + 0x84, 0x00, 0xc3, 0x43, 0x5f, 0x05, 0x4a, 0x00, 0xc3, 0x42, 0x0c, 0x00, + 0x0c, 0x00, 0xc3, 0x41, 0xaa, 0x7e, 0xa0, 0x00, 0x8a, 0x26, 0x04, 0x00, + 0x7d, 0xd8, 0x1c, 0x18, 0x80, 0x23, 0x18, 0x18, 0x80, 0x23, 0x3e, 0x1d, + 0xc5, 0x11, 0x58, 0x1d, 0x45, 0x10, 0x44, 0x1d, 0x84, 0x13, 0xc5, 0xa5, + 0xd7, 0xb5, 0xd9, 0xb5, 0xdb, 0xb5, 0xdd, 0xb5, 0x20, 0x1d, 0x40, 0x12, + 0x26, 0x1d, 0x04, 0x12, 0x54, 0x1d, 0xc0, 0x12, 0xf4, 0xa5, 0x8a, 0xa5, + 0x73, 0xa5, 0x46, 0xa5, 0x30, 0xa5, 0x48, 0x1d, 0x84, 0x11, 0x1f, 0xa5, + 0x00, 0x18, 0x00, 0x20, 0x2e, 0x0b, 0x60, 0x03, 0x0c, 0x70, 0x9e, 0x20, + 0x06, 0x04, 0x1a, 0xb5, 0x03, 0xf0, 0x8a, 0x26, 0x3e, 0x16, 0xc1, 0x40, + 0xc8, 0xc7, 0xe0, 0x78, 0xfa, 0xc3, 0xa8, 0xc1, 0x4a, 0x24, 0x00, 0x71, + 0x0a, 0x27, 0x80, 0x21, 0x0a, 0x23, 0x40, 0x21, 0x0a, 0x20, 0x00, 0x31, + 0x78, 0x41, 0x50, 0x46, 0x08, 0x46, 0x55, 0x20, 0x0d, 0x08, 0x80, 0xc2, + 0xed, 0x70, 0xd3, 0x44, 0x00, 0x3f, 0x00, 0x00, 0xa8, 0x20, 0x80, 0x06, + 0x04, 0x11, 0x00, 0x04, 0x00, 0x30, 0x80, 0x0f, 0x03, 0x40, 0x6f, 0x12, + 0x04, 0x30, 0xc0, 0x83, 0xc4, 0xf6, 0x01, 0x30, 0x00, 0x05, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc0, 0x02, + 0x48, 0x30, 0x80, 0x00, 0x48, 0x30, 0xc0, 0x02, 0x04, 0x1a, 0x10, 0x00, + 0x42, 0x0c, 0x20, 0x01, 0x00, 0xc0, 0x10, 0x40, 0x3a, 0x0c, 0x20, 0x01, + 0x01, 0xc0, 0x00, 0x20, 0x10, 0x20, 0x32, 0x0c, 0x20, 0x01, 0x02, 0xc0, + 0xf6, 0x08, 0x60, 0x00, 0x02, 0x70, 0x0e, 0x79, 0xc1, 0x40, 0x1e, 0x0d, + 0x20, 0x00, 0x30, 0x42, 0x28, 0x96, 0x10, 0x40, 0x10, 0x49, 0x2f, 0x20, + 0x06, 0x80, 0x0a, 0x00, 0x03, 0x00, 0x13, 0x78, 0x0e, 0x78, 0x48, 0x30, + 0x80, 0x00, 0x00, 0x30, 0x80, 0x0f, 0x00, 0x3d, 0x00, 0x00, 0x82, 0x09, + 0x4f, 0xf5, 0x48, 0x30, 0xc0, 0x02, 0x2a, 0x16, 0x55, 0x11, 0x12, 0x16, + 0x51, 0x11, 0xea, 0x0d, 0x60, 0x02, 0x0e, 0x78, 0x48, 0x30, 0x80, 0x00, + 0x66, 0x09, 0x6f, 0xf5, 0x00, 0x30, 0x00, 0x05, 0x00, 0x42, 0x22, 0x40, + 0x9a, 0x0e, 0x20, 0x00, 0xa2, 0x41, 0x2a, 0x9e, 0x8b, 0x96, 0x68, 0x9e, + 0x5b, 0x96, 0x1e, 0x21, 0x14, 0x00, 0x18, 0x24, 0xd1, 0x10, 0x09, 0xb6, + 0x05, 0xea, 0xc1, 0x40, 0x1e, 0x0d, 0x20, 0x00, 0x42, 0x41, 0x2f, 0x21, + 0x46, 0x04, 0x2f, 0x22, 0x06, 0x05, 0x3f, 0x22, 0x41, 0x00, 0x3b, 0x79, + 0x0e, 0x9e, 0x18, 0xe1, 0x35, 0x26, 0x52, 0x10, 0x5e, 0x0d, 0x20, 0x00, + 0x2c, 0x71, 0x48, 0x9e, 0x30, 0x9e, 0x0e, 0xb6, 0xb6, 0x0a, 0x20, 0x01, + 0x0f, 0x9e, 0x48, 0x96, 0x31, 0x96, 0x59, 0x61, 0x2e, 0x7b, 0x0b, 0x08, + 0xe3, 0x00, 0x0f, 0xb6, 0x2f, 0xb6, 0x33, 0x9e, 0x12, 0x9e, 0x9e, 0x0a, + 0x20, 0x01, 0x4e, 0x7a, 0x34, 0x96, 0x48, 0x96, 0x31, 0x4a, 0x2e, 0x7b, + 0x09, 0x0b, 0x23, 0x00, 0x12, 0xb6, 0x32, 0xb6, 0x35, 0x9e, 0x4e, 0x78, + 0x82, 0x0a, 0x20, 0x01, 0x02, 0x42, 0x2f, 0x9e, 0x2e, 0x70, 0x21, 0x09, + 0x23, 0x04, 0x08, 0xb6, 0x2c, 0x16, 0x80, 0x10, 0x1e, 0x1e, 0x04, 0x14, + 0x88, 0xe8, 0x0e, 0x9e, 0x0d, 0x0a, 0x03, 0x20, 0x2e, 0x71, 0xee, 0xb6, + 0x2c, 0x1e, 0x43, 0x10, 0x12, 0x9e, 0x0f, 0x08, 0x03, 0x20, 0x2c, 0x1e, + 0xc2, 0x13, 0x24, 0x1e, 0x04, 0x14, 0x18, 0x9e, 0xe6, 0x0c, 0x20, 0x00, + 0x2c, 0x71, 0x18, 0xb6, 0x53, 0x09, 0x30, 0x20, 0x00, 0x1b, 0x42, 0x24, + 0x17, 0x96, 0x6c, 0x71, 0x14, 0x70, 0x0c, 0x71, 0x0a, 0xf2, 0x39, 0x96, + 0x1a, 0x96, 0x58, 0x96, 0x2a, 0x78, 0x34, 0x6a, 0x2e, 0x79, 0x0e, 0x78, + 0x3e, 0x21, 0x00, 0x00, 0x3b, 0x96, 0x06, 0xe9, 0x5c, 0x96, 0x3d, 0x96, + 0x3d, 0x21, 0x83, 0x00, 0x15, 0xe8, 0x15, 0xeb, 0x1f, 0x96, 0x3c, 0x16, + 0x81, 0x10, 0x3d, 0x09, 0x25, 0x00, 0x40, 0x21, 0x50, 0x00, 0x2f, 0x21, + 0x07, 0x04, 0x10, 0x71, 0x3c, 0x1e, 0x02, 0x14, 0xca, 0x20, 0x25, 0x20, + 0x2e, 0xf0, 0x18, 0x9e, 0x2e, 0x70, 0x32, 0x40, 0x5a, 0xf0, 0x44, 0x16, + 0x00, 0x11, 0x3c, 0x1e, 0xc2, 0x13, 0x36, 0x09, 0x60, 0x03, 0xc0, 0xb8, + 0x9e, 0x20, 0x06, 0x04, 0x0e, 0x70, 0x2e, 0x71, 0x1a, 0xb6, 0x46, 0xf0, + 0x38, 0x9e, 0x1a, 0x9e, 0x74, 0x69, 0x1b, 0x79, 0x62, 0x79, 0x2f, 0x21, + 0x46, 0x80, 0x0a, 0x00, 0x03, 0x00, 0x33, 0x79, 0x2e, 0x79, 0x40, 0x16, + 0x02, 0x11, 0x15, 0x09, 0xa3, 0x00, 0x0e, 0x71, 0x00, 0x1b, 0x83, 0x20, + 0x38, 0x9e, 0x1a, 0x9e, 0x0e, 0x72, 0x74, 0x69, 0x42, 0x16, 0x41, 0x11, + 0x9e, 0x09, 0x20, 0x01, 0x6e, 0x7a, 0x1a, 0xb6, 0x44, 0x16, 0x00, 0x11, + 0xe6, 0x08, 0x60, 0x03, 0xc0, 0xb8, 0x1e, 0x20, 0x00, 0x04, 0x2e, 0x70, + 0x2f, 0x23, 0x07, 0x90, 0x1d, 0xf2, 0x46, 0x16, 0x00, 0x11, 0x48, 0x16, + 0x0c, 0x11, 0x4c, 0x71, 0x4a, 0x20, 0x00, 0x20, 0x98, 0x60, 0x44, 0x71, + 0x10, 0x78, 0x4f, 0x79, 0x41, 0x28, 0xc8, 0x01, 0x41, 0x28, 0x03, 0x02, + 0x0c, 0x23, 0x40, 0x90, 0x44, 0x20, 0x41, 0x10, 0x79, 0x61, 0x79, 0x20, + 0x00, 0x00, 0x00, 0x20, 0x50, 0x20, 0x70, 0xf7, 0x46, 0x1e, 0x04, 0x10, + 0x02, 0xf0, 0x0e, 0x70, 0x44, 0x16, 0x81, 0x10, 0x0c, 0x70, 0xf8, 0xb6, + 0xc0, 0xb9, 0xfc, 0xb6, 0x4a, 0x1e, 0x42, 0x10, 0x4c, 0x16, 0x41, 0x11, + 0x1b, 0x09, 0x03, 0x00, 0x44, 0x16, 0x00, 0x11, 0x3c, 0x1e, 0xc2, 0x13, + 0x7a, 0x08, 0x60, 0x03, 0xc0, 0xb8, 0x9e, 0x20, 0x06, 0x04, 0x1a, 0xb6, + 0x02, 0xf0, 0x1a, 0x96, 0x2f, 0x23, 0x06, 0x80, 0x10, 0x00, 0x23, 0x00, + 0x10, 0x79, 0x0c, 0x70, 0x8f, 0xb8, 0x09, 0x09, 0x00, 0x00, 0x33, 0x78, + 0x04, 0x20, 0x82, 0x0f, 0x00, 0x00, 0xfe, 0xff, 0x42, 0x78, 0x5d, 0x79, + 0x2f, 0x26, 0x08, 0xf0, 0x0d, 0x0b, 0x33, 0x00, 0xc0, 0x21, 0x62, 0x00, + 0x30, 0x78, 0x13, 0x79, 0x18, 0x96, 0x2e, 0x79, 0x04, 0xb8, 0x0e, 0x78, + 0x13, 0x08, 0x42, 0x00, 0x4a, 0x16, 0x80, 0x10, 0x05, 0xe8, 0x00, 0x1b, + 0x43, 0x20, 0x4a, 0x1e, 0xc2, 0x13, 0x08, 0x16, 0x0b, 0x10, 0x43, 0x86, + 0x25, 0x85, 0x04, 0x85, 0xf8, 0xad, 0x00, 0x13, 0x83, 0x20, 0x3d, 0x20, + 0xc8, 0x02, 0x36, 0x70, 0x79, 0x23, 0x00, 0x00, 0x07, 0xb8, 0x3d, 0x21, + 0x8c, 0x00, 0xcf, 0x20, 0xa2, 0x01, 0x30, 0x72, 0xca, 0x24, 0x01, 0x12, + 0x18, 0xad, 0x87, 0xec, 0x85, 0xb8, 0x10, 0x1d, 0xc0, 0x12, 0x45, 0xa5, + 0x18, 0xad, 0x7e, 0x86, 0x3f, 0x86, 0x29, 0x0b, 0x44, 0x00, 0x28, 0x85, + 0x87, 0x85, 0x30, 0x72, 0x3d, 0x24, 0xc8, 0x12, 0x3d, 0x21, 0x8c, 0x00, + 0xca, 0x24, 0x01, 0x12, 0x88, 0xec, 0x83, 0xb8, 0x1c, 0x1d, 0xc0, 0x12, + 0x48, 0xa5, 0x2c, 0x70, 0x18, 0xad, 0x03, 0xf0, 0x21, 0x6b, 0x60, 0x85, + 0x81, 0x85, 0x2b, 0x0b, 0x24, 0x03, 0x3e, 0xa6, 0x23, 0x85, 0x82, 0x85, + 0x30, 0x72, 0x3d, 0x24, 0xc8, 0x12, 0x3d, 0x21, 0x8c, 0x00, 0xca, 0x24, + 0x01, 0x12, 0x89, 0xec, 0x84, 0xb8, 0x08, 0x1d, 0xc0, 0x12, 0x43, 0xa5, + 0x2c, 0x70, 0x18, 0xad, 0x02, 0xf0, 0x21, 0x6b, 0x44, 0x8e, 0x20, 0xa5, + 0x05, 0xea, 0x45, 0x20, 0x00, 0x0e, 0xe4, 0xae, 0x18, 0xad, 0x00, 0x1f, + 0x02, 0x20, 0x04, 0x1e, 0xc0, 0x23, 0x02, 0x86, 0x23, 0x86, 0x4c, 0x70, + 0x00, 0x20, 0x00, 0x84, 0x41, 0x21, 0x01, 0x80, 0x02, 0xa6, 0x23, 0xa6, + 0x00, 0x1e, 0x00, 0x20, 0x02, 0x85, 0x23, 0x85, 0x00, 0x20, 0x00, 0x84, + 0x46, 0xc0, 0x41, 0x21, 0x03, 0x80, 0x24, 0x85, 0x05, 0x85, 0x47, 0xc3, + 0x00, 0x21, 0x01, 0x84, 0x41, 0x20, 0x00, 0x80, 0x44, 0xc1, 0x45, 0xc0, + 0x86, 0xc0, 0x84, 0xc1, 0x43, 0x48, 0x40, 0x49, 0x15, 0x21, 0x8d, 0x30, + 0x15, 0x20, 0x8c, 0x30, 0x54, 0x71, 0x4c, 0x71, 0x60, 0xa5, 0x00, 0xa4, + 0xf4, 0xf5, 0xda, 0xc7, 0xe6, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x31, 0x40, 0x24, 0x05, 0x30, 0x40, 0x24, + 0x86, 0x31, 0x48, 0x47, 0x28, 0x45, 0x86, 0x0c, 0xef, 0xf0, 0x07, 0x1c, + 0x43, 0x30, 0x07, 0x14, 0x83, 0x30, 0x06, 0x14, 0x81, 0x30, 0x2f, 0x78, + 0x23, 0x0b, 0x04, 0x00, 0x17, 0x08, 0x51, 0x00, 0x00, 0xc0, 0x41, 0x68, + 0x0f, 0x0f, 0xa4, 0x10, 0xb8, 0x60, 0xa4, 0x16, 0x8c, 0x10, 0x40, 0xc2, + 0x80, 0xa8, 0x24, 0x71, 0x06, 0x1c, 0x42, 0x30, 0xef, 0xf1, 0x00, 0xc0, + 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xc6, 0xc7, 0xe0, 0x78, + 0xe8, 0xc2, 0x50, 0x40, 0x28, 0x46, 0x2c, 0x70, 0x10, 0xda, 0x60, 0x40, + 0x88, 0x47, 0xf2, 0x0d, 0xaf, 0xf7, 0x68, 0x45, 0x0c, 0x70, 0x07, 0xee, + 0x0b, 0x08, 0xd1, 0x2f, 0x0c, 0x71, 0x00, 0x1d, 0x43, 0x10, 0x00, 0xa7, + 0xc8, 0xc6, 0xe0, 0x78, 0xe6, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x00, 0x80, + 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, + 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, 0x02, 0x0c, 0xef, 0xf0, 0x03, 0x1c, + 0x83, 0x35, 0x02, 0x14, 0x80, 0x30, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, + 0xeb, 0x09, 0x24, 0x00, 0x04, 0x77, 0xdb, 0x08, 0x95, 0x05, 0x25, 0x20, + 0x00, 0x00, 0x17, 0xf0, 0x17, 0xf0, 0x19, 0xf0, 0x19, 0xf0, 0x1b, 0xf0, + 0x1b, 0xf0, 0x22, 0xf0, 0x22, 0xf0, 0x24, 0xf0, 0x24, 0xf0, 0x27, 0xf0, + 0x27, 0xf0, 0x29, 0xf0, 0x29, 0xf0, 0x2c, 0xf0, 0x2d, 0xf0, 0x35, 0xf0, + 0x3a, 0xf0, 0x3d, 0xf0, 0x44, 0xf0, 0x46, 0xf0, 0x4c, 0xf0, 0x17, 0x86, + 0x0a, 0xf0, 0x18, 0x86, 0x08, 0xf0, 0x19, 0x86, 0x06, 0xf0, 0x1a, 0x86, + 0x04, 0xf0, 0x1b, 0x86, 0x02, 0xf0, 0x1c, 0x86, 0x81, 0xc3, 0xa1, 0x41, + 0xc2, 0x08, 0x2f, 0xed, 0xe1, 0x42, 0x43, 0xf0, 0x0f, 0x9e, 0x17, 0xf0, + 0x12, 0x9e, 0x15, 0xf0, 0x08, 0x9e, 0x13, 0xf0, 0x2c, 0x16, 0x80, 0x10, + 0x34, 0xf0, 0x18, 0x9e, 0x0d, 0xf0, 0x0e, 0x9e, 0x0b, 0xf0, 0x09, 0x9e, + 0x09, 0xf0, 0x46, 0x16, 0x00, 0x11, 0x0e, 0xf0, 0x4a, 0x16, 0x80, 0x10, + 0x28, 0xf0, 0x74, 0x16, 0x40, 0x11, 0x81, 0xc3, 0xa1, 0x41, 0x46, 0x0c, + 0x60, 0x00, 0xe1, 0x42, 0x25, 0xf0, 0x1c, 0x96, 0x81, 0xc3, 0xa1, 0x41, + 0x6e, 0x0a, 0x2f, 0xf4, 0xe1, 0x42, 0x1f, 0xf0, 0x3c, 0x16, 0x80, 0x10, + 0x16, 0xf0, 0x23, 0x86, 0x02, 0x86, 0x40, 0x24, 0x04, 0x31, 0xa1, 0x42, + 0xd6, 0x0a, 0x2f, 0xfa, 0xe1, 0x43, 0x13, 0xf0, 0x1e, 0x86, 0x04, 0xf0, + 0x80, 0x16, 0x00, 0x10, 0x81, 0xc3, 0xa1, 0x41, 0xa6, 0x0b, 0xaf, 0xf7, + 0xe1, 0x42, 0x09, 0xf0, 0x98, 0x16, 0x80, 0x10, 0x81, 0xc3, 0xa1, 0x41, + 0x1e, 0x0d, 0xaf, 0xf2, 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, + 0x02, 0x1c, 0x02, 0x30, 0x89, 0xf1, 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, + 0x00, 0xad, 0x21, 0xad, 0xc6, 0xc7, 0xe0, 0x78, 0xe2, 0xc3, 0xa2, 0xc1, + 0x08, 0x45, 0x97, 0x80, 0x18, 0x80, 0x54, 0x15, 0x46, 0x11, 0x56, 0x15, + 0x45, 0x11, 0x4e, 0x15, 0x44, 0x11, 0x50, 0x15, 0x43, 0x11, 0x52, 0x15, + 0x42, 0x11, 0x41, 0xc0, 0x80, 0xc0, 0x12, 0x09, 0x20, 0x00, 0x40, 0xc4, + 0x00, 0x41, 0x58, 0x15, 0x00, 0x11, 0x00, 0xc3, 0x01, 0xc2, 0x77, 0xa5, + 0x58, 0xa5, 0x18, 0xe8, 0x1a, 0x85, 0x99, 0x85, 0x54, 0x15, 0x46, 0x11, + 0x56, 0x15, 0x45, 0x11, 0x4e, 0x15, 0x44, 0x11, 0x50, 0x15, 0x43, 0x11, + 0x52, 0x15, 0x42, 0x11, 0x41, 0xc0, 0x80, 0xc0, 0xde, 0x08, 0x20, 0x00, + 0x40, 0xc4, 0x00, 0xc3, 0x01, 0xc2, 0x00, 0x41, 0x79, 0xa5, 0x5a, 0xa5, + 0x20, 0x40, 0xc2, 0xc7, 0xe2, 0xc3, 0xa2, 0xc1, 0x08, 0x45, 0x5b, 0x80, + 0x1c, 0x80, 0x8c, 0x70, 0x40, 0xc2, 0x41, 0xc0, 0x80, 0xc0, 0xc3, 0x42, + 0x00, 0x00, 0xc8, 0x3b, 0xc3, 0x43, 0xff, 0xff, 0x39, 0xc4, 0xc3, 0x45, + 0x00, 0x00, 0x91, 0x37, 0xa6, 0x08, 0x20, 0x00, 0x80, 0x46, 0x00, 0xc2, + 0x01, 0xc1, 0x14, 0x70, 0x5b, 0xa5, 0x3c, 0xa5, 0xc6, 0xf6, 0x74, 0x15, + 0x40, 0x11, 0x1f, 0x08, 0x13, 0x00, 0x07, 0xf0, 0x4b, 0xf6, 0x74, 0x15, + 0x40, 0x11, 0x13, 0x08, 0x52, 0x00, 0x3c, 0x95, 0x13, 0x78, 0x74, 0x1d, + 0x04, 0x10, 0x01, 0x69, 0x1c, 0xb5, 0xc2, 0xc7, 0x81, 0x04, 0xc0, 0x00, + 0x19, 0x61, 0xc3, 0x40, 0x00, 0x00, 0xff, 0x7f, 0x10, 0x71, 0xca, 0x21, + 0x09, 0x00, 0x07, 0xf6, 0x0b, 0x09, 0x83, 0x0f, 0xff, 0xff, 0x00, 0x80, + 0x21, 0x68, 0xe0, 0x7f, 0x2e, 0x78, 0xe0, 0x78, 0xe6, 0xc2, 0x28, 0x47, + 0x10, 0xd9, 0x6a, 0x0d, 0x60, 0x00, 0x08, 0x45, 0x08, 0x46, 0x10, 0xd9, + 0x5e, 0x0d, 0x60, 0x00, 0xe1, 0x40, 0xc7, 0x78, 0x0e, 0x78, 0x56, 0x0d, + 0x60, 0x00, 0x0f, 0xd9, 0xfd, 0x65, 0x94, 0xe8, 0x10, 0xd9, 0x4a, 0x0d, + 0x60, 0x00, 0xa1, 0x40, 0xc7, 0x78, 0x0e, 0x78, 0x3e, 0x0d, 0x60, 0x00, + 0x0f, 0xd9, 0x0a, 0xe8, 0xd5, 0x70, 0xc3, 0x40, 0xff, 0x07, 0xff, 0xff, + 0x6f, 0x25, 0x43, 0x10, 0xca, 0x25, 0x09, 0x10, 0xa1, 0x40, 0xc6, 0xc6, + 0xf0, 0xc2, 0x30, 0x43, 0x49, 0x79, 0xcd, 0x70, 0x8d, 0xbe, 0x08, 0x47, + 0xd8, 0x61, 0x0e, 0xd9, 0x0a, 0x22, 0x80, 0x21, 0x0a, 0x21, 0x40, 0x21, + 0x0a, 0x24, 0x00, 0x21, 0x06, 0x0d, 0x60, 0x00, 0x68, 0x45, 0x96, 0x0f, + 0xef, 0xff, 0x21, 0x87, 0x1e, 0x25, 0xc1, 0x14, 0x00, 0x17, 0x10, 0x10, + 0x08, 0x45, 0xd8, 0x61, 0xee, 0x0c, 0x60, 0x00, 0x0e, 0xd9, 0x00, 0x41, + 0x7a, 0x0f, 0xef, 0xff, 0x02, 0x40, 0x10, 0x40, 0x1a, 0x25, 0x40, 0x14, + 0x0e, 0xd9, 0xda, 0x0c, 0x60, 0x00, 0xd8, 0x60, 0x00, 0x41, 0x66, 0x0f, + 0xef, 0xff, 0x02, 0x40, 0x1e, 0x24, 0xc1, 0x24, 0x01, 0xa7, 0xd8, 0x61, + 0xc2, 0x0c, 0x60, 0x00, 0x0e, 0xd9, 0x10, 0x40, 0x1a, 0x25, 0x80, 0x14, + 0x0e, 0xd9, 0xb6, 0x0c, 0x60, 0x00, 0xd8, 0x60, 0x00, 0x41, 0x42, 0x0f, + 0xef, 0xff, 0x02, 0x40, 0xc3, 0x41, 0x00, 0x00, 0xff, 0x7f, 0x15, 0x09, + 0x62, 0x03, 0x00, 0xa7, 0xa1, 0x41, 0x0d, 0x0d, 0x83, 0x1f, 0xff, 0xff, + 0x00, 0x80, 0x32, 0x6e, 0x2e, 0x78, 0xd0, 0xc6, 0xf1, 0xc0, 0x1e, 0x21, + 0x0c, 0x00, 0x0c, 0x70, 0x04, 0x32, 0x00, 0x80, 0xc6, 0xf6, 0x01, 0x32, + 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, 0x01, 0x32, 0x80, 0x0f, + 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc0, 0x02, 0x4c, 0x70, 0x48, 0x30, + 0x80, 0x00, 0x8f, 0xba, 0x33, 0x4a, 0x48, 0x30, 0xc1, 0x02, 0x5d, 0x7a, + 0x6c, 0x79, 0x99, 0x61, 0x58, 0x61, 0x52, 0x0c, 0x60, 0x00, 0x0f, 0xd9, + 0xd1, 0xc0, 0xe0, 0x7f, 0x0e, 0x78, 0xe0, 0x78, 0xe8, 0xc3, 0x82, 0x24, + 0x0c, 0x34, 0x50, 0x40, 0x08, 0x47, 0x84, 0xc0, 0x8a, 0x22, 0x0c, 0x00, + 0x4e, 0x0c, 0xaf, 0xe9, 0x28, 0x45, 0x00, 0x87, 0x40, 0x24, 0x83, 0x30, + 0x40, 0x24, 0x04, 0x32, 0x40, 0x24, 0x05, 0x33, 0x40, 0x24, 0x06, 0x31, + 0x40, 0x24, 0xc7, 0x30, 0xa1, 0x41, 0x02, 0x42, 0x5a, 0x08, 0xef, 0xf0, + 0x02, 0x1c, 0x83, 0x35, 0x02, 0xc5, 0xb5, 0x70, 0xc0, 0xf4, 0x03, 0x14, + 0x8e, 0x30, 0xad, 0x70, 0x2c, 0x70, 0x34, 0x70, 0xba, 0xf4, 0x02, 0x14, + 0x81, 0x30, 0xcf, 0x78, 0x30, 0x70, 0x6c, 0x01, 0x2d, 0x00, 0x04, 0x77, + 0x95, 0xe0, 0x4c, 0x01, 0x0d, 0x00, 0x25, 0x20, 0x00, 0x00, 0x17, 0xf0, + 0x1b, 0xf0, 0x21, 0xf0, 0x25, 0xf0, 0x2b, 0xf0, 0x2f, 0xf0, 0x35, 0xf0, + 0x39, 0xf0, 0x3f, 0xf0, 0x43, 0xf0, 0x4a, 0xf0, 0x4e, 0xf0, 0x54, 0xf0, + 0x58, 0xf0, 0x5f, 0xf0, 0x64, 0xf0, 0x6b, 0xf0, 0x6f, 0xf0, 0x76, 0xf0, + 0x7b, 0xf0, 0x81, 0xf0, 0x86, 0xf0, 0x84, 0xc0, 0x62, 0x0d, 0xef, 0xec, + 0x81, 0xc1, 0x17, 0xa7, 0x86, 0xf0, 0x84, 0xc0, 0x56, 0x0d, 0xef, 0xec, + 0x81, 0xc1, 0x18, 0xa7, 0x80, 0xf0, 0x84, 0xc0, 0x4a, 0x0d, 0xef, 0xec, + 0x81, 0xc1, 0x19, 0xa7, 0x7a, 0xf0, 0x84, 0xc0, 0x3e, 0x0d, 0xef, 0xec, + 0x81, 0xc1, 0x1a, 0xa7, 0x74, 0xf0, 0x84, 0xc0, 0x32, 0x0d, 0xef, 0xec, + 0x81, 0xc1, 0x1b, 0xa7, 0x6e, 0xf0, 0x84, 0xc0, 0x26, 0x0d, 0xef, 0xec, + 0x81, 0xc1, 0x1c, 0xa7, 0x68, 0xf0, 0x84, 0xc0, 0x32, 0x0c, 0xe0, 0x00, + 0x81, 0xc1, 0x0f, 0xb7, 0x62, 0xf0, 0x84, 0xc0, 0x26, 0x0c, 0xe0, 0x00, + 0x81, 0xc1, 0x12, 0xb7, 0x5c, 0xf0, 0x84, 0xc0, 0x1a, 0x0c, 0xe0, 0x00, + 0x81, 0xc1, 0x08, 0xb7, 0x56, 0xf0, 0x84, 0xc0, 0xe6, 0x09, 0xaf, 0xf2, + 0x81, 0xc1, 0x2c, 0x1f, 0x02, 0x10, 0x50, 0xf0, 0x84, 0xc0, 0x02, 0x0c, + 0xe0, 0x00, 0x81, 0xc1, 0x18, 0xb7, 0x4a, 0xf0, 0x84, 0xc0, 0xf6, 0x0b, + 0xe0, 0x00, 0x81, 0xc1, 0x0e, 0xb7, 0x44, 0xf0, 0x84, 0xc0, 0xea, 0x0b, + 0xe0, 0x00, 0x81, 0xc1, 0x09, 0xb7, 0x3e, 0xf0, 0x84, 0xc0, 0xc2, 0x0e, + 0xef, 0xf3, 0x81, 0xc1, 0x46, 0x1f, 0x04, 0x10, 0x36, 0xf0, 0x84, 0xc0, + 0xa6, 0x09, 0xaf, 0xf2, 0x81, 0xc1, 0x4a, 0x1f, 0x02, 0x10, 0x30, 0xf0, + 0x84, 0xc0, 0xc2, 0x0b, 0xe0, 0x00, 0x81, 0xc1, 0x74, 0x1f, 0x04, 0x10, + 0x28, 0xf0, 0x84, 0xc0, 0x96, 0x0e, 0xef, 0xf3, 0x81, 0xc1, 0x1c, 0xb7, + 0x22, 0xf0, 0x84, 0xc0, 0x7e, 0x09, 0xaf, 0xf2, 0x81, 0xc1, 0x3c, 0x1f, + 0x02, 0x10, 0x1c, 0xf0, 0x84, 0xc0, 0x3e, 0x08, 0x60, 0x00, 0x81, 0xc1, + 0x23, 0xa7, 0x02, 0xa7, 0x14, 0xf0, 0x84, 0xc0, 0xca, 0x0f, 0x6f, 0xf7, + 0x81, 0xc1, 0x1e, 0xa7, 0x0e, 0xf0, 0x84, 0xc0, 0xbe, 0x0f, 0x6f, 0xf7, + 0x81, 0xc1, 0x80, 0x1f, 0x00, 0x10, 0x08, 0xf0, 0x84, 0xc0, 0x4a, 0x09, + 0xaf, 0xf2, 0x81, 0xc1, 0x98, 0x1f, 0x02, 0x10, 0x01, 0xc0, 0x8a, 0x21, + 0x3e, 0x06, 0x12, 0x70, 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, 0x01, 0x20, + 0x3d, 0x20, 0x00, 0x20, 0x1e, 0x66, 0x47, 0xf1, 0xa1, 0x40, 0xc8, 0xc7, + 0x2c, 0x70, 0x9e, 0xb9, 0x20, 0x42, 0x10, 0x71, 0x22, 0xb9, 0x3e, 0xf7, + 0x2c, 0x70, 0x0b, 0xea, 0x5b, 0x61, 0x0b, 0x08, 0xc4, 0x00, 0x62, 0x78, + 0x54, 0x79, 0x41, 0x2a, 0x82, 0x80, 0x3d, 0x79, 0xf8, 0xf5, 0xe0, 0x7f, + 0x30, 0x78, 0xe0, 0x78, 0xe0, 0x7f, 0x04, 0x18, 0x43, 0x00, 0xe0, 0x78, + 0xe2, 0xc0, 0x00, 0x1e, 0x03, 0x00, 0x20, 0x10, 0x89, 0x00, 0x0b, 0x09, + 0x51, 0x10, 0x87, 0x80, 0x86, 0xa0, 0x84, 0xeb, 0x83, 0x81, 0x87, 0xa0, + 0x21, 0x10, 0x8c, 0x00, 0x4a, 0x24, 0x00, 0x71, 0x0c, 0xec, 0x48, 0x43, + 0x0a, 0x24, 0x40, 0x11, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x13, 0x08, 0x14, + 0x04, 0x1c, 0x10, 0x12, 0x88, 0x44, 0x0b, 0xf0, 0x28, 0x43, 0xa8, 0x44, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x13, 0x08, 0x14, 0x04, 0x1c, 0x10, 0x12, + 0x68, 0x44, 0x0f, 0xec, 0x4a, 0x24, 0x00, 0x71, 0x40, 0x20, 0x0b, 0x02, + 0x0a, 0x24, 0x40, 0x11, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x13, 0x08, 0x14, + 0x04, 0x1c, 0x10, 0x12, 0x3c, 0xf0, 0x61, 0x09, 0x30, 0x10, 0x4a, 0x24, + 0x00, 0x71, 0xa5, 0x80, 0x0c, 0x15, 0x0c, 0x00, 0x04, 0x34, 0x40, 0x93, + 0x55, 0xf6, 0x87, 0x80, 0x50, 0x24, 0xfe, 0x97, 0x11, 0xf2, 0xa6, 0x80, + 0x04, 0x34, 0x40, 0x93, 0x8d, 0xf7, 0x4a, 0x24, 0x00, 0x71, 0x40, 0x20, + 0x0b, 0x02, 0xa8, 0x44, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x13, 0x08, 0x14, + 0x04, 0x1c, 0x10, 0x12, 0x1e, 0xf0, 0x4a, 0x24, 0x00, 0x71, 0x40, 0x20, + 0x0b, 0x02, 0xa8, 0x44, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x14, 0x08, 0x14, + 0x04, 0x1b, 0x10, 0x12, 0x80, 0xdc, 0x20, 0x18, 0x03, 0x00, 0x00, 0x1e, + 0x02, 0x03, 0x0e, 0xf0, 0x80, 0xdc, 0x40, 0x20, 0x0b, 0x02, 0x00, 0x1e, + 0x02, 0x03, 0xa8, 0x44, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x14, 0x08, 0x14, + 0x04, 0x1b, 0x10, 0x12, 0x04, 0x88, 0x1f, 0x08, 0x90, 0x00, 0x43, 0x08, + 0x51, 0x00, 0x8f, 0xeb, 0x4a, 0x24, 0x00, 0x71, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x11, 0x00, 0x04, 0x04, 0x1d, 0x10, 0x00, 0x10, 0xf0, 0x15, 0x0c, + 0x30, 0x00, 0x4a, 0x24, 0x00, 0x71, 0x00, 0x16, 0x80, 0x00, 0xc6, 0xb8, + 0x17, 0x00, 0x00, 0x00, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x12, 0x00, 0x04, + 0x04, 0x1d, 0x10, 0x00, 0x00, 0x16, 0x80, 0x00, 0x87, 0xb8, 0x00, 0x1e, + 0x02, 0x00, 0xc2, 0xc4, 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x39, 0x50, 0x40, + 0x08, 0x47, 0x89, 0xc0, 0x8a, 0x22, 0x0c, 0x00, 0x3a, 0x09, 0xaf, 0xe9, + 0x28, 0x45, 0x00, 0x87, 0x40, 0x24, 0x83, 0x35, 0x40, 0x24, 0x04, 0x37, + 0x40, 0x24, 0x05, 0x38, 0x40, 0x24, 0x06, 0x36, 0x40, 0x24, 0xc7, 0x35, + 0xa1, 0x41, 0x02, 0x42, 0x46, 0x0d, 0xaf, 0xf0, 0x16, 0x1c, 0x03, 0x31, + 0x07, 0xc5, 0x9b, 0x0d, 0x31, 0x10, 0x2c, 0x70, 0x17, 0x14, 0x8e, 0x30, + 0xad, 0x70, 0x8f, 0x09, 0x31, 0x00, 0xcf, 0x78, 0x16, 0x14, 0x81, 0x30, + 0x83, 0x09, 0x04, 0x00, 0x2f, 0x08, 0x30, 0x01, 0x86, 0xc1, 0x3d, 0x08, + 0xb0, 0x00, 0x86, 0xc1, 0x4b, 0x08, 0xf0, 0x00, 0x86, 0xc1, 0x57, 0x08, + 0x71, 0x00, 0x89, 0xc0, 0x86, 0xc1, 0x62, 0x0f, 0x2f, 0xf6, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x41, 0xa7, 0x22, 0xa7, 0x03, 0xa7, + 0x1d, 0xf0, 0x89, 0xc0, 0x1a, 0x0f, 0x2f, 0xf4, 0x83, 0xc2, 0x03, 0xc1, + 0x04, 0xc0, 0x2f, 0xa7, 0x10, 0xa7, 0x15, 0xf0, 0x89, 0xc0, 0x3a, 0x0f, + 0x2f, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x44, 0xa7, + 0x25, 0xa7, 0x06, 0xa7, 0x09, 0xf0, 0x89, 0xc0, 0xf2, 0x0e, 0x2f, 0xf4, + 0x83, 0xc2, 0x03, 0xc1, 0x04, 0xc0, 0x2d, 0xa7, 0x0e, 0xa7, 0x06, 0xc0, + 0x8a, 0x21, 0x3e, 0x06, 0x12, 0x70, 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, + 0x01, 0x20, 0x3d, 0x20, 0x00, 0x20, 0x1e, 0x66, 0xbb, 0xf1, 0xa1, 0x40, + 0xc8, 0xc7, 0xe0, 0x78, 0xf2, 0xc3, 0xaf, 0xc1, 0x4a, 0x24, 0xc0, 0x70, + 0x54, 0x20, 0x02, 0x0a, 0x08, 0x46, 0x55, 0x20, 0x0f, 0x08, 0x50, 0x40, + 0xa8, 0x20, 0x40, 0x02, 0x60, 0x82, 0x04, 0x11, 0x00, 0x04, 0x01, 0x30, + 0xc0, 0x00, 0x04, 0x1a, 0x10, 0x00, 0x20, 0x82, 0x0c, 0x70, 0x61, 0x69, + 0x87, 0xe1, 0x7c, 0x02, 0x2b, 0x00, 0x60, 0xa2, 0x16, 0x41, 0x00, 0x10, + 0x0c, 0x20, 0x0e, 0x42, 0x4a, 0x24, 0xc0, 0x70, 0x48, 0x33, 0x86, 0x00, + 0x48, 0xc1, 0x40, 0x24, 0x08, 0x33, 0x40, 0x24, 0x0b, 0x36, 0xc3, 0x43, + 0xfa, 0x44, 0x00, 0x00, 0x4a, 0x21, 0x00, 0x00, 0x46, 0xc4, 0x47, 0xc2, + 0xa8, 0x20, 0x00, 0x04, 0xf0, 0x23, 0x42, 0x10, 0x15, 0x20, 0x4c, 0x10, + 0x24, 0x71, 0x07, 0x32, 0x89, 0x01, 0x60, 0x42, 0x04, 0x31, 0xc0, 0x90, + 0xca, 0x22, 0x45, 0x02, 0x00, 0x1c, 0x80, 0x10, 0x4a, 0x24, 0xc0, 0x70, + 0xa8, 0x20, 0xc0, 0x03, 0xf0, 0x20, 0x02, 0x10, 0xc3, 0x41, 0xfa, 0xc4, + 0x00, 0x00, 0x15, 0x23, 0x03, 0x10, 0x04, 0x32, 0x40, 0x80, 0x04, 0x71, + 0xca, 0x21, 0x89, 0x00, 0x20, 0xa3, 0x6c, 0x4e, 0xfc, 0x4e, 0x54, 0x26, + 0x83, 0x18, 0x86, 0xc2, 0x40, 0x24, 0x04, 0x33, 0x40, 0x24, 0x05, 0x30, + 0xb6, 0x0c, 0x20, 0x02, 0x80, 0xc5, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, + 0x51, 0xa6, 0x32, 0xa6, 0x13, 0xa6, 0x04, 0x6e, 0xa8, 0x4e, 0x40, 0x26, + 0x03, 0x17, 0x83, 0xc2, 0x40, 0x24, 0x04, 0x30, 0x40, 0x24, 0x05, 0x39, + 0x96, 0x0d, 0x20, 0x02, 0x70, 0x41, 0x89, 0xc1, 0x18, 0xda, 0x96, 0x0f, + 0x6f, 0xe9, 0x22, 0x40, 0x01, 0x87, 0x00, 0xc3, 0x01, 0xc2, 0x02, 0xc1, + 0x4a, 0x24, 0xc0, 0x70, 0x54, 0x26, 0x12, 0x1c, 0x04, 0x77, 0x78, 0xa6, + 0x59, 0xa6, 0x3a, 0xa6, 0x04, 0x1f, 0x00, 0x10, 0xa8, 0x20, 0x00, 0x02, + 0x04, 0x12, 0x00, 0x24, 0x00, 0x30, 0x00, 0x00, 0x04, 0x1d, 0x10, 0x10, + 0x80, 0xc0, 0x66, 0x0b, 0x6f, 0xf8, 0x80, 0xc5, 0x4a, 0x24, 0xc0, 0x70, + 0x2f, 0x34, 0x00, 0x20, 0x83, 0xc1, 0xa8, 0x20, 0x40, 0x02, 0x04, 0x11, + 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x04, 0x1d, 0x10, 0x10, 0x80, 0xc0, + 0x42, 0x0b, 0x6f, 0xf8, 0x40, 0x24, 0x15, 0x30, 0x4a, 0x24, 0xc0, 0x70, + 0x2f, 0x33, 0x00, 0x20, 0x4a, 0x20, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x04, + 0x08, 0x45, 0x40, 0x24, 0x11, 0x33, 0x15, 0x26, 0x00, 0x10, 0xf0, 0x21, + 0x41, 0x23, 0x18, 0x80, 0x15, 0x25, 0x42, 0x23, 0x00, 0x30, 0x41, 0x00, + 0x01, 0x6d, 0x20, 0xa2, 0x80, 0xc0, 0x0e, 0x0b, 0x6f, 0xf8, 0x00, 0x34, + 0xd5, 0x24, 0x07, 0x30, 0x40, 0x05, 0x74, 0x16, 0x8b, 0x10, 0x00, 0x30, + 0x88, 0x0f, 0x7a, 0x44, 0x00, 0x00, 0x23, 0x0b, 0x11, 0x10, 0x04, 0x30, + 0x80, 0x9f, 0x6d, 0x44, 0x66, 0xc6, 0xcb, 0xf6, 0x04, 0xc0, 0xf0, 0x21, + 0x41, 0x23, 0x6d, 0x71, 0x74, 0x1e, 0x43, 0x10, 0x1e, 0xa6, 0x3f, 0xa6, + 0x02, 0xf0, 0x04, 0xc0, 0x03, 0xc4, 0x50, 0x20, 0xc2, 0x07, 0x50, 0x24, + 0xc1, 0x17, 0x02, 0x31, 0x82, 0x00, 0xc3, 0x41, 0xab, 0x43, 0x00, 0x00, + 0x04, 0x32, 0x40, 0x80, 0xb0, 0x00, 0x2d, 0x00, 0x04, 0x34, 0x40, 0x90, + 0x4f, 0xf7, 0x04, 0x34, 0x80, 0x9f, 0xfa, 0xc3, 0x00, 0x00, 0xd1, 0xf6, + 0x04, 0x30, 0x80, 0x8f, 0xae, 0xc2, 0x67, 0x66, 0xcb, 0xf6, 0x04, 0x30, + 0x80, 0x8f, 0x6a, 0x44, 0xcd, 0xec, 0x8c, 0x00, 0x06, 0x00, 0xf0, 0x21, + 0x42, 0x23, 0x04, 0x32, 0x40, 0x80, 0x80, 0x00, 0x2c, 0x00, 0x2c, 0x70, + 0x61, 0x87, 0x97, 0x0b, 0x73, 0x00, 0x20, 0xa7, 0x8f, 0x0b, 0x10, 0x10, + 0x04, 0x34, 0x80, 0xaf, 0x48, 0x44, 0x00, 0x00, 0xc5, 0xf6, 0x04, 0x33, + 0x80, 0xaf, 0x54, 0x44, 0x00, 0x80, 0x7a, 0x00, 0x0c, 0x00, 0x04, 0x33, + 0x80, 0xaf, 0x96, 0x44, 0x00, 0x00, 0x58, 0xf7, 0x46, 0x43, 0x04, 0x30, + 0xc0, 0x90, 0x54, 0xf7, 0x00, 0x30, 0x03, 0x00, 0x00, 0x34, 0x0c, 0x13, + 0x02, 0x36, 0xc3, 0x70, 0x74, 0x49, 0x00, 0x24, 0x02, 0x33, 0x03, 0x03, + 0x2f, 0x33, 0xc0, 0x00, 0x01, 0x33, 0x83, 0x0f, 0x96, 0x42, 0x00, 0x00, + 0x04, 0x32, 0xc0, 0x80, 0x3e, 0x00, 0x06, 0x00, 0x7c, 0x86, 0x2d, 0xeb, + 0x7e, 0x86, 0x04, 0x30, 0xc0, 0x80, 0xd9, 0xf6, 0x1f, 0x86, 0x04, 0x32, + 0x00, 0x80, 0x55, 0xf7, 0x74, 0x1e, 0x03, 0x10, 0x2c, 0x71, 0x11, 0xf0, + 0x1c, 0x86, 0x1f, 0x08, 0x71, 0x00, 0x2c, 0x70, 0x00, 0x87, 0x41, 0x68, + 0x13, 0x08, 0x72, 0x01, 0x40, 0xa7, 0xc3, 0x40, 0x58, 0x44, 0x00, 0x80, + 0x00, 0x1a, 0x00, 0x20, 0x3c, 0xa6, 0x48, 0x8f, 0x0c, 0x70, 0x0c, 0x18, + 0x00, 0x20, 0x08, 0x18, 0x00, 0x20, 0x04, 0x18, 0x00, 0x20, 0x11, 0x09, + 0xa0, 0x00, 0x00, 0x18, 0x00, 0x20, 0x28, 0xaf, 0x02, 0xe9, 0x81, 0xd8, + 0xd2, 0xc7, 0xc3, 0x40, 0x62, 0x44, 0x33, 0x93, 0x2c, 0x71, 0x00, 0x1a, + 0x00, 0x20, 0x70, 0x1e, 0x41, 0x10, 0x74, 0x1e, 0x03, 0x10, 0xe7, 0xf1, + 0xec, 0xc3, 0xa2, 0xc1, 0x08, 0x46, 0x04, 0x16, 0x00, 0x14, 0x60, 0x44, + 0x40, 0x24, 0xc3, 0x30, 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, + 0x48, 0x47, 0x28, 0x45, 0x1e, 0x0a, 0xaf, 0xf0, 0x03, 0x1c, 0x03, 0x31, + 0x02, 0x14, 0x80, 0x30, 0x40, 0x26, 0x10, 0x13, 0x40, 0x26, 0x11, 0x1c, + 0x40, 0x26, 0x12, 0x1e, 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0x4d, 0x09, + 0x04, 0x00, 0x23, 0x08, 0x30, 0x01, 0x81, 0xc3, 0x1f, 0x08, 0xb0, 0x00, + 0x81, 0xc3, 0x27, 0x08, 0xf0, 0x00, 0x81, 0xc3, 0x29, 0x08, 0x71, 0x00, + 0x81, 0xc3, 0xe1, 0x42, 0xc1, 0x40, 0xa1, 0x41, 0x06, 0xf0, 0x42, 0x40, + 0x08, 0xf0, 0x02, 0x40, 0xa1, 0x41, 0xe1, 0x42, 0xea, 0x0b, 0x0f, 0xf6, + 0x06, 0xf0, 0x22, 0x40, 0xa1, 0x41, 0xb2, 0x0b, 0x2f, 0xf4, 0xe1, 0x42, + 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, 0x02, 0x1c, 0x02, 0x30, 0xda, 0xf1, + 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, 0x00, 0xad, 0x21, 0xad, 0xcc, 0xc7, + 0xe2, 0xc2, 0x60, 0x40, 0x2c, 0x70, 0x10, 0xda, 0x5e, 0x0b, 0x6f, 0xf7, + 0x88, 0x45, 0x00, 0x1d, 0x01, 0x10, 0xc2, 0xc6, 0xec, 0xc3, 0xa2, 0xc1, + 0x08, 0x46, 0x50, 0x16, 0x00, 0x14, 0x60, 0x44, 0x40, 0x24, 0xc3, 0x30, + 0x40, 0x24, 0x05, 0x31, 0x40, 0x24, 0x86, 0x30, 0x48, 0x47, 0x28, 0x45, + 0x7a, 0x09, 0xaf, 0xf0, 0x03, 0x1c, 0x43, 0x33, 0x02, 0x14, 0x80, 0x30, + 0x40, 0x26, 0x11, 0x14, 0x42, 0x26, 0x12, 0x13, 0x42, 0x26, 0x10, 0x1d, + 0x03, 0x14, 0x81, 0x30, 0x0f, 0x78, 0xab, 0x09, 0x24, 0x00, 0x04, 0x77, + 0x97, 0x08, 0x55, 0x03, 0x25, 0x20, 0x00, 0x00, 0x0d, 0xf0, 0x14, 0xf0, + 0x15, 0xf0, 0x1c, 0xf0, 0x1c, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x25, 0xf0, + 0x25, 0xf0, 0x27, 0xf0, 0x28, 0xf0, 0x2f, 0xf0, 0x35, 0xf0, 0x81, 0xc3, + 0x02, 0x40, 0xa1, 0x41, 0x06, 0x0e, 0x20, 0x03, 0xe1, 0x42, 0x35, 0xf0, + 0x81, 0xc3, 0xc1, 0x40, 0x03, 0xf0, 0x81, 0xc3, 0x22, 0x40, 0xa1, 0x41, + 0xa2, 0x0b, 0xef, 0xf4, 0xe1, 0x42, 0x2b, 0xf0, 0x03, 0x86, 0x15, 0xf0, + 0x07, 0x86, 0x05, 0xf0, 0x0a, 0x86, 0x03, 0xf0, 0x0b, 0x86, 0x81, 0xc3, + 0xa1, 0x41, 0x1e, 0x09, 0xef, 0xf4, 0xe1, 0x42, 0x1d, 0xf0, 0x08, 0x86, + 0x07, 0xf0, 0x0d, 0x86, 0x05, 0xf0, 0x24, 0x16, 0x80, 0x10, 0x0b, 0xf0, + 0x0c, 0x86, 0x81, 0xc3, 0xa1, 0x41, 0x0e, 0x0e, 0xaf, 0xec, 0xe1, 0x42, + 0x0f, 0xf0, 0x38, 0x16, 0x80, 0x10, 0x81, 0xc3, 0xa1, 0x41, 0xde, 0x0a, + 0x6f, 0xf2, 0xe1, 0x42, 0x07, 0xf0, 0x81, 0xc3, 0x42, 0x40, 0xa1, 0x41, + 0xde, 0x0a, 0x2f, 0xf6, 0xe1, 0x42, 0x02, 0x14, 0x80, 0x30, 0x04, 0x71, + 0x02, 0x1c, 0x02, 0x30, 0xaa, 0xf1, 0x01, 0xc0, 0x41, 0x28, 0x01, 0x02, + 0x00, 0xad, 0x21, 0xad, 0xcc, 0xc7, 0xe0, 0x78, 0xf9, 0x03, 0x80, 0x00, + 0xe8, 0xc3, 0x82, 0x24, 0x0c, 0x3d, 0x50, 0x40, 0x08, 0x47, 0x8d, 0xc0, + 0x8a, 0x22, 0x0c, 0x00, 0x0a, 0x0c, 0x6f, 0xe9, 0x28, 0x45, 0x1c, 0x17, + 0x00, 0x14, 0x40, 0x24, 0x83, 0x33, 0x40, 0x24, 0x04, 0x35, 0x40, 0x24, + 0x05, 0x3c, 0x40, 0x24, 0x06, 0x34, 0x40, 0x24, 0xc7, 0x33, 0xa1, 0x41, + 0x02, 0x42, 0x16, 0x08, 0xaf, 0xf0, 0x0e, 0x1c, 0x43, 0x33, 0x05, 0xc5, + 0xb5, 0x70, 0x92, 0xf4, 0x0f, 0x14, 0x8e, 0x30, 0xad, 0x70, 0x2c, 0x70, + 0x34, 0x70, 0x8c, 0xf4, 0x0e, 0x14, 0x81, 0x30, 0xcf, 0x78, 0x30, 0x70, + 0x0c, 0x01, 0x2d, 0x00, 0x04, 0x77, 0xf1, 0x08, 0x55, 0x03, 0x25, 0x20, + 0x00, 0x00, 0x0e, 0xf0, 0x17, 0xf0, 0x23, 0xf0, 0x2d, 0xf0, 0x33, 0xf0, + 0x37, 0xf0, 0x3d, 0xf0, 0x41, 0xf0, 0x47, 0xf0, 0x4b, 0xf0, 0x52, 0xf0, + 0x56, 0xf0, 0x5d, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0xde, 0x0c, 0x20, 0x03, + 0x86, 0xc2, 0x86, 0xc1, 0x18, 0xda, 0x92, 0x0b, 0x6f, 0xe9, 0xe1, 0x40, + 0x5c, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0x7a, 0x0a, 0xef, 0xf4, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x4d, 0xa7, 0x2e, 0xa7, 0x0f, 0xa7, + 0x50, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0x62, 0x0a, 0xef, 0xf4, 0x80, 0xc2, + 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x51, 0xa7, 0x32, 0xa7, 0x13, 0xa7, + 0x44, 0xf0, 0x8d, 0xc0, 0xea, 0x0c, 0xaf, 0xec, 0x84, 0xc1, 0x10, 0xa7, + 0x3e, 0xf0, 0x8d, 0xc0, 0xd2, 0x0f, 0xaf, 0xf4, 0x84, 0xc1, 0x14, 0xa7, + 0x38, 0xf0, 0x8d, 0xc0, 0xc6, 0x0f, 0xaf, 0xf4, 0x84, 0xc1, 0x17, 0xa7, + 0x32, 0xf0, 0x8d, 0xc0, 0xba, 0x0f, 0xaf, 0xf4, 0x84, 0xc1, 0x18, 0xa7, + 0x2c, 0xf0, 0x8d, 0xc0, 0xba, 0x0c, 0xaf, 0xec, 0x84, 0xc1, 0x15, 0xa7, + 0x26, 0xf0, 0x8d, 0xc0, 0xae, 0x0c, 0xaf, 0xec, 0x84, 0xc1, 0x1a, 0xa7, + 0x20, 0xf0, 0x8d, 0xc0, 0x92, 0x09, 0x6f, 0xf2, 0x84, 0xc1, 0x58, 0x1f, + 0x02, 0x10, 0x1a, 0xf0, 0x8d, 0xc0, 0x96, 0x0c, 0xaf, 0xec, 0x84, 0xc1, + 0x19, 0xa7, 0x14, 0xf0, 0x8d, 0xc0, 0x7a, 0x09, 0x6f, 0xf2, 0x84, 0xc1, + 0x6c, 0x1f, 0x02, 0x10, 0x0c, 0xf0, 0x8d, 0xc0, 0x84, 0xc1, 0x6a, 0x09, + 0x2f, 0xf6, 0x80, 0xc2, 0x00, 0xc2, 0x01, 0xc1, 0x02, 0xc0, 0x4a, 0xa7, + 0x2b, 0xa7, 0x0c, 0xa7, 0x04, 0xc0, 0x8a, 0x21, 0x3e, 0x06, 0x12, 0x70, + 0xca, 0x25, 0x4d, 0x10, 0x3c, 0x20, 0x01, 0x20, 0x3d, 0x20, 0x00, 0x20, + 0x1e, 0x66, 0x76, 0xf1, 0xa1, 0x40, 0xc8, 0xc7, 0xe0, 0x7e, 0xe0, 0x78, + 0xe4, 0xc3, 0xa2, 0xc1, 0xa0, 0x81, 0x28, 0x46, 0x08, 0xda, 0xb9, 0x60, + 0xa6, 0x0a, 0x6f, 0xe9, 0x80, 0xc0, 0x01, 0xc1, 0x00, 0xc0, 0x08, 0xe5, + 0xa0, 0xa6, 0xc4, 0xc7, 0x80, 0x83, 0x85, 0x72, 0x27, 0x0a, 0x24, 0x03, + 0xa1, 0xc1, 0x4c, 0x70, 0x02, 0x1c, 0x04, 0x30, 0x00, 0x83, 0x40, 0x24, + 0x8c, 0x30, 0x4c, 0x64, 0x58, 0x60, 0x54, 0x71, 0x4c, 0x71, 0x38, 0x60, + 0x80, 0xa8, 0xf8, 0xf5, 0x00, 0x83, 0x04, 0x72, 0x00, 0xa3, 0xe0, 0x7f, + 0x87, 0x74, 0xe0, 0x78, 0xee, 0xc2, 0x70, 0x43, 0x48, 0x47, 0x10, 0x40, + 0xc4, 0xe1, 0xd8, 0x00, 0x25, 0x00, 0xcd, 0x70, 0xcb, 0x45, 0xa0, 0x00, + 0xd0, 0x86, 0x00, 0x8d, 0x0b, 0x08, 0x71, 0x00, 0xff, 0xd8, 0x08, 0x8d, + 0x04, 0xf0, 0x00, 0x1d, 0x43, 0x10, 0x08, 0xad, 0xd3, 0x42, 0xa0, 0x00, + 0x64, 0xe1, 0x0f, 0x08, 0x21, 0x04, 0x4c, 0x20, 0x40, 0xa9, 0xc3, 0x85, + 0x20, 0xf0, 0xc3, 0x40, 0x12, 0x00, 0xec, 0x4a, 0xcb, 0x44, 0x12, 0x00, + 0xf0, 0x4a, 0xca, 0x24, 0x01, 0x10, 0x40, 0x25, 0x06, 0x11, 0xc3, 0x40, + 0xa0, 0x00, 0x8c, 0x86, 0x8a, 0x23, 0x10, 0x00, 0xc3, 0x44, 0xa0, 0x00, + 0x64, 0xe5, 0x8a, 0x25, 0x08, 0x00, 0x42, 0x42, 0x23, 0x20, 0x00, 0x03, + 0x02, 0x41, 0xcd, 0x70, 0x03, 0xe8, 0xc0, 0xad, 0x38, 0xf0, 0xc3, 0xa5, + 0x08, 0x1d, 0x02, 0x14, 0x7f, 0xd8, 0xc4, 0x78, 0x00, 0xaf, 0x01, 0x85, + 0x76, 0x6e, 0x54, 0x23, 0x01, 0x08, 0x40, 0xda, 0x70, 0x41, 0x10, 0x71, + 0x40, 0xd9, 0x8a, 0xf7, 0x4f, 0x26, 0xc0, 0x11, 0x00, 0xaf, 0x01, 0x85, + 0x00, 0x1d, 0x03, 0x10, 0x02, 0x20, 0x41, 0x04, 0x21, 0xaf, 0x01, 0x85, + 0x2f, 0x20, 0x47, 0x20, 0x02, 0x22, 0x02, 0x04, 0x02, 0xaf, 0x01, 0x85, + 0x4c, 0x20, 0xc0, 0xaf, 0x00, 0x27, 0x01, 0x14, 0x28, 0xb8, 0xca, 0x22, + 0x2d, 0x00, 0x03, 0xaf, 0x04, 0x69, 0xea, 0x0f, 0x2f, 0xf7, 0x2c, 0x70, + 0x00, 0x21, 0x81, 0x24, 0x04, 0x6f, 0x9a, 0x09, 0x6f, 0xe9, 0x02, 0x42, + 0x21, 0x6e, 0x44, 0xd8, 0xcd, 0x71, 0x23, 0xa5, 0x00, 0x1b, 0x04, 0x20, + 0xc1, 0x40, 0xce, 0xc6, 0xea, 0xc2, 0x48, 0x47, 0x10, 0x40, 0xc4, 0xe1, + 0xa0, 0x00, 0x25, 0x00, 0x2c, 0x70, 0xcb, 0x45, 0xa0, 0x00, 0xd0, 0x86, + 0x00, 0x8d, 0x0d, 0x08, 0xb1, 0x00, 0xff, 0xd8, 0x09, 0x8d, 0x05, 0xf0, + 0x00, 0x1d, 0x83, 0x10, 0x09, 0xad, 0x0b, 0x08, 0x01, 0x04, 0xc1, 0x85, + 0x08, 0xf0, 0xc3, 0x8f, 0x02, 0x8f, 0x09, 0x1d, 0x02, 0x14, 0x08, 0xbe, + 0x05, 0x7e, 0xc1, 0xa5, 0x8c, 0x26, 0x10, 0x90, 0x62, 0x00, 0x0d, 0x00, + 0x00, 0x8f, 0x41, 0x8f, 0xc6, 0xb8, 0x36, 0x68, 0x58, 0x61, 0x57, 0x0e, + 0x04, 0x10, 0xd3, 0x41, 0xa0, 0x00, 0x64, 0xe1, 0x00, 0x21, 0x40, 0x04, + 0x26, 0x09, 0x6f, 0xe9, 0x24, 0x6f, 0x00, 0x17, 0xc0, 0x10, 0x3b, 0x08, + 0x33, 0x00, 0x4c, 0x20, 0x40, 0xa9, 0xc3, 0x40, 0x12, 0x00, 0xf4, 0x4a, + 0xcb, 0x47, 0x12, 0x00, 0xf8, 0x4a, 0xca, 0x27, 0x01, 0x10, 0xc3, 0x40, + 0xa0, 0x00, 0x8c, 0x86, 0xc3, 0x43, 0xa0, 0x00, 0x64, 0xe5, 0x8a, 0x24, + 0x08, 0x00, 0x22, 0x41, 0x23, 0x20, 0xc0, 0x03, 0xc1, 0x42, 0x2c, 0x70, + 0x00, 0x1d, 0x03, 0x10, 0x86, 0xe8, 0x2c, 0x71, 0x04, 0xf0, 0x2c, 0x70, + 0x00, 0x1d, 0x03, 0x10, 0x20, 0x40, 0xca, 0xc6, 0xe2, 0xc2, 0x08, 0x44, + 0xfd, 0xe0, 0x68, 0x45, 0x09, 0xf2, 0xfe, 0xe4, 0x0c, 0xf4, 0x40, 0x40, + 0xdf, 0x59, 0x00, 0x1d, 0x05, 0x11, 0x0c, 0x71, 0x11, 0xf0, 0x25, 0xd8, + 0x56, 0x0e, 0xef, 0xff, 0xa1, 0x43, 0x0d, 0xf0, 0xbf, 0xe4, 0x0c, 0x70, + 0x09, 0xf7, 0x15, 0x0c, 0x50, 0x10, 0x15, 0x0c, 0x50, 0x11, 0x0b, 0x0c, + 0xd1, 0x10, 0x21, 0xd8, 0xf2, 0xf1, 0xc2, 0xc6, 0x20, 0xd8, 0xf0, 0xf1, + 0x22, 0xd8, 0xee, 0xf1, 0xf1, 0xc0, 0x00, 0x43, 0xfd, 0xe0, 0x06, 0xf4, + 0x25, 0xd8, 0x0a, 0x0f, 0xcf, 0xff, 0x0d, 0xf0, 0xbf, 0xe3, 0x0c, 0x70, + 0x09, 0xf7, 0x17, 0x0b, 0x50, 0x00, 0x17, 0x0b, 0x50, 0x01, 0x0b, 0x0b, + 0xd1, 0x00, 0x21, 0xd8, 0xf3, 0xf1, 0xd1, 0xc0, 0xe0, 0x7e, 0x20, 0xd8, + 0xef, 0xf1, 0x22, 0xd8, 0xed, 0xf1, 0xe0, 0x78, 0xe4, 0xc3, 0xa1, 0xc1, + 0x80, 0xc0, 0xc3, 0x41, 0x13, 0x00, 0x58, 0x90, 0x52, 0x08, 0x6f, 0xe9, + 0x4c, 0x74, 0x3b, 0x58, 0x08, 0x46, 0x28, 0x45, 0xfe, 0xd8, 0x80, 0xc1, + 0x8c, 0x70, 0xc1, 0x42, 0xa1, 0x43, 0x6b, 0x58, 0xf8, 0xd8, 0x80, 0xc1, + 0x8c, 0x70, 0xc1, 0x42, 0xa1, 0x43, 0x6b, 0x58, 0xc3, 0x40, 0xf0, 0x00, + 0x3f, 0x00, 0x20, 0x88, 0x84, 0xb9, 0x20, 0xa8, 0xc4, 0xc7, 0xe0, 0x78, + 0x09, 0x08, 0x12, 0x00, 0xe0, 0x7f, 0x39, 0x78, 0x12, 0x78, 0x39, 0x78, + 0xe0, 0x7f, 0x12, 0x78, 0xe6, 0xc2, 0x08, 0x45, 0x12, 0x18, 0x85, 0x07, + 0x28, 0xda, 0x0c, 0x18, 0x01, 0x05, 0x68, 0x18, 0x81, 0x02, 0xc3, 0x41, + 0xc0, 0x49, 0x00, 0x92, 0xc3, 0x40, 0x07, 0x49, 0x00, 0x24, 0x40, 0x25, + 0x0e, 0x17, 0x64, 0x1d, 0x81, 0x12, 0x58, 0x1d, 0xc3, 0x10, 0x50, 0xad, + 0x22, 0xa5, 0x01, 0xa5, 0x2c, 0x70, 0x3c, 0xda, 0x1e, 0x0e, 0x2f, 0xf7, + 0xc1, 0x40, 0x96, 0x0f, 0xef, 0xef, 0xc1, 0x40, 0x1a, 0x85, 0x19, 0x08, + 0x72, 0x02, 0xed, 0x70, 0x19, 0x85, 0x11, 0x08, 0x70, 0x02, 0xc1, 0x40, + 0x7e, 0x0f, 0xef, 0xef, 0x64, 0x1d, 0x41, 0x12, 0x09, 0x95, 0xc3, 0x43, + 0xc8, 0x42, 0x00, 0x00, 0xcb, 0x44, 0x83, 0x3a, 0x6f, 0x12, 0x48, 0x30, + 0x00, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x00, 0x30, 0x00, 0x03, 0x04, 0x30, + 0xc0, 0x83, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, + 0xc0, 0x02, 0x30, 0x8d, 0x10, 0x7a, 0x8b, 0xe2, 0x48, 0x31, 0x01, 0x00, + 0xca, 0x20, 0xa6, 0x02, 0x10, 0x78, 0x00, 0x31, 0xc1, 0x00, 0x48, 0x20, + 0xc0, 0x00, 0x0c, 0xb5, 0x9a, 0x0d, 0xaf, 0xf3, 0x00, 0x31, 0x00, 0x03, + 0x48, 0x30, 0xc0, 0x02, 0x05, 0xa5, 0xc6, 0xc6, 0xe6, 0xc2, 0x08, 0x45, + 0x8a, 0x20, 0x0a, 0x00, 0xcb, 0x46, 0x16, 0x43, 0x00, 0x00, 0xc3, 0x41, + 0xfd, 0x44, 0x00, 0x20, 0x10, 0xb5, 0xc7, 0xa5, 0x24, 0xa5, 0x01, 0xa5, + 0xfe, 0x0f, 0xef, 0xea, 0x55, 0x25, 0x40, 0x1c, 0xf2, 0x09, 0x2f, 0xeb, + 0x56, 0x25, 0x80, 0x1a, 0x4a, 0x24, 0x00, 0x74, 0x56, 0x25, 0x01, 0x1d, + 0x0a, 0x20, 0x80, 0x0f, 0x13, 0x00, 0x34, 0x6b, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x10, 0x02, 0x04, 0x04, 0x19, 0x90, 0x00, 0x67, 0x85, 0x21, 0x85, + 0xcb, 0x43, 0x10, 0x42, 0x00, 0x00, 0x07, 0x36, 0xc8, 0x70, 0x80, 0x3f, + 0x00, 0x00, 0x8b, 0x1d, 0x98, 0x13, 0x48, 0x31, 0x81, 0x00, 0xc3, 0x40, + 0x48, 0x44, 0x00, 0x00, 0xcb, 0x46, 0x48, 0x41, 0x00, 0x00, 0x78, 0x1d, + 0xd8, 0x12, 0x8a, 0x1d, 0x18, 0x10, 0x00, 0x31, 0x80, 0x03, 0xcb, 0x47, + 0x83, 0x3a, 0x6f, 0x12, 0x00, 0x30, 0xc0, 0x03, 0x2d, 0x70, 0xc3, 0x42, + 0x96, 0x44, 0x00, 0x00, 0xcb, 0x44, 0x1c, 0x49, 0x00, 0x40, 0xc3, 0x43, + 0xaf, 0x49, 0x00, 0xc8, 0x04, 0x30, 0x40, 0x82, 0x89, 0x1d, 0x98, 0x10, + 0x86, 0xa5, 0x65, 0xa5, 0xc4, 0x1d, 0x00, 0x12, 0xc6, 0xf6, 0x01, 0x30, + 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0xbf, 0x00, 0x00, 0x30, 0x95, 0x48, 0x30, 0xc0, 0x02, 0x48, 0x30, + 0x82, 0x00, 0x48, 0x31, 0x00, 0x00, 0x00, 0x30, 0x80, 0x03, 0x48, 0x32, + 0xc1, 0x02, 0x00, 0x30, 0xc0, 0x03, 0x49, 0x21, 0x01, 0x02, 0x48, 0x21, + 0x01, 0x01, 0x04, 0x30, 0x40, 0x82, 0x22, 0xa5, 0xc6, 0xf6, 0x01, 0x30, + 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc0, 0x02, 0x48, 0x30, 0x80, 0x00, + 0x48, 0x30, 0xc0, 0x02, 0x49, 0x20, 0x40, 0x06, 0x48, 0x20, 0x00, 0x01, + 0x09, 0xa5, 0x0e, 0x08, 0x20, 0x00, 0xa1, 0x40, 0xc6, 0xc6, 0xe0, 0x78, + 0xe8, 0xc3, 0xa4, 0xc1, 0x4a, 0x24, 0x00, 0x76, 0x08, 0x46, 0x40, 0x20, + 0x0d, 0x0b, 0x0c, 0x70, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1d, 0x11, 0x10, + 0x4a, 0x24, 0x80, 0x77, 0x53, 0x1e, 0x59, 0x10, 0xcc, 0x1e, 0x00, 0x10, + 0x0c, 0x1e, 0x00, 0x10, 0x55, 0x26, 0x00, 0x1d, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x18, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x55, 0x26, 0x4f, 0x1a, + 0x0a, 0x20, 0xc0, 0x03, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, + 0x00, 0x18, 0x03, 0x00, 0x56, 0x26, 0x80, 0x1a, 0x06, 0x09, 0x2f, 0xeb, + 0x10, 0x40, 0x41, 0x87, 0x02, 0x87, 0x60, 0x87, 0xc3, 0x41, 0x7a, 0x44, + 0x00, 0x00, 0x43, 0xc1, 0x41, 0xc2, 0x42, 0xc0, 0x80, 0xc1, 0x10, 0xda, + 0x02, 0x40, 0xd2, 0x0d, 0x2f, 0xe9, 0x40, 0xc3, 0x4a, 0x24, 0x00, 0x74, + 0x56, 0x26, 0x00, 0x1b, 0xc3, 0x41, 0x13, 0x00, 0x74, 0x6b, 0x00, 0x42, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x03, 0x04, 0x04, 0x1a, 0xd0, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1d, 0x11, 0x10, + 0x4a, 0x24, 0xc0, 0x70, 0x0a, 0x21, 0x80, 0x0f, 0x7a, 0xc4, 0x00, 0x00, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1d, 0x50, 0x10, 0x80, 0xc1, 0xb1, 0x1e, + 0x43, 0x10, 0x0e, 0x0e, 0x60, 0x00, 0x28, 0x1e, 0x01, 0x10, 0x55, 0x26, + 0x40, 0x1b, 0x80, 0xc1, 0x7a, 0x0d, 0x2f, 0xe9, 0x10, 0xda, 0xc8, 0xc7, + 0xf0, 0xc3, 0x82, 0x24, 0x06, 0x3e, 0x08, 0x46, 0x54, 0x20, 0x00, 0x09, + 0x2c, 0x70, 0x14, 0xda, 0xa6, 0x0b, 0x2f, 0xf7, 0x8a, 0x21, 0x8e, 0x21, + 0x4a, 0x24, 0x40, 0x71, 0x54, 0x26, 0x92, 0x1b, 0x00, 0x21, 0x91, 0x23, + 0x4a, 0x20, 0x00, 0x20, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1a, 0x11, 0x20, + 0x2c, 0x70, 0x28, 0x47, 0x8f, 0xbf, 0x40, 0xdc, 0x00, 0x19, 0x02, 0x24, + 0xfe, 0x19, 0x04, 0xa4, 0xfc, 0x19, 0x04, 0xa4, 0x47, 0x09, 0x75, 0x01, + 0x15, 0x26, 0x43, 0x10, 0x4d, 0x83, 0x1d, 0x0a, 0x70, 0x01, 0x14, 0x26, + 0x40, 0x10, 0x23, 0x0a, 0x51, 0x02, 0x52, 0x18, 0x04, 0x04, 0x48, 0x18, + 0x04, 0x04, 0x7f, 0xd8, 0x17, 0xb8, 0x10, 0xf0, 0x52, 0x18, 0xc4, 0x03, + 0x48, 0x18, 0x04, 0x03, 0x4f, 0xd8, 0x18, 0xb8, 0x08, 0xf0, 0x52, 0x18, + 0xc4, 0x03, 0x48, 0x18, 0x04, 0x03, 0xc3, 0x40, 0x7f, 0x7f, 0xff, 0xff, + 0x17, 0xa3, 0x24, 0x71, 0xde, 0xf1, 0x8a, 0x20, 0x07, 0x0d, 0xd8, 0x60, + 0x2c, 0x70, 0x26, 0x0b, 0x2f, 0xf7, 0x8a, 0x22, 0x06, 0x00, 0x8c, 0x20, + 0xc1, 0xa7, 0x94, 0x00, 0x2d, 0x00, 0xad, 0x70, 0x15, 0x26, 0x14, 0x14, + 0x74, 0x14, 0x02, 0x20, 0x4a, 0x24, 0x80, 0x7b, 0x0a, 0x23, 0x80, 0x2f, + 0x13, 0x00, 0xfc, 0x6c, 0x40, 0x23, 0x03, 0x23, 0xa8, 0x20, 0x80, 0x02, + 0x04, 0x13, 0x00, 0x04, 0x82, 0xc1, 0xb9, 0x61, 0xa5, 0x71, 0x38, 0x20, + 0x80, 0x00, 0x00, 0xa9, 0xea, 0x0e, 0xe0, 0x01, 0x82, 0xc0, 0x14, 0x70, + 0x0c, 0x70, 0x0a, 0xf2, 0x14, 0x26, 0x01, 0x14, 0xfa, 0x19, 0x1c, 0x00, + 0x80, 0x21, 0x0a, 0x0d, 0x00, 0xb1, 0x22, 0xf0, 0x74, 0x14, 0x03, 0x20, + 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0xc0, 0x02, 0x04, 0x13, 0x01, 0x24, + 0x40, 0x24, 0x42, 0x31, 0x1a, 0x62, 0x04, 0x71, 0x38, 0x21, 0xc1, 0x00, + 0x20, 0xaa, 0x40, 0x24, 0x40, 0x31, 0x0e, 0x0b, 0xef, 0xf3, 0x14, 0x26, + 0x0d, 0x14, 0xa1, 0x41, 0x80, 0x21, 0x0a, 0x0d, 0x04, 0xe8, 0x8a, 0x20, + 0x04, 0x00, 0x03, 0xf0, 0x40, 0xd8, 0xe0, 0xb1, 0xfa, 0x1d, 0x1c, 0x10, + 0x06, 0x71, 0xb7, 0xf1, 0x8e, 0xc0, 0x2c, 0x70, 0x8a, 0x22, 0x06, 0x00, + 0x7e, 0x0a, 0x2f, 0xf7, 0x40, 0x24, 0x10, 0x3e, 0x54, 0x26, 0x93, 0x1e, + 0x40, 0x24, 0x4f, 0x30, 0x04, 0x13, 0x00, 0x24, 0xd5, 0xe0, 0x9c, 0x00, + 0x29, 0x00, 0x4e, 0x68, 0xbc, 0xe2, 0x34, 0x01, 0x2d, 0x00, 0x2c, 0x71, + 0x0c, 0x70, 0x28, 0x43, 0x8d, 0x70, 0x25, 0x20, 0x80, 0x00, 0x69, 0xf0, + 0x90, 0xf0, 0x67, 0xf0, 0x8e, 0xf0, 0x65, 0xf0, 0x8c, 0xf0, 0x63, 0xf0, + 0x8a, 0xf0, 0x61, 0xf0, 0x88, 0xf0, 0x5f, 0xf0, 0x86, 0xf0, 0x5d, 0xf0, + 0x84, 0xf0, 0x84, 0xf0, 0x82, 0xf0, 0x82, 0xf0, 0x80, 0xf0, 0x2c, 0xf0, + 0x7e, 0xf0, 0x2a, 0xf0, 0x7c, 0xf0, 0x28, 0xf0, 0x7a, 0xf0, 0x26, 0xf0, + 0x78, 0xf0, 0x24, 0xf0, 0x76, 0xf0, 0x22, 0xf0, 0x74, 0xf0, 0x20, 0xf0, + 0x72, 0xf0, 0x72, 0xf0, 0x70, 0xf0, 0x70, 0xf0, 0x6e, 0xf0, 0x2f, 0xf0, + 0x6c, 0xf0, 0x2d, 0xf0, 0x6a, 0xf0, 0x2b, 0xf0, 0x68, 0xf0, 0x29, 0xf0, + 0x66, 0xf0, 0x27, 0xf0, 0x64, 0xf0, 0x25, 0xf0, 0x62, 0xf0, 0x23, 0xf0, + 0x60, 0xf0, 0x33, 0xf0, 0x5e, 0xf0, 0x31, 0xf0, 0x5c, 0xf0, 0x2f, 0xf0, + 0x5a, 0xf0, 0x31, 0xf0, 0x58, 0xf0, 0x2f, 0xf0, 0x56, 0xf0, 0x2d, 0xf0, + 0x0c, 0x70, 0x2c, 0x70, 0x6d, 0x71, 0x28, 0xf0, 0x8c, 0x20, 0x42, 0x8d, + 0xd1, 0xf6, 0x2c, 0x71, 0x8c, 0x20, 0x82, 0x8d, 0x44, 0xf2, 0x8c, 0x20, + 0x02, 0x8e, 0xf4, 0xf3, 0x8c, 0x20, 0x82, 0x8e, 0x42, 0xf2, 0x8c, 0x20, + 0x03, 0x80, 0x0c, 0xf2, 0x40, 0xf0, 0x0c, 0x71, 0x12, 0xf0, 0x80, 0x20, + 0xbe, 0x0a, 0x79, 0x08, 0x75, 0x01, 0x15, 0xd9, 0x71, 0x09, 0x0e, 0x00, + 0x2c, 0x71, 0x0c, 0x70, 0x28, 0x43, 0x8d, 0x71, 0x20, 0xaf, 0x01, 0xaf, + 0x02, 0xaf, 0x60, 0xc1, 0x05, 0xf0, 0x0c, 0x70, 0x2c, 0x71, 0x08, 0x43, + 0x8d, 0x71, 0x86, 0xe8, 0x04, 0xe9, 0x09, 0x0b, 0x10, 0x10, 0x95, 0xec, + 0x34, 0x70, 0xc3, 0x43, 0xcc, 0x3d, 0xcd, 0xcc, 0xc3, 0x42, 0x8b, 0x3a, + 0x58, 0xa0, 0xc3, 0x41, 0x1c, 0x41, 0x0a, 0xe8, 0x7c, 0x72, 0x75, 0x70, + 0xc3, 0x40, 0x20, 0x3c, 0x12, 0xac, 0x5c, 0x71, 0x95, 0x70, 0x3c, 0x70, + 0x40, 0xc0, 0x80, 0xc1, 0x4c, 0x74, 0x0a, 0x0b, 0x2f, 0xe9, 0x02, 0x40, + 0xa5, 0x71, 0xe0, 0xe5, 0xd4, 0x06, 0xe5, 0xff, 0x06, 0x74, 0x0e, 0xf0, + 0x0c, 0x70, 0x6d, 0x71, 0x8d, 0x70, 0xdb, 0xf1, 0x0c, 0x71, 0xd7, 0xf1, + 0x2c, 0x71, 0x0c, 0x70, 0x00, 0x1c, 0x01, 0x30, 0x28, 0x43, 0xd2, 0xf1, + 0x00, 0x12, 0x82, 0x20, 0xdf, 0x16, 0x00, 0x16, 0x0e, 0x0f, 0xef, 0xf2, + 0x8e, 0xc1, 0x7f, 0xda, 0xc3, 0x43, 0xc8, 0x42, 0x00, 0x00, 0x17, 0xba, + 0xc3, 0x41, 0x74, 0x49, 0x00, 0x24, 0xc3, 0x40, 0x7a, 0x44, 0x00, 0x00, + 0xfb, 0x19, 0x43, 0xa0, 0xde, 0x1e, 0x19, 0x10, 0xdd, 0x1e, 0xd8, 0x10, + 0x4c, 0xa6, 0x2b, 0xa6, 0x0a, 0xa6, 0xd0, 0xc7, 0xea, 0xc2, 0x10, 0x40, + 0xe2, 0x0f, 0xaf, 0xeb, 0x55, 0x20, 0x4d, 0x0a, 0x8a, 0x21, 0x44, 0x20, + 0xff, 0xdf, 0xcb, 0x41, 0x23, 0x3c, 0x0a, 0xd7, 0xc3, 0x40, 0x48, 0x43, + 0x00, 0x00, 0x83, 0xdc, 0x76, 0x18, 0x83, 0x20, 0x74, 0x18, 0x05, 0x20, + 0x8a, 0x26, 0x01, 0x09, 0xcb, 0x40, 0xa0, 0x42, 0x00, 0x00, 0xcb, 0x43, + 0x20, 0x41, 0x00, 0x00, 0x16, 0xbf, 0xcb, 0x46, 0xfa, 0x44, 0x00, 0x00, + 0xdb, 0x47, 0x0e, 0x3d, 0x4d, 0xf3, 0x0a, 0x26, 0x80, 0x3f, 0xd6, 0x3c, + 0x62, 0xa1, 0xc3, 0x45, 0x03, 0x3b, 0x6f, 0x12, 0x8a, 0x24, 0x07, 0x0d, + 0x8a, 0x27, 0x04, 0x0b, 0x17, 0xbc, 0xc3, 0x43, 0xc8, 0x41, 0x00, 0x00, + 0xc3, 0x42, 0x7a, 0x45, 0x00, 0x00, 0xc3, 0x41, 0x70, 0x41, 0x00, 0x00, + 0x68, 0x18, 0x44, 0x24, 0x70, 0x18, 0x40, 0x22, 0x6c, 0x18, 0x00, 0x20, + 0x8a, 0x20, 0x87, 0x00, 0x1f, 0xa5, 0x48, 0x1d, 0x80, 0x11, 0x44, 0x1d, + 0x00, 0x12, 0x40, 0x1d, 0xc0, 0x12, 0xef, 0xa5, 0xce, 0xa5, 0xe4, 0x1d, + 0xc0, 0x97, 0xe0, 0x1d, 0x80, 0x97, 0xdc, 0x1d, 0x40, 0x91, 0x74, 0x1d, + 0x00, 0x11, 0x64, 0x1d, 0xc0, 0x11, 0x98, 0xa5, 0x77, 0xa5, 0x56, 0xa5, + 0x29, 0xa5, 0xca, 0xc6, 0xe4, 0xc0, 0xcb, 0x46, 0x7f, 0x47, 0x00, 0xff, + 0x2d, 0xdd, 0x80, 0xdc, 0x8a, 0x23, 0x08, 0x00, 0xc3, 0x42, 0x00, 0x00, + 0xff, 0xff, 0x2c, 0x70, 0x1a, 0x18, 0xc3, 0x00, 0xc8, 0xa0, 0xae, 0xb0, + 0x8c, 0xb0, 0x65, 0xa0, 0x49, 0xb0, 0x42, 0xa0, 0x43, 0xb0, 0x26, 0xb0, + 0x27, 0xb0, 0x28, 0xb0, 0xc4, 0xc4, 0xe0, 0x78, 0xe6, 0xc2, 0x08, 0x45, + 0x1a, 0x0f, 0xef, 0xff, 0x55, 0x20, 0x8e, 0x0a, 0xfe, 0x08, 0xaf, 0xfc, + 0xa1, 0x40, 0x11, 0x86, 0xd8, 0x16, 0x01, 0x90, 0x11, 0xdb, 0x48, 0x30, + 0x80, 0x00, 0x1a, 0xbb, 0x00, 0x30, 0xc0, 0x00, 0x3b, 0xdf, 0xcb, 0x44, + 0x83, 0x3a, 0x6f, 0x12, 0x00, 0x31, 0x82, 0x0f, 0xc8, 0x42, 0x00, 0x00, + 0x18, 0xbf, 0x00, 0x30, 0x01, 0x03, 0x0d, 0x70, 0x00, 0x32, 0xc0, 0x03, + 0xcb, 0x43, 0x74, 0x45, 0x00, 0x24, 0x04, 0x31, 0x00, 0x82, 0x3c, 0x1d, + 0x43, 0x10, 0xe4, 0x1e, 0x43, 0x90, 0xfe, 0xa5, 0x04, 0x1d, 0xc0, 0x12, + 0x1f, 0xa5, 0xc7, 0xf6, 0x01, 0x31, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, + 0x05, 0xf0, 0x01, 0x31, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x38, 0x86, + 0x48, 0x30, 0xc2, 0x02, 0x48, 0x31, 0x81, 0x00, 0x00, 0x31, 0xc0, 0x00, + 0x48, 0x32, 0x81, 0x00, 0x00, 0x30, 0x00, 0x03, 0x48, 0x31, 0xc1, 0x02, + 0x04, 0x30, 0x00, 0x82, 0x32, 0xa6, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, + 0x00, 0x00, 0x3e, 0x86, 0x48, 0x30, 0xc2, 0x02, 0x6d, 0x70, 0x48, 0x31, + 0x81, 0x00, 0x00, 0x31, 0xc0, 0x00, 0x48, 0x32, 0x81, 0x00, 0x00, 0x30, + 0x00, 0x03, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x30, 0xc0, 0x82, 0x39, 0xa6, + 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x3c, 0x86, 0x48, 0x30, + 0xc2, 0x02, 0x48, 0x31, 0x81, 0x00, 0x00, 0x31, 0xc0, 0x00, 0x48, 0x32, + 0x81, 0x00, 0x00, 0x30, 0x00, 0x03, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x30, + 0xc0, 0x82, 0x3d, 0xa6, 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, + 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, + 0x48, 0x30, 0xc0, 0x02, 0x4a, 0x24, 0xc0, 0x70, 0x48, 0x30, 0x80, 0x00, + 0xc3, 0x41, 0x13, 0x00, 0xf0, 0x6b, 0x48, 0x30, 0xc0, 0x02, 0x49, 0x20, + 0x00, 0x05, 0x48, 0x20, 0x80, 0x00, 0x1f, 0xa6, 0x0a, 0x20, 0x40, 0x03, + 0x80, 0x20, 0x0a, 0x04, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x02, 0x04, + 0x04, 0x18, 0x90, 0x00, 0xc3, 0x40, 0x06, 0x3b, 0x00, 0xe2, 0x7e, 0x1e, + 0x18, 0x10, 0x32, 0x0e, 0x2f, 0xfd, 0xa1, 0x40, 0xc6, 0xc6, 0xe0, 0x78, + 0xea, 0xc3, 0xa7, 0xc1, 0x47, 0xdc, 0x4a, 0x24, 0x00, 0x71, 0x08, 0x46, + 0x55, 0x20, 0x4f, 0x08, 0x6d, 0x18, 0x03, 0x02, 0x18, 0xbc, 0xc3, 0x43, + 0xa3, 0x42, 0x0b, 0xd7, 0xcb, 0x45, 0xd3, 0x3e, 0x98, 0xdd, 0xc3, 0x42, + 0x3b, 0x4a, 0xc1, 0xbf, 0xc3, 0x41, 0xdc, 0x44, 0x30, 0x4e, 0xc3, 0x40, + 0x7b, 0x3e, 0xd7, 0x5e, 0x90, 0x1e, 0x85, 0x11, 0x55, 0x26, 0x0b, 0x18, + 0x9a, 0xa6, 0x79, 0xa6, 0xb8, 0xa6, 0x55, 0xa6, 0x34, 0xa6, 0x0c, 0xa6, + 0x0a, 0x20, 0x80, 0x0f, 0x13, 0x00, 0xc4, 0x6d, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x10, 0x01, 0x04, 0x04, 0x1b, 0x50, 0x10, 0x4a, 0x24, 0x00, 0x71, + 0xcb, 0x43, 0x51, 0x3f, 0x18, 0xb7, 0xcb, 0x44, 0x98, 0x3d, 0xc2, 0xb5, + 0xc3, 0x43, 0x4c, 0x3f, 0xcd, 0xcc, 0x8a, 0x22, 0x10, 0x02, 0xc3, 0x41, + 0x83, 0x41, 0x3b, 0x6c, 0xc3, 0x40, 0x21, 0x3d, 0xe0, 0x61, 0x28, 0x1e, + 0x85, 0x11, 0xb7, 0xa6, 0x48, 0x1f, 0xc0, 0x12, 0x8a, 0xa7, 0x7b, 0xa7, + 0xea, 0x1e, 0x84, 0x10, 0x2b, 0xa6, 0x2c, 0x70, 0xd3, 0x40, 0x80, 0x3f, + 0x00, 0x00, 0x1a, 0xa7, 0xa8, 0x20, 0x40, 0x03, 0x15, 0x26, 0x40, 0x10, + 0x80, 0x10, 0x00, 0x00, 0x83, 0xc5, 0x15, 0x25, 0x42, 0x10, 0x02, 0x30, + 0x00, 0x20, 0x24, 0x71, 0x00, 0xa2, 0x2e, 0x0a, 0xa0, 0x01, 0x83, 0xc0, + 0x4a, 0x21, 0x00, 0x20, 0xa6, 0x0e, 0xef, 0xfa, 0x00, 0x15, 0x00, 0x10, + 0x26, 0x71, 0xf9, 0x09, 0x34, 0xa1, 0x04, 0x1d, 0x10, 0x10, 0x4a, 0x24, + 0x00, 0x71, 0x54, 0x26, 0x00, 0x1e, 0x83, 0xc1, 0xa8, 0x20, 0x00, 0x02, + 0x04, 0x11, 0x02, 0x04, 0x02, 0x30, 0x82, 0x20, 0x04, 0x18, 0x90, 0x00, + 0x3e, 0x86, 0x1f, 0x86, 0x5d, 0x86, 0x6a, 0x87, 0x4a, 0x24, 0xc0, 0x70, + 0x55, 0x26, 0x10, 0x1a, 0x41, 0xc1, 0x42, 0xc0, 0x80, 0xc1, 0x0a, 0x20, + 0x00, 0x04, 0x40, 0xc2, 0xa8, 0x20, 0x00, 0x02, 0x04, 0x11, 0x02, 0x04, + 0x07, 0x33, 0x82, 0x00, 0x04, 0x18, 0x90, 0x00, 0x4a, 0x24, 0xc0, 0x70, + 0x0c, 0x70, 0xbc, 0x4e, 0x36, 0x1e, 0x43, 0x10, 0x35, 0x1e, 0x43, 0x10, + 0x2a, 0x1e, 0x02, 0x10, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x19, 0x11, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x26, 0x00, 0x14, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x18, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x04, 0x6e, 0xad, 0x70, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, 0x78, 0x4e, 0x34, 0x1e, + 0x42, 0x13, 0xd2, 0x0b, 0x2f, 0xfc, 0x2a, 0x1e, 0x42, 0x13, 0x02, 0x87, + 0x40, 0x87, 0x21, 0x87, 0x8a, 0x87, 0x4a, 0x24, 0xc0, 0x70, 0xc3, 0x43, + 0x51, 0x39, 0x17, 0xb7, 0xa6, 0xa7, 0xa4, 0xa7, 0x36, 0x1e, 0x43, 0x10, + 0x35, 0x1e, 0x43, 0x10, 0x14, 0x1f, 0xc0, 0x10, 0x45, 0xc0, 0x83, 0xc0, + 0x43, 0xc2, 0x44, 0xc1, 0xa8, 0x20, 0x00, 0x02, 0x04, 0x10, 0x01, 0x04, + 0x07, 0x34, 0x41, 0x10, 0x04, 0x18, 0x50, 0x20, 0x4a, 0x24, 0xc0, 0x70, + 0x0c, 0x70, 0x55, 0x26, 0x41, 0x1b, 0x0b, 0xa7, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x19, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x19, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x55, 0x26, 0x00, 0x1d, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, 0xe9, 0x1e, 0x03, 0x10, + 0x00, 0x18, 0x03, 0x00, 0xca, 0xc7, 0xe0, 0x78, 0x4a, 0x24, 0xc0, 0x70, + 0xc3, 0x41, 0x8c, 0x42, 0x00, 0x00, 0xcb, 0x44, 0xa0, 0x40, 0x00, 0x00, + 0xfa, 0xdb, 0x40, 0x20, 0x02, 0x06, 0x08, 0x18, 0x41, 0x01, 0x04, 0x18, + 0x43, 0x00, 0x2a, 0xa0, 0x85, 0xa0, 0x24, 0xa0, 0x0c, 0x18, 0xc0, 0x00, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1a, 0x11, 0x00, 0xe0, 0x7f, 0x00, 0x1a, + 0x01, 0x00, 0xe0, 0x78, 0xe8, 0xc2, 0x4a, 0x24, 0x80, 0x71, 0x10, 0x40, + 0x55, 0x20, 0x8e, 0x0e, 0xc3, 0x43, 0xa0, 0x3f, 0x00, 0x00, 0xc3, 0x42, + 0x7a, 0x44, 0x00, 0x00, 0xc3, 0x41, 0xfa, 0x43, 0x00, 0x00, 0x8d, 0x70, + 0xc3, 0x40, 0x00, 0x00, 0x40, 0x9c, 0x14, 0x1e, 0x01, 0x10, 0x64, 0xa6, + 0x43, 0xa6, 0x22, 0xa6, 0x56, 0x20, 0x01, 0x28, 0xcb, 0x45, 0x13, 0x00, + 0x64, 0x6c, 0x01, 0xa6, 0x00, 0x1e, 0x00, 0x10, 0xa8, 0x20, 0x80, 0x02, + 0x98, 0x65, 0x08, 0x10, 0xc0, 0x00, 0x85, 0x71, 0x48, 0x30, 0x80, 0x00, + 0x04, 0x19, 0x10, 0x00, 0xc3, 0x41, 0x20, 0x42, 0x00, 0x00, 0x8a, 0x20, + 0x04, 0x07, 0x40, 0x25, 0x0f, 0x1d, 0x2c, 0xa6, 0x02, 0x70, 0x18, 0xda, + 0xe6, 0x0d, 0xef, 0xe8, 0xe1, 0x41, 0x8a, 0x20, 0x04, 0x0d, 0x02, 0x70, + 0x54, 0x25, 0x81, 0x19, 0xd6, 0x0d, 0xef, 0xe8, 0x18, 0xda, 0x8a, 0x20, + 0x05, 0x03, 0x02, 0x70, 0x18, 0xda, 0xca, 0x0d, 0xef, 0xe8, 0xe1, 0x41, + 0x4a, 0x24, 0xc0, 0x70, 0x8a, 0x20, 0x05, 0x09, 0x7d, 0xd9, 0x02, 0x70, + 0x40, 0x29, 0xc1, 0x05, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x50, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0x0a, 0x21, 0x80, 0x0f, 0x74, 0x49, 0x00, 0x24, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x50, 0x00, 0x4a, 0x24, 0x80, 0x71, + 0x81, 0xd9, 0x17, 0xb9, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x50, 0x00, + 0x28, 0x15, 0x08, 0x10, 0x2c, 0x15, 0x0b, 0x10, 0xec, 0x85, 0x4a, 0x24, + 0xc0, 0x70, 0x7d, 0xda, 0x8a, 0x21, 0x06, 0x0b, 0xcb, 0x44, 0xc8, 0x41, + 0x00, 0x00, 0xc3, 0x43, 0x12, 0x00, 0x80, 0x4f, 0x05, 0xba, 0x02, 0x71, + 0x00, 0x18, 0x00, 0x03, 0xc0, 0x1e, 0xc0, 0x10, 0xbc, 0x1e, 0x80, 0x10, + 0xb4, 0x1e, 0xc0, 0x12, 0xb0, 0x1e, 0x00, 0x12, 0xb8, 0x1e, 0xc0, 0x13, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x19, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, + 0x56, 0x20, 0xc1, 0x2d, 0x0a, 0x20, 0x40, 0x03, 0xa8, 0x20, 0x00, 0x02, + 0x02, 0x10, 0x42, 0x05, 0x48, 0x32, 0x82, 0x00, 0x04, 0x19, 0x90, 0x00, + 0x8a, 0x21, 0x0f, 0x0a, 0x8a, 0x20, 0x09, 0x0f, 0xdc, 0x1e, 0x40, 0x10, + 0x00, 0x20, 0x0e, 0x20, 0xf6, 0x0b, 0xaf, 0xef, 0xc1, 0x40, 0x08, 0xd9, + 0x0a, 0x0d, 0xaf, 0xef, 0xc1, 0x40, 0x1c, 0xe5, 0x8a, 0x21, 0x08, 0x00, + 0x02, 0x40, 0xb6, 0x08, 0x20, 0x00, 0xa1, 0x42, 0x8a, 0x21, 0x08, 0x00, + 0x02, 0x40, 0xaa, 0x08, 0x20, 0x00, 0xa1, 0x42, 0x0a, 0x08, 0x20, 0x00, + 0x02, 0x40, 0xc8, 0xc6, 0xe6, 0xc3, 0xa6, 0xc1, 0x08, 0x46, 0x55, 0x20, + 0xcf, 0x0c, 0x8a, 0x20, 0x09, 0x0f, 0xd8, 0x60, 0x96, 0x0c, 0xaf, 0xef, + 0x8a, 0x25, 0x0c, 0x1f, 0x4a, 0x24, 0x00, 0x71, 0xc1, 0x42, 0xb8, 0x66, + 0xad, 0x70, 0x2c, 0x70, 0x80, 0x22, 0x0c, 0x01, 0xa8, 0x20, 0xc0, 0x02, + 0x33, 0x21, 0x83, 0x0f, 0x13, 0x00, 0x60, 0x6c, 0x24, 0x71, 0x48, 0x33, + 0x83, 0x00, 0x04, 0x1a, 0xd0, 0x00, 0x4a, 0x24, 0x80, 0x72, 0x93, 0x1f, + 0x58, 0x13, 0x00, 0x18, 0x83, 0x02, 0xe0, 0x18, 0x44, 0x83, 0xd8, 0x18, + 0x44, 0x83, 0xe2, 0x18, 0x42, 0x83, 0xda, 0x18, 0x42, 0x83, 0xc0, 0x18, + 0x42, 0x83, 0x8a, 0x20, 0x0b, 0x05, 0xd8, 0x60, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x18, 0x11, 0x00, 0x40, 0x87, 0x21, 0x87, 0x02, 0x87, 0x8d, 0x1f, + 0x58, 0x13, 0x43, 0xc2, 0x44, 0xc1, 0x45, 0xc0, 0x40, 0x26, 0x02, 0x18, + 0x80, 0xc1, 0xc1, 0x40, 0x40, 0xc5, 0x41, 0xc5, 0x2a, 0x0f, 0x2f, 0xfe, + 0x42, 0xc5, 0x80, 0x26, 0x0c, 0x19, 0xa0, 0xae, 0xc6, 0xc7, 0xe0, 0x78, + 0xf0, 0xc3, 0xa6, 0xc1, 0x40, 0x92, 0xc3, 0x43, 0x48, 0x47, 0x00, 0x00, + 0x00, 0x20, 0x8d, 0x0f, 0x00, 0x00, 0xbc, 0x02, 0x48, 0x32, 0x02, 0x00, + 0x10, 0x40, 0x07, 0x33, 0x82, 0x00, 0xbb, 0x15, 0x00, 0x96, 0xcb, 0x46, + 0xc8, 0x41, 0x00, 0x00, 0xd1, 0x41, 0x48, 0x30, 0x80, 0x00, 0xcb, 0x44, + 0x83, 0x3a, 0x6f, 0x12, 0x48, 0x31, 0x0b, 0x00, 0x0d, 0x70, 0x04, 0x32, + 0x80, 0x83, 0xca, 0x21, 0x85, 0x20, 0x00, 0x31, 0x00, 0x20, 0x00, 0x30, + 0x00, 0x03, 0x04, 0x30, 0x00, 0x82, 0xc7, 0xf6, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, + 0x00, 0x00, 0xba, 0x15, 0x01, 0x96, 0x48, 0x30, 0xc2, 0x02, 0x07, 0x33, + 0xd2, 0x02, 0x8a, 0x27, 0x0c, 0x17, 0x48, 0x31, 0x81, 0x00, 0x00, 0x31, + 0x40, 0x20, 0x48, 0x32, 0x81, 0x00, 0x00, 0x30, 0x00, 0x03, 0x48, 0x31, + 0xc1, 0x02, 0x04, 0x30, 0x00, 0x82, 0x3c, 0xa5, 0xc6, 0xf6, 0x01, 0x30, + 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, 0x01, 0x30, 0x80, 0x0f, + 0x00, 0xbf, 0x00, 0x00, 0x07, 0x36, 0x8b, 0x74, 0x80, 0x3f, 0x00, 0x00, + 0x8b, 0x15, 0x01, 0x96, 0x48, 0x30, 0xc2, 0x02, 0x6c, 0x70, 0x48, 0x31, + 0x80, 0x00, 0x48, 0x32, 0x82, 0x00, 0x02, 0x77, 0x00, 0x31, 0x00, 0x20, + 0x48, 0x32, 0xc2, 0x02, 0x5b, 0xa5, 0x00, 0x33, 0x00, 0x10, 0x78, 0x1d, + 0xc0, 0x12, 0x00, 0x30, 0x00, 0x03, 0x04, 0x30, 0xc0, 0x80, 0xc7, 0xf6, + 0x01, 0x30, 0x81, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x05, 0xf0, 0x01, 0x30, + 0x81, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x8c, 0x15, 0x00, 0x96, 0x48, 0x31, + 0xc1, 0x02, 0x48, 0x30, 0x80, 0x00, 0x34, 0xaf, 0x00, 0x31, 0x00, 0x20, + 0x00, 0x33, 0x00, 0x10, 0x00, 0x30, 0x00, 0x03, 0x04, 0x30, 0xc0, 0x80, + 0xc6, 0xf6, 0x01, 0x30, 0x81, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x81, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x90, 0x15, 0x00, 0x96, + 0x48, 0x31, 0xc1, 0x02, 0x4c, 0x70, 0x48, 0x30, 0x80, 0x00, 0x35, 0xaf, + 0x00, 0x32, 0x00, 0x20, 0x00, 0x30, 0x00, 0x03, 0x04, 0x30, 0x80, 0x80, + 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x08, 0x15, 0x01, 0x90, + 0x48, 0x30, 0xc3, 0x02, 0x57, 0xa5, 0x48, 0x31, 0x81, 0x00, 0x40, 0xb7, + 0x00, 0x31, 0x40, 0x20, 0x42, 0xaf, 0x48, 0x33, 0x81, 0x00, 0x00, 0x30, + 0x00, 0x03, 0x48, 0x31, 0xc1, 0x02, 0x04, 0x30, 0x80, 0x80, 0x3f, 0xa5, + 0xc6, 0xf6, 0x01, 0x30, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x30, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc0, 0x02, + 0x00, 0x31, 0x81, 0x2f, 0xcc, 0x3e, 0xcd, 0xcc, 0x4c, 0x70, 0x48, 0x30, + 0x80, 0x00, 0x04, 0x31, 0x80, 0x80, 0x48, 0x30, 0xc0, 0x02, 0x19, 0xa5, + 0xc6, 0xf6, 0x01, 0x31, 0x80, 0x0f, 0x00, 0x3f, 0x00, 0x00, 0x06, 0xf0, + 0x01, 0x31, 0x80, 0x0f, 0x00, 0xbf, 0x00, 0x00, 0x48, 0x30, 0xc1, 0x02, + 0x8a, 0x20, 0x09, 0x0f, 0x02, 0x70, 0x55, 0x20, 0x93, 0x2e, 0x4a, 0x0a, + 0xaf, 0xef, 0x20, 0x1f, 0x42, 0x10, 0x4a, 0x24, 0x80, 0x72, 0x8a, 0x20, + 0x0b, 0x05, 0x2c, 0x70, 0x00, 0x20, 0x00, 0x04, 0xe0, 0x1f, 0x42, 0x90, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, 0x40, 0x20, 0x00, 0x22, + 0xe0, 0xda, 0x62, 0x41, 0x5e, 0x0a, 0xef, 0xe8, 0x44, 0x1d, 0x01, 0x10, + 0x8a, 0x21, 0x04, 0x07, 0x02, 0x71, 0x80, 0xc0, 0x18, 0xda, 0x4e, 0x0a, + 0xef, 0xe8, 0x40, 0x24, 0x14, 0x30, 0x4a, 0x24, 0x80, 0x71, 0x40, 0x20, + 0x13, 0x2f, 0xcb, 0x47, 0xc8, 0x42, 0x00, 0x00, 0xa8, 0x20, 0x80, 0x03, + 0x04, 0x14, 0x00, 0x24, 0x00, 0x30, 0x80, 0x03, 0x07, 0x30, 0x40, 0x04, + 0x00, 0x30, 0xc0, 0x03, 0x07, 0x30, 0x80, 0x04, 0x04, 0x1b, 0x10, 0x20, + 0x8a, 0x21, 0x04, 0x0d, 0x02, 0x71, 0x80, 0xc0, 0x18, 0xda, 0x12, 0x0a, + 0xef, 0xe8, 0x40, 0x24, 0x14, 0x30, 0x4a, 0x24, 0x80, 0x71, 0xa8, 0x20, + 0xc0, 0x03, 0x04, 0x14, 0x00, 0x24, 0x00, 0x30, 0x80, 0x03, 0x07, 0x30, + 0x40, 0x04, 0x00, 0x30, 0xc0, 0x03, 0x07, 0x30, 0x80, 0x04, 0x04, 0x1b, + 0x10, 0x20, 0x8a, 0x21, 0x05, 0x03, 0x02, 0x71, 0x80, 0xc0, 0x18, 0xda, + 0xde, 0x09, 0xef, 0xe8, 0x40, 0x24, 0x14, 0x30, 0x4a, 0x24, 0x80, 0x71, + 0xa8, 0x20, 0x80, 0x03, 0x04, 0x14, 0x00, 0x24, 0x00, 0x30, 0x80, 0x03, + 0x07, 0x30, 0x40, 0x04, 0x00, 0x30, 0xc0, 0x03, 0x07, 0x30, 0x80, 0x04, + 0x04, 0x1b, 0x10, 0x20, 0xb6, 0x15, 0x00, 0x96, 0xc3, 0x41, 0x48, 0x41, + 0x00, 0x00, 0x04, 0x31, 0x40, 0xa0, 0x00, 0x30, 0x80, 0x03, 0xca, 0x21, + 0x45, 0x20, 0x07, 0x30, 0x40, 0x04, 0x04, 0x18, 0x43, 0x20, 0x7e, 0x1d, + 0x18, 0x90, 0xd0, 0xc7, 0xa3, 0xc1, 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x20, + 0x02, 0x02, 0x2c, 0x70, 0x38, 0x18, 0x45, 0x00, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x1a, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0x3a, 0x18, 0x42, 0x00, + 0x40, 0xc1, 0x41, 0xc1, 0x62, 0xc1, 0x80, 0xc3, 0x80, 0xc1, 0xa8, 0x20, + 0x40, 0x01, 0x04, 0x19, 0x53, 0x00, 0x4a, 0x24, 0x40, 0x72, 0xa8, 0x20, + 0x40, 0x02, 0x01, 0x13, 0xc1, 0x04, 0x48, 0x31, 0x81, 0x00, 0x04, 0x1a, + 0x50, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0xfc, 0x48, 0x40, 0x20, 0x02, 0x02, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x12, 0x03, 0x04, 0x04, 0x19, 0xd0, 0x00, + 0x48, 0x18, 0x03, 0x00, 0xe0, 0x7f, 0xa3, 0xc0, 0xe8, 0xc2, 0x08, 0x45, + 0x55, 0x20, 0x10, 0x08, 0xcd, 0x70, 0xcb, 0x41, 0x32, 0x01, 0xe6, 0x78, + 0x3e, 0x18, 0xc5, 0x01, 0xcb, 0x40, 0x00, 0x00, 0x9c, 0x6c, 0x58, 0x18, + 0x45, 0x00, 0xcb, 0x43, 0xef, 0x41, 0x96, 0xe8, 0xcb, 0x47, 0x5f, 0x05, + 0xbe, 0x0a, 0xcb, 0x44, 0x64, 0x75, 0x84, 0x00, 0xc3, 0x43, 0x5f, 0x05, + 0x4a, 0x00, 0xc3, 0x42, 0x0c, 0x00, 0x0c, 0x00, 0xc3, 0x41, 0xaa, 0x7e, + 0xa0, 0x00, 0x8a, 0x26, 0x04, 0x00, 0x7d, 0xd8, 0x20, 0x18, 0x80, 0x23, + 0x1c, 0x18, 0x80, 0x23, 0x20, 0x1d, 0x40, 0x12, 0x26, 0x1d, 0x04, 0x12, + 0x54, 0x1d, 0xc0, 0x12, 0xf4, 0xa5, 0x8a, 0xa5, 0x73, 0xa5, 0x46, 0xa5, + 0x44, 0x1d, 0x84, 0x13, 0x30, 0xa5, 0x48, 0x1d, 0x84, 0x11, 0xc5, 0xa5, + 0xd7, 0xb5, 0xd9, 0xb5, 0xdb, 0xb5, 0xdd, 0xb5, 0x1f, 0xa5, 0x04, 0x18, + 0x00, 0x20, 0xc2, 0x0f, 0x20, 0x02, 0x0c, 0x70, 0x9e, 0x20, 0x06, 0x04, + 0x6c, 0x70, 0x8a, 0x22, 0xdd, 0x09, 0x8a, 0x21, 0xb5, 0x0d, 0x8a, 0x27, + 0xdc, 0x1c, 0xcb, 0x44, 0x33, 0x09, 0x00, 0x00, 0x8b, 0xbb, 0x24, 0x18, + 0x82, 0x23, 0xdc, 0xa5, 0xdb, 0xa5, 0xd8, 0xb5, 0x2c, 0x1d, 0x83, 0x10, + 0x74, 0x1d, 0x45, 0x10, 0x4a, 0x1d, 0x82, 0x13, 0x46, 0x1d, 0x84, 0x13, + 0xdc, 0xb5, 0x3c, 0x1d, 0x82, 0x13, 0xc3, 0xa5, 0xc2, 0xa5, 0x00, 0x18, + 0x80, 0x23, 0xde, 0xa5, 0x5a, 0xa5, 0x39, 0xa5, 0x58, 0xa5, 0x37, 0xa5, + 0xf2, 0xb5, 0x87, 0xa5, 0x64, 0xa5, 0x1a, 0xb5, 0x55, 0x25, 0x80, 0x18, + 0x2c, 0x70, 0x96, 0x0e, 0xaf, 0xf6, 0x11, 0xda, 0xc8, 0xc6, 0xe0, 0x78, + 0xf1, 0xc0, 0x1e, 0x21, 0x0c, 0x00, 0x0c, 0x70, 0x8f, 0xb8, 0x31, 0x48, + 0x4c, 0x79, 0x1d, 0x7b, 0x99, 0x61, 0x78, 0x61, 0x16, 0x08, 0xaf, 0xff, + 0x0f, 0xd9, 0xd1, 0xc0, 0xe0, 0x7f, 0x0e, 0x78, 0xe4, 0xc0, 0x7f, 0xda, + 0xc3, 0x43, 0x22, 0xbe, 0x88, 0x2f, 0x17, 0xba, 0xc3, 0x41, 0xd7, 0x3e, + 0x1e, 0x74, 0xcb, 0x44, 0x13, 0x00, 0xd4, 0x6d, 0x70, 0xa0, 0x4f, 0xa0, + 0x2e, 0xa0, 0x2d, 0xa0, 0x22, 0x84, 0x41, 0x84, 0x60, 0x84, 0x23, 0xa0, + 0x42, 0xa0, 0x61, 0xa0, 0x44, 0x84, 0x63, 0x84, 0x25, 0x84, 0x4a, 0x24, + 0x80, 0x71, 0x40, 0x20, 0x0b, 0x07, 0x45, 0xa0, 0x64, 0xa0, 0x26, 0xa0, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1b, 0x11, 0x10, 0x4a, 0x24, 0xc0, 0x70, + 0x54, 0x20, 0x03, 0x0a, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x1b, 0x11, 0x00, + 0x4a, 0x24, 0xc0, 0x70, 0x54, 0x20, 0x02, 0x0c, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x1a, 0x11, 0x00, 0x4a, 0x24, 0xc0, 0x70, 0xcb, 0x46, 0x30, 0x44, + 0x66, 0xc6, 0x2c, 0x70, 0xcb, 0x45, 0x7a, 0x44, 0x00, 0x00, 0x54, 0x20, + 0x8c, 0x08, 0x70, 0x18, 0x41, 0x00, 0x74, 0x18, 0x43, 0x00, 0xc0, 0xa2, + 0x20, 0xa3, 0xbf, 0xa0, 0x78, 0x18, 0x40, 0x00, 0x84, 0x18, 0x40, 0x00, + 0x88, 0x18, 0x42, 0x00, 0x80, 0x18, 0x40, 0x00, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x1c, 0x11, 0x10, 0xc4, 0xc4, 0xe0, 0x78, 0x4a, 0x24, 0x00, 0x71, + 0xa8, 0x20, 0x80, 0x01, 0x14, 0x10, 0x02, 0x04, 0x04, 0x19, 0x90, 0x00, + 0xe0, 0x7e, 0xe0, 0x78, 0x2c, 0x72, 0x4c, 0x71, 0x2f, 0x21, 0x42, 0x80, + 0x42, 0xf7, 0x0c, 0x7a, 0x0c, 0x78, 0xfc, 0xf5, 0xe0, 0x7f, 0x40, 0x40, + 0x40, 0x81, 0x58, 0x60, 0x01, 0x10, 0xcc, 0x00, 0x00, 0x88, 0x62, 0x6a, + 0x40, 0x2c, 0x02, 0x12, 0x45, 0x78, 0xe0, 0x7f, 0x60, 0xa1, 0xe0, 0x78, + 0xe0, 0x7f, 0x00, 0xa1, 0x31, 0x88, 0x0d, 0xe9, 0x18, 0x88, 0x1b, 0x08, + 0x51, 0x00, 0xc3, 0x40, 0xa0, 0x00, 0xa0, 0x86, 0x00, 0x88, 0x14, 0x70, + 0x80, 0xd8, 0x05, 0xf2, 0xe0, 0x7e, 0xe0, 0x7f, 0x0c, 0x70, 0xe0, 0x7f, + 0xff, 0xd8, 0xe0, 0x78, 0xf1, 0xc0, 0x58, 0x88, 0x4a, 0x24, 0xc0, 0x70, + 0x20, 0x43, 0xc3, 0x41, 0xa0, 0x00, 0xbc, 0xc1, 0xa8, 0x20, 0x80, 0x01, + 0x00, 0x81, 0x0b, 0x08, 0x80, 0x00, 0x08, 0xe1, 0x05, 0xf0, 0x96, 0x0b, + 0x20, 0x00, 0x01, 0x81, 0x00, 0xa3, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, + 0xe6, 0xc2, 0x4a, 0x24, 0xc0, 0x70, 0xc3, 0x43, 0xa0, 0x00, 0x7c, 0xc1, + 0x28, 0x47, 0x60, 0x41, 0xa8, 0x20, 0x40, 0x02, 0x1c, 0x11, 0x02, 0x04, + 0x09, 0x0a, 0x01, 0x00, 0xe8, 0x19, 0x03, 0x80, 0xe0, 0x78, 0x58, 0x88, + 0x4a, 0x24, 0xc0, 0x70, 0x54, 0x23, 0x00, 0x08, 0xa8, 0x20, 0x80, 0x01, + 0x20, 0x80, 0x0b, 0x09, 0x80, 0x00, 0x08, 0xe0, 0x14, 0xf0, 0xc1, 0x80, + 0x04, 0x36, 0xc0, 0x93, 0x10, 0xf2, 0xcb, 0x45, 0xf0, 0x00, 0x49, 0x00, + 0x55, 0xd8, 0xee, 0x0d, 0x2f, 0xf7, 0x40, 0xad, 0x48, 0x37, 0x41, 0x12, + 0x48, 0x36, 0x40, 0x12, 0x03, 0x1d, 0x44, 0x10, 0x05, 0x1d, 0x04, 0x10, + 0xc6, 0xc6, 0xe0, 0x78, 0xfa, 0xc2, 0xfc, 0x1c, 0xc8, 0xb6, 0xd6, 0x0b, + 0x6f, 0xf4, 0xaa, 0xc1, 0x5a, 0x0f, 0x2f, 0xf4, 0x18, 0x41, 0x47, 0xc0, + 0x3b, 0x58, 0x0e, 0x70, 0x38, 0x43, 0xcb, 0x47, 0xa0, 0x00, 0xbc, 0xc1, + 0x12, 0x47, 0x12, 0x43, 0x46, 0xc0, 0x34, 0x1f, 0x00, 0x14, 0x38, 0x1f, + 0x00, 0x14, 0x3c, 0x1f, 0x00, 0x14, 0x40, 0x1f, 0x00, 0x14, 0x07, 0xc0, + 0x0c, 0x27, 0x00, 0xa0, 0x5e, 0x02, 0x26, 0x00, 0x40, 0x2f, 0xce, 0x21, + 0x23, 0x76, 0x07, 0x86, 0x14, 0x70, 0x22, 0x02, 0x02, 0x00, 0x69, 0x8e, + 0x31, 0x8e, 0x8e, 0x8e, 0x18, 0x16, 0x91, 0x10, 0x78, 0x23, 0x00, 0x00, + 0x79, 0x21, 0x02, 0x00, 0x04, 0x7a, 0x05, 0xec, 0x0d, 0x87, 0x04, 0x71, + 0x0d, 0xa7, 0x05, 0xea, 0x0e, 0x87, 0x04, 0x71, 0x0e, 0xa7, 0x05, 0xe9, + 0x0f, 0x87, 0x04, 0x71, 0x0f, 0xa7, 0x05, 0xeb, 0x10, 0x87, 0x04, 0x71, + 0x10, 0xa7, 0x78, 0x24, 0x00, 0x10, 0x46, 0x78, 0xe0, 0xb8, 0xf1, 0xf4, + 0x2f, 0x26, 0x45, 0x24, 0xd6, 0x70, 0xda, 0x01, 0x2c, 0x00, 0xae, 0x71, + 0xc1, 0x40, 0x20, 0x1c, 0xc1, 0x30, 0xd6, 0x0a, 0xaf, 0xf3, 0x24, 0x1c, + 0x40, 0x35, 0xad, 0x86, 0x2c, 0x86, 0x10, 0x42, 0x8e, 0x70, 0x2f, 0x20, + 0x40, 0x04, 0x04, 0x32, 0x00, 0xa5, 0x44, 0xc0, 0xd4, 0xf7, 0x42, 0x26, + 0x00, 0x2d, 0x0f, 0x78, 0x27, 0x08, 0xd4, 0x00, 0x19, 0x8e, 0xe5, 0xb8, + 0xa9, 0xf4, 0x50, 0x21, 0xfe, 0x87, 0xc3, 0x40, 0x48, 0x44, 0x00, 0x00, + 0xce, 0xf2, 0x04, 0x31, 0x00, 0x80, 0xca, 0x21, 0x09, 0x00, 0xcb, 0xf0, + 0xd3, 0x42, 0x7f, 0x47, 0x00, 0xff, 0x0f, 0x70, 0x84, 0xc1, 0x89, 0xc2, + 0x40, 0x24, 0x04, 0x38, 0xc3, 0x40, 0xa0, 0x00, 0x8c, 0x86, 0xe1, 0x43, + 0x18, 0x1f, 0x43, 0x10, 0x14, 0x1c, 0x80, 0x34, 0x96, 0x5a, 0x82, 0x0a, + 0xef, 0xfb, 0x10, 0x41, 0x18, 0x1f, 0x03, 0x10, 0x00, 0x16, 0x80, 0x70, + 0xa0, 0x00, 0xb8, 0x86, 0x2b, 0x08, 0x5e, 0x00, 0x45, 0x87, 0x0c, 0x17, + 0x07, 0x10, 0x08, 0x17, 0x86, 0x10, 0x04, 0x17, 0x05, 0x10, 0x00, 0x17, + 0x84, 0x10, 0x90, 0x8f, 0x28, 0xc3, 0x05, 0xc1, 0x24, 0xc0, 0x41, 0xc2, + 0x2f, 0x22, 0x47, 0x04, 0x92, 0x09, 0xaf, 0xf6, 0x40, 0xc4, 0x8c, 0x21, + 0x3f, 0xad, 0x0d, 0xf4, 0x0b, 0x87, 0x00, 0x32, 0x92, 0x2f, 0x00, 0x3f, + 0x00, 0x00, 0x86, 0x71, 0x0b, 0x08, 0x25, 0x05, 0x0f, 0x71, 0x2c, 0x1f, + 0x00, 0x15, 0x8a, 0x20, 0x3f, 0x0d, 0x04, 0x32, 0x40, 0xa3, 0x39, 0x21, + 0x00, 0x20, 0xc5, 0x20, 0x6b, 0x00, 0x05, 0x20, 0x40, 0x05, 0x7d, 0x08, + 0x51, 0x80, 0xcb, 0x45, 0xf0, 0x00, 0x34, 0x00, 0x87, 0x09, 0x32, 0x20, + 0x52, 0xd8, 0x19, 0x08, 0x30, 0x30, 0x52, 0xd8, 0x4e, 0x0c, 0x0f, 0xf7, + 0x48, 0x32, 0x41, 0x22, 0x4e, 0x21, 0x00, 0x20, 0x0c, 0xb5, 0x2d, 0xb5, + 0x08, 0xc1, 0xfe, 0x0f, 0xef, 0xfb, 0xe1, 0x40, 0x42, 0x26, 0x01, 0x2d, + 0x2f, 0x79, 0x19, 0x09, 0xf5, 0x00, 0x05, 0xc0, 0x04, 0x30, 0x80, 0x8f, + 0x7f, 0x47, 0x00, 0xff, 0x44, 0xf7, 0x7f, 0xd8, 0x17, 0xb8, 0x45, 0xc0, + 0x6a, 0x09, 0x00, 0x00, 0x44, 0x16, 0x11, 0x10, 0x08, 0x45, 0x10, 0xa6, + 0xca, 0x0a, 0x6f, 0xf5, 0xc1, 0x40, 0x24, 0xe8, 0x04, 0x31, 0x40, 0xa3, + 0x4b, 0xf2, 0x0c, 0x70, 0x04, 0x35, 0x00, 0x90, 0x46, 0x00, 0x2c, 0x00, + 0x3c, 0x96, 0xa1, 0xe9, 0x4e, 0x16, 0x82, 0x10, 0x8a, 0x21, 0xbf, 0x0f, + 0x0c, 0x77, 0x8c, 0x22, 0xc3, 0x8f, 0xca, 0x20, 0x41, 0x00, 0x38, 0x1e, + 0x45, 0x10, 0x4e, 0x1e, 0x02, 0x10, 0xff, 0xd8, 0x17, 0xf0, 0xd6, 0x0b, + 0x0f, 0xf7, 0x48, 0x32, 0x41, 0x22, 0x4e, 0x21, 0x00, 0x20, 0x0c, 0xb5, + 0x2d, 0xb5, 0x2e, 0xf0, 0x2c, 0x71, 0x12, 0x0d, 0x6f, 0xf3, 0xc1, 0x40, + 0x27, 0xf0, 0x4e, 0x70, 0x65, 0xf1, 0x04, 0x35, 0x00, 0x90, 0x10, 0xf7, + 0x0e, 0xe9, 0x1c, 0xb6, 0x0c, 0x70, 0xbe, 0x0a, 0x0f, 0xf4, 0x06, 0xc3, + 0x00, 0x42, 0x2c, 0x73, 0xac, 0x70, 0xc1, 0x40, 0x86, 0x08, 0x6f, 0xf7, + 0x0a, 0x24, 0xc0, 0x06, 0xc3, 0x40, 0x7f, 0x43, 0x00, 0x00, 0x04, 0x35, + 0x00, 0x90, 0xca, 0x20, 0x45, 0x03, 0x48, 0x30, 0x40, 0x02, 0x06, 0xc3, + 0x0f, 0x7a, 0x78, 0x22, 0x05, 0x00, 0x2c, 0x72, 0xc1, 0x40, 0x62, 0x08, + 0x6f, 0xf7, 0x0a, 0x24, 0xc0, 0x06, 0xb1, 0xa6, 0x66, 0x71, 0xcf, 0x05, + 0xef, 0xff, 0xe6, 0x71, 0x00, 0x41, 0xc3, 0x40, 0xc8, 0x3f, 0x00, 0x00, + 0x04, 0x35, 0x00, 0x90, 0xca, 0x20, 0x49, 0x03, 0x04, 0x32, 0x40, 0xa0, + 0xae, 0x70, 0xc5, 0xf6, 0x30, 0x42, 0x08, 0x45, 0x2d, 0xf1, 0x04, 0x32, + 0x00, 0xa0, 0x08, 0x45, 0xca, 0x22, 0x05, 0x20, 0x27, 0xf1, 0x49, 0x0b, + 0x30, 0x20, 0x2e, 0x71, 0x07, 0xc0, 0x1b, 0xe8, 0x18, 0xde, 0x40, 0xdd, + 0x33, 0x21, 0x80, 0x33, 0x17, 0x08, 0x52, 0x00, 0x30, 0x21, 0x41, 0x33, + 0x50, 0x21, 0xfe, 0x87, 0x05, 0xf2, 0x32, 0x0f, 0xe0, 0x00, 0x0f, 0x78, + 0x0a, 0xe8, 0x07, 0xc0, 0x06, 0x71, 0x55, 0x25, 0x0d, 0x18, 0xe1, 0x08, + 0x24, 0xa0, 0x55, 0x26, 0x0e, 0x18, 0x03, 0xf0, 0x2e, 0x70, 0xc3, 0x40, + 0xa0, 0x00, 0xa0, 0x86, 0x00, 0x18, 0x42, 0x04, 0x0c, 0x87, 0x0b, 0x08, + 0xc5, 0x04, 0x30, 0x1f, 0xc0, 0x14, 0x06, 0x0d, 0xcf, 0xfb, 0xaa, 0xc0, + 0x04, 0x14, 0x1b, 0x34, 0xda, 0xc6, 0xe0, 0x78, 0xf1, 0xc0, 0x0e, 0x0d, + 0x6f, 0xe8, 0x0c, 0x71, 0xc3, 0x41, 0x13, 0x00, 0x8c, 0x08, 0xe2, 0x09, + 0x2f, 0xf7, 0x0c, 0x72, 0xc3, 0x41, 0x13, 0x00, 0xd0, 0x08, 0x6a, 0x0a, + 0x2f, 0xf7, 0x0c, 0x72, 0xf2, 0x0e, 0xc0, 0x00, 0xd1, 0xc0, 0xe0, 0x7e, + 0x00, 0x41, 0x04, 0x30, 0x80, 0x8f, 0x7f, 0x47, 0x00, 0xff, 0x0c, 0x70, + 0xe0, 0x20, 0xca, 0x07, 0x04, 0x31, 0x00, 0x80, 0x7f, 0xd8, 0x17, 0xb8, + 0xe0, 0x7f, 0xca, 0x20, 0x4d, 0x00, 0xe0, 0x78, 0xe8, 0xc3, 0xa3, 0xc1, + 0x08, 0x47, 0x03, 0x80, 0xa6, 0x0a, 0xa0, 0x00, 0xa0, 0x80, 0x07, 0x85, + 0x1d, 0x08, 0xd0, 0x00, 0x89, 0x08, 0x51, 0x01, 0x28, 0x85, 0x44, 0x81, + 0x61, 0x91, 0x0c, 0x11, 0x10, 0x00, 0x00, 0x82, 0x82, 0xbb, 0x61, 0xb1, + 0x40, 0xc0, 0x0c, 0xf0, 0x08, 0x85, 0x02, 0x88, 0x67, 0x08, 0x7f, 0x00, + 0x80, 0xc1, 0x44, 0x85, 0x60, 0x7a, 0xa1, 0x40, 0x10, 0x40, 0x30, 0xe8, + 0xfe, 0x0f, 0x80, 0x00, 0x04, 0x87, 0x40, 0x24, 0xc3, 0x32, 0x40, 0x24, + 0x04, 0x31, 0x02, 0x41, 0xa0, 0x80, 0x11, 0x87, 0xc4, 0x85, 0xf2, 0x0e, + 0x2f, 0xfb, 0x42, 0x86, 0x52, 0x0a, 0x80, 0x00, 0x0b, 0x14, 0x80, 0x30, + 0x0f, 0x08, 0x51, 0x00, 0x00, 0xc0, 0x23, 0x85, 0x01, 0xa6, 0x60, 0x79, + 0xa1, 0x40, 0x01, 0x87, 0x07, 0x80, 0x0b, 0x20, 0x80, 0x8f, 0x00, 0x08, + 0x18, 0x00, 0x10, 0xf2, 0x04, 0x87, 0x01, 0xc1, 0x01, 0x80, 0x64, 0x80, + 0x42, 0x83, 0x20, 0xa2, 0x00, 0xc1, 0x43, 0x80, 0x60, 0x7a, 0x21, 0xa3, + 0x04, 0xf0, 0x06, 0x0c, 0x6f, 0xf6, 0xa1, 0x40, 0xa2, 0x0f, 0x80, 0x00, + 0xc8, 0xc7, 0xe0, 0x78, 0xe2, 0xc2, 0x11, 0x80, 0xa6, 0x0f, 0x2f, 0xfb, + 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0x61, 0x00, + 0x6f, 0xfb, 0x2f, 0x79, 0xe2, 0xc2, 0x11, 0x80, 0xaa, 0x08, 0x6f, 0xfb, + 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0x9d, 0x01, 0x6f, 0xfb, + 0x11, 0x80, 0xe0, 0x78, 0x55, 0x05, 0x2f, 0xfb, 0x11, 0x80, 0xe0, 0x78, + 0x45, 0x05, 0x6f, 0xfb, 0x11, 0x80, 0xe0, 0x78, 0x1d, 0x07, 0x6f, 0xfb, + 0x11, 0x80, 0xe0, 0x78, 0xfa, 0xc2, 0xfc, 0x1c, 0xc8, 0xb6, 0xa1, 0xc1, + 0xcb, 0x45, 0xa0, 0x00, 0x84, 0x6e, 0x0a, 0x85, 0x0a, 0x80, 0x14, 0x70, + 0xfa, 0x05, 0x62, 0x00, 0x8a, 0x20, 0xfc, 0x00, 0x0b, 0x85, 0x80, 0x20, + 0x4e, 0x00, 0x20, 0x88, 0x6e, 0x0a, 0xe0, 0x01, 0xa1, 0x40, 0x2a, 0x85, + 0x0b, 0x85, 0x4a, 0x0d, 0x20, 0x01, 0x30, 0x19, 0x41, 0x00, 0x0b, 0x85, + 0x4b, 0xd9, 0xed, 0x70, 0xdf, 0x18, 0x58, 0x03, 0x70, 0x18, 0x42, 0x00, + 0x80, 0x20, 0x0e, 0x00, 0xe0, 0xa8, 0x76, 0x09, 0x6f, 0xf6, 0x54, 0x25, + 0x80, 0x19, 0x6e, 0x09, 0x6f, 0xf6, 0x54, 0x25, 0x00, 0x18, 0xdb, 0x41, + 0x13, 0x00, 0xec, 0x6d, 0xd3, 0x41, 0x00, 0x00, 0x00, 0x80, 0xcb, 0x46, + 0x7f, 0x7f, 0xff, 0xff, 0x40, 0x24, 0x07, 0x30, 0x56, 0x21, 0xc1, 0x3b, + 0x40, 0xdb, 0xcc, 0x75, 0xa1, 0x40, 0xc3, 0x42, 0x00, 0x00, 0xef, 0xff, + 0x0a, 0x24, 0x40, 0x04, 0x40, 0xc7, 0x00, 0x1e, 0xc0, 0x73, 0xa0, 0x00, + 0x88, 0x99, 0x22, 0x0c, 0xaf, 0xf5, 0xc1, 0x45, 0xdb, 0x43, 0x13, 0x00, + 0x78, 0x6f, 0x40, 0x24, 0x07, 0x30, 0x54, 0x23, 0x81, 0x3c, 0x40, 0xdb, + 0xcc, 0x75, 0xa1, 0x40, 0xc3, 0x42, 0x00, 0x00, 0xef, 0xff, 0x0a, 0x24, + 0x40, 0x04, 0xfe, 0x0b, 0xaf, 0xf5, 0xc1, 0x45, 0x40, 0x24, 0x07, 0x30, + 0x40, 0xdb, 0xcc, 0x75, 0xc1, 0x45, 0xa1, 0x40, 0x63, 0x41, 0xc3, 0x42, + 0x00, 0x00, 0xef, 0xff, 0xe2, 0x0b, 0xaf, 0xf5, 0x0a, 0x24, 0x40, 0x04, + 0xc3, 0x40, 0x13, 0x00, 0x2c, 0x87, 0x2e, 0x09, 0x6f, 0xf5, 0x40, 0xc7, + 0xc3, 0x41, 0xa0, 0x00, 0xbc, 0x9a, 0x6a, 0x0c, 0x2f, 0xf3, 0x0c, 0x71, + 0xd3, 0x44, 0x13, 0x00, 0x78, 0x72, 0x58, 0x24, 0x40, 0x2b, 0xee, 0x08, + 0xaf, 0xf5, 0x2c, 0x71, 0x40, 0x21, 0x00, 0x35, 0xe2, 0x08, 0xaf, 0xf5, + 0x2c, 0x71, 0xd3, 0x47, 0x13, 0x00, 0x90, 0x77, 0x58, 0x27, 0x40, 0x2b, + 0x2e, 0x08, 0x20, 0x02, 0x10, 0xd9, 0xd3, 0x43, 0x13, 0x00, 0x2c, 0x75, + 0x40, 0x24, 0x05, 0x30, 0x54, 0x23, 0x81, 0x2d, 0x40, 0xda, 0x8a, 0x24, + 0x01, 0x08, 0xa1, 0x40, 0xe6, 0x0d, 0xa0, 0x01, 0x22, 0x43, 0x42, 0x27, + 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, + 0xa1, 0x40, 0xd2, 0x0d, 0xa0, 0x01, 0x22, 0x43, 0x55, 0x23, 0x01, 0x29, + 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0xba, 0x0d, 0xa0, 0x01, 0x22, 0x43, 0xd3, 0x46, 0x13, 0x00, 0x84, 0x83, + 0x40, 0x24, 0x05, 0x30, 0x55, 0x26, 0x01, 0x29, 0x40, 0xda, 0x8a, 0x24, + 0x01, 0x08, 0xa1, 0x40, 0x9e, 0x0d, 0xa0, 0x01, 0x22, 0x43, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xe2, 0x41, + 0x8a, 0x0d, 0xa0, 0x01, 0x22, 0x43, 0xc3, 0x40, 0x13, 0x00, 0xbc, 0x87, + 0x72, 0x08, 0x4f, 0xf5, 0xc3, 0x41, 0xa0, 0x00, 0x64, 0x9b, 0xb2, 0x0b, + 0x2f, 0xf3, 0x0c, 0x73, 0x40, 0x21, 0x00, 0x3f, 0x3a, 0x08, 0xaf, 0xf5, + 0x2c, 0x71, 0x54, 0x21, 0x00, 0x3a, 0x32, 0x08, 0xaf, 0xf5, 0x2c, 0x71, + 0x57, 0x27, 0x80, 0x2d, 0x82, 0x0f, 0xe0, 0x01, 0x10, 0xd9, 0xd3, 0x45, + 0x13, 0x00, 0xbc, 0x7e, 0x40, 0x24, 0x05, 0x30, 0x55, 0x25, 0x81, 0x2d, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x3a, 0x0d, 0xa0, 0x01, + 0x22, 0x43, 0xd3, 0x42, 0x13, 0x00, 0xf4, 0x79, 0x40, 0x24, 0x05, 0x30, + 0x58, 0x22, 0x01, 0x29, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0x1e, 0x0d, 0xa0, 0x01, 0x22, 0x43, 0x55, 0x25, 0xc1, 0x2f, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x0a, 0x0d, + 0xa0, 0x01, 0x22, 0x43, 0xdb, 0x40, 0x13, 0x00, 0xe8, 0x85, 0x40, 0x24, + 0x05, 0x30, 0x57, 0x20, 0x01, 0x39, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, + 0xa1, 0x40, 0xee, 0x0c, 0xa0, 0x01, 0x22, 0x43, 0x57, 0x22, 0x81, 0x2d, + 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0xd6, 0x0c, 0xa0, 0x01, 0x22, 0x43, 0xc3, 0x40, 0x13, 0x00, 0x74, 0x87, + 0xbe, 0x0f, 0x0f, 0xf5, 0xc3, 0x41, 0xa0, 0x00, 0x10, 0x9b, 0xfe, 0x0a, + 0x2f, 0xf3, 0x0c, 0x72, 0x58, 0x24, 0x00, 0x2a, 0x86, 0x0f, 0x6f, 0xf5, + 0x2c, 0x71, 0x40, 0x21, 0x00, 0x3a, 0x7e, 0x0f, 0x6f, 0xf5, 0x2c, 0x71, + 0x58, 0x27, 0x00, 0x29, 0xce, 0x0e, 0xe0, 0x01, 0x10, 0xd9, 0x58, 0x27, + 0xc1, 0x2f, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, + 0xa1, 0x40, 0x8e, 0x0c, 0xa0, 0x01, 0x22, 0x43, 0x54, 0x27, 0x81, 0x2d, + 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0x76, 0x0c, 0xa0, 0x01, 0x22, 0x43, 0x58, 0x27, 0x81, 0x2d, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x62, 0x0c, + 0xa0, 0x01, 0x22, 0x43, 0x55, 0x26, 0xc1, 0x2f, 0x40, 0x24, 0x05, 0x30, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x4a, 0x0c, 0xa0, 0x01, + 0x22, 0x43, 0x55, 0x27, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, + 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x36, 0x0c, 0xa0, 0x01, 0x22, 0x43, + 0x22, 0x0f, 0x2f, 0xf5, 0x56, 0x23, 0xc0, 0x39, 0xc3, 0x41, 0xa0, 0x00, + 0xd8, 0x99, 0xc6, 0x0b, 0x20, 0x01, 0x0c, 0x76, 0x2c, 0x71, 0xea, 0x0e, + 0x6f, 0xf5, 0x23, 0x40, 0x54, 0x23, 0x00, 0x3f, 0xde, 0x0e, 0x6f, 0xf5, + 0x2c, 0x71, 0x57, 0x24, 0x00, 0x2a, 0xd6, 0x0e, 0x6f, 0xf5, 0x2c, 0x70, + 0xc3, 0x40, 0x13, 0x00, 0x20, 0x81, 0x10, 0xd9, 0x22, 0x0e, 0xe0, 0x01, + 0x10, 0x40, 0x42, 0x20, 0x00, 0x29, 0x1a, 0x0e, 0xe0, 0x01, 0x2c, 0x70, + 0x57, 0x20, 0x00, 0x29, 0x0e, 0x0e, 0xe0, 0x01, 0x2c, 0x70, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x62, 0x41, + 0xce, 0x0b, 0xa0, 0x01, 0x22, 0x43, 0x54, 0x26, 0x01, 0x29, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xba, 0x0b, + 0xa0, 0x01, 0x22, 0x43, 0x57, 0x27, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xa2, 0x0b, 0xa0, 0x01, + 0x22, 0x43, 0x92, 0x0e, 0x2f, 0xf5, 0x56, 0x23, 0x40, 0x3e, 0xc3, 0x41, + 0xa0, 0x00, 0x70, 0x9a, 0x32, 0x0b, 0x20, 0x01, 0x09, 0xd8, 0x42, 0x24, + 0x00, 0x2a, 0x56, 0x0e, 0x6f, 0xf5, 0x2c, 0x71, 0x55, 0x23, 0x40, 0x3b, + 0x4a, 0x0e, 0x6f, 0xf5, 0x2c, 0x71, 0x42, 0x24, 0x00, 0x25, 0x42, 0x0e, + 0x6f, 0xf5, 0x2c, 0x70, 0x55, 0x20, 0x80, 0x2d, 0x92, 0x0d, 0xe0, 0x01, + 0x10, 0xd9, 0x55, 0x20, 0x40, 0x2b, 0x8a, 0x0d, 0xe0, 0x01, 0x2c, 0x70, + 0x55, 0x20, 0x00, 0x29, 0x7e, 0x0d, 0xe0, 0x01, 0x2c, 0x70, 0x42, 0x0e, + 0x2f, 0xf5, 0x56, 0x23, 0x00, 0x3c, 0xc3, 0x41, 0xa0, 0x00, 0x24, 0x9a, + 0xe2, 0x0a, 0x20, 0x01, 0x07, 0xd8, 0x55, 0x23, 0xc0, 0x38, 0x06, 0x0e, + 0x6f, 0xf5, 0x2c, 0x71, 0x55, 0x23, 0x00, 0x3a, 0xfa, 0x0d, 0x6f, 0xf5, + 0x2c, 0x71, 0x42, 0x24, 0x00, 0x2f, 0xf2, 0x0d, 0x6f, 0xf5, 0x2c, 0x70, + 0x54, 0x20, 0x80, 0x2d, 0x42, 0x0d, 0xe0, 0x01, 0x10, 0xd9, 0x54, 0x20, + 0x00, 0x29, 0x3a, 0x0d, 0xe0, 0x01, 0x2c, 0x70, 0x40, 0x20, 0x00, 0x29, + 0x2e, 0x0d, 0xe0, 0x01, 0x2c, 0x70, 0x56, 0x23, 0x01, 0x29, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xee, 0x0a, + 0xa0, 0x01, 0x22, 0x43, 0x55, 0x26, 0x41, 0x2b, 0x40, 0x24, 0x05, 0x30, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xd6, 0x0a, 0xa0, 0x01, + 0x22, 0x43, 0x54, 0x27, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, + 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xc2, 0x0a, 0xa0, 0x01, 0x22, 0x43, + 0xae, 0x0d, 0x2f, 0xf5, 0x55, 0x20, 0x40, 0x3b, 0xc3, 0x41, 0xa0, 0x00, + 0x44, 0x9d, 0x46, 0x08, 0x2f, 0xf3, 0x10, 0xd8, 0x58, 0x24, 0xc0, 0x2d, + 0x72, 0x0d, 0x6f, 0xf5, 0x2c, 0x70, 0x40, 0x23, 0x00, 0x29, 0xc6, 0x0c, + 0xe0, 0x01, 0x10, 0xd9, 0x86, 0x0d, 0x2f, 0xf5, 0x55, 0x20, 0xc0, 0x3f, + 0xc3, 0x41, 0xa0, 0x00, 0x88, 0xa2, 0xd2, 0x08, 0x20, 0x01, 0x0b, 0xd8, + 0x58, 0x23, 0xc0, 0x2e, 0x4a, 0x0d, 0x6f, 0xf5, 0x2c, 0x70, 0x58, 0x24, + 0x00, 0x2f, 0x42, 0x0d, 0x6f, 0xf5, 0x2c, 0x70, 0x42, 0x23, 0x00, 0x29, + 0x92, 0x0c, 0xe0, 0x01, 0x10, 0xd9, 0x54, 0x23, 0x01, 0x29, 0x40, 0x24, + 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x52, 0x0a, + 0xa0, 0x01, 0xa1, 0x40, 0x54, 0x26, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, + 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x3a, 0x0a, 0xa0, 0x01, + 0xa1, 0x40, 0x2a, 0x0d, 0x2f, 0xf5, 0x55, 0x24, 0x00, 0x2e, 0xc3, 0x41, + 0xa0, 0x00, 0x5c, 0xa7, 0xae, 0x09, 0x2f, 0xf3, 0x0d, 0xd8, 0x57, 0x23, + 0x80, 0x2e, 0xee, 0x0c, 0x6f, 0xf5, 0x2c, 0x70, 0x58, 0x23, 0x00, 0x2b, + 0xe2, 0x0c, 0x6f, 0xf5, 0x2c, 0x70, 0x40, 0x25, 0x00, 0x29, 0x36, 0x0c, + 0xe0, 0x01, 0x10, 0xd9, 0x42, 0x25, 0x00, 0x29, 0x2a, 0x0c, 0xe0, 0x01, + 0x40, 0xd9, 0xee, 0x0c, 0x2f, 0xf5, 0x56, 0x24, 0x40, 0x29, 0xc3, 0x41, + 0xa0, 0x00, 0x1c, 0xaa, 0x72, 0x09, 0x20, 0x01, 0x0e, 0xd8, 0x58, 0x23, + 0xc0, 0x29, 0xb2, 0x0c, 0x6f, 0xf5, 0x2c, 0x70, 0x54, 0x25, 0x00, 0x29, + 0x02, 0x0c, 0xe0, 0x01, 0x2c, 0x70, 0x10, 0xd9, 0xfa, 0x0b, 0xe0, 0x01, + 0xa2, 0x40, 0xbe, 0x0c, 0x2f, 0xf5, 0x56, 0x24, 0x80, 0x2b, 0xc3, 0x41, + 0xa0, 0x00, 0x10, 0x99, 0x0a, 0x0a, 0x2f, 0xf3, 0x29, 0xd8, 0x57, 0x23, + 0x80, 0x29, 0x82, 0x0c, 0x6f, 0xf5, 0x2c, 0x70, 0x10, 0xd9, 0xd6, 0x0b, + 0xe0, 0x01, 0xc2, 0x40, 0xcb, 0x46, 0xa0, 0x00, 0x2e, 0x6f, 0x00, 0x96, + 0x50, 0xd9, 0x04, 0x20, 0x80, 0x0f, 0x00, 0x00, 0x7f, 0xff, 0x00, 0xb6, + 0xba, 0x0b, 0xe0, 0x01, 0x40, 0x26, 0x00, 0x29, 0x0a, 0x96, 0x55, 0x25, + 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x04, 0x20, 0x80, 0x0f, 0x00, 0x00, + 0x7f, 0xff, 0x0a, 0xb6, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0x6a, 0x09, 0xa0, 0x01, 0x22, 0x43, 0x57, 0x20, 0x81, 0x3d, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x56, 0x09, + 0xa0, 0x01, 0x22, 0x43, 0x58, 0x22, 0x41, 0x2b, 0x40, 0x24, 0x05, 0x30, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x3e, 0x09, 0xa0, 0x01, + 0x22, 0x43, 0x54, 0x25, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x2a, 0x09, 0xa0, 0x01, 0xa1, 0x40, + 0x58, 0x20, 0x01, 0x39, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, + 0x8a, 0x24, 0x01, 0x08, 0x12, 0x09, 0xa0, 0x01, 0xa1, 0x40, 0xc3, 0x40, + 0x13, 0x00, 0xdc, 0x88, 0xfa, 0x0b, 0x0f, 0xf5, 0xc3, 0x41, 0xa0, 0x00, + 0xd4, 0x9c, 0x66, 0x08, 0x2f, 0xf3, 0x12, 0xd8, 0x58, 0x23, 0x80, 0x28, + 0xc2, 0x0b, 0x6f, 0xf5, 0x2c, 0x70, 0x55, 0x25, 0x40, 0x2b, 0x16, 0x0b, + 0xe0, 0x01, 0x10, 0xd9, 0xd6, 0x0b, 0x2f, 0xf5, 0x55, 0x23, 0x00, 0x3f, + 0xc3, 0x41, 0xa0, 0x00, 0xf0, 0x9e, 0x26, 0x08, 0x20, 0x01, 0x0c, 0xd8, + 0x58, 0x23, 0x40, 0x2c, 0x9a, 0x0b, 0x6f, 0xf5, 0x2c, 0x70, 0x58, 0x25, + 0x00, 0x29, 0xee, 0x0a, 0xe0, 0x01, 0x10, 0xd9, 0x58, 0x25, 0x80, 0x2d, + 0xe2, 0x0a, 0xe0, 0x01, 0x40, 0xd9, 0x58, 0x25, 0x40, 0x2b, 0xda, 0x0a, + 0xe0, 0x01, 0x40, 0xd9, 0x59, 0x27, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, + 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x96, 0x08, 0xa0, 0x01, + 0xa1, 0x40, 0x55, 0x26, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x82, 0x08, 0xa0, 0x01, 0xa1, 0x40, + 0x6e, 0x0b, 0x2f, 0xf5, 0x55, 0x21, 0x00, 0x3a, 0xc3, 0x41, 0xa0, 0x00, + 0xe4, 0x9f, 0xea, 0x0e, 0xef, 0xf2, 0x15, 0xd8, 0xc3, 0x41, 0x00, 0x00, + 0xef, 0xff, 0x32, 0x0b, 0x6f, 0xf5, 0x54, 0x21, 0x80, 0x3c, 0xcb, 0x47, + 0x13, 0x00, 0x58, 0x7c, 0x58, 0x27, 0xc0, 0x1f, 0x7a, 0x0a, 0xe0, 0x01, + 0x10, 0xd9, 0x58, 0x27, 0x00, 0x19, 0x72, 0x0a, 0xe0, 0x01, 0x2c, 0x70, + 0x58, 0x27, 0x80, 0x1d, 0x66, 0x0a, 0xe0, 0x01, 0x2c, 0x70, 0x00, 0x16, + 0x00, 0x71, 0xa0, 0x00, 0xde, 0x6e, 0x2c, 0x70, 0xa2, 0xb8, 0x00, 0x1e, + 0x04, 0x70, 0xa0, 0x00, 0xde, 0x6e, 0x4e, 0x0a, 0xe0, 0x01, 0x58, 0x27, + 0x40, 0x1b, 0x00, 0x16, 0x00, 0x71, 0xa0, 0x00, 0xf2, 0x6e, 0x55, 0x27, + 0x01, 0x19, 0x40, 0x24, 0x05, 0x30, 0xa2, 0xb8, 0x00, 0x1e, 0x04, 0x70, + 0xa0, 0x00, 0xf2, 0x6e, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0xf6, 0x0f, 0x60, 0x01, 0x22, 0x43, 0x58, 0x20, 0xc1, 0x3f, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xe2, 0x0f, + 0x60, 0x01, 0x22, 0x43, 0x55, 0x27, 0xc1, 0x2f, 0x40, 0x24, 0x05, 0x30, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xca, 0x0f, 0x60, 0x01, + 0x22, 0x43, 0xba, 0x0a, 0x2f, 0xf5, 0x55, 0x24, 0x80, 0x29, 0xc3, 0x41, + 0xa0, 0x00, 0x6c, 0x9c, 0x46, 0x0e, 0xef, 0xf2, 0x17, 0xd8, 0xc3, 0x41, + 0x00, 0x00, 0xef, 0xff, 0x7a, 0x0a, 0x6f, 0xf5, 0x54, 0x21, 0x00, 0x3f, + 0x57, 0x27, 0x00, 0x19, 0xca, 0x09, 0xe0, 0x01, 0x10, 0xd9, 0x57, 0x27, + 0x80, 0x1d, 0xc2, 0x09, 0xe0, 0x01, 0x2c, 0x70, 0x54, 0x27, 0x81, 0x1d, + 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0x7e, 0x0f, 0x60, 0x01, 0x22, 0x43, 0x59, 0x20, 0x01, 0x39, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x6a, 0x0f, + 0x60, 0x01, 0x22, 0x43, 0x55, 0x27, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x52, 0x0f, 0x60, 0x01, + 0x22, 0x43, 0x42, 0x0a, 0x2f, 0xf5, 0x55, 0x21, 0x80, 0x3e, 0xc3, 0x41, + 0xa0, 0x00, 0xb8, 0xa4, 0x3e, 0x0e, 0xe0, 0x00, 0x18, 0xd8, 0xc3, 0x41, + 0x00, 0x00, 0xef, 0xff, 0x02, 0x0a, 0x6f, 0xf5, 0x55, 0x21, 0xc0, 0x38, + 0x4c, 0x4f, 0x56, 0x09, 0xe0, 0x01, 0x10, 0xd9, 0x42, 0x27, 0x00, 0x19, + 0x4a, 0x09, 0xe0, 0x01, 0x2c, 0x70, 0x2c, 0x70, 0x42, 0x09, 0xe0, 0x01, + 0xe1, 0x40, 0x00, 0x16, 0x00, 0x71, 0xa0, 0x00, 0x06, 0x6f, 0x2c, 0x70, + 0xa2, 0xb8, 0x00, 0x1e, 0x04, 0x70, 0xa0, 0x00, 0x06, 0x6f, 0x2a, 0x09, + 0xe0, 0x01, 0x54, 0x27, 0x00, 0x19, 0x58, 0x20, 0x81, 0x2d, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xe6, 0x0e, + 0x60, 0x01, 0x22, 0x43, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, + 0x01, 0x08, 0xa1, 0x40, 0x03, 0x41, 0xd2, 0x0e, 0x60, 0x01, 0x22, 0x43, + 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0x42, 0x41, 0xbe, 0x0e, 0x60, 0x01, 0x22, 0x43, 0xaa, 0x09, 0x2f, 0xf5, + 0x56, 0x21, 0x80, 0x39, 0xc3, 0x41, 0xa0, 0x00, 0x78, 0x98, 0xca, 0x0d, + 0xe0, 0x00, 0x2a, 0xd8, 0xc3, 0x41, 0x00, 0x00, 0xef, 0xff, 0x6e, 0x09, + 0x6f, 0xf5, 0x40, 0x23, 0x00, 0x3a, 0xc3, 0x41, 0x00, 0x00, 0xef, 0xff, + 0x5e, 0x09, 0x6f, 0xf5, 0x40, 0x23, 0x00, 0x3f, 0xc3, 0x41, 0x00, 0x00, + 0xef, 0xff, 0x52, 0x09, 0x6f, 0xf5, 0x54, 0x23, 0x00, 0x3a, 0x55, 0x27, + 0xc0, 0x1f, 0xa2, 0x08, 0xe0, 0x01, 0x2c, 0x70, 0x00, 0x16, 0x00, 0x71, + 0xa0, 0x00, 0x1a, 0x6f, 0x10, 0xd9, 0x04, 0x20, 0x80, 0x0f, 0x00, 0x00, + 0x7f, 0xff, 0x00, 0x1e, 0x04, 0x70, 0xa0, 0x00, 0x1a, 0x6f, 0x82, 0x08, + 0xe0, 0x01, 0x56, 0x27, 0x00, 0x19, 0x59, 0x25, 0x00, 0x29, 0x76, 0x08, + 0xe0, 0x01, 0x10, 0xd9, 0x58, 0x25, 0xc0, 0x2f, 0x6a, 0x08, 0xe0, 0x01, + 0x4a, 0x21, 0x00, 0x04, 0x4a, 0x24, 0xc0, 0x70, 0x58, 0x23, 0x82, 0x2f, + 0xa8, 0x20, 0xc0, 0x02, 0x04, 0x12, 0x00, 0x04, 0x08, 0x80, 0x21, 0x90, + 0x04, 0x21, 0x81, 0x0f, 0x00, 0x00, 0x7f, 0xff, 0x21, 0xb0, 0xcd, 0x70, + 0x8f, 0xbe, 0x56, 0x25, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, + 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x06, 0x0e, 0x60, 0x01, 0xc1, 0x43, + 0x58, 0x20, 0x81, 0x3d, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, + 0x01, 0x08, 0xa1, 0x40, 0xee, 0x0d, 0x60, 0x01, 0xc1, 0x43, 0x59, 0x22, + 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, + 0xa1, 0x40, 0xda, 0x0d, 0x60, 0x01, 0xc1, 0x43, 0x59, 0x20, 0x01, 0x29, + 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, + 0xc2, 0x0d, 0x60, 0x01, 0xc1, 0x43, 0x58, 0x20, 0x41, 0x3b, 0x40, 0x24, + 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0xae, 0x0d, + 0x60, 0x01, 0xc1, 0x43, 0x58, 0x22, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, + 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x96, 0x0d, 0x60, 0x01, + 0xc1, 0x43, 0x58, 0x20, 0xc1, 0x2f, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, + 0x8a, 0x24, 0x01, 0x08, 0xa1, 0x40, 0x82, 0x0d, 0x60, 0x01, 0xc1, 0x43, + 0x42, 0x20, 0x01, 0x39, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, + 0x01, 0x08, 0xa1, 0x40, 0x6a, 0x0d, 0x60, 0x01, 0xc1, 0x43, 0x57, 0x22, + 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x40, 0xda, 0x8a, 0x24, 0x01, 0x08, + 0xa1, 0x40, 0x56, 0x0d, 0x60, 0x01, 0xc1, 0x43, 0xc3, 0x40, 0x13, 0x00, + 0xfc, 0x89, 0x3e, 0x08, 0x0f, 0xf5, 0xc3, 0x41, 0xa0, 0x00, 0x48, 0x9e, + 0x2a, 0x0d, 0xe0, 0x00, 0x1f, 0xd8, 0x55, 0x23, 0x80, 0x3c, 0x06, 0x08, + 0x6f, 0xf5, 0x2c, 0x70, 0x57, 0x23, 0x00, 0x2c, 0xfa, 0x0f, 0x2f, 0xf5, + 0x2c, 0x70, 0x42, 0x23, 0x00, 0x2e, 0xf2, 0x0f, 0x2f, 0xf5, 0x2c, 0x70, + 0x58, 0x23, 0x80, 0x2d, 0xe6, 0x0f, 0x2f, 0xf5, 0x2c, 0x70, 0x58, 0x26, + 0x80, 0x2d, 0x3a, 0x0f, 0xa0, 0x01, 0x10, 0xd9, 0x58, 0x26, 0x41, 0x2b, + 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, + 0xf6, 0x0c, 0x60, 0x01, 0xa1, 0x40, 0x54, 0x20, 0x01, 0x39, 0x40, 0x24, + 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0xe2, 0x0c, + 0x60, 0x01, 0xa1, 0x40, 0x55, 0x22, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, + 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0xca, 0x0c, 0x60, 0x01, + 0xa1, 0x40, 0x58, 0x20, 0x41, 0x2b, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0xb6, 0x0c, 0x60, 0x01, 0xa1, 0x40, + 0x40, 0x20, 0x01, 0x39, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, + 0x8a, 0x24, 0x01, 0x08, 0x9e, 0x0c, 0x60, 0x01, 0xa1, 0x40, 0x54, 0x22, + 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, + 0x01, 0x08, 0x8a, 0x0c, 0x60, 0x01, 0xa1, 0x40, 0xc3, 0x40, 0x13, 0x00, + 0x6c, 0x89, 0x72, 0x0f, 0xcf, 0xf4, 0xc3, 0x41, 0xa0, 0x00, 0x9c, 0x99, + 0x56, 0x0c, 0xef, 0xf2, 0x20, 0xd8, 0x2c, 0x70, 0x3a, 0x0f, 0x2f, 0xf5, + 0x82, 0x40, 0x55, 0x20, 0xc0, 0x2f, 0x8e, 0x0e, 0xa0, 0x01, 0x10, 0xd9, + 0x56, 0x20, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, + 0x8a, 0x24, 0x01, 0x08, 0x4a, 0x0c, 0x60, 0x01, 0xa1, 0x40, 0x40, 0x22, + 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, + 0x01, 0x08, 0x36, 0x0c, 0x60, 0x01, 0xa1, 0x40, 0xc3, 0x40, 0x13, 0x00, + 0x8c, 0x8a, 0x1e, 0x0f, 0xcf, 0xf4, 0xc3, 0x41, 0xa0, 0x00, 0xb8, 0x9b, + 0x46, 0x0c, 0xef, 0xf2, 0x21, 0xd8, 0x55, 0x23, 0xc0, 0x3d, 0xe6, 0x0e, + 0x2f, 0xf5, 0x2c, 0x70, 0x57, 0x26, 0x00, 0x29, 0x36, 0x0e, 0xa0, 0x01, + 0x10, 0xd9, 0x42, 0x26, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0xf6, 0x0b, 0x60, 0x01, 0xa1, 0x40, + 0x55, 0x22, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, + 0x8a, 0x24, 0x01, 0x08, 0xde, 0x0b, 0x60, 0x01, 0xa1, 0x40, 0xc3, 0x40, + 0x13, 0x00, 0xd4, 0x8a, 0xc6, 0x0e, 0xcf, 0xf4, 0xc3, 0x41, 0xa0, 0x00, + 0xbc, 0x9d, 0xd2, 0x0b, 0xe0, 0x00, 0x3c, 0xd8, 0x40, 0x24, 0x00, 0x2f, + 0x8e, 0x0e, 0x2f, 0xf5, 0x2c, 0x70, 0x54, 0x20, 0x80, 0x3d, 0xe2, 0x0d, + 0xa0, 0x01, 0x10, 0xd9, 0x55, 0x20, 0x01, 0x39, 0x40, 0x24, 0x05, 0x30, + 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x9e, 0x0b, 0x60, 0x01, + 0xa1, 0x40, 0x55, 0x22, 0xc1, 0x2f, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x8a, 0x0b, 0x60, 0x01, 0xa1, 0x40, + 0x76, 0x0e, 0xef, 0xf4, 0x54, 0x24, 0x00, 0x2a, 0xc3, 0x41, 0xa0, 0x00, + 0x14, 0xa1, 0x42, 0x09, 0xef, 0xf2, 0x22, 0xd8, 0x58, 0x24, 0x80, 0x2c, + 0x3a, 0x0e, 0x2f, 0xf5, 0x2c, 0x70, 0x55, 0x23, 0x40, 0x2b, 0x8e, 0x0d, + 0xa0, 0x01, 0x10, 0xd9, 0x55, 0x23, 0xc0, 0x2f, 0x82, 0x0d, 0xa0, 0x01, + 0x2c, 0x70, 0x55, 0x23, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x42, 0x0b, 0x60, 0x01, 0xa1, 0x40, + 0x40, 0x27, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, + 0x8a, 0x24, 0x01, 0x08, 0x2a, 0x0b, 0x60, 0x01, 0xa1, 0x40, 0xc3, 0x40, + 0x13, 0x00, 0x44, 0x8a, 0x12, 0x0e, 0xcf, 0xf4, 0xc3, 0x41, 0xa0, 0x00, + 0x10, 0x9c, 0x26, 0x0b, 0xef, 0xf2, 0x2b, 0xd8, 0x40, 0x24, 0x00, 0x2a, + 0xda, 0x0d, 0x2f, 0xf5, 0x2c, 0x70, 0x58, 0x26, 0x00, 0x29, 0x2e, 0x0d, + 0xa0, 0x01, 0x10, 0xd9, 0x57, 0x26, 0x81, 0x2d, 0x40, 0x24, 0x05, 0x30, + 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0xea, 0x0a, 0x60, 0x01, + 0xa1, 0x40, 0x55, 0x22, 0x41, 0x2b, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0xd6, 0x0a, 0x60, 0x01, 0xa1, 0x40, + 0xc3, 0x40, 0x13, 0x00, 0x4c, 0x88, 0xbe, 0x0d, 0xcf, 0xf4, 0xc3, 0x41, + 0xa0, 0x00, 0x90, 0x98, 0x86, 0x09, 0xef, 0xf2, 0x2c, 0xd8, 0x58, 0x24, + 0xc0, 0x28, 0x86, 0x0d, 0x2f, 0xf5, 0x2c, 0x70, 0x55, 0x27, 0x40, 0x1b, + 0xd6, 0x0c, 0xa0, 0x01, 0x10, 0xd9, 0x55, 0x27, 0x81, 0x1d, 0x40, 0x24, + 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x96, 0x0a, + 0x60, 0x01, 0xa1, 0x40, 0x56, 0x27, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, + 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x7e, 0x0a, 0x60, 0x01, + 0xa1, 0x40, 0xc3, 0x40, 0x13, 0x00, 0x24, 0x89, 0x66, 0x0d, 0xcf, 0xf4, + 0xc3, 0x41, 0xa0, 0x00, 0xac, 0x98, 0x22, 0x0a, 0xef, 0xf2, 0x2d, 0xd8, + 0x57, 0x24, 0x80, 0x2c, 0x2e, 0x0d, 0x2f, 0xf5, 0x2c, 0x70, 0x58, 0x20, + 0x00, 0x29, 0x82, 0x0c, 0xa0, 0x01, 0x10, 0xd9, 0x57, 0x20, 0x81, 0x2d, + 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, + 0x3e, 0x0a, 0x60, 0x01, 0xa1, 0x40, 0x42, 0x22, 0x01, 0x29, 0x40, 0x24, + 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x2a, 0x0a, + 0x60, 0x01, 0xa1, 0x40, 0xc3, 0x40, 0x13, 0x00, 0xb4, 0x89, 0x12, 0x0d, + 0xcf, 0xf4, 0xc3, 0x41, 0xa0, 0x00, 0xcc, 0x98, 0xd2, 0x09, 0xe0, 0x00, + 0x3d, 0xd8, 0x40, 0x24, 0x00, 0x25, 0xda, 0x0c, 0x2f, 0xf5, 0x2c, 0x70, + 0x59, 0x26, 0x00, 0x29, 0x2a, 0x0c, 0xa0, 0x01, 0x10, 0xd9, 0x58, 0x26, + 0xc1, 0x2f, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, + 0x01, 0x08, 0xea, 0x09, 0x60, 0x01, 0xa1, 0x40, 0x54, 0x22, 0x01, 0x29, + 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, + 0xd2, 0x09, 0x60, 0x01, 0xa1, 0x40, 0xc3, 0x40, 0x13, 0x00, 0x94, 0x88, + 0xba, 0x0c, 0xcf, 0xf4, 0xc3, 0x41, 0xa0, 0x00, 0x34, 0x99, 0x2a, 0x09, + 0xe0, 0x00, 0x40, 0xd8, 0x57, 0x24, 0x00, 0x2f, 0x82, 0x0c, 0x2f, 0xf5, + 0x2c, 0x70, 0x57, 0x25, 0x80, 0x2d, 0xd6, 0x0b, 0xa0, 0x01, 0x10, 0xd9, + 0x57, 0x25, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, + 0x8a, 0x24, 0x01, 0x08, 0x92, 0x09, 0x60, 0x01, 0xa1, 0x40, 0x58, 0x22, + 0xc1, 0x2f, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, + 0x01, 0x08, 0x7e, 0x09, 0x60, 0x01, 0xa1, 0x40, 0xc3, 0x40, 0x13, 0x00, + 0x04, 0x88, 0x66, 0x0c, 0xcf, 0xf4, 0xc3, 0x41, 0xa0, 0x00, 0xec, 0x98, + 0x4a, 0x08, 0xe0, 0x00, 0x41, 0xd8, 0x40, 0x23, 0x00, 0x35, 0x2e, 0x0c, + 0x2f, 0xf5, 0x2c, 0x70, 0x56, 0x22, 0x00, 0x29, 0x7e, 0x0b, 0xa0, 0x01, + 0x10, 0xd9, 0x59, 0x27, 0x01, 0x19, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, + 0x6c, 0x70, 0x8a, 0x24, 0x01, 0x08, 0x3e, 0x09, 0x60, 0x01, 0xa1, 0x40, + 0x56, 0x26, 0x01, 0x29, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, + 0x8a, 0x24, 0x01, 0x08, 0x26, 0x09, 0x60, 0x01, 0xa1, 0x40, 0x55, 0x27, + 0x41, 0x2b, 0x40, 0x24, 0x05, 0x30, 0x4c, 0x70, 0x6c, 0x70, 0x8a, 0x24, + 0x01, 0x08, 0x12, 0x09, 0x60, 0x01, 0xa1, 0x40, 0x86, 0x09, 0xaf, 0xf5, + 0xa1, 0x40, 0x87, 0x74, 0x04, 0x14, 0x1b, 0x34, 0xda, 0xc6, 0xe0, 0x78, + 0xe4, 0xc2, 0x08, 0x46, 0x03, 0x80, 0x00, 0x80, 0x48, 0x80, 0x04, 0x82, + 0x61, 0x92, 0x23, 0x82, 0xa0, 0x80, 0x11, 0x86, 0x82, 0xbb, 0x22, 0x0d, + 0xaf, 0xfb, 0x61, 0xb2, 0x19, 0x08, 0xfe, 0x01, 0x00, 0x42, 0x24, 0x86, + 0xc6, 0xba, 0x00, 0x81, 0x64, 0x80, 0x22, 0x83, 0x40, 0xa9, 0x23, 0x80, + 0x60, 0x79, 0xa1, 0xa3, 0xc4, 0xc6, 0xe0, 0x78, 0xe2, 0xc2, 0x11, 0x80, + 0x56, 0x0f, 0xaf, 0xfb, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0x11, 0x80, 0xd5, 0x07, 0xaf, 0xfb, 0x2f, 0x79, 0xe2, 0xc2, 0x11, 0x80, + 0xf2, 0x0f, 0xaf, 0xfb, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0x21, 0x01, 0xef, 0xfb, 0x11, 0x80, 0xe0, 0x78, 0x11, 0x04, 0xaf, 0xfb, + 0x11, 0x80, 0xe0, 0x78, 0x91, 0x01, 0xef, 0xfb, 0x11, 0x80, 0xe0, 0x78, + 0x71, 0x02, 0xef, 0xfb, 0x11, 0x80, 0xe0, 0x78, 0xec, 0xc3, 0x83, 0x80, + 0x08, 0x47, 0x00, 0x84, 0xa8, 0x80, 0x02, 0x15, 0x09, 0x11, 0x4f, 0x21, + 0x80, 0x10, 0x01, 0xb5, 0x01, 0x84, 0xc8, 0x80, 0x02, 0x16, 0x08, 0x11, + 0x4f, 0x20, 0x80, 0x10, 0x01, 0xb6, 0x02, 0x84, 0x44, 0x85, 0x63, 0x86, + 0x23, 0x85, 0x08, 0x80, 0x00, 0x12, 0x11, 0x00, 0x0c, 0x10, 0x0b, 0x00, + 0x0f, 0x0b, 0x30, 0x10, 0xa8, 0xc1, 0x41, 0x90, 0x82, 0xba, 0x41, 0xb0, + 0x05, 0xf0, 0x40, 0x24, 0x0b, 0x33, 0x0c, 0x1c, 0x01, 0x30, 0x03, 0x84, + 0x41, 0x28, 0x88, 0x10, 0x08, 0x80, 0x43, 0x80, 0x40, 0x45, 0x06, 0xea, + 0x41, 0x90, 0x82, 0xba, 0x41, 0xb0, 0x06, 0xf0, 0x40, 0x24, 0x05, 0x32, + 0x08, 0x1c, 0x01, 0x30, 0x50, 0x87, 0x80, 0x95, 0xa0, 0x96, 0x01, 0x92, + 0x17, 0x08, 0x3e, 0x00, 0x44, 0x20, 0x44, 0x10, 0x44, 0x21, 0x08, 0x11, + 0x05, 0x24, 0x3e, 0x82, 0x2a, 0xf4, 0xa0, 0xb8, 0x01, 0xb2, 0x48, 0x34, + 0x02, 0x10, 0x48, 0x35, 0x00, 0x10, 0x07, 0x30, 0x86, 0x00, 0x04, 0x87, + 0x49, 0x8f, 0x80, 0x80, 0x91, 0x40, 0x13, 0x0a, 0xb4, 0x00, 0x10, 0x14, + 0x12, 0x10, 0xa1, 0x80, 0xc4, 0x85, 0x82, 0x86, 0x02, 0xf0, 0x84, 0xc4, + 0x08, 0x12, 0x07, 0x20, 0x65, 0x42, 0x11, 0x87, 0xd2, 0x09, 0xef, 0xfb, + 0x40, 0xc4, 0x04, 0x1a, 0x40, 0x24, 0x1e, 0x41, 0x60, 0x79, 0x02, 0x40, + 0x09, 0x8f, 0x11, 0x08, 0xb4, 0x00, 0xa1, 0x40, 0x04, 0x1e, 0x40, 0x14, + 0x23, 0x85, 0x40, 0x79, 0xcc, 0xc7, 0xe0, 0x78, 0xe8, 0xc2, 0x63, 0x80, + 0x00, 0x41, 0x00, 0x83, 0x61, 0x83, 0x48, 0x80, 0x68, 0x83, 0x10, 0x81, + 0xe1, 0x92, 0x4f, 0x27, 0x8c, 0x10, 0x81, 0xb2, 0x84, 0x82, 0xa1, 0x93, + 0xc1, 0x90, 0x00, 0x12, 0x08, 0x01, 0x00, 0x13, 0x09, 0x01, 0x0c, 0x13, + 0x07, 0x00, 0x43, 0x82, 0x00, 0x14, 0x10, 0x10, 0x4f, 0x25, 0x8b, 0x10, + 0x22, 0xbd, 0x02, 0x1b, 0xc4, 0x02, 0x1b, 0x0e, 0x3e, 0x10, 0x44, 0x25, + 0x43, 0x10, 0x44, 0x27, 0x0c, 0x11, 0x05, 0x23, 0x3e, 0x83, 0x03, 0xf2, + 0xc8, 0xc6, 0xa0, 0xbe, 0xc1, 0xb0, 0x84, 0x81, 0x48, 0x30, 0x0b, 0x10, + 0x48, 0x31, 0x00, 0x10, 0x0a, 0x24, 0x00, 0x04, 0xa0, 0x84, 0x07, 0x30, + 0xc5, 0x02, 0x11, 0x81, 0xe0, 0x41, 0xc4, 0x85, 0x4a, 0x0b, 0xef, 0xfb, + 0x08, 0x16, 0x06, 0x10, 0x23, 0x85, 0xa1, 0x40, 0x60, 0x79, 0x04, 0x1e, + 0x00, 0x14, 0xc8, 0xc6, 0xe6, 0xc3, 0xa6, 0xc1, 0x83, 0x80, 0x00, 0x41, + 0xec, 0x70, 0x00, 0x84, 0x62, 0x84, 0xe8, 0x80, 0x01, 0x84, 0x02, 0x17, + 0x05, 0x11, 0x08, 0x80, 0x4f, 0x25, 0x82, 0x00, 0x41, 0xb7, 0xa1, 0x90, + 0x68, 0x83, 0x4f, 0x25, 0x82, 0x10, 0x41, 0xb0, 0x41, 0x93, 0x83, 0x84, + 0x41, 0x2d, 0x84, 0x10, 0x4f, 0x22, 0x8d, 0x00, 0xa1, 0xb3, 0x88, 0x84, + 0xc4, 0x87, 0x0c, 0x17, 0x08, 0x10, 0x0c, 0x10, 0x09, 0x00, 0xa1, 0x94, + 0x0c, 0x13, 0x0b, 0x00, 0xc0, 0x86, 0x19, 0x0d, 0xbf, 0x10, 0x41, 0x2a, + 0x86, 0x00, 0x43, 0x84, 0x82, 0xbd, 0xa1, 0xb4, 0x00, 0x12, 0x87, 0x00, + 0x85, 0x27, 0x3e, 0x00, 0x90, 0x81, 0x40, 0x93, 0xa0, 0x97, 0x00, 0x90, + 0x61, 0x94, 0x44, 0x24, 0x44, 0x00, 0x1f, 0x0b, 0x3e, 0x00, 0x44, 0x26, + 0x46, 0x00, 0x44, 0x25, 0x05, 0x01, 0x05, 0x25, 0x05, 0x01, 0x05, 0x25, + 0xbe, 0x81, 0x03, 0xf2, 0xc6, 0xc7, 0xa0, 0xbb, 0x61, 0xb4, 0x48, 0x35, + 0x0c, 0x10, 0x48, 0x32, 0x03, 0x00, 0x2f, 0x27, 0xc7, 0x01, 0x48, 0x30, + 0x02, 0x00, 0x04, 0x81, 0x07, 0x33, 0x03, 0x03, 0x07, 0x32, 0x02, 0x03, + 0xc1, 0x45, 0xa0, 0x80, 0x11, 0x81, 0xe4, 0x85, 0x22, 0x87, 0x42, 0xc1, + 0x41, 0xc3, 0x40, 0xc2, 0x21, 0x41, 0x01, 0x42, 0x4a, 0x0d, 0xef, 0xfb, + 0x61, 0x43, 0x23, 0x85, 0xa1, 0x40, 0x60, 0x79, 0xc1, 0xa7, 0xc6, 0xc7, + 0xe2, 0xc2, 0x11, 0x80, 0x92, 0x0e, 0xef, 0xfb, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0xad, 0x07, 0xef, 0xfb, 0x2f, 0x79, + 0xe2, 0xc2, 0x11, 0x80, 0x9a, 0x08, 0x2f, 0xfc, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x2d, 0x07, 0x2f, 0xfc, 0x11, 0x80, 0xe0, 0x78, + 0x91, 0x04, 0xef, 0xfb, 0x11, 0x80, 0xe0, 0x78, 0x21, 0x00, 0x6f, 0xfc, + 0x11, 0x80, 0xe0, 0x78, 0xe5, 0x00, 0x6f, 0xfc, 0x11, 0x80, 0xe0, 0x78, + 0xec, 0xc2, 0xa0, 0x80, 0x68, 0x46, 0x50, 0x41, 0x8a, 0x85, 0xeb, 0x85, + 0x0c, 0x84, 0x17, 0x08, 0x71, 0x00, 0x30, 0x40, 0xe1, 0x40, 0x80, 0x20, + 0x0e, 0x00, 0x30, 0x1c, 0x01, 0x10, 0x00, 0x18, 0x03, 0x00, 0x44, 0x20, + 0x52, 0xa0, 0x0b, 0xf2, 0x80, 0x27, 0x0e, 0x10, 0x00, 0x8f, 0x0f, 0x08, + 0xa5, 0x03, 0xa1, 0x40, 0xd2, 0x08, 0x40, 0x01, 0xc0, 0xaf, 0x78, 0x22, + 0x01, 0x20, 0x85, 0xee, 0x0c, 0x77, 0x83, 0xe9, 0xcc, 0xc6, 0x78, 0x26, + 0x00, 0x10, 0x05, 0x20, 0x7e, 0x80, 0x32, 0xf4, 0x0a, 0x24, 0x80, 0x73, + 0x40, 0x21, 0x0b, 0x24, 0xed, 0x70, 0x2c, 0x70, 0x4c, 0x70, 0x6c, 0x70, + 0x0a, 0x20, 0x40, 0x04, 0xa8, 0x20, 0x80, 0x04, 0x18, 0x13, 0x0c, 0x15, + 0x95, 0x71, 0xca, 0x23, 0x01, 0x00, 0x0b, 0xf2, 0x95, 0x75, 0xca, 0x21, + 0x01, 0x00, 0x07, 0xf2, 0x09, 0x0c, 0xd1, 0x10, 0x00, 0x42, 0x03, 0xf0, + 0xe1, 0x80, 0x18, 0xe0, 0x03, 0xea, 0xe1, 0x82, 0x06, 0xf0, 0x04, 0xeb, + 0xe1, 0x83, 0x04, 0xf0, 0x02, 0xe9, 0xe1, 0x81, 0xd5, 0x71, 0xc1, 0x40, + 0xca, 0x20, 0x6e, 0x00, 0x0a, 0x24, 0x00, 0x70, 0x40, 0x21, 0x01, 0x21, + 0xa8, 0x20, 0x00, 0x01, 0x18, 0x19, 0xd0, 0x03, 0xa1, 0x40, 0x02, 0x41, + 0x22, 0x42, 0x02, 0x0c, 0x2f, 0xf5, 0xc1, 0x43, 0xcc, 0xc6, 0xe0, 0x78, + 0x3e, 0x78, 0xe0, 0x7e, 0x48, 0x88, 0x00, 0x19, 0x05, 0x00, 0x42, 0x22, + 0x3c, 0x80, 0xe0, 0x7c, 0x83, 0x80, 0x6c, 0x70, 0xa8, 0x20, 0x00, 0x03, + 0x04, 0x14, 0x00, 0x14, 0x08, 0x80, 0x42, 0x88, 0x0b, 0x0a, 0x9f, 0x01, + 0x05, 0x90, 0x05, 0x7b, 0x60, 0xb1, 0xe0, 0x78, 0xe0, 0x7e, 0xe0, 0x78, + 0x52, 0xd9, 0x03, 0x18, 0x43, 0x00, 0x01, 0x18, 0x03, 0x00, 0x00, 0x18, + 0x03, 0x01, 0xe0, 0x7f, 0x22, 0xa8, 0xe0, 0x78, 0xfa, 0xc2, 0xfc, 0x1c, + 0xc8, 0xb6, 0xbb, 0xc1, 0xc3, 0x80, 0x08, 0x47, 0x44, 0x17, 0x19, 0x10, + 0xd1, 0x40, 0x00, 0x86, 0x88, 0xc5, 0x28, 0x80, 0x01, 0x91, 0x44, 0x81, + 0x82, 0xb8, 0x01, 0xb1, 0x00, 0x82, 0x0c, 0x11, 0x1b, 0x00, 0x2c, 0x70, + 0x47, 0xc0, 0x88, 0xc0, 0x6e, 0x0e, 0xef, 0xf5, 0x14, 0xda, 0x4a, 0x24, + 0xc0, 0x70, 0x84, 0xc0, 0xa8, 0x20, 0x40, 0x01, 0x08, 0x43, 0xa0, 0xa0, + 0x04, 0x74, 0x08, 0x17, 0x89, 0x10, 0x04, 0xc2, 0x05, 0xc3, 0xcc, 0x71, + 0xec, 0x70, 0x40, 0x24, 0x04, 0x38, 0xc8, 0x40, 0x4d, 0x08, 0x45, 0x12, + 0x04, 0x10, 0x0c, 0x22, 0x08, 0x84, 0x20, 0x90, 0x3d, 0x09, 0x85, 0x0f, + 0x00, 0x00, 0xf0, 0xff, 0x21, 0x90, 0x35, 0x09, 0x9f, 0x00, 0x8c, 0x94, + 0x8c, 0x24, 0x05, 0x95, 0x0a, 0xf2, 0x8c, 0x24, 0x85, 0x96, 0x0c, 0xf2, + 0x8c, 0x24, 0x05, 0x96, 0x0d, 0xf4, 0x84, 0x80, 0x43, 0x80, 0x08, 0xf0, + 0x84, 0x80, 0x0c, 0x10, 0x04, 0x00, 0x04, 0xf0, 0x84, 0x80, 0x63, 0x80, + 0x82, 0xb9, 0x21, 0xb0, 0xc0, 0x84, 0xe4, 0x71, 0x05, 0x71, 0xdc, 0xf1, + 0x30, 0x87, 0x81, 0x91, 0x00, 0x1b, 0x00, 0x11, 0x44, 0xc2, 0x29, 0x0c, + 0x3e, 0x10, 0x45, 0xc3, 0x04, 0x11, 0x80, 0x30, 0x11, 0x08, 0x34, 0x04, + 0x41, 0x28, 0x0b, 0x01, 0xc3, 0xb8, 0x09, 0x08, 0xc0, 0x02, 0xcc, 0x72, + 0x2f, 0x20, 0xc7, 0x01, 0x93, 0x08, 0xa4, 0x01, 0xa0, 0xbc, 0x81, 0xb1, + 0x04, 0x87, 0x29, 0x8f, 0x82, 0x80, 0x04, 0x10, 0x14, 0x00, 0x00, 0x10, + 0x16, 0x00, 0x91, 0x43, 0x10, 0x14, 0x18, 0x10, 0x10, 0x14, 0x15, 0x20, + 0x1d, 0x09, 0x34, 0x01, 0x10, 0x16, 0x17, 0x20, 0x84, 0x80, 0xa3, 0x80, + 0x91, 0x40, 0x10, 0x14, 0x12, 0x10, 0x10, 0x15, 0x11, 0x10, 0x56, 0x40, + 0x36, 0x41, 0x04, 0xf0, 0x8d, 0xc0, 0x92, 0xc1, 0x08, 0x10, 0x07, 0x30, + 0x08, 0x15, 0x06, 0x20, 0x08, 0x17, 0x05, 0x20, 0x41, 0xc0, 0x40, 0xc1, + 0x23, 0x40, 0x9a, 0x0b, 0x6f, 0xfc, 0x63, 0x41, 0x04, 0x1f, 0x80, 0x23, + 0xde, 0x41, 0x60, 0x79, 0xc2, 0x40, 0x07, 0xc0, 0x04, 0x1d, 0x00, 0x20, + 0x9e, 0x41, 0x60, 0x79, 0x82, 0x40, 0x04, 0x18, 0x80, 0x33, 0x7e, 0x41, + 0x60, 0x79, 0x62, 0x40, 0x09, 0x8f, 0x1b, 0x08, 0x34, 0x01, 0xa1, 0x40, + 0x04, 0x19, 0x80, 0x23, 0x23, 0x85, 0x40, 0x79, 0x04, 0x1a, 0x80, 0x23, + 0x1e, 0x41, 0x60, 0x79, 0x02, 0x40, 0xbb, 0xc0, 0x04, 0x14, 0x1b, 0x34, + 0xda, 0xc6, 0xe0, 0x78, 0xe2, 0xc2, 0x11, 0x80, 0x86, 0x0c, 0x6f, 0xfc, + 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0xfd, 0x04, + 0x6f, 0xfc, 0x2f, 0x79, 0xe2, 0xc2, 0x11, 0x80, 0x66, 0x0d, 0x6f, 0xfc, + 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0xe6, 0xc0, 0xc3, 0x80, + 0x71, 0x80, 0x08, 0x10, 0x8b, 0x00, 0xad, 0x71, 0x40, 0x86, 0xe4, 0x8b, + 0x48, 0x82, 0x41, 0x2f, 0x08, 0x11, 0x85, 0x92, 0x80, 0xb1, 0x3f, 0x0d, + 0xc5, 0x12, 0x04, 0x16, 0x03, 0x12, 0x4c, 0x93, 0x8c, 0x22, 0x05, 0x85, + 0x0a, 0xf2, 0x8c, 0x22, 0x05, 0x86, 0x0c, 0x71, 0x09, 0xf2, 0x8c, 0x22, + 0x85, 0x86, 0x06, 0xf4, 0x0c, 0x72, 0x05, 0xf0, 0x0c, 0x74, 0x03, 0xf0, + 0x0c, 0x70, 0xeb, 0x78, 0xcb, 0x20, 0x01, 0x82, 0x05, 0xf2, 0x08, 0x83, + 0x05, 0x90, 0x05, 0x7c, 0x80, 0xb1, 0xa5, 0x71, 0xe3, 0xf1, 0xc6, 0xc4, + 0x25, 0x05, 0x6f, 0xfc, 0x11, 0x80, 0xe0, 0x78, 0x0d, 0x02, 0x6f, 0xfc, + 0x11, 0x80, 0xe0, 0x78, 0x3d, 0x05, 0x6f, 0xfc, 0x11, 0x80, 0xe0, 0x78, + 0xee, 0xc2, 0x08, 0x45, 0x03, 0x80, 0x91, 0x85, 0x28, 0x47, 0x00, 0x80, + 0x54, 0x8c, 0x04, 0x14, 0x93, 0x10, 0x91, 0x41, 0x68, 0x80, 0x21, 0x93, + 0xa4, 0xb9, 0x83, 0x0a, 0x30, 0x00, 0x21, 0xb3, 0x09, 0x15, 0x89, 0x10, + 0x2c, 0x70, 0x8d, 0x70, 0x20, 0x46, 0x5f, 0x09, 0x65, 0x02, 0x6d, 0x70, + 0x44, 0x85, 0x26, 0x4a, 0x4c, 0x70, 0x02, 0x16, 0x88, 0x10, 0x11, 0x72, + 0x0a, 0x24, 0x80, 0x01, 0x81, 0x47, 0xc0, 0x21, 0x66, 0x00, 0xe8, 0x44, + 0x0a, 0x26, 0x00, 0x01, 0x6f, 0xf7, 0x82, 0x86, 0x0a, 0x26, 0x00, 0x01, + 0x30, 0x24, 0xcc, 0x12, 0x88, 0x84, 0x80, 0x94, 0xd3, 0x74, 0x00, 0x00, + 0xff, 0xff, 0xe8, 0x44, 0xca, 0x26, 0x22, 0x00, 0xca, 0x24, 0x62, 0x10, + 0x0a, 0xf2, 0x15, 0x09, 0x50, 0x00, 0xe8, 0x44, 0x0d, 0x0f, 0x31, 0x00, + 0x0a, 0x26, 0x00, 0x01, 0xcc, 0x71, 0x8d, 0x70, 0x65, 0x74, 0x44, 0x71, + 0xdb, 0xf1, 0x1b, 0x0e, 0x30, 0x00, 0x40, 0xda, 0xc4, 0x93, 0xc1, 0x41, + 0xd2, 0x08, 0xef, 0xf5, 0xc3, 0xb3, 0xc0, 0xb7, 0x0b, 0xf0, 0x30, 0x85, + 0x03, 0xf0, 0x30, 0x85, 0x43, 0xb3, 0xc2, 0x08, 0xef, 0xf5, 0x20, 0x91, + 0x10, 0x85, 0x00, 0x90, 0x00, 0xb7, 0x41, 0x2b, 0x10, 0x21, 0xcd, 0x71, + 0x08, 0x8d, 0x79, 0x0e, 0x05, 0x10, 0x03, 0x85, 0xc0, 0x48, 0x48, 0x80, + 0x8c, 0x90, 0x61, 0x92, 0x8c, 0x24, 0x05, 0x95, 0x50, 0x23, 0x01, 0x01, + 0x21, 0xb2, 0x0b, 0xf2, 0x8c, 0x24, 0x05, 0x96, 0x2c, 0x71, 0x0a, 0xf2, + 0x8c, 0x24, 0x85, 0x96, 0x05, 0xf4, 0x2c, 0x72, 0x04, 0xf0, 0x2c, 0x74, + 0x02, 0xf0, 0x2c, 0x70, 0x0b, 0x21, 0xc0, 0x84, 0x14, 0x27, 0x92, 0x13, + 0x06, 0xf2, 0x30, 0x85, 0x84, 0xbb, 0x20, 0x91, 0x61, 0xb2, 0x0a, 0xf0, + 0x0b, 0x21, 0x00, 0x84, 0x04, 0xf4, 0x15, 0x11, 0x81, 0x20, 0x0c, 0xe9, + 0x30, 0x85, 0x20, 0x91, 0x56, 0x08, 0xcf, 0xf5, 0x10, 0x85, 0x00, 0x90, + 0x00, 0x1a, 0x04, 0x20, 0xc5, 0x71, 0xce, 0xf1, 0xc3, 0x41, 0x00, 0x00, + 0xff, 0xff, 0x42, 0x08, 0xcf, 0xf5, 0x00, 0x1a, 0xc5, 0x2f, 0xf8, 0xf1, + 0xce, 0xc6, 0xe0, 0x78, 0x31, 0x04, 0x6f, 0xfc, 0x11, 0x80, 0xe0, 0x78, + 0xee, 0xc3, 0xa8, 0xc1, 0x08, 0x47, 0x01, 0x80, 0x23, 0x87, 0x0e, 0x70, + 0xcd, 0x70, 0x07, 0x80, 0xa0, 0x81, 0x0b, 0x20, 0x80, 0x8f, 0x20, 0x00, + 0x01, 0x00, 0x03, 0xf2, 0xc1, 0x81, 0x19, 0x08, 0x9e, 0x00, 0x04, 0x20, + 0x80, 0x0f, 0x22, 0x00, 0x00, 0x00, 0x52, 0x20, 0x7e, 0x84, 0x04, 0xf2, + 0x08, 0x11, 0x10, 0x00, 0x56, 0x0c, 0xcf, 0xff, 0x07, 0x85, 0x1f, 0x08, + 0xd0, 0x00, 0xa9, 0x08, 0x51, 0x01, 0x08, 0x85, 0x21, 0x90, 0x44, 0x80, + 0x82, 0xb9, 0x21, 0xb0, 0x20, 0x82, 0x0c, 0x10, 0x13, 0x00, 0x40, 0xc1, + 0x0c, 0xf0, 0x08, 0x85, 0x02, 0x88, 0x3d, 0x08, 0x7f, 0x00, 0x80, 0xc1, + 0x44, 0x85, 0x60, 0x7a, 0xa1, 0x40, 0x81, 0x08, 0x30, 0x00, 0x10, 0x43, + 0x4e, 0x70, 0x52, 0x41, 0x27, 0xee, 0x08, 0x86, 0x21, 0x90, 0x4b, 0x09, + 0xbf, 0x00, 0x2e, 0x70, 0x47, 0x86, 0x33, 0x0a, 0xd0, 0x00, 0x65, 0x0a, + 0x71, 0x01, 0x82, 0xb9, 0x44, 0x80, 0x21, 0xb0, 0x20, 0x82, 0x03, 0x80, + 0x43, 0xc1, 0x13, 0xf0, 0xe2, 0x0d, 0xaf, 0xf5, 0xa1, 0x40, 0x05, 0xee, + 0xda, 0x0d, 0xaf, 0xf5, 0xc1, 0x40, 0x45, 0x08, 0x30, 0x20, 0x02, 0x40, + 0xce, 0x0d, 0x8f, 0xf5, 0x1c, 0xf0, 0x44, 0x86, 0x83, 0xc1, 0x60, 0x7a, + 0xc1, 0x40, 0x00, 0x10, 0x91, 0x00, 0x85, 0x21, 0x3e, 0x20, 0x3f, 0x08, + 0x10, 0x20, 0x20, 0x10, 0x02, 0x20, 0x21, 0x92, 0x33, 0x09, 0x9f, 0x00, + 0x1e, 0x44, 0x1f, 0x08, 0xd0, 0x00, 0x15, 0x08, 0x71, 0x01, 0x82, 0xb9, + 0x64, 0x82, 0x21, 0xb2, 0x03, 0x82, 0x20, 0x83, 0x42, 0xc1, 0x09, 0xf0, + 0x36, 0x09, 0x00, 0x00, 0xce, 0xc7, 0x06, 0x46, 0x82, 0xc1, 0x60, 0x7a, + 0x02, 0x40, 0x00, 0x10, 0x92, 0x00, 0x85, 0x22, 0x3e, 0x20, 0x22, 0x09, + 0x00, 0x00, 0x01, 0x87, 0x1e, 0x88, 0x15, 0x08, 0x7f, 0x00, 0x40, 0x24, + 0x04, 0x34, 0x04, 0x87, 0xa0, 0x80, 0xc4, 0x85, 0x08, 0x16, 0x04, 0x10, + 0x11, 0x87, 0x2f, 0x22, 0x47, 0x04, 0x2f, 0x23, 0x87, 0x04, 0x40, 0x24, + 0xc5, 0x31, 0x66, 0x0e, 0x6f, 0xfc, 0x62, 0x41, 0x01, 0x87, 0x1e, 0x88, + 0x17, 0x08, 0x5f, 0x00, 0x07, 0x14, 0xc0, 0x30, 0x0f, 0x08, 0x13, 0x00, + 0x00, 0xc0, 0x01, 0xa6, 0x23, 0x85, 0x60, 0x79, 0xa1, 0x40, 0xce, 0xc7, + 0xe2, 0xc2, 0x11, 0x80, 0xf6, 0x08, 0xaf, 0xfc, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0xb5, 0x01, 0xaf, 0xfc, 0x2f, 0x79, + 0xe2, 0xc2, 0x11, 0x80, 0x26, 0x0a, 0xaf, 0xfc, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x1d, 0x03, 0xaf, 0xfc, 0x11, 0x80, 0xe0, 0x78, + 0xd9, 0x04, 0x6f, 0xfc, 0x11, 0x80, 0xe0, 0x78, 0x11, 0x03, 0xaf, 0xfc, + 0x11, 0x80, 0xe0, 0x78, 0xa9, 0x05, 0xaf, 0xfc, 0x11, 0x80, 0xe0, 0x78, + 0xe4, 0xc2, 0x08, 0x46, 0x03, 0x80, 0x00, 0x80, 0x48, 0x80, 0x04, 0x82, + 0x61, 0x92, 0x23, 0x82, 0xa0, 0x80, 0x11, 0x86, 0x82, 0xbb, 0x36, 0x09, + 0xef, 0xfc, 0x61, 0xb2, 0x19, 0x08, 0xfe, 0x01, 0x00, 0x42, 0x24, 0x86, + 0xc6, 0xba, 0x00, 0x81, 0x64, 0x80, 0x22, 0x83, 0x40, 0xa9, 0x23, 0x80, + 0x60, 0x79, 0xa1, 0xa3, 0xc4, 0xc6, 0xe0, 0x78, 0xe2, 0xc2, 0x11, 0x80, + 0xde, 0x09, 0xef, 0xfc, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0x11, 0x80, 0x55, 0x02, 0xef, 0xfc, 0x2f, 0x79, 0xe2, 0xc2, 0x11, 0x80, + 0x5e, 0x0a, 0xef, 0xfc, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0xbd, 0x02, 0xef, 0xfc, 0x11, 0x80, 0xe0, 0x78, 0x25, 0x00, 0xef, 0xfc, + 0x11, 0x80, 0xe0, 0x78, 0xb1, 0x02, 0xef, 0xfc, 0x11, 0x80, 0xe0, 0x78, + 0x51, 0x03, 0xef, 0xfc, 0x11, 0x80, 0xe0, 0x78, 0xc3, 0x41, 0xa0, 0x00, + 0x84, 0x6e, 0x49, 0x81, 0x20, 0xa0, 0x00, 0x7a, 0x5e, 0x78, 0xe0, 0x7e, + 0xe8, 0xc2, 0x28, 0x47, 0x50, 0x40, 0x08, 0x45, 0x2c, 0x70, 0x8a, 0x22, + 0x06, 0x00, 0x3e, 0x09, 0xef, 0xf5, 0xe1, 0x40, 0x1f, 0x08, 0x30, 0x20, + 0x2c, 0x70, 0xcd, 0x70, 0x06, 0xed, 0x04, 0x85, 0x20, 0x48, 0x66, 0x08, + 0xaf, 0xf5, 0xe1, 0x41, 0xc5, 0x71, 0xcf, 0x79, 0xf1, 0x09, 0x24, 0x84, + 0xe5, 0x74, 0xc8, 0xc6, 0xee, 0xc3, 0xa4, 0xc1, 0x08, 0x47, 0x03, 0x80, + 0xc0, 0x80, 0xa1, 0x80, 0x08, 0x86, 0x28, 0x85, 0x02, 0x10, 0x10, 0x01, + 0x26, 0x0a, 0xef, 0xff, 0x02, 0x11, 0x12, 0x01, 0x07, 0x85, 0x23, 0x08, + 0xd0, 0x00, 0xdd, 0x08, 0x51, 0x01, 0xd9, 0x0a, 0x9f, 0x20, 0x08, 0x85, + 0x64, 0x80, 0x41, 0x90, 0x0c, 0x10, 0x13, 0x00, 0x20, 0x83, 0x82, 0xba, + 0x41, 0xb0, 0x40, 0xc1, 0x0c, 0xf0, 0x08, 0x85, 0x02, 0x88, 0x3d, 0x08, + 0x7f, 0x00, 0x80, 0xc1, 0x44, 0x85, 0x60, 0x7a, 0xa1, 0x40, 0xb1, 0x08, + 0x30, 0x00, 0x10, 0x43, 0x07, 0x86, 0x37, 0x08, 0xf0, 0x00, 0x81, 0xc1, + 0xa1, 0x08, 0x71, 0x01, 0x44, 0x20, 0x11, 0xa1, 0x1f, 0xf4, 0x08, 0x86, + 0x2e, 0x70, 0x64, 0x80, 0x41, 0x90, 0x0c, 0x10, 0x10, 0x00, 0x20, 0x83, + 0x82, 0xba, 0x41, 0xb0, 0x41, 0xc1, 0x1c, 0xf0, 0xaa, 0x0b, 0xaf, 0xf5, + 0xa1, 0x40, 0xa6, 0x0b, 0xaf, 0xf5, 0xc1, 0x40, 0x3a, 0xf0, 0x65, 0x86, + 0x00, 0xc2, 0x60, 0x7b, 0xc1, 0x40, 0x10, 0x40, 0x14, 0x70, 0x83, 0xc0, + 0x78, 0x20, 0x11, 0x20, 0xca, 0x20, 0x01, 0x20, 0x08, 0xf0, 0x41, 0x29, + 0x91, 0x20, 0x6f, 0x20, 0x43, 0x00, 0x40, 0x24, 0x10, 0x33, 0x41, 0xc0, + 0x1a, 0x0f, 0xcf, 0xff, 0x30, 0x87, 0x01, 0x91, 0x11, 0x08, 0x1e, 0x00, + 0x45, 0x0a, 0x9f, 0x20, 0x41, 0x09, 0x31, 0x20, 0xa0, 0xb8, 0x01, 0xb1, + 0x04, 0x87, 0x00, 0x14, 0x04, 0x30, 0x40, 0x24, 0xc6, 0x32, 0x02, 0x41, + 0xa0, 0x80, 0x11, 0x87, 0x62, 0x42, 0x22, 0x43, 0xc4, 0x85, 0x96, 0x0d, + 0xef, 0xfc, 0x08, 0x16, 0x05, 0x10, 0x56, 0x09, 0xcf, 0xff, 0x0b, 0x14, + 0xc0, 0x30, 0x11, 0x08, 0x13, 0x00, 0x00, 0xc0, 0x23, 0x85, 0x01, 0xa6, + 0x60, 0x79, 0xa1, 0x40, 0xce, 0x0e, 0xcf, 0xff, 0xce, 0xc7, 0xe0, 0x78, + 0xe2, 0xc2, 0x11, 0x80, 0xd2, 0x0f, 0xef, 0xfc, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0x19, 0x01, 0x2f, 0xfd, 0x2f, 0x79, + 0xe2, 0xc2, 0x11, 0x80, 0x76, 0x09, 0x2f, 0xfd, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x91, 0x01, 0x6f, 0xfd, 0x11, 0x80, 0xe0, 0x78, + 0xed, 0x02, 0xef, 0xfc, 0x11, 0x80, 0xe0, 0x78, 0x31, 0x02, 0x6f, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0x69, 0x03, 0x6f, 0xfd, 0x11, 0x80, 0xe0, 0x78, + 0xe2, 0xc2, 0x29, 0x08, 0xb1, 0x00, 0x4c, 0x73, 0xcb, 0x45, 0xa0, 0x00, + 0xbc, 0x86, 0x21, 0x85, 0xc3, 0x40, 0xa0, 0x00, 0x7c, 0x6e, 0x00, 0x80, + 0x24, 0x71, 0x21, 0xa5, 0x2c, 0x71, 0x72, 0x08, 0x2f, 0xf8, 0x6c, 0x70, + 0x00, 0x1d, 0x43, 0x10, 0xc2, 0xc6, 0xe0, 0x78, 0xf0, 0xc3, 0xa9, 0xc1, + 0x63, 0x80, 0x20, 0x83, 0x28, 0x81, 0x41, 0x91, 0x82, 0xba, 0x41, 0xb1, + 0x41, 0x83, 0xa8, 0x82, 0xe1, 0x95, 0x4f, 0x27, 0x82, 0x10, 0x41, 0xb5, + 0x81, 0x80, 0x43, 0x85, 0xc4, 0x85, 0xa4, 0x81, 0x9e, 0x8c, 0x23, 0x81, + 0x00, 0x16, 0x14, 0x10, 0x00, 0x15, 0x11, 0x10, 0x19, 0x0c, 0x3f, 0x10, + 0xf1, 0x43, 0x62, 0x83, 0x88, 0x83, 0xa1, 0x94, 0x0d, 0x0d, 0xbf, 0x10, + 0x82, 0xbd, 0x63, 0x84, 0xa1, 0xb4, 0x0b, 0xf0, 0x8d, 0x70, 0xcb, 0x45, + 0x7f, 0x43, 0x00, 0x00, 0x80, 0xc3, 0x42, 0xc4, 0x41, 0xc4, 0x40, 0xc4, + 0x43, 0xc5, 0x84, 0x80, 0x11, 0x80, 0x40, 0x24, 0x04, 0x35, 0x40, 0x24, + 0xc7, 0x34, 0xc2, 0x84, 0xa0, 0x84, 0x04, 0x14, 0x12, 0x10, 0x10, 0x16, + 0x10, 0x10, 0xe4, 0x85, 0x08, 0x10, 0x06, 0x20, 0xe6, 0x0f, 0x6f, 0xfd, + 0x08, 0x17, 0x05, 0x10, 0x04, 0x1f, 0x40, 0x14, 0x04, 0x18, 0x40, 0x24, + 0x23, 0x85, 0x60, 0x79, 0xa1, 0x40, 0x17, 0x0b, 0xbf, 0x20, 0x85, 0xc1, + 0x42, 0x40, 0x9e, 0x0a, 0xe0, 0x00, 0x82, 0x42, 0x5e, 0x41, 0x60, 0x79, + 0x42, 0x40, 0x13, 0x14, 0x80, 0x30, 0x03, 0xe8, 0xd0, 0xc7, 0x23, 0x86, + 0x60, 0x79, 0xc1, 0x40, 0xd0, 0xc7, 0xe0, 0x78, 0xe2, 0xc2, 0x11, 0x80, + 0x46, 0x08, 0xaf, 0xfd, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0x11, 0x80, 0x9d, 0x00, 0xaf, 0xfd, 0x2f, 0x79, 0xe2, 0xc2, 0x11, 0x80, + 0xf2, 0x09, 0xaf, 0xfd, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0xe9, 0x07, 0x8f, 0xff, 0x51, 0x02, 0xaf, 0xfd, 0x11, 0x80, 0xe0, 0x78, + 0xed, 0x06, 0x6f, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0x59, 0x02, 0xaf, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0x15, 0x02, 0x00, 0x00, 0x29, 0x04, 0xaf, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0xf0, 0xc3, 0xa9, 0xc1, 0x63, 0x80, 0x20, 0x83, + 0x88, 0x81, 0x21, 0x94, 0x82, 0xb9, 0x21, 0xb4, 0x21, 0x83, 0x48, 0x81, + 0xe1, 0x92, 0x4f, 0x27, 0x81, 0x10, 0x21, 0xb2, 0x21, 0x80, 0xc4, 0x82, + 0xa4, 0x84, 0x43, 0x82, 0x27, 0x81, 0x00, 0x16, 0x14, 0x10, 0x00, 0x15, + 0x11, 0x10, 0x04, 0x21, 0x8b, 0x0f, 0x22, 0x00, 0x00, 0x00, 0x23, 0x84, + 0xf1, 0x43, 0x52, 0x23, 0x7e, 0x94, 0x0b, 0xf2, 0x62, 0x83, 0x88, 0x83, + 0xa1, 0x94, 0x0f, 0x0d, 0xbf, 0x10, 0x82, 0xbd, 0x63, 0x84, 0xa1, 0xb4, + 0x0a, 0xf0, 0x8d, 0x70, 0xcb, 0x45, 0x7f, 0x43, 0x00, 0x00, 0x80, 0xc3, + 0x42, 0xc4, 0x41, 0xc4, 0x40, 0xc4, 0x43, 0xc5, 0x84, 0x80, 0x11, 0x80, + 0x40, 0x24, 0x04, 0x35, 0x40, 0x24, 0xc7, 0x34, 0xc2, 0x84, 0xa0, 0x84, + 0x04, 0x14, 0x12, 0x10, 0x10, 0x16, 0x10, 0x10, 0xe4, 0x85, 0x08, 0x10, + 0x06, 0x20, 0xda, 0x0e, 0x6f, 0xfd, 0x08, 0x17, 0x05, 0x10, 0x04, 0x1f, + 0x40, 0x14, 0x04, 0x18, 0x40, 0x24, 0x23, 0x85, 0x60, 0x79, 0xa1, 0x40, + 0x15, 0x0b, 0xbf, 0x20, 0x85, 0xc1, 0x42, 0x40, 0x8e, 0x09, 0xe0, 0x00, + 0x82, 0x42, 0x5e, 0x41, 0x60, 0x79, 0x42, 0x40, 0x13, 0x14, 0x80, 0x30, + 0x02, 0xe8, 0xd0, 0xc7, 0x23, 0x86, 0x60, 0x79, 0xc1, 0x40, 0xd0, 0xc7, + 0xe2, 0xc2, 0x11, 0x80, 0x3a, 0x0f, 0x6f, 0xfd, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0x91, 0x07, 0x6f, 0xfd, 0x2f, 0x79, + 0xe2, 0xc2, 0x11, 0x80, 0xe6, 0x08, 0xaf, 0xfd, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0xdd, 0x06, 0x8f, 0xff, 0x45, 0x01, 0xaf, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0xe1, 0x05, 0x6f, 0xfd, 0x11, 0x80, 0xe0, 0x78, + 0x4d, 0x01, 0xaf, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0x09, 0x01, 0x00, 0x00, + 0x1d, 0x03, 0xaf, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0xf0, 0xc3, 0xa9, 0xc1, + 0x43, 0x80, 0x20, 0x82, 0x88, 0x81, 0x21, 0x94, 0x82, 0xb9, 0x21, 0xb4, + 0x21, 0x82, 0x68, 0x81, 0xe1, 0x93, 0x4f, 0x27, 0x81, 0x10, 0x21, 0xb3, + 0x22, 0x82, 0x43, 0x83, 0xc4, 0x83, 0x64, 0x84, 0xa8, 0x81, 0x23, 0x84, + 0x00, 0x16, 0x14, 0x10, 0x00, 0x13, 0x11, 0x00, 0x81, 0x95, 0x11, 0x0c, + 0xbf, 0x10, 0xf1, 0x43, 0x63, 0x85, 0x82, 0xbc, 0x81, 0xb5, 0x0b, 0xf0, + 0x8d, 0x70, 0xcb, 0x45, 0x7f, 0x43, 0x00, 0x00, 0x80, 0xc3, 0x42, 0xc4, + 0x41, 0xc4, 0x40, 0xc4, 0x43, 0xc5, 0x84, 0x80, 0x11, 0x80, 0x40, 0x24, + 0x04, 0x35, 0x40, 0x24, 0xc7, 0x34, 0xc2, 0x84, 0xa0, 0x84, 0x04, 0x14, + 0x12, 0x10, 0x10, 0x16, 0x10, 0x10, 0xe4, 0x85, 0x08, 0x10, 0x06, 0x20, + 0xde, 0x0d, 0x6f, 0xfd, 0x08, 0x17, 0x05, 0x10, 0x04, 0x1f, 0x40, 0x14, + 0x04, 0x18, 0x40, 0x24, 0x23, 0x85, 0x60, 0x79, 0xa1, 0x40, 0x17, 0x0b, + 0xbf, 0x20, 0x85, 0xc1, 0x42, 0x40, 0x96, 0x08, 0xe0, 0x00, 0x82, 0x42, + 0x5e, 0x41, 0x60, 0x79, 0x42, 0x40, 0x13, 0x14, 0x80, 0x30, 0x03, 0xe8, + 0xd0, 0xc7, 0x23, 0x86, 0x60, 0x79, 0xc1, 0x40, 0xd0, 0xc7, 0xe0, 0x78, + 0xe2, 0xc2, 0x11, 0x80, 0x3e, 0x0e, 0x6f, 0xfd, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0x95, 0x06, 0x6f, 0xfd, 0x2f, 0x79, + 0xe2, 0xc2, 0x11, 0x80, 0xea, 0x0f, 0x6f, 0xfd, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0xe1, 0x05, 0x8f, 0xff, 0x49, 0x00, 0xaf, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0xe5, 0x04, 0x6f, 0xfd, 0x11, 0x80, 0xe0, 0x78, + 0x51, 0x00, 0xaf, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0x0d, 0x00, 0x00, 0x00, + 0x21, 0x02, 0xaf, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0xe6, 0xc2, 0x08, 0x47, + 0x50, 0x87, 0x03, 0x80, 0x28, 0x45, 0xc0, 0x92, 0x00, 0x80, 0x4a, 0x09, + 0xaf, 0xf5, 0xc1, 0x41, 0x03, 0x87, 0xc1, 0x41, 0x01, 0x80, 0x3e, 0x09, + 0xaf, 0xf5, 0xc0, 0xb5, 0xc1, 0xb5, 0xc6, 0xc6, 0xe4, 0xc2, 0x08, 0x46, + 0x03, 0x80, 0x00, 0x80, 0x48, 0x80, 0x04, 0x82, 0x61, 0x92, 0x23, 0x82, + 0xa0, 0x80, 0x11, 0x86, 0x82, 0xbb, 0x7a, 0x0e, 0xaf, 0xfd, 0x61, 0xb2, + 0x19, 0x08, 0xfe, 0x01, 0x00, 0x42, 0x24, 0x86, 0xc6, 0xba, 0x00, 0x81, + 0x64, 0x80, 0x22, 0x83, 0x40, 0xa9, 0x23, 0x80, 0x60, 0x79, 0xa1, 0xa3, + 0xc4, 0xc6, 0xe0, 0x78, 0xe2, 0xc2, 0x11, 0x80, 0x02, 0x0f, 0xaf, 0xfd, + 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0x55, 0x07, + 0xaf, 0xfd, 0x2f, 0x79, 0xe2, 0xc2, 0x11, 0x80, 0x5e, 0x0f, 0xaf, 0xfd, + 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0xc1, 0x07, 0xaf, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0x91, 0x05, 0xaf, 0xfd, 0x11, 0x80, 0xe0, 0x78, + 0xc9, 0x07, 0xaf, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0x69, 0x00, 0xef, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0xf4, 0xc3, 0xa5, 0xc1, 0x08, 0x45, 0x03, 0x80, + 0x00, 0x80, 0x48, 0x80, 0x01, 0x92, 0x82, 0xb8, 0x01, 0xb2, 0x04, 0x85, + 0x61, 0x85, 0x23, 0x82, 0x44, 0x82, 0xc1, 0x80, 0x00, 0x10, 0x15, 0x00, + 0x87, 0x83, 0x00, 0x12, 0x12, 0x00, 0x10, 0x16, 0x11, 0x10, 0x10, 0x15, + 0x16, 0x20, 0x0f, 0x0c, 0x7f, 0x16, 0xd1, 0x40, 0x4c, 0x72, 0x83, 0xc3, + 0x06, 0xf0, 0xe2, 0x80, 0x4c, 0x73, 0xc4, 0x87, 0xd1, 0x44, 0x62, 0x86, + 0x0b, 0x0c, 0x7f, 0x17, 0x40, 0x24, 0x04, 0x31, 0x06, 0xf0, 0x46, 0x48, + 0x04, 0x86, 0x10, 0x43, 0x08, 0x10, 0x04, 0x00, 0x08, 0x16, 0x05, 0x20, + 0x36, 0x42, 0x11, 0x85, 0x46, 0x09, 0xef, 0xfd, 0x40, 0x24, 0xc6, 0x30, + 0x03, 0x14, 0xc0, 0x30, 0x13, 0x08, 0x13, 0x00, 0x04, 0x1e, 0x80, 0x24, + 0xbe, 0x41, 0x60, 0x79, 0xa2, 0x40, 0x03, 0x14, 0x80, 0x30, 0x11, 0x08, + 0xfe, 0x00, 0x02, 0x40, 0x04, 0x19, 0x80, 0x24, 0x1e, 0x41, 0x40, 0x79, + 0x01, 0x85, 0x07, 0x80, 0x1b, 0x08, 0x5e, 0x06, 0x03, 0x14, 0x81, 0x30, + 0x13, 0x09, 0x1e, 0x01, 0x04, 0x1c, 0x80, 0x24, 0x23, 0x87, 0x60, 0x79, + 0xe1, 0x40, 0x01, 0x85, 0x07, 0x80, 0x19, 0x08, 0x5e, 0x07, 0x03, 0x14, + 0x80, 0x30, 0x11, 0x08, 0x7e, 0x01, 0xc1, 0x40, 0x04, 0x1b, 0x80, 0x24, + 0x23, 0x86, 0x40, 0x79, 0xd4, 0xc7, 0xe0, 0x78, 0xe2, 0xc2, 0x11, 0x80, + 0xce, 0x0c, 0xef, 0xfd, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0x11, 0x80, 0x1d, 0x05, 0xef, 0xfd, 0x2f, 0x79, 0xe2, 0xc2, 0x11, 0x80, + 0x3a, 0x0d, 0xef, 0xfd, 0x88, 0x45, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0x11, 0x07, 0xef, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0xa9, 0x07, 0xaf, 0xfd, + 0x11, 0x80, 0xe0, 0x78, 0x51, 0x00, 0x2f, 0xfe, 0x11, 0x80, 0xe0, 0x78, + 0x31, 0x02, 0x2f, 0xfe, 0x11, 0x80, 0xe0, 0x78, 0x41, 0x28, 0xc1, 0x00, + 0x44, 0x21, 0x01, 0x07, 0x30, 0x21, 0x82, 0x0f, 0xa0, 0x00, 0x44, 0xe1, + 0x2c, 0x71, 0x00, 0x29, 0x00, 0x00, 0x04, 0x7a, 0xe0, 0x7f, 0x79, 0x22, + 0x00, 0x00, 0xe0, 0x78, 0xc3, 0x41, 0xa0, 0x00, 0x44, 0xe1, 0x01, 0x81, + 0x40, 0x81, 0x62, 0x81, 0x05, 0x20, 0x8c, 0x0f, 0xff, 0xf9, 0x00, 0x00, + 0x05, 0x22, 0x82, 0x0f, 0xff, 0x0f, 0x00, 0xfc, 0x05, 0x23, 0x80, 0x0f, + 0x00, 0x70, 0xf9, 0x78, 0x81, 0xa1, 0x40, 0xa1, 0xe0, 0x7f, 0x02, 0xa1, + 0x8c, 0x20, 0x02, 0x88, 0xe0, 0x20, 0xc5, 0x07, 0x41, 0x28, 0xc1, 0x00, + 0x44, 0x21, 0x02, 0x07, 0x00, 0x22, 0x82, 0x0f, 0xa0, 0x00, 0x44, 0xe1, + 0x20, 0x82, 0xc4, 0xb8, 0x0f, 0x21, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0xa2, + 0x99, 0x03, 0x8f, 0xff, 0xe6, 0xc2, 0xd1, 0x80, 0x08, 0x45, 0x10, 0x80, + 0x28, 0x47, 0x44, 0x8e, 0x2f, 0x0a, 0x71, 0x00, 0x00, 0x90, 0x95, 0xe8, + 0x03, 0x85, 0x2c, 0x70, 0x1a, 0x0f, 0x6f, 0xf5, 0x00, 0x80, 0x03, 0x85, + 0xc3, 0x41, 0x00, 0x00, 0xff, 0xff, 0x01, 0x80, 0x0a, 0x0f, 0x6f, 0xf5, + 0x00, 0x1f, 0x05, 0x10, 0x10, 0x85, 0x44, 0x8e, 0x02, 0x1f, 0xc5, 0x1f, + 0x00, 0x90, 0x94, 0xe8, 0x25, 0x0a, 0x91, 0x00, 0x03, 0x85, 0xc3, 0x41, + 0x00, 0x00, 0xff, 0xff, 0xea, 0x0e, 0x6f, 0xf5, 0x00, 0x80, 0x03, 0x85, + 0x2c, 0x70, 0x01, 0x80, 0xde, 0x0e, 0x6f, 0xf5, 0x00, 0x1f, 0xc5, 0x1f, + 0x02, 0x1f, 0x05, 0x10, 0xc6, 0xc6, 0xe0, 0x78, 0xfa, 0xc2, 0xfc, 0x1c, + 0xc8, 0xb6, 0xa6, 0xc1, 0x04, 0x1c, 0x00, 0x31, 0xa0, 0x80, 0x01, 0xc0, + 0x00, 0x12, 0x14, 0x00, 0xd3, 0x41, 0x7f, 0x47, 0x00, 0xff, 0x2c, 0x15, + 0x19, 0x10, 0x00, 0x80, 0x58, 0x43, 0x0f, 0x70, 0xd3, 0x43, 0x10, 0x3a, + 0xe0, 0x2d, 0xd3, 0x42, 0x48, 0x42, 0x00, 0x00, 0xed, 0x70, 0x45, 0xc0, + 0x0c, 0x70, 0x0a, 0x27, 0x40, 0x24, 0x0a, 0x25, 0x40, 0x24, 0x44, 0xc3, + 0x40, 0xc1, 0x42, 0xc0, 0x43, 0xc0, 0xdb, 0x0f, 0x25, 0x15, 0x8a, 0x23, + 0x0e, 0x01, 0x00, 0xc6, 0xf6, 0x7e, 0x00, 0x86, 0xc7, 0x08, 0x30, 0x00, + 0xea, 0xe0, 0x1a, 0xf2, 0xe8, 0xe0, 0x2f, 0xf4, 0x1d, 0x8d, 0xbb, 0x08, + 0x3e, 0x00, 0x68, 0xd8, 0x21, 0x86, 0x43, 0xc0, 0x04, 0x31, 0x40, 0x84, + 0x30, 0x45, 0xca, 0x25, 0x41, 0x24, 0x53, 0xf2, 0x04, 0x35, 0xc0, 0xa4, + 0x8a, 0x20, 0x3f, 0x2d, 0x94, 0xf7, 0x04, 0x35, 0x80, 0xa4, 0xd8, 0xf6, + 0x67, 0x03, 0x00, 0x00, 0x1d, 0x8d, 0x8f, 0x08, 0x3e, 0x00, 0x6a, 0xd8, + 0x21, 0x86, 0x42, 0xc0, 0x04, 0x31, 0x40, 0x84, 0x30, 0x47, 0x3d, 0xf2, + 0x04, 0x37, 0xc0, 0xa4, 0x8a, 0x20, 0x3f, 0x2d, 0x46, 0x03, 0x25, 0x00, + 0x04, 0x37, 0x80, 0xa4, 0x3e, 0x03, 0x09, 0x00, 0x04, 0x1e, 0x00, 0x16, + 0x31, 0xf0, 0x01, 0x86, 0x04, 0x30, 0x00, 0x86, 0x5a, 0x00, 0x0c, 0x00, + 0x04, 0x30, 0x80, 0x8f, 0x7f, 0x47, 0x00, 0xef, 0x4e, 0x00, 0x0d, 0x00, + 0xd3, 0x40, 0xc8, 0x3f, 0x00, 0x00, 0x07, 0x30, 0x00, 0x04, 0x22, 0x09, + 0x2f, 0xf2, 0x10, 0x46, 0x48, 0x30, 0x40, 0x02, 0x29, 0x68, 0x2b, 0x78, + 0x0e, 0xf2, 0x4a, 0x24, 0x00, 0x71, 0x0c, 0x72, 0xa8, 0x20, 0x80, 0x01, + 0x05, 0x29, 0x02, 0x00, 0x0c, 0x78, 0x45, 0x79, 0x01, 0x69, 0x48, 0x30, + 0x00, 0x00, 0x07, 0xf0, 0x48, 0x30, 0x00, 0x00, 0x04, 0x36, 0x00, 0xa0, + 0x07, 0xf2, 0x00, 0x30, 0x00, 0x04, 0x01, 0xa6, 0x03, 0xf0, 0x0a, 0x27, + 0x40, 0x24, 0xe5, 0x71, 0x95, 0xf1, 0x23, 0x73, 0x00, 0x8b, 0x35, 0xe8, + 0x02, 0x85, 0x20, 0x88, 0x28, 0x40, 0x2f, 0xe9, 0xe1, 0x80, 0x8d, 0x70, + 0xcb, 0x46, 0x00, 0x00, 0xff, 0xff, 0x81, 0x4f, 0x00, 0x91, 0x49, 0x08, + 0xd1, 0x02, 0x08, 0x89, 0x50, 0x81, 0x42, 0x20, 0x3c, 0x80, 0x00, 0x1a, + 0x84, 0x03, 0x10, 0xf2, 0x0c, 0x11, 0x0b, 0x00, 0xa8, 0x20, 0x00, 0x03, + 0x04, 0x13, 0x00, 0x14, 0x08, 0x80, 0x43, 0x90, 0x05, 0xea, 0x44, 0x90, + 0x03, 0xea, 0xc4, 0xb0, 0xc3, 0xb0, 0xe0, 0x78, 0x09, 0x89, 0x42, 0x20, + 0x3c, 0x80, 0x0a, 0xf2, 0x10, 0x11, 0x01, 0x00, 0xa8, 0x20, 0x80, 0x01, + 0x04, 0x11, 0x00, 0x04, 0x04, 0x80, 0xc0, 0xb0, 0x85, 0x71, 0xb7, 0x0c, + 0x04, 0x92, 0x00, 0x1b, 0x02, 0x06, 0x8a, 0x23, 0x4e, 0x11, 0x00, 0x23, + 0x4b, 0x16, 0x00, 0x13, 0x80, 0x10, 0xbf, 0x08, 0x10, 0x00, 0x02, 0x85, + 0x20, 0x88, 0xb3, 0x09, 0x30, 0x00, 0x28, 0x40, 0x61, 0x80, 0xcd, 0x70, + 0xcb, 0x47, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x4b, 0x00, 0x91, 0x45, 0x08, + 0x91, 0x03, 0x08, 0x89, 0x50, 0x81, 0x42, 0x20, 0x3c, 0x80, 0xe0, 0xb2, + 0x0e, 0xf2, 0x43, 0x81, 0xa8, 0x20, 0x00, 0x03, 0x04, 0x12, 0x00, 0x04, + 0x08, 0x80, 0x83, 0x90, 0x05, 0xec, 0x84, 0x90, 0x03, 0xec, 0xe4, 0xb0, + 0xe3, 0xb0, 0xe0, 0x78, 0x09, 0x89, 0x42, 0x20, 0x3c, 0x80, 0x0a, 0xf2, + 0x10, 0x11, 0x01, 0x00, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x00, 0x04, + 0x04, 0x80, 0xe0, 0xb0, 0xc5, 0x71, 0xbb, 0x0e, 0x04, 0x92, 0xcd, 0x70, + 0xcb, 0x47, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x4b, 0x00, 0x91, 0x45, 0x08, + 0x51, 0x03, 0x08, 0x89, 0x50, 0x81, 0x42, 0x20, 0x3c, 0x80, 0xe0, 0xb2, + 0x0e, 0xf2, 0x43, 0x81, 0xa8, 0x20, 0x00, 0x03, 0x04, 0x12, 0x00, 0x04, + 0x08, 0x80, 0x83, 0x90, 0x05, 0xec, 0x84, 0x90, 0x03, 0xec, 0xe4, 0xb0, + 0xe3, 0xb0, 0xe0, 0x78, 0x09, 0x89, 0x42, 0x20, 0x3c, 0x80, 0x0a, 0xf2, + 0x10, 0x11, 0x01, 0x00, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x00, 0x04, + 0x04, 0x80, 0xe0, 0xb0, 0xc5, 0x71, 0xbb, 0x0e, 0x04, 0x92, 0x00, 0x1b, + 0x02, 0x16, 0x80, 0x21, 0x8e, 0x31, 0x00, 0x11, 0x80, 0x30, 0x33, 0xe8, + 0x02, 0x85, 0x20, 0x88, 0x28, 0x43, 0x2d, 0xe9, 0xc1, 0x80, 0xed, 0x70, + 0xcb, 0x44, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x4e, 0x00, 0x91, 0x45, 0x08, + 0x11, 0x03, 0x08, 0x89, 0x50, 0x81, 0x42, 0x20, 0x3c, 0x80, 0x80, 0xb2, + 0x0e, 0xf2, 0x43, 0x81, 0xa8, 0x20, 0x00, 0x03, 0x04, 0x12, 0x00, 0x04, + 0x08, 0x80, 0x63, 0x90, 0x05, 0xeb, 0x64, 0x90, 0x03, 0xeb, 0x84, 0xb0, + 0x83, 0xb0, 0xe0, 0x78, 0x09, 0x89, 0x42, 0x20, 0x3c, 0x80, 0x0a, 0xf2, + 0x10, 0x11, 0x01, 0x00, 0xa8, 0x20, 0x80, 0x01, 0x04, 0x11, 0x00, 0x04, + 0x04, 0x80, 0x80, 0xb0, 0xe5, 0x71, 0xbb, 0x0f, 0xc4, 0x92, 0x00, 0x19, + 0x02, 0x36, 0x00, 0xc1, 0x04, 0xc3, 0x04, 0x14, 0x04, 0x30, 0xa1, 0x40, + 0x96, 0x09, 0x2f, 0xf5, 0x63, 0x42, 0xef, 0x08, 0x31, 0x00, 0x10, 0x40, + 0x07, 0x85, 0xe7, 0x08, 0x1e, 0x02, 0x03, 0xc0, 0x1a, 0xe8, 0x02, 0x85, + 0xde, 0x08, 0x6f, 0xf4, 0x1f, 0xd9, 0x04, 0x35, 0x80, 0xaf, 0x7f, 0x47, + 0x00, 0xef, 0x00, 0x42, 0x10, 0xf7, 0x10, 0xea, 0x10, 0x82, 0x00, 0x90, + 0x48, 0x30, 0x00, 0x00, 0x00, 0x35, 0x01, 0x20, 0x07, 0x36, 0x40, 0x70, + 0x48, 0x47, 0x00, 0x00, 0x31, 0x82, 0x48, 0x30, 0x40, 0x02, 0x1f, 0xa1, + 0x02, 0xc0, 0x1c, 0xe8, 0x02, 0x85, 0xaa, 0x08, 0x6f, 0xf4, 0x1f, 0xd9, + 0x04, 0x37, 0x80, 0xaf, 0x7f, 0x47, 0x00, 0xef, 0x00, 0x42, 0x12, 0xf7, + 0x10, 0xea, 0x10, 0x82, 0x00, 0x90, 0x48, 0x30, 0x00, 0x00, 0x00, 0x37, + 0x01, 0x20, 0x07, 0x36, 0x40, 0x70, 0x48, 0x47, 0x00, 0x00, 0x31, 0x82, + 0x48, 0x30, 0x40, 0x02, 0x84, 0x19, 0x00, 0x00, 0x00, 0xc0, 0xed, 0x70, + 0xc4, 0x68, 0x67, 0x40, 0x6b, 0x0f, 0x05, 0x10, 0x00, 0xc0, 0x08, 0x10, + 0x01, 0x04, 0x40, 0xc0, 0xea, 0xe1, 0x12, 0xf2, 0xe8, 0xe1, 0x2a, 0xf4, + 0x00, 0x86, 0x04, 0x30, 0x80, 0x8f, 0x7f, 0x47, 0x00, 0xff, 0x24, 0xf2, + 0x02, 0x85, 0x4e, 0x08, 0x6f, 0xf4, 0x1f, 0xd9, 0x31, 0x80, 0x10, 0x80, + 0x3f, 0x81, 0x10, 0xf0, 0x00, 0x86, 0x04, 0x30, 0x80, 0x8f, 0x7f, 0x47, + 0x00, 0xff, 0x16, 0xf2, 0x02, 0x85, 0x32, 0x08, 0x6f, 0xf4, 0x1f, 0xd9, + 0x31, 0x80, 0x10, 0x80, 0x84, 0x11, 0x01, 0x00, 0x00, 0x90, 0x48, 0x31, + 0x01, 0x00, 0x48, 0x30, 0x00, 0x00, 0x00, 0x30, 0x40, 0x00, 0x07, 0x36, + 0x00, 0x70, 0x48, 0x47, 0x00, 0x00, 0x00, 0xa6, 0x08, 0xe6, 0xe5, 0x71, + 0xcb, 0xf1, 0x4a, 0x85, 0x6c, 0x70, 0x8d, 0x70, 0x30, 0x1a, 0x41, 0x00, + 0x2c, 0x1a, 0x00, 0x06, 0x05, 0xc1, 0x8f, 0x78, 0x23, 0x08, 0x45, 0x00, + 0x04, 0xc1, 0x16, 0x21, 0x00, 0x00, 0x20, 0x80, 0x09, 0xe9, 0x01, 0x80, + 0x04, 0x30, 0x80, 0x8f, 0x7f, 0x47, 0x00, 0xef, 0x03, 0xf7, 0x64, 0x71, + 0x6b, 0xa2, 0x85, 0x71, 0xee, 0xf1, 0x02, 0x40, 0xa6, 0xc0, 0x04, 0x14, + 0x1b, 0x34, 0xda, 0xc6, 0xe4, 0xc2, 0x08, 0x46, 0x03, 0x80, 0x00, 0x80, + 0x48, 0x80, 0x04, 0x82, 0x61, 0x92, 0x23, 0x82, 0xa0, 0x80, 0x11, 0x86, + 0x82, 0xbb, 0x4a, 0x0f, 0xef, 0xfd, 0x61, 0xb2, 0x19, 0x08, 0xfe, 0x01, + 0x00, 0x42, 0x24, 0x86, 0xc6, 0xba, 0x00, 0x81, 0x64, 0x80, 0x22, 0x83, + 0x40, 0xa9, 0x23, 0x80, 0x60, 0x79, 0xa1, 0xa3, 0xc4, 0xc6, 0xe0, 0x78, + 0xe2, 0xc2, 0x11, 0x80, 0xe2, 0x09, 0x2f, 0xfe, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x11, 0x80, 0x65, 0x02, 0x2f, 0xfe, 0x2f, 0x79, + 0xe2, 0xc2, 0x11, 0x80, 0x6e, 0x0a, 0x2f, 0xfe, 0x88, 0x45, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x51, 0x03, 0x2f, 0xfe, 0x11, 0x80, 0xe0, 0x78, + 0x1d, 0x06, 0xef, 0xfd, 0x11, 0x80, 0xe0, 0x78, 0x45, 0x03, 0x2f, 0xfe, + 0x11, 0x80, 0xe0, 0x78, 0xa1, 0x04, 0x2f, 0xfe, 0x11, 0x80, 0xe0, 0x78, + 0xf2, 0xc3, 0x82, 0x24, 0x0c, 0x3f, 0x28, 0x45, 0x22, 0x89, 0x08, 0x46, + 0x8a, 0x25, 0x3e, 0x27, 0x8c, 0x21, 0x83, 0x8f, 0xc9, 0xf4, 0x4a, 0x24, + 0xc0, 0x73, 0x8a, 0x27, 0x8e, 0x10, 0xdf, 0x67, 0x4a, 0x20, 0x00, 0x00, + 0xa8, 0x20, 0x80, 0x01, 0x81, 0xc1, 0x19, 0x61, 0x04, 0x71, 0x00, 0xa9, + 0x03, 0x8d, 0x09, 0xe8, 0x2e, 0x71, 0x8a, 0x25, 0xfe, 0x26, 0x0f, 0x08, + 0x34, 0x04, 0x61, 0xc0, 0xb3, 0xf0, 0x4a, 0x21, 0xc0, 0x23, 0x8a, 0x22, + 0x07, 0x2d, 0x54, 0x26, 0x14, 0x19, 0x54, 0x26, 0x93, 0x1b, 0xae, 0x70, + 0x0e, 0x71, 0x0c, 0x70, 0x00, 0x22, 0x92, 0x23, 0x00, 0x1c, 0x01, 0x31, + 0x0c, 0x20, 0x40, 0xa4, 0x42, 0x01, 0x2d, 0x00, 0x14, 0x70, 0x9f, 0xf4, + 0x81, 0xc0, 0x04, 0x77, 0x32, 0x20, 0x00, 0x04, 0x04, 0x77, 0x8e, 0xe0, + 0x22, 0x01, 0x0d, 0x00, 0x25, 0x20, 0x00, 0x00, 0x0f, 0xf0, 0x1a, 0xf0, + 0x27, 0xf0, 0x33, 0xf0, 0x45, 0xf0, 0x4b, 0xf0, 0x4f, 0xf0, 0x55, 0xf0, + 0x5a, 0xf0, 0x61, 0xf0, 0x66, 0xf0, 0x6c, 0xf0, 0x70, 0xf0, 0x76, 0xf0, + 0x7a, 0xf0, 0x80, 0xc1, 0x56, 0x24, 0x42, 0x3d, 0x82, 0x0d, 0x20, 0x00, + 0xa1, 0x40, 0x56, 0x24, 0x41, 0x3d, 0x14, 0xda, 0x82, 0x40, 0x1a, 0xf0, + 0x80, 0xc1, 0x00, 0x24, 0x82, 0x3f, 0x00, 0x00, 0x94, 0x01, 0x5e, 0x0e, + 0x20, 0x00, 0xa1, 0x40, 0x00, 0x24, 0x81, 0x3f, 0x00, 0x00, 0x94, 0x01, + 0x14, 0xda, 0x62, 0x40, 0x0a, 0xf0, 0x80, 0xc1, 0x85, 0xc2, 0x62, 0x08, + 0x60, 0x00, 0xa1, 0x40, 0x85, 0xc1, 0x8a, 0x22, 0x06, 0x00, 0x42, 0x40, + 0x6a, 0x0e, 0x4f, 0xe7, 0x59, 0xf0, 0x80, 0xc1, 0x00, 0x24, 0x82, 0x3f, + 0x00, 0x00, 0xbc, 0x01, 0x06, 0x09, 0x60, 0x00, 0xa1, 0x40, 0x70, 0x16, + 0x82, 0x10, 0x00, 0x24, 0x81, 0x3f, 0x00, 0x00, 0xbc, 0x01, 0x82, 0x0a, + 0x6f, 0xf1, 0xdf, 0x16, 0x00, 0x16, 0x10, 0x45, 0x45, 0xf0, 0x80, 0xc1, + 0x2a, 0x0b, 0x60, 0x00, 0xa1, 0x40, 0x0a, 0xa6, 0x3f, 0xf0, 0x80, 0xc1, + 0x1e, 0x0b, 0x60, 0x00, 0xa1, 0x40, 0x0b, 0xa6, 0x39, 0xf0, 0x80, 0xc1, + 0x12, 0x0b, 0x60, 0x00, 0xa1, 0x40, 0x0c, 0xa6, 0x33, 0xf0, 0x80, 0xc1, + 0x06, 0x0b, 0x60, 0x00, 0xa1, 0x40, 0xdd, 0x1e, 0x18, 0x10, 0x2d, 0xf0, + 0x80, 0xc1, 0xfa, 0x0a, 0x60, 0x00, 0xa1, 0x40, 0xde, 0x1e, 0x18, 0x10, + 0x25, 0xf0, 0x80, 0xc1, 0x1e, 0x0d, 0xe0, 0x00, 0xa1, 0x40, 0xff, 0x1f, + 0x02, 0x90, 0x1f, 0xf0, 0x80, 0xc1, 0x12, 0x0d, 0xe0, 0x00, 0xa1, 0x40, + 0x00, 0xaf, 0x19, 0xf0, 0x80, 0xc1, 0x06, 0x0d, 0xe0, 0x00, 0xa1, 0x40, + 0x01, 0xaf, 0x13, 0xf0, 0x80, 0xc1, 0xfa, 0x0c, 0xe0, 0x00, 0xa1, 0x40, + 0x02, 0xaf, 0x0d, 0xf0, 0x80, 0xc1, 0xee, 0x0c, 0xe0, 0x00, 0xa1, 0x40, + 0x03, 0xaf, 0x07, 0xf0, 0x80, 0xc1, 0xe2, 0x0c, 0xe0, 0x00, 0xa1, 0x40, + 0x04, 0xaf, 0xb6, 0x70, 0x79, 0x25, 0x00, 0x20, 0xc0, 0x20, 0x61, 0x20, + 0x5e, 0xf1, 0xa2, 0x40, 0xd2, 0xc7, 0xe0, 0x78, 0x4a, 0x24, 0xc0, 0x70, + 0xa8, 0x20, 0x40, 0x02, 0x02, 0x10, 0x42, 0x05, 0x07, 0x0a, 0x13, 0x00, + 0x53, 0x7a, 0x02, 0x19, 0x94, 0x00, 0xe0, 0x7e, 0xe4, 0xc2, 0x08, 0x46, + 0x4a, 0x25, 0x00, 0x10, 0x1a, 0x0e, 0x6f, 0xf9, 0x00, 0x86, 0xa5, 0x71, + 0xf9, 0x0d, 0x34, 0x91, 0x04, 0x1e, 0x10, 0x10, 0xc4, 0xc6, 0xe0, 0x78, + 0x2c, 0x72, 0x4c, 0x71, 0x2f, 0x21, 0x42, 0x80, 0x42, 0xf7, 0x09, 0x7a, + 0x46, 0x21, 0x01, 0x80, 0x04, 0xf2, 0x0e, 0x78, 0x09, 0x78, 0xf8, 0xf1, + 0xe0, 0x7f, 0x4e, 0x78, 0xf1, 0xc0, 0x00, 0x41, 0x14, 0x73, 0x0c, 0x77, + 0x07, 0xf7, 0xf0, 0x26, 0x41, 0x70, 0x13, 0x00, 0xbc, 0xaa, 0x03, 0xe9, + 0x40, 0x79, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0xe6, 0xc3, 0xa5, 0xc1, + 0x68, 0x45, 0x60, 0x83, 0x28, 0x46, 0x14, 0xe3, 0x2b, 0x0a, 0xe4, 0x00, + 0x00, 0x41, 0x80, 0xc0, 0x14, 0xda, 0x22, 0x0d, 0x6f, 0xe7, 0x80, 0xc7, + 0x4a, 0x24, 0x00, 0x75, 0xa8, 0x20, 0x00, 0x02, 0x00, 0x85, 0x01, 0x17, + 0x81, 0x14, 0xd8, 0x60, 0xc5, 0x71, 0x20, 0xa8, 0x00, 0x85, 0x14, 0xe0, + 0x00, 0xa5, 0xc6, 0xc7, 0xe4, 0xc2, 0x08, 0x46, 0x20, 0x40, 0x28, 0x45, + 0xa2, 0x0d, 0x2f, 0xfe, 0x00, 0x19, 0x01, 0x00, 0xc0, 0xa5, 0xa1, 0x40, + 0xc4, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0x08, 0x45, 0x70, 0x18, 0x03, 0x00, + 0x54, 0x20, 0x00, 0x09, 0x2c, 0x70, 0x1e, 0x0b, 0x6f, 0xf5, 0x14, 0xda, + 0x4a, 0x24, 0x40, 0x71, 0x54, 0x25, 0x80, 0x1b, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x18, 0x11, 0x00, 0x8a, 0x20, 0x07, 0x0d, 0xb8, 0x60, 0x2c, 0x70, + 0xfe, 0x0a, 0x6f, 0xf5, 0x8a, 0x22, 0x06, 0x00, 0x4a, 0x24, 0x40, 0x71, + 0x40, 0x25, 0x00, 0x1d, 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, + 0x8a, 0x24, 0x01, 0x78, 0x54, 0x25, 0x80, 0x1e, 0x4a, 0x26, 0x00, 0x10, + 0xa8, 0x20, 0x00, 0x01, 0x04, 0x18, 0x11, 0x00, 0xa1, 0x40, 0x1e, 0x0f, + 0x2f, 0xfe, 0xdf, 0x1d, 0x98, 0x13, 0x4a, 0x24, 0x40, 0x71, 0xa1, 0x40, + 0xa8, 0x20, 0x40, 0x01, 0xc1, 0xa0, 0x08, 0x18, 0x11, 0x00, 0x8a, 0x20, + 0x0e, 0x00, 0xb8, 0x60, 0x00, 0x18, 0x03, 0x00, 0xa1, 0x40, 0xc4, 0xc6, + 0xe4, 0xc2, 0x08, 0x46, 0x20, 0x40, 0x28, 0x45, 0x04, 0x19, 0x03, 0x00, + 0x66, 0x0a, 0x6f, 0xfe, 0x00, 0x19, 0x01, 0x00, 0xc0, 0xa5, 0xa1, 0x40, + 0xc4, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0x08, 0x46, 0x20, 0x40, 0x28, 0x45, + 0x82, 0x0a, 0x6f, 0xfe, 0x00, 0x19, 0x01, 0x00, 0xa1, 0x40, 0x7a, 0x0a, + 0x6f, 0xfe, 0x58, 0x1d, 0x01, 0x10, 0xc0, 0xa5, 0xa1, 0x40, 0xc4, 0xc6, + 0x4a, 0x24, 0xc0, 0x70, 0x40, 0x21, 0x03, 0x02, 0x0a, 0x22, 0x80, 0x0f, + 0x13, 0x00, 0x38, 0x6c, 0x04, 0x19, 0x43, 0x00, 0x00, 0x19, 0x01, 0x00, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x12, 0x0c, 0x04, 0x04, 0x1b, 0x10, 0x03, + 0x14, 0x19, 0x05, 0x00, 0x00, 0xa1, 0xe0, 0x7f, 0x20, 0x40, 0xe0, 0x78, + 0xe4, 0xc2, 0x08, 0x46, 0x78, 0x49, 0x28, 0x45, 0x6e, 0x0e, 0x6f, 0xfa, + 0x00, 0x19, 0x01, 0x00, 0x7e, 0x0b, 0x6f, 0xfe, 0xa1, 0x40, 0xc0, 0xa5, + 0xa1, 0x40, 0xc4, 0xc6, 0xe4, 0xc2, 0x08, 0x46, 0x20, 0x40, 0x28, 0x45, + 0x04, 0x19, 0x03, 0x00, 0x4e, 0x0d, 0x6f, 0xfe, 0x00, 0x19, 0x01, 0x00, + 0xc0, 0xa5, 0xa1, 0x40, 0xc4, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0x08, 0x46, + 0x20, 0x40, 0x28, 0x45, 0x04, 0x19, 0x03, 0x00, 0x6a, 0x0d, 0x6f, 0xfe, + 0x00, 0x19, 0x01, 0x00, 0xc0, 0xa5, 0xa1, 0x40, 0xc4, 0xc6, 0xe0, 0x78, + 0xe4, 0xc2, 0x08, 0x46, 0x0c, 0x70, 0x38, 0x19, 0x02, 0x00, 0x04, 0xa9, + 0x00, 0xa1, 0x20, 0x40, 0x06, 0x0a, 0xaf, 0xfe, 0x28, 0x45, 0xc0, 0xa5, + 0xa1, 0x40, 0xc4, 0xc6, 0xe2, 0xc0, 0x4a, 0x24, 0xc0, 0x70, 0x46, 0xdd, + 0x4c, 0x70, 0xfa, 0xdc, 0x40, 0x21, 0x03, 0x04, 0x04, 0x19, 0x43, 0x00, + 0xa7, 0xa1, 0x40, 0xa1, 0x82, 0xa1, 0x43, 0xa1, 0xa8, 0x20, 0x00, 0x01, + 0x04, 0x1b, 0x11, 0x00, 0x00, 0xa1, 0x20, 0x40, 0xc2, 0xc4, 0xe0, 0x78, + 0xe4, 0xc2, 0x08, 0x46, 0x20, 0x40, 0x28, 0x45, 0x04, 0x19, 0x03, 0x00, + 0x26, 0x0a, 0xaf, 0xfe, 0x00, 0x19, 0x01, 0x00, 0xc0, 0xa5, 0xa1, 0x40, + 0xc4, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0x08, 0x46, 0x20, 0x40, 0x28, 0x45, + 0x16, 0x0b, 0xaf, 0xfe, 0x00, 0x19, 0x01, 0x00, 0xc0, 0xa5, 0xa1, 0x40, + 0xc4, 0xc6, 0xe0, 0x78, 0x6c, 0x70, 0xf5, 0x20, 0xc2, 0x00, 0x09, 0x0a, + 0x13, 0x00, 0x53, 0x7a, 0x14, 0x21, 0xcc, 0x00, 0x74, 0x71, 0x6c, 0x71, + 0x40, 0xb4, 0xf7, 0xf5, 0xe0, 0x7e, 0xe0, 0x78, 0xe6, 0xc1, 0xa6, 0xc1, + 0x80, 0x80, 0x01, 0x80, 0x48, 0x41, 0x44, 0xc4, 0x45, 0xc0, 0x80, 0x81, + 0x40, 0x81, 0x01, 0x81, 0x50, 0x24, 0xfe, 0x97, 0x42, 0xc2, 0x43, 0xc0, + 0x18, 0xf2, 0x04, 0x34, 0x80, 0x9f, 0x80, 0x3f, 0x00, 0x00, 0x14, 0xf2, + 0x4a, 0x20, 0x00, 0x00, 0x40, 0x24, 0x0b, 0x34, 0x15, 0x23, 0x02, 0x10, + 0xa0, 0x82, 0x14, 0x71, 0x0c, 0x71, 0x07, 0x35, 0x0d, 0x13, 0xa0, 0xa2, + 0xf8, 0xf5, 0x01, 0x81, 0x07, 0x30, 0x0d, 0x03, 0x43, 0xc5, 0x03, 0xf0, + 0x03, 0xc5, 0x4a, 0x24, 0xc0, 0x70, 0xed, 0x70, 0x84, 0xc6, 0x40, 0x24, + 0x06, 0x30, 0xe9, 0x43, 0xa8, 0x20, 0xc0, 0x08, 0xf0, 0x23, 0xc1, 0x02, + 0xf0, 0x21, 0xc8, 0x12, 0x0c, 0x70, 0x41, 0xc7, 0x40, 0xc1, 0x15, 0x26, + 0x0c, 0x00, 0x01, 0x4e, 0x40, 0x84, 0x14, 0x71, 0x00, 0x30, 0x41, 0x10, + 0x0c, 0x71, 0x01, 0x32, 0x41, 0x00, 0x20, 0xa4, 0xf5, 0xf5, 0x00, 0xc1, + 0x01, 0xc0, 0x15, 0x25, 0xc2, 0x02, 0x00, 0x35, 0x48, 0x10, 0x15, 0x24, + 0xcc, 0x02, 0x02, 0x30, 0x00, 0x02, 0x65, 0x71, 0x00, 0xa2, 0x20, 0xa4, + 0x41, 0xc0, 0xc6, 0xc5, 0xe6, 0xc3, 0xa5, 0xc1, 0x68, 0x45, 0x60, 0x83, + 0x28, 0x46, 0x14, 0xe3, 0x2b, 0x0a, 0xe4, 0x00, 0x00, 0x41, 0x80, 0xc0, + 0x14, 0xda, 0x56, 0x0a, 0x6f, 0xe7, 0x80, 0xc7, 0x4a, 0x24, 0x00, 0x75, + 0xa8, 0x20, 0x00, 0x02, 0x00, 0x85, 0x01, 0x17, 0x81, 0x14, 0xd8, 0x60, + 0xc5, 0x71, 0x20, 0xa8, 0x00, 0x85, 0x14, 0xe0, 0x00, 0xa5, 0xc6, 0xc7, + 0xed, 0x06, 0x0f, 0xf8, 0xf1, 0xc0, 0x00, 0x41, 0x01, 0x80, 0x84, 0x20, + 0x03, 0x0c, 0x13, 0x08, 0x30, 0x08, 0x90, 0xe0, 0x0c, 0x70, 0x08, 0xf4, + 0x00, 0x81, 0x9b, 0x5a, 0x04, 0xf0, 0x7a, 0x0f, 0x2f, 0xf8, 0x00, 0x81, + 0xd1, 0xc0, 0xe0, 0x7e, 0xe6, 0xc1, 0xa9, 0xc1, 0x80, 0x80, 0x68, 0x41, + 0x48, 0x40, 0x43, 0xc4, 0x61, 0x80, 0x42, 0x80, 0x00, 0x81, 0x44, 0xc3, + 0x45, 0xc2, 0x40, 0xc0, 0x60, 0x81, 0x41, 0x81, 0x02, 0x81, 0x50, 0x23, + 0xfe, 0x87, 0x41, 0xc2, 0x42, 0xc0, 0x1c, 0xf2, 0x7f, 0xda, 0x17, 0xba, + 0x04, 0x33, 0x80, 0x80, 0x16, 0xf2, 0x4a, 0x24, 0xc0, 0x70, 0x83, 0xc0, + 0xa8, 0x20, 0xc0, 0x01, 0x20, 0x80, 0x07, 0x31, 0xc1, 0x00, 0x04, 0x18, + 0x50, 0x00, 0x2c, 0x71, 0x80, 0xc0, 0x35, 0x78, 0x80, 0x80, 0x34, 0x72, + 0x2c, 0x72, 0x07, 0x34, 0xcc, 0x10, 0x80, 0xa0, 0xb8, 0xf7, 0x40, 0xc2, + 0x6d, 0x70, 0x6c, 0x70, 0x0c, 0x70, 0x14, 0x20, 0xc1, 0x00, 0xf0, 0x21, + 0x41, 0x10, 0x41, 0x68, 0x86, 0xc4, 0x15, 0x24, 0x8d, 0x10, 0x15, 0x24, + 0x0e, 0x10, 0x0c, 0x71, 0x20, 0xa5, 0xeb, 0x0a, 0xb4, 0x80, 0x00, 0x1e, + 0x40, 0x10, 0xf0, 0x20, 0xc6, 0x10, 0x4a, 0x24, 0xc0, 0x70, 0x83, 0xc1, + 0x20, 0x1c, 0xc0, 0x32, 0xa8, 0x20, 0xc0, 0x02, 0x04, 0x11, 0x00, 0x04, + 0x40, 0x84, 0x00, 0x36, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x04, 0x1c, + 0x10, 0x10, 0x06, 0xc7, 0x4a, 0x20, 0x00, 0x00, 0x21, 0x68, 0x80, 0xc5, + 0x86, 0xc4, 0x25, 0x4d, 0x35, 0x7c, 0xc0, 0x84, 0x00, 0x35, 0xc6, 0x13, + 0x14, 0x20, 0xc2, 0x00, 0x02, 0x36, 0x8d, 0x11, 0x0c, 0x71, 0x15, 0x25, + 0x82, 0x00, 0xa0, 0xa4, 0xe1, 0x09, 0xb4, 0x80, 0xa0, 0xa2, 0x15, 0x24, + 0xc0, 0x00, 0x64, 0x71, 0x89, 0x0b, 0xf4, 0x80, 0xe0, 0xa0, 0xc6, 0xc5, + 0xe2, 0xc2, 0x28, 0x45, 0x20, 0x81, 0x40, 0x43, 0x14, 0xda, 0x19, 0x61, + 0xd6, 0x0e, 0x2f, 0xf5, 0x60, 0x40, 0x00, 0x85, 0x14, 0xe0, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0xe6, 0xc3, 0x82, 0x24, 0x06, 0x30, 0x68, 0x45, + 0x60, 0x83, 0x28, 0x46, 0x56, 0x23, 0x03, 0x0c, 0x2f, 0x0a, 0xe4, 0x00, + 0x00, 0x41, 0x80, 0xc0, 0x8a, 0x22, 0x06, 0x00, 0xf2, 0x08, 0x6f, 0xe7, + 0x80, 0xc7, 0x8a, 0x24, 0x06, 0x70, 0xa8, 0x20, 0x40, 0x02, 0x00, 0x85, + 0x01, 0x17, 0x81, 0x14, 0xd8, 0x60, 0xc5, 0x71, 0x20, 0xa8, 0x00, 0x85, + 0x56, 0x20, 0x00, 0x0c, 0x00, 0xa5, 0xc6, 0xc7, 0xe2, 0xc2, 0x08, 0x45, + 0x04, 0x71, 0xf2, 0x0b, 0x2f, 0xf2, 0x0f, 0x78, 0x10, 0xd9, 0xa1, 0x40, + 0x0c, 0x58, 0xc3, 0x40, 0xa0, 0x00, 0xf0, 0x86, 0x20, 0x80, 0xc3, 0x40, + 0x12, 0x00, 0x98, 0xbb, 0x09, 0x09, 0x20, 0x00, 0xb5, 0x71, 0xc2, 0xc6, + 0x60, 0xd8, 0xca, 0x20, 0x21, 0x06, 0xb5, 0x70, 0xca, 0x20, 0xa1, 0x01, + 0x0f, 0x58, 0xc2, 0xc6, 0xe6, 0xc2, 0x48, 0x45, 0x28, 0x46, 0xfe, 0x0c, + 0x6f, 0xf2, 0x08, 0x47, 0x14, 0x70, 0x0c, 0x70, 0x26, 0xf2, 0x8c, 0xd8, + 0x5f, 0x27, 0x01, 0x17, 0xea, 0x78, 0x30, 0x21, 0x82, 0x0f, 0xa0, 0x00, + 0xa8, 0x4d, 0x30, 0x20, 0x80, 0x0f, 0xa0, 0x00, 0x10, 0x4a, 0x50, 0x70, + 0x0c, 0x71, 0xd8, 0xf7, 0x80, 0x85, 0x2d, 0x0c, 0x85, 0x10, 0x5f, 0x27, + 0x01, 0x1f, 0x30, 0x21, 0x83, 0x0f, 0xa0, 0x00, 0xcc, 0x4c, 0x99, 0x62, + 0x0a, 0xe1, 0x19, 0x09, 0xe5, 0x00, 0x6c, 0x24, 0x41, 0x10, 0x40, 0x86, + 0x59, 0x61, 0x00, 0x19, 0x01, 0x00, 0x20, 0x85, 0x24, 0x74, 0x20, 0xa5, + 0xc6, 0xc6, 0xe0, 0x78, 0xe2, 0xc2, 0x28, 0x45, 0x20, 0x81, 0x40, 0x43, + 0x14, 0xda, 0x19, 0x61, 0xe2, 0x0d, 0x2f, 0xf5, 0x60, 0x40, 0x00, 0x85, + 0x14, 0xe0, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0xe6, 0xc3, 0x82, 0x24, + 0x06, 0x30, 0x68, 0x45, 0x60, 0x83, 0x28, 0x46, 0x56, 0x23, 0x03, 0x0c, + 0x2f, 0x0a, 0xe4, 0x00, 0x00, 0x41, 0x80, 0xc0, 0x8a, 0x22, 0x06, 0x00, + 0xfe, 0x0f, 0x2f, 0xe7, 0x80, 0xc7, 0x8a, 0x24, 0x06, 0x70, 0xa8, 0x20, + 0x40, 0x02, 0x00, 0x85, 0x01, 0x17, 0x81, 0x14, 0xd8, 0x60, 0xc5, 0x71, + 0x20, 0xa8, 0x00, 0x85, 0x56, 0x20, 0x00, 0x0c, 0x00, 0xa5, 0xc6, 0xc7, + 0xe2, 0xc0, 0x08, 0x44, 0x14, 0x70, 0x1c, 0xd8, 0x2a, 0xf2, 0x2a, 0xe9, + 0x60, 0x91, 0xe1, 0xd8, 0x4d, 0x0b, 0x81, 0x0f, 0x00, 0x00, 0x2b, 0x66, + 0x76, 0x81, 0xb6, 0x84, 0x41, 0x0b, 0x41, 0x03, 0xa1, 0x94, 0x0d, 0x0d, + 0xde, 0x11, 0x39, 0x0b, 0x34, 0x04, 0x70, 0xbb, 0x80, 0x23, 0x3e, 0x01, + 0x2d, 0x0b, 0x84, 0x00, 0x41, 0x91, 0x29, 0x0a, 0x41, 0x03, 0x62, 0x94, + 0x42, 0x91, 0x21, 0x0a, 0xc1, 0x00, 0x63, 0x94, 0x43, 0x91, 0x19, 0x0a, + 0xc1, 0x00, 0x78, 0x84, 0x58, 0x81, 0x11, 0x0a, 0xc1, 0x00, 0x59, 0x84, + 0x39, 0x81, 0x09, 0x09, 0x81, 0x00, 0x0c, 0x70, 0xc2, 0xc4, 0xe0, 0x78, + 0xe2, 0xc2, 0x08, 0x45, 0x14, 0x70, 0x1c, 0xd8, 0x1a, 0xf2, 0x20, 0x95, + 0x31, 0x09, 0x81, 0x0f, 0x00, 0x00, 0x2b, 0x66, 0x5e, 0x85, 0x78, 0xd9, + 0xda, 0x0d, 0xaf, 0xea, 0xa1, 0x40, 0x14, 0x70, 0x1d, 0xd8, 0x0e, 0xf2, + 0x1b, 0x85, 0x56, 0x85, 0x0a, 0xb8, 0x10, 0x72, 0xe1, 0xd8, 0x08, 0xf7, + 0x38, 0x85, 0x80, 0x22, 0x3e, 0x09, 0x09, 0x0a, 0x44, 0x00, 0x0c, 0x70, + 0xc2, 0xc6, 0xe0, 0x78, 0xe8, 0xc2, 0xcb, 0x45, 0x12, 0x00, 0x00, 0x40, + 0x2d, 0x0d, 0x81, 0x1f, 0x12, 0x00, 0x00, 0x40, 0x2c, 0x70, 0xed, 0x71, + 0x17, 0x69, 0x00, 0x20, 0x8e, 0x0f, 0xa0, 0x00, 0xe0, 0x5e, 0x00, 0x96, + 0x35, 0x08, 0x80, 0x0f, 0x00, 0x00, 0x2b, 0x66, 0x01, 0x69, 0xed, 0x08, + 0xb4, 0x80, 0x2c, 0x71, 0xcd, 0x70, 0x12, 0xf0, 0x38, 0x25, 0x81, 0x1f, + 0x20, 0x00, 0x00, 0x70, 0x38, 0x25, 0x80, 0x1f, 0x20, 0x00, 0x00, 0x20, + 0x25, 0x78, 0x0f, 0x08, 0x71, 0x00, 0xcd, 0x70, 0xcb, 0x46, 0x12, 0x00, + 0x84, 0x3f, 0xed, 0x70, 0x6e, 0x0f, 0xef, 0xff, 0xc1, 0x40, 0xc3, 0x08, + 0x11, 0x00, 0xc3, 0x41, 0x13, 0x00, 0x70, 0x9d, 0xb2, 0x49, 0xfe, 0x0e, + 0xef, 0xff, 0xc1, 0x40, 0xaf, 0x08, 0x11, 0x00, 0x0a, 0x09, 0x00, 0x00, + 0x4e, 0x0f, 0xef, 0xff, 0x08, 0x45, 0xa3, 0x08, 0x11, 0x00, 0x01, 0x96, + 0x2d, 0x08, 0x5e, 0x00, 0x97, 0x08, 0xbe, 0x00, 0x16, 0xd8, 0x16, 0x85, + 0x2c, 0x77, 0x41, 0x28, 0xbc, 0x80, 0x0a, 0xf2, 0x54, 0x25, 0x80, 0x1f, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x02, 0x04, 0x06, 0x39, 0x81, 0x00, + 0x17, 0x85, 0x77, 0x08, 0x61, 0x00, 0x13, 0xd8, 0x7c, 0x15, 0x0b, 0x10, + 0x00, 0x23, 0x40, 0x13, 0x54, 0x20, 0x81, 0x0f, 0xa1, 0x40, 0xaa, 0x0e, + 0xef, 0xff, 0x61, 0x42, 0xad, 0xe8, 0x54, 0x25, 0x82, 0x1f, 0x54, 0x23, + 0x83, 0x1f, 0xc1, 0x40, 0x1e, 0x0e, 0x2f, 0xf8, 0xa1, 0x41, 0x10, 0x40, + 0x00, 0x16, 0x00, 0x70, 0xa0, 0x00, 0xd8, 0x5e, 0x2c, 0x70, 0xa2, 0x0c, + 0x2f, 0xf5, 0x80, 0xda, 0xda, 0x0e, 0xe0, 0x00, 0xa1, 0x40, 0x99, 0xe8, + 0x16, 0xef, 0x36, 0x85, 0x16, 0x86, 0x16, 0x70, 0xc2, 0x21, 0x22, 0x04, + 0x38, 0x60, 0x00, 0x20, 0x8e, 0x0f, 0x12, 0x00, 0x7c, 0x40, 0x02, 0x26, + 0x0d, 0x70, 0xed, 0xff, 0x85, 0xbf, 0x2e, 0x09, 0xcf, 0xed, 0x1a, 0x65, + 0x2c, 0x70, 0x6e, 0x0c, 0x2f, 0xf5, 0xc1, 0x40, 0xc8, 0xc6, 0x7a, 0x0f, + 0xaf, 0xec, 0x2c, 0x71, 0xe2, 0xc2, 0x28, 0x45, 0x20, 0x81, 0x40, 0x43, + 0x8a, 0x22, 0x06, 0x00, 0x19, 0x61, 0xc6, 0x0b, 0x2f, 0xf5, 0x60, 0x40, + 0x00, 0x85, 0x56, 0x20, 0x00, 0x0c, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0xe2, 0xc1, 0x80, 0x83, 0x85, 0x74, 0x29, 0x0a, 0x24, 0x03, 0xa1, 0xc1, + 0x4a, 0x24, 0x00, 0x71, 0x40, 0xc0, 0x0c, 0x70, 0xa8, 0x20, 0x40, 0x02, + 0xa0, 0x83, 0x80, 0xc2, 0x0c, 0x62, 0x04, 0x71, 0xba, 0x61, 0x24, 0x71, + 0x80, 0xaa, 0x00, 0x83, 0x04, 0x74, 0x00, 0xa3, 0xc2, 0xc5, 0xe0, 0x78, + 0xf5, 0x02, 0xef, 0xf2, 0xc0, 0xd8, 0xe0, 0x78, 0xc3, 0x40, 0x13, 0x00, + 0x90, 0xa9, 0xe0, 0x7e, 0x4a, 0x21, 0x00, 0x00, 0x01, 0x10, 0x82, 0x04, + 0x81, 0x69, 0x20, 0x43, 0x54, 0x70, 0xca, 0x23, 0x01, 0x03, 0x0b, 0x0b, + 0xb3, 0x0b, 0x81, 0x41, 0x76, 0xea, 0x79, 0x22, 0x01, 0x00, 0x7a, 0x23, + 0x80, 0x0b, 0xe0, 0x7f, 0x25, 0x78, 0xe0, 0x78, 0xe2, 0xc2, 0x06, 0x0c, + 0xef, 0xf2, 0x08, 0x45, 0x8c, 0x25, 0x83, 0x9f, 0x0c, 0xf2, 0x8c, 0x25, + 0x83, 0x9e, 0x12, 0xf2, 0x8c, 0x25, 0xc3, 0x9e, 0x0c, 0xf2, 0x8c, 0x25, + 0x43, 0x9e, 0x0f, 0xf4, 0x0c, 0x73, 0x0b, 0xf0, 0x0a, 0x0c, 0x2f, 0xe9, + 0x0c, 0x73, 0x06, 0x0c, 0x2f, 0xe9, 0x0c, 0x72, 0x0c, 0x71, 0x03, 0xf0, + 0x0c, 0x72, 0xfa, 0x0b, 0x0f, 0xe9, 0xc2, 0xc6, 0xe2, 0xc2, 0x28, 0x45, + 0x20, 0x81, 0x40, 0x43, 0x8a, 0x22, 0x06, 0x00, 0x19, 0x61, 0x02, 0x0b, + 0x2f, 0xf5, 0x60, 0x40, 0x00, 0x85, 0x56, 0x20, 0x00, 0x0c, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0xe2, 0xc0, 0xa0, 0x83, 0x81, 0x6d, 0x11, 0x0a, + 0x24, 0x03, 0xb9, 0x61, 0x00, 0xa9, 0x00, 0x83, 0x04, 0x71, 0x00, 0xa3, + 0xc2, 0xc4, 0xe0, 0x78, 0x42, 0x22, 0x3c, 0x80, 0xe0, 0x7c, 0x40, 0x21, + 0x43, 0x06, 0xa8, 0x20, 0x00, 0x03, 0x07, 0x13, 0x01, 0x00, 0x0d, 0x09, + 0x01, 0x00, 0x20, 0x8b, 0x87, 0xb9, 0x20, 0xab, 0x55, 0x23, 0x03, 0x08, + 0xe0, 0x7e, 0xe0, 0x78, 0x14, 0x70, 0xe0, 0x7c, 0x39, 0x88, 0x87, 0xb9, + 0x39, 0xa8, 0x00, 0x80, 0xfc, 0xe8, 0xe0, 0x7e, 0xe8, 0xc3, 0xa1, 0xc1, + 0xc3, 0x41, 0xa0, 0x00, 0xfc, 0x86, 0x00, 0x89, 0x04, 0xe8, 0x00, 0x19, + 0x03, 0x00, 0x91, 0x5a, 0x8a, 0x20, 0x42, 0x2c, 0xcb, 0x47, 0xf0, 0x00, + 0x4b, 0x00, 0xcb, 0x46, 0x00, 0x00, 0xfc, 0x7f, 0x0c, 0x70, 0xc3, 0x41, + 0x00, 0x00, 0xff, 0xff, 0x80, 0xc2, 0x0a, 0x0e, 0x6f, 0xf7, 0x6c, 0x77, + 0x00, 0xc0, 0x78, 0xe8, 0xad, 0x70, 0x5a, 0xd9, 0x00, 0x1f, 0x02, 0x14, + 0xab, 0x21, 0x08, 0x0e, 0x0e, 0xf0, 0x0b, 0x09, 0x50, 0x00, 0x05, 0xe9, + 0x16, 0xf0, 0x60, 0x58, 0x06, 0xe8, 0xc3, 0x40, 0xa0, 0x00, 0xf4, 0x86, + 0x00, 0x80, 0x40, 0x78, 0x00, 0xc0, 0x0e, 0xf0, 0x19, 0x08, 0x6e, 0x03, + 0xaf, 0x79, 0x4a, 0x69, 0xdf, 0x0a, 0x55, 0x83, 0xc4, 0x78, 0x9a, 0x5a, + 0x00, 0xc1, 0xd2, 0x78, 0x24, 0x78, 0x40, 0xc0, 0xa5, 0x71, 0xad, 0x0d, + 0x15, 0x94, 0xf2, 0xe8, 0xd2, 0xf1, 0xe0, 0x78, 0xf1, 0xc0, 0x04, 0x77, + 0x0f, 0x78, 0x04, 0xe9, 0x21, 0x58, 0x03, 0xf0, 0x1d, 0x58, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0x2f, 0x7b, 0x8c, 0xd8, 0x6a, 0x78, + 0x00, 0x20, 0x80, 0x0f, 0xa0, 0x00, 0x25, 0x4a, 0x2f, 0x27, 0xbf, 0x00, + 0x6f, 0x23, 0x3f, 0x00, 0x6f, 0x26, 0x3f, 0x04, 0x20, 0x88, 0x00, 0x18, + 0xc3, 0x0f, 0x2f, 0x26, 0xbf, 0x00, 0x8c, 0x21, 0xc3, 0x8f, 0x07, 0xf2, + 0xf0, 0x26, 0xc0, 0x70, 0x13, 0x00, 0x4c, 0x90, 0x8c, 0x58, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xe2, 0xc2, 0x4d, 0x08, 0xd1, 0x01, 0xc3, 0x40, + 0xf0, 0x00, 0x5b, 0x00, 0xa0, 0x88, 0x20, 0x88, 0xe0, 0x78, 0xfd, 0x0d, + 0x41, 0x90, 0xc3, 0x40, 0xa0, 0x00, 0xb2, 0x41, 0x20, 0x88, 0x35, 0x0d, + 0x40, 0x10, 0xa0, 0xa8, 0xb2, 0x0a, 0xaf, 0xe6, 0xa1, 0x40, 0x12, 0x0f, + 0xaf, 0xec, 0xa1, 0x40, 0xcb, 0x45, 0xf0, 0x00, 0x47, 0x00, 0x32, 0x0c, + 0xaf, 0xe6, 0x00, 0x8d, 0x0b, 0xe8, 0x00, 0x8d, 0x00, 0x16, 0x01, 0x70, + 0xa0, 0x00, 0xf8, 0x86, 0x40, 0x79, 0x07, 0xf0, 0x22, 0x0d, 0x0f, 0xf3, + 0xc2, 0xc6, 0x0c, 0x70, 0x0f, 0x58, 0xc3, 0x40, 0xa0, 0x00, 0xa0, 0x42, + 0x20, 0x88, 0x2f, 0x27, 0xff, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0xc3, 0x42, + 0xf0, 0x00, 0x50, 0x02, 0x00, 0x82, 0x10, 0x20, 0x40, 0x00, 0x00, 0xa2, + 0x2f, 0x26, 0xff, 0x00, 0xc2, 0xc6, 0xe0, 0x78, 0xe0, 0x7f, 0x00, 0xa1, + 0x40, 0x81, 0x02, 0xa1, 0x54, 0x70, 0xe0, 0x7c, 0x21, 0x81, 0x00, 0x7a, + 0xe2, 0xc3, 0xa3, 0xc1, 0x08, 0xb8, 0x8f, 0xb8, 0x97, 0xb8, 0x88, 0x45, + 0xff, 0xdc, 0xc3, 0x44, 0x13, 0x00, 0xc8, 0x4d, 0x40, 0x24, 0x05, 0x32, + 0xcc, 0x70, 0x98, 0xb8, 0x42, 0xc4, 0x22, 0x0a, 0x6f, 0xf3, 0x40, 0xc5, + 0x8e, 0x09, 0x2f, 0xf8, 0x82, 0xc1, 0xc2, 0xc7, 0xe2, 0xc3, 0xa3, 0xc1, + 0x08, 0xb8, 0x97, 0xb8, 0x88, 0x45, 0xff, 0xdc, 0xc3, 0x44, 0x13, 0x00, + 0xc8, 0x4d, 0x40, 0x24, 0x05, 0x32, 0xcc, 0x70, 0x98, 0xb8, 0x42, 0xc4, + 0xf6, 0x09, 0x6f, 0xf3, 0x40, 0xc5, 0x66, 0x09, 0x2f, 0xf8, 0x82, 0xc1, + 0xc2, 0xc7, 0xe0, 0x78, 0x4a, 0x22, 0x40, 0x00, 0x02, 0x10, 0x01, 0x05, + 0x79, 0x21, 0x03, 0x00, 0x71, 0x4a, 0x0b, 0x09, 0xf3, 0x00, 0x44, 0x71, + 0x78, 0xeb, 0x7a, 0x21, 0xc0, 0x00, 0xe0, 0x7f, 0x65, 0x78, 0xe0, 0x78, + 0xe4, 0xc3, 0xa1, 0xc1, 0xa0, 0x81, 0x28, 0x46, 0x4c, 0x74, 0xb9, 0x60, + 0x06, 0x0b, 0x2f, 0xe7, 0x80, 0xc0, 0x00, 0xc0, 0x24, 0x6d, 0x20, 0xa6, + 0xc4, 0xc7, 0xe0, 0x78, 0xe6, 0xc3, 0xaa, 0xc1, 0x68, 0x45, 0x60, 0x83, + 0x28, 0x46, 0x28, 0xe3, 0x2b, 0x0a, 0xe4, 0x00, 0x00, 0x41, 0x80, 0xc0, + 0x28, 0xda, 0xe2, 0x0a, 0x2f, 0xe7, 0x80, 0xc7, 0x4a, 0x24, 0x00, 0x7a, + 0xa8, 0x20, 0x00, 0x02, 0x00, 0x85, 0x01, 0x17, 0x81, 0x14, 0xd8, 0x60, + 0xc5, 0x71, 0x20, 0xa8, 0x00, 0x85, 0x28, 0xe0, 0x00, 0xa5, 0xc6, 0xc7, + 0xe2, 0xc2, 0xc3, 0x42, 0xa0, 0x00, 0xae, 0x4a, 0xff, 0xd8, 0xcb, 0x44, + 0xa0, 0x00, 0x22, 0x4a, 0xc3, 0x41, 0xa0, 0x00, 0x3a, 0x4b, 0xf5, 0xdd, + 0xfb, 0xdb, 0x03, 0xaa, 0x03, 0xac, 0x03, 0xa9, 0xa0, 0xac, 0x60, 0xaa, + 0xfa, 0x0b, 0x6f, 0xf3, 0x60, 0xa9, 0xc3, 0x41, 0xa0, 0x00, 0x04, 0x42, + 0x00, 0x19, 0x80, 0x0f, 0x13, 0x00, 0x4c, 0x4d, 0xc2, 0xc6, 0xe0, 0x78, + 0xf1, 0xc0, 0x00, 0x16, 0x02, 0x70, 0xa0, 0x00, 0xc8, 0x87, 0xc3, 0x40, + 0x13, 0x00, 0x78, 0x4c, 0xc3, 0x41, 0x13, 0x00, 0x5c, 0x90, 0x6c, 0x70, + 0xc3, 0x45, 0xa1, 0x00, 0x7c, 0x1b, 0xc3, 0x46, 0xa0, 0x00, 0x08, 0xe9, + 0x12, 0x0a, 0xef, 0xf8, 0x8a, 0x24, 0x82, 0x00, 0x00, 0x1e, 0x00, 0x70, + 0xa0, 0x00, 0x00, 0x87, 0xd1, 0xc0, 0xe0, 0x7e, 0xe4, 0xc2, 0xc3, 0x40, + 0xf0, 0x00, 0x3e, 0x00, 0x20, 0x88, 0x81, 0xb9, 0x20, 0xa8, 0x00, 0x16, + 0x80, 0x70, 0xf0, 0x00, 0x0c, 0x01, 0x1b, 0x08, 0x3e, 0x01, 0xad, 0x70, + 0x2e, 0x0c, 0x8f, 0xf8, 0x08, 0x45, 0x29, 0x68, 0x0c, 0x70, 0x97, 0xb8, + 0x10, 0x71, 0xca, 0x25, 0x06, 0x10, 0x1a, 0x0d, 0x8f, 0xed, 0x02, 0x0d, + 0xaf, 0xed, 0x08, 0x46, 0x00, 0x41, 0xa1, 0x42, 0x06, 0x0f, 0x6f, 0xf8, + 0xc1, 0x40, 0xa6, 0x0a, 0xcf, 0xf6, 0x0c, 0x70, 0xc4, 0xc6, 0xe0, 0x78, + 0xe4, 0xc3, 0xa2, 0xc1, 0xcb, 0x45, 0xa0, 0x00, 0x64, 0xe7, 0x0c, 0x71, + 0x3a, 0x0c, 0x2f, 0xf7, 0x9c, 0x4d, 0x00, 0x16, 0x02, 0x70, 0xa0, 0x00, + 0xd0, 0x87, 0xcb, 0x46, 0xa0, 0x00, 0xe0, 0x86, 0x00, 0xa6, 0x54, 0x25, + 0x86, 0x1a, 0xc3, 0x40, 0x13, 0x00, 0x34, 0x64, 0xc3, 0x41, 0x13, 0x00, + 0x37, 0x90, 0x6c, 0x70, 0xc3, 0x45, 0xa1, 0x00, 0x7c, 0x11, 0x7a, 0x09, + 0xef, 0xf8, 0x8a, 0x24, 0xc2, 0x00, 0x01, 0xa6, 0x4a, 0x26, 0x00, 0x10, + 0xc3, 0x40, 0x69, 0x72, 0x4e, 0x56, 0x40, 0xc0, 0x74, 0xd8, 0x04, 0x1c, + 0x04, 0x30, 0x6a, 0x4e, 0x60, 0xc0, 0x54, 0xd8, 0xcc, 0x78, 0xf0, 0x26, + 0x82, 0x73, 0xa0, 0x00, 0xd4, 0x87, 0xf0, 0x26, 0x85, 0x73, 0xa0, 0x00, + 0xe0, 0x87, 0x55, 0x25, 0x81, 0x1a, 0x00, 0x20, 0x46, 0x00, 0x62, 0x6e, + 0x4e, 0x26, 0xc4, 0x11, 0xc3, 0x40, 0x13, 0x00, 0x24, 0x6a, 0x32, 0x09, + 0xef, 0xf8, 0x80, 0xc1, 0x15, 0x25, 0x81, 0x13, 0xc5, 0x71, 0xbd, 0x0e, + 0xf4, 0x90, 0x00, 0xa1, 0xc4, 0xc7, 0xe0, 0x78, 0xf2, 0xc2, 0x70, 0x42, + 0x50, 0x45, 0x30, 0x43, 0x08, 0x46, 0xcb, 0x47, 0xf0, 0x00, 0x34, 0x00, + 0x97, 0xd8, 0x34, 0x70, 0x06, 0x01, 0x21, 0x00, 0x17, 0xaf, 0x2e, 0x70, + 0x8a, 0x24, 0x03, 0x20, 0x32, 0x40, 0x1a, 0x20, 0x0d, 0x25, 0xdd, 0x65, + 0x32, 0x15, 0xc1, 0x10, 0x29, 0x09, 0x32, 0x00, 0x53, 0x21, 0x00, 0x01, + 0x21, 0x08, 0x75, 0x06, 0x25, 0xb9, 0x53, 0x21, 0x42, 0x00, 0x36, 0x0c, + 0xaf, 0xf3, 0xa1, 0x41, 0x32, 0x15, 0x81, 0x10, 0x0c, 0x71, 0xc3, 0x42, + 0xf0, 0x00, 0x60, 0x02, 0x38, 0x78, 0x00, 0xa2, 0x08, 0x85, 0x84, 0x20, + 0x03, 0x0c, 0xa0, 0xe0, 0x56, 0x00, 0x22, 0x00, 0x8d, 0x71, 0x2e, 0x15, + 0x80, 0x10, 0x2f, 0x15, 0x82, 0x10, 0x00, 0x2c, 0x01, 0x10, 0x2f, 0x27, + 0xff, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0xc3, 0x40, 0xf0, 0x00, 0x40, 0x02, + 0x11, 0x0a, 0x10, 0x00, 0x45, 0x80, 0x26, 0x7a, 0x45, 0xa0, 0x2f, 0x26, + 0xff, 0x00, 0x07, 0xf0, 0x45, 0x80, 0x45, 0x79, 0x25, 0xa0, 0x2f, 0x26, + 0xff, 0x00, 0x2e, 0x15, 0x82, 0x10, 0x58, 0x7c, 0x86, 0xa0, 0x2f, 0x27, + 0xff, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0x24, 0x80, 0x10, 0x21, 0x81, 0x00, + 0x24, 0xa0, 0x2f, 0x26, 0xff, 0x00, 0x06, 0x71, 0x0c, 0x20, 0xc0, 0xa4, + 0x6a, 0x07, 0xc5, 0xff, 0x6f, 0x26, 0xff, 0x05, 0x98, 0xd8, 0xad, 0x70, + 0x17, 0xaf, 0x5a, 0xd9, 0x0c, 0x70, 0xab, 0x21, 0x08, 0x0e, 0xaa, 0x1e, + 0x02, 0x10, 0xad, 0x1e, 0x02, 0x10, 0xaf, 0x1e, 0x02, 0x10, 0xb2, 0x0b, + 0x6f, 0xf3, 0xc1, 0x40, 0x25, 0x08, 0xb4, 0x00, 0x08, 0x43, 0x00, 0x86, + 0x86, 0x0b, 0xef, 0xff, 0x07, 0x1e, 0x43, 0x10, 0xc1, 0x40, 0xa2, 0x41, + 0x56, 0x0b, 0xef, 0xff, 0x42, 0x42, 0x18, 0x8e, 0x0a, 0x21, 0xc0, 0x22, + 0x16, 0xaf, 0x07, 0xf0, 0x32, 0x16, 0x80, 0x10, 0x8e, 0x09, 0x2f, 0xf2, + 0xc4, 0xb8, 0xa5, 0x71, 0xb7, 0x0d, 0xe4, 0x94, 0x55, 0x26, 0x0e, 0x1c, + 0x06, 0xf0, 0x6f, 0x26, 0xff, 0x05, 0x98, 0xd8, 0x2e, 0x70, 0x17, 0xaf, + 0x99, 0xd8, 0x35, 0x0a, 0x30, 0x20, 0x17, 0xaf, 0xcd, 0x70, 0xb7, 0x6e, + 0xa2, 0x75, 0xa1, 0x40, 0xd6, 0x0c, 0x6f, 0xf3, 0x3a, 0x1d, 0x05, 0x10, + 0x17, 0x08, 0xb4, 0x00, 0x00, 0x42, 0xa1, 0x40, 0x2a, 0x0b, 0xef, 0xff, + 0x07, 0x1d, 0x43, 0x10, 0x18, 0x8d, 0x50, 0x41, 0x16, 0xaf, 0xc5, 0x71, + 0xdb, 0x0e, 0x84, 0x94, 0x9a, 0xd8, 0x5a, 0xd9, 0x17, 0xaf, 0x2f, 0x20, + 0x47, 0x04, 0xab, 0x21, 0x08, 0x0e, 0xd2, 0xc6, 0xe2, 0xc2, 0x28, 0x45, + 0x20, 0x81, 0x40, 0x43, 0x28, 0xda, 0x19, 0x61, 0xaa, 0x0d, 0xef, 0xf4, + 0x60, 0x40, 0x00, 0x85, 0x28, 0xe0, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0x48, 0x81, 0x23, 0x92, 0x0b, 0x08, 0x44, 0x00, 0x24, 0x92, 0x09, 0x21, + 0x01, 0x00, 0xe0, 0x7f, 0x20, 0x40, 0xe0, 0x78, 0xf6, 0xc3, 0xa3, 0xc1, + 0x50, 0x47, 0x30, 0x44, 0x2a, 0x08, 0xef, 0xf3, 0x08, 0x45, 0xd3, 0x42, + 0x00, 0x00, 0xff, 0xff, 0x8f, 0x08, 0xa0, 0x04, 0x10, 0x41, 0x0e, 0x70, + 0xd3, 0x45, 0x00, 0x00, 0xef, 0xff, 0x40, 0x24, 0x16, 0x30, 0x4a, 0x47, + 0x08, 0x8d, 0x4d, 0x08, 0x25, 0x20, 0xf0, 0x7e, 0x03, 0x85, 0xf0, 0x20, + 0x0e, 0x04, 0x07, 0x86, 0x0b, 0x08, 0xf1, 0x00, 0xc1, 0x40, 0xe6, 0x08, + 0xcf, 0xf4, 0x17, 0x0d, 0x64, 0x24, 0x0a, 0x23, 0x80, 0x24, 0x22, 0x40, + 0xc1, 0x41, 0x23, 0x20, 0x00, 0x05, 0xe2, 0x42, 0x10, 0x43, 0xc1, 0x40, + 0x7e, 0x0a, 0xef, 0xf4, 0x62, 0x41, 0x14, 0x26, 0x00, 0x24, 0x00, 0x18, + 0xc4, 0x04, 0xf0, 0x78, 0x9a, 0x0e, 0xaf, 0xf3, 0x62, 0x41, 0x08, 0x47, + 0x06, 0x71, 0xdc, 0xf1, 0x10, 0x85, 0x85, 0x0d, 0xa4, 0x23, 0xe0, 0xb0, + 0x47, 0x85, 0x05, 0xea, 0x80, 0xc1, 0x60, 0x7a, 0xa1, 0x40, 0x69, 0x85, + 0x05, 0xeb, 0x80, 0xc2, 0xc1, 0x41, 0x60, 0x7b, 0xa1, 0x40, 0x92, 0x0e, + 0xaf, 0xf3, 0xa1, 0x40, 0x10, 0x85, 0x21, 0x90, 0x80, 0xb9, 0x21, 0xb0, + 0xd6, 0xc7, 0x08, 0x8d, 0x11, 0xe8, 0xed, 0x70, 0x40, 0x24, 0x10, 0x30, + 0x4a, 0x26, 0x00, 0x10, 0x03, 0x85, 0xe0, 0x60, 0x23, 0x80, 0x40, 0x79, + 0x08, 0x8d, 0xc5, 0x71, 0x02, 0x18, 0xd5, 0x2f, 0xf1, 0x0e, 0x24, 0x90, + 0xe5, 0x74, 0x69, 0x85, 0x10, 0x85, 0x00, 0x18, 0x84, 0x04, 0x06, 0xeb, + 0x80, 0xc2, 0x42, 0x41, 0x60, 0x7b, 0xa1, 0x40, 0x09, 0x8d, 0x10, 0xe8, + 0xcd, 0x70, 0xed, 0x70, 0x04, 0x85, 0xc3, 0x41, 0x00, 0x00, 0xff, 0xff, + 0x16, 0x09, 0x2f, 0xf4, 0xc0, 0x60, 0x09, 0x8d, 0xe5, 0x71, 0xf1, 0x0f, + 0x24, 0x90, 0xc5, 0x74, 0xd6, 0xc7, 0xe0, 0x78, 0xf1, 0xc0, 0x88, 0x81, + 0x62, 0x8c, 0x0f, 0x0b, 0x9e, 0x01, 0x65, 0x94, 0x64, 0x7a, 0x17, 0x0a, + 0xc1, 0x00, 0xc3, 0x42, 0x00, 0x00, 0xff, 0xff, 0x19, 0x08, 0x80, 0x00, + 0x87, 0xe8, 0x43, 0x94, 0x08, 0xf0, 0xc3, 0x42, 0x00, 0x00, 0xff, 0xff, + 0x04, 0xf0, 0xca, 0x0e, 0xcf, 0xff, 0x00, 0x42, 0xd1, 0xc0, 0xe0, 0x7f, + 0x50, 0x78, 0xe0, 0x78, 0xe2, 0xc2, 0x88, 0x81, 0xa1, 0x94, 0x0f, 0x0d, + 0x9e, 0x11, 0x65, 0x94, 0x64, 0x7a, 0x1b, 0x0a, 0xc1, 0x00, 0xc3, 0x42, + 0x00, 0x00, 0xff, 0xff, 0x1d, 0x08, 0x80, 0x00, 0x03, 0xe8, 0x13, 0x0d, + 0x1f, 0x11, 0x44, 0x94, 0x08, 0xf0, 0xc3, 0x42, 0x00, 0x00, 0xff, 0xff, + 0x04, 0xf0, 0x8e, 0x0e, 0xcf, 0xff, 0x00, 0x42, 0x50, 0x78, 0xc2, 0xc6, + 0xf1, 0xc0, 0x88, 0x81, 0x62, 0x8c, 0x0f, 0x0b, 0x9e, 0x01, 0x65, 0x94, + 0x64, 0x7a, 0x17, 0x0a, 0xc1, 0x00, 0xc3, 0x42, 0x00, 0x00, 0xff, 0xff, + 0x19, 0x08, 0x80, 0x00, 0x87, 0xe8, 0x44, 0x94, 0x08, 0xf0, 0xc3, 0x42, + 0x00, 0x00, 0xff, 0xff, 0x04, 0xf0, 0x5a, 0x0e, 0xcf, 0xff, 0x00, 0x42, + 0xd1, 0xc0, 0xe0, 0x7f, 0x50, 0x78, 0xe0, 0x78, 0xe6, 0xc0, 0x64, 0x80, + 0x8d, 0x70, 0x41, 0xa3, 0x08, 0x8b, 0x2d, 0x0c, 0x05, 0x10, 0x03, 0x8b, + 0x10, 0xe8, 0x1a, 0x24, 0x0d, 0x10, 0x4c, 0x70, 0xc6, 0x83, 0x47, 0x49, + 0x44, 0x71, 0xb5, 0x7e, 0x00, 0x86, 0x01, 0x37, 0x00, 0x10, 0x00, 0xa6, + 0x03, 0x8b, 0xf1, 0x0a, 0x24, 0x80, 0xa5, 0x71, 0x85, 0x71, 0xec, 0xf1, + 0xc6, 0xc4, 0xe0, 0x78, 0xe6, 0xc2, 0xa4, 0x80, 0x08, 0x46, 0x00, 0x95, + 0x9b, 0x08, 0x85, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x9f, 0x08, 0x30, 0x00, + 0xc1, 0x40, 0xd6, 0x09, 0x00, 0x00, 0x23, 0x85, 0x1c, 0x15, 0x08, 0x10, + 0x6c, 0x70, 0x68, 0x43, 0x02, 0x8e, 0x85, 0x0b, 0x05, 0x00, 0x02, 0x86, + 0x64, 0x48, 0x08, 0x84, 0x40, 0x90, 0x6f, 0x0a, 0x80, 0x0f, 0x00, 0x00, + 0xff, 0xff, 0x04, 0x86, 0x2f, 0x21, 0xc7, 0x12, 0x0a, 0x27, 0x00, 0x02, + 0xcc, 0x70, 0x00, 0x90, 0x05, 0x2a, 0x02, 0x00, 0x0c, 0x70, 0x50, 0x7f, + 0x13, 0x08, 0x45, 0x02, 0x02, 0x17, 0x04, 0x05, 0x31, 0x0f, 0x00, 0x11, + 0xc4, 0x74, 0x04, 0x71, 0xf8, 0xf1, 0x78, 0x61, 0x00, 0x18, 0xc2, 0x02, + 0x14, 0x20, 0x4f, 0x12, 0x03, 0x8d, 0x40, 0xb7, 0x88, 0x84, 0x1f, 0x20, + 0x42, 0x02, 0xe4, 0x85, 0x05, 0x85, 0x65, 0x71, 0x15, 0x27, 0x4f, 0x12, + 0x55, 0x78, 0xe4, 0xa4, 0x03, 0xa4, 0x0d, 0xf0, 0x7a, 0x61, 0x00, 0xaa, + 0xe8, 0x84, 0x43, 0x8d, 0x85, 0x85, 0x0c, 0x7a, 0x04, 0x85, 0x55, 0x7c, + 0xc0, 0x70, 0x04, 0xa7, 0x83, 0xa7, 0x64, 0x71, 0xc2, 0xf1, 0x08, 0x1d, + 0x03, 0x10, 0x15, 0xf0, 0x08, 0x1d, 0xc2, 0x12, 0x11, 0xf0, 0x02, 0x8e, + 0x42, 0x20, 0x3c, 0x80, 0x0d, 0xf2, 0x44, 0x85, 0x65, 0x85, 0x22, 0x86, + 0x08, 0x1d, 0x03, 0x10, 0xa8, 0x20, 0xc0, 0x01, 0x04, 0x11, 0x00, 0x04, + 0x08, 0x80, 0x44, 0xa0, 0x63, 0xa0, 0x0c, 0x70, 0xc6, 0xc6, 0xe0, 0x78, + 0xea, 0xc2, 0x24, 0x80, 0x08, 0x45, 0x00, 0x91, 0xdb, 0x08, 0x30, 0x00, + 0xcd, 0x70, 0x0c, 0x11, 0x11, 0x00, 0xe8, 0x81, 0x1c, 0x11, 0x08, 0x00, + 0x4c, 0x70, 0x08, 0x89, 0x9b, 0x0a, 0x25, 0x00, 0x14, 0x27, 0x8b, 0x10, + 0xf4, 0x27, 0x80, 0x10, 0x04, 0x71, 0x00, 0x1b, 0x04, 0x10, 0xf4, 0x20, + 0x83, 0x10, 0x10, 0x78, 0x43, 0x08, 0xc1, 0x00, 0x63, 0x89, 0x1a, 0xeb, + 0x4a, 0x21, 0x00, 0x10, 0x06, 0x81, 0x4c, 0x7b, 0xf4, 0x20, 0x86, 0x10, + 0x00, 0x21, 0xcc, 0x10, 0x80, 0x48, 0x48, 0x36, 0x03, 0x00, 0x25, 0x71, + 0x07, 0x30, 0xc3, 0x00, 0x05, 0x81, 0x95, 0x78, 0x60, 0xa0, 0x06, 0x81, + 0x95, 0x78, 0x00, 0x18, 0x01, 0x00, 0x63, 0x89, 0xd9, 0x09, 0xc4, 0x90, + 0x04, 0x81, 0x61, 0x81, 0x00, 0x1b, 0x84, 0x13, 0x1d, 0xf0, 0x3f, 0x0b, + 0x94, 0x00, 0x24, 0x11, 0x80, 0x00, 0x37, 0x08, 0x51, 0x00, 0x03, 0x89, + 0x11, 0xe8, 0x2d, 0x70, 0x86, 0x81, 0x4c, 0x78, 0x65, 0x81, 0x21, 0x70, + 0x04, 0x4c, 0x15, 0x7b, 0x25, 0x71, 0x80, 0xa3, 0x66, 0x81, 0x15, 0x7b, + 0x00, 0x1b, 0x01, 0x00, 0x03, 0x89, 0xe9, 0x09, 0x04, 0x90, 0x04, 0x81, + 0x61, 0x81, 0x00, 0x1b, 0x05, 0x10, 0x55, 0x78, 0x60, 0xa0, 0x44, 0x71, + 0xb3, 0xf1, 0x0e, 0x70, 0x24, 0x19, 0x82, 0x03, 0x02, 0x8d, 0x49, 0x08, + 0x05, 0x20, 0x01, 0x11, 0x80, 0x24, 0xf4, 0x27, 0x00, 0x10, 0x8a, 0xe8, + 0x02, 0x85, 0xc0, 0x60, 0x28, 0x80, 0x22, 0x89, 0x09, 0x09, 0x1e, 0x00, + 0x42, 0x0b, 0xcf, 0xf3, 0xc5, 0x74, 0x06, 0x71, 0xee, 0xf1, 0x22, 0x8d, + 0x10, 0xe9, 0xcd, 0x70, 0xed, 0x70, 0x02, 0x85, 0xc0, 0x60, 0x48, 0x80, + 0x42, 0x8a, 0x0d, 0x0a, 0x1e, 0x00, 0x26, 0x0b, 0xcf, 0xf3, 0x22, 0x8d, + 0xe5, 0x71, 0xef, 0x0f, 0x64, 0x90, 0xc5, 0x74, 0xca, 0xc6, 0xe0, 0x78, + 0x04, 0x80, 0x65, 0x80, 0x60, 0xa1, 0x04, 0x80, 0xe0, 0x7f, 0x00, 0xa2, + 0xe4, 0xc2, 0xc4, 0x80, 0x08, 0x45, 0x2c, 0x70, 0x24, 0x1e, 0x43, 0x10, + 0x42, 0x88, 0x03, 0x86, 0x08, 0x1e, 0x03, 0x10, 0x3a, 0x0a, 0xef, 0xf4, + 0x04, 0x1e, 0x01, 0x10, 0x22, 0x8d, 0x04, 0x86, 0x52, 0x69, 0x2e, 0x0a, + 0xef, 0xf4, 0x2c, 0x70, 0x22, 0x8d, 0x03, 0x8e, 0x0a, 0x79, 0x05, 0x86, + 0x52, 0x69, 0x1e, 0x0a, 0xef, 0xf4, 0x2c, 0x70, 0x22, 0x8d, 0x03, 0x8e, + 0x0a, 0x79, 0x06, 0x86, 0x52, 0x69, 0x0e, 0x0a, 0xef, 0xf4, 0x2c, 0x70, + 0x22, 0x8d, 0x07, 0x86, 0x3b, 0x7a, 0x02, 0x0a, 0xef, 0xf4, 0x2c, 0x70, + 0x22, 0x8d, 0x08, 0x86, 0x3b, 0x7a, 0xf6, 0x09, 0xef, 0xf4, 0x2c, 0x70, + 0xc4, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0xa4, 0x80, 0x22, 0x88, 0x08, 0x46, + 0x04, 0x85, 0x52, 0x69, 0xde, 0x09, 0xef, 0xf4, 0x2c, 0x70, 0x22, 0x8e, + 0x08, 0x85, 0x3b, 0x7a, 0xd2, 0x09, 0xef, 0xf4, 0x2c, 0x70, 0x22, 0x8e, + 0x03, 0x8d, 0x0a, 0x79, 0x06, 0x85, 0x52, 0x69, 0xc2, 0x09, 0xef, 0xf4, + 0x2c, 0x70, 0xc4, 0xc6, 0x44, 0x80, 0x22, 0x88, 0x05, 0x82, 0x04, 0x1a, + 0x01, 0x00, 0x3b, 0x7a, 0xad, 0x01, 0xef, 0xf4, 0x2c, 0x70, 0xe0, 0x78, + 0xf1, 0xc0, 0x21, 0x80, 0x0d, 0x09, 0x50, 0x00, 0x86, 0xe9, 0xe6, 0x0f, + 0xcf, 0xff, 0x04, 0xf0, 0xae, 0x0f, 0xcf, 0xff, 0xd1, 0xc0, 0xe0, 0x7e, + 0xea, 0xc2, 0xa8, 0x46, 0xe0, 0x86, 0x8b, 0x80, 0x28, 0x45, 0x00, 0x27, + 0x01, 0x11, 0x70, 0x40, 0x50, 0x41, 0x14, 0x24, 0xcb, 0x13, 0x15, 0x24, + 0xc3, 0x13, 0x34, 0x7c, 0x4c, 0x95, 0xfa, 0x1b, 0x5c, 0x14, 0xfa, 0x1c, + 0x1c, 0x14, 0x2c, 0x95, 0x05, 0x80, 0x5d, 0xa3, 0xa0, 0xb9, 0x38, 0x60, + 0xe0, 0xb0, 0x2c, 0x70, 0xa2, 0x08, 0xaf, 0xf4, 0xa1, 0x40, 0x28, 0x85, + 0x01, 0x6f, 0x00, 0xa6, 0x08, 0x19, 0x04, 0x04, 0x06, 0x19, 0x44, 0x04, + 0xca, 0xc6, 0xe0, 0x78, 0xe6, 0xc0, 0x00, 0x43, 0x99, 0x88, 0x00, 0x82, + 0x20, 0x46, 0x91, 0x70, 0xa6, 0x00, 0x25, 0x00, 0x8a, 0x20, 0x7f, 0x0c, + 0x42, 0x24, 0x3c, 0x90, 0x4b, 0xf2, 0xa4, 0x83, 0xec, 0x70, 0xcb, 0x41, + 0x00, 0x00, 0xee, 0xff, 0xcb, 0x40, 0x48, 0x47, 0x00, 0x00, 0xe8, 0x43, + 0xa8, 0x20, 0x41, 0x00, 0xf0, 0x25, 0xc3, 0x12, 0x5a, 0x23, 0x0f, 0x15, + 0xc8, 0x83, 0x6c, 0x93, 0xc0, 0x77, 0x00, 0x96, 0x60, 0xa7, 0x29, 0x68, + 0x30, 0x79, 0x13, 0x09, 0x64, 0x10, 0x14, 0x70, 0x48, 0x30, 0x00, 0x00, + 0x07, 0x30, 0x00, 0x10, 0x06, 0xf0, 0xc3, 0x40, 0x7f, 0x47, 0x00, 0xff, + 0xca, 0x20, 0xc1, 0x01, 0x63, 0x96, 0x01, 0xa7, 0x29, 0x6b, 0x30, 0x79, + 0x0f, 0x09, 0x64, 0x10, 0x48, 0x33, 0x00, 0x00, 0x07, 0x30, 0x00, 0x10, + 0x07, 0xf0, 0x74, 0x70, 0xc3, 0x40, 0x7f, 0x47, 0x00, 0xff, 0xca, 0x20, + 0xc1, 0x01, 0x64, 0x96, 0x02, 0xa7, 0x29, 0x6b, 0x30, 0x79, 0x11, 0x09, + 0x64, 0x10, 0x48, 0x33, 0x00, 0x00, 0x07, 0x30, 0x00, 0x10, 0x09, 0xf0, + 0x74, 0x70, 0x2c, 0x70, 0xc3, 0x40, 0x7f, 0x47, 0x00, 0xff, 0xca, 0x20, + 0x41, 0x00, 0x25, 0x96, 0x65, 0x71, 0x03, 0xa7, 0x28, 0xb7, 0x0c, 0x70, + 0x80, 0xa2, 0xc6, 0xc4, 0xfa, 0xc2, 0xfc, 0x1c, 0xc8, 0xb6, 0xad, 0xc1, + 0x0a, 0x23, 0xc0, 0x31, 0x0a, 0x23, 0x80, 0x21, 0x0a, 0x21, 0x40, 0x31, + 0x0a, 0x25, 0x00, 0x21, 0x70, 0x42, 0x50, 0x47, 0x30, 0x46, 0x08, 0x47, + 0xad, 0x70, 0x04, 0x1c, 0x01, 0x34, 0x42, 0xc5, 0xa1, 0x0a, 0x30, 0x00, + 0x40, 0xc5, 0x9d, 0x0d, 0x10, 0x20, 0x99, 0x09, 0x14, 0x32, 0x0a, 0x87, + 0x0a, 0x80, 0x4c, 0x20, 0x00, 0x80, 0xae, 0x01, 0x21, 0x00, 0x8a, 0x21, + 0xfc, 0x20, 0x4c, 0x22, 0x00, 0xa8, 0xa2, 0x01, 0x25, 0x00, 0x8a, 0x21, + 0xff, 0x26, 0xd1, 0x0e, 0x30, 0x20, 0x8a, 0x20, 0xbc, 0x20, 0x8e, 0x70, + 0x92, 0x40, 0x02, 0x87, 0xcd, 0x70, 0x20, 0x88, 0x6b, 0x08, 0x65, 0x20, + 0x40, 0x24, 0x18, 0x33, 0x01, 0x80, 0x83, 0xc3, 0x40, 0x24, 0x04, 0x3c, + 0x2c, 0x70, 0xf0, 0x20, 0x11, 0x04, 0xc2, 0x42, 0x38, 0x11, 0x0c, 0x20, + 0x23, 0x20, 0x00, 0x03, 0x22, 0x40, 0x0c, 0xc0, 0x3d, 0x0e, 0x25, 0x10, + 0x40, 0x24, 0x04, 0x30, 0x01, 0x10, 0x83, 0x34, 0x34, 0x11, 0x0c, 0x20, + 0x22, 0x40, 0xa2, 0x41, 0x23, 0x20, 0x00, 0x03, 0x23, 0x42, 0x00, 0xc3, + 0x0e, 0xeb, 0x81, 0xc2, 0xe2, 0x40, 0x42, 0x41, 0x0a, 0x24, 0x40, 0x05, + 0x76, 0x0c, 0xef, 0xf3, 0x0a, 0x25, 0x40, 0x06, 0x08, 0x45, 0x86, 0xe8, + 0x86, 0x71, 0xad, 0x70, 0xc5, 0x71, 0xe3, 0xf1, 0x06, 0x71, 0xcd, 0xf1, + 0x8a, 0x21, 0xbc, 0x20, 0x8f, 0xf0, 0x83, 0xc3, 0x40, 0x24, 0x04, 0x3b, + 0x2c, 0x70, 0xe1, 0x40, 0xde, 0x0a, 0x2f, 0xf4, 0xc2, 0x42, 0x0b, 0xc0, + 0x3d, 0x0e, 0x25, 0x10, 0x40, 0x24, 0x04, 0x32, 0x01, 0x10, 0x83, 0x34, + 0xe1, 0x40, 0xa2, 0x41, 0xd2, 0x0a, 0x2f, 0xf4, 0x23, 0x42, 0x02, 0xc0, + 0x10, 0xe8, 0x00, 0xc3, 0x81, 0xc2, 0xe2, 0x40, 0x42, 0x41, 0x0a, 0x24, + 0x40, 0x05, 0x22, 0x0c, 0xef, 0xf3, 0x0a, 0x25, 0x40, 0x06, 0x89, 0x08, + 0x31, 0x00, 0x10, 0x41, 0x86, 0x71, 0xad, 0x70, 0xc5, 0x71, 0xe3, 0xf1, + 0xb1, 0x41, 0x3c, 0xf0, 0x8e, 0x70, 0xcd, 0x70, 0x63, 0xc5, 0x02, 0x87, + 0x20, 0x88, 0x3f, 0x0e, 0x65, 0x10, 0x40, 0x24, 0x04, 0x30, 0x01, 0x80, + 0x23, 0xc3, 0xa0, 0x60, 0x23, 0x42, 0x8d, 0x80, 0x23, 0x20, 0x00, 0x03, + 0xa2, 0x41, 0x00, 0xc3, 0x0e, 0xeb, 0x81, 0xc2, 0xe2, 0x40, 0x42, 0x41, + 0x0a, 0x24, 0x40, 0x05, 0xd6, 0x0b, 0xef, 0xf3, 0x0a, 0x25, 0x40, 0x06, + 0x10, 0x40, 0x87, 0xe8, 0x86, 0x71, 0x0e, 0x70, 0xa5, 0x74, 0xc5, 0x71, + 0xe1, 0xf1, 0x40, 0x24, 0x04, 0x32, 0x6c, 0x70, 0xe1, 0x40, 0xa2, 0x41, + 0x52, 0x0a, 0x2f, 0xf4, 0x23, 0x42, 0x02, 0xc3, 0x0a, 0x21, 0x00, 0x24, + 0x0c, 0xeb, 0x81, 0xc2, 0xe2, 0x40, 0x42, 0x41, 0x0a, 0x24, 0x40, 0x05, + 0x9e, 0x0b, 0xef, 0xf3, 0x0a, 0x25, 0x40, 0x06, 0x10, 0x41, 0x86, 0x71, + 0x33, 0x09, 0x31, 0x20, 0x2f, 0x25, 0x07, 0x85, 0x15, 0xf2, 0x01, 0xc0, + 0x81, 0xc2, 0xe2, 0x41, 0x70, 0xb8, 0x41, 0xc0, 0xe1, 0x40, 0xa2, 0x43, + 0x0a, 0x24, 0x40, 0x06, 0x0a, 0x26, 0x80, 0x05, 0x36, 0x0f, 0xef, 0xf3, + 0x0a, 0x27, 0xc0, 0x06, 0x01, 0xc0, 0x2e, 0x70, 0x00, 0x1b, 0x00, 0x20, + 0x0e, 0xf0, 0x2c, 0x70, 0xe2, 0x40, 0x42, 0x42, 0xc2, 0x0e, 0xaf, 0xf4, + 0x00, 0x1b, 0x01, 0x20, 0x2f, 0x26, 0x07, 0xf5, 0x8a, 0x20, 0xff, 0x06, + 0xca, 0x21, 0x01, 0x20, 0x2c, 0x70, 0xa2, 0x40, 0xaa, 0x0e, 0xaf, 0xf4, + 0x23, 0x42, 0x22, 0x40, 0xad, 0xc0, 0x04, 0x14, 0x1b, 0x34, 0xda, 0xc6, + 0xec, 0xc2, 0xbe, 0x0f, 0xaf, 0xfe, 0x08, 0x47, 0x01, 0x87, 0x04, 0xe8, + 0x36, 0x09, 0x8f, 0xf3, 0x4e, 0x70, 0xcd, 0x70, 0x02, 0x87, 0x20, 0x88, + 0x55, 0x0e, 0x65, 0x10, 0x2e, 0x70, 0x01, 0x80, 0x32, 0x40, 0xc5, 0x48, + 0x08, 0x8d, 0x29, 0x08, 0x05, 0x20, 0x03, 0x85, 0x30, 0x20, 0x40, 0x04, + 0x28, 0x80, 0x47, 0x80, 0x61, 0x91, 0x54, 0x73, 0x46, 0x23, 0x82, 0x01, + 0x82, 0xba, 0x41, 0xb1, 0x03, 0xf4, 0x6a, 0x09, 0x8f, 0xf4, 0x26, 0x74, + 0x06, 0x71, 0xee, 0xf1, 0x09, 0x8d, 0x0e, 0xe8, 0x2e, 0x70, 0x32, 0x40, + 0x04, 0x85, 0xa2, 0x0c, 0xef, 0xff, 0x30, 0x20, 0x40, 0x04, 0x09, 0x8d, + 0x06, 0x71, 0xf5, 0x08, 0x24, 0xa0, 0x26, 0x74, 0xc5, 0x71, 0xd6, 0xf1, + 0xad, 0x70, 0x18, 0x8f, 0x17, 0x0d, 0x05, 0x10, 0x03, 0x87, 0x30, 0x20, + 0x80, 0x04, 0x04, 0xe8, 0x7a, 0x0c, 0xcf, 0xff, 0x46, 0x74, 0xa5, 0x71, + 0xf5, 0xf1, 0xca, 0x0c, 0xcf, 0xfe, 0xcc, 0xc6, 0x15, 0x09, 0xf0, 0x00, + 0x0a, 0x80, 0x1b, 0x09, 0x91, 0x00, 0x24, 0x18, 0x80, 0x0f, 0x13, 0x00, + 0xc8, 0x52, 0xe0, 0x7e, 0x24, 0x18, 0x80, 0x0f, 0x13, 0x00, 0x90, 0x52, + 0xe0, 0x7e, 0x24, 0x18, 0x80, 0x0f, 0x13, 0x00, 0x00, 0x53, 0xe0, 0x7e, + 0xf2, 0xc3, 0xa6, 0xc1, 0x0a, 0x20, 0x00, 0x21, 0x70, 0x45, 0x50, 0x44, + 0x30, 0x43, 0x08, 0x46, 0x2e, 0x70, 0x54, 0x70, 0x04, 0x1c, 0x01, 0x30, + 0x06, 0xf2, 0x76, 0x70, 0x8a, 0x21, 0xbc, 0x20, 0x02, 0xf2, 0xb6, 0x70, + 0x80, 0x02, 0x21, 0x00, 0x4c, 0x20, 0x00, 0xa2, 0x78, 0x02, 0x05, 0x00, + 0x0a, 0x86, 0x8a, 0x21, 0xfc, 0x20, 0x0a, 0x80, 0x04, 0x77, 0x14, 0x71, + 0x68, 0x02, 0x2d, 0x00, 0x2c, 0x70, 0xeb, 0x86, 0xa2, 0x40, 0xa2, 0x0d, + 0xaf, 0xf4, 0x02, 0x42, 0x40, 0x24, 0x05, 0x32, 0x40, 0x24, 0x06, 0x34, + 0x40, 0x24, 0x87, 0x33, 0xc1, 0x40, 0x62, 0x41, 0x82, 0x42, 0xa2, 0x43, + 0xee, 0x0a, 0x6f, 0xf4, 0x0a, 0x24, 0x00, 0x04, 0x14, 0x70, 0x3c, 0x02, + 0x22, 0x00, 0x10, 0x41, 0x02, 0xc5, 0x4e, 0x70, 0x52, 0x41, 0x38, 0xed, + 0x6d, 0x09, 0x11, 0x20, 0x04, 0xc0, 0x67, 0x08, 0x25, 0x05, 0x84, 0xc2, + 0x40, 0x24, 0xc5, 0x33, 0x40, 0x24, 0xc6, 0x35, 0x40, 0x24, 0x07, 0x31, + 0x62, 0x40, 0x82, 0x41, 0xa2, 0x43, 0x9e, 0x0b, 0x2f, 0xf4, 0x0a, 0x24, + 0x00, 0x04, 0x10, 0x41, 0xa2, 0xe8, 0x0f, 0x14, 0x81, 0x30, 0x8c, 0x21, + 0x83, 0x8f, 0x08, 0xf4, 0x01, 0xc2, 0xc1, 0x40, 0xa2, 0x0e, 0x2f, 0xf4, + 0xa2, 0x41, 0x0a, 0xf0, 0xe2, 0x0e, 0x6f, 0xf3, 0x02, 0x86, 0x10, 0xe8, + 0x6a, 0x80, 0x01, 0xc2, 0x60, 0x7b, 0xa2, 0x41, 0x2e, 0x70, 0x02, 0xc0, + 0x2c, 0x70, 0x02, 0x42, 0xa9, 0x68, 0xa2, 0x40, 0x12, 0x0d, 0xaf, 0xf4, + 0x42, 0xc5, 0xcf, 0xf1, 0x8a, 0x21, 0xbc, 0x20, 0xf5, 0xf1, 0x2e, 0x70, + 0x4c, 0x87, 0x0a, 0x87, 0x2a, 0x86, 0x00, 0x30, 0x80, 0x00, 0x48, 0x30, + 0xc0, 0x02, 0x0d, 0xa1, 0x0b, 0x87, 0x00, 0x32, 0x00, 0x00, 0x48, 0x30, + 0xc0, 0x02, 0x15, 0x09, 0x31, 0x20, 0x0e, 0xa1, 0x0e, 0x14, 0x80, 0x30, + 0x09, 0x08, 0x15, 0x01, 0x28, 0x19, 0x81, 0x00, 0x70, 0x17, 0x80, 0x10, + 0x42, 0x20, 0x3c, 0x80, 0x11, 0xf2, 0x44, 0x86, 0xa8, 0x20, 0xc0, 0x03, + 0xf0, 0x22, 0x81, 0x04, 0x14, 0x27, 0x80, 0x14, 0xfa, 0x10, 0x03, 0x07, + 0x80, 0x20, 0x0a, 0x0d, 0x28, 0x81, 0x46, 0x71, 0x63, 0xb1, 0x00, 0x90, + 0x04, 0xb1, 0x58, 0x8e, 0x19, 0xea, 0x63, 0x86, 0x2c, 0x70, 0x20, 0x4b, + 0x8d, 0x71, 0x00, 0x10, 0x0b, 0x01, 0xa2, 0x88, 0x00, 0x2c, 0xcc, 0x12, + 0x42, 0x25, 0x3c, 0x90, 0x00, 0x1c, 0x04, 0x33, 0x08, 0xf2, 0x02, 0x80, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x0d, 0x04, 0xa8, 0x85, 0x85, 0xb5, + 0x24, 0x71, 0xdb, 0x09, 0x84, 0x80, 0x4e, 0x70, 0x52, 0x40, 0x02, 0x86, + 0x20, 0x88, 0x77, 0x08, 0x45, 0x20, 0x01, 0x80, 0xf0, 0x20, 0x0d, 0x04, + 0x48, 0x85, 0x08, 0xea, 0x80, 0xc1, 0x60, 0x7a, 0xa1, 0x40, 0x00, 0x14, + 0x03, 0x31, 0x19, 0xf0, 0x08, 0x8d, 0x6c, 0x70, 0x00, 0x1c, 0x84, 0x34, + 0x42, 0x20, 0x3c, 0x80, 0x11, 0xf2, 0x43, 0x85, 0x4a, 0x23, 0x00, 0x00, + 0xa8, 0x20, 0x40, 0x03, 0x04, 0x12, 0x00, 0x04, 0x08, 0x80, 0x22, 0x88, + 0x0d, 0x09, 0x9f, 0x01, 0x05, 0x90, 0x05, 0x7b, 0x00, 0x1c, 0xc4, 0x30, + 0xe0, 0x78, 0x09, 0x8d, 0x08, 0x43, 0x13, 0xe8, 0x84, 0x85, 0x2c, 0x70, + 0x20, 0x4c, 0x42, 0x88, 0x42, 0x22, 0x3c, 0x80, 0x08, 0xf2, 0x02, 0x80, + 0xa8, 0x20, 0x80, 0x01, 0x04, 0x10, 0x02, 0x04, 0x48, 0x82, 0x65, 0xb2, + 0x24, 0x71, 0xe9, 0x09, 0xc4, 0x82, 0x06, 0x71, 0xc5, 0xf1, 0x8a, 0x20, + 0x4e, 0x00, 0x1d, 0x67, 0x7a, 0x0b, 0x20, 0x00, 0xc1, 0x40, 0x20, 0x8d, + 0x10, 0x42, 0xe2, 0x0d, 0xef, 0xff, 0xc1, 0x40, 0x01, 0x8d, 0x05, 0xe8, + 0xa6, 0x08, 0x20, 0x00, 0xc1, 0x40, 0x80, 0x27, 0xce, 0x10, 0x00, 0x8f, + 0x8f, 0x08, 0x30, 0x00, 0x0e, 0x70, 0xed, 0x70, 0x19, 0x8e, 0x87, 0x0f, + 0x05, 0x10, 0x04, 0x86, 0x30, 0x20, 0x0d, 0x04, 0x8a, 0x20, 0xbe, 0x0a, + 0x2c, 0x95, 0x38, 0x60, 0x1b, 0x08, 0x74, 0x01, 0x15, 0xda, 0x20, 0x40, + 0x80, 0x20, 0x3d, 0x00, 0x23, 0x08, 0x75, 0x02, 0x8a, 0x22, 0x45, 0x00, + 0x0b, 0x0a, 0x0f, 0x00, 0x0b, 0xf0, 0xef, 0x0a, 0x0e, 0x80, 0x8a, 0x20, + 0x84, 0x00, 0x40, 0xc0, 0x80, 0xc1, 0x3e, 0x0b, 0x6f, 0xf4, 0xa1, 0x40, + 0x2c, 0x95, 0x23, 0x09, 0xd5, 0x04, 0xc3, 0x40, 0x05, 0x00, 0x40, 0x51, + 0x17, 0x08, 0x4e, 0x00, 0xc3, 0x40, 0x20, 0xbc, 0x12, 0xac, 0x40, 0xc0, + 0x80, 0xc1, 0x1e, 0x0b, 0x6f, 0xf4, 0xa1, 0x40, 0x2c, 0x95, 0x42, 0x21, + 0x00, 0x0e, 0x1d, 0x08, 0x75, 0x01, 0x15, 0xd9, 0x15, 0x09, 0x2e, 0x00, + 0x80, 0xc1, 0xc3, 0x40, 0x1c, 0xc1, 0x0a, 0xe8, 0x40, 0xc0, 0xfe, 0x0a, + 0x6f, 0xf4, 0xa1, 0x40, 0x06, 0x74, 0xe5, 0x71, 0xbe, 0xf1, 0x36, 0x70, + 0xca, 0x21, 0x81, 0x24, 0x22, 0x40, 0xd2, 0xc7, 0xe6, 0xc2, 0x18, 0x10, + 0x84, 0x00, 0xeb, 0x80, 0xac, 0x70, 0x6c, 0x70, 0x4b, 0x0b, 0x25, 0x01, + 0x6d, 0x70, 0x23, 0x80, 0x8d, 0x70, 0x65, 0x49, 0x14, 0x27, 0xc1, 0x10, + 0x52, 0x11, 0x09, 0x01, 0x48, 0x11, 0x0e, 0x01, 0x02, 0x15, 0x88, 0x10, + 0x11, 0x74, 0xc0, 0x23, 0x66, 0x00, 0x70, 0xf7, 0x22, 0x85, 0x30, 0x21, + 0xc1, 0x02, 0x28, 0x81, 0x43, 0x91, 0x05, 0xea, 0x08, 0x19, 0x44, 0x02, + 0xc3, 0xb1, 0xc3, 0x42, 0x00, 0x00, 0xff, 0xff, 0x09, 0x0e, 0x81, 0x10, + 0x44, 0xb1, 0x43, 0xb1, 0x65, 0x74, 0x85, 0x71, 0xea, 0xf1, 0x22, 0x80, + 0x0a, 0x26, 0x40, 0x30, 0x00, 0x11, 0x9f, 0x00, 0x0c, 0x25, 0xc0, 0x87, + 0x5a, 0x02, 0x26, 0x00, 0xec, 0x70, 0x04, 0x16, 0x00, 0x30, 0xf0, 0x20, + 0x4c, 0x01, 0x08, 0x8c, 0x00, 0x46, 0x10, 0xe8, 0x23, 0x84, 0x0a, 0x24, + 0x80, 0x71, 0xec, 0x70, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x11, 0x00, 0x04, + 0x08, 0x80, 0x02, 0x88, 0x24, 0xb8, 0xc0, 0xb8, 0x00, 0x27, 0x07, 0x00, + 0xa9, 0x8c, 0xcd, 0x70, 0xc9, 0x43, 0x6c, 0x70, 0x0c, 0x70, 0x31, 0x0b, + 0x65, 0x03, 0x0d, 0x71, 0x24, 0x84, 0x61, 0x49, 0x42, 0x89, 0x42, 0x22, + 0x3c, 0x80, 0x0e, 0xf2, 0x22, 0x81, 0x00, 0x42, 0xa8, 0x20, 0x80, 0x02, + 0x04, 0x11, 0x00, 0x04, 0x08, 0x80, 0x05, 0x90, 0x10, 0x72, 0xc5, 0x23, + 0x02, 0x10, 0x00, 0x42, 0x64, 0x71, 0xeb, 0xf1, 0x4e, 0x87, 0x0d, 0x87, + 0x2f, 0x87, 0x2f, 0x23, 0xc8, 0x02, 0x00, 0x28, 0x8b, 0x10, 0x0f, 0x23, + 0x02, 0x10, 0x0f, 0x22, 0x4d, 0x00, 0x7d, 0x0d, 0xe1, 0x10, 0x00, 0x28, + 0x09, 0x10, 0x42, 0x26, 0x3c, 0x80, 0xe6, 0xf2, 0x0c, 0x14, 0x0d, 0x10, + 0xa8, 0x20, 0xc0, 0x0c, 0xc0, 0x4d, 0x2f, 0x21, 0xc7, 0x01, 0x4f, 0x09, + 0xb5, 0x00, 0x08, 0x80, 0x0a, 0x10, 0x08, 0x01, 0x40, 0x27, 0x06, 0x1d, + 0x8d, 0x70, 0x52, 0xdb, 0x49, 0x0c, 0x25, 0x11, 0x2c, 0x71, 0x04, 0x16, + 0x02, 0x04, 0x58, 0x79, 0x04, 0x21, 0x02, 0x82, 0x12, 0xf2, 0x23, 0x90, + 0x31, 0x72, 0xcc, 0x22, 0xc2, 0x82, 0x09, 0xf4, 0x0c, 0xe9, 0x24, 0x90, + 0x0a, 0xe9, 0x71, 0x67, 0x24, 0xb0, 0x23, 0xb0, 0x06, 0xf0, 0x06, 0xe9, + 0x24, 0x90, 0x04, 0xe9, 0x71, 0x67, 0x24, 0xb0, 0x64, 0x72, 0x85, 0x71, + 0xe4, 0xf1, 0x23, 0x90, 0x06, 0xe9, 0x24, 0x90, 0x04, 0xe9, 0x52, 0x17, + 0x01, 0x11, 0x24, 0xb0, 0xc5, 0x71, 0xb0, 0xf0, 0x00, 0x28, 0x48, 0x10, + 0x05, 0x20, 0x40, 0x12, 0x63, 0x08, 0xe1, 0x00, 0x42, 0x26, 0x3c, 0x80, + 0xa6, 0xf2, 0xa3, 0x84, 0xa8, 0x20, 0x80, 0x0a, 0x2f, 0x20, 0xc7, 0x01, + 0x4b, 0x08, 0xb5, 0x00, 0x40, 0x27, 0x08, 0x1d, 0xc0, 0x4d, 0x8d, 0x70, + 0x52, 0xda, 0x08, 0x80, 0x0a, 0x10, 0x0b, 0x01, 0x37, 0x0c, 0x25, 0x11, + 0x2c, 0x71, 0x04, 0x10, 0x03, 0x14, 0x78, 0x79, 0x04, 0x21, 0xc3, 0x82, + 0x10, 0xf2, 0x17, 0x0b, 0x61, 0x02, 0x23, 0x90, 0x0c, 0xe9, 0x24, 0x90, + 0x0a, 0xe9, 0x51, 0x67, 0x24, 0xb0, 0x23, 0xb0, 0x06, 0xf0, 0x06, 0xe9, + 0x24, 0x90, 0x04, 0xe9, 0x51, 0x67, 0x24, 0xb0, 0x44, 0x72, 0x85, 0x71, + 0xe6, 0xf1, 0xc5, 0x71, 0x7a, 0xf0, 0x5d, 0x0a, 0xe1, 0x00, 0x42, 0x26, + 0x3c, 0x80, 0x76, 0xf2, 0x0c, 0x14, 0x0d, 0x10, 0xa8, 0x20, 0x40, 0x09, + 0x2f, 0x20, 0xc7, 0x01, 0x41, 0x08, 0xb5, 0x00, 0x40, 0x27, 0x09, 0x1d, + 0xc0, 0x4d, 0x8d, 0x70, 0x52, 0xda, 0x28, 0x80, 0x65, 0x91, 0x31, 0x0c, + 0x25, 0x11, 0x0c, 0x71, 0x04, 0x11, 0x08, 0x14, 0x00, 0x28, 0x00, 0x02, + 0x04, 0x20, 0xc0, 0x80, 0x0b, 0xf2, 0x17, 0x08, 0xc1, 0x02, 0x03, 0x91, + 0x07, 0xe8, 0x04, 0x91, 0x05, 0xe8, 0x50, 0x67, 0x22, 0xb8, 0x04, 0xb1, + 0x03, 0xb1, 0x44, 0x72, 0x85, 0x71, 0xeb, 0xf1, 0xc5, 0x71, 0x4e, 0xf0, + 0x05, 0x20, 0xc0, 0x12, 0x67, 0x08, 0xe1, 0x00, 0x42, 0x26, 0x3c, 0x80, + 0x46, 0xf2, 0xc3, 0x84, 0x4a, 0x25, 0x00, 0x10, 0xa8, 0x20, 0x80, 0x0a, + 0x2f, 0x20, 0xc7, 0x01, 0x4b, 0x08, 0xb5, 0x00, 0x40, 0x27, 0x09, 0x1d, + 0xa0, 0x4e, 0x52, 0xda, 0x8d, 0x70, 0x08, 0x80, 0x0a, 0x10, 0x0b, 0x01, + 0x37, 0x0c, 0x25, 0x11, 0x2c, 0x71, 0x04, 0x11, 0x03, 0x14, 0x78, 0x79, + 0x04, 0x21, 0xc3, 0x82, 0x10, 0xf2, 0x15, 0x0b, 0x21, 0x02, 0x23, 0x90, + 0x0c, 0xe9, 0x24, 0x90, 0x0a, 0xe9, 0x51, 0x67, 0x24, 0xb0, 0x08, 0xf0, + 0x06, 0xe9, 0x24, 0x90, 0x04, 0xe9, 0x51, 0x67, 0x24, 0xb0, 0x23, 0xb0, + 0x44, 0x72, 0x85, 0x71, 0xe6, 0xf1, 0xa5, 0x71, 0x18, 0xf0, 0x31, 0x0e, + 0x10, 0x00, 0x2d, 0x08, 0xe1, 0x10, 0x0a, 0x24, 0x80, 0x71, 0x23, 0x84, + 0xa8, 0x20, 0x00, 0x04, 0x04, 0x11, 0x00, 0x04, 0x08, 0x80, 0x45, 0x90, + 0x13, 0x0b, 0x81, 0x00, 0x43, 0x90, 0x07, 0xea, 0x44, 0x90, 0x05, 0xea, + 0x56, 0x17, 0x02, 0x11, 0x44, 0xb0, 0xe0, 0x78, 0xa9, 0x05, 0xef, 0xff, + 0xa4, 0x71, 0xc6, 0xc6, 0xec, 0xc2, 0x18, 0x10, 0x89, 0x00, 0x2c, 0x10, + 0x06, 0x00, 0xed, 0x70, 0x08, 0x46, 0xe9, 0x43, 0xf1, 0x40, 0x2f, 0x20, + 0xc8, 0x02, 0x47, 0x08, 0x65, 0x02, 0x8d, 0x70, 0x23, 0x86, 0x02, 0x49, + 0x14, 0x26, 0x00, 0x00, 0x48, 0x10, 0x03, 0x01, 0x02, 0x12, 0x88, 0x00, + 0x90, 0x78, 0x2b, 0x08, 0x05, 0x02, 0x22, 0x82, 0x00, 0x49, 0x08, 0x80, + 0x23, 0x90, 0x0d, 0x09, 0xc5, 0x00, 0x4a, 0x20, 0xc0, 0x23, 0x63, 0xb0, + 0xc3, 0x41, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x0b, 0x41, 0x00, 0x24, 0xb0, + 0x23, 0xb0, 0x85, 0x71, 0xec, 0xf1, 0x65, 0x71, 0xdd, 0xf1, 0xd3, 0x42, + 0x00, 0x00, 0xff, 0xff, 0x02, 0x86, 0x20, 0x88, 0xb5, 0x0f, 0x65, 0x10, + 0x2e, 0x70, 0x01, 0x80, 0x42, 0x42, 0xe5, 0x48, 0x28, 0x8d, 0x2f, 0x20, + 0x48, 0x04, 0x1b, 0x08, 0x45, 0x00, 0x23, 0x85, 0x00, 0x49, 0x08, 0x80, + 0x23, 0x90, 0xee, 0x08, 0x6f, 0xf3, 0x50, 0x78, 0x00, 0x42, 0x26, 0x71, + 0xf2, 0xf1, 0x09, 0x6a, 0x10, 0x78, 0x4f, 0x08, 0x85, 0x0f, 0x00, 0x00, + 0xef, 0xff, 0x09, 0x15, 0x86, 0x10, 0x6c, 0x70, 0x2f, 0x23, 0x88, 0x10, + 0x71, 0x0b, 0xa5, 0x01, 0x0d, 0x70, 0x04, 0x85, 0x61, 0x48, 0x02, 0x11, + 0x89, 0x00, 0x2f, 0x20, 0x08, 0x02, 0x31, 0x70, 0xc0, 0x23, 0x66, 0x00, + 0x74, 0xf7, 0x82, 0x81, 0x00, 0x4c, 0x08, 0x80, 0x83, 0x90, 0x0b, 0xec, + 0x13, 0x0c, 0xc5, 0x12, 0x84, 0x90, 0x4a, 0x20, 0xc0, 0x23, 0x0b, 0x0c, + 0xe5, 0x12, 0x43, 0xb0, 0x44, 0xb0, 0x05, 0x71, 0xeb, 0xf1, 0x50, 0x78, + 0x35, 0x08, 0xa1, 0x04, 0x2c, 0x70, 0x09, 0x15, 0x88, 0x10, 0x2d, 0x09, + 0x25, 0x02, 0x8d, 0x70, 0x04, 0x85, 0x22, 0x48, 0x02, 0x12, 0x8b, 0x00, + 0x90, 0x78, 0x71, 0x70, 0xc0, 0x21, 0x66, 0x00, 0x75, 0xf7, 0x62, 0x82, + 0x85, 0x71, 0x00, 0x4b, 0x08, 0x80, 0x08, 0x18, 0xc5, 0x0f, 0x06, 0x18, + 0xc5, 0x0f, 0xf4, 0xf1, 0xe5, 0x71, 0xa6, 0xf1, 0x02, 0x40, 0xcc, 0xc6, + 0x08, 0x80, 0x84, 0x21, 0x41, 0x0e, 0x85, 0x21, 0x02, 0x01, 0x0a, 0x18, + 0x05, 0x00, 0x00, 0x18, 0xc5, 0x0f, 0xe0, 0x7f, 0x21, 0xb0, 0xe0, 0x78, + 0x08, 0x80, 0x21, 0x90, 0x00, 0x18, 0xc5, 0x0f, 0x6c, 0x21, 0x81, 0x00, + 0x82, 0xb9, 0xe0, 0x7f, 0x21, 0xb0, 0xe0, 0x78, 0x0f, 0x08, 0x34, 0x04, + 0x2c, 0x71, 0xc3, 0x41, 0x00, 0x00, 0xff, 0xff, 0x02, 0xf0, 0x18, 0x79, + 0xe0, 0x7f, 0x30, 0x78, 0x40, 0x81, 0x48, 0x60, 0x44, 0x71, 0xe0, 0x7f, + 0x40, 0xa1, 0xe0, 0x78, 0xec, 0xc2, 0xcb, 0x45, 0xf0, 0x00, 0x34, 0x00, + 0x93, 0xda, 0x2c, 0x70, 0x94, 0xd8, 0x57, 0xad, 0x00, 0x1e, 0x42, 0x70, + 0xa0, 0x00, 0xb4, 0x41, 0x17, 0xad, 0xa2, 0x5a, 0x34, 0xe8, 0xa3, 0x5a, + 0x95, 0xd8, 0x96, 0x0a, 0xaf, 0xf7, 0x17, 0xad, 0x96, 0xd8, 0x17, 0xad, + 0x34, 0x58, 0x10, 0x42, 0x3e, 0x58, 0x10, 0x41, 0x2e, 0x58, 0x10, 0x40, + 0x2f, 0x58, 0x08, 0x47, 0x02, 0x41, 0x22, 0x42, 0x00, 0x43, 0x42, 0x40, + 0xa4, 0x5a, 0x08, 0x46, 0x03, 0xe8, 0xc1, 0x40, 0x67, 0x58, 0x9b, 0xd9, + 0x9c, 0xd8, 0x37, 0xad, 0x42, 0x0a, 0xaf, 0xf7, 0x17, 0xad, 0x9d, 0xd8, + 0xf6, 0x0d, 0x6f, 0xff, 0x17, 0xad, 0x9e, 0xd8, 0x72, 0x0e, 0x6f, 0xff, + 0x17, 0xad, 0x9f, 0xd8, 0x1e, 0x0e, 0x6f, 0xff, 0x17, 0xad, 0xa0, 0xd8, + 0xd4, 0xad, 0x17, 0xad, 0x42, 0x40, 0x02, 0x41, 0x22, 0x42, 0xe1, 0x43, + 0xb1, 0x5a, 0x06, 0xf0, 0x14, 0x8d, 0x84, 0xe8, 0x20, 0xd8, 0x14, 0xad, + 0xa2, 0xd8, 0x4a, 0x0a, 0xaf, 0xf7, 0x17, 0xad, 0xa3, 0xd8, 0x17, 0xad, + 0x40, 0x58, 0xe0, 0x78, 0xc3, 0x40, 0xa0, 0x00, 0x04, 0x87, 0x01, 0x18, + 0x43, 0x00, 0x00, 0x16, 0x81, 0x70, 0xf0, 0x00, 0x06, 0x01, 0xe0, 0x7f, + 0x20, 0xa8, 0xe0, 0x78, 0xc3, 0x42, 0xa0, 0x00, 0x04, 0x87, 0x21, 0x8a, + 0x00, 0x43, 0x0c, 0x70, 0x34, 0x70, 0xe0, 0x7c, 0x40, 0x8a, 0x7f, 0xd9, + 0x44, 0x79, 0x00, 0x21, 0xc1, 0x80, 0x10, 0x00, 0x24, 0x00, 0x8c, 0x21, + 0x02, 0x80, 0x20, 0x40, 0x82, 0xf6, 0x7f, 0xd8, 0x84, 0x22, 0x02, 0x00, + 0x05, 0x7a, 0x00, 0x1e, 0x82, 0x70, 0xf0, 0x00, 0x06, 0x01, 0xe0, 0x7f, + 0x0c, 0x71, 0xe0, 0x78, 0xe0, 0x7e, 0xe0, 0x78, 0xea, 0xc3, 0xa7, 0xc1, + 0x08, 0x45, 0x01, 0x80, 0x82, 0x85, 0xe3, 0x85, 0xc0, 0x85, 0x00, 0x34, + 0x08, 0x10, 0x00, 0x30, 0x06, 0x00, 0x00, 0x34, 0x09, 0x13, 0x30, 0x40, + 0x00, 0x36, 0xcb, 0x13, 0x00, 0x37, 0x04, 0x10, 0x00, 0x36, 0x87, 0x13, + 0x00, 0x36, 0x00, 0x13, 0x68, 0x46, 0x01, 0x33, 0x0c, 0x12, 0x02, 0x30, + 0x00, 0x01, 0x02, 0x31, 0x8b, 0x11, 0x01, 0x34, 0x0c, 0x13, 0x01, 0x30, + 0x03, 0x00, 0x41, 0xc4, 0x02, 0x33, 0xc1, 0x11, 0x40, 0xc3, 0x00, 0x37, + 0xc0, 0x13, 0x01, 0x30, 0x40, 0x00, 0xa7, 0x0a, 0x70, 0x00, 0x42, 0xc0, + 0x21, 0x0a, 0x30, 0x01, 0x83, 0xc1, 0x1b, 0x0a, 0xb1, 0x00, 0x44, 0x6e, + 0x40, 0x26, 0x03, 0x12, 0x80, 0xc1, 0x40, 0x26, 0x05, 0x13, 0xa1, 0x40, + 0xa6, 0x0c, 0x6f, 0xfc, 0xc1, 0x44, 0xca, 0xc7, 0xda, 0x09, 0xef, 0xef, + 0xa1, 0x40, 0x43, 0x85, 0x22, 0x85, 0xe1, 0x85, 0x00, 0x85, 0x05, 0xc4, + 0x03, 0xc3, 0x00, 0x31, 0x82, 0x00, 0x7f, 0xdd, 0x00, 0x30, 0xc1, 0x03, + 0x17, 0xbd, 0x02, 0x33, 0x00, 0x03, 0x02, 0x31, 0x81, 0x00, 0x01, 0x30, + 0x02, 0x00, 0x01, 0x31, 0x40, 0x00, 0x02, 0x35, 0x81, 0x10, 0xb2, 0x0e, + 0xef, 0xee, 0x02, 0x42, 0x01, 0xc2, 0x08, 0x47, 0x00, 0xa6, 0x00, 0x32, + 0x81, 0x00, 0x52, 0x22, 0xc0, 0x07, 0x02, 0x35, 0x41, 0x10, 0x02, 0x42, + 0x2f, 0x31, 0x40, 0x00, 0x92, 0x0e, 0xef, 0xee, 0x01, 0x31, 0x41, 0x03, + 0x04, 0xc2, 0x03, 0xc1, 0x01, 0x30, 0x03, 0x00, 0x00, 0xc4, 0x02, 0x31, + 0x80, 0x00, 0x02, 0x42, 0x01, 0x30, 0x01, 0x00, 0x52, 0x24, 0xc0, 0x17, + 0x02, 0x35, 0x41, 0x10, 0x6e, 0x0e, 0xef, 0xee, 0x61, 0xa6, 0xe3, 0xa6, + 0x5c, 0xf0, 0x80, 0xc0, 0xbe, 0x0b, 0xaf, 0xf4, 0x83, 0xc1, 0x03, 0xc0, + 0x04, 0x30, 0x80, 0x8f, 0x7c, 0x3f, 0xae, 0x5d, 0xd3, 0xf6, 0x05, 0xc1, + 0x2e, 0x0a, 0x2f, 0xf3, 0x01, 0x30, 0x40, 0x00, 0x01, 0xc1, 0x02, 0xc2, + 0x6c, 0x70, 0x00, 0x30, 0x40, 0x00, 0x04, 0x32, 0xc0, 0x80, 0x52, 0x20, + 0xc0, 0x07, 0xca, 0xf6, 0x7f, 0xd9, 0x17, 0xb9, 0x09, 0xf0, 0x01, 0xc0, + 0x02, 0xc1, 0x52, 0x20, 0xc0, 0x07, 0x05, 0xf0, 0xc3, 0x41, 0x80, 0xbf, + 0x00, 0x00, 0x1e, 0x0e, 0xef, 0xee, 0x02, 0x42, 0x08, 0x47, 0x05, 0xc1, + 0x04, 0xc0, 0xf2, 0x09, 0x2f, 0xf3, 0x01, 0x30, 0x40, 0x00, 0x02, 0xc1, + 0x10, 0x41, 0x04, 0x31, 0x80, 0x8f, 0x80, 0xbf, 0x00, 0x00, 0xcc, 0xf6, + 0x04, 0x31, 0x80, 0x8f, 0x35, 0xbf, 0xf3, 0x04, 0x46, 0xf7, 0x21, 0x85, + 0x00, 0x85, 0x52, 0x21, 0xc1, 0x07, 0x04, 0xf0, 0x23, 0x85, 0x02, 0x85, + 0xe2, 0x0d, 0xef, 0xee, 0x02, 0x42, 0x00, 0x30, 0x8d, 0x0f, 0x00, 0xc0, + 0x00, 0x00, 0x0c, 0x70, 0x04, 0x35, 0x00, 0x90, 0x45, 0xf7, 0x01, 0x35, + 0x8d, 0x1f, 0xc9, 0x40, 0xdb, 0x0f, 0x00, 0xc0, 0x7f, 0xd9, 0x17, 0xb9, + 0x00, 0x31, 0x00, 0x20, 0x02, 0x42, 0xe1, 0xa6, 0xb6, 0x0d, 0xef, 0xee, + 0xa0, 0xa6, 0xa3, 0xa6, 0x02, 0xa6, 0xca, 0xc7, 0xe2, 0xc2, 0x28, 0x45, + 0x20, 0x81, 0x40, 0x43, 0x4c, 0x76, 0x19, 0x61, 0xda, 0x0b, 0x6f, 0xf4, + 0x60, 0x40, 0x00, 0x85, 0x04, 0x76, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, + 0xe6, 0xc3, 0xa2, 0xc1, 0x68, 0x45, 0x60, 0x83, 0x28, 0x46, 0x64, 0x76, + 0x2b, 0x0a, 0xe4, 0x00, 0x00, 0x41, 0x80, 0xc0, 0x4c, 0x76, 0xfe, 0x0d, + 0x6f, 0xe6, 0x80, 0xc7, 0x4a, 0x24, 0x80, 0x71, 0xa8, 0x20, 0x00, 0x02, + 0x00, 0x85, 0x01, 0x17, 0x81, 0x14, 0xd8, 0x60, 0xc5, 0x71, 0x20, 0xa8, + 0x00, 0x85, 0x04, 0x76, 0x00, 0xa5, 0xc6, 0xc7, 0xe2, 0xc3, 0x08, 0x45, + 0x01, 0x80, 0x84, 0x20, 0x03, 0x0c, 0x15, 0x08, 0x31, 0x04, 0xa1, 0xc1, + 0x0e, 0x8d, 0x00, 0x15, 0x04, 0x10, 0x1d, 0x78, 0x9d, 0x5a, 0xc2, 0xc7, + 0xff, 0xd8, 0x40, 0xc0, 0xc3, 0x44, 0x13, 0x00, 0x24, 0x1a, 0x40, 0x24, + 0x05, 0x30, 0xa1, 0x40, 0xaa, 0x5a, 0xa1, 0x40, 0x17, 0x58, 0x00, 0xc0, + 0xc2, 0xc7, 0xe0, 0x78, 0xea, 0xc2, 0x08, 0x46, 0x48, 0x30, 0x00, 0x00, + 0x48, 0x47, 0x30, 0x40, 0xc3, 0x41, 0x13, 0x00, 0x10, 0x4d, 0x60, 0x42, + 0x0a, 0x21, 0x00, 0x21, 0x68, 0x45, 0x83, 0x58, 0x14, 0x77, 0x12, 0xf2, + 0x9f, 0x25, 0x02, 0x13, 0xc3, 0x41, 0xa0, 0x00, 0xcc, 0x49, 0xb9, 0x61, + 0x00, 0x25, 0x8d, 0x1f, 0xa0, 0x00, 0x25, 0x4a, 0xe5, 0xa1, 0x10, 0x19, + 0x00, 0x04, 0xca, 0xa1, 0x00, 0xad, 0xca, 0xc6, 0xf0, 0x26, 0x40, 0x73, + 0x13, 0x00, 0x40, 0x90, 0x09, 0x09, 0x10, 0x20, 0x8d, 0x58, 0xca, 0xc6, + 0x8b, 0x58, 0xca, 0xc6, 0x00, 0x41, 0x14, 0x70, 0x0c, 0x70, 0xe0, 0x7c, + 0xab, 0x11, 0x80, 0x00, 0x14, 0x70, 0x0c, 0x71, 0xe0, 0x7d, 0xac, 0x11, + 0x81, 0x00, 0x34, 0x70, 0xe0, 0x7d, 0xe0, 0x7f, 0x0c, 0x70, 0xe0, 0x78, + 0xec, 0xc3, 0xa1, 0xc1, 0x34, 0x58, 0x10, 0x40, 0x3e, 0x58, 0x08, 0x47, + 0x2e, 0x58, 0x08, 0x46, 0x2f, 0x58, 0x08, 0x45, 0x10, 0xd8, 0x8d, 0x58, + 0x8a, 0x21, 0x82, 0x2c, 0xff, 0xd9, 0x0c, 0x70, 0x10, 0xb9, 0x80, 0xc2, + 0x56, 0x0e, 0xaf, 0xf6, 0x6c, 0x77, 0x00, 0xc0, 0x78, 0xe8, 0x4a, 0x22, + 0x00, 0x24, 0x00, 0x1e, 0x42, 0x74, 0xf0, 0x00, 0x4b, 0x00, 0x03, 0xf0, + 0x00, 0xc0, 0x11, 0x20, 0x80, 0x84, 0x3c, 0xf2, 0x2f, 0x20, 0x87, 0x04, + 0x1d, 0x08, 0x10, 0x04, 0x4b, 0x08, 0xb0, 0x04, 0x91, 0xe0, 0x34, 0xf4, + 0x02, 0x40, 0xc1, 0x41, 0xe1, 0x42, 0xa1, 0x43, 0x99, 0x5a, 0x4c, 0x20, + 0xc0, 0x88, 0x2c, 0xf4, 0x00, 0x16, 0x00, 0x70, 0xa0, 0x00, 0xe0, 0x86, + 0x2c, 0x70, 0x4c, 0x77, 0x5a, 0x0f, 0x6f, 0xf6, 0x6c, 0x70, 0x78, 0xe8, + 0x02, 0x40, 0xc1, 0x41, 0xe1, 0x42, 0xa1, 0x43, 0x98, 0x5a, 0x00, 0x16, + 0x00, 0x70, 0xa0, 0x00, 0xe0, 0x86, 0x2c, 0x70, 0x4c, 0x70, 0x9a, 0x08, + 0xaf, 0xf6, 0x6c, 0x70, 0x12, 0xf0, 0x2f, 0x27, 0xff, 0x00, 0x6f, 0x23, + 0x3f, 0x00, 0xc3, 0x40, 0xa0, 0x00, 0x74, 0x49, 0x26, 0x80, 0x47, 0x80, + 0x18, 0x18, 0x01, 0x00, 0x1c, 0x18, 0x01, 0x00, 0x2f, 0x26, 0xff, 0x00, + 0xff, 0xd8, 0x45, 0x58, 0x46, 0x71, 0x4c, 0x22, 0xc0, 0xa4, 0x80, 0x07, + 0xce, 0xff, 0xae, 0xf1, 0x7f, 0xdc, 0x17, 0xbc, 0xc3, 0x43, 0x80, 0x3f, + 0x50, 0xb5, 0xc3, 0x42, 0x85, 0x3f, 0xc2, 0x03, 0xc3, 0x41, 0x73, 0x3f, + 0x31, 0x86, 0x83, 0xa0, 0x62, 0xa0, 0x41, 0xa0, 0x10, 0x18, 0x50, 0x00, + 0x2c, 0x70, 0x8d, 0x02, 0x6f, 0xf4, 0x1a, 0xda, 0x00, 0x1e, 0x02, 0x70, + 0xa0, 0x00, 0xb8, 0x86, 0xe0, 0x7e, 0xe0, 0x78, 0xc3, 0x43, 0x13, 0x00, + 0xf8, 0x6a, 0x42, 0xa3, 0x21, 0xa3, 0xe0, 0x7f, 0x00, 0xa3, 0xe0, 0x78, + 0xf1, 0xc0, 0x2c, 0x71, 0x00, 0x29, 0x00, 0x00, 0xb3, 0x5a, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0x2c, 0x71, 0x00, 0x29, 0x00, 0x00, + 0xb4, 0x5a, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0xf1, 0xc0, 0x2c, 0x71, + 0x00, 0x29, 0x00, 0x00, 0x8e, 0x58, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, + 0x2f, 0x27, 0xff, 0x00, 0x6f, 0x23, 0x3f, 0x00, 0xc3, 0x42, 0xa0, 0x00, + 0x78, 0x6e, 0x20, 0x82, 0x25, 0x78, 0x00, 0xa2, 0x2f, 0x26, 0xff, 0x00, + 0xc3, 0x40, 0xf0, 0x00, 0x40, 0x01, 0x00, 0x18, 0x01, 0x02, 0xe0, 0x7e, + 0xe4, 0xc3, 0xa1, 0xc1, 0x08, 0x45, 0x2f, 0x27, 0x7f, 0x00, 0x6f, 0x23, + 0x3f, 0x00, 0xaa, 0x20, 0x90, 0x02, 0xab, 0x20, 0xd0, 0x02, 0xcb, 0x46, + 0xa0, 0x00, 0x78, 0x6e, 0xaa, 0x20, 0x88, 0x01, 0x0f, 0x78, 0x14, 0x73, + 0x0c, 0xf7, 0x00, 0x86, 0xa5, 0x78, 0x00, 0xa6, 0x2f, 0x26, 0x7f, 0x00, + 0xc3, 0x40, 0xf0, 0x00, 0x40, 0x01, 0x00, 0x18, 0x01, 0x02, 0xc4, 0xc7, + 0x2f, 0x26, 0x7f, 0x00, 0xd2, 0x0b, 0x8f, 0xf6, 0x3d, 0x08, 0x70, 0x00, + 0x2f, 0x21, 0x48, 0x83, 0x00, 0x1c, 0x01, 0x30, 0x05, 0xf2, 0xc3, 0x40, + 0xa0, 0x00, 0x00, 0x87, 0x09, 0xf0, 0x04, 0x25, 0x81, 0x9f, 0xff, 0x00, + 0x00, 0x00, 0x11, 0xf2, 0xc3, 0x40, 0xa0, 0x00, 0xe4, 0x86, 0x00, 0x80, + 0x4c, 0x71, 0x6c, 0x70, 0xee, 0x0a, 0xaf, 0xf6, 0x40, 0x24, 0x04, 0x30, + 0x00, 0xc0, 0x04, 0xe8, 0x3a, 0x0b, 0xcf, 0xf7, 0xc4, 0xc7, 0x04, 0x25, + 0x81, 0x9f, 0x00, 0x0f, 0x00, 0x00, 0x04, 0xf2, 0x02, 0x86, 0xf0, 0xe8, + 0x6c, 0x25, 0xc1, 0x96, 0xf2, 0xf3, 0x01, 0x86, 0xea, 0xe8, 0xf0, 0xf1, + 0xe2, 0xc2, 0x76, 0x0b, 0xaf, 0xf6, 0x08, 0x45, 0x2d, 0x08, 0x70, 0x00, + 0x2f, 0x21, 0x48, 0x83, 0x05, 0xf2, 0xc3, 0x40, 0xa0, 0x00, 0x00, 0x87, + 0x09, 0xf0, 0x04, 0x25, 0x81, 0x9f, 0xff, 0x00, 0x00, 0x00, 0x0b, 0xf2, + 0xc3, 0x40, 0xa0, 0x00, 0xe4, 0x86, 0x00, 0x80, 0x4c, 0x71, 0x12, 0x0a, + 0xaf, 0xf6, 0x6c, 0x70, 0xc2, 0xc6, 0x04, 0x25, 0x81, 0x9f, 0x00, 0x0f, + 0x00, 0x00, 0xc3, 0x42, 0xa0, 0x00, 0x78, 0x6e, 0x03, 0xf2, 0x02, 0x82, + 0xf2, 0xe8, 0x6c, 0x25, 0xc1, 0x96, 0xf4, 0xf3, 0x01, 0x82, 0xee, 0xe8, + 0xf0, 0xf1, 0xe0, 0x78, 0xf1, 0xc0, 0x62, 0xb8, 0x39, 0x08, 0xf5, 0x00, + 0xa1, 0xc1, 0x0f, 0x78, 0xf0, 0x26, 0x00, 0x70, 0xa0, 0x00, 0x64, 0xe7, + 0x07, 0xe9, 0x2c, 0x71, 0x4c, 0x73, 0xce, 0x09, 0xaf, 0xf6, 0x6c, 0x70, + 0x0e, 0xf0, 0x2c, 0x71, 0x4c, 0x73, 0x6c, 0x70, 0x40, 0x24, 0x04, 0x30, + 0x3e, 0x0a, 0xaf, 0xf6, 0x00, 0x1c, 0x01, 0x30, 0x00, 0xc0, 0x04, 0xe8, + 0x8a, 0x0a, 0xcf, 0xf7, 0x87, 0x74, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, + 0xf1, 0xc0, 0x9f, 0x20, 0x02, 0x03, 0x00, 0x20, 0x81, 0x0f, 0xa0, 0x00, + 0x25, 0x4a, 0x00, 0x89, 0x05, 0xe8, 0x0d, 0x78, 0x00, 0x19, 0xc3, 0x0f, + 0x85, 0x58, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0xe4, 0xc2, 0x08, 0x46, + 0x12, 0x58, 0x08, 0x45, 0xa4, 0x16, 0x00, 0x11, 0xb5, 0x70, 0xca, 0x25, + 0x61, 0x10, 0xb1, 0x70, 0x0c, 0x70, 0x0a, 0xf2, 0x56, 0x86, 0x05, 0xea, + 0xb0, 0x78, 0x60, 0x7a, 0xc1, 0x41, 0x0c, 0x71, 0xa4, 0x1e, 0x44, 0x13, + 0xc4, 0xc6, 0xe0, 0x78, 0xea, 0xc2, 0x8c, 0xdb, 0x0a, 0x7b, 0x08, 0x45, + 0xc3, 0x40, 0xa0, 0x00, 0x24, 0x4a, 0x1f, 0x63, 0x00, 0x8f, 0x28, 0x46, + 0x50, 0x40, 0x35, 0xe9, 0xb2, 0xe8, 0xc3, 0x40, 0xa0, 0x00, 0x64, 0x41, + 0x21, 0x8f, 0xb6, 0x78, 0x41, 0x80, 0xe0, 0x80, 0x8c, 0x21, 0xc3, 0x8f, + 0xcb, 0x44, 0xa0, 0x00, 0xcc, 0x49, 0x06, 0xf2, 0x78, 0x64, 0x0a, 0x80, + 0x45, 0x0e, 0x05, 0x10, 0x16, 0x6e, 0x41, 0x2e, 0x8b, 0x16, 0x00, 0x27, + 0x11, 0x90, 0x01, 0x22, 0xcf, 0x82, 0x8c, 0x21, 0xc3, 0x8f, 0x10, 0xf2, + 0x78, 0x64, 0x25, 0x80, 0x44, 0x80, 0x3b, 0x27, 0x40, 0x10, 0x3d, 0x21, + 0x82, 0x20, 0x30, 0x77, 0xca, 0x20, 0x81, 0x00, 0x8c, 0xe8, 0x52, 0x0f, + 0xef, 0xff, 0xa1, 0x40, 0xc1, 0x40, 0x22, 0x41, 0xe1, 0x42, 0xa1, 0x43, + 0x3a, 0x0c, 0xef, 0xff, 0x0a, 0x24, 0x00, 0x04, 0xca, 0xc6, 0x92, 0xe8, + 0x36, 0x0f, 0xef, 0xff, 0xa1, 0x40, 0xa1, 0x40, 0x9f, 0x20, 0x02, 0x03, + 0xc3, 0x42, 0xa0, 0x00, 0xcc, 0x49, 0x2c, 0x70, 0x58, 0x60, 0x00, 0x1f, + 0x43, 0x10, 0x25, 0xa0, 0x24, 0xa0, 0x2a, 0xa0, 0xf0, 0x26, 0x40, 0x73, + 0x13, 0x00, 0x40, 0x90, 0x09, 0x08, 0x10, 0x20, 0x8d, 0x58, 0xca, 0xc6, + 0x8b, 0x58, 0xca, 0xc6, 0xe2, 0xc2, 0x59, 0x88, 0xc1, 0xba, 0x54, 0x72, + 0x17, 0xf2, 0x2f, 0x27, 0x7f, 0x03, 0x6f, 0x23, 0x3f, 0x00, 0x50, 0x80, + 0x04, 0x32, 0x40, 0x80, 0x0d, 0xf2, 0x4c, 0x70, 0x04, 0x31, 0x80, 0x80, + 0xc5, 0xf7, 0x30, 0xa0, 0x0e, 0x18, 0x43, 0x00, 0x03, 0xf0, 0x13, 0x18, + 0x43, 0x00, 0x10, 0xd8, 0x8d, 0x58, 0x2f, 0x26, 0x7f, 0x03, 0xc2, 0xc6, + 0xe2, 0xc2, 0x59, 0x88, 0xc1, 0xba, 0x54, 0x72, 0x11, 0xf2, 0x2f, 0x27, + 0x7f, 0x03, 0x6f, 0x23, 0x3f, 0x00, 0x4c, 0x10, 0x02, 0x01, 0x13, 0x0a, + 0x40, 0x00, 0x4c, 0x18, 0x44, 0x00, 0x0f, 0x18, 0x43, 0x00, 0x10, 0xd8, + 0x8d, 0x58, 0x2f, 0x26, 0x7f, 0x03, 0xc2, 0xc6, 0xe6, 0xc3, 0xa4, 0xc1, + 0x08, 0x45, 0x19, 0x88, 0x28, 0x46, 0xc1, 0xb8, 0x14, 0x72, 0x27, 0xf2, + 0x40, 0x24, 0xc1, 0x33, 0x83, 0xc2, 0x40, 0x24, 0x83, 0x32, 0x40, 0x24, + 0x04, 0x30, 0x40, 0x24, 0x05, 0x31, 0xa1, 0x40, 0x39, 0x58, 0x00, 0xc1, + 0xc1, 0x40, 0x4c, 0x70, 0x04, 0x31, 0x80, 0x83, 0xca, 0x20, 0x45, 0x00, + 0x04, 0x31, 0x80, 0x80, 0xca, 0x26, 0x09, 0x10, 0x2f, 0x27, 0xff, 0x03, + 0x6f, 0x23, 0x3f, 0x00, 0x10, 0x85, 0x04, 0x30, 0x80, 0x83, 0x07, 0xf2, + 0x10, 0xd8, 0xd0, 0xa5, 0x0e, 0x1d, 0x43, 0x10, 0x8d, 0x58, 0x2f, 0x26, + 0xff, 0x03, 0xc6, 0xc7, 0xcb, 0x44, 0x13, 0x00, 0xc8, 0xaa, 0x80, 0x84, + 0x95, 0x70, 0xe0, 0x20, 0x02, 0x03, 0xe0, 0x7e, 0xcb, 0x44, 0x13, 0x00, + 0xc4, 0xaa, 0x80, 0x84, 0x95, 0x70, 0xe0, 0x7c, 0x00, 0x7c, 0xe0, 0x78, + 0xe8, 0xc2, 0x96, 0x0a, 0xcf, 0xf7, 0xcb, 0x45, 0x13, 0x00, 0x90, 0xaa, + 0x2a, 0x85, 0x10, 0x40, 0x92, 0x0a, 0xef, 0xf7, 0x09, 0x69, 0x4d, 0x08, + 0x74, 0x02, 0x08, 0x46, 0x08, 0x85, 0x86, 0x0a, 0xef, 0xf7, 0x04, 0x77, + 0x8a, 0x0d, 0xef, 0xec, 0x08, 0x47, 0x39, 0x0f, 0x75, 0x12, 0x21, 0x6f, + 0x55, 0x26, 0x83, 0x1f, 0x2f, 0x79, 0x40, 0x20, 0xc2, 0x20, 0x6f, 0x7e, + 0x08, 0x20, 0x40, 0x00, 0x4f, 0x7a, 0xd9, 0x60, 0x25, 0x0a, 0x64, 0x00, + 0x2c, 0x71, 0x0f, 0x78, 0x86, 0x0d, 0xef, 0xec, 0xc1, 0x41, 0x3a, 0x0e, + 0xef, 0xec, 0xc1, 0x40, 0x0a, 0x0c, 0x60, 0x01, 0x00, 0x85, 0xc8, 0xc6, + 0x2f, 0xd8, 0xb2, 0x09, 0xef, 0xeb, 0x2c, 0x71, 0xaa, 0x09, 0xef, 0xeb, + 0x2d, 0xd8, 0xe0, 0x78, 0xc3, 0x40, 0x13, 0x00, 0x8c, 0xaa, 0xfd, 0x05, + 0xaf, 0xf4, 0x00, 0x80, 0xea, 0xc2, 0xcb, 0x45, 0x13, 0x00, 0x94, 0xaa, + 0x00, 0x85, 0x21, 0x85, 0xe4, 0x85, 0xc5, 0x85, 0x02, 0x79, 0x26, 0xb9, + 0x1e, 0x21, 0x81, 0x0f, 0xaa, 0xaa, 0xab, 0xaa, 0x08, 0x15, 0x11, 0x10, + 0x0c, 0x15, 0x10, 0x10, 0x4a, 0x0e, 0xaf, 0xf4, 0x2f, 0x79, 0x02, 0x85, + 0xf2, 0x4e, 0x02, 0x20, 0x41, 0x24, 0x27, 0xb9, 0x27, 0xba, 0x2f, 0x79, + 0x96, 0x0e, 0xaf, 0xf4, 0x4f, 0x7a, 0xca, 0xc6, 0xe4, 0xc2, 0xcb, 0x45, + 0x13, 0x00, 0xac, 0xaa, 0xf2, 0x0a, 0xef, 0xec, 0xc0, 0x85, 0x63, 0x85, + 0x42, 0x85, 0x00, 0x41, 0x64, 0x77, 0xc1, 0x40, 0xa5, 0x5a, 0xc4, 0xc6, + 0xf1, 0xc0, 0x5a, 0xd8, 0xab, 0x20, 0x08, 0x0e, 0x97, 0x5a, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xe2, 0xc2, 0x28, 0x45, 0x20, 0x81, 0x40, 0x43, + 0x10, 0xda, 0x19, 0x61, 0x7e, 0x0d, 0x2f, 0xf4, 0x60, 0x40, 0x00, 0x85, + 0x10, 0xe0, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0xe6, 0xc3, 0xa4, 0xc1, + 0x68, 0x45, 0x60, 0x83, 0x28, 0x46, 0x10, 0xe3, 0x2b, 0x0a, 0xe4, 0x00, + 0x00, 0x41, 0x80, 0xc0, 0x10, 0xda, 0xa2, 0x0f, 0x2f, 0xe6, 0x80, 0xc7, + 0x4a, 0x24, 0x00, 0x74, 0xa8, 0x20, 0x00, 0x02, 0x00, 0x85, 0x01, 0x17, + 0x81, 0x14, 0xd8, 0x60, 0xc5, 0x71, 0x20, 0xa8, 0x00, 0x85, 0x10, 0xe0, + 0x00, 0xa5, 0xc6, 0xc7, 0xe2, 0xc2, 0x08, 0x45, 0x00, 0x90, 0xd3, 0x70, + 0x00, 0x00, 0x2b, 0x66, 0x1c, 0xd8, 0x17, 0xf4, 0x5e, 0x85, 0x78, 0xd9, + 0xe2, 0x0d, 0xaf, 0xe9, 0xa1, 0x40, 0x14, 0x70, 0x1d, 0xd8, 0x0f, 0xf2, + 0x4a, 0x24, 0x00, 0x71, 0x0c, 0x70, 0x4c, 0x70, 0xa8, 0x20, 0x40, 0x02, + 0x4f, 0x79, 0x15, 0x25, 0x41, 0x10, 0x4b, 0x11, 0x01, 0x06, 0x04, 0xe9, + 0x44, 0x71, 0xc2, 0xc6, 0x1e, 0xd8, 0xc2, 0xc6, 0xe4, 0xc3, 0xa1, 0xc1, + 0x0f, 0x7d, 0x11, 0x0d, 0xb5, 0x11, 0x0c, 0x73, 0x48, 0x25, 0x80, 0x10, + 0x80, 0x20, 0x83, 0x0f, 0xd3, 0x68, 0xc3, 0x40, 0xa0, 0x00, 0x74, 0x49, + 0x84, 0x26, 0x1f, 0x1e, 0x1e, 0x66, 0x2c, 0x77, 0x0c, 0x70, 0x80, 0xc2, + 0x62, 0x08, 0xaf, 0xf6, 0x20, 0x43, 0x00, 0xc0, 0x79, 0xe8, 0x9e, 0x78, + 0x41, 0x86, 0x20, 0x86, 0x04, 0x1e, 0x01, 0x10, 0x00, 0x1e, 0x01, 0x10, + 0xbe, 0x78, 0xa1, 0x40, 0x45, 0x58, 0xef, 0xf1, 0xe2, 0xc3, 0x08, 0x45, + 0x01, 0x80, 0x84, 0x20, 0x03, 0x0c, 0x15, 0x08, 0x31, 0x04, 0xa1, 0xc1, + 0x0e, 0x8d, 0x00, 0x15, 0x04, 0x10, 0x1d, 0x78, 0xa1, 0x5a, 0xc2, 0xc7, + 0xff, 0xd8, 0x40, 0xc0, 0xc3, 0x44, 0x13, 0x00, 0x24, 0x1a, 0x40, 0x24, + 0x05, 0x30, 0xa1, 0x40, 0xb5, 0x5a, 0xa1, 0x40, 0x17, 0x58, 0x00, 0xc0, + 0xc2, 0xc7, 0xe0, 0x78, 0xe2, 0xc2, 0x28, 0x45, 0x20, 0x81, 0x40, 0x43, + 0x18, 0xda, 0x19, 0x61, 0x6a, 0x0c, 0x2f, 0xf4, 0x60, 0x40, 0x00, 0x85, + 0x18, 0xe0, 0x00, 0xa5, 0xc2, 0xc6, 0xe0, 0x78, 0xe6, 0xc3, 0xa6, 0xc1, + 0x68, 0x45, 0x60, 0x83, 0x28, 0x46, 0x18, 0xe3, 0x2b, 0x0a, 0xe4, 0x00, + 0x00, 0x41, 0x80, 0xc0, 0x18, 0xda, 0x8e, 0x0e, 0x2f, 0xe6, 0x80, 0xc7, + 0x4a, 0x24, 0x00, 0x76, 0xa8, 0x20, 0x00, 0x02, 0x00, 0x85, 0x01, 0x17, + 0x81, 0x14, 0xd8, 0x60, 0xc5, 0x71, 0x20, 0xa8, 0x00, 0x85, 0x18, 0xe0, + 0x00, 0xa5, 0xc6, 0xc7, 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, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0xbd, 0x37, 0x86, 0x35, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbd, 0x37, 0x86, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x37, 0x86, 0x35, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb7, 0xd1, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0xb7, 0xd1, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0xb7, 0xd1, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x41, 0x32, 0x00, 0xac, 0xc5, 0xa7, 0x36, 0xac, 0xc5, 0xa7, 0x36, + 0xac, 0xc5, 0xa7, 0x36, 0x00, 0x00, 0x00, 0x00, 0xac, 0xc5, 0x27, 0x37, + 0xac, 0xc5, 0x27, 0x37, 0xac, 0xc5, 0x27, 0x37, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xd3, 0x02, 0x37, 0x38, 0xa9, 0x68, 0x12, 0x37, 0xa9, 0x68, 0x92, 0x36, + 0x35, 0xfa, 0x8e, 0x37, 0x88, 0xc3, 0x64, 0x36, 0x88, 0xc3, 0xe4, 0x35, + 0xdb, 0x0f, 0x49, 0x40, 0xf3, 0x66, 0xdf, 0x3e, 0xc2, 0xb8, 0xb2, 0x3d, + 0x02, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x35, 0xfa, 0x0e, 0x3c, 0x88, 0xc3, 0xe4, 0x3a, 0x88, 0xc3, 0x64, 0x3a, + 0xf3, 0x66, 0x5f, 0x3f, 0xf3, 0x66, 0xdf, 0x3e, 0x50, 0x77, 0x56, 0x3e, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x14, 0x05, 0x14, 0x05, + 0xc4, 0x09, 0x00, 0x00, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3f, 0x9a, 0x99, 0x19, 0x3e, 0x9a, 0x99, 0x99, 0x3d, + 0x0a, 0xd7, 0xa3, 0x3c, 0x0a, 0xd7, 0xa3, 0x3c, 0x0a, 0xd7, 0xa3, 0x3c, + 0xbd, 0x37, 0x86, 0x35, 0xbd, 0x37, 0x86, 0x35, 0xbd, 0x37, 0x86, 0x35, + 0x00, 0x24, 0xf4, 0x49, 0x00, 0x24, 0xf4, 0x49, 0x00, 0x24, 0xf4, 0x49, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, + 0xba, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, + 0xf6, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, + 0x9c, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, + 0x8e, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, + 0xa4, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x17, 0xb7, 0x51, 0x39, 0x6f, 0x12, 0x03, 0x3b, 0x53, 0x05, 0xa3, 0x3c, + 0xb6, 0xf3, 0x3d, 0x3e, 0x8c, 0xe0, 0x5a, 0x3c, 0x8c, 0xe0, 0xda, 0x3c, + 0x8c, 0xe0, 0x5a, 0x3c, 0x00, 0x00, 0x80, 0x3f, 0xf8, 0xdf, 0xd2, 0xbf, + 0xf9, 0x6d, 0x33, 0x3f, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4c, 0x8e, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0xd4, 0x78, 0xa0, 0x00, + 0x77, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x8d, 0x13, 0x00, + 0x44, 0x54, 0x13, 0x00, 0xd8, 0x83, 0xa0, 0x00, 0x79, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xbc, 0x8d, 0x13, 0x00, 0x44, 0x54, 0x13, 0x00, + 0x00, 0x84, 0xa0, 0x00, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0x8d, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0xdc, 0x76, 0xa0, 0x00, + 0x75, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0xdc, 0x8d, 0x13, 0x00, + 0x44, 0x54, 0x13, 0x00, 0x28, 0x84, 0xa0, 0x00, 0xbd, 0x02, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xec, 0x8d, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x30, 0x77, 0xa0, 0x00, 0xc1, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x8e, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x4c, 0x77, 0xa0, 0x00, + 0xc3, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x8e, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0x68, 0x77, 0xa0, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x84, 0x6e, 0xa0, 0x00, 0x04, 0x01, 0x00, 0x00, 0xfc, 0x8d, 0x13, 0x00, + 0x48, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, 0xa0, 0x2d, 0x13, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x66, 0x11, 0x00, + 0x34, 0x66, 0x11, 0x00, 0x04, 0x66, 0x11, 0x00, 0x40, 0x66, 0x11, 0x00, + 0x1c, 0x66, 0x11, 0x00, 0x10, 0x66, 0x11, 0x00, 0x28, 0x66, 0x11, 0x00, + 0x48, 0x70, 0xa0, 0x00, 0xe4, 0x9f, 0xa0, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x84, 0x6e, 0xa0, 0x00, 0x04, 0x01, 0x00, 0x00, 0x2c, 0x8e, 0x13, 0x00, + 0x50, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, 0xf8, 0x2e, 0x13, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x13, 0x00, + 0xf0, 0x2f, 0x13, 0x00, 0xc0, 0x2f, 0x13, 0x00, 0xf8, 0x2f, 0x13, 0x00, + 0xd8, 0x2f, 0x13, 0x00, 0xd0, 0x2f, 0x13, 0x00, 0xe8, 0x2f, 0x13, 0x00, + 0x58, 0x70, 0xa0, 0x00, 0xb8, 0xa4, 0xa0, 0x00, 0x2a, 0x00, 0x00, 0x00, + 0x84, 0x6e, 0xa0, 0x00, 0x04, 0x03, 0x00, 0x00, 0x30, 0x74, 0x13, 0x00, + 0xc8, 0x8c, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, 0x0c, 0x31, 0x13, 0x00, + 0x08, 0x33, 0x13, 0x00, 0x98, 0x32, 0x13, 0x00, 0x38, 0x34, 0x13, 0x00, + 0xf8, 0x32, 0x13, 0x00, 0x70, 0x32, 0x13, 0x00, 0x00, 0x33, 0x13, 0x00, + 0x88, 0x32, 0x13, 0x00, 0x80, 0x32, 0x13, 0x00, 0xf0, 0x32, 0x13, 0x00, + 0x70, 0x70, 0xa0, 0x00, 0x78, 0x98, 0xa0, 0x00, 0x01, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa4, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x18, 0x76, 0xa0, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x88, 0x76, 0xa0, 0x00, + 0x65, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x8c, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0x14, 0x77, 0xa0, 0x00, 0x23, 0x03, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd4, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0xa0, 0x77, 0xa0, 0x00, 0x25, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0xbc, 0x77, 0xa0, 0x00, + 0x29, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x8c, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0xd8, 0x77, 0xa0, 0x00, 0x05, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x8d, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x64, 0x78, 0xa0, 0x00, 0x7b, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x8d, 0x13, 0x00, 0x44, 0x54, 0x13, 0x00, 0x50, 0x84, 0xa0, 0x00, + 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8d, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0x0c, 0x79, 0xa0, 0x00, 0x7d, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x58, 0x8d, 0x13, 0x00, 0x44, 0x54, 0x13, 0x00, + 0x78, 0x84, 0xa0, 0x00, 0x81, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x7c, 0x8d, 0x13, 0x00, 0x44, 0x54, 0x13, 0x00, 0xa0, 0x84, 0xa0, 0x00, + 0x41, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x8d, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0xd0, 0x79, 0xa0, 0x00, 0x39, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x8d, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x08, 0x7a, 0xa0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, + 0x03, 0x01, 0x00, 0x00, 0xf8, 0x8c, 0x13, 0x00, 0x60, 0x8b, 0x13, 0x00, + 0xbc, 0x6e, 0xa0, 0x00, 0x40, 0x34, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc4, 0x35, 0x13, 0x00, 0xb4, 0x35, 0x13, 0x00, + 0x84, 0x35, 0x13, 0x00, 0xbc, 0x35, 0x13, 0x00, 0x9c, 0x35, 0x13, 0x00, + 0x94, 0x35, 0x13, 0x00, 0xac, 0x35, 0x13, 0x00, 0x78, 0x70, 0xa0, 0x00, + 0xf0, 0x9e, 0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x34, 0x8d, 0x13, 0x00, 0x1c, 0x8d, 0x13, 0x00, + 0xb4, 0x6e, 0xa0, 0x00, 0x08, 0x38, 0x13, 0x00, 0x00, 0x39, 0x13, 0x00, + 0xe4, 0x38, 0x13, 0x00, 0x04, 0x39, 0x13, 0x00, 0xf0, 0x38, 0x13, 0x00, + 0xbc, 0x38, 0x13, 0x00, 0xf8, 0x38, 0x13, 0x00, 0xd4, 0x38, 0x13, 0x00, + 0xcc, 0x38, 0x13, 0x00, 0xe8, 0x38, 0x13, 0x00, 0xc8, 0x70, 0xa0, 0x00, + 0xd8, 0x99, 0xa0, 0x00, 0x07, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x64, 0x8d, 0x13, 0x00, 0x4c, 0x8d, 0x13, 0x00, + 0xb4, 0x6e, 0xa0, 0x00, 0x0c, 0x39, 0x13, 0x00, 0x0c, 0x3a, 0x13, 0x00, + 0xf0, 0x39, 0x13, 0x00, 0x10, 0x3a, 0x13, 0x00, 0xfc, 0x39, 0x13, 0x00, + 0xc8, 0x39, 0x13, 0x00, 0x04, 0x3a, 0x13, 0x00, 0xe0, 0x39, 0x13, 0x00, + 0xd8, 0x39, 0x13, 0x00, 0xf4, 0x39, 0x13, 0x00, 0xd4, 0x70, 0xa0, 0x00, + 0x24, 0x9a, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x88, 0x8d, 0x13, 0x00, 0x70, 0x8d, 0x13, 0x00, + 0xb4, 0x6e, 0xa0, 0x00, 0x18, 0x3a, 0x13, 0x00, 0x08, 0x3b, 0x13, 0x00, + 0xec, 0x3a, 0x13, 0x00, 0x0c, 0x3b, 0x13, 0x00, 0xf8, 0x3a, 0x13, 0x00, + 0xc4, 0x3a, 0x13, 0x00, 0x00, 0x3b, 0x13, 0x00, 0xdc, 0x3a, 0x13, 0x00, + 0xd4, 0x3a, 0x13, 0x00, 0xf0, 0x3a, 0x13, 0x00, 0xe0, 0x70, 0xa0, 0x00, + 0x70, 0x9a, 0xa0, 0x00, 0xcb, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0xfc, 0x75, 0xa0, 0x00, + 0x2d, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x8b, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0x34, 0x76, 0xa0, 0x00, 0x55, 0x01, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x6c, 0x76, 0xa0, 0x00, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0xa4, 0x76, 0xa0, 0x00, + 0x67, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x8c, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0xc0, 0x76, 0xa0, 0x00, 0x4f, 0x01, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2c, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x84, 0x77, 0xa0, 0x00, 0x63, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x10, 0x78, 0xa0, 0x00, + 0x51, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x8c, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0xb8, 0x78, 0xa0, 0x00, 0x89, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5c, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0xf0, 0x78, 0xa0, 0x00, 0x87, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x28, 0x79, 0xa0, 0x00, + 0x71, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x8c, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0x44, 0x79, 0xa0, 0x00, 0x85, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x74, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x60, 0x79, 0xa0, 0x00, 0x4b, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x7c, 0x79, 0xa0, 0x00, + 0x5d, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x8c, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0x98, 0x79, 0xa0, 0x00, 0x4d, 0x01, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0xec, 0x79, 0xa0, 0x00, 0x5b, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8c, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x5c, 0x7a, 0xa0, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x02, 0x01, 0x00, 0x00, + 0xec, 0x8b, 0x13, 0x00, 0x2c, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xf4, 0x62, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x98, 0x63, 0x11, 0x00, 0x80, 0x63, 0x11, 0x00, 0x50, 0x63, 0x11, 0x00, + 0x8c, 0x63, 0x11, 0x00, 0x68, 0x63, 0x11, 0x00, 0x5c, 0x63, 0x11, 0x00, + 0x74, 0x63, 0x11, 0x00, 0x00, 0x70, 0xa0, 0x00, 0x14, 0xa1, 0xa0, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x24, 0x8c, 0x13, 0x00, 0x4c, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x78, 0x2e, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x66, 0x11, 0x00, 0xc8, 0x66, 0x11, 0x00, 0x98, 0x66, 0x11, 0x00, + 0xd4, 0x66, 0x11, 0x00, 0xb0, 0x66, 0x11, 0x00, 0xa4, 0x66, 0x11, 0x00, + 0xbc, 0x66, 0x11, 0x00, 0x50, 0x70, 0xa0, 0x00, 0x6c, 0x9c, 0xa0, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x44, 0x8c, 0x13, 0x00, 0x3c, 0x8c, 0x13, 0x00, 0xbc, 0x6e, 0xa0, 0x00, + 0xf0, 0x6d, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6f, 0x11, 0x00, 0x20, 0x6f, 0x11, 0x00, 0xf0, 0x6e, 0x11, 0x00, + 0x2c, 0x6f, 0x11, 0x00, 0x08, 0x6f, 0x11, 0x00, 0xfc, 0x6e, 0x11, 0x00, + 0x14, 0x6f, 0x11, 0x00, 0x9c, 0x70, 0xa0, 0x00, 0x5c, 0xa7, 0xa0, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x4c, 0x8c, 0x13, 0x00, 0x74, 0x8b, 0x13, 0x00, 0xbc, 0x6e, 0xa0, 0x00, + 0x90, 0x36, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd4, 0x37, 0x13, 0x00, 0xc4, 0x37, 0x13, 0x00, 0x94, 0x37, 0x13, 0x00, + 0xcc, 0x37, 0x13, 0x00, 0xac, 0x37, 0x13, 0x00, 0xa4, 0x37, 0x13, 0x00, + 0xbc, 0x37, 0x13, 0x00, 0xa0, 0x70, 0xa0, 0x00, 0x1c, 0xaa, 0xa0, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x94, 0x8c, 0x13, 0x00, 0xbc, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xfc, 0x77, 0x11, 0x00, 0x38, 0x3d, 0x13, 0x00, 0x34, 0x3d, 0x13, 0x00, + 0x78, 0x79, 0x11, 0x00, 0xec, 0x78, 0x11, 0x00, 0x94, 0x78, 0x11, 0x00, + 0xf8, 0x78, 0x11, 0x00, 0xac, 0x78, 0x11, 0x00, 0xa0, 0x78, 0x11, 0x00, + 0xe0, 0x78, 0x11, 0x00, 0x38, 0x71, 0xa0, 0x00, 0x10, 0x99, 0xa0, 0x00, + 0x54, 0x7d, 0x13, 0x00, 0xc0, 0x7d, 0x13, 0x00, 0x9c, 0x7d, 0x13, 0x00, + 0x78, 0x7d, 0x13, 0x00, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x24, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x50, 0x76, 0xa0, 0x00, + 0x47, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x8b, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0xf8, 0x76, 0xa0, 0x00, 0xd3, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5c, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0xf4, 0x77, 0xa0, 0x00, 0xdf, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x2c, 0x78, 0xa0, 0x00, + 0xe7, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8b, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0x48, 0x78, 0xa0, 0x00, 0x31, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x80, 0x78, 0xa0, 0x00, 0xdd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x84, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x9c, 0x78, 0xa0, 0x00, + 0x43, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x8b, 0x13, 0x00, + 0x7c, 0xd2, 0x11, 0x00, 0xb4, 0x79, 0xa0, 0x00, 0x27, 0x03, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb8, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, + 0x24, 0x7a, 0xa0, 0x00, 0x45, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x8b, 0x13, 0x00, 0x7c, 0xd2, 0x11, 0x00, 0x40, 0x7a, 0xa0, 0x00, + 0xe4, 0x86, 0x13, 0x00, 0xc4, 0x71, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0xcc, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xc8, 0x84, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x7a, 0xa0, 0x00, + 0x9c, 0x86, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xe8, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2c, 0x73, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x7a, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x7a, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x7a, 0xa0, 0x00, + 0xc8, 0x72, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x02, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x73, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb0, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x7a, 0xa0, 0x00, + 0xc8, 0x72, 0x13, 0x00, 0x54, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xce, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x54, 0x73, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x7b, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x7b, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x7b, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x7b, 0xa0, 0x00, + 0x2c, 0x87, 0x13, 0x00, 0x64, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xac, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x68, 0x73, 0xa0, 0x00, + 0x74, 0x87, 0x13, 0x00, 0x78, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xae, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x7c, 0x73, 0xa0, 0x00, + 0xbc, 0x87, 0x13, 0x00, 0xdc, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xb0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x90, 0x73, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x7b, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x7b, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x7b, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb0, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x7b, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xec, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x7c, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb4, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2c, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xdc, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x7d, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x7e, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x7e, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x7e, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x7e, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x7e, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x62, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x7e, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb4, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x7e, 0xa0, 0x00, + 0x04, 0x88, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x16, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xa4, 0x73, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x7e, 0xa0, 0x00, + 0x8c, 0x6e, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xee, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xb8, 0x73, 0xa0, 0x00, + 0x8c, 0x6e, 0x13, 0x00, 0x88, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xbc, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xdc, 0x6e, 0xa0, 0x00, + 0x8c, 0x6e, 0x13, 0x00, 0x7c, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xc2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xf0, 0x6e, 0xa0, 0x00, + 0x8c, 0x6e, 0x13, 0x00, 0x50, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x34, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xcc, 0x73, 0xa0, 0x00, + 0x10, 0x73, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xe0, 0x73, 0xa0, 0x00, + 0x10, 0x73, 0x13, 0x00, 0x04, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x1a, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xf4, 0x73, 0xa0, 0x00, + 0xd4, 0x6e, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xf2, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x74, 0xa0, 0x00, + 0xd4, 0x6e, 0x13, 0x00, 0x9c, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x9a, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x6f, 0xa0, 0x00, + 0xd4, 0x6e, 0x13, 0x00, 0x04, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x1c, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x74, 0xa0, 0x00, + 0xd4, 0x6e, 0x13, 0x00, 0x50, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x32, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x30, 0x74, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x7f, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x7f, 0xa0, 0x00, + 0x4c, 0x88, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x06, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x44, 0x74, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xec, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x7f, 0xa0, 0x00, + 0x1c, 0x6f, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x18, 0x6f, 0xa0, 0x00, + 0x1c, 0x6f, 0x13, 0x00, 0x50, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x54, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x58, 0x74, 0xa0, 0x00, + 0x1c, 0x6f, 0x13, 0x00, 0x64, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x5a, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6c, 0x74, 0xa0, 0x00, + 0x1c, 0x6f, 0x13, 0x00, 0x78, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x58, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x80, 0x74, 0xa0, 0x00, + 0x68, 0x70, 0x13, 0x00, 0x9c, 0x71, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0x96, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x85, 0xa0, 0x00, + 0x68, 0x70, 0x13, 0x00, 0xa4, 0x74, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x85, 0xa0, 0x00, + 0x68, 0x70, 0x13, 0x00, 0xd8, 0x71, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0xd0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x85, 0xa0, 0x00, + 0x94, 0x88, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x14, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x94, 0x74, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x7f, 0xa0, 0x00, + 0x58, 0x73, 0x13, 0x00, 0x88, 0x71, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0xba, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa8, 0x85, 0xa0, 0x00, + 0xa0, 0x73, 0x13, 0x00, 0x04, 0x70, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0x1e, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xe0, 0x85, 0xa0, 0x00, + 0x58, 0x73, 0x13, 0x00, 0x28, 0x6e, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0xd6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x86, 0xa0, 0x00, + 0xa0, 0x73, 0x13, 0x00, 0x28, 0x6e, 0x13, 0x00, 0x3c, 0xec, 0x11, 0x00, + 0x54, 0xec, 0x11, 0x00, 0x50, 0xeb, 0x11, 0x00, 0xbc, 0xeb, 0x11, 0x00, + 0xd8, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x86, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x7f, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2c, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x7f, 0xa0, 0x00, + 0xdc, 0x88, 0x13, 0x00, 0x28, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xda, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xa8, 0x74, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xdc, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x7f, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x80, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb4, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x80, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x80, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x80, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xcc, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x80, 0xa0, 0x00, + 0x24, 0x89, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x08, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xbc, 0x74, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x80, 0xa0, 0x00, + 0xb0, 0x70, 0x13, 0x00, 0x40, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x38, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd0, 0x74, 0xa0, 0x00, + 0xb0, 0x70, 0x13, 0x00, 0x00, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xdc, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xe4, 0x74, 0xa0, 0x00, + 0xb0, 0x70, 0x13, 0x00, 0xc4, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xca, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xf8, 0x74, 0xa0, 0x00, + 0xf8, 0x70, 0x13, 0x00, 0x68, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x3a, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x75, 0xa0, 0x00, + 0xf8, 0x70, 0x13, 0x00, 0x14, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xde, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x20, 0x75, 0xa0, 0x00, + 0xf8, 0x70, 0x13, 0x00, 0xd8, 0x71, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xce, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x75, 0xa0, 0x00, + 0x40, 0x71, 0x13, 0x00, 0xe0, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x3e, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x75, 0xa0, 0x00, + 0x40, 0x71, 0x13, 0x00, 0x3c, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xe2, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5c, 0x75, 0xa0, 0x00, + 0x40, 0x71, 0x13, 0x00, 0x28, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xd4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x70, 0x75, 0xa0, 0x00, + 0x6c, 0x89, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xfc, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x84, 0x75, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x80, 0xa0, 0x00, + 0xb4, 0x89, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x0e, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x98, 0x75, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x80, 0xa0, 0x00, + 0xfc, 0x89, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xac, 0x75, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x81, 0xa0, 0x00, + 0x44, 0x8a, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x04, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xc0, 0x75, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x81, 0xa0, 0x00, + 0x8c, 0x8a, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd4, 0x75, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x81, 0xa0, 0x00, + 0xe8, 0x73, 0x13, 0x00, 0xb8, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x40, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2c, 0x6f, 0xa0, 0x00, + 0xe8, 0x73, 0x13, 0x00, 0x90, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x42, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x81, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb6, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x81, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x81, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x81, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x81, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb4, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xba, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2c, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x83, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x6f, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x83, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x6e, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x83, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf4, 0x74, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x83, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbc, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x83, 0xa0, 0x00, + 0xd4, 0x8a, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0xa0, 0xec, 0x11, 0x00, 0xb4, 0xec, 0x11, 0x00, + 0x0c, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xe8, 0x75, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb4, 0x72, 0x13, 0x00, 0xb8, 0xec, 0x11, 0x00, + 0xc4, 0xec, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x86, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x83, 0xa0, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x20, 0x8b, 0x13, 0x00, 0x1c, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x80, 0x61, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x61, 0x11, 0x00, 0xe4, 0x61, 0x11, 0x00, 0xb4, 0x61, 0x11, 0x00, + 0xf0, 0x61, 0x11, 0x00, 0xcc, 0x61, 0x11, 0x00, 0xc0, 0x61, 0x11, 0x00, + 0xd8, 0x61, 0x11, 0x00, 0xe8, 0x6f, 0xa0, 0x00, 0x44, 0x9d, 0xa0, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x28, 0x8b, 0x13, 0x00, 0xdc, 0x8b, 0x13, 0x00, 0xbc, 0x6e, 0xa0, 0x00, + 0x1c, 0x1e, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x13, 0x00, 0xf0, 0x1e, 0x13, 0x00, 0xc0, 0x1e, 0x13, 0x00, + 0xf8, 0x1e, 0x13, 0x00, 0xd8, 0x1e, 0x13, 0x00, 0xd0, 0x1e, 0x13, 0x00, + 0xe8, 0x1e, 0x13, 0x00, 0xf8, 0x6f, 0xa0, 0x00, 0x88, 0xa2, 0xa0, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x30, 0x8b, 0x13, 0x00, 0x04, 0x8c, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xbc, 0x63, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x64, 0x11, 0x00, 0x2c, 0x64, 0x11, 0x00, 0xfc, 0x63, 0x11, 0x00, + 0x38, 0x64, 0x11, 0x00, 0x14, 0x64, 0x11, 0x00, 0x08, 0x64, 0x11, 0x00, + 0x20, 0x64, 0x11, 0x00, 0x10, 0x70, 0xa0, 0x00, 0xbc, 0x9a, 0xa0, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x34, 0x8b, 0x13, 0x00, 0x14, 0x8c, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x50, 0x64, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd8, 0x64, 0x11, 0x00, 0xc0, 0x64, 0x11, 0x00, 0x90, 0x64, 0x11, 0x00, + 0xcc, 0x64, 0x11, 0x00, 0xa8, 0x64, 0x11, 0x00, 0x9c, 0x64, 0x11, 0x00, + 0xb4, 0x64, 0x11, 0x00, 0x20, 0x70, 0xa0, 0x00, 0x10, 0x9b, 0xa0, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x38, 0x8b, 0x13, 0x00, 0x1c, 0x8c, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xe4, 0x64, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x65, 0x11, 0x00, 0x54, 0x65, 0x11, 0x00, 0x24, 0x65, 0x11, 0x00, + 0x60, 0x65, 0x11, 0x00, 0x3c, 0x65, 0x11, 0x00, 0x30, 0x65, 0x11, 0x00, + 0x48, 0x65, 0x11, 0x00, 0x30, 0x70, 0xa0, 0x00, 0x64, 0x9b, 0xa0, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x44, 0x8b, 0x13, 0x00, 0x40, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x20, 0x2d, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x98, 0x2d, 0x13, 0x00, 0x88, 0x2d, 0x13, 0x00, 0x58, 0x2d, 0x13, 0x00, + 0x90, 0x2d, 0x13, 0x00, 0x70, 0x2d, 0x13, 0x00, 0x68, 0x2d, 0x13, 0x00, + 0x80, 0x2d, 0x13, 0x00, 0x40, 0x70, 0xa0, 0x00, 0xec, 0x98, 0xa0, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x58, 0x8b, 0x13, 0x00, 0x54, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x20, 0x6a, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x6a, 0x11, 0x00, 0x84, 0x6a, 0x11, 0x00, 0x54, 0x6a, 0x11, 0x00, + 0x90, 0x6a, 0x11, 0x00, 0x6c, 0x6a, 0x11, 0x00, 0x60, 0x6a, 0x11, 0x00, + 0x78, 0x6a, 0x11, 0x00, 0x60, 0x70, 0xa0, 0x00, 0x90, 0x98, 0xa0, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x68, 0x8b, 0x13, 0x00, 0x64, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xcc, 0x35, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x36, 0x13, 0x00, 0x34, 0x36, 0x13, 0x00, 0x04, 0x36, 0x13, 0x00, + 0x3c, 0x36, 0x13, 0x00, 0x1c, 0x36, 0x13, 0x00, 0x14, 0x36, 0x13, 0x00, + 0x2c, 0x36, 0x13, 0x00, 0x84, 0x70, 0xa0, 0x00, 0x34, 0x99, 0xa0, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x80, 0x8b, 0x13, 0x00, 0x7c, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x64, 0x70, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x70, 0x11, 0x00, 0xc8, 0x70, 0x11, 0x00, 0x98, 0x70, 0x11, 0x00, + 0xd4, 0x70, 0x11, 0x00, 0xb0, 0x70, 0x11, 0x00, 0xa4, 0x70, 0x11, 0x00, + 0xbc, 0x70, 0x11, 0x00, 0xa8, 0x70, 0xa0, 0x00, 0xd4, 0x9c, 0xa0, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x8c, 0x8b, 0x13, 0x00, 0x88, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xf0, 0x70, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x71, 0x11, 0x00, 0x54, 0x71, 0x11, 0x00, 0x24, 0x71, 0x11, 0x00, + 0x60, 0x71, 0x11, 0x00, 0x3c, 0x71, 0x11, 0x00, 0x30, 0x71, 0x11, 0x00, + 0x48, 0x71, 0x11, 0x00, 0xb8, 0x70, 0xa0, 0x00, 0xac, 0x98, 0xa0, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x94, 0x8b, 0x13, 0x00, 0x90, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x50, 0x75, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0x75, 0x11, 0x00, 0xb4, 0x75, 0x11, 0x00, 0x84, 0x75, 0x11, 0x00, + 0xc0, 0x75, 0x11, 0x00, 0x9c, 0x75, 0x11, 0x00, 0x90, 0x75, 0x11, 0x00, + 0xa8, 0x75, 0x11, 0x00, 0xf4, 0x70, 0xa0, 0x00, 0x9c, 0x99, 0xa0, 0x00, + 0x3d, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x9c, 0x8b, 0x13, 0x00, 0x98, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x38, 0x3b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x3b, 0x13, 0x00, 0xa0, 0x3b, 0x13, 0x00, 0x70, 0x3b, 0x13, 0x00, + 0xa8, 0x3b, 0x13, 0x00, 0x88, 0x3b, 0x13, 0x00, 0x80, 0x3b, 0x13, 0x00, + 0x98, 0x3b, 0x13, 0x00, 0x04, 0x71, 0xa0, 0x00, 0xcc, 0x98, 0xa0, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x04, 0x00, 0x00, + 0xa4, 0x8b, 0x13, 0x00, 0x3c, 0x8e, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xb8, 0x3b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbc, 0x3c, 0x13, 0x00, 0xac, 0x3c, 0x13, 0x00, 0x7c, 0x3c, 0x13, 0x00, + 0xb4, 0x3c, 0x13, 0x00, 0x94, 0x3c, 0x13, 0x00, 0x8c, 0x3c, 0x13, 0x00, + 0xa4, 0x3c, 0x13, 0x00, 0x18, 0x71, 0xa0, 0x00, 0x48, 0x9e, 0xa0, 0x00, + 0x2b, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xac, 0x8b, 0x13, 0x00, 0xa8, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0xec, 0x76, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x77, 0x11, 0x00, 0x50, 0x77, 0x11, 0x00, 0x20, 0x77, 0x11, 0x00, + 0x5c, 0x77, 0x11, 0x00, 0x38, 0x77, 0x11, 0x00, 0x2c, 0x77, 0x11, 0x00, + 0x44, 0x77, 0x11, 0x00, 0x20, 0x71, 0xa0, 0x00, 0x10, 0x9c, 0xa0, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xb4, 0x8b, 0x13, 0x00, 0xb0, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x74, 0x77, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x77, 0x11, 0x00, 0xd8, 0x77, 0x11, 0x00, 0xa8, 0x77, 0x11, 0x00, + 0xe4, 0x77, 0x11, 0x00, 0xc0, 0x77, 0x11, 0x00, 0xb4, 0x77, 0x11, 0x00, + 0xcc, 0x77, 0x11, 0x00, 0x30, 0x71, 0xa0, 0x00, 0xb8, 0x9b, 0xa0, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x84, 0x6e, 0xa0, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xc8, 0x8b, 0x13, 0x00, 0xc4, 0x8b, 0x13, 0x00, 0xb4, 0x6e, 0xa0, 0x00, + 0x94, 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x42, 0x13, 0x00, 0xfc, 0x41, 0x13, 0x00, 0xcc, 0x41, 0x13, 0x00, + 0x04, 0x42, 0x13, 0x00, 0xe4, 0x41, 0x13, 0x00, 0xdc, 0x41, 0x13, 0x00, + 0xf4, 0x41, 0x13, 0x00, 0x44, 0x71, 0xa0, 0x00, 0xbc, 0x9d, 0xa0, 0x00, + 0x9c, 0x71, 0x13, 0x00, 0x50, 0x75, 0x13, 0x00, 0xd8, 0x80, 0x13, 0x00, + 0x08, 0x75, 0x13, 0x00, 0xb0, 0x71, 0x13, 0x00, 0xdc, 0x76, 0x13, 0x00, + 0x00, 0x77, 0x13, 0x00, 0x24, 0x77, 0x13, 0x00, 0x60, 0x7a, 0x13, 0x00, + 0x8c, 0x6f, 0x13, 0x00, 0x14, 0x7b, 0x13, 0x00, 0x50, 0x6e, 0x13, 0x00, + 0x64, 0x6e, 0x13, 0x00, 0x78, 0x6e, 0x13, 0x00, 0xec, 0x71, 0x13, 0x00, + 0x0c, 0x7d, 0x13, 0x00, 0x44, 0x81, 0x13, 0x00, 0x68, 0x74, 0x13, 0x00, + 0x00, 0x72, 0x13, 0x00, 0x50, 0x7e, 0x13, 0x00, 0xa4, 0x7b, 0x13, 0x00, + 0xa8, 0x83, 0x13, 0x00, 0x90, 0x74, 0x13, 0x00, 0x08, 0x7e, 0x13, 0x00, + 0xa4, 0x74, 0x13, 0x00, 0x70, 0x7f, 0x13, 0x00, 0x84, 0x83, 0x13, 0x00, + 0x14, 0x72, 0x13, 0x00, 0x90, 0x80, 0x13, 0x00, 0x78, 0x72, 0x13, 0x00, + 0x1c, 0x82, 0x13, 0x00, 0x8c, 0x72, 0x13, 0x00, 0x64, 0x82, 0x13, 0x00, + 0x6c, 0x80, 0x13, 0x00, 0xac, 0x82, 0x13, 0x00, 0xa0, 0x72, 0x13, 0x00, + 0xf4, 0x82, 0x13, 0x00, 0x54, 0x70, 0x13, 0x00, 0x3c, 0x83, 0x13, 0x00, + 0xb0, 0x81, 0x13, 0x00, 0xe0, 0x74, 0x13, 0x00, 0x0c, 0x86, 0x13, 0x00, + 0xb4, 0x72, 0x13, 0x00, 0x54, 0x86, 0x13, 0x00, 0x98, 0x7e, 0x13, 0x00, + 0x80, 0x7b, 0x13, 0x00, 0xe4, 0x7d, 0x13, 0x00, 0x58, 0x7c, 0x13, 0x00, + 0x40, 0x74, 0x13, 0x00, 0x88, 0x71, 0x13, 0x00, 0x04, 0x76, 0x13, 0x00, + 0xb4, 0x77, 0x13, 0x00, 0xe0, 0x75, 0x13, 0x00, 0x28, 0x76, 0x13, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x8c, 0x8e, 0x13, 0x00, 0x08, 0x75, 0x13, 0x00, + 0x20, 0x81, 0x13, 0x00, 0xc4, 0x71, 0x13, 0x00, 0x00, 0x6e, 0x13, 0x00, + 0x2c, 0x7e, 0x13, 0x00, 0x8c, 0x81, 0x13, 0x00, 0xd8, 0x71, 0x13, 0x00, + 0x14, 0x6e, 0x13, 0x00, 0x28, 0x6e, 0x13, 0x00, 0x3c, 0x6e, 0x13, 0x00, + 0x10, 0x7c, 0x13, 0x00, 0xec, 0x7b, 0x13, 0x00, 0x30, 0x7d, 0x13, 0x00, + 0xb0, 0x78, 0x13, 0x00, 0x74, 0x7e, 0x13, 0x00, 0xf8, 0x78, 0x13, 0x00, + 0xb8, 0x74, 0x13, 0x00, 0x7c, 0x74, 0x13, 0x00, 0xe0, 0x7e, 0x13, 0x00, + 0x98, 0x7e, 0x13, 0x00, 0x04, 0x7f, 0x13, 0x00, 0xbc, 0x7e, 0x13, 0x00, + 0xb4, 0x80, 0x13, 0x00, 0xd0, 0x79, 0x13, 0x00, 0x74, 0x75, 0x13, 0x00, + 0xf0, 0x83, 0x13, 0x00, 0x70, 0x76, 0x13, 0x00, 0x5c, 0x84, 0x13, 0x00, + 0xc8, 0x7b, 0x13, 0x00, 0xa0, 0x7c, 0x13, 0x00, 0x28, 0x7f, 0x13, 0x00, + 0x58, 0x85, 0x13, 0x00, 0x40, 0x82, 0x13, 0x00, 0x18, 0x7a, 0x13, 0x00, + 0x88, 0x82, 0x13, 0x00, 0x3c, 0x7a, 0x13, 0x00, 0x18, 0x83, 0x13, 0x00, + 0xa8, 0x7a, 0x13, 0x00, 0x84, 0x83, 0x13, 0x00, 0xa8, 0x83, 0x13, 0x00, + 0x78, 0x86, 0x13, 0x00, 0xf0, 0x7a, 0x13, 0x00, 0xdc, 0x76, 0x13, 0x00, + 0x98, 0x75, 0x13, 0x00, 0x6c, 0x77, 0x13, 0x00, 0x00, 0x77, 0x13, 0x00, + 0x94, 0x76, 0x13, 0x00, 0xfc, 0x77, 0x13, 0x00, 0x38, 0x7b, 0x13, 0x00, + 0xa4, 0x84, 0x13, 0x00, 0x44, 0x78, 0x13, 0x00, 0xa0, 0x6f, 0x13, 0x00, + 0xb4, 0x6f, 0x13, 0x00, 0xc8, 0x6f, 0x13, 0x00, 0xdc, 0x7f, 0x13, 0x00, + 0x10, 0x85, 0x13, 0x00, 0xd4, 0x78, 0x13, 0x00, 0x00, 0x80, 0x13, 0x00, + 0x34, 0x85, 0x13, 0x00, 0x1c, 0x79, 0x13, 0x00, 0x24, 0x80, 0x13, 0x00, + 0xc4, 0x85, 0x13, 0x00, 0xac, 0x79, 0x13, 0x00, 0x2c, 0x7e, 0x13, 0x00, + 0xe4, 0x7d, 0x13, 0x00, 0x08, 0x7e, 0x13, 0x00, 0x64, 0x6f, 0x13, 0x00, + 0xdc, 0x6f, 0x13, 0x00, 0x78, 0x6f, 0x13, 0x00, 0x24, 0x77, 0x13, 0x00, + 0x94, 0x7f, 0x13, 0x00, 0x64, 0x79, 0x13, 0x00, 0xec, 0x6d, 0x13, 0x00, + 0xf0, 0x6f, 0x13, 0x00, 0x28, 0x72, 0x13, 0x00, 0x2c, 0x75, 0x13, 0x00, + 0xcc, 0x83, 0x13, 0x00, 0x48, 0x77, 0x13, 0x00, 0x20, 0x81, 0x13, 0x00, + 0xfc, 0x80, 0x13, 0x00, 0xd8, 0x80, 0x13, 0x00, 0xbc, 0x7e, 0x13, 0x00, + 0x10, 0x7c, 0x13, 0x00, 0x7c, 0x7c, 0x13, 0x00, 0x04, 0x70, 0x13, 0x00, + 0x18, 0x70, 0x13, 0x00, 0x3c, 0x72, 0x13, 0x00, 0x4c, 0x76, 0x13, 0x00, + 0x38, 0x84, 0x13, 0x00, 0xd8, 0x77, 0x13, 0x00, 0x8c, 0x81, 0x13, 0x00, + 0x68, 0x81, 0x13, 0x00, 0x44, 0x81, 0x13, 0x00, 0x50, 0x72, 0x13, 0x00, + 0x2c, 0x70, 0x13, 0x00, 0x64, 0x72, 0x13, 0x00, 0x4c, 0x7f, 0x13, 0x00, + 0x7c, 0x85, 0x13, 0x00, 0x40, 0x79, 0x13, 0x00, 0xf8, 0x81, 0x13, 0x00, + 0xd4, 0x81, 0x13, 0x00, 0xb0, 0x81, 0x13, 0x00, 0xd0, 0x82, 0x13, 0x00, + 0x30, 0x86, 0x13, 0x00, 0x84, 0x7a, 0x13, 0x00, 0x28, 0x76, 0x13, 0x00, + 0x60, 0x83, 0x13, 0x00, 0xcc, 0x7a, 0x13, 0x00, 0xfc, 0x80, 0x13, 0x00, + 0xbc, 0x75, 0x13, 0x00, 0x14, 0x84, 0x13, 0x00, 0x90, 0x77, 0x13, 0x00, + 0x68, 0x81, 0x13, 0x00, 0xb8, 0x76, 0x13, 0x00, 0x80, 0x84, 0x13, 0x00, + 0x20, 0x78, 0x13, 0x00, 0x70, 0x7f, 0x13, 0x00, 0xe0, 0x7e, 0x13, 0x00, + 0x04, 0x7f, 0x13, 0x00, 0xf8, 0x81, 0x13, 0x00, 0xd4, 0x81, 0x13, 0x00, + 0xb8, 0x7f, 0x13, 0x00, 0xa0, 0x85, 0x13, 0x00, 0x88, 0x79, 0x13, 0x00, + 0x78, 0x7d, 0x13, 0x00, 0xe8, 0x7c, 0x13, 0x00, 0xec, 0x84, 0x13, 0x00, + 0x8c, 0x78, 0x13, 0x00, 0x5c, 0x7b, 0x13, 0x00, 0xc8, 0x7b, 0x13, 0x00, + 0x80, 0x7b, 0x13, 0x00, 0xa4, 0x7b, 0x13, 0x00, 0x9c, 0x7d, 0x13, 0x00, + 0xc4, 0x7c, 0x13, 0x00, 0xc8, 0x84, 0x13, 0x00, 0x68, 0x78, 0x13, 0x00, + 0xc0, 0x7d, 0x13, 0x00, 0x48, 0x80, 0x13, 0x00, 0xe8, 0x85, 0x13, 0x00, + 0xf4, 0x79, 0x13, 0x00, 0x7c, 0x7c, 0x13, 0x00, 0x34, 0x7c, 0x13, 0x00, + 0xa0, 0x7c, 0x13, 0x00, 0x58, 0x7c, 0x13, 0x00, 0x40, 0x70, 0x13, 0x00, + 0xcc, 0x74, 0x13, 0x00, 0xf4, 0x74, 0x13, 0x00, 0x54, 0x74, 0x13, 0x00, + 0xac, 0x82, 0x13, 0x00, 0x1c, 0x82, 0x13, 0x00, 0x3c, 0x83, 0x13, 0x00, + 0x54, 0x86, 0x13, 0x00, 0xe0, 0x75, 0x13, 0x00, 0xf4, 0x82, 0x13, 0x00, + 0x0c, 0x7d, 0x13, 0x00, 0x90, 0x80, 0x13, 0x00, 0x64, 0x82, 0x13, 0x00, + 0x50, 0x7e, 0x13, 0x00, 0x14, 0x7b, 0x13, 0x00, 0x50, 0x75, 0x13, 0x00, + 0x5c, 0x7b, 0x13, 0x00, 0xec, 0x7b, 0x13, 0x00, 0x34, 0x7c, 0x13, 0x00, + 0x54, 0x7d, 0x13, 0x00, 0x2c, 0x87, 0x13, 0x00, 0xbc, 0x87, 0x13, 0x00, + 0x74, 0x87, 0x13, 0x00, 0xdc, 0x88, 0x13, 0x00, 0xe4, 0x86, 0x13, 0x00, + 0x58, 0x73, 0x13, 0x00, 0xb0, 0x70, 0x13, 0x00, 0xfc, 0x89, 0x13, 0x00, + 0x6c, 0x89, 0x13, 0x00, 0x8c, 0x8a, 0x13, 0x00, 0xd4, 0x8a, 0x13, 0x00, + 0xc8, 0x72, 0x13, 0x00, 0x44, 0x8a, 0x13, 0x00, 0x4c, 0x88, 0x13, 0x00, + 0x24, 0x89, 0x13, 0x00, 0xb4, 0x89, 0x13, 0x00, 0x94, 0x88, 0x13, 0x00, + 0x04, 0x88, 0x13, 0x00, 0x9c, 0x86, 0x13, 0x00, 0x68, 0x70, 0x13, 0x00, + 0xf8, 0x70, 0x13, 0x00, 0xa0, 0x73, 0x13, 0x00, 0xe8, 0x73, 0x13, 0x00, + 0x40, 0x71, 0x13, 0x00, 0x8c, 0x6e, 0x13, 0x00, 0x10, 0x73, 0x13, 0x00, + 0xd4, 0x6e, 0x13, 0x00, 0x1c, 0x6f, 0x13, 0x00, 0x98, 0x75, 0x13, 0x00, + 0x6c, 0x77, 0x13, 0x00, 0xbc, 0x75, 0x13, 0x00, 0x14, 0x84, 0x13, 0x00, + 0x90, 0x77, 0x13, 0x00, 0x94, 0x7f, 0x13, 0x00, 0x64, 0x79, 0x13, 0x00, + 0xb8, 0x7f, 0x13, 0x00, 0xa0, 0x85, 0x13, 0x00, 0x88, 0x79, 0x13, 0x00, + 0x94, 0x76, 0x13, 0x00, 0xfc, 0x77, 0x13, 0x00, 0xb8, 0x76, 0x13, 0x00, + 0x80, 0x84, 0x13, 0x00, 0x20, 0x78, 0x13, 0x00, 0x2c, 0x75, 0x13, 0x00, + 0xcc, 0x83, 0x13, 0x00, 0x48, 0x77, 0x13, 0x00, 0x4c, 0x76, 0x13, 0x00, + 0x38, 0x84, 0x13, 0x00, 0xd8, 0x77, 0x13, 0x00, 0x74, 0x75, 0x13, 0x00, + 0xf0, 0x83, 0x13, 0x00, 0x4c, 0x7f, 0x13, 0x00, 0x7c, 0x85, 0x13, 0x00, + 0x40, 0x79, 0x13, 0x00, 0x28, 0x7f, 0x13, 0x00, 0x58, 0x85, 0x13, 0x00, + 0x70, 0x76, 0x13, 0x00, 0x5c, 0x84, 0x13, 0x00, 0xe8, 0x7c, 0x13, 0x00, + 0xec, 0x84, 0x13, 0x00, 0x8c, 0x78, 0x13, 0x00, 0xc4, 0x7c, 0x13, 0x00, + 0xc8, 0x84, 0x13, 0x00, 0x68, 0x78, 0x13, 0x00, 0x48, 0x80, 0x13, 0x00, + 0xe8, 0x85, 0x13, 0x00, 0xf4, 0x79, 0x13, 0x00, 0xdc, 0x7f, 0x13, 0x00, + 0x10, 0x85, 0x13, 0x00, 0xd4, 0x78, 0x13, 0x00, 0x00, 0x80, 0x13, 0x00, + 0x34, 0x85, 0x13, 0x00, 0x1c, 0x79, 0x13, 0x00, 0x24, 0x80, 0x13, 0x00, + 0xc4, 0x85, 0x13, 0x00, 0xac, 0x79, 0x13, 0x00, 0xd0, 0x82, 0x13, 0x00, + 0x30, 0x86, 0x13, 0x00, 0x84, 0x7a, 0x13, 0x00, 0x6c, 0x80, 0x13, 0x00, + 0x0c, 0x86, 0x13, 0x00, 0x60, 0x7a, 0x13, 0x00, 0x40, 0x82, 0x13, 0x00, + 0x18, 0x7a, 0x13, 0x00, 0x60, 0x83, 0x13, 0x00, 0xcc, 0x7a, 0x13, 0x00, + 0x78, 0x86, 0x13, 0x00, 0xf0, 0x7a, 0x13, 0x00, 0x04, 0x76, 0x13, 0x00, + 0xb4, 0x77, 0x13, 0x00, 0x18, 0x83, 0x13, 0x00, 0xa8, 0x7a, 0x13, 0x00, + 0x30, 0x7d, 0x13, 0x00, 0xb0, 0x78, 0x13, 0x00, 0xb4, 0x80, 0x13, 0x00, + 0xd0, 0x79, 0x13, 0x00, 0x88, 0x82, 0x13, 0x00, 0x3c, 0x7a, 0x13, 0x00, + 0x74, 0x7e, 0x13, 0x00, 0xf8, 0x78, 0x13, 0x00, 0x38, 0x7b, 0x13, 0x00, + 0xa4, 0x84, 0x13, 0x00, 0x44, 0x78, 0x13, 0x00, 0x43, 0x61, 0x6c, 0x69, + 0x62, 0x42, 0x53, 0x58, 0x00, 0x4e, 0x56, 0x69, 0x72, 0x74, 0x00, 0x53, + 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x67, 0x17, 0x00, + 0x48, 0x6f, 0x73, 0x74, 0x00, 0xa9, 0x1a, 0xa1, 0xab, 0x55, 0x17, 0x48, + 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x00, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x20, 0x25, 0x75, 0x20, 0x6c, 0x65, 0x6e, + 0x20, 0x25, 0x75, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x25, 0x6c, 0x6c, + 0x75, 0x2e, 0x20, 0x20, 0x00, 0x25, 0x64, 0x2e, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x20, + 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x65, + 0x73, 0x74, 0x20, 0x25, 0x75, 0x2e, 0x20, 0x20, 0x00, 0x54, 0x68, 0x65, + 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, + 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x65, 0x64, 0x20, + 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, + 0x79, 0x20, 0x64, 0x6f, 0x67, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, + 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x20, 0x20, 0x45, 0x20, + 0x70, 0x6c, 0x75, 0x72, 0x69, 0x62, 0x75, 0x73, 0x20, 0x75, 0x6e, 0x75, + 0x6d, 0x2e, 0x20, 0x20, 0x43, 0x6f, 0x67, 0x69, 0x74, 0x6f, 0x20, 0x65, + 0x72, 0x67, 0x6f, 0x20, 0x73, 0x75, 0x6d, 0x2e, 0x20, 0x20, 0x56, 0x69, + 0x6e, 0x69, 0x2c, 0x20, 0x76, 0x69, 0x64, 0x69, 0x2c, 0x20, 0x76, 0x69, + 0x63, 0x69, 0x2e, 0x00, 0x49, 0x64, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x65, 0x78, 0x70, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0xbf, 0x80, 0x71, 0x31, 0x3f, 0x80, 0x71, 0x31, 0xbf, + 0xd1, 0xf7, 0x17, 0x37, 0xd1, 0xf7, 0x17, 0xb7, 0x6c, 0x6f, 0x67, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xce, 0x02, 0x00, + 0xeb, 0x3c, 0xeb, 0xae, 0x1f, 0xa4, 0xe4, 0xa1, 0xaf, 0x7b, 0x98, 0x7f, + 0x6b, 0xc8, 0x8e, 0x6d, 0x7b, 0x9d, 0xc1, 0x98, 0x02, 0x32, 0x96, 0x89, + 0x48, 0xa4, 0x10, 0xcd, 0x17, 0xce, 0xb8, 0x3c, 0x4d, 0x12, 0x4f, 0x2b, + 0x32, 0x11, 0xc0, 0x3a, 0x42, 0x15, 0x29, 0xea, 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, + 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, 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, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x91, 0x13, 0x00, 0x74, 0x91, 0x13, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x74, 0x91, 0x13, 0x00, 0x78, 0x91, 0x13, 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, + 0xc3, 0x40, 0x12, 0x00, 0x00, 0x40, 0x6b, 0x20, 0x40, 0x09, 0x0a, 0x22, + 0x80, 0x8f, 0x10, 0x00, 0x84, 0x2b, 0xe2, 0x20, 0x82, 0x00, 0x0a, 0x22, + 0x80, 0x8f, 0x13, 0x00, 0xb4, 0x92, 0xe2, 0x20, 0x82, 0x00, 0x9a, 0x08, + 0x00, 0x00, 0xdb, 0x44, 0xa0, 0x00, 0x20, 0x5c, 0xab, 0x24, 0x09, 0x39, + 0xdb, 0x44, 0xa0, 0x00, 0x20, 0x6c, 0xab, 0x24, 0x49, 0x39, 0x9e, 0x0f, + 0x8f, 0xfd, 0x6a, 0x20, 0x80, 0x02, 0x8e, 0xb8, 0x29, 0x20, 0x00, 0x80, + 0xdb, 0x42, 0xa0, 0x00, 0x1c, 0x5c, 0x6f, 0x70, 0x22, 0x20, 0x80, 0x0f, + 0x13, 0x00, 0xac, 0x94, 0x41, 0x02, 0xcf, 0xe4, 0x88, 0x9b, 0x13, 0x00, + 0xc3, 0x40, 0x12, 0x00, 0x80, 0x4b, 0xd3, 0x70, 0x12, 0x00, 0x80, 0x4b, + 0xe0, 0x7c, 0xab, 0x20, 0x8a, 0x04, 0xe0, 0x7e, 0x41, 0x88, 0x00, 0x43, + 0x00, 0x88, 0x1c, 0xba, 0x5c, 0xba, 0x08, 0xba, 0x05, 0x7a, 0x40, 0xb1, + 0x01, 0x8b, 0x02, 0x13, 0xc2, 0x00, 0x24, 0xb8, 0x04, 0xba, 0x05, 0x7a, + 0x41, 0xb1, 0x04, 0x8b, 0x43, 0x8b, 0x1c, 0xb8, 0x5c, 0xb8, 0x08, 0xb8, + 0x45, 0x78, 0xe0, 0x7f, 0x02, 0xb1, 0xe0, 0x78, 0x00, 0x10, 0xc2, 0x00, + 0x40, 0xb1, 0x01, 0x10, 0xc2, 0x00, 0x41, 0xb1, 0x02, 0x10, 0xc0, 0x00, + 0xe0, 0x7f, 0x02, 0xb1, 0xe8, 0xc3, 0xab, 0xc1, 0xcb, 0x46, 0xf0, 0x00, + 0x34, 0x00, 0x0c, 0x70, 0x14, 0xae, 0x16, 0xae, 0x15, 0xae, 0x00, 0x16, + 0x0d, 0x70, 0xa0, 0x00, 0xd8, 0x5e, 0x0a, 0xd8, 0x4c, 0x74, 0x9a, 0x4d, + 0x9e, 0x0c, 0x6f, 0xea, 0x30, 0x40, 0x08, 0x8d, 0x46, 0x8d, 0x67, 0x8d, + 0x25, 0x8d, 0x08, 0xb8, 0x08, 0xba, 0x65, 0x78, 0x45, 0x79, 0x10, 0xb8, + 0x25, 0x78, 0x35, 0xb8, 0x8c, 0x20, 0x8f, 0x83, 0xcc, 0x20, 0x82, 0x8f, + 0x00, 0x00, 0xea, 0x05, 0xcc, 0x20, 0x82, 0x8f, 0x00, 0x00, 0xd5, 0x07, + 0xcc, 0x20, 0x82, 0x8f, 0x00, 0x00, 0xdd, 0x07, 0x07, 0xf2, 0x01, 0x8e, + 0x6c, 0x20, 0x40, 0x01, 0x45, 0x20, 0xc0, 0x00, 0x01, 0xae, 0x66, 0x15, + 0x80, 0x10, 0x06, 0xe8, 0x00, 0x1e, 0x02, 0x70, 0xf0, 0x00, 0x06, 0x01, + 0x80, 0xc0, 0x7a, 0x09, 0xaf, 0xfe, 0x54, 0x25, 0xce, 0x1c, 0x00, 0x10, + 0xc0, 0x20, 0x79, 0x08, 0x32, 0x00, 0x1a, 0xd9, 0x19, 0xd9, 0xfe, 0x0b, + 0x6f, 0xea, 0xc1, 0x40, 0x7f, 0x15, 0x81, 0x10, 0x38, 0x20, 0x42, 0x00, + 0x6a, 0xc1, 0xb5, 0x08, 0x61, 0x00, 0x29, 0x1c, 0x82, 0x30, 0x67, 0xd8, + 0xb8, 0x60, 0x84, 0xc1, 0xc5, 0xff, 0x54, 0x25, 0x80, 0x1d, 0x40, 0x24, + 0x81, 0x35, 0xc3, 0xff, 0x71, 0xd8, 0xb8, 0x60, 0x40, 0x24, 0x81, 0x38, + 0xc0, 0xff, 0x75, 0x15, 0xc1, 0x10, 0x70, 0x15, 0x80, 0x10, 0x6b, 0x15, + 0x82, 0x10, 0x04, 0xb9, 0x6c, 0x20, 0xc3, 0x00, 0x41, 0x2a, 0x00, 0x01, + 0x84, 0x21, 0x3c, 0x00, 0x25, 0x78, 0x65, 0x78, 0x48, 0x30, 0x81, 0x00, + 0x7f, 0xd8, 0x17, 0xb8, 0x00, 0x31, 0x81, 0x0f, 0x75, 0x37, 0x8f, 0xc2, + 0x01, 0x31, 0x01, 0x00, 0x07, 0x30, 0x40, 0x00, 0x43, 0xc0, 0x2c, 0xf0, + 0x8e, 0x0b, 0x6f, 0xea, 0xc1, 0x40, 0x2d, 0x8d, 0x38, 0x20, 0x42, 0x00, + 0x6a, 0xc1, 0x49, 0x08, 0x61, 0x00, 0x29, 0x1c, 0x82, 0x30, 0x67, 0x15, + 0xcb, 0x10, 0x68, 0x15, 0xc1, 0x10, 0x69, 0x15, 0xc2, 0x10, 0x6a, 0x15, + 0xc3, 0x10, 0x6b, 0x15, 0xcc, 0x10, 0x6c, 0x15, 0xce, 0x10, 0x6d, 0x15, + 0xcf, 0x10, 0x6e, 0x15, 0xc0, 0x10, 0x6f, 0x15, 0xcd, 0x10, 0x10, 0x1c, + 0xc4, 0x32, 0x12, 0x1c, 0x44, 0x30, 0x14, 0x1c, 0x84, 0x30, 0x83, 0x41, + 0x6b, 0xb1, 0x8c, 0xb1, 0xcd, 0xb1, 0xf1, 0xb1, 0x12, 0xb1, 0xb3, 0xb1, + 0xc3, 0x40, 0xa1, 0x00, 0xff, 0x7f, 0xee, 0x0e, 0x4f, 0xf6, 0x43, 0x08, + 0x74, 0x02, 0x08, 0x45, 0xd6, 0x0e, 0x4f, 0xf6, 0x68, 0xbd, 0x08, 0x46, + 0xe6, 0x09, 0xaf, 0xeb, 0xaf, 0x7d, 0x23, 0x6e, 0xb8, 0x60, 0x2f, 0x79, + 0x29, 0x09, 0x24, 0x00, 0x2d, 0xd8, 0xd6, 0x09, 0x8f, 0xeb, 0xf6, 0x09, + 0xaf, 0xeb, 0xa1, 0x41, 0xa6, 0x0a, 0xaf, 0xeb, 0xa1, 0x40, 0x80, 0xc1, + 0xc3, 0x40, 0x13, 0x00, 0xf8, 0x6a, 0xca, 0x0c, 0xef, 0xe4, 0x2c, 0xda, + 0xc8, 0xc7, 0x2f, 0xd8, 0x16, 0x0e, 0x6f, 0xea, 0x2c, 0x71, 0xe0, 0x78, + 0xf1, 0xc0, 0xcb, 0x44, 0xf0, 0x00, 0x34, 0x00, 0x22, 0x94, 0xc3, 0x40, + 0x00, 0x00, 0x2e, 0x14, 0x10, 0x78, 0x47, 0x09, 0x21, 0x00, 0x1a, 0xd8, + 0xc3, 0x40, 0xa0, 0x00, 0x64, 0x88, 0xc3, 0x41, 0xa1, 0x00, 0x88, 0x27, + 0x12, 0x49, 0xc3, 0x43, 0x00, 0x00, 0x67, 0x17, 0x0d, 0x0a, 0x72, 0x00, + 0x63, 0xb4, 0xca, 0x0a, 0xef, 0xf2, 0x2c, 0x70, 0xc3, 0x40, 0x13, 0x00, + 0xf0, 0x9d, 0x22, 0x08, 0x00, 0x00, 0xc3, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xe8, 0xfa, 0x0f, 0x8f, 0xe4, 0x92, 0x0e, 0x00, 0x00, 0xd1, 0xc0, + 0xe0, 0x7e, 0xba, 0x0d, 0x6f, 0xea, 0x2c, 0x70, 0xea, 0xc3, 0xa1, 0xc1, + 0x08, 0x46, 0x07, 0xe8, 0x9a, 0x0d, 0xaf, 0xe4, 0xc1, 0x40, 0x05, 0xe8, + 0xca, 0xc7, 0x0c, 0x70, 0xca, 0xc7, 0x03, 0x8e, 0x0d, 0x08, 0xf4, 0x00, + 0x40, 0x26, 0x0d, 0x12, 0xe1, 0x86, 0x10, 0xf0, 0xa4, 0x6e, 0xcb, 0x47, + 0x10, 0x00, 0xcc, 0x2a, 0x0a, 0xf0, 0x04, 0x6d, 0xa4, 0x68, 0x08, 0xf0, + 0x4e, 0x20, 0x02, 0x20, 0x66, 0x0a, 0xef, 0xf2, 0x2c, 0x70, 0x2a, 0x45, + 0x21, 0x85, 0x00, 0x85, 0x34, 0x70, 0x30, 0x40, 0x10, 0xf2, 0x40, 0x25, + 0x11, 0x12, 0xf4, 0xf6, 0x80, 0xc3, 0x00, 0x42, 0x22, 0x40, 0x60, 0x7f, + 0x02, 0x41, 0x40, 0x20, 0xc0, 0x20, 0x6c, 0x20, 0x40, 0x00, 0x1d, 0x65, + 0x08, 0xe5, 0xee, 0xf1, 0xe3, 0xe8, 0xc3, 0x43, 0xd0, 0xba, 0xad, 0x0b, + 0xc3, 0x42, 0xad, 0x0b, 0xd0, 0xba, 0xc3, 0x41, 0x00, 0x00, 0x0b, 0x0a, + 0x0c, 0x70, 0x60, 0xa5, 0x41, 0xa5, 0x02, 0x1e, 0x43, 0x13, 0x20, 0xb6, + 0xca, 0xc7, 0xe0, 0x78, 0xe6, 0xc2, 0x0c, 0x71, 0xa6, 0x5a, 0xcb, 0x45, + 0xa0, 0x00, 0x18, 0x87, 0x02, 0xa5, 0x0c, 0x71, 0xa7, 0x5a, 0x04, 0xa5, + 0x0c, 0x71, 0xc3, 0x41, 0x12, 0x00, 0xe0, 0x55, 0xae, 0x5a, 0x08, 0x46, + 0x0c, 0x71, 0xc3, 0x41, 0x12, 0x00, 0xd4, 0x56, 0xaf, 0x5a, 0x08, 0x47, + 0x0c, 0x73, 0xa6, 0x5a, 0x03, 0xa5, 0x0c, 0x73, 0xc3, 0x41, 0x12, 0x00, + 0xb8, 0x55, 0xae, 0x5a, 0x00, 0x41, 0x0c, 0x70, 0x04, 0xee, 0x04, 0xef, + 0x79, 0x21, 0x00, 0x00, 0xc6, 0xc6, 0xe0, 0x78, 0xf1, 0xc0, 0xc3, 0x40, + 0x12, 0x00, 0x54, 0x57, 0xac, 0x5a, 0xc3, 0x41, 0xa0, 0x00, 0x30, 0x87, + 0xd1, 0xc0, 0xe0, 0x7f, 0x00, 0xa1, 0xe0, 0x78, 0xe2, 0xc2, 0x42, 0x21, + 0x3c, 0x80, 0xc3, 0x43, 0x00, 0x00, 0xff, 0xff, 0xad, 0x70, 0x15, 0xf2, + 0x40, 0x20, 0x0c, 0x07, 0xa8, 0x20, 0x40, 0x04, 0x00, 0x84, 0x1b, 0x08, + 0x81, 0x00, 0x2e, 0x8c, 0x06, 0x94, 0xc0, 0xb9, 0x84, 0x20, 0xcf, 0x8f, + 0x25, 0x7d, 0x05, 0xf2, 0x70, 0x70, 0xca, 0x23, 0x05, 0x00, 0x55, 0x24, + 0x0c, 0x1c, 0x83, 0x82, 0xbb, 0x78, 0x2c, 0x8c, 0xa1, 0xb9, 0x05, 0x79, + 0x2c, 0xac, 0x23, 0x82, 0xe2, 0x0a, 0x2f, 0xf1, 0x60, 0x40, 0xc2, 0xc6, + 0x08, 0x44, 0x42, 0x22, 0x3c, 0x80, 0x4a, 0x20, 0x00, 0x00, 0xe0, 0x7c, + 0x40, 0x21, 0x03, 0x07, 0xa8, 0x20, 0xc0, 0x01, 0xc0, 0x13, 0x01, 0x04, + 0x38, 0x21, 0x01, 0x03, 0x25, 0x78, 0xe0, 0x7e, 0xee, 0xc2, 0xcb, 0x47, + 0xf0, 0x00, 0x00, 0x01, 0x13, 0x8f, 0xcb, 0x45, 0xf0, 0x00, 0x40, 0x02, + 0x80, 0xb8, 0x13, 0xaf, 0x12, 0x8f, 0x80, 0xb8, 0x12, 0xaf, 0x11, 0x8f, + 0xa0, 0xb8, 0x11, 0xaf, 0x01, 0x85, 0x21, 0x85, 0x44, 0x20, 0x42, 0x00, + 0x50, 0x21, 0x00, 0x00, 0x45, 0x78, 0x01, 0xa5, 0x00, 0x16, 0x01, 0x70, + 0xa0, 0x00, 0x74, 0x6e, 0xc3, 0x40, 0xa0, 0x00, 0x20, 0x6c, 0x16, 0x0f, + 0x0f, 0xf6, 0xaa, 0x20, 0x49, 0x09, 0x02, 0x0f, 0x2f, 0xf6, 0xaa, 0x21, + 0x09, 0x09, 0xfa, 0x09, 0x8f, 0xfe, 0x5e, 0x0d, 0x6f, 0xfd, 0x0c, 0x70, + 0x5e, 0x0a, 0x8f, 0xfe, 0x66, 0x0a, 0x8f, 0xfe, 0xa2, 0x0a, 0x8f, 0xfe, + 0x92, 0x0a, 0x4f, 0xf0, 0x10, 0x40, 0x14, 0x70, 0xd8, 0xf2, 0xd2, 0x0c, + 0x8f, 0xfd, 0x03, 0x90, 0xcb, 0x46, 0xf0, 0x00, 0x34, 0x00, 0x04, 0xb6, + 0x0e, 0x10, 0x80, 0x20, 0x22, 0x85, 0x22, 0xb8, 0xa0, 0xb9, 0xc0, 0xb8, + 0x25, 0x78, 0x02, 0xa5, 0x02, 0x10, 0x81, 0x20, 0x08, 0x8f, 0x0f, 0x09, + 0x7f, 0x00, 0x6c, 0x20, 0x40, 0x00, 0x80, 0xb8, 0x02, 0xf0, 0x81, 0xb8, + 0x08, 0xaf, 0x56, 0x0a, 0x6f, 0xf0, 0x17, 0x1e, 0x83, 0x14, 0x2f, 0x10, + 0x81, 0x00, 0x2e, 0x10, 0x82, 0x00, 0x40, 0x29, 0x00, 0x02, 0x45, 0x78, + 0x11, 0x08, 0x80, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x20, 0x53, 0x8f, + 0xc6, 0xf7, 0x08, 0xf0, 0x00, 0x1e, 0x43, 0x70, 0xa0, 0x00, 0x9c, 0x42, + 0x8a, 0x20, 0x93, 0x0f, 0xa9, 0x5a, 0x14, 0x70, 0x92, 0xf2, 0xc3, 0x40, + 0xa0, 0x00, 0x20, 0x5c, 0xc3, 0x41, 0xa0, 0x00, 0x20, 0x6c, 0x56, 0x0d, + 0x6f, 0xea, 0x17, 0x1e, 0xc3, 0x14, 0xcb, 0x45, 0xa0, 0x00, 0xb8, 0x88, + 0x28, 0xd9, 0xc3, 0x42, 0xa0, 0x00, 0x54, 0x40, 0x56, 0x25, 0x00, 0x1c, + 0x17, 0x1e, 0x43, 0x15, 0x22, 0x0b, 0x6f, 0xf6, 0x17, 0x1e, 0x83, 0x15, + 0xc3, 0x40, 0xa0, 0x00, 0x58, 0x8d, 0xc3, 0x42, 0xa0, 0x00, 0x74, 0x40, + 0x0e, 0x0b, 0x6f, 0xf6, 0x28, 0xd9, 0xc3, 0x40, 0xa0, 0x00, 0x78, 0x90, + 0xc3, 0x42, 0xa0, 0x00, 0xec, 0x40, 0xf6, 0x09, 0xef, 0xeb, 0x20, 0xd9, + 0xc3, 0x40, 0xa0, 0x00, 0x78, 0x94, 0xc3, 0x42, 0xa0, 0x00, 0x08, 0x41, + 0xe2, 0x09, 0xef, 0xeb, 0x20, 0xd9, 0x10, 0x8f, 0x10, 0xd9, 0x80, 0xb8, + 0x10, 0xaf, 0xa1, 0x40, 0x7e, 0x0a, 0x2f, 0xf4, 0x17, 0x1e, 0xc3, 0x15, + 0xd2, 0x08, 0x20, 0x00, 0x02, 0x40, 0xab, 0x08, 0x30, 0x00, 0xad, 0x70, + 0x34, 0x58, 0x10, 0x43, 0x2e, 0x58, 0x10, 0x42, 0x3e, 0x58, 0x10, 0x41, + 0x2f, 0x58, 0x00, 0x44, 0x02, 0x40, 0x62, 0x41, 0x42, 0x42, 0xda, 0x0a, + 0x20, 0x00, 0x22, 0x43, 0x87, 0x08, 0x10, 0x00, 0x36, 0x0a, 0x0f, 0xeb, + 0x0e, 0xe8, 0x0b, 0x8e, 0x19, 0x08, 0x5f, 0x00, 0x34, 0x58, 0x10, 0x40, + 0x2e, 0x58, 0x00, 0x42, 0x30, 0xd8, 0x02, 0x41, 0x33, 0x58, 0x04, 0xe8, + 0xaa, 0x09, 0x0f, 0xeb, 0x3e, 0x0d, 0x00, 0x00, 0x2f, 0xe8, 0x91, 0xd8, + 0xde, 0x0a, 0xef, 0xf5, 0x17, 0xae, 0x14, 0x8e, 0xa9, 0xe8, 0x82, 0x0d, + 0xcf, 0xff, 0x8a, 0x20, 0x08, 0x0e, 0xaa, 0xda, 0x2c, 0x70, 0xc1, 0x68, + 0xab, 0x22, 0x08, 0x0e, 0x2b, 0x21, 0x80, 0x03, 0x08, 0x8f, 0xc3, 0x43, + 0xfa, 0x02, 0x80, 0xf0, 0xc3, 0x41, 0x31, 0x01, 0x00, 0x2d, 0xc1, 0xb8, + 0x14, 0x72, 0x55, 0xdc, 0xca, 0x21, 0xc1, 0x00, 0x01, 0x6e, 0xc9, 0x43, + 0xab, 0x24, 0x08, 0x1e, 0x2b, 0x21, 0x00, 0x00, 0xc3, 0x40, 0xa0, 0x00, + 0xe0, 0x42, 0x00, 0x88, 0xad, 0x71, 0x09, 0xe8, 0x0c, 0x75, 0x0d, 0xf0, + 0x2a, 0xd8, 0xad, 0x70, 0x14, 0xae, 0xa1, 0x40, 0xce, 0xc6, 0xc3, 0x40, + 0xa0, 0x00, 0xe1, 0x42, 0x00, 0x88, 0x7b, 0xe8, 0x0c, 0x73, 0xab, 0x22, + 0x08, 0x0e, 0x2b, 0x20, 0xc0, 0x02, 0xf5, 0xf1, 0x2e, 0xd8, 0x3a, 0x0a, + 0x6f, 0xea, 0x2c, 0x70, 0xe6, 0xc2, 0xcb, 0x45, 0xf0, 0x00, 0x34, 0x00, + 0x17, 0x1d, 0x03, 0x16, 0x2f, 0x88, 0x4d, 0x88, 0xce, 0x88, 0x8c, 0x88, + 0x08, 0xb9, 0x08, 0xba, 0x25, 0x7e, 0x85, 0x7a, 0x10, 0xbe, 0xc3, 0x43, + 0xf0, 0x00, 0x40, 0x02, 0x53, 0x22, 0xc1, 0x02, 0x45, 0x7e, 0x3a, 0xb3, + 0x2c, 0xbe, 0x95, 0x88, 0x53, 0x26, 0x4b, 0x11, 0xd7, 0x88, 0x34, 0x88, + 0x56, 0x88, 0x08, 0xbc, 0x08, 0xbe, 0x25, 0x7c, 0x05, 0x26, 0x81, 0x10, + 0x4a, 0x24, 0x40, 0x76, 0x10, 0xb9, 0x85, 0x79, 0x2d, 0x70, 0x0d, 0x71, + 0xcd, 0x70, 0x24, 0xa3, 0xa8, 0x20, 0x41, 0x02, 0x71, 0x76, 0x45, 0xf2, + 0x0f, 0x0e, 0x14, 0x14, 0x5c, 0x88, 0x3d, 0x88, 0xff, 0x88, 0x9e, 0x88, + 0x05, 0xf0, 0x58, 0x88, 0x39, 0x88, 0xfb, 0x88, 0x9a, 0x88, 0x08, 0xb9, + 0x08, 0xbf, 0x45, 0x79, 0x05, 0x27, 0x02, 0x13, 0x10, 0xba, 0x45, 0x79, + 0x01, 0x29, 0x41, 0x02, 0xc1, 0xb9, 0x34, 0x71, 0x3e, 0x00, 0x21, 0x00, + 0x34, 0x72, 0x0f, 0xf2, 0x34, 0x73, 0x1f, 0xf4, 0x2f, 0x27, 0xbf, 0x00, + 0x6f, 0x23, 0x3f, 0x00, 0x25, 0x83, 0x0f, 0x21, 0x81, 0x03, 0x25, 0xa3, + 0x2f, 0x26, 0xbf, 0x00, 0x0b, 0xf0, 0x2f, 0x27, 0xbf, 0x00, 0x6f, 0x23, + 0x3f, 0x00, 0x25, 0x83, 0x10, 0x21, 0x81, 0x03, 0x25, 0xa3, 0x2f, 0x26, + 0xbf, 0x00, 0x2c, 0x71, 0xd8, 0x79, 0x26, 0xa3, 0x0f, 0xf0, 0x00, 0x28, + 0x81, 0x13, 0x28, 0xa3, 0x0b, 0xf0, 0x2f, 0x27, 0xbf, 0x00, 0x6f, 0x23, + 0x3f, 0x00, 0x27, 0x83, 0x0f, 0x21, 0x81, 0x03, 0x27, 0xa3, 0x2f, 0x26, + 0xbf, 0x00, 0x25, 0x72, 0xc5, 0x71, 0x61, 0x40, 0xad, 0x5a, 0xa7, 0x08, + 0x30, 0x00, 0x4a, 0x24, 0x40, 0x71, 0x11, 0xd8, 0x4a, 0x21, 0x00, 0x00, + 0xa8, 0x20, 0xc0, 0x01, 0xab, 0x20, 0xd0, 0x02, 0x04, 0x71, 0xab, 0x21, + 0x88, 0x01, 0x4a, 0x24, 0x80, 0x71, 0x16, 0xdc, 0x6c, 0x71, 0x23, 0xda, + 0x0c, 0x72, 0x24, 0xd9, 0xab, 0x24, 0xd0, 0x12, 0xab, 0x23, 0x88, 0x01, + 0xab, 0x22, 0xd0, 0x02, 0xab, 0x20, 0x88, 0x01, 0xab, 0x21, 0xd0, 0x02, + 0xab, 0x20, 0x88, 0x01, 0x17, 0xd8, 0x2c, 0x74, 0xa8, 0x20, 0xc0, 0x01, + 0xab, 0x20, 0xd0, 0x02, 0x04, 0x71, 0xab, 0x21, 0x88, 0x01, 0x4a, 0x24, + 0xc0, 0x70, 0x1d, 0xdc, 0x1e, 0xdb, 0x4c, 0x73, 0x1f, 0xd8, 0xab, 0x24, + 0xd0, 0x12, 0xab, 0x21, 0x88, 0x01, 0xab, 0x23, 0xd0, 0x02, 0xab, 0x22, + 0x88, 0x01, 0xab, 0x20, 0xd0, 0x02, 0x15, 0xd8, 0xab, 0x21, 0x88, 0x01, + 0xa8, 0x20, 0xc0, 0x02, 0x40, 0x20, 0x02, 0x04, 0x42, 0x20, 0x01, 0x04, + 0x04, 0x71, 0xab, 0x22, 0xd0, 0x02, 0xab, 0x21, 0x88, 0x01, 0x28, 0xda, + 0x07, 0xd9, 0x0c, 0x71, 0xab, 0x22, 0xd0, 0x02, 0xab, 0x21, 0x88, 0x01, + 0x17, 0x1d, 0x43, 0x16, 0xc6, 0xc6, 0xb0, 0xd9, 0x0c, 0x70, 0x34, 0xad, + 0xc6, 0xc6, 0xe0, 0x78, 0xea, 0xc2, 0x30, 0x41, 0x0e, 0x71, 0x36, 0xe9, + 0x40, 0x20, 0x0f, 0x07, 0xad, 0x70, 0x45, 0xde, 0x01, 0x87, 0x1d, 0x08, + 0x92, 0x04, 0x29, 0x08, 0x90, 0x04, 0x2f, 0x08, 0x50, 0x08, 0x3b, 0x08, + 0x91, 0x08, 0x00, 0x1f, 0x80, 0x1f, 0xa0, 0x00, 0x08, 0x41, 0x1c, 0xf0, + 0x12, 0xe8, 0x2b, 0x08, 0x51, 0x04, 0x00, 0x1f, 0x80, 0x1f, 0xa0, 0x00, + 0x54, 0x40, 0x14, 0xf0, 0x00, 0x1f, 0x80, 0x1f, 0xa0, 0x00, 0x74, 0x40, + 0x0e, 0xf0, 0x00, 0x1f, 0x80, 0x1f, 0xa0, 0x00, 0xec, 0x40, 0x0a, 0xf0, + 0x00, 0x1f, 0x01, 0x10, 0x06, 0xf0, 0x0e, 0x70, 0x00, 0x1e, 0x82, 0x73, + 0xf0, 0x00, 0x49, 0x00, 0x36, 0x09, 0x6f, 0xf6, 0xe1, 0x40, 0xa5, 0x71, + 0xa9, 0x0d, 0x64, 0x94, 0x55, 0x27, 0x0f, 0x1c, 0x02, 0x40, 0xca, 0xc6, + 0xf1, 0xc0, 0xa8, 0x5a, 0x14, 0x70, 0x0c, 0x71, 0x07, 0xf4, 0x29, 0xda, + 0xc3, 0x41, 0xf0, 0x00, 0x48, 0x00, 0x0c, 0x70, 0x40, 0xa9, 0xd1, 0xc0, + 0xe0, 0x7e, 0xe0, 0x78, 0xec, 0xc2, 0x50, 0x42, 0x30, 0x41, 0x10, 0x40, + 0xcb, 0x45, 0xf0, 0x00, 0x4b, 0x00, 0x20, 0x40, 0x40, 0x41, 0x60, 0x42, + 0x80, 0x43, 0xd2, 0x0f, 0xef, 0xff, 0x00, 0x1d, 0x83, 0x16, 0x14, 0x70, + 0x0c, 0x70, 0x4f, 0xf2, 0xc3, 0x42, 0xa0, 0x00, 0x54, 0x40, 0x22, 0x40, + 0x42, 0x41, 0x1e, 0x0b, 0xef, 0xff, 0x00, 0x1d, 0xc3, 0x16, 0xc3, 0x42, + 0xa0, 0x00, 0x74, 0x40, 0x22, 0x40, 0x0e, 0x0b, 0xef, 0xff, 0x42, 0x41, + 0xcb, 0x46, 0xf0, 0x00, 0x40, 0x02, 0xc3, 0x41, 0xf0, 0x00, 0x77, 0x02, + 0xe0, 0x86, 0x2d, 0x10, 0x83, 0x20, 0x00, 0x89, 0x6c, 0x20, 0x42, 0x00, + 0x53, 0x23, 0x40, 0x00, 0x45, 0x78, 0x00, 0xa9, 0x02, 0x40, 0x22, 0x41, + 0x42, 0x42, 0x02, 0x0a, 0x20, 0x00, 0x00, 0x1d, 0x03, 0x17, 0x28, 0xbf, + 0xca, 0xbf, 0x0d, 0xe8, 0x02, 0x40, 0x22, 0x41, 0xba, 0x09, 0x20, 0x00, + 0x42, 0x42, 0x05, 0xe8, 0x85, 0x27, 0x07, 0x10, 0x03, 0xf0, 0x85, 0x27, + 0x03, 0x10, 0x22, 0x41, 0x42, 0x42, 0xf6, 0x09, 0x20, 0x00, 0x00, 0x1d, + 0x43, 0x17, 0x60, 0x86, 0x8a, 0x21, 0x18, 0x00, 0x14, 0x70, 0xc5, 0x27, + 0x42, 0x10, 0x46, 0x27, 0x02, 0x10, 0x08, 0xba, 0x04, 0x23, 0x81, 0x0f, + 0xf8, 0xff, 0xff, 0x00, 0x0c, 0x71, 0x45, 0x79, 0x20, 0xa6, 0x00, 0x1d, + 0x83, 0x17, 0xcc, 0xc6, 0xf1, 0xc0, 0xc3, 0x40, 0x13, 0x00, 0x90, 0xa9, + 0x6e, 0x0e, 0x4f, 0xfe, 0x83, 0xe8, 0xd1, 0xc0, 0xe0, 0x7e, 0x3a, 0x0f, + 0x2f, 0xea, 0x2c, 0x71, 0xe2, 0xc2, 0xc3, 0x41, 0xa0, 0x00, 0xe0, 0x42, + 0xcb, 0x45, 0xf0, 0x00, 0x34, 0x00, 0xc3, 0x40, 0xa0, 0x00, 0xe1, 0x42, + 0x00, 0x19, 0x03, 0x00, 0x17, 0x1d, 0x43, 0x14, 0xce, 0x0f, 0xef, 0xff, + 0x00, 0x18, 0x43, 0x00, 0xba, 0x0a, 0xcf, 0xff, 0x05, 0xe8, 0x92, 0xd8, + 0xde, 0x0c, 0x2f, 0xfe, 0x17, 0xad, 0x14, 0x8d, 0x83, 0xe8, 0x20, 0xd8, + 0x14, 0xad, 0xaf, 0xd8, 0x17, 0xad, 0x40, 0x58, 0xee, 0xc2, 0x70, 0x43, + 0x50, 0x41, 0x30, 0x42, 0x83, 0x0b, 0x30, 0x00, 0x10, 0x40, 0xad, 0x70, + 0xd7, 0x6d, 0x22, 0x76, 0xc1, 0x40, 0x35, 0x58, 0x0b, 0x08, 0x95, 0x00, + 0x3e, 0x1e, 0x83, 0x10, 0x05, 0xf0, 0x0b, 0x08, 0x54, 0x01, 0x3e, 0x1e, + 0xc3, 0x1f, 0x19, 0x8e, 0x40, 0x26, 0x0f, 0x17, 0xc1, 0xb8, 0x23, 0x08, + 0x71, 0x00, 0xe1, 0x40, 0x01, 0x97, 0x17, 0xe8, 0x48, 0x30, 0x00, 0x00, + 0xc3, 0x41, 0x12, 0x00, 0x64, 0x4b, 0xc1, 0x42, 0xb2, 0x5a, 0x23, 0x08, + 0x33, 0x00, 0x01, 0xaf, 0x1a, 0xf0, 0x02, 0x41, 0x9e, 0x08, 0x20, 0x00, + 0x42, 0x42, 0x09, 0xe8, 0x00, 0x41, 0x00, 0x80, 0xfe, 0xe8, 0xc0, 0xa1, + 0x03, 0xf0, 0x01, 0x1f, 0xc3, 0x1f, 0x28, 0x86, 0x0c, 0xe9, 0x21, 0x16, + 0x80, 0x10, 0xc1, 0xb8, 0x14, 0x72, 0x0c, 0x70, 0x05, 0xf4, 0x2f, 0x78, + 0x02, 0x41, 0x42, 0x42, 0x33, 0x58, 0x08, 0xa6, 0xa5, 0x71, 0x8d, 0x0d, + 0xc4, 0x94, 0x02, 0x40, 0xce, 0x0d, 0xef, 0xff, 0x42, 0x41, 0x5b, 0x0b, + 0x30, 0x20, 0x10, 0x42, 0xed, 0x70, 0xcd, 0x70, 0x11, 0xf0, 0x35, 0x58, + 0x10, 0x40, 0xa1, 0x40, 0x3a, 0x58, 0x35, 0x58, 0x0c, 0x20, 0x00, 0xa0, + 0xe1, 0x40, 0x56, 0xf7, 0xa1, 0x40, 0x3a, 0x58, 0x35, 0x58, 0x3e, 0x1d, + 0x02, 0x10, 0x0c, 0x71, 0x0e, 0xf0, 0x17, 0x6e, 0x00, 0x21, 0x0d, 0xa0, + 0x09, 0xf2, 0xa1, 0x40, 0x3a, 0x58, 0x07, 0xe8, 0x19, 0x8d, 0xc1, 0xb8, + 0xcf, 0x08, 0x71, 0x80, 0xa1, 0x40, 0xe1, 0x40, 0xc5, 0x71, 0x72, 0x76, + 0x3c, 0x26, 0xcf, 0x14, 0xca, 0x26, 0x26, 0x10, 0x04, 0x7f, 0xad, 0xf7, + 0xeb, 0xe8, 0x42, 0x40, 0xce, 0xc6, 0xe0, 0x78, 0xe2, 0xc2, 0x61, 0x88, + 0x08, 0x45, 0x40, 0x2b, 0x80, 0x07, 0x42, 0x28, 0xbe, 0x87, 0x0e, 0x00, + 0x24, 0x00, 0x80, 0x8d, 0x81, 0x40, 0x3d, 0x58, 0x07, 0xf0, 0xc1, 0xbb, + 0x0b, 0x0b, 0xb1, 0x00, 0x0c, 0x70, 0x81, 0x40, 0x33, 0x58, 0x00, 0xa5, + 0xc2, 0xc6, 0xe0, 0x78, 0x8d, 0x70, 0x17, 0xea, 0x2d, 0x10, 0x83, 0x00, + 0x27, 0x0b, 0x70, 0x00, 0x0a, 0x24, 0x80, 0x70, 0x3c, 0x49, 0xc3, 0x42, + 0xa0, 0x00, 0x08, 0x41, 0xa8, 0x20, 0xc0, 0x02, 0x20, 0x80, 0x0f, 0x09, + 0x81, 0x00, 0x34, 0x88, 0x07, 0x09, 0x9f, 0x00, 0x8d, 0x71, 0x55, 0x20, + 0x00, 0x0c, 0xe0, 0x7f, 0x81, 0x40, 0xe0, 0x78, 0x2d, 0x10, 0x80, 0x00, + 0x0f, 0x08, 0x51, 0x00, 0xc3, 0x40, 0xa0, 0x00, 0x54, 0x40, 0x21, 0x01, + 0xcf, 0xff, 0xc3, 0x40, 0xa0, 0x00, 0x08, 0x41, 0x15, 0x01, 0xcf, 0xff, + 0xc3, 0x40, 0xa0, 0x00, 0x74, 0x40, 0x0d, 0x01, 0xcf, 0xff, 0xe0, 0x78, + 0xc3, 0x42, 0xf0, 0x00, 0x4b, 0x00, 0x1b, 0xd9, 0x0c, 0x70, 0x00, 0x1a, + 0xc3, 0x07, 0xab, 0x21, 0xd0, 0x02, 0xab, 0x20, 0x88, 0x01, 0xc3, 0x40, + 0xf0, 0x00, 0x20, 0x01, 0x20, 0xd9, 0x26, 0xa0, 0x20, 0xa0, 0x6f, 0x26, + 0xff, 0x05, 0x90, 0xd9, 0x0c, 0x71, 0xe0, 0x7f, 0x20, 0xaa, 0x00, 0x00, + 0x2b, 0x66, 0x00, 0x00, 0x00, 0x00, 0x67, 0x17, 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, + 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x69, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x51, 0x01, 0x00, 0x2e, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x49, 0x03, + 0x54, 0x3b, 0x11, 0x00, 0x70, 0x91, 0x13, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x58, 0x87, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x74, 0x91, 0x13, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x87, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x6c, 0xa0, 0x00, 0x63, 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0xfc, + 0x23, 0x10, 0x00, 0xcc, 0x02, 0x04, 0x54, 0x22, 0x10, 0x00, 0xb4, 0xff, + 0x11, 0x00, 0xb8, 0xe2, 0x00, 0x00, 0x10, 0x00, 0xac, 0x00, 0x12, 0x00, + 0x40, 0x36, 0x11, 0x00, 0x18, 0xa0, 0x11, 0x00, 0x50, 0x39, 0x00, 0x00, + 0x11, 0x00, 0x04, 0x3a, 0x11, 0x00, 0x84, 0xa1, 0x11, 0x00, 0xf4, 0xa3, + 0x11, 0x00, 0xc8, 0x67, 0x00, 0x00, 0x13, 0x00, 0x04, 0xa4, 0x11, 0x00, + 0x00, 0xa2, 0x11, 0x00, 0x80, 0x1d, 0x12, 0x00, 0x28, 0x1e, 0x00, 0x08, + 0x12, 0x00, 0x58, 0x1f, 0x12, 0x00, 0x2c, 0x0a, 0x12, 0x00, 0x04, 0x02, + 0x04, 0xf4, 0x09, 0x12, 0x00, 0x02, 0x00, 0xdc, 0x02, 0x04, 0x34, 0x6c, + 0x12, 0x00, 0xa4, 0x01, 0x12, 0x00, 0xe8, 0x00, 0x12, 0x00, 0xe0, 0x67, + 0x00, 0x00, 0x12, 0x00, 0x68, 0x04, 0x12, 0x00, 0xb4, 0x9f, 0x11, 0x00, + 0x10, 0x80, 0x11, 0x00, 0x6c, 0x6a, 0x80, 0x0c, 0x13, 0x00, 0x80, 0x4b, + 0x12, 0x00, 0xc0, 0x02, 0x04, 0x00, 0x4c, 0x02, 0x6c, 0x02, 0x04, 0x34, + 0x27, 0x10, 0x00, 0xa0, 0x2c, 0x00, 0x4d, 0x12, 0x00, 0x20, 0x02, 0x04, + 0x40, 0x02, 0x04, 0x88, 0x63, 0x02, 0x24, 0x02, 0x18, 0xc0, 0x02, 0x04, + 0x9c, 0x24, 0x08, 0xa0, 0x10, 0x00, 0x60, 0x02, 0x14, 0x34, 0x47, 0x13, + 0x00, 0x8c, 0x13, 0x11, 0x00, 0xa0, 0x02, 0x04, 0xb8, 0x02, 0x04, 0x20, + 0x80, 0x94, 0xae, 0x11, 0x00, 0x3c, 0x02, 0x04, 0xf4, 0x7e, 0x11, 0x00, + 0x2c, 0x1a, 0x12, 0x00, 0xb0, 0x02, 0x04, 0xb2, 0x00, 0xbc, 0x02, 0x04, + 0x54, 0x1b, 0x02, 0x7c, 0x02, 0x04, 0x18, 0x02, 0x0c, 0x3c, 0x6b, 0x12, + 0x00, 0xfc, 0x18, 0x12, 0x00, 0xa0, 0x0c, 0xd8, 0x19, 0x12, 0x00, 0x94, + 0x02, 0x10, 0x14, 0x02, 0x0c, 0xf0, 0x17, 0x02, 0x74, 0x02, 0xec, 0x04, + 0x09, 0x13, 0x00, 0x02, 0xa8, 0x84, 0x02, 0x5c, 0xd4, 0x1d, 0x13, 0x00, + 0x4c, 0x1a, 0x13, 0x00, 0xdc, 0x02, 0x04, 0x28, 0x02, 0x04, 0x78, 0x02, + 0x04, 0x0c, 0x12, 0xec, 0x97, 0x02, 0xb8, 0x02, 0x04, 0x4c, 0x36, 0x13, + 0x00, 0xfc, 0x02, 0x20, 0x34, 0x75, 0x02, 0x64, 0x69, 0x11, 0x00, 0x00, + 0x08, 0x7c, 0x96, 0x12, 0x00, 0x54, 0x67, 0x10, 0x00, 0xc0, 0x66, 0x10, + 0x02, 0xd8, 0x10, 0x00, 0xfc, 0x68, 0x28, 0xa8, 0x10, 0x00, 0x0c, 0x02, + 0x10, 0x4c, 0x02, 0x08, 0x20, 0x69, 0x10, 0x00, 0x68, 0x02, 0x08, 0xd8, + 0x02, 0x04, 0x2c, 0x02, 0x04, 0x2a, 0x21, 0x14, 0x02, 0x04, 0xa4, 0x02, + 0x44, 0xc4, 0x02, 0x04, 0x0c, 0x9c, 0x12, 0x24, 0x61, 0x13, 0x00, 0x44, + 0x02, 0x04, 0x48, 0xf5, 0x08, 0x0a, 0x11, 0x00, 0xc0, 0x12, 0x38, 0x40, + 0x24, 0x12, 0x00, 0x4c, 0x02, 0x04, 0x60, 0x02, 0x04, 0xcc, 0x26, 0x12, + 0x00, 0x82, 0x82, 0xf0, 0x02, 0x04, 0x30, 0x27, 0x12, 0x00, 0xa8, 0x02, + 0x04, 0xc8, 0x02, 0x04, 0x00, 0x29, 0x12, 0x00, 0x98, 0x02, 0x04, 0x0a, + 0x0a, 0xec, 0x02, 0x04, 0xfc, 0x02, 0x04, 0x50, 0x2a, 0x12, 0x00, 0x60, + 0x02, 0x04, 0xdc, 0x02, 0x04, 0xc4, 0x37, 0x12, 0x00, 0x40, 0x08, 0xf4, + 0x5d, 0x12, 0x00, 0x14, 0x69, 0x12, 0x5c, 0x38, 0x12, 0x00, 0xec, 0x02, + 0x04, 0x94, 0x39, 0x12, 0x00, 0x2a, 0x08, 0xa0, 0x02, 0x04, 0xb8, 0x02, + 0x04, 0xc4, 0x02, 0x04, 0x88, 0x3a, 0x12, 0x00, 0xac, 0x02, 0x04, 0x24, + 0x3c, 0x12, 0x00, 0xca, 0x2c, 0xbc, 0x02, 0x04, 0xa4, 0x02, 0x68, 0xe0, + 0x31, 0x02, 0x68, 0x02, 0x04, 0x04, 0x32, 0x02, 0x3c, 0x02, 0x04, 0x80, + 0x02, 0x04, 0x00, 0x33, 0xab, 0x2a, 0x12, 0xc8, 0x02, 0x1c, 0x30, 0x02, + 0x04, 0x34, 0x02, 0x04, 0x58, 0x02, 0x88, 0xa8, 0x02, 0x14, 0xd8, 0x02, + 0x04, 0xfc, 0x02, 0x04, 0x00, 0x35, 0x83, 0xaa, 0x12, 0xe4, 0x02, 0x04, + 0x30, 0x36, 0x12, 0x00, 0x84, 0x02, 0x04, 0x94, 0x02, 0x04, 0xdc, 0x02, + 0x04, 0x08, 0x02, 0x84, 0x10, 0x02, 0x04, 0x2a, 0x10, 0x1c, 0x02, 0x04, + 0x40, 0x02, 0x04, 0x90, 0x02, 0x04, 0xa0, 0xf3, 0x11, 0x00, 0x95, 0x00, + 0x0d, 0x01, 0xb4, 0x6e, 0xa0, 0xa4, 0x00, 0x00, 0xbc, 0x02, 0x04, 0xf4, + 0x8b, 0x22, 0x3c, 0x8d, 0x12, 0x50, 0x8e, 0x13, 0x00, 0xe0, 0xb5, 0xa0, + 0x00, 0x03, 0x00, 0x01, 0x4b, 0x00, 0x00, 0x6f, 0x7f, 0x40, 0xff, 0x01, + 0x02, 0x2f, 0x08, 0x1f, 0x13, 0x00, 0x60, 0x99, 0xa0, 0xc0, 0x84, 0x00, + 0xe0, 0xbd, 0xa0, 0x00, 0xd0, 0x02, 0x2c, 0x02, 0x13, 0x00, 0xc4, 0x06, + 0x08, 0xe0, 0xb6, 0xa0, 0x00, 0x02, 0x24, 0x12, 0xdc, 0x50, 0x03, 0x14, + 0x20, 0xb8, 0x09, 0x0c, 0xff, 0xff, 0x00, 0x00, 0x04, 0x03, 0x15, 0x0a, + 0x04, 0x03, 0x14, 0x03, 0x0a, 0x10, 0x03, 0x0b, 0x1f, 0xe8, 0x03, 0x14, + 0x02, 0x40, 0x03, 0x0b, 0x08, 0x04, 0x03, 0x14, 0x04, 0x00, 0x40, 0x00, + 0x00, 0x80, 0x08, 0x13, 0x00, 0x05, 0x14, 0x09, 0x10, 0x03, 0x0a, 0xff, + 0xff, 0x0f, 0x14, 0x03, 0x14, 0x0f, 0x04, 0x0f, 0x10, 0x0f, 0x10, 0x0f, + 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x03, + 0x10, 0x03, 0xa8, 0x03, 0x08, 0x07, 0x04, 0x07, 0x10, 0xff, 0xff, 0x07, + 0x08, 0x0f, 0x18, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x48, 0x0f, + 0x08, 0x07, 0x10, 0x0f, 0x30, 0x0b, 0x18, 0x0b, 0x0c, 0x07, 0x28, 0x03, + 0x08, 0x03, 0x18, 0x03, 0x04, 0x07, 0x0c, 0xff, 0xff, 0x03, 0x08, 0x07, + 0x04, 0x07, 0x18, 0x0f, 0x10, 0x03, 0x10, 0x0b, 0x1c, 0x0b, 0x0c, 0x03, + 0x1c, 0x03, 0x04, 0x0f, 0x14, 0x0f, 0x10, 0x0b, 0x24, 0x0f, 0x1c, 0x07, + 0x10, 0x07, 0x08, 0x0b, 0x2c, 0xff, 0xff, 0x03, 0x0c, 0x0f, 0x04, 0x0f, + 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, + 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, + 0x10, 0x0f, 0x10, 0xff, 0xff, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, + 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, + 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x0b, 0x10, 0x13, + 0xf4, 0x70, 0xfb, 0x04, 0x00, 0x00, 0x10, 0x02, 0x02, 0x08, 0x17, 0x06, + 0x14, 0x04, 0x4b, 0x69, 0x03, 0x14, 0x01, 0x08, 0x22, 0x05, 0x09, 0x03, + 0x14, 0x4f, 0x50, 0x0f, 0x14, 0xff, 0xf8, 0x03, 0x2a, 0x0f, 0x14, 0x09, + 0x14, 0x02, 0x62, 0x02, 0x7d, 0x03, 0x10, 0x03, 0x04, 0x05, 0x28, 0x00, + 0x01, 0x00, 0x72, 0x17, 0x03, 0x10, 0x03, 0x04, 0x0f, 0x14, 0x09, 0x14, + 0xfd, 0xc5, 0x42, 0xc8, 0x02, 0x03, 0x0e, 0x05, 0x04, 0x05, 0x28, 0x0f, + 0x14, 0x53, 0x2c, 0x0f, 0x14, 0x0f, 0x14, 0x00, 0x57, 0x04, 0x01, 0x00, + 0x20, 0x05, 0x4c, 0x03, 0x06, 0xc3, 0xfc, 0x05, 0x50, 0x0f, 0xa0, 0x00, + 0x00, 0x05, 0x00, 0x02, 0xa0, 0x5e, 0x40, 0x05, 0x00, 0x02, 0x64, 0x0f, + 0x14, 0x0f, 0x14, 0x55, 0xb8, 0x1f, 0x54, 0x02, 0x61, 0xf4, 0xff, 0x00, + 0x08, 0x0f, 0x78, 0x04, 0x03, 0xa3, 0x02, 0x05, 0x03, 0x88, 0x03, 0x04, + 0x06, 0x8c, 0x03, 0x0b, 0x08, 0x04, 0x05, 0x14, 0x0f, 0x78, 0x03, 0x39, + 0x0f, 0x14, 0x03, 0x14, 0xff, 0xff, 0x08, 0x37, 0x04, 0x09, 0x0f, 0x3c, + 0x03, 0x15, 0x0f, 0x14, 0x09, 0x14, 0x03, 0x0a, 0x09, 0x04, 0x0f, 0x28, + 0x03, 0x1a, 0x0f, 0x14, 0x09, 0x14, 0x12, 0xca, 0x1f, 0xcc, 0x03, 0x8f, + 0x0f, 0xdc, 0xfb, 0x17, 0x0f, 0x14, 0x15, 0x2c, 0x01, 0x12, 0x6a, 0x03, + 0x4b, 0x04, 0x04, 0x05, 0x64, 0x12, 0x2a, 0x1f, 0xa4, 0x0e, 0x3c, 0x02, + 0x2d, 0x01, 0x02, 0x04, 0x00, 0xdc, 0x6f, 0x80, 0x3a, 0xa0, 0x00, 0x24, + 0x72, 0xa0, 0x00, 0xe4, 0x02, 0x08, 0xe0, 0x02, 0x04, 0x5e, 0x02, 0x04, + 0x02, 0x18, 0x04, 0x7a, 0x38, 0xae, 0x00, 0x68, 0xa0, 0x00, 0x68, 0xad, + 0xa0, 0x00, 0x5c, 0x71, 0xa0, 0x00, 0x54, 0x02, 0x04, 0xa8, 0x05, 0x1c, + 0x04, 0x38, 0xec, 0x55, 0xab, 0x02, 0x0c, 0x2c, 0x02, 0x38, 0xf4, 0x02, + 0x08, 0xf0, 0x02, 0x04, 0x60, 0x02, 0x04, 0x07, 0x38, 0x48, 0x02, 0x38, + 0xfc, 0x02, 0x10, 0x64, 0x02, 0x04, 0x3a, 0xa8, 0x62, 0x02, 0x04, 0x54, + 0x02, 0x04, 0x02, 0x1c, 0x04, 0x38, 0x04, 0x70, 0xa0, 0x00, 0x34, 0x02, + 0x38, 0x0c, 0x02, 0x08, 0x08, 0x02, 0x04, 0x56, 0x55, 0x66, 0x05, 0x1c, + 0x04, 0x70, 0x58, 0x02, 0x38, 0x74, 0x02, 0x70, 0x6c, 0x02, 0x6c, 0x64, + 0x02, 0x04, 0xac, 0x0a, 0x1c, 0x68, 0x02, 0x1c, 0x3c, 0x55, 0x55, 0x02, + 0x38, 0x18, 0x02, 0x34, 0x14, 0x02, 0x04, 0x68, 0x0a, 0x1c, 0x88, 0x02, + 0x1c, 0x54, 0x02, 0x1c, 0x28, 0x02, 0x18, 0x24, 0x02, 0x04, 0x6a, 0x55, + 0x2d, 0x0a, 0x1c, 0xa8, 0x02, 0x1c, 0xb8, 0x02, 0x04, 0x74, 0x02, 0x20, + 0x6c, 0x02, 0x04, 0x34, 0x02, 0x20, 0x02, 0x8c, 0x02, 0x02, 0x04, 0x00, + 0x8c, 0x55, 0x57, 0x02, 0x10, 0x3c, 0x02, 0x10, 0x6e, 0x02, 0x30, 0x6c, + 0x02, 0x04, 0x55, 0x02, 0x04, 0x02, 0x18, 0x04, 0xa8, 0x44, 0x02, 0x18, + 0x80, 0x02, 0x8c, 0x7c, 0x35, 0xa0, 0x02, 0x88, 0x74, 0x02, 0x04, 0xb0, + 0x05, 0x1c, 0x22, 0xd7, 0x00, 0x00, 0x28, 0xb0, 0xa0, 0x00, 0xd8, 0x02, + 0x54, 0x9c, 0x02, 0x40, 0xba, 0xaa, 0x94, 0x02, 0x04, 0x4c, 0x02, 0x2c, + 0x02, 0x38, 0x04, 0x1c, 0x3c, 0x02, 0x1c, 0xe8, 0x02, 0x1c, 0xac, 0x02, + 0x18, 0xa4, 0x02, 0x04, 0x54, 0x0a, 0x1c, 0xaa, 0x56, 0x50, 0x02, 0x1c, + 0xf8, 0x02, 0x1c, 0xbc, 0x02, 0x18, 0xb4, 0x02, 0x04, 0x5c, 0x05, 0x1c, + 0x04, 0x70, 0x64, 0x02, 0x0c, 0xc4, 0x02, 0x14, 0x6c, 0x35, 0xa8, 0x02, + 0x08, 0x68, 0x02, 0x04, 0x70, 0x05, 0x70, 0x14, 0x18, 0x08, 0xaf, 0xa0, + 0x00, 0x8c, 0x02, 0x8c, 0x8c, 0x02, 0x88, 0x84, 0x02, 0x04, 0xaa, 0x5a, + 0xb4, 0x0a, 0x1c, 0x18, 0x02, 0x1c, 0x98, 0x02, 0x1c, 0x9c, 0x02, 0x18, + 0x94, 0x02, 0x04, 0xb8, 0x05, 0x1c, 0x04, 0x8c, 0x64, 0x02, 0x70, 0xa4, + 0xd5, 0xaa, 0x02, 0x1c, 0xac, 0x02, 0x18, 0xa4, 0x02, 0x04, 0xbc, 0x05, + 0x1c, 0x04, 0x54, 0x28, 0x02, 0x38, 0x7c, 0x02, 0x68, 0x74, 0x02, 0x14, + 0x72, 0x02, 0x04, 0xae, 0x6a, 0x56, 0x02, 0x04, 0x02, 0xc4, 0x04, 0x8c, + 0x88, 0x02, 0x18, 0xcc, 0x02, 0x8c, 0x90, 0x02, 0x08, 0x8c, 0x02, 0x04, + 0x76, 0x05, 0x1c, 0x94, 0x3b, 0xc8, 0x55, 0x57, 0x02, 0x50, 0x98, 0x02, + 0x14, 0x7a, 0x02, 0x14, 0x78, 0x02, 0x04, 0x57, 0x02, 0x04, 0x02, 0x38, + 0x04, 0x54, 0x68, 0x02, 0x54, 0xa4, 0x02, 0x1c, 0x7e, 0xb5, 0xaa, 0x02, + 0x14, 0x7c, 0x02, 0x04, 0x58, 0x02, 0x04, 0x07, 0x1c, 0x88, 0x02, 0x1c, + 0xd4, 0x02, 0x3c, 0xbc, 0x02, 0x88, 0xb4, 0x02, 0x04, 0xc0, 0x05, 0x1c, + 0x55, 0xad, 0x04, 0x70, 0xac, 0x02, 0x34, 0xb0, 0x02, 0x04, 0x82, 0x02, + 0x14, 0x80, 0x02, 0x04, 0x59, 0x02, 0x04, 0x07, 0x38, 0x98, 0x02, 0x38, + 0xb4, 0x02, 0x1c, 0xea, 0xaa, 0x86, 0x02, 0x14, 0x84, 0x02, 0x04, 0x5a, + 0x02, 0x04, 0x02, 0x1c, 0x04, 0x38, 0xbc, 0x02, 0x18, 0xd4, 0x02, 0xa8, + 0xc4, 0x02, 0x08, 0xc0, 0x02, 0x04, 0x16, 0x40, 0x88, 0x05, 0x1c, 0x04, + 0x8c, 0xa8, 0x02, 0x38, 0x20, 0xb4, 0xa0, 0x00, 0x30, 0xb1, 0xa0, 0x00, + 0x10, 0x02, 0x04, 0xb8, 0x57, 0x55, 0x02, 0x10, 0x02, 0x38, 0x04, 0x1c, + 0xc8, 0x02, 0x0c, 0xdc, 0x02, 0x38, 0xd0, 0x02, 0x34, 0xcc, 0x02, 0x04, + 0x8a, 0x0a, 0x38, 0xd8, 0x02, 0x1c, 0xec, 0x55, 0x55, 0x02, 0xa8, 0xdc, + 0x02, 0xa4, 0xd4, 0x02, 0x04, 0xc8, 0x0a, 0x1c, 0xe8, 0x02, 0x1c, 0xe4, + 0x02, 0x38, 0xdc, 0x02, 0x34, 0xd8, 0x02, 0x04, 0x8c, 0x55, 0x55, 0x0a, + 0x1c, 0xf8, 0x02, 0x1c, 0xec, 0x02, 0x1c, 0xe8, 0x02, 0x18, 0xe4, 0x02, + 0x04, 0x8e, 0x0a, 0x1c, 0x08, 0x12, 0x88, 0xf4, 0x02, 0x1c, 0xf0, 0xb5, + 0xaa, 0x02, 0x18, 0xec, 0x02, 0x04, 0x90, 0x05, 0x1c, 0x04, 0xc4, 0xf8, + 0x02, 0x10, 0xfc, 0x02, 0x1c, 0x00, 0x02, 0x6c, 0xfc, 0x02, 0x0c, 0x92, + 0x0a, 0x1c, 0xb2, 0x56, 0x08, 0x02, 0x14, 0x04, 0x73, 0x02, 0xc0, 0x02, + 0x08, 0x0c, 0x02, 0x04, 0x94, 0x05, 0x1c, 0x24, 0xbc, 0x0c, 0x02, 0x18, + 0x14, 0x02, 0x14, 0x98, 0x75, 0x55, 0x02, 0x14, 0x96, 0x02, 0x04, 0x5b, + 0x02, 0x04, 0x02, 0xe0, 0x04, 0x54, 0x1c, 0x02, 0x18, 0x10, 0x22, 0x68, + 0x0c, 0x02, 0x58, 0x04, 0x02, 0x04, 0xd4, 0x55, 0x55, 0x0a, 0x1c, 0x24, + 0x02, 0x1c, 0x14, 0x02, 0x3c, 0x2c, 0x02, 0x08, 0x28, 0x02, 0x04, 0x9a, + 0x0a, 0x1c, 0x34, 0x02, 0x10, 0x1c, 0x02, 0x38, 0x1c, 0xb5, 0xaa, 0x02, + 0x34, 0x14, 0x02, 0x04, 0xd8, 0x05, 0x1c, 0x14, 0x34, 0x18, 0x02, 0xc4, + 0x3c, 0x02, 0x20, 0x9e, 0x02, 0x14, 0x9c, 0x02, 0x04, 0x5c, 0x02, 0x04, + 0xab, 0xba, 0x02, 0x70, 0x04, 0x8c, 0x1c, 0x02, 0x50, 0x40, 0x02, 0x1c, + 0xa2, 0x02, 0x14, 0xa0, 0x02, 0x04, 0x5d, 0x02, 0x04, 0x02, 0x1c, 0x04, + 0x8c, 0x48, 0x02, 0x18, 0xaa, 0xf1, 0x24, 0x02, 0x20, 0x50, 0x02, 0x08, + 0x4c, 0x02, 0x04, 0xa4, 0x02, 0x1c, 0x45, 0xa4, 0x01, 0x00, 0xef, 0x42, + 0xc0, 0x02, 0x28, 0x04, 0x03, 0x04, 0x65, 0xf1, 0xff, 0x02, 0x0a, 0x3c, + 0xe7, 0x11, 0x66, 0x68, 0x0f, 0x20, 0x02, 0x1d, 0x02, 0x03, 0x0f, 0x20, + 0x02, 0x13, 0x04, 0x03, 0x07, 0x40, 0x03, 0x0d, 0x0f, 0x60, 0x03, 0x14, + 0x07, 0x20, 0xf7, 0xfd, 0x07, 0x40, 0x53, 0x35, 0x0b, 0x80, 0x06, 0x03, + 0x25, 0x06, 0x04, 0x0f, 0x40, 0x03, 0x17, 0x0f, 0x40, 0x04, 0x52, 0x75, + 0x0b, 0x40, 0x0f, 0x20, 0x0f, 0x20, 0x07, 0x20, 0x03, 0x4c, 0xff, 0xff, + 0x0f, 0x60, 0x03, 0x14, 0x07, 0x20, 0x07, 0xa0, 0x0f, 0x40, 0x0f, 0x20, + 0x0f, 0x20, 0x07, 0x20, 0x03, 0x4c, 0x0f, 0x60, 0x03, 0x14, 0x07, 0x20, + 0x07, 0x60, 0x1f, 0x00, 0x1f, 0x00, 0x0f, 0x60, 0xff, 0xbb, 0x0f, 0x40, + 0x0f, 0x20, 0x07, 0x20, 0x03, 0x6c, 0x0f, 0x80, 0x03, 0x14, 0x07, 0x20, + 0x0f, 0x80, 0x03, 0x1c, 0x03, 0x04, 0x0a, 0x03, 0x05, 0x06, 0x04, 0x03, + 0x40, 0x05, 0x1f, 0x60, 0xff, 0xff, 0x06, 0x1c, 0x03, 0x07, 0x0f, 0x20, + 0x03, 0x14, 0x07, 0x60, 0x03, 0x0c, 0x03, 0x20, 0x0f, 0xe0, 0x0f, 0x60, + 0x0f, 0xc0, 0x07, 0x40, 0x0f, 0xa0, 0x03, 0x50, 0x03, 0x04, 0x0f, 0x40, + 0x0f, 0x40, 0xff, 0xcf, 0x0f, 0x40, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, + 0x07, 0x20, 0x03, 0x6c, 0x03, 0xc0, 0x0f, 0x20, 0x07, 0x20, 0x07, 0xa0, + 0x1f, 0x20, 0x07, 0x20, 0x10, 0x75, 0x35, 0x40, 0x1f, 0x00, 0xff, 0xfe, + 0x0f, 0xc0, 0x0f, 0x40, 0x07, 0x40, 0x07, 0x80, 0x0f, 0x40, 0x0f, 0x40, + 0x0f, 0x20, 0x0f, 0x20, 0x02, 0x1e, 0xc0, 0x2f, 0x60, 0x0f, 0x40, 0x0f, + 0x40, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0xff, 0xff, 0x0f, 0x20, 0x0f, + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x1f, 0x20, 0x1f, 0x20, 0x0f, + 0x20, 0x0f, 0x20, 0x0f, 0x60, 0x0f, 0x60, 0x0f, 0x20, 0x0f, 0x20, 0x2f, + 0x00, 0x07, 0x60, 0x27, 0x00, 0xff, 0xff, 0x0f, 0x20, 0x0f, 0x20, 0x0f, + 0x20, 0x07, 0x20, 0x17, 0xe0, 0x0f, 0x20, 0x07, 0x20, 0x0f, 0x60, 0x03, + 0x30, 0x03, 0x04, 0x0f, 0x20, 0x0f, 0x40, 0x0f, 0x20, 0x1f, 0x20, 0x07, + 0x20, 0x27, 0xa0, 0xff, 0xff, 0x0f, 0x20, 0x07, 0x20, 0x03, 0x6c, 0x33, + 0x00, 0x2f, 0x40, 0x2f, 0x40, 0x1f, 0x40, 0x1f, 0x40, 0x0f, 0x20, 0x0f, + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, + 0x20, 0xff, 0xff, 0x0f, 0x20, 0x0f, 0x20, 0x1f, 0x40, 0x17, 0x00, 0x1f, + 0x80, 0x13, 0x10, 0x03, 0x04, 0x0f, 0x20, 0x0f, 0x40, 0x0f, 0x20, 0x0f, + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0xff, + 0xff, 0x0f, 0xe0, 0x0f, 0xe0, 0x1f, 0xe0, 0x07, 0x40, 0x03, 0xcc, 0x13, + 0xe0, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x80, 0x07, 0x20, 0x1f, 0x20, 0x03, + 0x50, 0x03, 0x04, 0x0f, 0x20, 0x0f, 0x40, 0x0f, 0x20, 0xff, 0xff, 0x0f, + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xc0, 0x07, 0x20, 0x2f, + 0xe0, 0x03, 0x9c, 0x03, 0x04, 0x07, 0x20, 0x03, 0x0c, 0x13, 0x00, 0x2f, + 0xe0, 0x2f, 0xe0, 0x1f, 0x60, 0x1f, 0x60, 0xaf, 0xa0, 0x0f, 0x20, 0x0b, + 0x20, 0x02, 0x64, 0x08, 0x6f, 0x1c, 0xa2, 0x54, 0x78, 0x92, 0xd4, 0xe0, + 0xb2, 0xa0, 0x00, 0xa0, 0x02, 0x04, 0x4c, 0x92, 0xd8, 0x5e, 0x41, 0x44, + 0x02, 0x04, 0x02, 0x24, 0x03, 0x03, 0x08, 0x28, 0x2c, 0x02, 0x28, 0x98, + 0x02, 0x28, 0x60, 0xb3, 0xa0, 0x00, 0x20, 0x02, 0x04, 0x64, 0xbd, 0xaa, + 0x02, 0x24, 0x5c, 0x02, 0x04, 0x03, 0x25, 0x02, 0x04, 0x08, 0x28, 0x38, + 0x02, 0x28, 0xc8, 0x02, 0x28, 0xe0, 0x02, 0x24, 0xa0, 0x02, 0x04, 0x84, + 0x02, 0x24, 0x5e, 0x55, 0x7c, 0x02, 0x04, 0x02, 0x24, 0x03, 0x03, 0x08, + 0x28, 0xc4, 0x92, 0xe8, 0xe0, 0xb2, 0x48, 0xb0, 0xb2, 0x7c, 0x80, 0x02, + 0x04, 0xcc, 0x92, 0xfc, 0xc4, 0xaf, 0xaa, 0x02, 0x04, 0x03, 0x25, 0x02, + 0x04, 0x08, 0x28, 0xcc, 0x02, 0x28, 0xf8, 0x02, 0x28, 0x10, 0x02, 0x9c, + 0xe0, 0x02, 0x28, 0xec, 0x02, 0x24, 0xe4, 0x02, 0x04, 0x57, 0xd5, 0x02, + 0x24, 0x03, 0x03, 0x08, 0x28, 0xd0, 0x02, 0x28, 0x04, 0x02, 0x78, 0x70, + 0x02, 0x28, 0x40, 0x02, 0x04, 0xfc, 0x02, 0x24, 0xf4, 0x02, 0x04, 0x03, + 0x25, 0x53, 0xbb, 0x13, 0x50, 0x02, 0x29, 0x10, 0x00, 0xfa, 0x44, 0x50, + 0x02, 0x4c, 0x5c, 0x02, 0x58, 0x03, 0x20, 0x28, 0x02, 0x38, 0x03, 0x08, + 0x07, 0x04, 0x04, 0xc4, 0xca, 0x5a, 0x3b, 0x00, 0xa4, 0x68, 0x01, 0x07, + 0x15, 0x06, 0x08, 0x90, 0xa2, 0xe8, 0xb0, 0x02, 0x04, 0x03, 0x0f, 0x74, + 0x02, 0xec, 0x03, 0x08, 0x07, 0x04, 0x01, 0x08, 0xd7, 0xce, 0x05, 0x0a, + 0x03, 0x70, 0x0f, 0x38, 0xd0, 0x02, 0x34, 0xf0, 0x02, 0x04, 0x03, 0x22, + 0x80, 0x0f, 0x38, 0x0a, 0x38, 0x02, 0xa8, 0x02, 0x00, 0x06, 0x10, 0x03, + 0x2c, 0x60, 0xe7, 0x60, 0xb9, 0xa0, 0x00, 0x60, 0xc2, 0xa8, 0x03, 0x0c, + 0x38, 0xc2, 0x44, 0x03, 0x08, 0x07, 0x04, 0x04, 0x18, 0x05, 0x0a, 0x0f, + 0x70, 0x03, 0x16, 0xda, 0x07, 0xb0, 0x02, 0xdc, 0xbc, 0x02, 0x04, 0x03, + 0x0c, 0x94, 0x0f, 0x70, 0x0a, 0xe0, 0x04, 0x70, 0xb4, 0xa6, 0x03, 0x2a, + 0x00, 0x00, 0xe0, 0xba, 0xa0, 0x74, 0x41, 0x00, 0xc0, 0x06, 0x70, 0x48, + 0x0f, 0x70, 0x0a, 0x70, 0x02, 0x38, 0x08, 0x0b, 0xa8, 0x20, 0xb5, 0xa0, + 0x00, 0x78, 0x06, 0xe0, 0x58, 0x6f, 0xb0, 0x0f, 0x38, 0x26, 0xbd, 0x03, + 0xa8, 0x04, 0x38, 0x20, 0x05, 0x6c, 0x03, 0x06, 0x60, 0xbc, 0xa0, 0x00, + 0x80, 0x02, 0x3c, 0x03, 0x0c, 0x78, 0x0f, 0x38, 0xf7, 0x0f, 0x06, 0x70, + 0x03, 0x1c, 0x0f, 0x04, 0xff, 0x02, 0x01, 0x0f, 0x14, 0x0f, 0x10, 0x0f, + 0x10, 0x07, 0x10, 0x03, 0x88, 0x07, 0x0c, 0x0b, 0x08, 0x98, 0xbb, 0x12, + 0x00, 0x80, 0xc1, 0x9c, 0x82, 0x11, 0x00, 0xd4, 0x4a, 0x12, 0x82, 0x9e, + 0x09, 0x1a, 0xf8, 0xcc, 0x12, 0x00, 0x7c, 0x0a, 0x04, 0x03, 0x1a, 0x8f, + 0x03, 0x1f, 0xe0, 0x03, 0x14, 0x0b, 0x04, 0xf3, 0x61, 0xe0, 0x95, 0x13, + 0x0b, 0x13, 0x08, 0x0c, 0x13, 0xdf, 0xcc, 0x5c, 0x12, 0x00, 0x00, 0x02, + 0x34, 0xb4, 0xf0, 0x00, 0x03, 0x69, 0xb0, 0x04, 0x4d, 0x09, 0x0c, 0xa0, + 0x01, 0xf0, 0x00, 0x13, 0x23, 0xa0, 0x07, 0x18, 0x02, 0x31, 0x80, 0x03, + 0x0c, 0x96, 0x7c, 0x08, 0x22, 0xc1, 0x12, 0x41, 0xe8, 0x03, 0x0c, 0x00, + 0xa0, 0x02, 0x50, 0x04, 0x00, 0x05, 0x3c, 0x02, 0x18, 0x12, 0x8d, 0x05, + 0x18, 0x03, 0x3a, 0x80, 0x3c, 0x04, 0x00, 0x48, 0x04, 0x24, 0x02, 0x23, + 0x03, 0x03, 0x13, 0xf0, 0x02, 0x00, 0x00, 0x80, 0x0e, 0x04, 0x7c, 0xeb, + 0xa0, 0x00, 0x7c, 0x02, 0x00, 0xf5, 0x02, 0x04, 0xff, 0xa0, 0x00, 0x0b, + 0x0b, 0x07, 0x0b, 0x02, 0x06, 0x03, 0x0d, 0x0d, 0x09, 0x0d, 0x00, 0x00, + 0x02, 0x08, 0x05, 0x1f, 0x1f, 0x13, 0x1d, 0x06, 0x10, 0x07, 0x25, 0x25, + 0x15, 0x25, 0x06, 0x14, 0x00, 0x00, 0x09, 0x79, 0x65, 0x69, 0x5d, 0x14, + 0x62, 0x0b, 0x79, 0x77, 0x77, 0x77, 0x14, 0x76, 0x0d, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x0e, 0x09, 0x0e, 0x03, 0x08, 0x04, 0x11, 0x11, 0x0b, 0x11, + 0x03, 0x0a, 0x07, 0x27, 0x00, 0x00, 0x27, 0x19, 0x24, 0x09, 0x08, 0x09, + 0x2f, 0x2f, 0x1a, 0x2f, 0x08, 0x19, 0x0c, 0x98, 0x7f, 0x84, 0x00, 0x18, + 0x74, 0x1a, 0x7b, 0x0e, 0x98, 0x95, 0x95, 0x95, 0x1a, 0x94, 0x11, 0x03, + 0x7d, 0x05, 0x04, 0xa9, 0x1a, 0xa1, 0x00, 0x00, 0xab, 0x55, 0x17, 0x00, + 0x00, 0x3d, 0x7e, 0x0d, 0xbf, 0x00, 0x00, 0x80, 0x3f, 0x3a, 0x3f, 0xd4, + 0x00, 0x00, 0xc0, 0xcc, 0x76, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x66, 0x02, 0x00, + 0x02, 0x00, 0x67, 0x17, 0xd4, 0x05, 0x22, 0x83, 0x2f, 0xc0, 0x87, 0x79, + 0x26, 0xf6, 0x0d, 0x4a, 0x03, 0x5b, 0x45, 0x99, 0x55, 0x60, 0x2b, 0xa2, + 0xb0, 0x19, 0x37, 0x52, 0x50, 0xbb, 0x2a, 0x49, 0xd7, 0xae, 0xa4, 0xc1, + 0x00, 0x00, 0x00, 0x00, 0x4f, 0x12, 0x94, 0x5e, 0x09, 0x4b, 0xc3, 0x52, + 0xf8, 0x61, 0x61, 0xb6, 0x31, 0x9a, 0xb6, 0x59, 0x78, 0x8c, 0x28, 0x8e, + 0x00, 0x00, 0x00, 0x00, 0x61, 0x7c, 0x36, 0x9d, 0xf6, 0x71, 0xa1, 0x8a, + 0x2c, 0x59, 0xa1, 0x5a, 0xd5, 0xd7, 0x21, 0x5e, 0xaa, 0xce, 0x32, 0xd5, + 0x74, 0x2a, 0x00, 0x00, 0xbc, 0xdc, 0x70, 0xc2, 0x00, 0x00, 0x00, 0x00, + 0x67, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7e, 0x06, 0xe3, + 0x04, 0x00, 0x00, 0x00, 0x2b, 0x66, 0x02, 0x00, 0x02, 0x00, 0x67, 0x17, + 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, 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, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x2a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x17, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc9, 0x13, 0x00, + 0x1c, 0xcd, 0x13, 0x00, 0x48, 0x2b, 0xa1, 0x00, 0xc8, 0x2c, 0xa1, 0x00, + 0xc8, 0x2c, 0xa1, 0x00, 0xc8, 0x3d, 0xa1, 0x00, 0xc8, 0x3d, 0xa1, 0x00, + 0x48, 0x3e, 0xa1, 0x00, 0x38, 0xc9, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x6c, 0x3e, 0xa1, 0x00, 0x00, 0x80, 0xa1, 0x00, 0xec, 0xcc, 0x13, 0x00, + 0xd4, 0xaa, 0x13, 0x00, 0xfc, 0xaa, 0x13, 0x00, 0xe4, 0xaa, 0x13, 0x00, + 0xa9, 0x1a, 0xa1, 0xab, 0x55, 0x17, 0x00, 0x00, 0xc3, 0x42, 0xf0, 0x00, + 0x4c, 0x00, 0x00, 0x82, 0x21, 0x68, 0x0c, 0x70, 0xe0, 0x7f, 0x20, 0xa2, + 0x68, 0x44, 0xc3, 0x43, 0xa1, 0x00, 0xac, 0x29, 0x56, 0x7b, 0x40, 0x83, + 0x61, 0x83, 0x0a, 0x25, 0x00, 0x01, 0x65, 0x04, 0xe0, 0x00, 0x81, 0x44, + 0x60, 0x44, 0xc3, 0x43, 0xa1, 0x00, 0xac, 0x29, 0x56, 0x7b, 0x40, 0x83, + 0x4d, 0x03, 0xe0, 0x00, 0x61, 0x83, 0xe0, 0x78, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x12, 0x00, 0x7c, 0x96, + 0xcb, 0x44, 0x00, 0x00, 0x4c, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0xc0, 0x66, + 0xcb, 0x44, 0x00, 0x00, 0x4e, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0x0c, 0x67, + 0xcb, 0x44, 0x00, 0x00, 0x51, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0x54, 0x67, + 0xcb, 0x44, 0x00, 0x00, 0x4d, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0xe0, 0x67, + 0xcb, 0x44, 0x00, 0x00, 0x4f, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x12, 0x00, 0xa4, 0x97, + 0xcb, 0x44, 0x00, 0x00, 0x58, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0x14, 0x68, + 0xcb, 0x44, 0x00, 0x00, 0x57, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x12, 0x00, 0xc4, 0x97, + 0xcb, 0x44, 0x00, 0x00, 0x59, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0x2c, 0x68, + 0xcb, 0x44, 0x00, 0x00, 0x56, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0x4c, 0x68, + 0xcb, 0x44, 0x00, 0x00, 0x52, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x12, 0x00, 0xe0, 0x97, + 0xcb, 0x44, 0x00, 0x00, 0x47, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0xd8, 0x68, + 0xcb, 0x44, 0x00, 0x00, 0x55, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x12, 0x00, 0xec, 0x97, + 0xcb, 0x44, 0x00, 0x00, 0x46, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0xfc, 0x68, + 0xcb, 0x44, 0x00, 0x00, 0x50, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x10, 0x00, 0x20, 0x69, + 0xcb, 0x44, 0x00, 0x00, 0x53, 0x00, 0x3e, 0x79, 0xe4, 0xc2, 0x08, 0x45, + 0x1f, 0x80, 0xb9, 0x15, 0x81, 0x10, 0x41, 0x80, 0xc2, 0x80, 0xc6, 0xb9, + 0xb9, 0x1d, 0x42, 0x10, 0x05, 0xea, 0xb9, 0x12, 0xc0, 0x00, 0x25, 0x08, + 0x12, 0x00, 0x5a, 0x0f, 0x20, 0x00, 0xa1, 0x40, 0x07, 0xee, 0x0f, 0x08, + 0x91, 0x00, 0xb9, 0x16, 0xc0, 0x10, 0x11, 0x08, 0x12, 0x00, 0x2c, 0x74, + 0x4c, 0x70, 0x7a, 0x0e, 0xa0, 0x00, 0xa1, 0x40, 0x0c, 0x70, 0xc4, 0xc6, + 0xe4, 0xc2, 0x08, 0x45, 0xb9, 0x10, 0xc0, 0x00, 0x33, 0x08, 0x12, 0x00, + 0x1f, 0x85, 0x21, 0x80, 0xc2, 0x80, 0x06, 0xe9, 0xb9, 0x11, 0xc0, 0x00, + 0x23, 0x08, 0x12, 0x00, 0x1a, 0x0f, 0x20, 0x00, 0xa1, 0x40, 0x08, 0xee, + 0x0d, 0x08, 0x91, 0x00, 0xb9, 0x16, 0xc0, 0x10, 0x0f, 0x08, 0x12, 0x00, + 0x2c, 0x74, 0x4c, 0x71, 0x3a, 0x0e, 0xa0, 0x00, 0xa1, 0x40, 0xb9, 0x15, + 0x81, 0x10, 0x0c, 0x70, 0x87, 0xb9, 0xb9, 0x1d, 0x42, 0x10, 0xc4, 0xc6, + 0xee, 0xc3, 0xa1, 0xc1, 0x50, 0x41, 0x30, 0x42, 0x2c, 0x70, 0x4c, 0x73, + 0x70, 0x40, 0x08, 0x45, 0xd2, 0x09, 0x20, 0x00, 0x03, 0x1c, 0x03, 0x30, + 0x2c, 0x71, 0x4c, 0x73, 0xc6, 0x09, 0x20, 0x00, 0xa1, 0x40, 0xb8, 0x15, + 0xc0, 0x10, 0x14, 0x77, 0x07, 0xf2, 0x14, 0x71, 0x65, 0xd8, 0x59, 0xf4, + 0x2c, 0x72, 0x4c, 0x71, 0x03, 0xf0, 0x2c, 0x72, 0x4c, 0x72, 0xaa, 0x09, + 0x20, 0x00, 0xa1, 0x40, 0x1f, 0x85, 0x08, 0xd9, 0xf4, 0x10, 0x93, 0x00, + 0x96, 0x0d, 0xa0, 0x00, 0xa1, 0x40, 0x8a, 0x08, 0x2f, 0xef, 0x0a, 0xd8, + 0xa1, 0x40, 0x8e, 0x08, 0x20, 0x00, 0x40, 0x25, 0x0e, 0x17, 0x7a, 0x08, + 0x2f, 0xef, 0x64, 0xd8, 0x40, 0x24, 0xc2, 0x30, 0x1b, 0xd9, 0x6c, 0x71, + 0x72, 0x0a, 0xe0, 0x00, 0xc1, 0x40, 0x03, 0x14, 0x80, 0x30, 0x23, 0xb8, + 0x44, 0x20, 0x40, 0x80, 0x03, 0x1c, 0x02, 0x30, 0xef, 0xf3, 0xdf, 0x85, + 0x2c, 0x70, 0x82, 0x08, 0x20, 0x00, 0xa1, 0x40, 0x56, 0x26, 0x0f, 0x18, + 0x00, 0xaf, 0x2c, 0x71, 0x72, 0x08, 0x20, 0x00, 0xa1, 0x40, 0x80, 0x26, + 0x84, 0x10, 0x00, 0xae, 0x2c, 0x72, 0x66, 0x08, 0x20, 0x00, 0xa1, 0x40, + 0x02, 0xae, 0x22, 0x0d, 0xa0, 0x00, 0x00, 0x8f, 0x00, 0x1a, 0x04, 0x20, + 0x16, 0x0d, 0xa0, 0x00, 0x00, 0x8e, 0x00, 0x19, 0x04, 0x20, 0x0e, 0x0d, + 0xa0, 0x00, 0x02, 0x8e, 0x00, 0x18, 0x04, 0x20, 0x16, 0x0f, 0x20, 0x00, + 0xa1, 0x40, 0xa1, 0x40, 0x0e, 0x0d, 0xa0, 0x00, 0x62, 0x41, 0x02, 0x08, + 0x2f, 0xef, 0x0a, 0xd8, 0x0c, 0x70, 0xce, 0xc7, 0xf1, 0xc0, 0xa1, 0xc1, + 0x1c, 0xe0, 0x40, 0x24, 0xc2, 0x30, 0x7e, 0xd9, 0x6c, 0x71, 0xe2, 0x0a, + 0xe0, 0x00, 0x03, 0x1c, 0xc3, 0x30, 0x87, 0x74, 0xd1, 0xc0, 0xe0, 0x7e, + 0x1f, 0x80, 0xe0, 0x7f, 0xf4, 0x10, 0x80, 0x00, 0xf1, 0xc0, 0xa1, 0xc1, + 0x1c, 0xe0, 0x1f, 0x09, 0xb0, 0x00, 0x03, 0x1c, 0x03, 0x30, 0x1f, 0x09, + 0x70, 0x00, 0x40, 0x24, 0xc2, 0x30, 0x4c, 0x70, 0x8f, 0xe9, 0x40, 0x24, + 0xc2, 0x30, 0x71, 0xd9, 0x06, 0xf0, 0x40, 0x24, 0xc2, 0x30, 0x73, 0xd9, + 0x02, 0xf0, 0x72, 0xd9, 0xae, 0x09, 0xe0, 0x00, 0x6c, 0x71, 0x03, 0x14, + 0x82, 0x30, 0x87, 0x74, 0xd1, 0xc0, 0xe0, 0x7f, 0x40, 0x40, 0xe0, 0x78, + 0x1f, 0x80, 0xe0, 0x7f, 0xfc, 0x10, 0x00, 0x00, 0x1f, 0x80, 0xe0, 0x7f, + 0xec, 0x10, 0x00, 0x00, 0x1f, 0x80, 0xe0, 0x7f, 0xe8, 0x10, 0x00, 0x00, + 0xe4, 0xc2, 0xdf, 0x80, 0x08, 0x45, 0xa9, 0xd8, 0xd8, 0x60, 0x2c, 0x70, + 0x3e, 0x09, 0x2f, 0xf2, 0x14, 0xda, 0x7f, 0xd9, 0x23, 0xda, 0x0c, 0x70, + 0x17, 0xb9, 0xa0, 0xa6, 0xd4, 0x1e, 0x01, 0x14, 0x48, 0xa6, 0xd8, 0x1e, + 0x02, 0x10, 0x29, 0xa6, 0x1c, 0xae, 0xfc, 0x1e, 0x00, 0x10, 0x3e, 0x0a, + 0xa0, 0x00, 0xa1, 0x40, 0xc4, 0xc6, 0xe0, 0x78, 0xe4, 0xc2, 0x7f, 0x81, + 0x4a, 0x24, 0xc0, 0x70, 0x08, 0x44, 0xc3, 0x40, 0xa1, 0x00, 0x2c, 0x2a, + 0x28, 0x45, 0x2c, 0x70, 0x0a, 0x22, 0x00, 0x00, 0xa8, 0x20, 0xc0, 0x01, + 0x08, 0x12, 0x8e, 0x04, 0x0b, 0x0e, 0x05, 0x13, 0x24, 0x71, 0x2c, 0x73, + 0x10, 0xde, 0x36, 0x78, 0x41, 0x80, 0x21, 0x88, 0xa1, 0x40, 0xe8, 0x1b, + 0x80, 0x00, 0x16, 0x0c, 0xa0, 0x00, 0xf4, 0x1b, 0x82, 0x03, 0x0c, 0x70, + 0xca, 0x09, 0xe0, 0x00, 0xa1, 0x41, 0xc1, 0x40, 0xc4, 0xc6, 0xe0, 0x78, + 0xe6, 0xc3, 0xa1, 0xc1, 0x03, 0x1c, 0x03, 0x30, 0xbf, 0x80, 0x48, 0x47, + 0x54, 0x73, 0x8c, 0x00, 0x2d, 0x00, 0x21, 0xda, 0x33, 0x09, 0xb0, 0x00, + 0x40, 0x20, 0x0e, 0x07, 0x47, 0x09, 0x70, 0x00, 0x40, 0x24, 0xc2, 0x30, + 0x22, 0xda, 0xba, 0xe9, 0x40, 0x24, 0xc2, 0x30, 0x69, 0xd9, 0x6c, 0x71, + 0xce, 0x08, 0xe0, 0x00, 0xc1, 0x40, 0x03, 0x14, 0x82, 0x30, 0x14, 0x6f, + 0x44, 0x20, 0x01, 0x0c, 0x46, 0x22, 0x00, 0x0c, 0x1b, 0xf0, 0x40, 0x24, + 0xc2, 0x30, 0x69, 0xd9, 0x6c, 0x71, 0xb2, 0x08, 0xe0, 0x00, 0xc1, 0x40, + 0x03, 0x14, 0x80, 0x30, 0xc1, 0xbf, 0x6c, 0x20, 0x40, 0x00, 0xe5, 0x78, + 0x0e, 0xf0, 0x69, 0xd9, 0x6c, 0x71, 0x9a, 0x08, 0xe0, 0x00, 0xc1, 0x40, + 0x03, 0x14, 0x82, 0x30, 0x12, 0x6f, 0x44, 0x20, 0x01, 0x03, 0x46, 0x22, + 0x00, 0x03, 0x25, 0x78, 0x03, 0x1c, 0x02, 0x30, 0x40, 0x24, 0xc2, 0x30, + 0x69, 0xd9, 0x6c, 0x71, 0x66, 0x09, 0xe0, 0x00, 0xc1, 0x40, 0x03, 0x14, + 0x81, 0x30, 0x4c, 0x70, 0x91, 0x1d, 0x42, 0x10, 0x40, 0x40, 0xc6, 0xc7, + 0xf6, 0xc3, 0xa4, 0xc1, 0x7c, 0x11, 0x12, 0x00, 0x30, 0x43, 0x08, 0x47, + 0xcd, 0x70, 0x55, 0x22, 0x0d, 0x2f, 0x0c, 0x1c, 0x84, 0x33, 0x4f, 0x08, + 0x73, 0x04, 0x42, 0xc6, 0x7d, 0x0f, 0xb5, 0x10, 0x90, 0xe7, 0x56, 0x44, + 0x14, 0x12, 0x0e, 0x20, 0x0c, 0x12, 0x10, 0x20, 0x22, 0x0c, 0x20, 0x00, + 0x10, 0x12, 0x11, 0x20, 0x27, 0xe8, 0x1a, 0x0c, 0x20, 0x00, 0x22, 0x40, + 0x23, 0xe8, 0x12, 0x0c, 0x20, 0x00, 0x02, 0x40, 0x1f, 0xe8, 0x0a, 0x0c, + 0x20, 0x00, 0xc1, 0x40, 0x1b, 0xe8, 0x2c, 0x70, 0x2e, 0x0c, 0x20, 0x00, + 0x62, 0x40, 0x2c, 0x70, 0x4c, 0x70, 0x52, 0x0b, 0xa0, 0x00, 0x62, 0x40, + 0x15, 0xf0, 0xd1, 0x0f, 0x70, 0x14, 0x8c, 0x27, 0x02, 0x90, 0x7a, 0xf2, + 0x8c, 0x27, 0xc3, 0x9f, 0x92, 0xf4, 0xc3, 0x85, 0xff, 0xd9, 0x0a, 0x0c, + 0x20, 0x00, 0x62, 0x40, 0xb8, 0x26, 0x02, 0x10, 0x75, 0xf0, 0x80, 0xd9, + 0xfa, 0x0b, 0x20, 0x00, 0x62, 0x40, 0xb9, 0x13, 0x80, 0x20, 0xcd, 0x70, + 0xc6, 0xb8, 0xb9, 0x1b, 0x02, 0x20, 0x6b, 0xf0, 0x7e, 0xf4, 0x03, 0x85, + 0x60, 0xdf, 0x0f, 0x1c, 0x82, 0x33, 0x8c, 0x20, 0x02, 0x80, 0x04, 0x1c, + 0x84, 0x33, 0x40, 0xc6, 0xcc, 0x20, 0x82, 0x8f, 0x00, 0x00, 0xff, 0x00, + 0x09, 0xf2, 0x06, 0x85, 0x8c, 0x20, 0x02, 0x80, 0xcc, 0x20, 0x82, 0x8f, + 0x00, 0x00, 0xff, 0x00, 0x84, 0xf4, 0x0e, 0x70, 0x12, 0x41, 0x2f, 0x22, + 0x46, 0x04, 0x2f, 0x23, 0x06, 0x04, 0x2f, 0x24, 0x86, 0x03, 0x62, 0x40, + 0x02, 0x08, 0xe0, 0x00, 0xe1, 0x41, 0x34, 0x13, 0x01, 0x20, 0x23, 0xd8, + 0x20, 0x1a, 0x00, 0x20, 0x60, 0x79, 0x62, 0x40, 0x58, 0x13, 0x02, 0x20, + 0xa4, 0x13, 0x00, 0x21, 0x60, 0x7a, 0x62, 0x41, 0x4e, 0x41, 0x06, 0xe9, + 0xa4, 0x11, 0x00, 0x01, 0x56, 0x81, 0x40, 0x7a, 0x6e, 0x0b, 0x20, 0x00, + 0x62, 0x40, 0x8f, 0x08, 0xb1, 0x00, 0x10, 0xdd, 0x08, 0x12, 0x0e, 0x20, + 0x83, 0x0e, 0x30, 0x10, 0xc1, 0x40, 0x2f, 0x86, 0x40, 0x79, 0x2d, 0x86, + 0x08, 0x47, 0x60, 0x79, 0xc1, 0x40, 0x4e, 0x86, 0xc1, 0x41, 0x60, 0x7a, + 0xe1, 0x40, 0x35, 0xf0, 0xa3, 0x85, 0x8c, 0x25, 0xc3, 0x9f, 0x33, 0xf4, + 0x82, 0xc1, 0x40, 0x24, 0x82, 0x32, 0x83, 0xc3, 0x46, 0x0c, 0xef, 0xff, + 0x62, 0x40, 0x0c, 0x14, 0x44, 0x31, 0x0a, 0x14, 0x43, 0x31, 0x08, 0x14, + 0x42, 0x31, 0x00, 0x41, 0x6e, 0x0f, 0xa0, 0x00, 0x62, 0x40, 0x38, 0xf0, + 0xc3, 0x85, 0x80, 0xd9, 0x1e, 0x0b, 0x20, 0x00, 0x62, 0x40, 0xb8, 0x26, + 0xc3, 0x1f, 0x0c, 0x70, 0x62, 0x41, 0x9e, 0x0f, 0xa0, 0x00, 0xe3, 0xa5, + 0x10, 0xee, 0x7c, 0x13, 0x01, 0x20, 0x00, 0x85, 0xec, 0x11, 0x0e, 0x00, + 0x26, 0x0a, 0x20, 0x00, 0x62, 0x41, 0x04, 0x36, 0x00, 0x90, 0x06, 0xf2, + 0x0c, 0x70, 0xae, 0x0f, 0xa0, 0x00, 0x62, 0x41, 0xa3, 0x85, 0xa1, 0x40, + 0xd6, 0xc7, 0xff, 0xd8, 0x62, 0x41, 0x99, 0xff, 0x82, 0xc1, 0x40, 0x24, + 0x82, 0x32, 0x83, 0xc3, 0xde, 0x0b, 0xef, 0xff, 0x62, 0x40, 0x0c, 0x14, + 0x44, 0x31, 0x0a, 0x14, 0x43, 0x31, 0x08, 0x14, 0x42, 0x31, 0x00, 0x41, + 0x06, 0x0f, 0xa0, 0x00, 0x62, 0x40, 0xa1, 0x40, 0x62, 0x41, 0x8f, 0xff, + 0x11, 0xdd, 0xe7, 0xf1, 0xa6, 0x0a, 0x20, 0x00, 0x62, 0x40, 0x2d, 0x08, + 0x91, 0x00, 0x72, 0x0a, 0x8f, 0xef, 0xe2, 0x08, 0xaf, 0xef, 0x08, 0x45, + 0x00, 0x42, 0x0c, 0x75, 0x5a, 0x0a, 0xaf, 0xef, 0xa1, 0x41, 0x2f, 0x80, + 0x40, 0x79, 0x8c, 0x20, 0x02, 0x80, 0xcc, 0x20, 0x82, 0x8f, 0x00, 0x00, + 0xff, 0x00, 0x67, 0xf3, 0x7e, 0xd9, 0xb6, 0xda, 0x6c, 0x71, 0x1e, 0x0a, + 0xa0, 0x00, 0x62, 0x40, 0x22, 0x09, 0xa0, 0x00, 0x62, 0x40, 0x7e, 0xd9, + 0x11, 0xda, 0x0a, 0xdb, 0x0a, 0x0a, 0xa0, 0x00, 0x62, 0x40, 0x08, 0xd9, + 0x46, 0x09, 0xa0, 0x00, 0x62, 0x40, 0x3a, 0x0c, 0xef, 0xee, 0x0a, 0xd8, + 0x40, 0xd9, 0x2c, 0xda, 0x6c, 0x70, 0x62, 0x40, 0xee, 0x09, 0xa0, 0x00, + 0x40, 0x23, 0x17, 0x27, 0x22, 0x0c, 0xef, 0xee, 0x0a, 0xd8, 0x5a, 0xd8, + 0xd3, 0x46, 0x48, 0x42, 0x00, 0x00, 0x8c, 0x70, 0xab, 0x20, 0x08, 0x0e, + 0x40, 0x24, 0xc2, 0x33, 0x6d, 0xd9, 0x6c, 0x71, 0x80, 0x45, 0xe2, 0x40, + 0x0a, 0x26, 0x80, 0x05, 0x1e, 0x0f, 0xa0, 0x00, 0x0f, 0x1c, 0x43, 0x32, + 0x80, 0xc2, 0x12, 0xd9, 0x6c, 0x76, 0xfa, 0x0d, 0xa0, 0x00, 0xe2, 0x40, + 0x00, 0x14, 0x94, 0x30, 0x02, 0x14, 0x90, 0x30, 0x03, 0x14, 0x8e, 0x30, + 0x04, 0x14, 0x91, 0x30, 0x05, 0x14, 0x95, 0x30, 0x01, 0x14, 0x8d, 0x30, + 0x8c, 0x70, 0x40, 0x24, 0xc2, 0x33, 0x6d, 0xd9, 0x6c, 0x71, 0x80, 0x45, + 0xe2, 0x40, 0x0a, 0x26, 0x80, 0x05, 0xe2, 0x0e, 0xa0, 0x00, 0x0f, 0x1c, + 0x43, 0x33, 0x80, 0xc2, 0x12, 0xd9, 0x6c, 0x76, 0xba, 0x0d, 0xa0, 0x00, + 0xe2, 0x40, 0x01, 0x14, 0x80, 0x30, 0x05, 0x14, 0x89, 0x30, 0x04, 0x14, + 0x84, 0x30, 0x03, 0x14, 0x86, 0x30, 0x40, 0x2d, 0x01, 0x22, 0x00, 0x14, + 0x85, 0x30, 0x02, 0x14, 0x87, 0x30, 0x08, 0xbd, 0x05, 0x21, 0x41, 0x04, + 0x05, 0x25, 0x02, 0x15, 0x2e, 0x7b, 0x40, 0x28, 0x01, 0x02, 0x40, 0x29, + 0x00, 0x12, 0x08, 0xbe, 0x4e, 0x7c, 0x40, 0x2e, 0x02, 0x02, 0x05, 0x20, + 0x00, 0x01, 0x05, 0x20, 0x90, 0x23, 0x05, 0x21, 0x41, 0x01, 0x05, 0x22, + 0xc2, 0x01, 0x0e, 0x78, 0x2f, 0x23, 0x06, 0x14, 0x2e, 0x79, 0x76, 0x48, + 0x4e, 0x78, 0x02, 0x21, 0x11, 0x03, 0x02, 0x20, 0xd0, 0x02, 0x9a, 0x21, + 0x0f, 0x2a, 0x9a, 0x20, 0x0f, 0x2a, 0xcb, 0x40, 0x00, 0x00, 0x00, 0x10, + 0x04, 0x29, 0x11, 0x22, 0x9a, 0x26, 0x0f, 0x1a, 0x82, 0xc0, 0x8a, 0x22, + 0x0f, 0x0a, 0x04, 0x28, 0x10, 0x22, 0x04, 0x2e, 0x0e, 0x12, 0x00, 0x18, + 0x44, 0x04, 0x2f, 0x20, 0x46, 0x04, 0x11, 0x78, 0x2f, 0x21, 0x06, 0x04, + 0x31, 0x79, 0x8c, 0x21, 0xcf, 0x89, 0x3a, 0x20, 0x8d, 0x00, 0x0c, 0x1c, + 0x84, 0x33, 0x0a, 0x1c, 0x04, 0x34, 0x09, 0xf6, 0x8e, 0x71, 0x8c, 0x20, + 0x0f, 0x8a, 0x81, 0xbd, 0xca, 0x24, 0xab, 0x20, 0x02, 0xf0, 0xb1, 0x44, + 0xce, 0x78, 0x11, 0x78, 0x8c, 0x20, 0xc7, 0x8c, 0x03, 0xf6, 0x86, 0x71, + 0x82, 0xbd, 0x7e, 0xd9, 0xb6, 0xda, 0x6c, 0x73, 0xaa, 0x08, 0xa0, 0x00, + 0x62, 0x40, 0xb2, 0x0f, 0x60, 0x00, 0x62, 0x40, 0x2f, 0x20, 0x07, 0x05, + 0x14, 0x71, 0x0d, 0xf7, 0x17, 0x0d, 0x3f, 0x10, 0x61, 0xdf, 0x11, 0x0d, + 0x7f, 0x10, 0xe2, 0xbd, 0x64, 0xdf, 0xca, 0x27, 0xa1, 0x10, 0x03, 0xf0, + 0x62, 0xdf, 0x2f, 0x05, 0xcf, 0xff, 0xe0, 0x78, 0xe6, 0xc3, 0xa1, 0xc1, + 0xbf, 0x81, 0x4a, 0x24, 0x80, 0x71, 0xcb, 0x47, 0xa1, 0x00, 0x4c, 0x2a, + 0x00, 0x42, 0x3c, 0x49, 0x6c, 0x70, 0xcd, 0x70, 0x0a, 0x21, 0xc0, 0x03, + 0xf0, 0x1d, 0x80, 0x10, 0xa8, 0x20, 0x00, 0x02, 0x08, 0x11, 0x0c, 0x04, + 0x04, 0x34, 0x80, 0x90, 0x43, 0xf6, 0xc5, 0x71, 0xcd, 0x76, 0xfc, 0x15, + 0x01, 0x10, 0x8c, 0x21, 0xc3, 0x8f, 0x09, 0xf2, 0x8c, 0x21, 0x02, 0x80, + 0x23, 0xf4, 0x0b, 0x0e, 0xf4, 0x10, 0x6c, 0x71, 0xcd, 0x73, 0x16, 0x27, + 0x81, 0x13, 0x68, 0x15, 0x82, 0x10, 0x24, 0x89, 0x97, 0x6b, 0x74, 0x70, + 0xc3, 0xb9, 0x84, 0x22, 0x01, 0x0c, 0x24, 0x15, 0x06, 0x10, 0x85, 0x79, + 0xca, 0x22, 0x21, 0x08, 0x45, 0x79, 0x8c, 0x70, 0x03, 0x1c, 0x42, 0x30, + 0x40, 0x24, 0xc2, 0x30, 0x40, 0xd9, 0x6c, 0x71, 0x5e, 0x0d, 0xa0, 0x00, + 0x80, 0x45, 0x03, 0x14, 0x80, 0x30, 0x68, 0x1d, 0x02, 0x10, 0xd6, 0x7f, + 0x00, 0x87, 0xec, 0x1d, 0x00, 0x10, 0xc6, 0xc7, 0xe4, 0xc2, 0x72, 0x0f, + 0xef, 0xff, 0x28, 0x45, 0x08, 0x46, 0x0c, 0x70, 0xfa, 0x0c, 0xa0, 0x00, + 0xa1, 0x41, 0xc1, 0x40, 0xc4, 0xc6, 0xe0, 0x78, 0xf1, 0xc0, 0x00, 0x42, + 0x0d, 0xe8, 0x2f, 0x82, 0x60, 0x79, 0x40, 0x40, 0x00, 0x41, 0x8c, 0x20, + 0x02, 0x80, 0x0c, 0x70, 0xcc, 0x21, 0x82, 0x8f, 0x00, 0x00, 0xff, 0x00, + 0x02, 0xf2, 0x0c, 0x71, 0xd1, 0xc0, 0xe0, 0x7e, 0x1f, 0x80, 0x56, 0x20, + 0x00, 0x0a, 0xe0, 0x7f, 0x00, 0x88, 0xe0, 0x78, 0xe8, 0xc3, 0xa1, 0xc1, + 0xbf, 0x80, 0x30, 0x40, 0xd4, 0x15, 0x02, 0x10, 0xd1, 0x0a, 0x60, 0x00, + 0x03, 0x1c, 0x03, 0x30, 0x8c, 0x20, 0x02, 0xa0, 0x40, 0x20, 0x0e, 0x07, + 0x09, 0xf2, 0x8c, 0x20, 0xc3, 0xaf, 0x0c, 0xf4, 0x24, 0x1d, 0x01, 0x10, + 0x03, 0x1c, 0x43, 0x34, 0x0b, 0xf0, 0x7f, 0xd8, 0x17, 0xb8, 0x03, 0x1c, + 0x83, 0x34, 0x06, 0xf0, 0x7f, 0xd8, 0x17, 0xb8, 0x03, 0x1c, 0x03, 0x34, + 0x09, 0xa5, 0xcb, 0x47, 0xa0, 0x40, 0x00, 0x00, 0x8c, 0x70, 0x40, 0x24, + 0xc2, 0x30, 0x7e, 0xd9, 0x6c, 0x71, 0x80, 0x45, 0xc1, 0x40, 0xaa, 0x0c, + 0xa0, 0x00, 0xe1, 0x46, 0x03, 0x14, 0x80, 0x30, 0x8c, 0x20, 0x02, 0xa0, + 0xa6, 0x1d, 0x02, 0x10, 0x0d, 0xf4, 0xb7, 0xd8, 0x8c, 0x70, 0x03, 0x1c, + 0x02, 0x30, 0x40, 0x24, 0xc2, 0x30, 0x40, 0xd9, 0x6c, 0x71, 0x80, 0x45, + 0xc1, 0x40, 0xe1, 0x46, 0x11, 0xf0, 0x68, 0x15, 0x80, 0x10, 0x8c, 0x70, + 0x40, 0x24, 0xc2, 0x30, 0xc3, 0xb8, 0x85, 0xb8, 0x03, 0x1c, 0x02, 0x30, + 0x40, 0xd9, 0x6c, 0x71, 0x80, 0x45, 0xc3, 0x46, 0x80, 0x3f, 0x00, 0x00, + 0xc1, 0x40, 0x5e, 0x0c, 0x80, 0x00, 0x03, 0x14, 0x80, 0x30, 0x8c, 0x70, + 0x8c, 0x20, 0x02, 0xa0, 0x40, 0x24, 0xc2, 0x30, 0x6c, 0xd9, 0x6c, 0x71, + 0x80, 0x45, 0x03, 0x1c, 0x03, 0x30, 0x68, 0x1d, 0x02, 0x10, 0x06, 0xf4, + 0xc3, 0x46, 0x80, 0x3f, 0x00, 0x00, 0x03, 0xf0, 0x80, 0x46, 0x32, 0x0c, + 0xa0, 0x00, 0xc1, 0x40, 0x03, 0x14, 0x80, 0x30, 0x94, 0x1d, 0x02, 0x10, + 0xd4, 0x1d, 0x00, 0x14, 0xc8, 0xc7, 0xe0, 0x78, 0xe4, 0xc3, 0xa1, 0xc1, + 0xbf, 0x80, 0x40, 0x20, 0x0e, 0x07, 0x40, 0x24, 0xc2, 0x30, 0x77, 0xd9, + 0x6c, 0x71, 0xc1, 0x40, 0xee, 0x0a, 0xa0, 0x00, 0x03, 0x1c, 0x03, 0x30, + 0x03, 0x14, 0x80, 0x30, 0x40, 0x24, 0xc2, 0x30, 0x77, 0xd9, 0x86, 0xb8, + 0x03, 0x1c, 0x02, 0x30, 0x6c, 0x71, 0xc6, 0x0b, 0xa0, 0x00, 0xc1, 0x40, + 0xc6, 0x08, 0xef, 0xee, 0x0c, 0x71, 0x03, 0x14, 0x80, 0x30, 0x9f, 0x1d, + 0x02, 0x10, 0xc4, 0xc7, 0xe4, 0xc2, 0x08, 0x45, 0x1f, 0x80, 0xb9, 0x15, + 0x81, 0x10, 0x40, 0x80, 0xc2, 0x80, 0xc6, 0xb9, 0xb9, 0x1d, 0x42, 0x10, + 0x05, 0xea, 0xb9, 0x12, 0xc0, 0x00, 0x25, 0x08, 0x12, 0x00, 0xb2, 0x0e, + 0xef, 0xff, 0xa1, 0x40, 0x07, 0xee, 0x0f, 0x08, 0x91, 0x00, 0xb9, 0x16, + 0xc0, 0x10, 0x11, 0x08, 0x12, 0x00, 0x2c, 0x74, 0x4c, 0x70, 0xd2, 0x0d, + 0x60, 0x00, 0xa1, 0x40, 0x0c, 0x70, 0xc4, 0xc6, 0xe4, 0xc2, 0x08, 0x45, + 0xb9, 0x10, 0xc0, 0x00, 0x33, 0x08, 0x12, 0x00, 0x1f, 0x85, 0x20, 0x80, + 0xc2, 0x80, 0x06, 0xe9, 0xb9, 0x11, 0xc0, 0x00, 0x23, 0x08, 0x12, 0x00, + 0x72, 0x0e, 0xef, 0xff, 0xa1, 0x40, 0x08, 0xee, 0x0d, 0x08, 0x91, 0x00, + 0xb9, 0x16, 0xc0, 0x10, 0x0f, 0x08, 0x12, 0x00, 0x2c, 0x74, 0x4c, 0x71, + 0x92, 0x0d, 0x60, 0x00, 0xa1, 0x40, 0xb9, 0x15, 0x81, 0x10, 0x0c, 0x70, + 0x87, 0xb9, 0xb9, 0x1d, 0x42, 0x10, 0xc4, 0xc6, 0xea, 0xc3, 0xa3, 0xc1, + 0xad, 0x70, 0x08, 0x46, 0x08, 0x1c, 0x44, 0x33, 0x41, 0xc5, 0x03, 0x1c, + 0x42, 0x33, 0xff, 0x86, 0x1c, 0xe0, 0x8a, 0x20, 0x81, 0x26, 0x40, 0x24, + 0xc2, 0x30, 0x2c, 0x73, 0x6c, 0x71, 0x02, 0x1c, 0x42, 0x33, 0xab, 0x20, + 0x08, 0x2e, 0x0e, 0x0a, 0xa0, 0x00, 0x10, 0x41, 0x03, 0x14, 0x80, 0x30, + 0x40, 0x24, 0x42, 0x30, 0x7e, 0xd9, 0x22, 0xb8, 0xc1, 0xb8, 0x03, 0x1c, + 0x02, 0x30, 0x6c, 0x71, 0x22, 0x40, 0xe2, 0x0a, 0xa0, 0x00, 0x01, 0x1c, + 0x43, 0x35, 0xe2, 0x0f, 0xaf, 0xee, 0x32, 0xd8, 0x01, 0x14, 0x80, 0x30, + 0xa6, 0x1f, 0x02, 0x10, 0x0c, 0x75, 0xd2, 0x0f, 0xaf, 0xee, 0xab, 0x20, + 0x08, 0x2e, 0x40, 0x24, 0x82, 0x30, 0x2c, 0x73, 0x6c, 0x71, 0xca, 0x09, + 0xa0, 0x00, 0x22, 0x40, 0x02, 0x14, 0x80, 0x30, 0x22, 0xb8, 0xc1, 0xb8, + 0x15, 0x08, 0x70, 0x00, 0x02, 0x1c, 0x02, 0x30, 0xa5, 0x71, 0xb0, 0x78, + 0xd5, 0x08, 0x94, 0x82, 0x23, 0xd8, 0xca, 0xc7, 0x40, 0x24, 0x82, 0x30, + 0x69, 0xd9, 0x6c, 0x71, 0x9e, 0x09, 0xa0, 0x00, 0x22, 0x40, 0x02, 0x14, + 0x80, 0x30, 0x40, 0x24, 0x42, 0x30, 0x69, 0xd9, 0x86, 0xb8, 0x01, 0x1c, + 0x02, 0x30, 0x6c, 0x71, 0x76, 0x0a, 0xa0, 0x00, 0x22, 0x40, 0x01, 0x14, + 0x80, 0x30, 0x01, 0x1c, 0xc3, 0x30, 0x40, 0x24, 0x42, 0x30, 0x91, 0x1f, + 0x02, 0x10, 0x7e, 0xd9, 0x6c, 0x71, 0x5e, 0x0a, 0xa0, 0x00, 0x22, 0x40, + 0x5e, 0x0f, 0xaf, 0xee, 0x32, 0xd8, 0x01, 0x14, 0x80, 0x30, 0xad, 0x70, + 0xa6, 0x1f, 0x02, 0x10, 0x5a, 0xd8, 0xab, 0x20, 0x08, 0x0e, 0x4a, 0x0f, + 0xaf, 0xee, 0x32, 0xd8, 0x40, 0x24, 0x82, 0x30, 0x1b, 0xd9, 0x6c, 0x71, + 0x42, 0x09, 0xa0, 0x00, 0x22, 0x40, 0x02, 0x14, 0x80, 0x30, 0x23, 0xb8, + 0x44, 0x20, 0x40, 0x80, 0x02, 0x1c, 0x02, 0x30, 0x05, 0xf4, 0xa5, 0x71, + 0xb0, 0x78, 0xd5, 0x08, 0x94, 0x82, 0x2c, 0x70, 0xc6, 0x08, 0x20, 0x00, + 0xc1, 0x40, 0x97, 0x1f, 0x1c, 0x10, 0x2c, 0x71, 0xba, 0x08, 0x20, 0x00, + 0xc1, 0x40, 0x98, 0x1f, 0x1c, 0x10, 0x2c, 0x72, 0xae, 0x08, 0x20, 0x00, + 0xc1, 0x40, 0x99, 0x1f, 0x1c, 0x10, 0x2c, 0x71, 0xaa, 0x0c, 0x20, 0x00, + 0xc1, 0x40, 0x81, 0xc2, 0x0c, 0xd9, 0x6c, 0x76, 0xf2, 0x08, 0xa0, 0x00, + 0x22, 0x40, 0x03, 0x14, 0x80, 0x30, 0x17, 0x08, 0xd0, 0x00, 0x19, 0x08, + 0x70, 0x00, 0x14, 0x70, 0x23, 0xd8, 0x3b, 0xf4, 0x01, 0x1c, 0x03, 0x35, + 0x06, 0xf0, 0x01, 0x1c, 0xc3, 0x35, 0x04, 0xf0, 0x01, 0x1c, 0x43, 0x35, + 0x40, 0x24, 0x42, 0x30, 0x7e, 0xd9, 0x6c, 0x71, 0xb2, 0x09, 0xa0, 0x00, + 0x22, 0x40, 0xb6, 0x0e, 0xaf, 0xee, 0x32, 0xd8, 0x01, 0x14, 0x80, 0x30, + 0x5a, 0xde, 0xad, 0x70, 0xa6, 0x1f, 0x02, 0x10, 0xab, 0x26, 0x08, 0x1e, + 0x0c, 0x75, 0x9e, 0x0e, 0xaf, 0xee, 0xab, 0x26, 0x08, 0x1e, 0x40, 0x24, + 0x82, 0x30, 0x2c, 0x73, 0x6c, 0x71, 0x96, 0x08, 0xa0, 0x00, 0x22, 0x40, + 0x02, 0x14, 0x81, 0x30, 0xa5, 0x71, 0x03, 0x14, 0x82, 0x30, 0xb0, 0x78, + 0x89, 0xe0, 0x41, 0x29, 0x80, 0x00, 0xc1, 0xb8, 0x02, 0x1c, 0x02, 0x30, + 0x03, 0xf7, 0xd1, 0x08, 0x81, 0x80, 0x50, 0x70, 0x65, 0xd8, 0xca, 0x20, + 0xe1, 0x00, 0xca, 0xc7, 0x1f, 0x80, 0xe0, 0x7f, 0x8c, 0x10, 0x00, 0x07, + 0xe4, 0xc3, 0xa1, 0xc1, 0x3f, 0x09, 0xb0, 0x00, 0x40, 0x20, 0x0d, 0x07, + 0x5f, 0x09, 0x70, 0x00, 0x40, 0x24, 0xc2, 0x30, 0x87, 0x09, 0x31, 0x00, + 0x0c, 0x70, 0x40, 0x24, 0xc2, 0x30, 0x74, 0xd9, 0x6c, 0x71, 0x3e, 0x08, + 0xa0, 0x00, 0xa1, 0x40, 0x03, 0x14, 0x8e, 0x30, 0x40, 0x24, 0xc2, 0x30, + 0x77, 0xd9, 0x6c, 0x71, 0x2a, 0x08, 0xa0, 0x00, 0xa1, 0x40, 0x03, 0x14, + 0x80, 0x30, 0x0e, 0xb8, 0x2a, 0xf0, 0x40, 0x24, 0xc2, 0x30, 0x76, 0xd9, + 0x6c, 0x71, 0x16, 0x08, 0xa0, 0x00, 0xa1, 0x40, 0x03, 0x14, 0x8e, 0x30, + 0x40, 0x24, 0xc2, 0x30, 0x77, 0xd9, 0x6c, 0x71, 0x02, 0x08, 0xa0, 0x00, + 0xa1, 0x40, 0x03, 0x14, 0x80, 0x30, 0x0a, 0xb8, 0x12, 0xf0, 0x75, 0xd9, + 0x6c, 0x71, 0xf2, 0x0f, 0x60, 0x00, 0xa1, 0x40, 0x03, 0x14, 0x8e, 0x30, + 0x40, 0x24, 0xc2, 0x30, 0x77, 0xd9, 0x6c, 0x71, 0xde, 0x0f, 0x60, 0x00, + 0xa1, 0x40, 0x03, 0x14, 0x80, 0x30, 0x0c, 0xb8, 0x04, 0x20, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0xc0, 0x0e, 0x78, 0x46, 0xb8, 0xc5, 0x78, 0xc4, 0xc7, + 0x1f, 0x80, 0xe0, 0x7f, 0x42, 0x10, 0x00, 0x06, 0xea, 0xc2, 0x30, 0x41, + 0xb9, 0x11, 0xc1, 0x00, 0x09, 0x09, 0x32, 0x00, 0x08, 0x40, 0xca, 0xc6, + 0x7c, 0x11, 0x10, 0x20, 0xcb, 0x46, 0x13, 0x00, 0xf8, 0x6a, 0xc3, 0x40, + 0x00, 0x00, 0xff, 0x7f, 0x55, 0x20, 0x0d, 0x2c, 0xf4, 0x15, 0xcc, 0x90, + 0xb2, 0x10, 0xc3, 0x20, 0xb3, 0x10, 0x82, 0x20, 0xb1, 0x10, 0x8b, 0x20, + 0xb6, 0x10, 0xcf, 0x20, 0x08, 0xbc, 0x08, 0xbb, 0xb5, 0x10, 0x81, 0x20, + 0x85, 0x7a, 0x05, 0x23, 0xc3, 0x02, 0x48, 0x32, 0x8b, 0x00, 0x48, 0x33, + 0x8c, 0x00, 0x41, 0x86, 0x60, 0x86, 0x08, 0xbf, 0xe5, 0x79, 0x48, 0x31, + 0x89, 0x00, 0x00, 0x32, 0xcb, 0x02, 0x22, 0x86, 0x00, 0x33, 0x02, 0x03, + 0x00, 0x43, 0x48, 0x32, 0xc2, 0x02, 0x00, 0x31, 0x4c, 0x02, 0x48, 0x33, + 0xc1, 0x12, 0x13, 0x08, 0xa2, 0x00, 0x4c, 0x1d, 0x00, 0x12, 0x08, 0x22, + 0x83, 0x0f, 0xff, 0xff, 0x00, 0x80, 0x48, 0x34, 0xc2, 0x12, 0x77, 0xa5, + 0x0f, 0x08, 0x62, 0x00, 0x00, 0x43, 0x08, 0x21, 0x83, 0x0f, 0xff, 0xff, + 0x00, 0x80, 0x11, 0x08, 0xa2, 0x00, 0x78, 0xa5, 0x08, 0x22, 0x80, 0x0f, + 0xff, 0xff, 0x00, 0x80, 0xc3, 0x41, 0xa1, 0x00, 0x52, 0x29, 0x20, 0x89, + 0x93, 0x09, 0x30, 0x00, 0x19, 0xa5, 0x7d, 0x85, 0x88, 0x11, 0x00, 0x20, + 0x8c, 0x11, 0x01, 0x20, 0x5e, 0x85, 0x1d, 0xa5, 0x02, 0x20, 0xc0, 0x80, + 0x3e, 0xa5, 0x32, 0x0f, 0xaf, 0xe3, 0x03, 0x21, 0x81, 0x80, 0x08, 0x47, + 0xb6, 0x0d, 0x60, 0x00, 0x22, 0x40, 0x23, 0x86, 0x00, 0x30, 0x40, 0x00, + 0x07, 0x36, 0x01, 0x70, 0x7a, 0x47, 0x00, 0x00, 0x02, 0x31, 0xc0, 0x03, + 0x07, 0x30, 0x40, 0x00, 0x50, 0x20, 0xc1, 0x07, 0x04, 0x31, 0x80, 0x8f, + 0x4c, 0x3e, 0xcd, 0xcc, 0x46, 0x00, 0x06, 0x00, 0xc3, 0x42, 0x8f, 0x3d, + 0x29, 0x5c, 0x04, 0x30, 0x80, 0x80, 0x0a, 0xf6, 0xc3, 0x41, 0x8f, 0xbd, + 0x29, 0x5c, 0x04, 0x30, 0x40, 0x80, 0x00, 0x42, 0xca, 0x22, 0x45, 0x00, + 0x3f, 0x85, 0xc3, 0x40, 0xc8, 0x42, 0x00, 0x00, 0x00, 0x32, 0x03, 0x00, + 0xb7, 0xb8, 0x01, 0x32, 0x41, 0x00, 0x00, 0x31, 0x00, 0x00, 0x3f, 0xa5, + 0x01, 0x33, 0x00, 0x00, 0x48, 0x30, 0xc0, 0x02, 0x6a, 0x0e, 0x60, 0x00, + 0x0d, 0x78, 0x43, 0x10, 0x01, 0x26, 0x60, 0x79, 0x22, 0x40, 0xca, 0xc6, + 0x1f, 0x80, 0xe0, 0x7f, 0x45, 0x10, 0x00, 0x06, 0x1f, 0x80, 0xe0, 0x7f, + 0x44, 0x10, 0x00, 0x06, 0xe4, 0xc0, 0x39, 0x08, 0xf0, 0x00, 0x7f, 0x83, + 0x37, 0x08, 0xb0, 0x00, 0x14, 0x71, 0x24, 0xd8, 0x13, 0xf4, 0x97, 0x13, + 0x0d, 0x07, 0x99, 0x13, 0x0e, 0x07, 0x98, 0x13, 0x0c, 0x07, 0x0c, 0x70, + 0xc4, 0xa9, 0x82, 0xa9, 0xa0, 0xa9, 0x28, 0xbe, 0x28, 0xbc, 0x28, 0xbd, + 0xc5, 0xa9, 0x83, 0xa9, 0xa1, 0xa9, 0x00, 0x1a, 0x85, 0x01, 0xc4, 0xc4, + 0xbd, 0x13, 0x83, 0x00, 0x04, 0xf0, 0x80, 0x23, 0x04, 0x0b, 0x60, 0x8b, + 0x0c, 0x70, 0xc0, 0xbb, 0x60, 0xa9, 0x00, 0x1a, 0x45, 0x00, 0xc4, 0xc4, + 0xe2, 0xc2, 0x08, 0x45, 0x1f, 0x80, 0x2c, 0x70, 0x4e, 0x18, 0x58, 0x00, + 0x4d, 0x18, 0x58, 0x00, 0x4f, 0x18, 0x58, 0x00, 0x42, 0x18, 0x58, 0x00, + 0xca, 0x0d, 0x60, 0x00, 0xa1, 0xa0, 0xde, 0x0e, 0x20, 0x00, 0xa1, 0x40, + 0xc2, 0xc6, 0xe0, 0x78, 0xe6, 0xc3, 0xa1, 0xc1, 0xbf, 0x81, 0x4a, 0x24, + 0x00, 0x71, 0xc3, 0x43, 0xa1, 0x00, 0x04, 0x2b, 0x28, 0x46, 0x2c, 0x70, + 0x0a, 0x22, 0xc0, 0x00, 0xa8, 0x20, 0xc0, 0x01, 0x08, 0x12, 0x0f, 0x05, + 0x0d, 0x0f, 0x05, 0x10, 0x24, 0x71, 0x2c, 0x74, 0x8a, 0x27, 0x1f, 0x14, + 0x6b, 0x15, 0x8c, 0x10, 0x24, 0x15, 0x06, 0x10, 0x8c, 0x1d, 0xdc, 0x13, + 0x36, 0x7b, 0x02, 0x8b, 0x41, 0x83, 0x6c, 0x24, 0x81, 0x10, 0xc2, 0xb8, + 0x25, 0x78, 0x8c, 0x70, 0x44, 0x1d, 0x98, 0x10, 0x03, 0x1c, 0x02, 0x30, + 0x3c, 0x4e, 0x40, 0x24, 0xc2, 0x30, 0x43, 0xd9, 0x6c, 0x71, 0xaa, 0x0e, + 0x60, 0x00, 0x80, 0x45, 0x03, 0x14, 0x80, 0x30, 0xc1, 0x41, 0x6b, 0x1d, + 0x02, 0x10, 0x42, 0x0e, 0x60, 0x00, 0x0c, 0x70, 0xe1, 0x40, 0xc6, 0xc7, + 0xe6, 0xc3, 0xa1, 0xc1, 0xdf, 0x80, 0x48, 0x47, 0x61, 0x09, 0xb0, 0x00, + 0x40, 0x20, 0x0d, 0x07, 0xa5, 0x09, 0x70, 0x00, 0x40, 0x24, 0xc2, 0x30, + 0x34, 0x70, 0x82, 0xf4, 0x40, 0x24, 0xc2, 0x30, 0x74, 0xd9, 0x6c, 0x71, + 0x52, 0x0d, 0x60, 0x00, 0xa1, 0x40, 0x40, 0x24, 0x82, 0x30, 0x74, 0xd9, + 0x6c, 0x71, 0xa1, 0x40, 0x32, 0x0e, 0x60, 0x00, 0x02, 0x1c, 0xc2, 0x33, + 0x32, 0x0b, 0xaf, 0xee, 0x0c, 0x71, 0x02, 0x14, 0x80, 0x30, 0x40, 0x24, + 0xc2, 0x30, 0x77, 0xd9, 0x9c, 0x1e, 0x02, 0x10, 0x6c, 0x71, 0x26, 0x0d, + 0x60, 0x00, 0xa1, 0x40, 0x03, 0x14, 0x80, 0x30, 0x28, 0xbf, 0xc1, 0xbf, + 0x6c, 0x20, 0x40, 0x00, 0xe5, 0x78, 0x4c, 0xf0, 0x40, 0x24, 0xc2, 0x30, + 0x76, 0xd9, 0x6c, 0x71, 0x06, 0x0d, 0x60, 0x00, 0xa1, 0x40, 0x40, 0x24, + 0x82, 0x30, 0x76, 0xd9, 0x6c, 0x71, 0xa1, 0x40, 0xe6, 0x0d, 0x60, 0x00, + 0x02, 0x1c, 0xc2, 0x33, 0xe6, 0x0a, 0xaf, 0xee, 0x0c, 0x71, 0x02, 0x14, + 0x80, 0x30, 0x40, 0x24, 0xc2, 0x30, 0x77, 0xd9, 0x9e, 0x1e, 0x02, 0x10, + 0x6c, 0x71, 0xda, 0x0c, 0x60, 0x00, 0xa1, 0x40, 0x03, 0x14, 0x80, 0x30, + 0x24, 0xbf, 0x44, 0x27, 0x01, 0x1c, 0x46, 0x20, 0x00, 0x0c, 0x25, 0xf0, + 0x75, 0xd9, 0x6c, 0x71, 0xbe, 0x0c, 0x60, 0x00, 0xa1, 0x40, 0x40, 0x24, + 0x82, 0x30, 0x75, 0xd9, 0x6c, 0x71, 0xa1, 0x40, 0x9e, 0x0d, 0x60, 0x00, + 0x02, 0x1c, 0xc2, 0x33, 0x9e, 0x0a, 0xaf, 0xee, 0x0c, 0x71, 0x02, 0x14, + 0x80, 0x30, 0x40, 0x24, 0xc2, 0x30, 0x77, 0xd9, 0x9d, 0x1e, 0x02, 0x10, + 0x6c, 0x71, 0x92, 0x0c, 0x60, 0x00, 0xa1, 0x40, 0x03, 0x14, 0x80, 0x30, + 0x26, 0xbf, 0x44, 0x27, 0x01, 0x13, 0x46, 0x20, 0x00, 0x03, 0x25, 0x78, + 0x02, 0x1c, 0x02, 0x30, 0x40, 0x24, 0x82, 0x30, 0x77, 0xd9, 0x6c, 0x71, + 0x5e, 0x0d, 0x60, 0x00, 0xa1, 0x40, 0x62, 0x0a, 0xaf, 0xee, 0x0c, 0x71, + 0x02, 0x14, 0x80, 0x30, 0x9f, 0x1e, 0x02, 0x10, 0xc6, 0xc7, 0xe0, 0x78, + 0xe6, 0xc3, 0xa1, 0xc1, 0xbf, 0x80, 0x40, 0x20, 0x0e, 0x07, 0x28, 0x47, + 0x40, 0x24, 0xc2, 0x30, 0x77, 0xd9, 0x6c, 0x71, 0xc1, 0x40, 0x42, 0x0c, + 0x60, 0x00, 0x03, 0x1c, 0x03, 0x30, 0x03, 0x14, 0x80, 0x30, 0x37, 0x6f, + 0x40, 0x24, 0x82, 0x30, 0xc6, 0xb8, 0x25, 0x78, 0x02, 0x1c, 0x02, 0x30, + 0x77, 0xd9, 0x6c, 0x71, 0x12, 0x0d, 0x60, 0x00, 0xc1, 0x40, 0x09, 0x85, + 0x12, 0x0a, 0xaf, 0xee, 0x48, 0x30, 0xc0, 0x02, 0x02, 0x14, 0x80, 0x30, + 0x9f, 0x1d, 0x02, 0x10, 0xc6, 0xc7, 0xe0, 0x78, 0xe2, 0xc3, 0xa1, 0xc1, + 0xbf, 0x80, 0x8a, 0x23, 0x44, 0x0b, 0x79, 0x21, 0x0c, 0x00, 0x34, 0x70, + 0x93, 0x15, 0x82, 0x10, 0x79, 0x65, 0x80, 0xa9, 0x46, 0x22, 0x01, 0x0c, + 0x24, 0x15, 0x06, 0x10, 0xcf, 0x21, 0x22, 0x01, 0x8c, 0x70, 0x03, 0x1c, + 0x42, 0x30, 0x1c, 0xe0, 0x40, 0x24, 0xc2, 0x30, 0x6b, 0xd9, 0x6c, 0x71, + 0xea, 0x0c, 0x60, 0x00, 0x80, 0x45, 0x03, 0x14, 0x80, 0x30, 0x93, 0x1d, + 0x02, 0x10, 0xc2, 0xc7, 0xe2, 0xc3, 0xa1, 0xc1, 0x03, 0x1c, 0x03, 0x30, + 0xbf, 0x80, 0x15, 0x09, 0xb5, 0x00, 0x1c, 0xe0, 0xbd, 0x15, 0x81, 0x10, + 0x07, 0xe9, 0x03, 0x1c, 0xc3, 0x35, 0x07, 0xf0, 0x03, 0x1c, 0x43, 0x35, + 0x03, 0xf0, 0x03, 0x1c, 0x03, 0x35, 0x8c, 0x70, 0x40, 0x24, 0xc2, 0x30, + 0x7e, 0xd9, 0x6c, 0x71, 0xc3, 0x46, 0x80, 0x3f, 0x00, 0x00, 0xa6, 0x0c, + 0x60, 0x00, 0x80, 0x45, 0x7e, 0x09, 0xaf, 0xee, 0x50, 0xd8, 0x03, 0x14, + 0x80, 0x30, 0xa6, 0x1d, 0x02, 0x10, 0xc2, 0xc7, 0xee, 0xc3, 0xa1, 0xc1, + 0xff, 0x81, 0x28, 0x45, 0x2b, 0x08, 0x73, 0x04, 0x08, 0x46, 0x5f, 0x0e, + 0xb5, 0x10, 0x8a, 0x20, 0x44, 0x0b, 0x08, 0x67, 0x85, 0xe8, 0xa1, 0x40, + 0x9a, 0x0f, 0xef, 0xff, 0xc1, 0x41, 0xb9, 0x15, 0x80, 0x10, 0xc6, 0xb8, + 0xb9, 0x1d, 0x02, 0x10, 0x42, 0x1f, 0x98, 0x13, 0x15, 0xf0, 0x91, 0xe6, + 0xad, 0xf2, 0x8c, 0x26, 0x02, 0x90, 0xcc, 0x26, 0x82, 0x9f, 0x00, 0x00, + 0xff, 0x00, 0x11, 0xf4, 0x8a, 0x20, 0x44, 0x0b, 0x08, 0x67, 0x86, 0xe8, + 0xff, 0xd9, 0x6a, 0x0f, 0xef, 0xff, 0xa1, 0x40, 0xff, 0xd8, 0x42, 0x1f, + 0x18, 0x10, 0x0c, 0x70, 0xc2, 0x0b, 0x60, 0x00, 0xa1, 0x41, 0x42, 0x17, + 0x0e, 0x16, 0xc1, 0x40, 0xce, 0xc7, 0xfb, 0x0e, 0x31, 0x94, 0xe9, 0x46, + 0x42, 0x17, 0x12, 0x16, 0x8c, 0x22, 0xc3, 0xaf, 0x06, 0xf2, 0xff, 0xd9, + 0x3a, 0x0f, 0xef, 0xff, 0xa1, 0x40, 0xdf, 0x85, 0xfc, 0x16, 0x00, 0x10, + 0x8a, 0x21, 0x01, 0x28, 0x02, 0x1c, 0x03, 0x30, 0x8c, 0x20, 0x02, 0x80, + 0xcc, 0x20, 0x82, 0x8f, 0x00, 0x00, 0xff, 0x00, 0xa2, 0xf2, 0x42, 0x16, + 0x00, 0x16, 0x8c, 0x20, 0x02, 0x80, 0xcc, 0x20, 0x82, 0x8f, 0x00, 0x00, + 0xff, 0x00, 0x9a, 0xf2, 0xd6, 0x0e, 0xaf, 0xff, 0xa1, 0x40, 0x1b, 0x08, + 0x91, 0x00, 0x02, 0x86, 0x2f, 0x80, 0x40, 0x79, 0x8c, 0x20, 0x02, 0x80, + 0xcc, 0x20, 0x82, 0x8f, 0x00, 0x00, 0xff, 0x00, 0x8a, 0xf2, 0x8a, 0x20, + 0x81, 0x26, 0x7e, 0xd9, 0x15, 0xda, 0x32, 0xdb, 0xa1, 0x40, 0xab, 0x20, + 0x08, 0x2e, 0x56, 0x0e, 0x20, 0x00, 0x40, 0x25, 0x13, 0x17, 0xcd, 0x70, + 0x0c, 0x75, 0x86, 0x08, 0xaf, 0xee, 0xab, 0x20, 0x08, 0x2e, 0x40, 0x24, + 0x82, 0x30, 0x2c, 0x73, 0x6c, 0x71, 0x7e, 0x0a, 0x60, 0x00, 0x62, 0x40, + 0x02, 0x14, 0x80, 0x30, 0x44, 0x20, 0x00, 0x03, 0x0f, 0x08, 0x10, 0x01, + 0xc5, 0x71, 0xcf, 0x78, 0xd9, 0x08, 0x54, 0x81, 0xcd, 0x75, 0x7c, 0x15, + 0x10, 0x10, 0x40, 0x24, 0x42, 0x30, 0x6d, 0xd9, 0x6c, 0x71, 0x62, 0x40, + 0x52, 0x0a, 0x60, 0x00, 0x01, 0x1c, 0x03, 0x30, 0x01, 0x14, 0x80, 0x30, + 0x8c, 0x70, 0x40, 0x24, 0x42, 0x30, 0x84, 0xb8, 0x01, 0x1c, 0x02, 0x30, + 0x6d, 0xd9, 0x6c, 0x71, 0x80, 0x45, 0x3a, 0x0b, 0x60, 0x00, 0x62, 0x40, + 0x01, 0x14, 0x80, 0x30, 0x95, 0x18, 0x02, 0x20, 0x1e, 0x08, 0xaf, 0xee, + 0x32, 0xd8, 0x5a, 0xd8, 0xab, 0x20, 0x08, 0x0e, 0x12, 0x08, 0xaf, 0xee, + 0x0c, 0x75, 0x40, 0x24, 0xc2, 0x30, 0x1b, 0xd9, 0x6c, 0x71, 0x62, 0x40, + 0x0a, 0x0a, 0x60, 0x00, 0x03, 0x1c, 0x03, 0x30, 0x03, 0x14, 0x80, 0x30, + 0x1d, 0x78, 0x44, 0x20, 0x40, 0x80, 0x02, 0x1c, 0x02, 0x30, 0x2f, 0xf4, + 0xc5, 0x71, 0xcf, 0x78, 0xcf, 0x08, 0x54, 0x81, 0x2a, 0xf0, 0x42, 0x17, + 0x10, 0x16, 0x11, 0xde, 0x8c, 0x20, 0xc3, 0xaf, 0x0f, 0xf4, 0xaa, 0x0f, + 0xaf, 0xff, 0xa1, 0x40, 0x99, 0x17, 0x44, 0x17, 0x98, 0x17, 0x43, 0x17, + 0x97, 0x17, 0x42, 0x17, 0x00, 0x41, 0x2a, 0x0a, 0x60, 0x00, 0xa1, 0x40, + 0x59, 0xf1, 0xff, 0xd9, 0xfe, 0x0d, 0xef, 0xff, 0xa1, 0x40, 0x86, 0x0f, + 0xaf, 0xff, 0xa1, 0x40, 0x99, 0x17, 0x44, 0x17, 0x98, 0x17, 0x43, 0x17, + 0x97, 0x17, 0x42, 0x17, 0x00, 0x41, 0x06, 0x0a, 0x60, 0x00, 0xa1, 0x40, + 0xa1, 0x40, 0x02, 0x41, 0x31, 0xf0, 0x2e, 0x72, 0x4c, 0x70, 0x6c, 0x70, + 0x40, 0x44, 0x22, 0x41, 0x06, 0x0a, 0x60, 0x00, 0xa1, 0x40, 0x2d, 0x85, + 0x23, 0xd8, 0x08, 0xa7, 0x60, 0x79, 0xa1, 0x40, 0x56, 0x85, 0xa4, 0x15, + 0x00, 0x11, 0x60, 0x7a, 0xa1, 0x41, 0x20, 0x87, 0x05, 0xe9, 0xa4, 0x11, + 0x00, 0x01, 0x56, 0x81, 0x40, 0x7a, 0x7a, 0x0d, 0xaf, 0xff, 0xa1, 0x40, + 0x1f, 0x08, 0x91, 0x00, 0xc2, 0x87, 0x0d, 0xee, 0x2f, 0x86, 0x60, 0x79, + 0xc1, 0x40, 0x2d, 0x86, 0x08, 0x47, 0x60, 0x79, 0xc1, 0x40, 0x4e, 0x86, + 0xc1, 0x41, 0x60, 0x7a, 0xe1, 0x40, 0x8c, 0x22, 0xc3, 0xaf, 0x10, 0xde, + 0x17, 0xf3, 0xa1, 0x40, 0x42, 0x41, 0x7a, 0x0d, 0xcf, 0xff, 0x13, 0xf1, + 0xe2, 0xc3, 0xa1, 0xc1, 0xbf, 0x81, 0x4a, 0x24, 0x40, 0x71, 0xcb, 0x44, + 0xa1, 0x00, 0x2c, 0x2b, 0x20, 0x45, 0x40, 0x21, 0x0b, 0x07, 0x2c, 0x70, + 0x0a, 0x22, 0x00, 0x03, 0xa8, 0x20, 0x80, 0x02, 0x04, 0x12, 0x03, 0x05, + 0x48, 0x33, 0x03, 0x00, 0x04, 0x33, 0x00, 0x80, 0x46, 0xf6, 0x24, 0x71, + 0x2c, 0x75, 0xc3, 0x43, 0x48, 0x44, 0x00, 0x00, 0x35, 0x7c, 0x6a, 0x15, + 0x82, 0x10, 0x22, 0x8c, 0x45, 0x1d, 0xd8, 0x10, 0x6c, 0x22, 0xc2, 0x00, + 0xc3, 0xb9, 0x45, 0x79, 0x03, 0x1c, 0x42, 0x30, 0x40, 0x24, 0xc2, 0x30, + 0x42, 0xd9, 0x6c, 0x71, 0xc3, 0x44, 0x13, 0x00, 0xb4, 0xc8, 0xc3, 0x46, + 0x80, 0x3f, 0x00, 0x00, 0xe6, 0x09, 0x60, 0x00, 0x61, 0x40, 0x03, 0x14, + 0x81, 0x30, 0x45, 0x15, 0x00, 0x16, 0x6a, 0x1d, 0x42, 0x10, 0xc2, 0xc7, + 0xe6, 0xc2, 0xbf, 0x83, 0x65, 0x08, 0xf0, 0x00, 0x68, 0x46, 0x7b, 0x08, + 0xb0, 0x00, 0xed, 0x70, 0xb9, 0x08, 0x71, 0x00, 0x24, 0xdf, 0x01, 0x89, + 0x40, 0x89, 0x08, 0xb8, 0x05, 0x7a, 0x97, 0x1d, 0x9c, 0x10, 0x03, 0x89, + 0x62, 0x89, 0x4e, 0x7a, 0x08, 0xb8, 0x65, 0x78, 0x98, 0x1d, 0x1c, 0x10, + 0x05, 0x89, 0x24, 0x89, 0x08, 0xb8, 0x25, 0x78, 0x99, 0x1d, 0x1c, 0x10, + 0x2c, 0x70, 0x0a, 0x0b, 0xef, 0xff, 0xc1, 0x40, 0x98, 0x15, 0x42, 0x17, + 0x2c, 0x71, 0xfe, 0x0a, 0xef, 0xff, 0xc1, 0x40, 0x99, 0x15, 0x42, 0x17, + 0x2c, 0x72, 0xf2, 0x0a, 0xef, 0xff, 0xc1, 0x40, 0x2c, 0x71, 0x0a, 0x0c, + 0xef, 0xff, 0xc1, 0x40, 0xed, 0x70, 0x32, 0xf0, 0x20, 0x89, 0x42, 0x15, + 0x00, 0x16, 0xed, 0x70, 0xc0, 0xb9, 0x59, 0x08, 0xb5, 0x00, 0xbd, 0x1d, + 0x42, 0x10, 0xce, 0x0c, 0xef, 0xff, 0xc1, 0x41, 0x24, 0xf0, 0x8a, 0x20, + 0x04, 0x0b, 0x40, 0x89, 0xb8, 0x60, 0x21, 0x88, 0x44, 0x22, 0x42, 0x80, + 0x40, 0xa8, 0x0e, 0xf4, 0x35, 0x09, 0x71, 0x00, 0x2c, 0x70, 0x1e, 0x0c, + 0xef, 0xff, 0xc1, 0x40, 0x42, 0x15, 0x00, 0x16, 0x25, 0x08, 0xb5, 0x00, + 0x0c, 0x71, 0xe9, 0xf1, 0x8e, 0xe9, 0x42, 0x15, 0x00, 0x16, 0x8c, 0x20, + 0xc3, 0x8f, 0x06, 0xf2, 0xff, 0xd9, 0x42, 0x0c, 0xef, 0xff, 0xc1, 0x40, + 0x2c, 0x71, 0xf6, 0x0b, 0xef, 0xff, 0xc1, 0x40, 0xe1, 0x40, 0xc6, 0xc6, + 0x5f, 0x81, 0x20, 0x45, 0x6c, 0x75, 0xf8, 0x1a, 0x00, 0x00, 0x80, 0x22, + 0x83, 0x03, 0x3c, 0x49, 0xc3, 0x44, 0x13, 0x00, 0x0c, 0xc0, 0xf1, 0x07, + 0x20, 0x00, 0x1b, 0xd9, 0x14, 0x70, 0x20, 0x45, 0xe0, 0x7d, 0x7c, 0x15, + 0x02, 0x00, 0x40, 0x25, 0x00, 0x07, 0x2c, 0x74, 0x80, 0x22, 0x42, 0x0a, + 0xc3, 0x44, 0x13, 0x00, 0x2c, 0xc0, 0xd1, 0x07, 0x20, 0x00, 0x14, 0xdb, + 0xe8, 0xc2, 0x28, 0x47, 0x02, 0xe8, 0xc8, 0xc6, 0xbf, 0x87, 0xb9, 0x17, + 0xc0, 0x10, 0x08, 0x15, 0x10, 0x10, 0x49, 0x08, 0x33, 0x00, 0xc1, 0x85, + 0xce, 0x15, 0xc0, 0x10, 0x3d, 0x08, 0x33, 0x00, 0x55, 0x25, 0x80, 0x1b, + 0xba, 0x15, 0xc1, 0x10, 0xb9, 0x15, 0x8c, 0x10, 0x04, 0x10, 0xc2, 0x00, + 0x08, 0xb9, 0x00, 0x10, 0xc3, 0x00, 0xbb, 0x15, 0x8b, 0x10, 0xb7, 0x15, + 0x88, 0x10, 0x85, 0x79, 0x2a, 0xa0, 0x08, 0xba, 0x08, 0xbb, 0x30, 0x80, + 0x05, 0x22, 0xc2, 0x02, 0x05, 0x23, 0x03, 0x02, 0x4b, 0xa0, 0x69, 0xa0, + 0x60, 0x79, 0xe1, 0x40, 0x55, 0x27, 0x8f, 0x18, 0x0e, 0xee, 0xb9, 0x16, + 0xc0, 0x10, 0x19, 0x08, 0x13, 0x00, 0xce, 0x15, 0x80, 0x10, 0x11, 0x08, + 0xbe, 0x01, 0xc1, 0x42, 0x21, 0x87, 0xd2, 0x0f, 0x20, 0x00, 0x00, 0x87, + 0x8f, 0x08, 0x10, 0xa0, 0xb9, 0x10, 0xc0, 0x20, 0x87, 0x08, 0x13, 0x80, + 0xce, 0x15, 0x80, 0x10, 0x7f, 0x08, 0x7e, 0x81, 0x02, 0x42, 0x21, 0x87, + 0xb2, 0x0f, 0x20, 0x00, 0x00, 0x87, 0xc8, 0xc6, 0xec, 0xc3, 0xa8, 0xc1, + 0x3f, 0x80, 0x08, 0x47, 0x30, 0x40, 0xd8, 0x11, 0x80, 0x00, 0x1f, 0x1c, + 0x03, 0x30, 0x8a, 0xe8, 0xd8, 0x18, 0x43, 0x20, 0xc3, 0x41, 0xf0, 0x00, + 0xfc, 0x02, 0x00, 0x89, 0xa1, 0xb8, 0x00, 0xa9, 0x1c, 0x10, 0x80, 0x20, + 0x40, 0x27, 0x12, 0x17, 0x85, 0x08, 0x31, 0x00, 0x03, 0x1c, 0x03, 0x30, + 0x1c, 0x18, 0x43, 0x20, 0x08, 0x87, 0x79, 0x08, 0x51, 0x04, 0xcb, 0x45, + 0xf0, 0x00, 0x77, 0x02, 0x00, 0x8d, 0xc1, 0xb8, 0x69, 0x08, 0xb1, 0x00, + 0x18, 0xda, 0x00, 0x8d, 0x42, 0x41, 0x6c, 0x20, 0x40, 0x00, 0x00, 0xad, + 0x46, 0x08, 0xaf, 0xe3, 0x81, 0xc0, 0x21, 0xd8, 0x8c, 0x70, 0x16, 0x1c, + 0x43, 0x36, 0x04, 0x1c, 0x80, 0x3f, 0xa0, 0x00, 0xec, 0x40, 0x42, 0xc0, + 0x81, 0xc0, 0x7f, 0xd9, 0xc3, 0x42, 0xa1, 0x00, 0x51, 0x29, 0x6c, 0x71, + 0xc3, 0x46, 0x80, 0x3f, 0x00, 0x00, 0xca, 0x0e, 0x20, 0x00, 0x80, 0x45, + 0xb6, 0xde, 0x81, 0xc0, 0x40, 0x24, 0xc2, 0x30, 0x7e, 0xd9, 0x6c, 0x71, + 0x76, 0x0f, 0x20, 0x00, 0x03, 0x1c, 0x82, 0x33, 0x76, 0x0c, 0x6f, 0xee, + 0x32, 0xd8, 0xa6, 0x18, 0x82, 0x23, 0x00, 0x8d, 0x6c, 0x20, 0x40, 0x00, + 0x81, 0xb8, 0x00, 0xad, 0x32, 0x09, 0x20, 0x00, 0xe1, 0x40, 0x40, 0x24, + 0xc2, 0x37, 0x2c, 0x70, 0x6c, 0x71, 0x5e, 0x0e, 0x20, 0x00, 0x42, 0x40, + 0x14, 0x70, 0x4a, 0x20, 0x80, 0x28, 0x8a, 0xf4, 0x1f, 0x14, 0x80, 0x30, + 0x4a, 0x20, 0x40, 0x28, 0x6c, 0x20, 0xc0, 0x00, 0x8c, 0x20, 0x03, 0x84, + 0x80, 0xf4, 0xdf, 0x87, 0x0e, 0x70, 0x08, 0x86, 0xf1, 0x08, 0x30, 0x00, + 0x03, 0x1c, 0x03, 0x30, 0xf6, 0x08, 0x20, 0x00, 0xe1, 0x40, 0xb6, 0xd8, + 0x03, 0x1c, 0x02, 0x30, 0x40, 0x24, 0xc2, 0x30, 0x7e, 0xd9, 0x6c, 0x71, + 0x0a, 0x0f, 0x20, 0x00, 0x42, 0x40, 0x0e, 0x0c, 0x6f, 0xee, 0x0c, 0x71, + 0xd6, 0x08, 0x20, 0x00, 0xe1, 0x40, 0x1f, 0x87, 0x8a, 0x24, 0x02, 0x70, + 0xc3, 0x41, 0xa1, 0x00, 0x84, 0x2a, 0x28, 0xe0, 0xa8, 0x20, 0x80, 0x01, + 0x01, 0x11, 0x82, 0x04, 0x01, 0x18, 0x92, 0x00, 0xad, 0x70, 0x40, 0x24, + 0xc2, 0x30, 0x7f, 0xd9, 0x6c, 0x71, 0x42, 0x40, 0xd2, 0x0e, 0x20, 0x00, + 0x03, 0x1c, 0x42, 0x33, 0xd2, 0x0b, 0x6f, 0xee, 0x0c, 0x71, 0x03, 0x14, + 0x80, 0x30, 0x03, 0x1c, 0x42, 0x33, 0x40, 0x24, 0xc2, 0x30, 0xa7, 0x1e, + 0x02, 0x10, 0x54, 0xd9, 0x6c, 0x71, 0xb2, 0x0e, 0x20, 0x00, 0x42, 0x40, + 0xb2, 0x0b, 0x6f, 0xee, 0x0c, 0x71, 0x03, 0x14, 0x81, 0x30, 0xbb, 0xd8, + 0xd3, 0x41, 0x80, 0x3f, 0x00, 0x00, 0x61, 0xc0, 0x7c, 0x1e, 0x42, 0x10, + 0x81, 0xc2, 0x53, 0xd9, 0x6c, 0x71, 0xa1, 0x44, 0xa1, 0x45, 0x42, 0x40, + 0xae, 0x0e, 0x20, 0x00, 0x0a, 0x26, 0x40, 0x04, 0x81, 0xc2, 0x55, 0xd9, + 0x6c, 0x71, 0xa1, 0x44, 0xa1, 0x45, 0x42, 0x40, 0x0a, 0x26, 0x40, 0x04, + 0x96, 0x0e, 0x20, 0x00, 0x61, 0xc5, 0x90, 0xd8, 0x61, 0xc0, 0x81, 0xc2, + 0x56, 0xd9, 0x6c, 0x71, 0xa1, 0x44, 0xa1, 0x45, 0x42, 0x40, 0x82, 0x0e, + 0x20, 0x00, 0x0a, 0x26, 0x40, 0x04, 0x81, 0xc2, 0x57, 0xd9, 0x6c, 0x71, + 0xa1, 0x44, 0xa1, 0x45, 0x42, 0x40, 0x0a, 0x26, 0x40, 0x04, 0x6a, 0x0e, + 0x20, 0x00, 0x04, 0x1c, 0xc3, 0x3f, 0xa8, 0xa6, 0x4e, 0x87, 0x0c, 0x70, + 0x60, 0x7a, 0xe1, 0x41, 0x02, 0x40, 0xcc, 0xc7, 0xf1, 0xc0, 0xa1, 0xc1, + 0x1c, 0xe0, 0x40, 0x24, 0xc2, 0x30, 0x7f, 0xd9, 0x6c, 0x71, 0x2e, 0x0d, + 0x20, 0x00, 0x03, 0x1c, 0x03, 0x30, 0x1e, 0x0b, 0x6f, 0xee, 0x0c, 0x71, + 0x87, 0x74, 0xd1, 0xc0, 0xe0, 0x7e, 0xe0, 0x78, 0x00, 0x41, 0x2f, 0x26, + 0x05, 0xf0, 0xc5, 0x21, 0x84, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x7f, + 0x2e, 0x78, 0xe0, 0x78, 0xe2, 0xc3, 0x45, 0x09, 0x75, 0x03, 0xa1, 0xc1, + 0xc3, 0x42, 0x00, 0x00, 0x28, 0x11, 0x39, 0x0a, 0x6e, 0x00, 0x53, 0x21, + 0xc3, 0x00, 0xbf, 0x80, 0x8c, 0x70, 0x1c, 0xe0, 0x69, 0x15, 0x82, 0x10, + 0x24, 0x15, 0x06, 0x10, 0x80, 0x45, 0x6c, 0x22, 0xc1, 0x00, 0x65, 0x79, + 0x03, 0x1c, 0x42, 0x30, 0x40, 0x24, 0xc2, 0x30, 0x41, 0xd9, 0xe6, 0x0d, + 0x20, 0x00, 0x6c, 0x71, 0x03, 0x14, 0x80, 0x30, 0x69, 0x1d, 0x02, 0x10, + 0xc2, 0xc7, 0xe0, 0x78, 0xe2, 0xc3, 0xa1, 0xc1, 0x03, 0x1c, 0x03, 0x30, + 0xbf, 0x80, 0x1c, 0xe0, 0x1d, 0xe9, 0x39, 0x09, 0x31, 0x01, 0x34, 0x6a, + 0x79, 0x15, 0x83, 0x10, 0x44, 0x21, 0x02, 0x04, 0x50, 0x23, 0x01, 0x01, + 0x45, 0x79, 0x8c, 0x70, 0x03, 0x1c, 0x42, 0x30, 0x40, 0x24, 0xc2, 0x30, + 0x51, 0xd9, 0x6c, 0x71, 0xc3, 0x46, 0x80, 0x3f, 0x00, 0x00, 0x9e, 0x0d, + 0x20, 0x00, 0x80, 0x45, 0x03, 0x14, 0x80, 0x30, 0x79, 0x1d, 0x02, 0x10, + 0xc2, 0xc7, 0x78, 0x15, 0x81, 0x10, 0x8c, 0x70, 0x6c, 0x71, 0x6c, 0x21, + 0x81, 0x00, 0x45, 0x79, 0x03, 0x1c, 0x42, 0x30, 0x40, 0x24, 0xc2, 0x30, + 0x50, 0xd9, 0xc3, 0x46, 0x80, 0x3f, 0x00, 0x00, 0x6e, 0x0d, 0x20, 0x00, + 0x80, 0x45, 0x03, 0x14, 0x80, 0x30, 0x78, 0x1d, 0x02, 0x10, 0xc2, 0xc7, + 0xe6, 0xc3, 0xa1, 0xc1, 0xdf, 0x80, 0x68, 0x47, 0x03, 0x1c, 0x82, 0x30, + 0x1c, 0xe0, 0x40, 0x24, 0xc2, 0x30, 0x6c, 0x71, 0x22, 0x0d, 0x20, 0x00, + 0x28, 0x45, 0x26, 0x0a, 0x6f, 0xee, 0x01, 0x6f, 0x03, 0x14, 0x80, 0x30, + 0xdd, 0x65, 0x28, 0x1d, 0x02, 0x10, 0xc6, 0xc7, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x13, 0x00, 0x28, 0x1a, + 0xcb, 0x44, 0x00, 0x00, 0x44, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x13, 0x00, 0x78, 0x1a, + 0xcb, 0x44, 0x00, 0x00, 0x45, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x13, 0x00, 0x4c, 0x1a, + 0xcb, 0x44, 0x00, 0x00, 0x42, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x13, 0x00, 0xdc, 0x1a, + 0xcb, 0x44, 0x00, 0x00, 0x43, 0x00, 0x3e, 0x79, 0xf2, 0xc3, 0x94, 0x24, + 0x2f, 0x3a, 0xc3, 0x40, 0xa0, 0x00, 0x8c, 0x86, 0xd6, 0x09, 0x20, 0x00, + 0x10, 0x42, 0xcb, 0x47, 0xf0, 0x00, 0x34, 0x00, 0x03, 0xe8, 0x50, 0xd9, + 0x2d, 0xf0, 0xcb, 0x46, 0x13, 0x00, 0xd8, 0xcc, 0x00, 0x8e, 0x1e, 0xe8, + 0xad, 0x70, 0xd3, 0x41, 0x13, 0x00, 0xdc, 0xcc, 0x0a, 0x20, 0x80, 0x2f, + 0x13, 0x00, 0xe4, 0xcc, 0x04, 0x11, 0x02, 0x24, 0x04, 0x10, 0x01, 0x24, + 0x00, 0x24, 0x83, 0x3f, 0x00, 0x00, 0x30, 0x06, 0x8a, 0x24, 0x08, 0x00, + 0xae, 0x09, 0x20, 0x00, 0x42, 0x40, 0x27, 0x08, 0x32, 0x00, 0x58, 0xd9, + 0x00, 0x8e, 0xa5, 0x71, 0xdd, 0x0d, 0x04, 0x90, 0x4f, 0xd8, 0x40, 0xc0, + 0x81, 0xc1, 0x80, 0xc2, 0x42, 0x40, 0x62, 0x09, 0x20, 0x00, 0x40, 0x24, + 0x14, 0x31, 0x06, 0xe8, 0x57, 0xd9, 0x34, 0xaf, 0x15, 0xaf, 0xd2, 0xc7, + 0x4e, 0x70, 0x00, 0xc0, 0x8b, 0x0a, 0x05, 0x20, 0x5a, 0x22, 0x0e, 0x25, + 0x30, 0x24, 0x80, 0x23, 0x1d, 0x78, 0xde, 0x09, 0x2f, 0xef, 0x10, 0x43, + 0x08, 0x45, 0x39, 0xe8, 0x07, 0x85, 0xb7, 0xe8, 0x81, 0xc0, 0x1e, 0x66, + 0x02, 0x86, 0x34, 0x15, 0x11, 0x10, 0x0e, 0x09, 0x20, 0x00, 0x30, 0x15, + 0x10, 0x10, 0x10, 0x45, 0x02, 0x09, 0x20, 0x00, 0x03, 0x86, 0x4c, 0x70, + 0x04, 0x30, 0x80, 0xa0, 0xa2, 0x41, 0xc7, 0xf7, 0x04, 0x30, 0x40, 0xa5, + 0x02, 0x41, 0xca, 0x21, 0x49, 0x05, 0x04, 0x31, 0x00, 0xa0, 0xca, 0x20, + 0x49, 0x04, 0x04, 0x35, 0x80, 0xa0, 0xd1, 0xf7, 0x04, 0x30, 0x40, 0xa0, + 0x05, 0xf2, 0x50, 0x21, 0xfe, 0x87, 0x03, 0xf2, 0x2c, 0xa5, 0x04, 0x31, + 0x00, 0xa0, 0x0f, 0xf2, 0x50, 0x20, 0xfe, 0x87, 0x0b, 0xf2, 0x0d, 0xa5, + 0x09, 0xf0, 0x59, 0xd8, 0x14, 0xaf, 0x16, 0x1f, 0xc2, 0x14, 0x55, 0xaf, + 0x19, 0x8d, 0x87, 0xb8, 0x19, 0xad, 0x46, 0x71, 0xbb, 0xf1, 0xc3, 0x40, + 0xa1, 0x00, 0xc8, 0x2c, 0xde, 0x0d, 0x0f, 0xff, 0xd2, 0xc7, 0xe0, 0x78, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x13, 0x00, 0xd4, 0x1d, 0xcb, 0x44, 0x00, 0x00, 0x41, 0x00, 0x3e, 0x79, + 0xee, 0xc3, 0x82, 0x24, 0x18, 0x3c, 0x4f, 0xd8, 0x40, 0xc0, 0x81, 0xc1, + 0xc3, 0x40, 0xa0, 0x00, 0x8c, 0x86, 0x8a, 0x08, 0x20, 0x00, 0x80, 0xc2, + 0xb2, 0xe8, 0x56, 0x0e, 0xcf, 0xee, 0xc6, 0x0c, 0xef, 0xee, 0x10, 0x43, + 0x10, 0x42, 0x0e, 0x70, 0x00, 0xc0, 0x55, 0x08, 0x25, 0x20, 0x81, 0xc0, + 0x5a, 0x20, 0x0d, 0x25, 0xa0, 0x60, 0x06, 0x09, 0x2f, 0xef, 0x1d, 0x78, + 0x08, 0x47, 0x1e, 0xe8, 0x07, 0x87, 0x9c, 0xe8, 0x81, 0xc0, 0xb8, 0x60, + 0x10, 0x10, 0x11, 0x01, 0xad, 0x70, 0xcd, 0x71, 0x1b, 0x09, 0x6e, 0x23, + 0xa1, 0x40, 0x62, 0x41, 0x0e, 0x0e, 0xef, 0xee, 0x42, 0x42, 0x0b, 0xe8, + 0x07, 0x88, 0x89, 0xe8, 0x78, 0x20, 0x00, 0x00, 0x04, 0x7e, 0xa5, 0x71, + 0xe5, 0x0d, 0x14, 0x98, 0x84, 0xee, 0x19, 0x8f, 0x87, 0xb8, 0x19, 0xaf, + 0x06, 0x71, 0xd8, 0xf1, 0xce, 0xc7, 0xe0, 0x78, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x13, 0x00, 0xfc, 0x1d, + 0xcb, 0x44, 0x00, 0x00, 0x49, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x11, 0x00, 0x2c, 0x69, + 0xcb, 0x44, 0x00, 0x00, 0x4b, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x13, 0x00, 0x4c, 0x36, + 0xcb, 0x44, 0x00, 0x00, 0x48, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x11, 0x00, 0x34, 0x75, + 0xcb, 0x44, 0x00, 0x00, 0x4a, 0x00, 0x3e, 0x79, 0x58, 0x88, 0x68, 0xba, + 0x9f, 0xe2, 0xe1, 0x20, 0xcd, 0x07, 0x40, 0x43, 0xc3, 0x42, 0x04, 0x90, + 0x01, 0x02, 0x11, 0x22, 0xc0, 0x80, 0xe0, 0x7c, 0x10, 0x80, 0xe0, 0x7f, + 0x00, 0xa1, 0xe0, 0x78, 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, + 0xe0, 0x20, 0x82, 0x0f, 0x11, 0x00, 0xf4, 0x7e, 0xcb, 0x44, 0x00, 0x00, + 0x31, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, + 0xe0, 0x20, 0x82, 0x0f, 0x11, 0x00, 0x10, 0x80, 0xcb, 0x44, 0x00, 0x00, + 0x1c, 0x00, 0x3e, 0x79, 0xc3, 0x40, 0xa1, 0x00, 0x8c, 0x29, 0xe0, 0x7f, + 0x00, 0x18, 0x43, 0x00, 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, + 0xe0, 0x20, 0x82, 0x0f, 0x11, 0x00, 0x84, 0xa1, 0xcb, 0x44, 0x00, 0x00, + 0x0a, 0x00, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, + 0xe0, 0x20, 0x82, 0x0f, 0x11, 0x00, 0x04, 0xa4, 0xcb, 0x44, 0x00, 0x00, + 0x0d, 0x00, 0x3e, 0x79, 0xe8, 0xc3, 0xa2, 0xc1, 0x28, 0x46, 0x08, 0x45, + 0x14, 0x70, 0x23, 0xd8, 0x45, 0xf2, 0x8b, 0x0e, 0x10, 0x10, 0x1a, 0x85, + 0xcb, 0x47, 0xff, 0x46, 0x00, 0xfe, 0x00, 0x30, 0xd0, 0x03, 0xb6, 0x0f, + 0xef, 0xff, 0xa1, 0x40, 0x48, 0x30, 0x00, 0x00, 0x42, 0x86, 0x4a, 0x24, + 0xc0, 0x70, 0x07, 0x30, 0x0b, 0x20, 0xc7, 0xde, 0x80, 0xc4, 0x18, 0xbe, + 0xa8, 0x20, 0xc0, 0x04, 0x04, 0x12, 0x00, 0x04, 0x00, 0x33, 0x01, 0x10, + 0xe1, 0x40, 0x04, 0x31, 0xc0, 0x83, 0x07, 0xf6, 0x04, 0x31, 0x80, 0x83, + 0xc1, 0x40, 0xca, 0x20, 0x46, 0x00, 0x48, 0x30, 0xc3, 0x02, 0x02, 0x1c, + 0xd4, 0x10, 0xc3, 0x40, 0xa1, 0x00, 0x8c, 0x29, 0x20, 0x88, 0x83, 0x42, + 0x81, 0x92, 0x40, 0x92, 0x8b, 0xe9, 0x22, 0x90, 0x13, 0x0a, 0x41, 0x00, + 0x24, 0x90, 0x0f, 0x0c, 0x61, 0x10, 0x70, 0x79, 0xc6, 0x90, 0x19, 0x0e, + 0x40, 0x10, 0x42, 0xb0, 0x00, 0x18, 0x03, 0x00, 0x84, 0xb0, 0x66, 0xb0, + 0x80, 0xc1, 0xda, 0x08, 0x20, 0x00, 0xa1, 0x40, 0x0c, 0x70, 0xc8, 0xc7, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x11, 0x00, 0x3c, 0xae, 0xcb, 0x44, 0x00, 0x00, 0x30, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x11, 0x00, 0x94, 0xae, 0xcb, 0x44, 0x00, 0x00, 0x2f, 0x00, 0x3e, 0x79, + 0xc3, 0x41, 0xf0, 0x00, 0x40, 0x02, 0x80, 0xd8, 0x08, 0xa1, 0x0c, 0x81, + 0xe7, 0xb8, 0xe0, 0x7d, 0x2f, 0x27, 0x3f, 0x00, 0x6f, 0x23, 0x3f, 0x00, + 0x44, 0x81, 0xa7, 0xba, 0x44, 0xa1, 0x2f, 0x26, 0x3f, 0x00, 0xe0, 0x7e, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x13, 0x00, 0x2c, 0x61, 0xcb, 0x44, 0x00, 0x00, 0x5b, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x13, 0x00, 0x44, 0x61, 0xcb, 0x44, 0x00, 0x00, 0x5c, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x13, 0x00, 0x88, 0x63, 0xcb, 0x44, 0x00, 0x00, 0x26, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0x80, 0x4c, 0xcb, 0x44, 0x00, 0x00, 0x27, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0xc0, 0x4c, 0xcb, 0x44, 0x00, 0x00, 0x28, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0xe8, 0x00, 0xcb, 0x44, 0x00, 0x00, 0x18, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0xa4, 0x01, 0xcb, 0x44, 0x00, 0x00, 0x17, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0x34, 0x6c, 0xcb, 0x44, 0x00, 0x00, 0x16, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0xdc, 0x09, 0xcb, 0x44, 0x00, 0x00, 0x15, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0xf4, 0x09, 0xcb, 0x44, 0x00, 0x00, 0x14, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0x04, 0x0a, 0xcb, 0x44, 0x00, 0x00, 0x13, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x12, 0x00, 0x2c, 0x0a, 0xcb, 0x44, 0x00, 0x00, 0x12, 0x00, 0x3e, 0x79, + 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, + 0x13, 0x00, 0x6c, 0x6a, 0x1d, 0xdc, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, + 0x51, 0x24, 0x80, 0x93, 0xe0, 0x20, 0x82, 0x0f, 0x12, 0x00, 0xc0, 0x4b, + 0x1f, 0xdc, 0x3e, 0x79, 0x6a, 0x24, 0x80, 0x12, 0x51, 0x24, 0x80, 0x93, + 0xe0, 0x20, 0x82, 0x0f, 0x12, 0x00, 0x40, 0x4c, 0x21, 0xdc, 0x3e, 0x79, + 0x9b, 0xc9, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x67, 0x17, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x5e, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x52, 0x00, 0x04, 0x7f, 0x20, 0x01, 0x40, 0x04, 0x00, 0x6f, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x22, 0x7a, 0x08, 0x41, 0x00, 0x05, + 0x00, 0x00, 0x17, 0x7a, 0x08, 0x41, 0x00, 0x0a, 0x00, 0x00, 0x18, 0x7a, + 0x08, 0x41, 0x00, 0x0a, 0x00, 0x00, 0xfe, 0x7a, 0x08, 0x41, 0x00, 0x07, + 0x00, 0x28, 0x00, 0x00, 0x39, 0x00, 0xc3, 0x00, 0x01, 0x52, 0x00, 0x04, + 0x7f, 0x50, 0x01, 0x40, 0x06, 0x00, 0x6f, 0x03, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x02, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x40, 0xfe, 0xff, + 0x18, 0xff, 0x00, 0x01, 0x00, 0x40, 0x40, 0x00, 0x40, 0x10, 0x00, 0x00, + 0xff, 0x00, 0x00, 0x00, 0xff, 0x80, 0x80, 0x08, 0x00, 0xff, 0xfe, 0x7f, + 0x18, 0x7f, 0xff, 0x02, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x7f, 0xff, 0x4f, + 0xff, 0xff, 0x7f, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x01, 0x40, 0xfe, 0x40, + 0x88, 0x00, 0x00, 0x03, 0x00, 0x40, 0x40, 0xff, 0x40, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, 0x00, 0x40, 0x40, 0x40, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x40, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x40, 0xff, + 0x40, 0xff, 0xff, 0x00, 0xff, 0x40, 0x40, 0x40, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x40, 0xff, 0x40, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, 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, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0xff, 0x00, 0xff, 0x80, 0x80, + 0x80, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x80, 0xff, 0x00, 0x00, 0x00, 0xff, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x00, 0xff, 0x00, 0xff, 0x80, 0x80, 0xff, 0x00, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, 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, 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, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xfe, 0x00, 0x88, 0x00, 0x00, 0x04, + 0x00, 0x12, 0x00, 0x20, 0x00, 0x3c, 0xac, 0x00, 0xac, 0x12, 0x20, 0x20, + 0x12, 0x3c, 0xac, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0xcd, 0xcc, 0xcc, 0xcd, 0x3d, 0xcc, 0x3d, 0xcc, 0x00, 0xcc, 0x00, + 0xcd, 0x00, 0x00, 0x3d, 0x00, 0x58, 0x00, 0x8b, 0x00, 0x3a, 0xa0, 0x00, + 0xa0, 0x58, 0x8b, 0x8b, 0x58, 0x3a, 0xa0, 0x3a, 0xac, 0x12, 0x20, 0x20, + 0x12, 0x3c, 0xac, 0x3c, 0xac, 0x58, 0x20, 0x8b, 0x12, 0x3a, 0xa0, 0x3c, + 0xa0, 0x58, 0x8b, 0x8b, 0x58, 0x3a, 0xa0, 0x3a, 0xac, 0x12, 0x20, 0x20, + 0x12, 0x3c, 0xac, 0x3c, 0xcc, 0xcd, 0xcc, 0xcc, 0xcd, 0x3d, 0xcc, 0x3d, + 0xcc, 0xcd, 0xcc, 0xcc, 0xcd, 0x3d, 0xcc, 0x3d, 0xcc, 0x58, 0xcc, 0x8b, + 0xcd, 0x3a, 0xa0, 0x3d, 0xa0, 0x00, 0x8b, 0x00, 0x58, 0x00, 0x00, 0x3a, + 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, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x0a, 0x1c, 0x1c, + 0x0a, 0x41, 0xe8, 0x41, 0xe8, 0x12, 0x1c, 0x20, 0x0a, 0x3c, 0xac, 0x41, + 0xac, 0x12, 0x20, 0x20, 0x12, 0x3c, 0xac, 0x3c, 0x01, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 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, 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, 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, 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, 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, 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, 0x01, 0xfe, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x87, 0x00, 0x00, + 0x03, 0x00, 0x6e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x03, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x70, 0xc9, 0x13, 0x00, 0x38, 0xc9, 0x13, 0x00, + 0xf1, 0xc0, 0x0e, 0x08, 0x00, 0x00, 0xd1, 0xc0, 0xe0, 0x7f, 0x0c, 0x70, + 0xe4, 0xc2, 0xad, 0x70, 0xcb, 0x46, 0xa1, 0x00, 0xac, 0x29, 0x00, 0x86, + 0x21, 0x86, 0x02, 0x79, 0x0b, 0x09, 0x72, 0x01, 0x22, 0xb9, 0x66, 0x0a, + 0xcf, 0xff, 0xa5, 0x71, 0xef, 0x0d, 0x34, 0x94, 0x08, 0xe6, 0xc4, 0xc6, + 0x49, 0x4e, 0x49, 0x03, 0x54, 0x3b, 0x11, 0x00, 0x50, 0x29, 0xa1, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x00, 0x02, 0x01, 0x05, 0x02, + 0x04, 0xc4, 0xc3, 0x13, 0x00, 0x03, 0x08, 0xf4, 0x06, 0x08, 0xdc, 0x06, + 0x08, 0x0c, 0xc4, 0x13, 0x34, 0xe8, 0x00, 0x06, 0x02, 0x20, 0x24, 0x02, + 0x08, 0x03, 0x20, 0x3c, 0xc5, 0x13, 0x00, 0x01, 0x02, 0x10, 0x54, 0x02, + 0x08, 0x02, 0x07, 0x0c, 0x03, 0x01, 0x00, 0x03, 0x20, 0x88, 0xc7, 0x13, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0xc6, 0x13, 0x00, 0x00, 0x00, 0x00, + 0xac, 0x29, 0xa1, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xda, 0x6c, + 0x3e, 0xa1, 0x00, 0x0f, 0x04, 0x0b, 0x10, 0x48, 0x02, 0x20, 0x4c, 0x06, + 0x04, 0x50, 0x02, 0x08, 0x03, 0x04, 0x54, 0x02, 0x08, 0x0b, 0x04, 0x6e, + 0x0f, 0x58, 0x02, 0x10, 0x0f, 0x04, 0x03, 0x10, 0x5c, 0x02, 0x18, 0x03, + 0x04, 0x68, 0x02, 0x08, 0x03, 0x04, 0x0b, 0x58, 0x07, 0x0c, 0x02, 0x03, + 0x00, 0x00, 0x00, 0x40, 0x14, 0x05, 0x7a, 0x3d, 0x04, 0x05, 0x00, 0x00, + 0xd6, 0xff, 0xf9, 0x3d, 0x08, 0x08, 0x03, 0x08, 0x79, 0x08, 0x04, 0x3e, + 0x10, 0x0c, 0x03, 0x08, 0xf9, 0x3e, 0x00, 0x00, 0x48, 0x41, 0x02, 0x1b, + 0x00, 0x00, 0x00, 0xc8, 0x41, 0x26, 0x63, 0x06, 0x02, 0x06, 0x02, 0x10, + 0x42, 0x07, 0x04, 0x08, 0xc8, 0x42, 0x02, 0x2b, 0x02, 0x0a, 0x48, 0x43, + 0x09, 0x02, 0x06, 0x02, 0x20, 0x43, 0xa2, 0xeb, 0x0a, 0x04, 0x08, 0x48, + 0x44, 0x0b, 0x02, 0x08, 0xd1, 0x02, 0x04, 0x0f, 0x03, 0x06, 0x10, 0x01, + 0x04, 0x08, 0x80, 0x04, 0x06, 0x0f, 0x05, 0x08, 0x10, 0x00, 0x61, 0x28, + 0x03, 0x28, 0x00, 0x0b, 0x88, 0x80, 0x10, 0x02, 0x11, 0x20, 0x80, 0x42, + 0x4c, 0x02, 0x07, 0x07, 0x03, 0x07, 0x00, 0xc0, 0x30, 0x81, 0x0b, 0xc0, + 0x00, 0x14, 0x14, 0x24, 0x04, 0x0a, 0x18, 0x48, 0x08, 0x11, 0x07, 0x17, + 0x08, 0x08, 0x44, 0x08, 0x15, 0x03, 0x03, 0x0b, 0x7d, 0x00, 0x04, 0x02, + 0x07, 0x80, 0x3d, 0xfa, 0x00, 0x04, 0x0f, 0x3e, 0xf4, 0x01, 0x02, 0x11, + 0x01, 0x03, 0x10, 0x3e, 0xe8, 0x03, 0x04, 0x7f, 0x3f, 0xd0, 0x07, 0x02, + 0x0f, 0x00, 0x80, 0x3f, 0x19, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, + 0x07, 0x00, 0x64, 0x00, 0x08, 0x00, 0xc8, 0x00, 0x09, 0x00, 0x90, 0x01, + 0x0a, 0x00, 0x00, 0x00, 0x20, 0x03, 0x0b, 0x00, 0x48, 0x2b, 0xa1, 0x00, + 0xef, 0x00, 0x00, 0x00, 0x00, 0x42, 0x2a, 0x00, 0x02, 0x01, 0x20, 0x01, + 0x10, 0x00, 0x0f, 0x01, 0x01, 0x0a, 0x05, 0x12, 0x21, 0x02, 0x07, 0xf0, + 0x02, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x19, 0x00, + 0x03, 0x78, 0x22, 0x00, 0x5c, 0xae, 0x13, 0x00, 0x7c, 0xaf, 0x08, 0x82, + 0x13, 0x00, 0x44, 0x02, 0x08, 0xb0, 0xb3, 0x13, 0x00, 0x4c, 0x02, 0x08, + 0xb8, 0xac, 0x13, 0x00, 0x78, 0x02, 0x04, 0x82, 0x38, 0x54, 0x02, 0x0c, + 0xf0, 0xbf, 0x13, 0x00, 0x94, 0x02, 0x08, 0xfc, 0xad, 0x13, 0x02, 0x3a, + 0x0f, 0x03, 0x05, 0x10, 0x64, 0x28, 0x60, 0x08, 0xa1, 0x00, 0x88, 0x27, + 0xa1, 0x05, 0x0d, 0x0a, 0x06, 0xb8, 0x1e, 0x05, 0x3e, 0x09, 0x0f, 0x48, + 0x44, 0x00, 0x00, 0xa4, 0x4f, 0x80, 0x3f, 0x02, 0x7a, 0x00, 0x08, 0x06, + 0x15, 0x01, 0x02, 0x08, 0x04, 0x04, 0x02, 0x90, 0x02, 0x0b, 0x04, 0x03, + 0x21, 0x01, 0x0f, 0xc0, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x0f, 0xc0, 0x02, + 0x30, 0x05, 0xc0, 0xa0, 0x00, 0xcc, 0xb9, 0x13, 0x00, 0x68, 0xbc, 0x13, + 0x00, 0x1c, 0x00, 0x41, 0xb8, 0x13, 0x00, 0xac, 0xbe, 0x13, 0x00, 0x6c, + 0x02, 0x10, 0x60, 0xb5, 0x13, 0x00, 0x20, 0x02, 0x04, 0x74, 0x15, 0x54, + 0x02, 0x0c, 0x24, 0x02, 0x18, 0xf4, 0x02, 0x08, 0x78, 0xb7, 0x13, 0x00, + 0x24, 0x02, 0xcc, 0x7c, 0x02, 0x0c, 0x00, 0x0e, 0x01, 0xa4, 0x63, 0x01, + 0x0f, 0xc0, 0x06, 0x20, 0xcd, 0xcc, 0x4c, 0x02, 0xb0, 0x06, 0x0d, 0x00, + 0x03, 0xc0, 0xc8, 0x41, 0x00, 0x00, 0xd0, 0x07, 0xd0, 0x06, 0x00, 0x07, + 0x05, 0x14, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x2c, 0xa1, 0x00, 0x0e, 0x04, 0x00, 0x00, + 0x00, 0xb2, 0x69, 0x00, 0x02, 0x01, 0xf0, 0x01, 0x02, 0x05, 0x0e, 0x03, + 0xc0, 0x0e, 0x10, 0x09, 0x0f, 0x48, 0x44, 0x09, 0x0c, 0x03, 0x09, 0x0b, + 0x06, 0x0a, 0x30, 0xf0, 0x6d, 0xac, 0x13, 0x00, 0x00, 0x03, 0x04, 0x06, + 0x10, 0x0f, 0x07, 0x0f, 0x10, 0x03, 0x10, 0xf1, 0x0f, 0x80, 0x02, 0x15, + 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x06, 0x32, 0x02, 0x03, 0x06, 0x0b, + 0x04, 0xc8, 0x43, 0x00, 0x00, 0xc8, 0x3f, 0x05, 0x12, 0x02, 0x06, 0x05, + 0x08, 0x0d, 0x06, 0x58, 0xab, 0x83, 0xcd, 0x02, 0x84, 0x0d, 0x13, 0x00, + 0x7f, 0xd6, 0xd0, 0x3d, 0x0e, 0x13, 0x08, 0x0f, 0xd1, 0x0f, 0x80, 0x02, + 0x1a, 0x05, 0x20, 0x02, 0x05, 0x02, 0x03, 0x7f, 0xdf, 0x0f, 0x80, 0x02, + 0x7c, 0x02, 0x80, 0x02, 0x19, 0x04, 0x03, 0x0f, 0x80, 0x04, 0x15, 0x00, + 0x0f, 0x80, 0x03, 0x16, 0x0f, 0x80, 0x03, 0x14, 0x07, 0x04, 0xcd, 0x0f, + 0x80, 0x02, 0x19, 0xbf, 0xf7, 0x07, 0x13, 0x0f, 0x80, 0x05, 0x80, 0x1f, + 0x00, 0x02, 0x31, 0x0a, 0x03, 0x28, 0x1f, 0x00, 0x0a, 0x1c, 0x0f, 0x0b, + 0x03, 0x10, 0xcb, 0x07, 0x6d, 0x03, 0x0d, 0x06, 0x04, 0x17, 0xda, 0xff, + 0xcd, 0x0f, 0x80, 0x0f, 0x80, 0x06, 0x2f, 0x0c, 0x07, 0x1f, 0x00, 0x03, + 0x1d, 0x1f, 0x00, 0x03, 0x14, 0x07, 0x04, 0xeb, 0x0f, 0x80, 0x02, 0x19, + 0x3f, 0x34, 0x02, 0x05, 0x0f, 0x03, 0x59, 0x6f, 0x0f, 0x10, 0x00, 0x02, + 0x2f, 0x1e, 0x04, 0x22, 0x70, 0x12, 0x00, 0x48, 0x2f, 0x84, 0x04, 0x1a, + 0x0f, 0x05, 0x05, 0x10, 0xa3, 0x0f, 0x80, 0x02, 0x17, 0x45, 0x6f, 0x7d, + 0x26, 0x00, 0x02, 0x0b, 0x0f, 0x03, 0x0a, 0x10, 0x02, 0x0f, 0x3a, 0x04, + 0x1c, 0x88, 0x02, 0x80, 0xb8, 0x02, 0x04, 0x04, 0x0d, 0x0f, 0x05, 0x0f, + 0x10, 0x02, 0x10, 0xfc, 0x7b, 0x3b, 0x0f, 0x46, 0x02, 0x14, 0x25, 0x02, + 0x04, 0x0f, 0x03, 0x05, 0x10, 0x3c, 0x00, 0x0a, 0x05, 0x14, 0x0d, 0x06, + 0x40, 0x0f, 0x7c, 0x0d, 0x1f, 0x0f, 0x0e, 0x00, 0xea, 0x3b, 0xeb, 0x0f, + 0x80, 0x02, 0x22, 0x3b, 0x1f, 0x80, 0x02, 0x14, 0x0f, 0x03, 0x00, 0x00, + 0x1f, 0x7f, 0x05, 0x22, 0xe8, 0x02, 0x80, 0x60, 0x1f, 0x80, 0x05, 0x1b, + 0x0f, 0x06, 0xed, 0xff, 0x04, 0x10, 0xf7, 0x0f, 0x80, 0x02, 0x16, 0x1c, + 0x02, 0x04, 0x03, 0x03, 0x2f, 0x80, 0x2f, 0x80, 0x03, 0x24, 0x0f, 0x04, + 0x2f, 0x80, 0x03, 0x20, 0x2f, 0x80, 0x03, 0x14, 0x07, 0x04, 0xb6, 0x3e, + 0xf3, 0x0f, 0x80, 0x02, 0x19, 0x0d, 0x02, 0x04, 0x03, 0x03, 0x03, 0x0f, + 0xe3, 0x00, 0x1c, 0x80, 0x4f, 0x80, 0x03, 0x33, 0x4f, 0x00, 0x04, 0x14, + 0xe1, 0x2e, 0xdc, 0xfe, 0x65, 0x42, 0x04, 0x09, 0x0f, 0x05, 0x02, 0x10, + 0xd0, 0x0f, 0x80, 0x02, 0x14, 0x0e, 0x26, 0x80, 0x0f, 0x80, 0x15, 0x00, + 0x02, 0x21, 0x04, 0x03, 0x4f, 0x80, 0x04, 0x15, 0xe8, 0xfb, 0x00, 0xc0, + 0xc6, 0x55, 0x00, 0x84, 0x06, 0x08, 0x03, 0x16, 0x0f, 0x80, 0x03, 0x14, + 0x07, 0x04, 0xcf, 0x0f, 0x80, 0x02, 0x19, 0x27, 0x59, 0x0f, 0x80, 0x05, + 0x80, 0x7f, 0xfb, 0x4f, 0x80, 0x02, 0x31, 0x0a, 0x03, 0x4f, 0x80, 0x0a, + 0x1b, 0x0f, 0x0b, 0x04, 0x10, 0xf4, 0x0f, 0x80, 0x02, 0x16, 0x0c, 0x02, + 0x04, 0x03, 0x03, 0x0f, 0x80, 0x0f, 0x80, 0x03, 0x24, 0xbf, 0xfd, 0x0f, + 0x04, 0x2f, 0x00, 0x03, 0x20, 0x1f, 0x00, 0x03, 0x14, 0x07, 0x04, 0xf6, + 0x0f, 0x80, 0x02, 0x19, 0x1f, 0x02, 0x04, 0x03, 0x03, 0x2f, 0x80, 0x0f, + 0x80, 0x03, 0x24, 0x0f, 0x04, 0xdf, 0xfe, 0x0f, 0x80, 0x03, 0x20, 0x2f, + 0x80, 0x03, 0x14, 0x07, 0x04, 0xe9, 0x0f, 0x80, 0x02, 0x19, 0x3d, 0x3f, + 0x80, 0x02, 0x14, 0x0f, 0x03, 0x3f, 0x80, 0x07, 0x20, 0x3f, 0x80, 0x07, + 0x18, 0xdb, 0x7f, 0x0f, 0x08, 0x07, 0x10, 0xfa, 0x0f, 0x80, 0x02, 0x19, + 0x37, 0x0f, 0x80, 0x02, 0x14, 0x0f, 0x03, 0x0f, 0x80, 0x07, 0x20, 0x0f, + 0x80, 0x07, 0x18, 0x0f, 0x08, 0x07, 0x10, 0xf9, 0x7b, 0xa3, 0x0f, 0x80, + 0x02, 0x19, 0x34, 0x36, 0x00, 0x02, 0x0b, 0x0f, 0x03, 0x0a, 0x10, 0x02, + 0x87, 0x27, 0x0a, 0x14, 0x00, 0x00, 0x18, 0x42, 0x7c, 0xd0, 0x42, 0x84, + 0x37, 0xdf, 0x0c, 0x15, 0x0f, 0x0d, 0x0a, 0x10, 0xf8, 0x0f, 0x80, 0x02, + 0x1c, 0x32, 0x30, 0x02, 0x05, 0x0f, 0x03, 0x0f, 0x10, 0x5f, 0x00, 0x06, + 0x20, 0xa0, 0x02, 0x7c, 0x5f, 0x00, 0xb7, 0xff, 0x06, 0x1b, 0x0f, 0x07, + 0x04, 0x10, 0xec, 0x0f, 0x80, 0x02, 0x16, 0x30, 0x1f, 0x80, 0x02, 0x14, + 0x0f, 0x03, 0x1f, 0x80, 0x07, 0x20, 0x0f, 0x80, 0x07, 0x18, 0x0f, 0x08, + 0x07, 0x10, 0xf6, 0xbf, 0xc0, 0x0f, 0x80, 0x02, 0x19, 0x06, 0x16, 0x5a, + 0x3f, 0x00, 0x3f, 0x00, 0x02, 0x2b, 0x0f, 0x03, 0x5f, 0x00, 0x04, 0x20, + 0x3f, 0x00, 0x04, 0x15, 0x06, 0x05, 0xcc, 0x0f, 0x80, 0xfd, 0xdf, 0x02, + 0x18, 0x07, 0x0f, 0x80, 0x02, 0x14, 0x05, 0x03, 0x5f, 0x80, 0x05, 0x16, + 0x0b, 0x06, 0x3f, 0x80, 0x03, 0x1c, 0x0f, 0x80, 0x03, 0x14, 0x07, 0x04, + 0xa4, 0x0f, 0x80, 0x02, 0x19, 0xdc, 0x6f, 0x46, 0x24, 0x02, 0x05, 0x0f, + 0x03, 0x0f, 0x10, 0x00, 0x8f, 0x00, 0x05, 0x21, 0x8f, 0x00, 0x05, 0x16, + 0x0f, 0x06, 0x09, 0x10, 0xc8, 0x0f, 0x80, 0x02, 0x1b, 0x26, 0xff, 0xdb, + 0x16, 0x00, 0x02, 0x0b, 0x0e, 0x03, 0x1c, 0x00, 0x57, 0xa7, 0x0c, 0x24, + 0x8f, 0x00, 0x0c, 0x1d, 0x0f, 0x0d, 0x02, 0x10, 0xe8, 0x0f, 0x80, 0x02, + 0x14, 0x39, 0x2f, 0x80, 0x02, 0x14, 0x7f, 0xfb, 0x0f, 0x03, 0x2f, 0x80, + 0x07, 0x20, 0x4f, 0x00, 0x07, 0x18, 0x0f, 0x08, 0x07, 0x10, 0xc6, 0x0f, + 0x80, 0x02, 0x19, 0x1d, 0x16, 0x00, 0x2f, 0x80, 0x2f, 0x80, 0x02, 0x2b, + 0x0f, 0x03, 0xdf, 0xfe, 0x2f, 0x80, 0x04, 0x20, 0x2f, 0x00, 0x04, 0x15, + 0x06, 0x05, 0xc2, 0x0f, 0x80, 0x02, 0x18, 0x0f, 0x06, 0x80, 0x6f, 0x80, + 0x0f, 0x80, 0x02, 0x2b, 0x0f, 0x03, 0x0f, 0x80, 0x04, 0x20, 0xb7, 0xff, + 0x6f, 0x80, 0x04, 0x15, 0x06, 0x05, 0xc3, 0x0f, 0x80, 0x02, 0x18, 0x10, + 0x0f, 0x80, 0x02, 0x14, 0x05, 0x03, 0x2c, 0x00, 0x8f, 0x80, 0x04, 0x23, + 0x3f, 0x00, 0x03, 0x15, 0x0f, 0x80, 0xdb, 0xff, 0x03, 0x14, 0x07, 0x04, + 0xc5, 0x0f, 0x80, 0x02, 0x19, 0x20, 0x06, 0x80, 0x1f, 0x80, 0x1f, 0x00, + 0x02, 0x2b, 0x0f, 0x03, 0x1f, 0x00, 0x04, 0x20, 0x1f, 0x80, 0x04, 0x15, + 0x06, 0x05, 0xf6, 0xdf, 0xa0, 0x0f, 0x80, 0x02, 0x18, 0x4d, 0x2f, 0x80, + 0x02, 0x14, 0x0f, 0x03, 0x2f, 0x80, 0x07, 0x20, 0x2f, 0x80, 0x07, 0x18, + 0x0f, 0x08, 0x07, 0x10, 0xa1, 0x0f, 0x80, 0x02, 0x19, 0xfe, 0xdb, 0x4b, + 0x0f, 0x80, 0x02, 0x14, 0x0f, 0x03, 0x0f, 0x80, 0x07, 0x20, 0x0f, 0x80, + 0x07, 0x18, 0x0f, 0x08, 0x07, 0x10, 0xe7, 0x0f, 0x80, 0x02, 0x19, 0x35, + 0x4f, 0x80, 0x02, 0x14, 0x7f, 0xec, 0x0f, 0x03, 0x02, 0x80, 0x16, 0xa6, + 0x0d, 0x1a, 0x7f, 0x00, 0x0d, 0x1e, 0x0f, 0x0e, 0x00, 0x00, 0xe6, 0x0f, + 0x80, 0x02, 0x23, 0x5e, 0x1f, 0x00, 0x02, 0x14, 0x0f, 0x03, 0x7f, 0xfb, + 0x02, 0x80, 0x0f, 0x13, 0x04, 0x10, 0x6f, 0x80, 0x04, 0x15, 0x0f, 0x05, + 0x0a, 0x10, 0xa2, 0x0f, 0x80, 0x02, 0x1c, 0x43, 0x0f, 0x80, 0x02, 0x14, + 0x0f, 0x03, 0x0f, 0x80, 0x07, 0x20, 0x07, 0x00, 0x0f, 0x80, 0x07, 0x18, + 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x3d, 0xa1, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x00, 0x32, 0xdd, 0x00, 0x02, 0x01, 0xe0, 0x01, + 0x02, 0x05, 0x0e, 0x03, 0xd0, 0x41, 0x03, 0x11, 0x19, 0x03, 0x05, 0x0f, + 0x04, 0x0a, 0x10, 0x03, 0x0a, 0x0c, 0x09, 0x0b, 0x18, 0x00, 0x6c, 0xc6, + 0x13, 0x09, 0x0d, 0x0f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x3e, 0xa1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x5c, 0x29, 0xa1, + 0x00, 0x00, 0x00, 0x00, 0x4c, 0x3e, 0xa1, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0xa4, 0x29, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x50, 0x3e, 0xa1, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x64, 0x29, 0xa1, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x3e, 0xa1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x6c, 0x29, 0xa1, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x3e, 0xa1, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x54, 0x29, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x3e, 0xa1, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x01, 0x74, 0x29, 0xa1, 0x00, 0x7c, 0x29, 0xa1, + 0x00, 0x9c, 0x29, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x68, 0x3e, 0xa1, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x84, 0x29, 0xa1, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x27, 0xa1, 0x00, 0x38, 0xfe, 0xff, 0xff, 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, + 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, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/lib/SensorLib/src/platform/esp_arduino.cpp b/lib/SensorLib/src/platform/esp_arduino.cpp new file mode 100644 index 0000000..169265a --- /dev/null +++ b/lib/SensorLib/src/platform/esp_arduino.cpp @@ -0,0 +1,66 @@ +/** + * @file esp_arduino.cpp + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd + * @date 2024-01-08 + * + */ +#if !defined(ARDUINO) && defined(ESP_PLATFORM) +#include "SensorLib.h" +#include "driver/gpio.h" +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include + + +void pinMode(uint32_t gpio, uint8_t mode) +{ + gpio_config_t config; + memset(&config, 0, sizeof(config)); + config.pin_bit_mask = 1ULL << gpio; + switch (mode) { + case INPUT: + config.mode = GPIO_MODE_INPUT; + break; + case OUTPUT: + config.mode = GPIO_MODE_OUTPUT; + break; + } + config.pull_up_en = GPIO_PULLUP_DISABLE; + config.pull_down_en = GPIO_PULLDOWN_DISABLE; + config.intr_type = GPIO_INTR_DISABLE; + ESP_ERROR_CHECK(gpio_config(&config)); +} + +void digitalWrite(uint32_t gpio, uint8_t level) +{ + gpio_set_level((gpio_num_t )gpio, level); +} + +int digitalRead(uint32_t gpio) +{ + return gpio_get_level((gpio_num_t)gpio); +} + +void delay(uint32_t ms) +{ + vTaskDelay(pdMS_TO_TICKS(ms)); + ets_delay_us((ms % portTICK_PERIOD_MS) * 1000UL); +} + +uint32_t millis() +{ + return (uint32_t) (esp_timer_get_time() / 1000LL); +} + +uint32_t micros() +{ + return (uint32_t) esp_timer_get_time(); +} + +void delayMicroseconds(uint32_t us) +{ + ets_delay_us(us); +} +#endif diff --git a/lib/SensorLib/src/platform/esp_arduino.h b/lib/SensorLib/src/platform/esp_arduino.h new file mode 100644 index 0000000..876de66 --- /dev/null +++ b/lib/SensorLib/src/platform/esp_arduino.h @@ -0,0 +1,22 @@ +/** + * @file esp_arduino.h + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd + * @date 2024-01-08 + * + */ +#pragma once + +#if !defined(ARDUINO) && defined(ESP_PLATFORM) + +void pinMode(uint32_t gpio, uint8_t mode); +void digitalWrite(uint32_t gpio, uint8_t level); +int digitalRead(uint32_t gpio); +void delay(uint32_t ms); +uint32_t millis(); +uint32_t micros(); +void delayMicroseconds(uint32_t us); + +#endif + diff --git a/lib/SensorLib/src/touch/TouchClassCST226.cpp b/lib/SensorLib/src/touch/TouchClassCST226.cpp new file mode 100644 index 0000000..8d292cb --- /dev/null +++ b/lib/SensorLib/src/touch/TouchClassCST226.cpp @@ -0,0 +1,323 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file TouchClassCST226.cpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-06 + */ +#include "TouchClassCST226.h" + +#define CST2xx_REG_STATUS (0x00) +#define CST226SE_BUFFER_NUM (28) + +#if defined(ARDUINO) +TouchClassCST226::TouchClassCST226() +{ + +} + +bool TouchClassCST226::begin(PLATFORM_WIRE_TYPE &wire, uint8_t address, int sda, int scl) +{ + return SensorCommon::begin(wire, address, sda, scl); +} + +#elif defined(ESP_PLATFORM) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) +bool TouchClassCST226::begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) +{ + return SensorCommon::begin(i2c_dev_bus_handle, addr); +} +#else +bool TouchClassCST226::begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) +{ + return SensorCommon::begin(port_num, addr, sda, scl); +} +#endif //ESP_IDF_VERSION + +#endif //ARDUINO + + +bool TouchClassCST226::begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) +{ + return SensorCommon::begin(addr, readRegCallback, writeRegCallback); +} + +void TouchClassCST226::reset() +{ + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OUTPUT); + this->setGpioLevel(__rst, LOW); + delay(100); + this->setGpioLevel(__rst, HIGH); + delay(100); + } else { + writeRegister(0xD1, 0x0E); + delay(20); + } +} + +uint8_t TouchClassCST226::getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point) +{ + uint8_t buffer[CST226SE_BUFFER_NUM]; + uint8_t index = 0; + + if (readRegister(CST2xx_REG_STATUS, buffer, CST226SE_BUFFER_NUM) == DEV_WIRE_ERR) { + return 0; + } + +#ifdef LOG_PORT + LOG_PORT.print("RAW:"); + for (int i = 0; i < CST226SE_BUFFER_NUM; ++i) { + LOG_PORT.printf("%02X,", buffer[i]); + } + LOG_PORT.println(); +#endif + + if (buffer[0] == 0x83 && buffer[1] == 0x17 && buffer[5] == 0x80) { + if (__homeButtonCb) { + __homeButtonCb(__userData); + } + return 0; + } + + if (buffer[6] != 0xAB)return 0; + if (buffer[0] == 0xAB)return 0; + if (buffer[5] == 0x80)return 0; + + uint8_t point = buffer[5] & 0x7F; + if (point > 5 || !point) { + writeRegister(0x00, 0xAB); + return 0; + } + + for (int i = 0; i < point; i++) { + report.id[i] = buffer[index] >> 4; + report.status[i] = buffer[index] & 0x0F; + report.x[i] = (uint16_t)((buffer[index + 1] << 4) | ((buffer[index + 3] >> 4) & 0x0F)); + report.y[i] = (uint16_t)((buffer[index + 2] << 4) | (buffer[index + 3] & 0x0F)); + report.pressure[i] = buffer[index + 4]; + index = (i == 0) ? (index + 7) : (index + 5); + } + + updateXY(point, report.x, report.y); + +#ifdef LOG_PORT + for (int i = 0; i < point; i++) { + LOG_PORT.printf("[%d]-X:%u Y:%u P:%u sta:%u ", report.id[i], report.x[i], report.y[i], report.pressure[i], report.status[i]); + } + LOG_PORT.println(); +#endif + + if (point) { + for (int i = 0; i < get_point; i++) { + x_array[i] = report.x[i]; + y_array[i] = report.y[i]; + } + } + + return point; +} + +bool TouchClassCST226::isPressed() +{ + static uint32_t lastPulse = 0; + if (__irq != SENSOR_PIN_NONE) { + int val = this->getGpioLevel(__irq) == LOW; + if (val) { + //Filter low levels with intervals greater than 1000ms + val = (millis() - lastPulse > 1000) ? false : true; + lastPulse = millis(); + return val; + } + return false; + } + return getPoint(NULL, NULL, 1); +} + + +const char *TouchClassCST226::getModelName() +{ + return "CST226SE"; +} + +void TouchClassCST226::sleep() +{ + writeRegister(0xD1, 0x05); +#ifdef ESP32 + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, OPEN_DRAIN); + } + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OPEN_DRAIN); + } +#endif +} + +void TouchClassCST226::wakeup() +{ + reset(); +} + +void TouchClassCST226::idle() +{ + +} + +uint8_t TouchClassCST226::getSupportTouchPoint() +{ + return 5; +} + +bool TouchClassCST226::getResolution(int16_t *x, int16_t *y) +{ + return false; +} + +void TouchClassCST226::setHomeButtonCallback(home_button_callback_t cb, void *user_data) +{ + __homeButtonCb = cb; + __userData = user_data; +} + +void TouchClassCST226::setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb) +{ + SensorCommon::setGpioModeCallback(mode_cb); + SensorCommon::setGpioWriteCallback(write_cb); + SensorCommon::setGpioReadCallback(read_cb); +} + +bool TouchClassCST226::initImpl() +{ + + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OUTPUT); + } + + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, INPUT); + } + + reset(); + + uint8_t buffer[8]; + // Enter Command mode + writeRegister(0xD1, 0x01); + delay(10); + uint8_t write_buffer[2] = {0xD1, 0xFC}; + writeThenRead(write_buffer, 2, buffer, 4); + uint32_t checkcode = 0; + checkcode = buffer[3]; + checkcode <<= 8; + checkcode |= buffer[2]; + checkcode <<= 8; + checkcode |= buffer[1]; + checkcode <<= 8; + checkcode |= buffer[0]; + + log_i("Chip checkcode:0x%lx.\r\n", checkcode); + + write_buffer[0] = {0xD1}; + write_buffer[1] = {0xF8}; + writeThenRead(write_buffer, 2, buffer, 4); + __resX = ( buffer[1] << 8) | buffer[0]; + __resY = ( buffer[3] << 8) | buffer[2]; + log_i("Chip resolution X:%u Y:%u\r\n", __resX, __resY); + + write_buffer[0] = {0xD2}; + write_buffer[1] = {0x04}; + writeThenRead(write_buffer, 2, buffer, 4); + uint32_t chipType = buffer[3]; + chipType <<= 8; + chipType |= buffer[2]; + + + uint32_t ProjectID = buffer[1]; + ProjectID <<= 8; + ProjectID |= buffer[0]; + log_i("Chip type :0x%lx, ProjectID:0X%lx\r\n", + chipType, ProjectID); + + + + write_buffer[0] = {0xD2}; + write_buffer[1] = {0x08}; + writeThenRead(write_buffer, 2, buffer, 8); + + uint32_t fwVersion = buffer[3]; + fwVersion <<= 8; + fwVersion |= buffer[2]; + fwVersion <<= 8; + fwVersion |= buffer[1]; + fwVersion <<= 8; + fwVersion |= buffer[0]; + + uint32_t checksum = buffer[7]; + checksum <<= 8; + checksum |= buffer[6]; + checksum <<= 8; + checksum |= buffer[5]; + checksum <<= 8; + checksum |= buffer[4]; + + log_i("Chip ic version:0x%lx, checksum:0x%lx\n", + fwVersion, checksum); + + if (fwVersion == 0xA5A5A5A5) { + log_i("Chip ic don't have firmware. \n"); + return false; + } + if ((checkcode & 0xffff0000) != 0xCACA0000) { + log_i("Firmware info read error .\n"); + return false; + } + + __chipID = chipType; + + // Exit Command mode + writeRegister(0xD1, 0x09); + return true; +} + +int TouchClassCST226::getReadMaskImpl() +{ + return -1; +} + + + + + + + + + + + + + + + diff --git a/lib/SensorLib/src/touch/TouchClassCST226.h b/lib/SensorLib/src/touch/TouchClassCST226.h new file mode 100644 index 0000000..7d1ceaa --- /dev/null +++ b/lib/SensorLib/src/touch/TouchClassCST226.h @@ -0,0 +1,97 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file TouchClassCST226.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-06 + */ +#pragma once + +#include "../TouchDrvInterface.hpp" +#include "../SensorCommon.tpp" + +class TouchClassCST226 : public TouchDrvInterface, + public SensorCommon +{ + friend class SensorCommon; + +public: + +#if defined(ARDUINO) + TouchClassCST226(); + + bool begin(PLATFORM_WIRE_TYPE &wire, uint8_t address, int sda, int scl); + +#elif defined(ESP_PLATFORM) +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr); +#else + bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl); +#endif //ESP_IDF_VERSION + +#endif + + bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback); + + void reset(); + + uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point); + + bool isPressed(); + + const char *getModelName(); + + void sleep(); + + void wakeup(); + + void idle(); + + uint8_t getSupportTouchPoint(); + + bool getResolution(int16_t *x, int16_t *y); + + void setHomeButtonCallback(home_button_callback_t cb, void *user_data); + + void setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb); + +private: + bool initImpl(); + int getReadMaskImpl(); +protected: + TouchData report; + +}; + + + + + + + + + + diff --git a/lib/SensorLib/src/touch/TouchClassCST816.cpp b/lib/SensorLib/src/touch/TouchClassCST816.cpp new file mode 100644 index 0000000..2d7708f --- /dev/null +++ b/lib/SensorLib/src/touch/TouchClassCST816.cpp @@ -0,0 +1,328 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file TouchClassCST816.cpp + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-06 + */ +#include "TouchClassCST816.h" + +#define CST8xx_REG_STATUS (0x00) +#define CST8xx_REG_XPOS_HIGH (0x03) +#define CST8xx_REG_XPOS_LOW (0x04) +#define CST8xx_REG_YPOS_HIGH (0x05) +#define CST8xx_REG_YPOS_LOW (0x06) +#define CST8xx_REG_DIS_AUTOSLEEP (0xFE) +#define CST8xx_REG_CHIP_ID (0xA7) +#define CST8xx_REG_FW_VERSION (0xA9) +#define CST8xx_REG_SLEEP (0xE5) + +#define CST816S_CHIP_ID (0xB4) +#define CST816T_CHIP_ID (0xB5) +#define CST716_CHIP_ID (0x20) +#define CST820_CHIP_ID (0xB7) +#define CST816D_CHIP_ID (0xB6) + +#if defined(ARDUINO) +TouchClassCST816::TouchClassCST816(): + __center_btn_x(0), + __center_btn_y(0) +{ +} + +bool TouchClassCST816::begin(PLATFORM_WIRE_TYPE &wire, uint8_t address, int sda, int scl) +{ + return SensorCommon::begin(wire, address, sda, scl); +} + +#elif defined(ESP_PLATFORM) + +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) +bool TouchClassCST816::begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) +{ + return SensorCommon::begin(i2c_dev_bus_handle, addr); +} +#else +bool TouchClassCST816::begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) +{ + return SensorCommon::begin(port_num, addr, sda, scl); +} + +#endif //ESP_IDF_VERSION +#endif //ARDUINO + +bool TouchClassCST816::begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) +{ + return SensorCommon::begin(addr, readRegCallback, writeRegCallback); +} + +void TouchClassCST816::reset() +{ + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OUTPUT); + this->setGpioLevel(__rst, LOW); + delay(30); + this->setGpioLevel(__rst, HIGH); + delay(50); + } +} + +uint8_t TouchClassCST816::getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point) +{ + uint8_t buffer[13]; + if (readRegister(CST8xx_REG_STATUS, buffer, 13) == DEV_WIRE_ERR) { + return 0; + } + + if (!buffer[2] || !x_array || !y_array || !get_point) { + return 0; + } + + // Some CST816T will return all 0xFF after turning off automatic sleep. + if (buffer[2] == 0xFF) { + return 0; + } + + // Only suitable for AMOLED 1.91 inch + // RAW:00,00,01,80,78,02,58,00,00,FF,FF,FF,FF, + // if (buffer[2] == 0x01 && buffer[3] == 0x80 && buffer[4] == 0x78 && buffer[5] == 0x02 && buffer[6] == 0x58) { + // if (__homeButtonCb) { + // __homeButtonCb(__userData); + // } + // return 0; + // } + + uint8_t point = buffer[2] & 0x0F; + + // CST816 only supports single touch + if (point > 1) { + return 0; + } + +#ifdef LOG_PORT + LOG_PORT.print("RAW:"); + for (int i = 0; i < 13; ++i) { + LOG_PORT.printf("%02X,", buffer[i]); + } + LOG_PORT.println(); +#endif + + int16_t tmp_x, tmp_y; + + tmp_x = ((buffer[CST8xx_REG_XPOS_HIGH] & 0x0F) << 8 | buffer[CST8xx_REG_XPOS_LOW]); + tmp_y = ((buffer[CST8xx_REG_YPOS_HIGH] & 0x0F) << 8 | buffer[CST8xx_REG_YPOS_LOW]); + + // Depends on touch screen firmware + if (tmp_x == __center_btn_x && tmp_y == __center_btn_y && __homeButtonCb) { + __homeButtonCb(__userData); + return 0; + } + + // if (get_point == 2) { + // x_array[1] = ((buffer[((uint8_t)0x09)] & 0x0F) << 8 | buffer[((uint8_t)0x10)]); + // y_array[1] = ((buffer[((uint8_t)0x11)] & 0x0F) << 8 | buffer[((uint8_t)0x12)]); + // } + + x_array[0] = tmp_x; + y_array[0] = tmp_y; + +#ifdef LOG_PORT + for (int i = 0; i < point; i++) { + LOG_PORT.printf("[%d] --> X:%d Y:%d \n", i, x_array[i], y_array[i]); + } +#endif + updateXY(point, x_array, y_array); + + return point; +} + +bool TouchClassCST816::isPressed() +{ + static uint32_t lastPulse = 0; + if (__irq != SENSOR_PIN_NONE) { + int val = this->getGpioLevel(__irq) == LOW; + if (val) { + //Filter low levels with intervals greater than 1000ms + val = (millis() - lastPulse > 1000) ? false : true; + lastPulse = millis(); + return val; + } + return false; + } + return getPoint(NULL, NULL, 1); +} + + +const char *TouchClassCST816::getModelName() +{ + switch (__chipID) { + case CST816S_CHIP_ID: + return "CST816S"; + case CST816T_CHIP_ID: + return "CST816T"; + case CST716_CHIP_ID: + return "CST716"; + case CST820_CHIP_ID: + return "CST820"; + case CST816D_CHIP_ID: + return "CST816D"; + default: + break; + } + return "UNKONW"; +} + +void TouchClassCST816::sleep() +{ + writeRegister(CST8xx_REG_SLEEP, 0x03); +#ifdef ESP32 + if (__irq != SENSOR_PIN_NONE) { + this->setGpioMode(__irq, OPEN_DRAIN); + } + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OPEN_DRAIN); + } +#endif +} + +void TouchClassCST816::wakeup() +{ + reset(); +} + +void TouchClassCST816::idle() +{ + +} + +uint8_t TouchClassCST816::getSupportTouchPoint() +{ + return 1; +} + +bool TouchClassCST816::getResolution(int16_t *x, int16_t *y) +{ + return false; +} + +void TouchClassCST816::setHomeButtonCallback(home_button_callback_t cb, void *user_data) +{ + __homeButtonCb = cb; + __userData = user_data; +} + +void TouchClassCST816::setCenterButtonCoordinate(int16_t x, int16_t y) +{ + __center_btn_x = x; + __center_btn_y = y; +} + + +void TouchClassCST816::disableAutoSleep() +{ + switch (__chipID) { + case CST816S_CHIP_ID: + case CST816T_CHIP_ID: + case CST820_CHIP_ID: + case CST816D_CHIP_ID: + reset(); + delay(50); + writeRegister(CST8xx_REG_DIS_AUTOSLEEP, 0x01); + break; + case CST716_CHIP_ID: + default: + break; + } +} + +void TouchClassCST816::enableAutoSleep() +{ + switch (__chipID) { + case CST816S_CHIP_ID: + case CST816T_CHIP_ID: + case CST820_CHIP_ID: + case CST816D_CHIP_ID: + reset(); + delay(50); + writeRegister(CST8xx_REG_DIS_AUTOSLEEP, 0x00); + break; + case CST716_CHIP_ID: + default: + break; + } +} + +void TouchClassCST816::setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb) +{ + SensorCommon::setGpioModeCallback(mode_cb); + SensorCommon::setGpioWriteCallback(write_cb); + SensorCommon::setGpioReadCallback(read_cb); +} + +bool TouchClassCST816::initImpl() +{ + + if (__rst != SENSOR_PIN_NONE) { + this->setGpioMode(__rst, OUTPUT); + } + + reset(); + + int chip_id = readRegister(CST8xx_REG_CHIP_ID); + log_i("Chip ID:0x%x\n", chip_id); + + int version = readRegister(CST8xx_REG_FW_VERSION); + log_i("Version :0x%x\n", version); + + // CST716 : 0x20 + // CST816S : 0xB4 + // CST816T : 0xB5 + // CST816D : 0xB6 + // CST226SE : A7 = 0X20 + if (chip_id != CST816S_CHIP_ID && + chip_id != CST816T_CHIP_ID && + chip_id != CST820_CHIP_ID && + chip_id != CST816D_CHIP_ID && + (chip_id != CST716_CHIP_ID || version == 0)) { + return false; + } + + __chipID = chip_id; + + log_i("Touch type:%s\n", getModelName()); + + return true; +} + +int TouchClassCST816::getReadMaskImpl() +{ + return -1; +} + + + + + diff --git a/lib/SensorLib/src/touch/TouchClassCST816.h b/lib/SensorLib/src/touch/TouchClassCST816.h new file mode 100644 index 0000000..e261a1a --- /dev/null +++ b/lib/SensorLib/src/touch/TouchClassCST816.h @@ -0,0 +1,102 @@ +/** + * + * @license MIT License + * + * Copyright (c) 2023 lewis he + * + * 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. + * + * @file TouchClassCST816.h + * @author Lewis He (lewishe@outlook.com) + * @date 2023-10-06 + */ +#pragma once + +#include "../TouchDrvInterface.hpp" +#include "../SensorCommon.tpp" +#include "../SensorLib.h" + +class TouchClassCST816 : public TouchDrvInterface, + public SensorCommon +{ + friend class SensorCommon; + +public: + +#if defined(ARDUINO) + TouchClassCST816(); + + bool begin(PLATFORM_WIRE_TYPE &wire, uint8_t address, int sda, int scl); + +#elif defined(ESP_PLATFORM) +#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)) + bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr); +#else + bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl); +#endif //ESP_IDF_VERSION +#endif + + bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback); + + + void reset(); + + uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point); + + bool isPressed(); + + const char *getModelName(); + + void sleep(); + + void wakeup(); + + void idle(); + + uint8_t getSupportTouchPoint(); + + bool getResolution(int16_t *x, int16_t *y); + + void setCenterButtonCoordinate(int16_t x, int16_t y); + + void setHomeButtonCallback(home_button_callback_t cb, void *user_data); + + void disableAutoSleep(); + + void enableAutoSleep(); + + void setGpioCallback(gpio_mode_fptr_t mode_cb, + gpio_write_fptr_t write_cb, + gpio_read_fptr_t read_cb); + +private: + bool initImpl(); + int getReadMaskImpl(); + +protected: + int16_t __center_btn_x; + int16_t __center_btn_y; +}; + + + + + + +