diff --git a/README.md b/README.md
index d6ee1a8..867a87f 100644
--- a/README.md
+++ b/README.md
@@ -32,15 +32,15 @@ What we need for functionality:
## Supported boards
-| Board name | Support | Stream | Micro SD | FLASH LED | FW update | DHT22/DHT11 | Documentation |
-|---------------------------|-------------|--------|----------|-----------|-----------|-------------|----------------------------------------------|
-| Ai-Thinker ESP32-cam | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/AI_Thinker-ESP32-cam/README.md) |
-| ESP32-S3-EYE 2.2 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/ESP32-S3-EYE-22/README.md) |
-| Freenove ESP32-Wrover cam | Full | Yes | No | External | Yes | Yes | [ here ](doc/ESP32-Wrover-dev/README.md) |
-| Freenove ESP32-S3-Wroom | in Progress | | | | | | |
-| ESP32-S3-DEV-CAM | in Progress | | | External | | | [ here ](doc/ESP32-S3-DEV-CAM/README.md) |
-| Seeed Studio XIAO ESP32S3 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/XIAO_ESP32S3/README.md) |
-| ESP32-S3-CAM | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/ESP32-S3-CAM/README.md) |
+| Board name | Support | Stream | Micro SD | FLASH LED | FW update | DHT22/DHT11 | Documentation |
+|---------------------------|-------------|--------|----------|-----------|-----------|-------------|------------------------------------------------|
+| Ai-Thinker ESP32-cam | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/AI_Thinker-ESP32-cam/README.md) |
+| ESP32-S3-EYE 2.2 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/ESP32-S3-EYE-22/README.md) |
+| Freenove ESP32-Wrover cam | Full | Yes | No | External | Yes | Yes | [ here ](doc/ESP32-Wrover-dev/README.md) |
+| Freenove ESP32-S3-Wroom | in Progress | | | | | | [ here ](doc/Freenove ESP32-S3-Wroom/README.md | |
+| ESP32-S3-DEV-CAM | in Progress | | | External | | | [ here ](doc/ESP32-S3-DEV-CAM/README.md) |
+| Seeed Studio XIAO ESP32S3 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/XIAO_ESP32S3/README.md) |
+| ESP32-S3-CAM | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/ESP32-S3-CAM/README.md) |
The compiled firmware for each supported board is published with every release.
diff --git a/doc/Freenove ESP32-S3-Wroom/Arduino_Configuration.png b/doc/Freenove ESP32-S3-Wroom/Arduino_Configuration.png
new file mode 100644
index 0000000..d9947d8
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/Arduino_Configuration.png differ
diff --git a/doc/Freenove ESP32-S3-Wroom/Board.jpg b/doc/Freenove ESP32-S3-Wroom/Board.jpg
new file mode 100644
index 0000000..4e0785b
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/Board.jpg differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/C_Tutorial.pdf b/doc/Freenove ESP32-S3-Wroom/C/C_Tutorial.pdf
new file mode 100644
index 0000000..204f881
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/C_Tutorial.pdf differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/DHT_sensor_library_for_ESPx-1.19.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/DHT_sensor_library_for_ESPx-1.19.zip
new file mode 100644
index 0000000..455dc88
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/DHT_sensor_library_for_ESPx-1.19.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP32-audioI2S-2.0.0.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP32-audioI2S-2.0.0.zip
new file mode 100644
index 0000000..bfbf63a
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP32-audioI2S-2.0.0.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP32Servo-3.0.4.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP32Servo-3.0.4.zip
new file mode 100644
index 0000000..f70adb0
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP32Servo-3.0.4.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP8266Audio-1.9.8.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP8266Audio-1.9.8.zip
new file mode 100644
index 0000000..0cddbda
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/ESP8266Audio-1.9.8.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/Freenove_IR_Lib_for_ESP32_v1.0.1.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/Freenove_IR_Lib_for_ESP32_v1.0.1.zip
new file mode 100644
index 0000000..fc2a62e
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/Freenove_IR_Lib_for_ESP32_v1.0.1.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/Freenove_WS2812_Lib_for_ESP32-2.0.0.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/Freenove_WS2812_Lib_for_ESP32-2.0.0.zip
new file mode 100644
index 0000000..0947a2b
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/Freenove_WS2812_Lib_for_ESP32-2.0.0.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/IRremoteESP8266-2.8.6.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/IRremoteESP8266-2.8.6.zip
new file mode 100644
index 0000000..a91641c
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/IRremoteESP8266-2.8.6.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/Keypad-3.1.1.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/Keypad-3.1.1.zip
new file mode 100644
index 0000000..cd49f00
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/Keypad-3.1.1.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/LiquidCrystal-1.0.7.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/LiquidCrystal-1.0.7.zip
new file mode 100644
index 0000000..4bd0b6a
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/LiquidCrystal-1.0.7.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/LiquidCrystal_I2C-1.1.2.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/LiquidCrystal_I2C-1.1.2.zip
new file mode 100644
index 0000000..b6eb2b7
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/LiquidCrystal_I2C-1.1.2.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/MPU6050_tockn-1.5.2.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/MPU6050_tockn-1.5.2.zip
new file mode 100644
index 0000000..5e09cd8
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/MPU6050_tockn-1.5.2.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Libraries/UltrasonicSensor-1.1.0.zip b/doc/Freenove ESP32-S3-Wroom/C/Libraries/UltrasonicSensor-1.1.0.zip
new file mode 100644
index 0000000..c4ed66e
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/C/Libraries/UltrasonicSensor-1.1.0.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_01.1_Blink/Sketch_01.1_Blink.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_01.1_Blink/Sketch_01.1_Blink.ino
new file mode 100644
index 0000000..5a8a894
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_01.1_Blink/Sketch_01.1_Blink.ino
@@ -0,0 +1,20 @@
+/**********************************************************************
+* Filename : Blink
+* Description : Make an led blinking.
+* Auther : www.freenove.com
+* Modification: 2022/10/19
+**********************************************************************/
+#define LED_BUILTIN 2
+// the setup function runs once when you press reset or power the board
+void setup() {
+ // initialize digital pin LED_BUILTIN as an output.
+ pinMode(LED_BUILTIN, OUTPUT);
+}
+
+// the loop function runs over and over again forever
+void loop() {
+ digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
+ delay(1000); // wait for a second
+ digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
+ delay(1000); // wait for a second
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_02.1_SerialPrinter/Sketch_02.1_SerialPrinter.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_02.1_SerialPrinter/Sketch_02.1_SerialPrinter.ino
new file mode 100644
index 0000000..97ff1cc
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_02.1_SerialPrinter/Sketch_02.1_SerialPrinter.ino
@@ -0,0 +1,16 @@
+/**********************************************************************
+ Filename : SerialPrinter
+ Description : Use UART send some data to PC, and show them on serial monitor.
+ Auther : www.freenove.com
+ Modification: 2022/10/20
+**********************************************************************/
+
+void setup() {
+ Serial.begin(115200);
+ Serial.println("ESP32S3 initialization completed!");
+}
+
+void loop() {
+ Serial.printf("Running time : %.1f s\r\n", millis() / 1000.0f);
+ delay(1000);
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_02.2_SerialRW/Sketch_02.2_SerialRW.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_02.2_SerialRW/Sketch_02.2_SerialRW.ino
new file mode 100644
index 0000000..6eb4a13
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_02.2_SerialRW/Sketch_02.2_SerialRW.ino
@@ -0,0 +1,30 @@
+/**********************************************************************
+ Filename : SerialRW
+ Description : Use UART read and write data between ESP32 and PC.
+ Auther : www.freenove.com
+ Modification: 2022/10/20
+**********************************************************************/
+String inputString = ""; //a String to hold incoming data
+bool stringComplete = false; // whether the string is complete
+
+void setup() {
+ Serial.begin(115200);
+ Serial.println(String("\nESP32S3 initialization completed!\r\n")
+ + String("Please input some characters,\r\n")
+ + String("select \"Newline\" below and Ctrl + Enter to send message to ESP32S3. \r\n"));
+}
+
+void loop() {
+ if (Serial.available()) { // judge whether data has been received
+ char inChar = Serial.read(); // read one character
+ inputString += inChar;
+ if (inChar == '\n') {
+ stringComplete = true;
+ }
+ }
+ if (stringComplete) {
+ Serial.printf("inputString: %s \r\n", inputString);
+ inputString = "";
+ stringComplete = false;
+ }
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_03.1_BLE_USART/Sketch_03.1_BLE_USART.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_03.1_BLE_USART/Sketch_03.1_BLE_USART.ino
new file mode 100644
index 0000000..9bd2051
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_03.1_BLE_USART/Sketch_03.1_BLE_USART.ino
@@ -0,0 +1,79 @@
+/**********************************************************************
+ Filename : BLE_USART
+ Description : Esp32 communicates with the phone by BLE and sends incoming data via a serial port
+ Auther : www.freenove.com
+ Modification: 2024/07/01
+**********************************************************************/
+#include "BLEDevice.h"
+#include "BLEServer.h"
+#include "BLEUtils.h"
+#include "BLE2902.h"
+
+BLECharacteristic *pCharacteristic;
+bool deviceConnected = false;
+uint8_t txValue = 0;
+long lastMsg = 0;
+String rxload="Test\n";
+
+#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
+#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
+#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
+
+class MyServerCallbacks: public BLEServerCallbacks {
+ void onConnect(BLEServer* pServer) {
+ deviceConnected = true;
+ };
+ void onDisconnect(BLEServer* pServer) {
+ deviceConnected = false;
+ //pServer->getAdvertising()->start(); //Reopen the pServer and wait for the connection.
+ }
+};
+
+class MyCallbacks: public BLECharacteristicCallbacks {
+ void onWrite(BLECharacteristic *pCharacteristic) {
+ String rxValue = pCharacteristic->getValue();
+ if (rxValue.length() > 0) {
+ rxload="";
+ for (int i = 0; i < rxValue.length(); i++){
+ rxload +=(char)rxValue[i];
+ }
+ }
+ }
+};
+
+void setupBLE(String BLEName){
+ const char *ble_name=BLEName.c_str();
+ BLEDevice::init(ble_name);
+ BLEServer *pServer = BLEDevice::createServer();
+ pServer->setCallbacks(new MyServerCallbacks());
+ BLEService *pService = pServer->createService(SERVICE_UUID);
+ pCharacteristic= pService->createCharacteristic(CHARACTERISTIC_UUID_TX,BLECharacteristic::PROPERTY_NOTIFY);
+ pCharacteristic->addDescriptor(new BLE2902());
+ BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);
+ pCharacteristic->setCallbacks(new MyCallbacks());
+ pService->start();
+ pServer->getAdvertising()->start();
+ Serial.println("Waiting a client connection to notify...");
+}
+
+void setup() {
+ Serial.begin(115200);
+ setupBLE("ESP32S3_Bluetooth");
+}
+
+void loop() {
+ long now = millis();
+ if (now - lastMsg > 100) {
+ if (deviceConnected&&rxload.length()>0) {
+ Serial.println(rxload);
+ rxload="";
+ }
+ if(Serial.available()>0){
+ String str=Serial.readString();
+ const char *newValue=str.c_str();
+ pCharacteristic->setValue(newValue);
+ pCharacteristic->notify();
+ }
+ lastMsg = now;
+ }
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/Sketch_04.1_SDMMC_Test.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/Sketch_04.1_SDMMC_Test.ino
new file mode 100644
index 0000000..2fceceb
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/Sketch_04.1_SDMMC_Test.ino
@@ -0,0 +1,65 @@
+/**********************************************************************
+ Filename : SDMMC Test
+ Description : The SD card is accessed using the SDMMC one-bit bus
+ Auther : www.freenove.com
+ Modification: 2022/10/28
+**********************************************************************/
+#include "sd_read_write.h"
+#include "SD_MMC.h"
+
+#define SD_MMC_CMD 38 //Please do not modify it.
+#define SD_MMC_CLK 39 //Please do not modify it.
+#define SD_MMC_D0 40 //Please do not modify it.
+
+void setup(){
+ Serial.begin(115200);
+ SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
+ if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
+ Serial.println("Card Mount Failed");
+ return;
+ }
+ uint8_t cardType = SD_MMC.cardType();
+ if(cardType == CARD_NONE){
+ Serial.println("No SD_MMC card attached");
+ return;
+ }
+
+ Serial.print("SD_MMC Card Type: ");
+ if(cardType == CARD_MMC){
+ Serial.println("MMC");
+ } else if(cardType == CARD_SD){
+ Serial.println("SDSC");
+ } else if(cardType == CARD_SDHC){
+ Serial.println("SDHC");
+ } else {
+ Serial.println("UNKNOWN");
+ }
+
+ uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
+ Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
+
+ listDir(SD_MMC, "/", 0);
+
+ createDir(SD_MMC, "/mydir");
+ listDir(SD_MMC, "/", 0);
+
+ removeDir(SD_MMC, "/mydir");
+ listDir(SD_MMC, "/", 2);
+
+ writeFile(SD_MMC, "/hello.txt", "Hello ");
+ appendFile(SD_MMC, "/hello.txt", "World!\n");
+ readFile(SD_MMC, "/hello.txt");
+
+ deleteFile(SD_MMC, "/foo.txt");
+ renameFile(SD_MMC, "/hello.txt", "/foo.txt");
+ readFile(SD_MMC, "/foo.txt");
+
+ testFileIO(SD_MMC, "/test.txt");
+
+ Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
+ Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
+}
+
+void loop(){
+ delay(10000);
+}
\ No newline at end of file
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/sd_read_write.cpp b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/sd_read_write.cpp
new file mode 100644
index 0000000..fa0b15e
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/sd_read_write.cpp
@@ -0,0 +1,154 @@
+#include "sd_read_write.h"
+
+void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
+ Serial.printf("Listing directory: %s\n", dirname);
+
+ File root = fs.open(dirname);
+ if(!root){
+ Serial.println("Failed to open directory");
+ return;
+ }
+ if(!root.isDirectory()){
+ Serial.println("Not a directory");
+ return;
+ }
+
+ File file = root.openNextFile();
+ while(file){
+ if(file.isDirectory()){
+ Serial.print(" DIR : ");
+ Serial.println(file.name());
+ if(levels){
+ listDir(fs, file.path(), levels -1);
+ }
+ } else {
+ Serial.print(" FILE: ");
+ Serial.print(file.name());
+ Serial.print(" SIZE: ");
+ Serial.println(file.size());
+ }
+ file = root.openNextFile();
+ }
+}
+
+void createDir(fs::FS &fs, const char * path){
+ Serial.printf("Creating Dir: %s\n", path);
+ if(fs.mkdir(path)){
+ Serial.println("Dir created");
+ } else {
+ Serial.println("mkdir failed");
+ }
+}
+
+void removeDir(fs::FS &fs, const char * path){
+ Serial.printf("Removing Dir: %s\n", path);
+ if(fs.rmdir(path)){
+ Serial.println("Dir removed");
+ } else {
+ Serial.println("rmdir failed");
+ }
+}
+
+void readFile(fs::FS &fs, const char * path){
+ Serial.printf("Reading file: %s\n", path);
+
+ File file = fs.open(path);
+ if(!file){
+ Serial.println("Failed to open file for reading");
+ return;
+ }
+
+ Serial.print("Read from file: ");
+ while(file.available()){
+ Serial.write(file.read());
+ }
+}
+
+void writeFile(fs::FS &fs, const char * path, const char * message){
+ Serial.printf("Writing file: %s\n", path);
+
+ File file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+ if(file.print(message)){
+ Serial.println("File written");
+ } else {
+ Serial.println("Write failed");
+ }
+}
+
+void appendFile(fs::FS &fs, const char * path, const char * message){
+ Serial.printf("Appending to file: %s\n", path);
+
+ File file = fs.open(path, FILE_APPEND);
+ if(!file){
+ Serial.println("Failed to open file for appending");
+ return;
+ }
+ if(file.print(message)){
+ Serial.println("Message appended");
+ } else {
+ Serial.println("Append failed");
+ }
+}
+
+void renameFile(fs::FS &fs, const char * path1, const char * path2){
+ Serial.printf("Renaming file %s to %s\n", path1, path2);
+ if (fs.rename(path1, path2)) {
+ Serial.println("File renamed");
+ } else {
+ Serial.println("Rename failed");
+ }
+}
+
+void deleteFile(fs::FS &fs, const char * path){
+ Serial.printf("Deleting file: %s\n", path);
+ if(fs.remove(path)){
+ Serial.println("File deleted");
+ } else {
+ Serial.println("Delete failed");
+ }
+}
+
+void testFileIO(fs::FS &fs, const char * path){
+ File file = fs.open(path);
+ static uint8_t buf[512];
+ size_t len = 0;
+ uint32_t start = millis();
+ uint32_t end = start;
+ if(file){
+ len = file.size();
+ size_t flen = len;
+ start = millis();
+ while(len){
+ size_t toRead = len;
+ if(toRead > 512){
+ toRead = 512;
+ }
+ file.read(buf, toRead);
+ len -= toRead;
+ }
+ end = millis() - start;
+ Serial.printf("%u bytes read for %u ms\r\n", flen, end);
+ file.close();
+ } else {
+ Serial.println("Failed to open file for reading");
+ }
+
+ file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+
+ size_t i;
+ start = millis();
+ for(i=0; i<2048; i++){
+ file.write(buf, 512);
+ }
+ end = millis() - start;
+ Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
+ file.close();
+}
\ No newline at end of file
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/sd_read_write.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/sd_read_write.h
new file mode 100644
index 0000000..9eb99a4
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_04.1_SDMMC_Test/sd_read_write.h
@@ -0,0 +1,18 @@
+#ifndef __SD_READ_WRITE_H
+#define __SD_READ_WRITE_H
+
+#include "Arduino.h"
+#include "FS.h"
+
+
+void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
+void createDir(fs::FS &fs, const char * path);
+void removeDir(fs::FS &fs, const char * path);
+void readFile(fs::FS &fs, const char * path);
+void writeFile(fs::FS &fs, const char * path, const char * message);
+void appendFile(fs::FS &fs, const char * path, const char * message);
+void renameFile(fs::FS &fs, const char * path1, const char * path2);
+void deleteFile(fs::FS &fs, const char * path);
+void testFileIO(fs::FS &fs, const char * path);
+
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.1_WiFi_Station/Sketch_05.1_WiFi_Station.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.1_WiFi_Station/Sketch_05.1_WiFi_Station.ino
new file mode 100644
index 0000000..049f78c
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.1_WiFi_Station/Sketch_05.1_WiFi_Station.ino
@@ -0,0 +1,28 @@
+/**********************************************************************
+ Filename : WiFi Station
+ Description : Connect to your router using ESP32
+ Auther : www.freenove.com
+ Modification: 2022/10/31
+**********************************************************************/
+#include
+
+const char *ssid_Router = "********"; //Enter the router name
+const char *password_Router = "********"; //Enter the router password
+
+void setup(){
+ Serial.begin(115200);
+ delay(2000);
+ Serial.println("Setup start");
+ WiFi.begin(ssid_Router, password_Router);
+ Serial.println(String("Connecting to ")+ssid_Router);
+ while (WiFi.status() != WL_CONNECTED){
+ delay(500);
+ Serial.print(".");
+ }
+ Serial.println("\nConnected, IP address: ");
+ Serial.println(WiFi.localIP());
+ Serial.println("Setup End");
+}
+
+void loop() {
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.2_WiFi_AP/Sketch_05.2_WiFi_AP.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.2_WiFi_AP/Sketch_05.2_WiFi_AP.ino
new file mode 100644
index 0000000..3a9d5ee
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.2_WiFi_AP/Sketch_05.2_WiFi_AP.ino
@@ -0,0 +1,36 @@
+/**********************************************************************
+ Filename : WiFi AP
+ Description : Set ESP32 to open an access point
+ Auther : www.freenove.com
+ Modification: 2022/10/31
+**********************************************************************/
+#include
+
+const char *ssid_AP = "WiFi_Name"; //Enter the router name
+const char *password_AP = "12345678"; //Enter the router password
+
+IPAddress local_IP(192,168,1,100);//Set the IP address of ESP32 itself
+IPAddress gateway(192,168,1,10); //Set the gateway of ESP32 itself
+IPAddress subnet(255,255,255,0); //Set the subnet mask for ESP32 itself
+
+void setup(){
+ Serial.begin(115200);
+ delay(2000);
+ Serial.println("Setting soft-AP configuration ... ");
+ WiFi.disconnect();
+ WiFi.mode(WIFI_AP);
+ Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
+ Serial.println("Setting soft-AP ... ");
+ boolean result = WiFi.softAP(ssid_AP, password_AP);
+ if(result){
+ Serial.println("Ready");
+ Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
+ Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
+ }else{
+ Serial.println("Failed!");
+ }
+ Serial.println("Setup End");
+}
+
+void loop() {
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.3_AP_Station/Sketch_05.3_AP_Station.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.3_AP_Station/Sketch_05.3_AP_Station.ino
new file mode 100644
index 0000000..8c0e7d1
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_05.3_AP_Station/Sketch_05.3_AP_Station.ino
@@ -0,0 +1,42 @@
+/**********************************************************************
+ Filename : WiFi AP+Station
+ Description : ESP32 connects to the user's router, turning on an access point
+ Auther : www.freenove.com
+ Modification: 2022/10/31
+**********************************************************************/
+#include
+
+const char *ssid_Router = "********"; //Enter the router name
+const char *password_Router = "********"; //Enter the router password
+const char *ssid_AP = "WiFi_Name"; //Enter the router name
+const char *password_AP = "12345678"; //Enter the router password
+
+void setup(){
+ Serial.begin(115200);
+ Serial.println("Setting soft-AP configuration ... ");
+ WiFi.disconnect();
+ WiFi.mode(WIFI_AP);
+ Serial.println("Setting soft-AP ... ");
+ boolean result = WiFi.softAP(ssid_AP, password_AP);
+ if(result){
+ Serial.println("Ready");
+ Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
+ Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
+ }else{
+ Serial.println("Failed!");
+ }
+
+ Serial.println("\nSetting Station configuration ... ");
+ WiFi.begin(ssid_Router, password_Router);
+ Serial.println(String("Connecting to ")+ ssid_Router);
+ while (WiFi.status() != WL_CONNECTED){
+ delay(500);
+ Serial.print(".");
+ }
+ Serial.println("\nConnected, IP address: ");
+ Serial.println(WiFi.localIP());
+ Serial.println("Setup End");
+}
+
+void loop() {
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.1_WiFiClient/Sketch_06.1_WiFiClient.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.1_WiFiClient/Sketch_06.1_WiFiClient.ino
new file mode 100644
index 0000000..84d7048
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.1_WiFiClient/Sketch_06.1_WiFiClient.ino
@@ -0,0 +1,59 @@
+/**********************************************************************
+ Filename : WiFi Client
+ Description : Use ESP32's WiFi client feature to connect and communicate with a remote IP.
+ Auther : www.freenove.com
+ Modification: 2022/10/31
+**********************************************************************/
+#include
+
+const char *ssid_Router = "********"; //Enter the router name
+const char *password_Router = "********"; //Enter the router password
+#define REMOTE_IP "********" //input the remote server which is you want to connect
+#define REMOTE_PORT 8888 //input the remote port which is the remote provide
+WiFiClient client;
+
+void setup() {
+ Serial.begin(115200);
+ delay(10);
+
+ WiFi.begin(ssid_Router, password_Router);
+ Serial.print("\nWaiting for WiFi... ");
+ while (WiFi.status() != WL_CONNECTED) {
+ Serial.print(".");
+ delay(500);
+ }
+ Serial.println("");
+ Serial.println("WiFi connected");
+ Serial.println("IP address: ");
+ Serial.println(WiFi.localIP());
+ delay(500);
+
+ Serial.print("Connecting to ");
+ Serial.println(REMOTE_IP);
+
+ while (!client.connect(REMOTE_IP, REMOTE_PORT)) {
+ Serial.println("Connection failed.");
+ Serial.println("Waiting a moment before retrying...");
+ }
+ Serial.println("Connected");
+ client.print("Hello\n");
+ client.print("This is my IP.\n");
+}
+
+void loop() {
+ if (client.available() > 0) {
+ delay(20);
+ //read back one line from the server
+ String line = client.readString();
+ Serial.println(REMOTE_IP + String(":") + line);
+ }
+ if (Serial.available() > 0) {
+ delay(20);
+ String line = Serial.readString();
+ client.print(line);
+ }
+ if (client.connected () == 0) {
+ client.stop();
+ WiFi.disconnect();
+ }
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.1_WiFiClient/sketchWiFi/sketchWiFi.pde b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.1_WiFiClient/sketchWiFi/sketchWiFi.pde
new file mode 100644
index 0000000..82ce0e4
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.1_WiFiClient/sketchWiFi/sketchWiFi.pde
@@ -0,0 +1,240 @@
+/*
+ ******************************************************************************
+ * Sketch WiFi Client and Server
+ * Author Zhentao Lin @ Freenove (http://www.freenove.com)
+ * Date 2020/7/11
+ ******************************************************************************
+ * Brief
+ * This sketch is used to control a 2D ellipse through communicate to an
+ * ESP32 board or other micro controller.
+ * It will automatically detect and connect to a device (serial port) which
+ * use the same trans format.
+ ******************************************************************************
+ * Copyright
+ * Copyright © Freenove (http://www.freenove.com)
+ * License
+ * Creative Commons Attribution ShareAlike 3.0
+ * (http://creativecommons.org/licenses/by-sa/3.0/legalcode)
+ ******************************************************************************
+*/
+import controlP5.*;
+import processing.net.*;
+
+ControlP5 cp5;
+//Println console;
+Server myServer;
+Client myClient;
+int dataIn=0;
+int radioFlag1=0;
+int radioFlag2=0;
+int send_flag=1;
+
+void setup() {
+ size(600,400);
+ smooth();
+ noStroke();
+ cp5 = new ControlP5(this);
+ cp5.addTab("default")
+ .activateEvent(true)
+ .setHeight(30)
+ .setWidth(100)
+ .setLabel("TCP Server")
+ .setId(1)
+ ;
+ cp5.getTab("TCP Client")
+ .activateEvent(true)
+ .setHeight(30)
+ .setWidth(100)
+ .setId(2)
+ ;
+
+ cp5.addTextfield("Local IP")
+ .setPosition(20,40)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .moveTo("default")
+ ;
+ cp5.addTextfield("Local PORT")
+ .setPosition(20,120)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .setText("8888")
+ .moveTo("default")
+ ;
+ cp5.addRadioButton("connect1")
+ .setPosition(20,200)
+ .setSize(100,25)
+ .addItem("Listening", 1)
+ .setColorLabel(color(0))
+ .moveTo("default")
+ ;
+
+ cp5.addTextfield("Remote IP")
+ .setPosition(20,40)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .setText("192.168.1.xxx")
+ .moveTo("TCP Client")
+ ;
+ cp5.addTextfield("Remote PORT")
+ .setPosition(20,120)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .setText("80")
+ .moveTo("TCP Client")
+ ;
+ cp5.addRadioButton("connect2")
+ .setPosition(20,200)
+ .setSize(100,25)
+ .addItem("connect Server",1)
+ .setColorLabel(color(0))
+ .moveTo("TCP Client")
+ ;
+
+ cp5.addTextarea("recvData")
+ .setPosition(200,40)
+ .setSize(350,150)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorBackground(color(100,255))
+ .scroll(15)
+ .setColorForeground(color(0,100))
+ .moveTo("global")
+ ;
+ cp5.addTextfield("sendData")
+ .setPosition(200,230)
+ .setSize(350,80)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setLabel("")
+ .setFocus(true)
+ .setColorBackground(color(100,255))
+ .setColorForeground(color(0,100))
+ .moveTo("global")
+ ;
+ cp5.addButton("clearRecv")
+ .setValue(0)
+ .setPosition(200,200)
+ .setSize(100,20)
+ .setColorLabel(color(255,100))
+ .moveTo("global")
+ ;
+ cp5.addButton("clearSend")
+ .setValue(0)
+ .setPosition(200,320)
+ .setSize(100,20)
+ .setColorLabel(color(255,100))
+ .moveTo("global")
+ ;
+ cp5.addButton("Send")
+ .setValue(0)
+ .setPosition(450,320)
+ .setSize(100,20)
+ .plugTo(this,"send_Textfield_SendData")
+ .setColorLabel(color(255,100))
+ .moveTo("global")
+ ;
+ cp5.get(Textfield.class,"Local IP").setText(Server.ip());
+}
+
+void draw(){
+ background(220);
+ if(radioFlag1==1){
+ Client thisClient = myServer.available();
+ if (thisClient !=null) {
+ String whatClientSaid = thisClient.readString();
+ if (whatClientSaid != null) {
+ cp5.get(Textarea.class,"recvData").append(thisClient.ip()+": ");
+ cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
+ }
+ }
+
+ }
+ // myServer.active()
+ if(radioFlag2==1){
+ if (myClient.available() > 0) {
+ String whatClientSaid = myClient.readString();
+ if (whatClientSaid != null) {
+ cp5.get(Textarea.class,"recvData").append(cp5.get(Textfield.class,"Remote IP").getText()+": ");
+ cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
+ }
+ }
+ }
+}
+
+void controlEvent(ControlEvent theControlEvent) {
+ if (theControlEvent.isTab()) {
+ if(theControlEvent.getTab().getId()==1){
+ cp5.get(Textarea.class,"recvData").clear();
+ cp5.get(Textfield.class,"sendData").clear();
+ send_flag=1;
+ }
+ else if(theControlEvent.getTab().getId()==2){
+ cp5.get(Textarea.class,"recvData").clear();
+ cp5.get(Textfield.class,"sendData").clear();
+ send_flag=2;
+ }
+ }
+}
+
+void connect1(int a) {
+ println("a radio Button event: "+a);
+ radioFlag1=a;
+ if(radioFlag1==1){
+ String port_buffer = cp5.get(Textfield.class,"Local PORT").getText();
+ int port = int(port_buffer);
+ myServer = new Server(this,port);
+ println(Server.ip());
+ cp5.get(Textfield.class,"Local IP").setText(Server.ip());
+ println(port);
+ }
+ else
+ myServer.stop();
+}
+void connect2(int a) {
+ println("a radio Button event: "+a);
+ radioFlag2=a;
+ if(radioFlag2==1){
+ String port_buffer = cp5.get(Textfield.class,"Remote PORT").getText();
+ String IP_buffer = cp5.get(Textfield.class,"Remote IP").getText();
+ int port = int(port_buffer);
+ if(IP_buffer.compareTo("192.168.1.xxx")==0){
+ println("connect error!");
+ }
+ else{
+ myClient = new Client(this,IP_buffer,port);
+ println("connect success!");
+ }
+
+ }
+ else
+ myClient.stop();
+}
+void clearRecv(){
+ cp5.get(Textarea.class,"recvData").clear();
+}
+void clearSend(){
+ cp5.get(Textfield.class,"sendData").clear();
+}
+void send_Textfield_SendData(){
+ if(send_flag==1){
+ myServer.write(cp5.get(Textfield.class,"sendData").getText());
+ cp5.get(Textfield.class,"sendData").clear();
+ }
+ else if(send_flag==2){
+ myClient.write(cp5.get(Textfield.class,"sendData").getText());
+ cp5.get(Textfield.class,"sendData").clear();
+ }
+}
\ No newline at end of file
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.2_WiFiServer/Sketch_06.2_WiFiServer.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.2_WiFiServer/Sketch_06.2_WiFiServer.ino
new file mode 100644
index 0000000..203cbb5
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.2_WiFiServer/Sketch_06.2_WiFiServer.ino
@@ -0,0 +1,53 @@
+/**********************************************************************
+ Filename : WiFi Server
+ Description : Use ESP32's WiFi server feature to wait for other WiFi devices to connect.
+ And communicate with them once a connection has been established.
+ Auther : www.freenove.com
+ Modification: 2024/07/01
+**********************************************************************/
+#include
+
+#define port 80
+const char *ssid_Router = "********"; //input your wifi name
+const char *password_Router = "********"; //input your wifi passwords
+WiFiServer server(port);
+
+void setup()
+{
+ Serial.begin(115200);
+ Serial.printf("\nConnecting to ");
+ Serial.println(ssid_Router);
+ WiFi.disconnect();
+ WiFi.begin(ssid_Router, password_Router);
+ delay(1000);
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(500);
+ Serial.print(".");
+ }
+ Serial.println("");
+ Serial.println("WiFi connected.");
+ Serial.print("IP address: ");
+ Serial.println(WiFi.localIP());
+ Serial.printf("IP port: %d\n",port);
+ server.begin(port);
+ WiFi.setAutoReconnect(true);
+}
+
+void loop(){
+ WiFiClient client = server.accept(); // listen for incoming clients
+ if (client) { // if you get a client,
+ Serial.println("Client connected.");
+ while (client.connected()) { // loop while the client's connected
+ if (client.available()) { // if there's bytes to read from the client,
+ Serial.println(client.readStringUntil('\n')); // print it out the serial monitor
+ while(client.read()>0); // clear the wifi receive area cache
+ }
+ if(Serial.available()){ // if there's bytes to read from the serial monitor,
+ client.print(Serial.readStringUntil('\n')); // print it out the client.
+ while(Serial.read()>0); // clear the wifi receive area cache
+ }
+ }
+ client.stop(); // stop the client connecting.
+ Serial.println("Client Disconnected.");
+ }
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.2_WiFiServer/sketchWiFi/sketchWiFi.pde b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.2_WiFiServer/sketchWiFi/sketchWiFi.pde
new file mode 100644
index 0000000..82ce0e4
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_06.2_WiFiServer/sketchWiFi/sketchWiFi.pde
@@ -0,0 +1,240 @@
+/*
+ ******************************************************************************
+ * Sketch WiFi Client and Server
+ * Author Zhentao Lin @ Freenove (http://www.freenove.com)
+ * Date 2020/7/11
+ ******************************************************************************
+ * Brief
+ * This sketch is used to control a 2D ellipse through communicate to an
+ * ESP32 board or other micro controller.
+ * It will automatically detect and connect to a device (serial port) which
+ * use the same trans format.
+ ******************************************************************************
+ * Copyright
+ * Copyright © Freenove (http://www.freenove.com)
+ * License
+ * Creative Commons Attribution ShareAlike 3.0
+ * (http://creativecommons.org/licenses/by-sa/3.0/legalcode)
+ ******************************************************************************
+*/
+import controlP5.*;
+import processing.net.*;
+
+ControlP5 cp5;
+//Println console;
+Server myServer;
+Client myClient;
+int dataIn=0;
+int radioFlag1=0;
+int radioFlag2=0;
+int send_flag=1;
+
+void setup() {
+ size(600,400);
+ smooth();
+ noStroke();
+ cp5 = new ControlP5(this);
+ cp5.addTab("default")
+ .activateEvent(true)
+ .setHeight(30)
+ .setWidth(100)
+ .setLabel("TCP Server")
+ .setId(1)
+ ;
+ cp5.getTab("TCP Client")
+ .activateEvent(true)
+ .setHeight(30)
+ .setWidth(100)
+ .setId(2)
+ ;
+
+ cp5.addTextfield("Local IP")
+ .setPosition(20,40)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .moveTo("default")
+ ;
+ cp5.addTextfield("Local PORT")
+ .setPosition(20,120)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .setText("8888")
+ .moveTo("default")
+ ;
+ cp5.addRadioButton("connect1")
+ .setPosition(20,200)
+ .setSize(100,25)
+ .addItem("Listening", 1)
+ .setColorLabel(color(0))
+ .moveTo("default")
+ ;
+
+ cp5.addTextfield("Remote IP")
+ .setPosition(20,40)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .setText("192.168.1.xxx")
+ .moveTo("TCP Client")
+ ;
+ cp5.addTextfield("Remote PORT")
+ .setPosition(20,120)
+ .setSize(160,40)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorLabel(color(0))
+ .setColorBackground(color(100,255))
+ .setText("80")
+ .moveTo("TCP Client")
+ ;
+ cp5.addRadioButton("connect2")
+ .setPosition(20,200)
+ .setSize(100,25)
+ .addItem("connect Server",1)
+ .setColorLabel(color(0))
+ .moveTo("TCP Client")
+ ;
+
+ cp5.addTextarea("recvData")
+ .setPosition(200,40)
+ .setSize(350,150)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setColorBackground(color(100,255))
+ .scroll(15)
+ .setColorForeground(color(0,100))
+ .moveTo("global")
+ ;
+ cp5.addTextfield("sendData")
+ .setPosition(200,230)
+ .setSize(350,80)
+ .setFont(createFont("微软雅黑 Light",20))
+ .setColor(color(255,255,0))
+ .setLabel("")
+ .setFocus(true)
+ .setColorBackground(color(100,255))
+ .setColorForeground(color(0,100))
+ .moveTo("global")
+ ;
+ cp5.addButton("clearRecv")
+ .setValue(0)
+ .setPosition(200,200)
+ .setSize(100,20)
+ .setColorLabel(color(255,100))
+ .moveTo("global")
+ ;
+ cp5.addButton("clearSend")
+ .setValue(0)
+ .setPosition(200,320)
+ .setSize(100,20)
+ .setColorLabel(color(255,100))
+ .moveTo("global")
+ ;
+ cp5.addButton("Send")
+ .setValue(0)
+ .setPosition(450,320)
+ .setSize(100,20)
+ .plugTo(this,"send_Textfield_SendData")
+ .setColorLabel(color(255,100))
+ .moveTo("global")
+ ;
+ cp5.get(Textfield.class,"Local IP").setText(Server.ip());
+}
+
+void draw(){
+ background(220);
+ if(radioFlag1==1){
+ Client thisClient = myServer.available();
+ if (thisClient !=null) {
+ String whatClientSaid = thisClient.readString();
+ if (whatClientSaid != null) {
+ cp5.get(Textarea.class,"recvData").append(thisClient.ip()+": ");
+ cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
+ }
+ }
+
+ }
+ // myServer.active()
+ if(radioFlag2==1){
+ if (myClient.available() > 0) {
+ String whatClientSaid = myClient.readString();
+ if (whatClientSaid != null) {
+ cp5.get(Textarea.class,"recvData").append(cp5.get(Textfield.class,"Remote IP").getText()+": ");
+ cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
+ }
+ }
+ }
+}
+
+void controlEvent(ControlEvent theControlEvent) {
+ if (theControlEvent.isTab()) {
+ if(theControlEvent.getTab().getId()==1){
+ cp5.get(Textarea.class,"recvData").clear();
+ cp5.get(Textfield.class,"sendData").clear();
+ send_flag=1;
+ }
+ else if(theControlEvent.getTab().getId()==2){
+ cp5.get(Textarea.class,"recvData").clear();
+ cp5.get(Textfield.class,"sendData").clear();
+ send_flag=2;
+ }
+ }
+}
+
+void connect1(int a) {
+ println("a radio Button event: "+a);
+ radioFlag1=a;
+ if(radioFlag1==1){
+ String port_buffer = cp5.get(Textfield.class,"Local PORT").getText();
+ int port = int(port_buffer);
+ myServer = new Server(this,port);
+ println(Server.ip());
+ cp5.get(Textfield.class,"Local IP").setText(Server.ip());
+ println(port);
+ }
+ else
+ myServer.stop();
+}
+void connect2(int a) {
+ println("a radio Button event: "+a);
+ radioFlag2=a;
+ if(radioFlag2==1){
+ String port_buffer = cp5.get(Textfield.class,"Remote PORT").getText();
+ String IP_buffer = cp5.get(Textfield.class,"Remote IP").getText();
+ int port = int(port_buffer);
+ if(IP_buffer.compareTo("192.168.1.xxx")==0){
+ println("connect error!");
+ }
+ else{
+ myClient = new Client(this,IP_buffer,port);
+ println("connect success!");
+ }
+
+ }
+ else
+ myClient.stop();
+}
+void clearRecv(){
+ cp5.get(Textarea.class,"recvData").clear();
+}
+void clearSend(){
+ cp5.get(Textfield.class,"sendData").clear();
+}
+void send_Textfield_SendData(){
+ if(send_flag==1){
+ myServer.write(cp5.get(Textfield.class,"sendData").getText());
+ cp5.get(Textfield.class,"sendData").clear();
+ }
+ else if(send_flag==2){
+ myClient.write(cp5.get(Textfield.class,"sendData").getText());
+ cp5.get(Textfield.class,"sendData").clear();
+ }
+}
\ No newline at end of file
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/Sketch_07.1_CameraWebServer.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/Sketch_07.1_CameraWebServer.ino
new file mode 100644
index 0000000..9c7dd48
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/Sketch_07.1_CameraWebServer.ino
@@ -0,0 +1,119 @@
+/**********************************************************************
+ Filename : Camera Web Server
+ Description : The camera images captured by the ESP32S3 are displayed on the web page.
+ Auther : www.freenove.com
+ Modification: 2024/07/01
+**********************************************************************/
+#include "esp_camera.h"
+#include
+
+// ===================
+// Select camera model
+// ===================
+//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
+//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
+#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
+//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
+//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
+//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
+//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
+//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
+//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
+//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
+// ** Espressif Internal Boards **
+//#define CAMERA_MODEL_ESP32_CAM_BOARD
+//#define CAMERA_MODEL_ESP32S2_CAM_BOARD
+//#define CAMERA_MODEL_ESP32S3_CAM_LCD
+
+#include "camera_pins.h"
+
+// ===========================
+// Enter your WiFi credentials
+// ===========================
+const char* ssid = "********";
+const char* password = "********";
+
+void startCameraServer();
+
+void setup() {
+ Serial.begin(115200);
+ Serial.setDebugOutput(true);
+ Serial.println();
+
+ camera_config_t config;
+ config.ledc_channel = LEDC_CHANNEL_0;
+ config.ledc_timer = LEDC_TIMER_0;
+ config.pin_d0 = Y2_GPIO_NUM;
+ config.pin_d1 = Y3_GPIO_NUM;
+ config.pin_d2 = Y4_GPIO_NUM;
+ config.pin_d3 = Y5_GPIO_NUM;
+ config.pin_d4 = Y6_GPIO_NUM;
+ config.pin_d5 = Y7_GPIO_NUM;
+ config.pin_d6 = Y8_GPIO_NUM;
+ config.pin_d7 = Y9_GPIO_NUM;
+ config.pin_xclk = XCLK_GPIO_NUM;
+ config.pin_pclk = PCLK_GPIO_NUM;
+ config.pin_vsync = VSYNC_GPIO_NUM;
+ config.pin_href = HREF_GPIO_NUM;
+ config.pin_sccb_sda = SIOD_GPIO_NUM;
+ config.pin_sccb_scl = SIOC_GPIO_NUM;
+ config.pin_pwdn = PWDN_GPIO_NUM;
+ config.pin_reset = RESET_GPIO_NUM;
+ config.xclk_freq_hz = 20000000;
+ config.frame_size = FRAMESIZE_UXGA;
+ config.pixel_format = PIXFORMAT_JPEG; // for streaming
+ config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
+ config.fb_location = CAMERA_FB_IN_PSRAM;
+ config.jpeg_quality = 12;
+ config.fb_count = 1;
+
+ // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
+ // for larger pre-allocated frame buffer.
+ if(psramFound()){
+ config.jpeg_quality = 10;
+ config.fb_count = 2;
+ config.grab_mode = CAMERA_GRAB_LATEST;
+ } else {
+ // Limit the frame size when PSRAM is not available
+ config.frame_size = FRAMESIZE_SVGA;
+ config.fb_location = CAMERA_FB_IN_DRAM;
+ }
+
+ // camera init
+ esp_err_t err = esp_camera_init(&config);
+ if (err != ESP_OK) {
+ Serial.printf("Camera init failed with error 0x%x", err);
+ return;
+ }
+
+ sensor_t * s = esp_camera_sensor_get();
+ // initial sensors are flipped vertically and colors are a bit saturated
+ s->set_vflip(s, 1); // flip it back
+ s->set_brightness(s, 1); // up the brightness just a bit
+ s->set_saturation(s, 0); // lower the saturation
+
+ WiFi.begin(ssid, password);
+ WiFi.setSleep(false);
+
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(500);
+ Serial.print(".");
+ }
+ while (WiFi.STA.hasIP() != true) {
+ Serial.print(".");
+ delay(500);
+ }
+ Serial.println("");
+ Serial.println("WiFi connected");
+
+ startCameraServer();
+
+ Serial.print("Camera Ready! Use 'http://");
+ Serial.print(WiFi.localIP());
+ Serial.println("' to connect");
+}
+
+void loop() {
+ // Do nothing. Everything is done in another task by the web server
+ delay(10000);
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/app_httpd.cpp b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/app_httpd.cpp
new file mode 100644
index 0000000..91a072d
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/app_httpd.cpp
@@ -0,0 +1,1383 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "esp_http_server.h"
+#include "esp_timer.h"
+#include "esp_camera.h"
+#include "img_converters.h"
+#include "fb_gfx.h"
+#include "driver/ledc.h"
+#include "sdkconfig.h"
+#include "camera_index.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#define TAG ""
+#else
+#include "esp_log.h"
+static const char *TAG = "camera_httpd";
+#endif
+
+// Face Detection will not work on boards without (or with disabled) PSRAM
+#ifdef BOARD_HAS_PSRAM
+#define CONFIG_ESP_FACE_DETECT_ENABLED 1
+// Face Recognition takes upward from 15 seconds per frame on chips other than ESP32S3
+// Makes no sense to have it enabled for them
+#if CONFIG_IDF_TARGET_ESP32S3
+#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 1
+#else
+#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0
+#endif
+#else
+#define CONFIG_ESP_FACE_DETECT_ENABLED 0
+#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0
+#endif
+
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+
+#include
+#include "human_face_detect_msr01.hpp"
+#include "human_face_detect_mnp01.hpp"
+
+#define TWO_STAGE 1 /* very large firmware, very slow, reboots when streaming...
+
+#define FACE_ID_SAVE_NUMBER 7
+#endif
+
+#define FACE_COLOR_WHITE 0x00FFFFFF
+#define FACE_COLOR_BLACK 0x00000000
+#define FACE_COLOR_RED 0x000000FF
+#define FACE_COLOR_GREEN 0x0000FF00
+#define FACE_COLOR_BLUE 0x00FF0000
+#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN)
+#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN)
+#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED)
+#endif
+
+#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
+int led_duty = 0;
+bool isStreaming = false;
+#ifdef CONFIG_LED_LEDC_LOW_SPEED_MODE
+#define CONFIG_LED_LEDC_SPEED_MODE LEDC_LOW_SPEED_MODE
+#else
+#define CONFIG_LED_LEDC_SPEED_MODE LEDC_HIGH_SPEED_MODE
+#endif
+#endif
+
+typedef struct
+{
+ httpd_req_t *req;
+ size_t len;
+} jpg_chunking_t;
+
+#define PART_BOUNDARY "123456789000000000000987654321"
+static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
+static const char *_STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
+static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\nX-Timestamp: %d.%06d\r\n\r\n";
+
+httpd_handle_t stream_httpd = NULL;
+httpd_handle_t camera_httpd = NULL;
+
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+
+static int8_t detection_enabled = 0;
+
+// #if TWO_STAGE
+// static HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
+// static HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
+// #else
+// static HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
+// #endif
+
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+static int8_t recognition_enabled = 0;
+static int8_t is_enrolling = 0;
+
+#if QUANT_TYPE
+ // S16 model
+ FaceRecognition112V1S16 recognizer;
+#else
+ // S8 model
+ FaceRecognition112V1S8 recognizer;
+#endif
+#endif
+
+#endif
+
+typedef struct
+{
+ size_t size; //number of values used for filtering
+ size_t index; //current value index
+ size_t count; //value count
+ int sum;
+ int *values; //array to be filled with values
+} ra_filter_t;
+
+static ra_filter_t ra_filter;
+
+static ra_filter_t *ra_filter_init(ra_filter_t *filter, size_t sample_size)
+{
+ memset(filter, 0, sizeof(ra_filter_t));
+
+ filter->values = (int *)malloc(sample_size * sizeof(int));
+ if (!filter->values)
+ {
+ return NULL;
+ }
+ memset(filter->values, 0, sample_size * sizeof(int));
+
+ filter->size = sample_size;
+ return filter;
+}
+
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+static int ra_filter_run(ra_filter_t *filter, int value)
+{
+ if (!filter->values)
+ {
+ return value;
+ }
+ filter->sum -= filter->values[filter->index];
+ filter->values[filter->index] = value;
+ filter->sum += filter->values[filter->index];
+ filter->index++;
+ filter->index = filter->index % filter->size;
+ if (filter->count < filter->size)
+ {
+ filter->count++;
+ }
+ return filter->sum / filter->count;
+}
+#endif
+
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+static void rgb_print(fb_data_t *fb, uint32_t color, const char *str)
+{
+ fb_gfx_print(fb, (fb->width - (strlen(str) * 14)) / 2, 10, color, str);
+}
+
+static int rgb_printf(fb_data_t *fb, uint32_t color, const char *format, ...)
+{
+ char loc_buf[64];
+ char *temp = loc_buf;
+ int len;
+ va_list arg;
+ va_list copy;
+ va_start(arg, format);
+ va_copy(copy, arg);
+ len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg);
+ va_end(copy);
+ if (len >= sizeof(loc_buf))
+ {
+ temp = (char *)malloc(len + 1);
+ if (temp == NULL)
+ {
+ return 0;
+ }
+ }
+ vsnprintf(temp, len + 1, format, arg);
+ va_end(arg);
+ rgb_print(fb, color, temp);
+ if (len > 64)
+ {
+ free(temp);
+ }
+ return len;
+}
+#endif
+static void draw_face_boxes(fb_data_t *fb, std::list *results, int face_id)
+{
+ int x, y, w, h;
+ uint32_t color = FACE_COLOR_YELLOW;
+ if (face_id < 0)
+ {
+ color = FACE_COLOR_RED;
+ }
+ else if (face_id > 0)
+ {
+ color = FACE_COLOR_GREEN;
+ }
+ if(fb->bytes_per_pixel == 2){
+ //color = ((color >> 8) & 0xF800) | ((color >> 3) & 0x07E0) | (color & 0x001F);
+ color = ((color >> 16) & 0x001F) | ((color >> 3) & 0x07E0) | ((color << 8) & 0xF800);
+ }
+ int i = 0;
+ for (std::list::iterator prediction = results->begin(); prediction != results->end(); prediction++, i++)
+ {
+ // rectangle box
+ x = (int)prediction->box[0];
+ y = (int)prediction->box[1];
+ w = (int)prediction->box[2] - x + 1;
+ h = (int)prediction->box[3] - y + 1;
+ if((x + w) > fb->width){
+ w = fb->width - x;
+ }
+ if((y + h) > fb->height){
+ h = fb->height - y;
+ }
+ fb_gfx_drawFastHLine(fb, x, y, w, color);
+ fb_gfx_drawFastHLine(fb, x, y + h - 1, w, color);
+ fb_gfx_drawFastVLine(fb, x, y, h, color);
+ fb_gfx_drawFastVLine(fb, x + w - 1, y, h, color);
+#if TWO_STAGE
+ // landmarks (left eye, mouth left, nose, right eye, mouth right)
+ int x0, y0, j;
+ for (j = 0; j < 10; j+=2) {
+ x0 = (int)prediction->keypoint[j];
+ y0 = (int)prediction->keypoint[j+1];
+ fb_gfx_fillRect(fb, x0, y0, 3, 3, color);
+ }
+#endif
+ }
+}
+
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+static int run_face_recognition(fb_data_t *fb, std::list *results)
+{
+ std::vector landmarks = results->front().keypoint;
+ int id = -1;
+
+ Tensor tensor;
+ tensor.set_element((uint8_t *)fb->data).set_shape({fb->height, fb->width, 3}).set_auto_free(false);
+
+ int enrolled_count = recognizer.get_enrolled_id_num();
+
+ if (enrolled_count < FACE_ID_SAVE_NUMBER && is_enrolling){
+ id = recognizer.enroll_id(tensor, landmarks, "", true);
+ ESP_LOGI(TAG, "Enrolled ID: %d", id);
+ rgb_printf(fb, FACE_COLOR_CYAN, "ID[%u]", id);
+ }
+
+ face_info_t recognize = recognizer.recognize(tensor, landmarks);
+ if(recognize.id >= 0){
+ rgb_printf(fb, FACE_COLOR_GREEN, "ID[%u]: %.2f", recognize.id, recognize.similarity);
+ } else {
+ rgb_print(fb, FACE_COLOR_RED, "Intruder Alert!");
+ }
+ return recognize.id;
+}
+#endif
+#endif
+
+#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
+void enable_led(bool en)
+{ // Turn LED On or Off
+ int duty = en ? led_duty : 0;
+ if (en && isStreaming && (led_duty > CONFIG_LED_MAX_INTENSITY))
+ {
+ duty = CONFIG_LED_MAX_INTENSITY;
+ }
+ ledc_set_duty(CONFIG_LED_LEDC_SPEED_MODE, CONFIG_LED_LEDC_CHANNEL, duty);
+ ledc_update_duty(CONFIG_LED_LEDC_SPEED_MODE, CONFIG_LED_LEDC_CHANNEL);
+ ESP_LOGI(TAG, "Set LED intensity to %d", duty);
+}
+#endif
+
+static esp_err_t bmp_handler(httpd_req_t *req)
+{
+ camera_fb_t *fb = NULL;
+ esp_err_t res = ESP_OK;
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ uint64_t fr_start = esp_timer_get_time();
+#endif
+ fb = esp_camera_fb_get();
+ if (!fb)
+ {
+ ESP_LOGE(TAG, "Camera capture failed");
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+
+ httpd_resp_set_type(req, "image/x-windows-bmp");
+ httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.bmp");
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+
+ char ts[32];
+ snprintf(ts, 32, "%ld.%06ld", fb->timestamp.tv_sec, fb->timestamp.tv_usec);
+ httpd_resp_set_hdr(req, "X-Timestamp", (const char *)ts);
+
+
+ uint8_t * buf = NULL;
+ size_t buf_len = 0;
+ bool converted = frame2bmp(fb, &buf, &buf_len);
+ esp_camera_fb_return(fb);
+ if(!converted){
+ ESP_LOGE(TAG, "BMP Conversion failed");
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+ res = httpd_resp_send(req, (const char *)buf, buf_len);
+ free(buf);
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ uint64_t fr_end = esp_timer_get_time();
+#endif
+ ESP_LOGI(TAG, "BMP: %llums, %uB", (uint64_t)((fr_end - fr_start) / 1000), buf_len);
+ return res;
+}
+
+static size_t jpg_encode_stream(void *arg, size_t index, const void *data, size_t len)
+{
+ jpg_chunking_t *j = (jpg_chunking_t *)arg;
+ if (!index)
+ {
+ j->len = 0;
+ }
+ if (httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK)
+ {
+ return 0;
+ }
+ j->len += len;
+ return len;
+}
+
+static esp_err_t capture_handler(httpd_req_t *req)
+{
+ camera_fb_t *fb = NULL;
+ esp_err_t res = ESP_OK;
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ int64_t fr_start = esp_timer_get_time();
+#endif
+
+#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
+ enable_led(true);
+ vTaskDelay(150 / portTICK_PERIOD_MS); // The LED needs to be turned on ~150ms before the call to esp_camera_fb_get()
+ fb = esp_camera_fb_get(); // or it won't be visible in the frame. A better way to do this is needed.
+ enable_led(false);
+#else
+ fb = esp_camera_fb_get();
+#endif
+
+ if (!fb)
+ {
+ ESP_LOGE(TAG, "Camera capture failed");
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+
+ httpd_resp_set_type(req, "image/jpeg");
+ httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+
+ char ts[32];
+ snprintf(ts, 32, "%ld.%06ld", fb->timestamp.tv_sec, fb->timestamp.tv_usec);
+ httpd_resp_set_hdr(req, "X-Timestamp", (const char *)ts);
+
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ size_t out_len, out_width, out_height;
+ uint8_t *out_buf;
+ bool s;
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ bool detected = false;
+#endif
+ int face_id = 0;
+ if (!detection_enabled || fb->width > 400)
+ {
+#endif
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ size_t fb_len = 0;
+#endif
+ if (fb->format == PIXFORMAT_JPEG)
+ {
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fb_len = fb->len;
+#endif
+ res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
+ }
+ else
+ {
+ jpg_chunking_t jchunk = {req, 0};
+ res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL;
+ httpd_resp_send_chunk(req, NULL, 0);
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fb_len = jchunk.len;
+#endif
+ }
+ esp_camera_fb_return(fb);
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ int64_t fr_end = esp_timer_get_time();
+#endif
+ ESP_LOGI(TAG, "JPG: %uB %ums", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start) / 1000));
+ return res;
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ }
+
+ jpg_chunking_t jchunk = {req, 0};
+
+ if (fb->format == PIXFORMAT_RGB565
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ && !recognition_enabled
+#endif
+ ){
+#if TWO_STAGE
+ HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
+ HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
+ std::list &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
+ std::list &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates);
+#else
+ HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
+ std::list &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
+#endif
+ if (results.size() > 0) {
+ fb_data_t rfb;
+ rfb.width = fb->width;
+ rfb.height = fb->height;
+ rfb.data = fb->buf;
+ rfb.bytes_per_pixel = 2;
+ rfb.format = FB_RGB565;
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ detected = true;
+#endif
+ draw_face_boxes(&rfb, &results, face_id);
+ }
+ s = fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 90, jpg_encode_stream, &jchunk);
+ esp_camera_fb_return(fb);
+ } else
+ {
+ out_len = fb->width * fb->height * 3;
+ out_width = fb->width;
+ out_height = fb->height;
+ out_buf = (uint8_t*)malloc(out_len);
+ if (!out_buf) {
+ ESP_LOGE(TAG, "out_buf malloc failed");
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+ s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
+ esp_camera_fb_return(fb);
+ if (!s) {
+ free(out_buf);
+ ESP_LOGE(TAG, "to rgb888 failed");
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+
+ fb_data_t rfb;
+ rfb.width = out_width;
+ rfb.height = out_height;
+ rfb.data = out_buf;
+ rfb.bytes_per_pixel = 3;
+ rfb.format = FB_BGR888;
+
+#if TWO_STAGE
+ HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
+ HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
+ std::list &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
+ std::list &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates);
+#else
+ HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
+ std::list &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
+#endif
+
+ if (results.size() > 0) {
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ detected = true;
+#endif
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ if (recognition_enabled) {
+ face_id = run_face_recognition(&rfb, &results);
+ }
+#endif
+ draw_face_boxes(&rfb, &results, face_id);
+ }
+
+ s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);
+ free(out_buf);
+ }
+
+ if (!s) {
+ ESP_LOGE(TAG, "JPEG compression failed");
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ int64_t fr_end = esp_timer_get_time();
+#endif
+ ESP_LOGI(TAG, "FACE: %uB %ums %s%d", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start) / 1000), detected ? "DETECTED " : "", face_id);
+ return res;
+#endif
+}
+
+static esp_err_t stream_handler(httpd_req_t *req)
+{
+ camera_fb_t *fb = NULL;
+ struct timeval _timestamp;
+ esp_err_t res = ESP_OK;
+ size_t _jpg_buf_len = 0;
+ uint8_t *_jpg_buf = NULL;
+ char *part_buf[128];
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ bool detected = false;
+ int64_t fr_ready = 0;
+ int64_t fr_recognize = 0;
+ int64_t fr_encode = 0;
+ int64_t fr_face = 0;
+ int64_t fr_start = 0;
+ #endif
+ int face_id = 0;
+ size_t out_len = 0, out_width = 0, out_height = 0;
+ uint8_t *out_buf = NULL;
+ bool s = false;
+#if TWO_STAGE
+ HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
+ HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
+#else
+ HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
+#endif
+#endif
+
+ static int64_t last_frame = 0;
+ if (!last_frame)
+ {
+ last_frame = esp_timer_get_time();
+ }
+
+ res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
+ if (res != ESP_OK)
+ {
+ return res;
+ }
+
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ httpd_resp_set_hdr(req, "X-Framerate", "60");
+
+#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
+ enable_led(true);
+ isStreaming = true;
+#endif
+
+ while (true)
+ {
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ detected = false;
+ #endif
+ face_id = 0;
+#endif
+
+ fb = esp_camera_fb_get();
+ if (!fb)
+ {
+ ESP_LOGE(TAG, "Camera capture failed");
+ res = ESP_FAIL;
+ }
+ else
+ {
+ _timestamp.tv_sec = fb->timestamp.tv_sec;
+ _timestamp.tv_usec = fb->timestamp.tv_usec;
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_start = esp_timer_get_time();
+ fr_ready = fr_start;
+ fr_encode = fr_start;
+ fr_recognize = fr_start;
+ fr_face = fr_start;
+ #endif
+ if (!detection_enabled || fb->width > 400)
+ {
+#endif
+ if (fb->format != PIXFORMAT_JPEG)
+ {
+ bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
+ esp_camera_fb_return(fb);
+ fb = NULL;
+ if (!jpeg_converted)
+ {
+ ESP_LOGE(TAG, "JPEG compression failed");
+ res = ESP_FAIL;
+ }
+ }
+ else
+ {
+ _jpg_buf_len = fb->len;
+ _jpg_buf = fb->buf;
+ }
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ }
+ else
+ {
+ if (fb->format == PIXFORMAT_RGB565
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ && !recognition_enabled
+#endif
+ ){
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_ready = esp_timer_get_time();
+#endif
+#if TWO_STAGE
+ std::list &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
+ std::list &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates);
+#else
+ std::list &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
+#endif
+#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_face = esp_timer_get_time();
+ fr_recognize = fr_face;
+#endif
+ if (results.size() > 0) {
+ fb_data_t rfb;
+ rfb.width = fb->width;
+ rfb.height = fb->height;
+ rfb.data = fb->buf;
+ rfb.bytes_per_pixel = 2;
+ rfb.format = FB_RGB565;
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ detected = true;
+#endif
+ draw_face_boxes(&rfb, &results, face_id);
+ }
+ s = fmt2jpg(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 80, &_jpg_buf, &_jpg_buf_len);
+ esp_camera_fb_return(fb);
+ fb = NULL;
+ if (!s) {
+ ESP_LOGE(TAG, "fmt2jpg failed");
+ res = ESP_FAIL;
+ }
+#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_encode = esp_timer_get_time();
+#endif
+ } else
+ {
+ out_len = fb->width * fb->height * 3;
+ out_width = fb->width;
+ out_height = fb->height;
+ out_buf = (uint8_t*)malloc(out_len);
+ if (!out_buf) {
+ ESP_LOGE(TAG, "out_buf malloc failed");
+ res = ESP_FAIL;
+ } else {
+ s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
+ esp_camera_fb_return(fb);
+ fb = NULL;
+ if (!s) {
+ free(out_buf);
+ ESP_LOGE(TAG, "to rgb888 failed");
+ res = ESP_FAIL;
+ } else {
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_ready = esp_timer_get_time();
+#endif
+
+ fb_data_t rfb;
+ rfb.width = out_width;
+ rfb.height = out_height;
+ rfb.data = out_buf;
+ rfb.bytes_per_pixel = 3;
+ rfb.format = FB_BGR888;
+
+#if TWO_STAGE
+ std::list &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
+ std::list &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates);
+#else
+ std::list &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
+#endif
+
+#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_face = esp_timer_get_time();
+ fr_recognize = fr_face;
+#endif
+
+ if (results.size() > 0) {
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ detected = true;
+#endif
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ if (recognition_enabled) {
+ face_id = run_face_recognition(&rfb, &results);
+ #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_recognize = esp_timer_get_time();
+ #endif
+ }
+#endif
+ draw_face_boxes(&rfb, &results, face_id);
+ }
+ s = fmt2jpg(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len);
+ free(out_buf);
+ if (!s) {
+ ESP_LOGE(TAG, "fmt2jpg failed");
+ res = ESP_FAIL;
+ }
+#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ fr_encode = esp_timer_get_time();
+#endif
+ }
+ }
+ }
+ }
+#endif
+ }
+ if (res == ESP_OK)
+ {
+ res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
+ }
+ if (res == ESP_OK)
+ {
+ size_t hlen = snprintf((char *)part_buf, 128, _STREAM_PART, _jpg_buf_len, _timestamp.tv_sec, _timestamp.tv_usec);
+ res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
+ }
+ if (res == ESP_OK)
+ {
+ res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
+ }
+ if (fb)
+ {
+ esp_camera_fb_return(fb);
+ fb = NULL;
+ _jpg_buf = NULL;
+ }
+ else if (_jpg_buf)
+ {
+ free(_jpg_buf);
+ _jpg_buf = NULL;
+ }
+ if (res != ESP_OK)
+ {
+ ESP_LOGE(TAG, "send frame failed failed");
+ break;
+ }
+ int64_t fr_end = esp_timer_get_time();
+
+#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ int64_t ready_time = (fr_ready - fr_start) / 1000;
+ int64_t face_time = (fr_face - fr_ready) / 1000;
+ int64_t recognize_time = (fr_recognize - fr_face) / 1000;
+ int64_t encode_time = (fr_encode - fr_recognize) / 1000;
+ int64_t process_time = (fr_encode - fr_start) / 1000;
+#endif
+
+ int64_t frame_time = fr_end - last_frame;
+ frame_time /= 1000;
+#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
+ uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
+#endif
+ ESP_LOGI(TAG, "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)"
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ ", %u+%u+%u+%u=%u %s%d"
+#endif
+ ,
+ (uint32_t)(_jpg_buf_len),
+ (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
+ avg_frame_time, 1000.0 / avg_frame_time
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ ,
+ (uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time,
+ (detected) ? "DETECTED " : "", face_id
+#endif
+ );
+ }
+
+#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
+ isStreaming = false;
+ enable_led(false);
+#endif
+
+ return res;
+}
+
+static esp_err_t parse_get(httpd_req_t *req, char **obuf)
+{
+ char *buf = NULL;
+ size_t buf_len = 0;
+
+ buf_len = httpd_req_get_url_query_len(req) + 1;
+ if (buf_len > 1) {
+ buf = (char *)malloc(buf_len);
+ if (!buf) {
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+ if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
+ *obuf = buf;
+ return ESP_OK;
+ }
+ free(buf);
+ }
+ httpd_resp_send_404(req);
+ return ESP_FAIL;
+}
+
+static esp_err_t cmd_handler(httpd_req_t *req)
+{
+ char *buf = NULL;
+ char variable[32];
+ char value[32];
+
+ if (parse_get(req, &buf) != ESP_OK) {
+ return ESP_FAIL;
+ }
+ if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) != ESP_OK ||
+ httpd_query_key_value(buf, "val", value, sizeof(value)) != ESP_OK) {
+ free(buf);
+ httpd_resp_send_404(req);
+ return ESP_FAIL;
+ }
+ free(buf);
+
+ int val = atoi(value);
+ ESP_LOGI(TAG, "%s = %d", variable, val);
+ sensor_t *s = esp_camera_sensor_get();
+ int res = 0;
+
+ if (!strcmp(variable, "framesize")) {
+ if (s->pixformat == PIXFORMAT_JPEG) {
+ res = s->set_framesize(s, (framesize_t)val);
+ }
+ }
+ else if (!strcmp(variable, "quality"))
+ res = s->set_quality(s, val);
+ else if (!strcmp(variable, "contrast"))
+ res = s->set_contrast(s, val);
+ else if (!strcmp(variable, "brightness"))
+ res = s->set_brightness(s, val);
+ else if (!strcmp(variable, "saturation"))
+ res = s->set_saturation(s, val);
+ else if (!strcmp(variable, "gainceiling"))
+ res = s->set_gainceiling(s, (gainceiling_t)val);
+ else if (!strcmp(variable, "colorbar"))
+ res = s->set_colorbar(s, val);
+ else if (!strcmp(variable, "awb"))
+ res = s->set_whitebal(s, val);
+ else if (!strcmp(variable, "agc"))
+ res = s->set_gain_ctrl(s, val);
+ else if (!strcmp(variable, "aec"))
+ res = s->set_exposure_ctrl(s, val);
+ else if (!strcmp(variable, "hmirror"))
+ res = s->set_hmirror(s, val);
+ else if (!strcmp(variable, "vflip"))
+ res = s->set_vflip(s, val);
+ else if (!strcmp(variable, "awb_gain"))
+ res = s->set_awb_gain(s, val);
+ else if (!strcmp(variable, "agc_gain"))
+ res = s->set_agc_gain(s, val);
+ else if (!strcmp(variable, "aec_value"))
+ res = s->set_aec_value(s, val);
+ else if (!strcmp(variable, "aec2"))
+ res = s->set_aec2(s, val);
+ else if (!strcmp(variable, "dcw"))
+ res = s->set_dcw(s, val);
+ else if (!strcmp(variable, "bpc"))
+ res = s->set_bpc(s, val);
+ else if (!strcmp(variable, "wpc"))
+ res = s->set_wpc(s, val);
+ else if (!strcmp(variable, "raw_gma"))
+ res = s->set_raw_gma(s, val);
+ else if (!strcmp(variable, "lenc"))
+ res = s->set_lenc(s, val);
+ else if (!strcmp(variable, "special_effect"))
+ res = s->set_special_effect(s, val);
+ else if (!strcmp(variable, "wb_mode"))
+ res = s->set_wb_mode(s, val);
+ else if (!strcmp(variable, "ae_level"))
+ res = s->set_ae_level(s, val);
+#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
+ else if (!strcmp(variable, "led_intensity")) {
+ led_duty = val;
+ if (isStreaming)
+ enable_led(true);
+ }
+#endif
+
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ else if (!strcmp(variable, "face_detect")) {
+ detection_enabled = val;
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ if (!detection_enabled) {
+ recognition_enabled = 0;
+ }
+#endif
+ }
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ else if (!strcmp(variable, "face_enroll")){
+ is_enrolling = !is_enrolling;
+ ESP_LOGI(TAG, "Enrolling: %s", is_enrolling?"true":"false");
+ }
+ else if (!strcmp(variable, "face_recognize")) {
+ recognition_enabled = val;
+ if (recognition_enabled) {
+ detection_enabled = val;
+ }
+ }
+#endif
+#endif
+ else {
+ ESP_LOGI(TAG, "Unknown command: %s", variable);
+ res = -1;
+ }
+
+ if (res < 0) {
+ return httpd_resp_send_500(req);
+ }
+
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, NULL, 0);
+}
+
+static int print_reg(char * p, sensor_t * s, uint16_t reg, uint32_t mask){
+ return sprintf(p, "\"0x%x\":%u,", reg, s->get_reg(s, reg, mask));
+}
+
+static esp_err_t status_handler(httpd_req_t *req)
+{
+ static char json_response[1024];
+
+ sensor_t *s = esp_camera_sensor_get();
+ char *p = json_response;
+ *p++ = '{';
+
+ if(s->id.PID == OV5640_PID || s->id.PID == OV3660_PID){
+ for(int reg = 0x3400; reg < 0x3406; reg+=2){
+ p+=print_reg(p, s, reg, 0xFFF);//12 bit
+ }
+ p+=print_reg(p, s, 0x3406, 0xFF);
+
+ p+=print_reg(p, s, 0x3500, 0xFFFF0);//16 bit
+ p+=print_reg(p, s, 0x3503, 0xFF);
+ p+=print_reg(p, s, 0x350a, 0x3FF);//10 bit
+ p+=print_reg(p, s, 0x350c, 0xFFFF);//16 bit
+
+ for(int reg = 0x5480; reg <= 0x5490; reg++){
+ p+=print_reg(p, s, reg, 0xFF);
+ }
+
+ for(int reg = 0x5380; reg <= 0x538b; reg++){
+ p+=print_reg(p, s, reg, 0xFF);
+ }
+
+ for(int reg = 0x5580; reg < 0x558a; reg++){
+ p+=print_reg(p, s, reg, 0xFF);
+ }
+ p+=print_reg(p, s, 0x558a, 0x1FF);//9 bit
+ } else if(s->id.PID == OV2640_PID){
+ p+=print_reg(p, s, 0xd3, 0xFF);
+ p+=print_reg(p, s, 0x111, 0xFF);
+ p+=print_reg(p, s, 0x132, 0xFF);
+ }
+
+ p += sprintf(p, "\"xclk\":%u,", s->xclk_freq_hz / 1000000);
+ p += sprintf(p, "\"pixformat\":%u,", s->pixformat);
+ p += sprintf(p, "\"framesize\":%u,", s->status.framesize);
+ p += sprintf(p, "\"quality\":%u,", s->status.quality);
+ p += sprintf(p, "\"brightness\":%d,", s->status.brightness);
+ p += sprintf(p, "\"contrast\":%d,", s->status.contrast);
+ p += sprintf(p, "\"saturation\":%d,", s->status.saturation);
+ p += sprintf(p, "\"sharpness\":%d,", s->status.sharpness);
+ p += sprintf(p, "\"special_effect\":%u,", s->status.special_effect);
+ p += sprintf(p, "\"wb_mode\":%u,", s->status.wb_mode);
+ p += sprintf(p, "\"awb\":%u,", s->status.awb);
+ p += sprintf(p, "\"awb_gain\":%u,", s->status.awb_gain);
+ p += sprintf(p, "\"aec\":%u,", s->status.aec);
+ p += sprintf(p, "\"aec2\":%u,", s->status.aec2);
+ p += sprintf(p, "\"ae_level\":%d,", s->status.ae_level);
+ p += sprintf(p, "\"aec_value\":%u,", s->status.aec_value);
+ p += sprintf(p, "\"agc\":%u,", s->status.agc);
+ p += sprintf(p, "\"agc_gain\":%u,", s->status.agc_gain);
+ p += sprintf(p, "\"gainceiling\":%u,", s->status.gainceiling);
+ p += sprintf(p, "\"bpc\":%u,", s->status.bpc);
+ p += sprintf(p, "\"wpc\":%u,", s->status.wpc);
+ p += sprintf(p, "\"raw_gma\":%u,", s->status.raw_gma);
+ p += sprintf(p, "\"lenc\":%u,", s->status.lenc);
+ p += sprintf(p, "\"hmirror\":%u,", s->status.hmirror);
+ p += sprintf(p, "\"dcw\":%u,", s->status.dcw);
+ p += sprintf(p, "\"colorbar\":%u", s->status.colorbar);
+#ifdef CONFIG_LED_ILLUMINATOR_ENABLED
+ p += sprintf(p, ",\"led_intensity\":%u", led_duty);
+#else
+ p += sprintf(p, ",\"led_intensity\":%d", -1);
+#endif
+#if CONFIG_ESP_FACE_DETECT_ENABLED
+ p += sprintf(p, ",\"face_detect\":%u", detection_enabled);
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ p += sprintf(p, ",\"face_enroll\":%u,", is_enrolling);
+ p += sprintf(p, "\"face_recognize\":%u", recognition_enabled);
+#endif
+#endif
+ *p++ = '}';
+ *p++ = 0;
+ httpd_resp_set_type(req, "application/json");
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, json_response, strlen(json_response));
+}
+
+static esp_err_t xclk_handler(httpd_req_t *req)
+{
+ char *buf = NULL;
+ char _xclk[32];
+
+ if (parse_get(req, &buf) != ESP_OK) {
+ return ESP_FAIL;
+ }
+ if (httpd_query_key_value(buf, "xclk", _xclk, sizeof(_xclk)) != ESP_OK) {
+ free(buf);
+ httpd_resp_send_404(req);
+ return ESP_FAIL;
+ }
+ free(buf);
+
+ int xclk = atoi(_xclk);
+ ESP_LOGI(TAG, "Set XCLK: %d MHz", xclk);
+
+ sensor_t *s = esp_camera_sensor_get();
+ int res = s->set_xclk(s, LEDC_TIMER_0, xclk);
+ if (res) {
+ return httpd_resp_send_500(req);
+ }
+
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, NULL, 0);
+}
+
+static esp_err_t reg_handler(httpd_req_t *req)
+{
+ char *buf = NULL;
+ char _reg[32];
+ char _mask[32];
+ char _val[32];
+
+ if (parse_get(req, &buf) != ESP_OK) {
+ return ESP_FAIL;
+ }
+ if (httpd_query_key_value(buf, "reg", _reg, sizeof(_reg)) != ESP_OK ||
+ httpd_query_key_value(buf, "mask", _mask, sizeof(_mask)) != ESP_OK ||
+ httpd_query_key_value(buf, "val", _val, sizeof(_val)) != ESP_OK) {
+ free(buf);
+ httpd_resp_send_404(req);
+ return ESP_FAIL;
+ }
+ free(buf);
+
+ int reg = atoi(_reg);
+ int mask = atoi(_mask);
+ int val = atoi(_val);
+ ESP_LOGI(TAG, "Set Register: reg: 0x%02x, mask: 0x%02x, value: 0x%02x", reg, mask, val);
+
+ sensor_t *s = esp_camera_sensor_get();
+ int res = s->set_reg(s, reg, mask, val);
+ if (res) {
+ return httpd_resp_send_500(req);
+ }
+
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, NULL, 0);
+}
+
+static esp_err_t greg_handler(httpd_req_t *req)
+{
+ char *buf = NULL;
+ char _reg[32];
+ char _mask[32];
+
+ if (parse_get(req, &buf) != ESP_OK) {
+ return ESP_FAIL;
+ }
+ if (httpd_query_key_value(buf, "reg", _reg, sizeof(_reg)) != ESP_OK ||
+ httpd_query_key_value(buf, "mask", _mask, sizeof(_mask)) != ESP_OK) {
+ free(buf);
+ httpd_resp_send_404(req);
+ return ESP_FAIL;
+ }
+ free(buf);
+
+ int reg = atoi(_reg);
+ int mask = atoi(_mask);
+ sensor_t *s = esp_camera_sensor_get();
+ int res = s->get_reg(s, reg, mask);
+ if (res < 0) {
+ return httpd_resp_send_500(req);
+ }
+ ESP_LOGI(TAG, "Get Register: reg: 0x%02x, mask: 0x%02x, value: 0x%02x", reg, mask, res);
+
+ char buffer[20];
+ const char * val = itoa(res, buffer, 10);
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, val, strlen(val));
+}
+
+static int parse_get_var(char *buf, const char * key, int def)
+{
+ char _int[16];
+ if(httpd_query_key_value(buf, key, _int, sizeof(_int)) != ESP_OK){
+ return def;
+ }
+ return atoi(_int);
+}
+
+static esp_err_t pll_handler(httpd_req_t *req)
+{
+ char *buf = NULL;
+
+ if (parse_get(req, &buf) != ESP_OK) {
+ return ESP_FAIL;
+ }
+
+ int bypass = parse_get_var(buf, "bypass", 0);
+ int mul = parse_get_var(buf, "mul", 0);
+ int sys = parse_get_var(buf, "sys", 0);
+ int root = parse_get_var(buf, "root", 0);
+ int pre = parse_get_var(buf, "pre", 0);
+ int seld5 = parse_get_var(buf, "seld5", 0);
+ int pclken = parse_get_var(buf, "pclken", 0);
+ int pclk = parse_get_var(buf, "pclk", 0);
+ free(buf);
+
+ ESP_LOGI(TAG, "Set Pll: bypass: %d, mul: %d, sys: %d, root: %d, pre: %d, seld5: %d, pclken: %d, pclk: %d", bypass, mul, sys, root, pre, seld5, pclken, pclk);
+ sensor_t *s = esp_camera_sensor_get();
+ int res = s->set_pll(s, bypass, mul, sys, root, pre, seld5, pclken, pclk);
+ if (res) {
+ return httpd_resp_send_500(req);
+ }
+
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, NULL, 0);
+}
+
+static esp_err_t win_handler(httpd_req_t *req)
+{
+ char *buf = NULL;
+
+ if (parse_get(req, &buf) != ESP_OK) {
+ return ESP_FAIL;
+ }
+
+ int startX = parse_get_var(buf, "sx", 0);
+ int startY = parse_get_var(buf, "sy", 0);
+ int endX = parse_get_var(buf, "ex", 0);
+ int endY = parse_get_var(buf, "ey", 0);
+ int offsetX = parse_get_var(buf, "offx", 0);
+ int offsetY = parse_get_var(buf, "offy", 0);
+ int totalX = parse_get_var(buf, "tx", 0);
+ int totalY = parse_get_var(buf, "ty", 0);
+ int outputX = parse_get_var(buf, "ox", 0);
+ int outputY = parse_get_var(buf, "oy", 0);
+ bool scale = parse_get_var(buf, "scale", 0) == 1;
+ bool binning = parse_get_var(buf, "binning", 0) == 1;
+ free(buf);
+
+ ESP_LOGI(TAG, "Set Window: Start: %d %d, End: %d %d, Offset: %d %d, Total: %d %d, Output: %d %d, Scale: %u, Binning: %u", startX, startY, endX, endY, offsetX, offsetY, totalX, totalY, outputX, outputY, scale, binning);
+ sensor_t *s = esp_camera_sensor_get();
+ int res = s->set_res_raw(s, startX, startY, endX, endY, offsetX, offsetY, totalX, totalY, outputX, outputY, scale, binning);
+ if (res) {
+ return httpd_resp_send_500(req);
+ }
+
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, NULL, 0);
+}
+
+static esp_err_t index_handler(httpd_req_t *req)
+{
+ httpd_resp_set_type(req, "text/html");
+ httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
+ sensor_t *s = esp_camera_sensor_get();
+ if (s != NULL) {
+ if (s->id.PID == OV3660_PID) {
+ return httpd_resp_send(req, (const char *)index_ov3660_html_gz, index_ov3660_html_gz_len);
+ } else if (s->id.PID == OV5640_PID) {
+ return httpd_resp_send(req, (const char *)index_ov5640_html_gz, index_ov5640_html_gz_len);
+ } else {
+ return httpd_resp_send(req, (const char *)index_ov2640_html_gz, index_ov2640_html_gz_len);
+ }
+ } else {
+ ESP_LOGE(TAG, "Camera sensor not found");
+ return httpd_resp_send_500(req);
+ }
+}
+
+void startCameraServer()
+{
+ httpd_config_t config = HTTPD_DEFAULT_CONFIG();
+ config.max_uri_handlers = 16;
+
+ httpd_uri_t index_uri = {
+ .uri = "/",
+ .method = HTTP_GET,
+ .handler = index_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t status_uri = {
+ .uri = "/status",
+ .method = HTTP_GET,
+ .handler = status_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t cmd_uri = {
+ .uri = "/control",
+ .method = HTTP_GET,
+ .handler = cmd_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t capture_uri = {
+ .uri = "/capture",
+ .method = HTTP_GET,
+ .handler = capture_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t stream_uri = {
+ .uri = "/stream",
+ .method = HTTP_GET,
+ .handler = stream_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t bmp_uri = {
+ .uri = "/bmp",
+ .method = HTTP_GET,
+ .handler = bmp_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t xclk_uri = {
+ .uri = "/xclk",
+ .method = HTTP_GET,
+ .handler = xclk_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t reg_uri = {
+ .uri = "/reg",
+ .method = HTTP_GET,
+ .handler = reg_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t greg_uri = {
+ .uri = "/greg",
+ .method = HTTP_GET,
+ .handler = greg_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t pll_uri = {
+ .uri = "/pll",
+ .method = HTTP_GET,
+ .handler = pll_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ httpd_uri_t win_uri = {
+ .uri = "/resolution",
+ .method = HTTP_GET,
+ .handler = win_handler,
+ .user_ctx = NULL
+#ifdef CONFIG_HTTPD_WS_SUPPORT
+ ,
+ .is_websocket = true,
+ .handle_ws_control_frames = false,
+ .supported_subprotocol = NULL
+#endif
+ };
+
+ ra_filter_init(&ra_filter, 20);
+
+#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
+ recognizer.set_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "fr");
+
+ // load ids from flash partition
+ recognizer.set_ids_from_flash();
+#endif
+ ESP_LOGI(TAG, "Starting web server on port: '%d'", config.server_port);
+ if (httpd_start(&camera_httpd, &config) == ESP_OK)
+ {
+ httpd_register_uri_handler(camera_httpd, &index_uri);
+ httpd_register_uri_handler(camera_httpd, &cmd_uri);
+ httpd_register_uri_handler(camera_httpd, &status_uri);
+ httpd_register_uri_handler(camera_httpd, &capture_uri);
+ httpd_register_uri_handler(camera_httpd, &bmp_uri);
+
+ httpd_register_uri_handler(camera_httpd, &xclk_uri);
+ httpd_register_uri_handler(camera_httpd, ®_uri);
+ httpd_register_uri_handler(camera_httpd, &greg_uri);
+ httpd_register_uri_handler(camera_httpd, &pll_uri);
+ httpd_register_uri_handler(camera_httpd, &win_uri);
+ }
+
+ config.server_port += 1;
+ config.ctrl_port += 1;
+ ESP_LOGI(TAG, "Starting stream server on port: '%d'", config.server_port);
+ if (httpd_start(&stream_httpd, &config) == ESP_OK)
+ {
+ httpd_register_uri_handler(stream_httpd, &stream_uri);
+ }
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/camera_index.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/camera_index.h
new file mode 100644
index 0000000..fa42e69
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/camera_index.h
@@ -0,0 +1,1571 @@
+
+
+//File: index_ov2640.html.gz, Size: 6787
+#define index_ov2640_html_gz_len 6787
+const uint8_t index_ov2640_html_gz[] = {
+ 0x1F, 0x8B, 0x08, 0x08, 0x23, 0xFC, 0x69, 0x5E, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F,
+ 0x6F, 0x76, 0x32, 0x36, 0x34, 0x30, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x00, 0xED, 0x3D, 0x6B, 0x73,
+ 0xDB, 0x46, 0x92, 0xDF, 0xFD, 0x2B, 0x60, 0x24, 0x6B, 0x92, 0x25, 0x92, 0x22, 0x29, 0x4A, 0x96,
+ 0x15, 0x89, 0x3E, 0x5B, 0x96, 0x1F, 0xB5, 0x76, 0xE2, 0xB5, 0x12, 0xC7, 0x5B, 0xA9, 0x2D, 0x07,
+ 0x04, 0x86, 0x24, 0x62, 0x10, 0xE0, 0x02, 0xA0, 0x48, 0x26, 0xA5, 0xDF, 0x71, 0x3F, 0xE8, 0xFE,
+ 0xD8, 0x75, 0xCF, 0x03, 0x18, 0x00, 0x83, 0x07, 0x49, 0x89, 0xF4, 0xFA, 0x8E, 0x4E, 0x45, 0x78,
+ 0x4C, 0xF7, 0xF4, 0xBB, 0x7B, 0x66, 0x30, 0xC0, 0xF9, 0x43, 0xCB, 0x33, 0xC3, 0xD5, 0x8C, 0x68,
+ 0x93, 0x70, 0xEA, 0x0C, 0x1E, 0x9C, 0xB3, 0x3F, 0x1A, 0xFC, 0xCE, 0x27, 0xC4, 0xB0, 0xD8, 0x21,
+ 0x3D, 0x9D, 0x92, 0xD0, 0xD0, 0xCC, 0x89, 0xE1, 0x07, 0x24, 0xBC, 0xD0, 0xE7, 0xE1, 0xA8, 0x75,
+ 0xAA, 0xA7, 0x6F, 0xBB, 0xC6, 0x94, 0x5C, 0xE8, 0x37, 0x36, 0x59, 0xCC, 0x3C, 0x3F, 0xD4, 0x35,
+ 0xD3, 0x73, 0x43, 0xE2, 0x42, 0xF3, 0x85, 0x6D, 0x85, 0x93, 0x0B, 0x8B, 0xDC, 0xD8, 0x26, 0x69,
+ 0xD1, 0x93, 0xA6, 0xED, 0xDA, 0xA1, 0x6D, 0x38, 0xAD, 0xC0, 0x34, 0x1C, 0x72, 0xD1, 0x95, 0x71,
+ 0x85, 0x76, 0xE8, 0x90, 0xC1, 0xD5, 0xF5, 0xFB, 0xA3, 0x9E, 0xF6, 0xD3, 0xC7, 0x5E, 0xFF, 0xA4,
+ 0x73, 0x7E, 0xC8, 0xAE, 0xC5, 0x6D, 0x82, 0x70, 0x25, 0x9F, 0xE3, 0x6F, 0xE8, 0x59, 0x2B, 0xED,
+ 0xAF, 0xC4, 0x25, 0xFC, 0x8D, 0x80, 0x88, 0xD6, 0xC8, 0x98, 0xDA, 0xCE, 0xEA, 0x4C, 0x7B, 0xE6,
+ 0x43, 0x9F, 0xCD, 0xD7, 0xC4, 0xB9, 0x21, 0xA1, 0x6D, 0x1A, 0xCD, 0xC0, 0x70, 0x83, 0x56, 0x40,
+ 0x7C, 0x7B, 0xF4, 0x43, 0x06, 0x70, 0x68, 0x98, 0x5F, 0xC6, 0xBE, 0x37, 0x77, 0xAD, 0x33, 0xED,
+ 0xBB, 0xEE, 0x29, 0xFE, 0xCB, 0x36, 0x32, 0x3D, 0xC7, 0xF3, 0xE1, 0xFE, 0xD5, 0x4B, 0xFC, 0x97,
+ 0xBD, 0x4F, 0x7B, 0x0F, 0xEC, 0x3F, 0xC9, 0x99, 0xD6, 0x3D, 0x99, 0x2D, 0x13, 0xF7, 0x6F, 0x1F,
+ 0x24, 0x4E, 0x27, 0xBD, 0x3C, 0xEA, 0x39, 0xFC, 0x69, 0x31, 0x7C, 0x40, 0xCC, 0xD0, 0xF6, 0xDC,
+ 0xF6, 0xD4, 0xB0, 0x5D, 0x05, 0x26, 0xCB, 0x0E, 0x66, 0x8E, 0x01, 0x32, 0x18, 0x39, 0xA4, 0x10,
+ 0xCF, 0x77, 0x53, 0xE2, 0xCE, 0x9B, 0x25, 0xD8, 0x10, 0x49, 0xCB, 0xB2, 0x7D, 0xD6, 0xEA, 0x0C,
+ 0xE5, 0x30, 0x9F, 0xBA, 0xA5, 0x68, 0x8B, 0xE8, 0x72, 0x3D, 0x97, 0x28, 0x04, 0x88, 0x1D, 0x2D,
+ 0x7C, 0x63, 0x86, 0x0D, 0xF0, 0x6F, 0xB6, 0xC9, 0xD4, 0x76, 0x99, 0x51, 0x9D, 0x69, 0x47, 0xFD,
+ 0xCE, 0x6C, 0x59, 0xA2, 0xCA, 0xA3, 0x13, 0xFC, 0x97, 0x6D, 0x34, 0x33, 0x2C, 0xCB, 0x76, 0xC7,
+ 0x67, 0xDA, 0xA9, 0x12, 0x85, 0xE7, 0x5B, 0xC4, 0x6F, 0xF9, 0x86, 0x65, 0xCF, 0x83, 0x33, 0xAD,
+ 0xAF, 0x6A, 0x33, 0x35, 0xFC, 0x31, 0xD0, 0x12, 0x7A, 0x40, 0x6C, 0xAB, 0xAB, 0xA4, 0x84, 0x37,
+ 0xF1, 0xED, 0xF1, 0x24, 0x04, 0x95, 0x66, 0xDA, 0xA4, 0x85, 0xC6, 0x5D, 0xA8, 0x4C, 0x9F, 0x85,
+ 0x72, 0x53, 0x4B, 0xCD, 0x70, 0xEC, 0xB1, 0xDB, 0xB2, 0x43, 0x32, 0x05, 0x76, 0x82, 0xD0, 0x27,
+ 0xA1, 0x39, 0x29, 0x22, 0x65, 0x64, 0x8F, 0xE7, 0x3E, 0x51, 0x10, 0x12, 0xC9, 0xAD, 0x80, 0x61,
+ 0xB8, 0x99, 0xBD, 0xD5, 0x5A, 0x90, 0xE1, 0x17, 0x3B, 0x6C, 0x71, 0x99, 0x0C, 0xC9, 0xC8, 0xF3,
+ 0x89, 0xB2, 0xA5, 0x68, 0xE1, 0x78, 0xE6, 0x97, 0x56, 0x10, 0x1A, 0x7E, 0x58, 0x05, 0xA1, 0x31,
+ 0x0A, 0x89, 0x5F, 0x8E, 0x8F, 0xA0, 0x55, 0x94, 0x63, 0xCB, 0xEF, 0x96, 0x37, 0xB0, 0x5D, 0xC7,
+ 0x76, 0x49, 0x75, 0xF2, 0xF2, 0xFA, 0x4D, 0xA2, 0x63, 0xAD, 0x2A, 0x28, 0xC6, 0x9E, 0x8E, 0x8B,
+ 0xAC, 0x84, 0xF2, 0x9A, 0xED, 0x8C, 0xFB, 0x4D, 0xB7, 0xD3, 0xF9, 0x5B, 0xF6, 0xE6, 0x84, 0x30,
+ 0x33, 0x35, 0xE6, 0xA1, 0xB7, 0xBD, 0x47, 0x64, 0xDC, 0x2A, 0xC5, 0xC7, 0x7F, 0x4D, 0x89, 0x65,
+ 0x1B, 0x5A, 0x5D, 0x72, 0xE7, 0xD3, 0x0E, 0xD8, 0x54, 0x43, 0x33, 0x5C, 0x4B, 0xAB, 0x7B, 0xBE,
+ 0x0D, 0x8E, 0x60, 0xD0, 0x70, 0xE3, 0xC0, 0x15, 0x48, 0x1C, 0x33, 0xD2, 0x50, 0xB0, 0x5C, 0xE0,
+ 0x33, 0xB2, 0x44, 0xD4, 0x6E, 0x83, 0xBF, 0x0A, 0x21, 0x07, 0x7F, 0xA5, 0x0E, 0xA4, 0xE0, 0x91,
+ 0xA2, 0x2F, 0xD2, 0x97, 0x4C, 0x61, 0x9E, 0xCE, 0xF0, 0x37, 0x35, 0x96, 0xAD, 0x42, 0xDD, 0x89,
+ 0x46, 0x42, 0x87, 0x90, 0x66, 0xCD, 0x3A, 0x34, 0xBD, 0x99, 0x68, 0x2D, 0x0D, 0xA3, 0x64, 0x43,
+ 0x0D, 0xC3, 0x91, 0xAA, 0x55, 0x8E, 0x3F, 0xD9, 0x28, 0xD6, 0x60, 0x57, 0xCD, 0x6A, 0x1C, 0x3B,
+ 0xD8, 0x3F, 0x95, 0x0D, 0x31, 0x4E, 0x72, 0xA3, 0x08, 0xFE, 0xAA, 0x47, 0x92, 0x18, 0x59, 0x69,
+ 0x34, 0x51, 0x20, 0xCE, 0x8F, 0x28, 0x19, 0xBC, 0x79, 0xDE, 0xAD, 0xC0, 0x5A, 0x4C, 0x42, 0xD5,
+ 0xE8, 0xA2, 0x40, 0x5C, 0x44, 0x43, 0x69, 0x94, 0xC1, 0xDF, 0x6D, 0x85, 0x7A, 0xE3, 0xBB, 0xE1,
+ 0x3C, 0x0C, 0x3D, 0x37, 0xD8, 0x2A, 0x45, 0xE5, 0xF9, 0xD9, 0x1F, 0xF3, 0x20, 0xB4, 0x47, 0xAB,
+ 0x16, 0x77, 0x69, 0xF0, 0xB3, 0x99, 0x01, 0x25, 0xE4, 0x90, 0x84, 0x0B, 0x42, 0x8A, 0xCB, 0x0D,
+ 0xD7, 0xB8, 0x81, 0xB8, 0x33, 0x1E, 0x3B, 0x2A, 0xDB, 0x33, 0xE7, 0x7E, 0x80, 0x75, 0xDB, 0xCC,
+ 0xB3, 0x01, 0xB1, 0x9F, 0xED, 0x38, 0xE9, 0x83, 0x15, 0x3B, 0x6A, 0x99, 0x43, 0x45, 0x5F, 0xDE,
+ 0x3C, 0x44, 0x19, 0x2B, 0x35, 0xE1, 0x01, 0x3B, 0x76, 0xB8, 0x52, 0xDE, 0xE3, 0x9E, 0xA8, 0xB8,
+ 0x23, 0x5C, 0xB0, 0x30, 0x2D, 0x24, 0xE9, 0x3A, 0x33, 0x27, 0xC4, 0xFC, 0x42, 0xAC, 0x83, 0xD2,
+ 0x32, 0xAC, 0xAC, 0x3C, 0x6C, 0xDB, 0xEE, 0x6C, 0x1E, 0xB6, 0xB0, 0x9C, 0x9A, 0xDD, 0x8B, 0xCE,
+ 0xA9, 0x41, 0x0A, 0x16, 0x7B, 0xBD, 0xA2, 0xA2, 0xE2, 0x78, 0xB6, 0x2C, 0x16, 0x82, 0x4C, 0xEC,
+ 0xC0, 0x31, 0x86, 0xC4, 0x29, 0x22, 0x99, 0x3B, 0x43, 0x4E, 0xD8, 0xE5, 0xB1, 0x2A, 0xBF, 0x76,
+ 0xA3, 0x94, 0xC5, 0xC9, 0xAB, 0xFF, 0xF8, 0x6F, 0x95, 0xE5, 0x48, 0x8F, 0x9B, 0x89, 0x4B, 0x01,
+ 0x71, 0xC0, 0xC1, 0xF2, 0x4A, 0x6F, 0x68, 0xB3, 0x00, 0x1A, 0x0A, 0x3B, 0xF0, 0x0D, 0x77, 0x4C,
+ 0x20, 0x16, 0x2C, 0x9B, 0xE2, 0xB0, 0x78, 0x60, 0x50, 0x89, 0x7D, 0x0C, 0xD5, 0xC7, 0xC5, 0x03,
+ 0x11, 0x16, 0x10, 0x9A, 0x5A, 0x9B, 0x1D, 0x6C, 0x50, 0x95, 0x48, 0xFA, 0x2D, 0x24, 0xA4, 0xAB,
+ 0xB4, 0x0E, 0x56, 0x98, 0x28, 0x3D, 0x27, 0x69, 0x5B, 0xCA, 0x42, 0xBF, 0x34, 0x34, 0x88, 0x21,
+ 0xDF, 0x68, 0x54, 0x36, 0x68, 0x1C, 0x8D, 0x8E, 0x3A, 0x47, 0xFD, 0xD2, 0xCA, 0x49, 0xC9, 0x65,
+ 0x6A, 0xE0, 0xA8, 0x08, 0x1D, 0x51, 0x58, 0x29, 0x34, 0x82, 0xC0, 0xB8, 0x51, 0x16, 0xED, 0x5E,
+ 0x60, 0xB3, 0x91, 0x9B, 0x31, 0x0C, 0x60, 0xEC, 0x16, 0x2A, 0x86, 0x5E, 0xDC, 0xD0, 0x7B, 0x4A,
+ 0xFA, 0x68, 0x49, 0xA7, 0x74, 0x01, 0x21, 0x5E, 0x35, 0xD9, 0x09, 0x0D, 0xA8, 0x9B, 0x48, 0x0A,
+ 0x56, 0x16, 0x95, 0x21, 0x59, 0x86, 0x2D, 0x8B, 0x98, 0x9E, 0xCF, 0xAA, 0xC1, 0x9C, 0x91, 0x63,
+ 0x4A, 0x91, 0xE5, 0x16, 0x7B, 0x36, 0xF1, 0x6E, 0x88, 0xAF, 0x10, 0x56, 0x4A, 0xA9, 0xFD, 0x27,
+ 0x7D, 0xAB, 0x02, 0x36, 0x03, 0xD2, 0xA3, 0x52, 0xF6, 0x49, 0x74, 0xBD, 0xAE, 0xD9, 0x2B, 0xF4,
+ 0x63, 0x86, 0xAE, 0x0D, 0x3E, 0x63, 0x0C, 0x1D, 0x62, 0x15, 0x64, 0x33, 0x8B, 0x8C, 0x8C, 0xB9,
+ 0x13, 0x96, 0x58, 0xA5, 0xD1, 0xC1, 0x7F, 0x45, 0x3D, 0xD2, 0x30, 0xF4, 0x1B, 0xCE, 0x0B, 0x5D,
+ 0xD0, 0xC0, 0xF1, 0x2F, 0x45, 0x9F, 0xA2, 0xD4, 0x30, 0x66, 0x33, 0x62, 0x40, 0x2B, 0x93, 0xE4,
+ 0xE9, 0xA1, 0xD2, 0x10, 0x43, 0x1D, 0xE7, 0x2B, 0x8D, 0xDB, 0x4B, 0x1D, 0x36, 0x2A, 0x1E, 0xD7,
+ 0xE2, 0xF9, 0x6C, 0xE4, 0x99, 0x73, 0x55, 0x55, 0x53, 0xCD, 0xF1, 0xB2, 0xF8, 0xCE, 0x84, 0xC8,
+ 0x02, 0xC7, 0xA6, 0xEE, 0x3F, 0x77, 0x5D, 0xD4, 0x68, 0x2B, 0xF4, 0x81, 0x4D, 0x45, 0x47, 0xD5,
+ 0x04, 0xB7, 0x51, 0x0C, 0x4B, 0x08, 0x36, 0x6F, 0xEE, 0x2A, 0x15, 0xA6, 0x14, 0xE1, 0x34, 0x8A,
+ 0xB4, 0x1A, 0xC4, 0x10, 0xDB, 0x12, 0xA8, 0xB6, 0x93, 0x4B, 0x38, 0x99, 0x4F, 0x55, 0x75, 0x94,
+ 0xE8, 0xAC, 0x0B, 0x49, 0x9F, 0x75, 0xE7, 0x8F, 0x87, 0x46, 0xBD, 0xD3, 0xEC, 0x34, 0x8F, 0xE0,
+ 0x7F, 0x8A, 0xF1, 0x4C, 0xB1, 0x71, 0x71, 0xF1, 0xE6, 0x58, 0x5E, 0x2A, 0x44, 0x97, 0x4F, 0x2B,
+ 0xE5, 0x05, 0xFB, 0x52, 0x5D, 0x54, 0xF7, 0xA4, 0xE4, 0xFC, 0x52, 0xB7, 0x5D, 0x92, 0x87, 0x73,
+ 0x4C, 0x7A, 0x7D, 0x43, 0x54, 0x58, 0xCB, 0xBA, 0x2A, 0x9E, 0x7A, 0x7F, 0xB6, 0x58, 0x11, 0xF2,
+ 0x7F, 0xDE, 0xDA, 0x25, 0x51, 0x7C, 0xD3, 0x96, 0xBE, 0xB6, 0x5C, 0x82, 0x7D, 0xDB, 0x46, 0x27,
+ 0x5F, 0xEB, 0x2D, 0x5E, 0xF5, 0x01, 0x85, 0x2E, 0x8C, 0x41, 0x7D, 0x18, 0x8C, 0xE6, 0x56, 0x86,
+ 0x52, 0x9B, 0x0D, 0x64, 0x30, 0xB2, 0x1D, 0xA7, 0xE5, 0x78, 0x8B, 0xF2, 0x4A, 0xA4, 0xD8, 0x92,
+ 0x33, 0x76, 0x5A, 0x6E, 0xF2, 0x9B, 0x52, 0x3B, 0x87, 0xC8, 0xF5, 0x1F, 0x41, 0xED, 0xB7, 0xED,
+ 0x70, 0x85, 0xAE, 0xB1, 0x59, 0xA2, 0xD8, 0xC0, 0x1E, 0xB7, 0xEB, 0xA8, 0x92, 0x29, 0xB1, 0x4A,
+ 0xB0, 0x78, 0xD8, 0xB3, 0xB0, 0x43, 0x73, 0xB2, 0xC1, 0xD0, 0x33, 0x1E, 0x18, 0xF9, 0xC4, 0x31,
+ 0xB0, 0x82, 0xDF, 0x68, 0x86, 0xA2, 0x74, 0xF8, 0x26, 0x83, 0x57, 0xE1, 0x84, 0x8A, 0xEE, 0xEB,
+ 0x99, 0x5D, 0x6A, 0xB3, 0xDA, 0x21, 0x3F, 0x56, 0xAB, 0xCD, 0xBA, 0xA4, 0xDC, 0x4F, 0x7A, 0x86,
+ 0xBA, 0xD1, 0x1A, 0x11, 0x5D, 0x04, 0xED, 0xB1, 0x4F, 0x56, 0x15, 0x98, 0x69, 0xF2, 0xBF, 0x67,
+ 0x6C, 0xFE, 0x78, 0xF3, 0xA9, 0x12, 0x9A, 0x00, 0xB8, 0x15, 0xB5, 0xFB, 0x41, 0x85, 0xAE, 0xF3,
+ 0xBB, 0xAC, 0x62, 0x8F, 0xD1, 0xEC, 0xA8, 0xAE, 0x57, 0x08, 0x37, 0x05, 0x29, 0x54, 0x6D, 0xAA,
+ 0x22, 0xFB, 0xAA, 0xC7, 0xF3, 0x64, 0x14, 0xE6, 0x2C, 0xFE, 0xD0, 0x3A, 0xF5, 0xA8, 0x38, 0xBA,
+ 0xB5, 0xA4, 0xD9, 0x94, 0xD2, 0xC8, 0x11, 0x4D, 0x62, 0xE6, 0x5B, 0x9F, 0x12, 0x33, 0x46, 0xCF,
+ 0xB5, 0x91, 0xE7, 0xAB, 0x44, 0x94, 0xCF, 0x54, 0xCD, 0xD0, 0x66, 0xCA, 0x53, 0x3E, 0xA8, 0x87,
+ 0x7C, 0xAA, 0xF7, 0x4E, 0x94, 0x6B, 0x2B, 0x05, 0x8D, 0x8B, 0x48, 0xCB, 0x9D, 0x05, 0xCC, 0xA6,
+ 0xAC, 0xDC, 0x01, 0xB2, 0x1C, 0x8B, 0x94, 0x8A, 0x2A, 0xF6, 0xCA, 0xA2, 0x08, 0x93, 0x9D, 0xC9,
+ 0x2A, 0x34, 0x76, 0x7B, 0x6A, 0x40, 0xD9, 0x8B, 0xE6, 0x6A, 0x00, 0x46, 0x95, 0xFE, 0xAA, 0x98,
+ 0xBB, 0x34, 0xC7, 0xDA, 0x3D, 0xE9, 0x94, 0x74, 0x69, 0x3A, 0x5E, 0xB0, 0xE5, 0x04, 0x58, 0xFE,
+ 0xFC, 0x97, 0xF2, 0x4E, 0xA5, 0xD4, 0x5D, 0xE8, 0x53, 0xC5, 0xEE, 0x98, 0x92, 0x79, 0xB7, 0xA3,
+ 0x8C, 0xB4, 0x85, 0xB3, 0x94, 0x74, 0x06, 0x8D, 0xAE, 0x5F, 0x9E, 0x69, 0x26, 0x51, 0x87, 0xD1,
+ 0xE4, 0x44, 0x5D, 0x95, 0xA9, 0xD2, 0x42, 0x3D, 0x4C, 0x6C, 0xCB, 0x22, 0x85, 0x73, 0xC1, 0x38,
+ 0xE6, 0xAD, 0x58, 0x3C, 0x20, 0xFD, 0xAA, 0x49, 0xA9, 0x7B, 0x71, 0x8A, 0xC2, 0xC7, 0x1A, 0xBA,
+ 0xF7, 0xED, 0x31, 0x3C, 0xD1, 0xE4, 0xCD, 0xA4, 0x27, 0x4B, 0x91, 0x42, 0x52, 0x95, 0xCE, 0x1D,
+ 0xCD, 0xB5, 0xA2, 0xC8, 0x40, 0x0E, 0xD8, 0x2A, 0x1B, 0xCD, 0x53, 0x54, 0xD1, 0x85, 0x94, 0x36,
+ 0x5F, 0x5B, 0xE2, 0xCB, 0x80, 0xAD, 0xBC, 0xD5, 0x95, 0x3B, 0x5C, 0x6A, 0xA3, 0x16, 0x90, 0xEE,
+ 0x37, 0x57, 0x34, 0x7B, 0xAA, 0x8C, 0x0A, 0x88, 0x8C, 0x52, 0x8C, 0x78, 0xB8, 0x2A, 0xD9, 0x6A,
+ 0x53, 0xE7, 0x38, 0x3F, 0x94, 0x9E, 0x86, 0x3B, 0x3F, 0x8C, 0x1F, 0xDC, 0x3B, 0xC7, 0x47, 0xE2,
+ 0xE4, 0x87, 0xE6, 0x78, 0x3F, 0xA6, 0x63, 0x04, 0xC1, 0x85, 0x8E, 0x8F, 0x76, 0xE9, 0xC9, 0x67,
+ 0xE8, 0xCE, 0x2D, 0xFB, 0x46, 0xB3, 0xAD, 0x0B, 0xDD, 0xF1, 0xC6, 0x5E, 0xEA, 0x1E, 0xBD, 0xCF,
+ 0xB4, 0x0C, 0x79, 0xEC, 0x42, 0x4F, 0xAC, 0x2F, 0xEA, 0x14, 0x2A, 0xBE, 0xA4, 0x0F, 0x1E, 0x7D,
+ 0xF7, 0xE4, 0xF1, 0xE3, 0x93, 0x1F, 0x1E, 0xB9, 0xC3, 0x60, 0xC6, 0xFF, 0xFF, 0x33, 0x5B, 0x8E,
+ 0xFD, 0xE9, 0x63, 0xEF, 0xA4, 0x0F, 0xC3, 0x3D, 0x12, 0x86, 0x60, 0x7A, 0xC1, 0xF9, 0x21, 0x45,
+ 0x9A, 0x22, 0xE4, 0x10, 0x28, 0xC9, 0xA1, 0x8D, 0x97, 0x3B, 0x2A, 0xF2, 0x44, 0x93, 0x00, 0x32,
+ 0xF8, 0xD0, 0xF0, 0x15, 0x4D, 0x68, 0x33, 0x56, 0x4C, 0xD3, 0x50, 0xA2, 0x53, 0x9D, 0x0C, 0xBD,
+ 0x65, 0x9A, 0x03, 0xCA, 0x14, 0x57, 0x18, 0x6F, 0x45, 0xAC, 0x3C, 0x84, 0x00, 0x46, 0xC1, 0x71,
+ 0x71, 0x15, 0xDA, 0x28, 0x1B, 0x25, 0x54, 0x80, 0x8D, 0x97, 0xA6, 0xF3, 0x45, 0xE8, 0x5E, 0x17,
+ 0x4A, 0x71, 0xBD, 0x90, 0x85, 0xCA, 0x9C, 0xAE, 0x12, 0xAC, 0x72, 0x18, 0x69, 0xD9, 0x90, 0x71,
+ 0x01, 0xA2, 0x6D, 0x51, 0xEC, 0xEC, 0x5A, 0x31, 0x26, 0x8A, 0x4D, 0xD2, 0xAB, 0x00, 0xD6, 0x07,
+ 0x9F, 0x2E, 0xDF, 0xFE, 0x5D, 0x7B, 0xF7, 0xFA, 0x4F, 0xA5, 0x86, 0xCA, 0x88, 0xC2, 0x18, 0x5D,
+ 0xA1, 0x67, 0x0A, 0xC6, 0xF4, 0x21, 0x64, 0xA2, 0x73, 0xCD, 0x50, 0x0C, 0x98, 0xED, 0x1D, 0xE2,
+ 0x8E, 0xC3, 0xC9, 0x85, 0xDE, 0xD5, 0xF1, 0x91, 0x16, 0x71, 0xD6, 0xD3, 0x35, 0x8C, 0xDF, 0xF4,
+ 0xE0, 0xC6, 0x70, 0xE6, 0x78, 0xD4, 0xA9, 0xC2, 0x6B, 0xD6, 0xB4, 0x94, 0xCD, 0x78, 0x60, 0x89,
+ 0x64, 0x2C, 0x05, 0xE2, 0xA4, 0x94, 0xF5, 0xC1, 0x35, 0x09, 0xCF, 0x0F, 0xD9, 0xAD, 0x12, 0xAD,
+ 0x15, 0xF7, 0x0D, 0x9E, 0xCC, 0xCC, 0xA1, 0xC8, 0x84, 0x8A, 0x14, 0x3F, 0xF2, 0x8D, 0x29, 0x41,
+ 0xA9, 0x54, 0xD2, 0xBC, 0xAC, 0xF5, 0x08, 0x52, 0x1F, 0x7C, 0x20, 0xB4, 0x20, 0x02, 0x32, 0x2A,
+ 0x29, 0xFE, 0x9C, 0xD7, 0xA8, 0x89, 0xFE, 0x23, 0x7B, 0xE6, 0x6B, 0x52, 0x2D, 0x83, 0x99, 0x79,
+ 0x05, 0xB9, 0x3F, 0x6C, 0xB5, 0xB4, 0xDE, 0xBB, 0xF7, 0x5A, 0xAB, 0x55, 0xA1, 0xB1, 0x37, 0xA3,
+ 0xEE, 0xC4, 0xF5, 0xDF, 0x3D, 0xD2, 0x07, 0xBF, 0x7C, 0x7A, 0xF5, 0xAC, 0x0E, 0x75, 0x61, 0x67,
+ 0xD9, 0xED, 0x75, 0x3A, 0x8D, 0xF3, 0x43, 0xD6, 0x64, 0x7D, 0x5C, 0x3D, 0xD0, 0x2B, 0xC5, 0xD5,
+ 0x3B, 0x05, 0x5C, 0x9D, 0x5E, 0x7F, 0x0B, 0x5C, 0x5D, 0x7D, 0xF0, 0xFA, 0x05, 0xC3, 0xF4, 0xB8,
+ 0xB7, 0x0D, 0x51, 0x60, 0xE0, 0x94, 0x26, 0x20, 0x67, 0xF9, 0xF8, 0xE4, 0x74, 0x73, 0x4C, 0x4F,
+ 0x80, 0xBB, 0x8F, 0x80, 0xE9, 0x14, 0x04, 0x75, 0xB2, 0x8D, 0x9C, 0x4E, 0xF5, 0x01, 0xE2, 0x81,
+ 0x88, 0xBE, 0xEC, 0x9F, 0x6E, 0x81, 0xE7, 0x31, 0x88, 0x08, 0x11, 0x01, 0x92, 0xE5, 0xD1, 0x36,
+ 0x32, 0x3A, 0xD1, 0x07, 0x97, 0x6F, 0x5E, 0xD6, 0xFB, 0xC0, 0x58, 0xEF, 0xC9, 0xC9, 0xE6, 0x78,
+ 0x8E, 0xF5, 0xC1, 0x3F, 0x90, 0x20, 0x20, 0x66, 0xD9, 0xEB, 0x6F, 0x41, 0x50, 0x5F, 0x1F, 0x00,
+ 0x3C, 0xE2, 0xD8, 0x18, 0x05, 0xD8, 0xF5, 0x6B, 0x4A, 0x0C, 0x22, 0xEA, 0x3E, 0xDE, 0x82, 0x2B,
+ 0xB0, 0xEA, 0x7F, 0xA0, 0x78, 0x00, 0xC9, 0xB2, 0xDB, 0xDF, 0xC6, 0xA6, 0x01, 0x11, 0x25, 0x09,
+ 0x7C, 0x0D, 0x5D, 0x6D, 0x73, 0x4C, 0x60, 0xD3, 0x4F, 0x4E, 0x96, 0x4F, 0x4E, 0xAA, 0x21, 0xC0,
+ 0x18, 0x89, 0xF1, 0xA6, 0x28, 0x8A, 0x16, 0x07, 0xD9, 0xA2, 0x00, 0xFA, 0xEF, 0x39, 0x0C, 0x8B,
+ 0xC2, 0xD5, 0xDA, 0xE1, 0x93, 0xC3, 0x81, 0x4C, 0xD8, 0x41, 0xB5, 0xC8, 0x29, 0x51, 0x12, 0x3D,
+ 0xA1, 0xA3, 0x0F, 0xFA, 0x15, 0x32, 0x54, 0xA2, 0x84, 0xA1, 0xB0, 0x09, 0xFA, 0x69, 0xDA, 0x44,
+ 0xCB, 0xC3, 0x84, 0x09, 0x2E, 0x71, 0xA4, 0x4B, 0x11, 0x64, 0xA3, 0xD0, 0xAC, 0xA0, 0xD5, 0x58,
+ 0xEA, 0x83, 0x93, 0xA3, 0xD2, 0x94, 0xB6, 0xB9, 0x32, 0x86, 0x74, 0x00, 0xEE, 0x92, 0x20, 0x58,
+ 0x5B, 0x1F, 0x31, 0xA8, 0x3E, 0x78, 0x1E, 0x1D, 0x6F, 0xA3, 0x95, 0x56, 0x6F, 0x0B, 0xB5, 0x48,
+ 0xE4, 0x30, 0xCD, 0xB4, 0x7A, 0x5C, 0x35, 0x71, 0xF1, 0x72, 0xB7, 0x8A, 0x29, 0xA3, 0x76, 0x1B,
+ 0xBD, 0x60, 0x01, 0xEE, 0x1B, 0x41, 0xB8, 0xB6, 0x56, 0x04, 0x20, 0x44, 0x68, 0x7E, 0xB4, 0x37,
+ 0x8D, 0x44, 0xA4, 0x7C, 0x03, 0xFA, 0x08, 0x8C, 0x70, 0xCE, 0x9E, 0x85, 0x5A, 0x5B, 0x23, 0x31,
+ 0x28, 0xD4, 0x03, 0xD1, 0xF1, 0xDE, 0xB4, 0x22, 0x91, 0xF3, 0x2D, 0xE8, 0x65, 0x46, 0x4C, 0xDB,
+ 0x70, 0x3E, 0x93, 0xD1, 0x08, 0x12, 0xD6, 0xFA, 0xBA, 0x49, 0x80, 0x83, 0x7E, 0xD8, 0xB9, 0x76,
+ 0x45, 0xCF, 0xD7, 0xAE, 0xCD, 0x53, 0xE8, 0x36, 0x2F, 0xD0, 0xD3, 0xD9, 0x9B, 0x4F, 0x52, 0x13,
+ 0x3A, 0x24, 0x62, 0x47, 0xFA, 0xE0, 0x47, 0x2F, 0xA2, 0x73, 0xF3, 0x02, 0xE3, 0x47, 0x32, 0xA6,
+ 0x73, 0xC0, 0xDB, 0x54, 0x3B, 0xAF, 0x7C, 0x63, 0x45, 0x37, 0x19, 0x6E, 0x53, 0x7C, 0x7D, 0x20,
+ 0x96, 0xF6, 0xB3, 0xED, 0x6E, 0xCE, 0x4C, 0x1F, 0x09, 0x21, 0xC4, 0xDD, 0x0E, 0x0B, 0x94, 0xA4,
+ 0xCF, 0xE1, 0x60, 0x3B, 0x24, 0x27, 0x38, 0x5E, 0x9D, 0xD9, 0xC6, 0xD7, 0x50, 0x6E, 0x19, 0x8B,
+ 0xE1, 0xDA, 0x6E, 0x01, 0x30, 0xFA, 0xE0, 0xD9, 0xAF, 0xCF, 0xD7, 0x0E, 0x52, 0x6C, 0x25, 0xB5,
+ 0x8A, 0x85, 0xC7, 0xF3, 0x11, 0xD8, 0x59, 0x66, 0xA2, 0x48, 0xED, 0x39, 0x55, 0x27, 0x8B, 0x14,
+ 0x7C, 0x09, 0x02, 0xE9, 0xC2, 0x93, 0x2E, 0xB1, 0x59, 0x8D, 0xC7, 0xFB, 0x8B, 0x60, 0x40, 0xC4,
+ 0xE7, 0xB1, 0x61, 0xAF, 0x9F, 0x57, 0x04, 0x20, 0xD5, 0x94, 0xF6, 0x0A, 0x8E, 0x76, 0xA5, 0x2E,
+ 0xD6, 0xED, 0xDE, 0x74, 0xC6, 0xB9, 0xDE, 0xB7, 0xE2, 0x80, 0x90, 0xA9, 0x67, 0xAD, 0x3F, 0x0D,
+ 0xC4, 0xE1, 0xF4, 0x01, 0x68, 0xED, 0x1D, 0x1C, 0xAC, 0x9D, 0x65, 0x04, 0x82, 0x7B, 0x4E, 0x2F,
+ 0xCF, 0xE6, 0xA1, 0xB7, 0x4D, 0x66, 0xB9, 0x9E, 0xBB, 0xEE, 0x6A, 0x9B, 0xB4, 0x72, 0xE9, 0x78,
+ 0x73, 0x6B, 0x73, 0x0C, 0x90, 0x53, 0x7E, 0x1A, 0x8D, 0x6C, 0x73, 0xF3, 0xAC, 0x04, 0x19, 0xE5,
+ 0xB5, 0x37, 0xAD, 0x08, 0x7F, 0xCF, 0x51, 0x9C, 0x98, 0xEB, 0x07, 0x08, 0x62, 0x82, 0x16, 0xAF,
+ 0x2E, 0xB5, 0xEB, 0xAB, 0x1F, 0xAF, 0x7F, 0xFA, 0xB0, 0x9B, 0xE8, 0x00, 0x7D, 0xEE, 0x29, 0x30,
+ 0x20, 0xB7, 0xFB, 0x8E, 0x09, 0x40, 0x44, 0x6F, 0x13, 0x3D, 0xF5, 0x98, 0xA2, 0x5E, 0x5C, 0xBF,
+ 0xDF, 0x95, 0x96, 0x7A, 0xFB, 0x53, 0x53, 0xEF, 0x6B, 0xD0, 0xD3, 0x67, 0x87, 0xDC, 0x10, 0x67,
+ 0x03, 0x5D, 0x31, 0x40, 0xD4, 0x97, 0xF6, 0x16, 0x8F, 0xF6, 0x36, 0x90, 0x8B, 0x48, 0xF9, 0x06,
+ 0x86, 0x71, 0x60, 0x15, 0x9F, 0x29, 0xD1, 0x9B, 0x38, 0x0F, 0x83, 0xD4, 0x07, 0x57, 0xCB, 0x99,
+ 0x17, 0xCC, 0xFD, 0x8A, 0x09, 0x55, 0xAD, 0x91, 0xCE, 0x56, 0x0A, 0x11, 0xA4, 0x30, 0x8D, 0x74,
+ 0xB8, 0x42, 0x70, 0x91, 0x44, 0x5A, 0x3F, 0xEB, 0xDF, 0xA9, 0x56, 0x10, 0xF9, 0x7D, 0x2A, 0x66,
+ 0xBC, 0x41, 0xDE, 0x19, 0x63, 0xDE, 0x79, 0x75, 0xB9, 0x9B, 0x50, 0x36, 0xDE, 0x5B, 0xC2, 0x19,
+ 0xEF, 0x35, 0xE1, 0x68, 0x7C, 0x0D, 0x5B, 0x48, 0x61, 0xC3, 0x41, 0x04, 0x07, 0x84, 0xB1, 0xF3,
+ 0x26, 0x03, 0x08, 0xC9, 0x73, 0xBA, 0xCB, 0x6D, 0x5C, 0x47, 0x90, 0x91, 0xF4, 0x9C, 0xA3, 0xD8,
+ 0x6F, 0x8E, 0xEF, 0xD4, 0x6B, 0x8E, 0x4A, 0xA9, 0xDD, 0xC6, 0x69, 0x90, 0x13, 0x93, 0xD8, 0x0E,
+ 0x6E, 0x65, 0x5E, 0x57, 0x21, 0x12, 0x2C, 0xD3, 0x89, 0x76, 0xC9, 0xCE, 0xB6, 0xD1, 0x4D, 0x6F,
+ 0x1B, 0xDD, 0xC8, 0x14, 0x25, 0xD5, 0x73, 0x72, 0x4F, 0x99, 0xA6, 0xDB, 0x3B, 0xBD, 0x4F, 0xF5,
+ 0x0C, 0x67, 0xEB, 0xC7, 0x34, 0x80, 0xD1, 0x07, 0xCF, 0xDF, 0xEF, 0x26, 0xA6, 0x61, 0x67, 0x15,
+ 0x63, 0xDA, 0x56, 0x11, 0x8C, 0x32, 0xB5, 0xEF, 0x52, 0x6C, 0xB1, 0x81, 0x36, 0x16, 0x48, 0xF8,
+ 0xAF, 0x3B, 0xD2, 0xC6, 0xA2, 0xBA, 0x36, 0xEE, 0x38, 0xC3, 0x2C, 0xBE, 0x06, 0xFD, 0xF8, 0xC6,
+ 0xE2, 0xF3, 0x78, 0x6A, 0xAC, 0xAD, 0x23, 0x0E, 0xA7, 0x0F, 0x3E, 0x18, 0x0B, 0xED, 0xD5, 0xBB,
+ 0x67, 0x3B, 0xD1, 0x95, 0xE8, 0x74, 0x3F, 0xFA, 0x8A, 0x58, 0xDE, 0xB7, 0xCE, 0x1C, 0xE2, 0xAE,
+ 0xEF, 0x54, 0x08, 0xA4, 0x0F, 0xDE, 0x12, 0x37, 0xD0, 0x2E, 0x3D, 0x9F, 0xBF, 0x76, 0x6E, 0x27,
+ 0x5A, 0xA3, 0x3D, 0xEF, 0x47, 0x65, 0x8C, 0xE9, 0x7D, 0xEB, 0x6B, 0x32, 0xB5, 0x7D, 0xDF, 0xF3,
+ 0xD7, 0x56, 0x19, 0x87, 0xD3, 0x07, 0xAF, 0x5B, 0xEF, 0xE8, 0xD1, 0x4E, 0xD4, 0x25, 0x7A, 0xDD,
+ 0x8F, 0xC6, 0x22, 0x9E, 0xF7, 0xAD, 0xB4, 0x9B, 0x91, 0x63, 0xCF, 0xD6, 0x56, 0x19, 0x85, 0xD2,
+ 0x07, 0x1F, 0x5B, 0x2F, 0xE1, 0xEF, 0x4E, 0xD4, 0xC5, 0x7A, 0xDC, 0x8F, 0xB2, 0x38, 0xB7, 0xFB,
+ 0x56, 0x95, 0x65, 0x2E, 0xD6, 0x56, 0x14, 0xC0, 0xE8, 0x83, 0x17, 0x97, 0xBF, 0x6A, 0xF5, 0x17,
+ 0xDE, 0xC2, 0xC5, 0x07, 0x2E, 0xB5, 0xAB, 0x1F, 0x1B, 0x3B, 0xD1, 0x18, 0x76, 0xBD, 0x1F, 0x7D,
+ 0x51, 0xA6, 0xF7, 0xAD, 0x2D, 0xBA, 0xAF, 0x66, 0x68, 0xAC, 0x1F, 0x0E, 0x05, 0x20, 0x3E, 0xFB,
+ 0x02, 0x47, 0xDA, 0x73, 0x63, 0x37, 0x01, 0x31, 0xEA, 0x77, 0x17, 0x45, 0x7B, 0xCC, 0xE4, 0xBE,
+ 0xF5, 0xE4, 0x10, 0xAB, 0x82, 0x8A, 0x92, 0x25, 0x86, 0xF5, 0x19, 0xB7, 0xA8, 0xE0, 0xD6, 0xCD,
+ 0x15, 0xD4, 0x1A, 0x57, 0x2F, 0xB4, 0x37, 0xE2, 0xB4, 0x02, 0x37, 0x1B, 0xCF, 0xD9, 0xE5, 0x0D,
+ 0x6D, 0x93, 0xF4, 0x24, 0x07, 0xB7, 0xBD, 0xE3, 0xE3, 0xED, 0x86, 0xB7, 0x79, 0xD3, 0xA8, 0xC7,
+ 0xC7, 0xF7, 0xA8, 0x93, 0x91, 0x61, 0x92, 0xCF, 0x16, 0x09, 0x37, 0x79, 0x18, 0x46, 0x82, 0xD5,
+ 0x07, 0x2F, 0xE1, 0x44, 0x7B, 0x41, 0x4F, 0x76, 0x55, 0x06, 0xCA, 0xFD, 0xEF, 0xC2, 0x93, 0x12,
+ 0xFC, 0xEE, 0xDB, 0x99, 0x28, 0x31, 0x50, 0x74, 0x7B, 0x63, 0x77, 0xA3, 0xBD, 0x05, 0x09, 0x70,
+ 0xAE, 0xBE, 0x0F, 0xEC, 0x7C, 0xB7, 0x0A, 0x8C, 0x89, 0xD8, 0x99, 0x0E, 0x25, 0xBE, 0x77, 0xA1,
+ 0x46, 0x79, 0x83, 0x11, 0x7F, 0x33, 0x67, 0x99, 0xA6, 0xF8, 0x46, 0x17, 0x3A, 0x9D, 0x46, 0xC2,
+ 0x56, 0x10, 0xDA, 0x8E, 0xA3, 0x0F, 0x5E, 0x91, 0x50, 0xBB, 0xC6, 0xC3, 0x8A, 0x3B, 0x5B, 0x24,
+ 0x2C, 0x62, 0x5B, 0x5B, 0xE8, 0x13, 0x63, 0xAA, 0x0F, 0xAE, 0xF1, 0x9D, 0xA5, 0x80, 0x0B, 0xCF,
+ 0xD6, 0x47, 0x46, 0x85, 0x48, 0x5C, 0xDF, 0x03, 0xA2, 0x22, 0x25, 0xF1, 0x77, 0xA1, 0xE9, 0x9A,
+ 0x38, 0x92, 0xAE, 0x0D, 0xAE, 0x68, 0x63, 0x0D, 0xAD, 0xAC, 0xBC, 0xBB, 0xCA, 0x5B, 0x6E, 0xE8,
+ 0x1E, 0x3B, 0xDC, 0x34, 0x97, 0x7C, 0xA3, 0x31, 0x68, 0x95, 0xED, 0xA0, 0x1D, 0x9C, 0x07, 0x33,
+ 0xC3, 0x15, 0xCD, 0xE8, 0xF6, 0xD2, 0x05, 0xDF, 0x2F, 0x38, 0xF4, 0x1C, 0x0B, 0x1A, 0x3E, 0xB3,
+ 0x6E, 0xF0, 0xED, 0x4E, 0x96, 0x76, 0x1D, 0xED, 0x7C, 0x43, 0x10, 0x30, 0x0B, 0x81, 0xA1, 0x44,
+ 0xB7, 0x13, 0x5F, 0xA0, 0x67, 0x7B, 0x14, 0xF1, 0x7D, 0x38, 0x05, 0xCA, 0xCD, 0xD9, 0xAC, 0xE7,
+ 0x93, 0x71, 0x24, 0x48, 0xD5, 0x1E, 0x4E, 0xE5, 0xD6, 0xBD, 0x0F, 0x64, 0x6C, 0x07, 0x40, 0xA3,
+ 0x06, 0x66, 0x71, 0x48, 0xB7, 0x3B, 0x31, 0x53, 0xAE, 0xB6, 0x95, 0x4E, 0xEE, 0x92, 0x6F, 0x04,
+ 0x56, 0x6E, 0x90, 0x5C, 0xAB, 0x62, 0x4C, 0x6F, 0x67, 0x4C, 0x62, 0x2C, 0x33, 0xFA, 0x87, 0xAD,
+ 0xD6, 0xA4, 0x8F, 0x1B, 0xB7, 0x34, 0xC1, 0xDA, 0xF9, 0xE1, 0xA4, 0x5F, 0xB6, 0xE7, 0xA8, 0x74,
+ 0xD7, 0x1D, 0x70, 0xBA, 0xF1, 0xA6, 0x3B, 0x94, 0xD2, 0x00, 0xA8, 0x69, 0x6A, 0xEF, 0x8C, 0xE0,
+ 0x4B, 0x53, 0xFB, 0x88, 0xF9, 0x7D, 0x87, 0x7B, 0xEF, 0x90, 0x76, 0xC3, 0xB2, 0xFC, 0xDC, 0xFD,
+ 0x77, 0xFD, 0xC4, 0xFE, 0xBB, 0x13, 0xB1, 0xFF, 0x4E, 0x9A, 0x69, 0x5F, 0x76, 0xBB, 0xDD, 0x2A,
+ 0x9C, 0x57, 0xDC, 0x82, 0x77, 0x27, 0x2C, 0x4D, 0x41, 0x98, 0x15, 0x59, 0xEA, 0x0B, 0x96, 0xFA,
+ 0x12, 0x4B, 0xA7, 0x77, 0xB9, 0xA9, 0xF0, 0x4E, 0x38, 0xE2, 0xEB, 0xB8, 0x5F, 0x09, 0x4B, 0x95,
+ 0xF6, 0x49, 0x52, 0xDB, 0xBE, 0xAB, 0x6D, 0x92, 0xB4, 0x49, 0x3A, 0x18, 0x1E, 0x17, 0xC6, 0x42,
+ 0x0A, 0xC2, 0x7C, 0xFE, 0xD5, 0x5D, 0xFA, 0xFC, 0x78, 0x0B, 0x9F, 0x1F, 0x67, 0x7C, 0x7E, 0x87,
+ 0xCE, 0x2E, 0x08, 0xFF, 0xC6, 0x1C, 0x5E, 0xB0, 0xB5, 0x86, 0xD3, 0x2B, 0xD9, 0xDA, 0xAD, 0x87,
+ 0x44, 0x96, 0xF0, 0xEA, 0x2E, 0x3D, 0x24, 0xC7, 0x6E, 0x37, 0x32, 0x52, 0x1E, 0x73, 0x06, 0xBB,
+ 0xC9, 0x49, 0xB4, 0x92, 0x92, 0xD5, 0xC9, 0x7B, 0xC7, 0x8D, 0x86, 0x47, 0x7D, 0x5E, 0x36, 0xDD,
+ 0x85, 0x7A, 0xAA, 0xEF, 0xC7, 0xCE, 0x6D, 0x72, 0x37, 0x45, 0x19, 0xBE, 0x11, 0x61, 0x26, 0x55,
+ 0xB8, 0x95, 0x0B, 0xB3, 0xCB, 0xB7, 0x7F, 0x5F, 0xAF, 0x16, 0x4B, 0xF7, 0xB4, 0xBB, 0x7A, 0x6C,
+ 0x33, 0x6B, 0x95, 0x05, 0xC6, 0x69, 0x87, 0x88, 0x83, 0x6F, 0x26, 0xE8, 0x7D, 0x8A, 0x38, 0x57,
+ 0x8C, 0x0D, 0xA5, 0xA0, 0x10, 0x81, 0xE5, 0x0D, 0xFA, 0x68, 0x20, 0xE4, 0x73, 0x96, 0x70, 0x2C,
+ 0xE2, 0x9A, 0xE6, 0x8D, 0x46, 0xF4, 0x73, 0x57, 0x8F, 0x31, 0x60, 0x04, 0x5F, 0xF0, 0x7A, 0xA7,
+ 0x1B, 0x91, 0xA4, 0x1A, 0xF2, 0xC5, 0x14, 0x46, 0xB4, 0x51, 0x13, 0xE3, 0x86, 0x76, 0x67, 0x22,
+ 0x38, 0x62, 0x22, 0x78, 0xF1, 0xE6, 0xA3, 0x4A, 0x06, 0xCC, 0xD7, 0x3A, 0x59, 0x11, 0x1C, 0x6D,
+ 0xFE, 0x6E, 0x85, 0x6E, 0x65, 0x69, 0x75, 0x62, 0x69, 0x1D, 0x8D, 0xE2, 0x2D, 0xA2, 0xDB, 0x84,
+ 0x2C, 0x85, 0x04, 0x8E, 0xD9, 0x43, 0xE0, 0xDA, 0x7B, 0xD9, 0x03, 0x2A, 0xD9, 0xC1, 0xF1, 0x3A,
+ 0x76, 0x60, 0x1D, 0x6D, 0x61, 0x06, 0xC7, 0x39, 0x66, 0x70, 0x57, 0x32, 0xE8, 0xEB, 0x83, 0xF7,
+ 0x9B, 0x98, 0x41, 0xBF, 0xA2, 0x19, 0x1C, 0x09, 0x33, 0x88, 0xF7, 0x0F, 0xF7, 0xAB, 0x0A, 0x4B,
+ 0xB2, 0x82, 0xC7, 0x23, 0x7C, 0x6C, 0xE6, 0x71, 0x35, 0x4F, 0xD8, 0x5D, 0xCC, 0x5D, 0xD8, 0xEE,
+ 0xFA, 0xF1, 0xF6, 0x57, 0xDB, 0xB5, 0xBC, 0xC5, 0x7A, 0x21, 0x57, 0xEE, 0xE8, 0x6B, 0x0F, 0xB7,
+ 0xEB, 0x8D, 0x5A, 0x71, 0x66, 0xA7, 0xB5, 0xC4, 0xCA, 0xDE, 0x0D, 0x3C, 0x5F, 0xCB, 0xBE, 0x39,
+ 0x24, 0xB1, 0x01, 0x51, 0xB4, 0xAE, 0x56, 0x04, 0x64, 0xB7, 0x5C, 0xBC, 0x79, 0xA9, 0x6D, 0xF0,
+ 0x5A, 0x07, 0x05, 0xB2, 0x2E, 0x7B, 0xF9, 0x85, 0xB6, 0xC1, 0xDB, 0x2F, 0x14, 0xD8, 0x72, 0xB6,
+ 0xA8, 0xE0, 0x8B, 0x48, 0xB4, 0xCD, 0xDE, 0x44, 0x52, 0xBA, 0x5B, 0x83, 0xB5, 0xDA, 0x3C, 0xA5,
+ 0x44, 0xE3, 0x32, 0xE6, 0xAD, 0x50, 0x63, 0x55, 0xDB, 0x62, 0x4F, 0x71, 0x4A, 0x06, 0xC0, 0xC1,
+ 0x97, 0x74, 0x37, 0x4B, 0x40, 0xAA, 0x6D, 0x4A, 0x4D, 0x13, 0xB6, 0x46, 0x65, 0xF8, 0xE9, 0x4C,
+ 0x0A, 0x66, 0x51, 0xE7, 0x6B, 0x06, 0xB3, 0xB8, 0xCE, 0x07, 0x63, 0xDA, 0xFB, 0xE0, 0xE5, 0x9F,
+ 0x0A, 0x96, 0x56, 0x9B, 0xB3, 0x74, 0x74, 0x57, 0x2C, 0x6D, 0x91, 0xAA, 0x22, 0xEB, 0x0A, 0xBD,
+ 0xD0, 0x70, 0x36, 0x36, 0x2E, 0x06, 0x0D, 0xB6, 0xC5, 0x62, 0xAE, 0x76, 0x0D, 0xAC, 0xEE, 0xD4,
+ 0xC0, 0x04, 0x01, 0xD5, 0x94, 0xD1, 0xCF, 0x2A, 0xE3, 0xF4, 0x6B, 0xB3, 0x2F, 0xC6, 0x51, 0x55,
+ 0xF3, 0x52, 0x70, 0x74, 0xF2, 0x35, 0x99, 0x97, 0x37, 0x0F, 0xF1, 0xEA, 0xC6, 0xC1, 0x8B, 0x81,
+ 0x63, 0xF0, 0xA2, 0x47, 0xBB, 0x37, 0xB0, 0x88, 0x82, 0x8D, 0xF5, 0x71, 0x74, 0xA7, 0xAF, 0x3C,
+ 0xBB, 0x8B, 0x08, 0xC6, 0x58, 0xDA, 0xC2, 0xC4, 0x7A, 0xFD, 0x1D, 0x9A, 0x98, 0xB4, 0xD0, 0xC4,
+ 0xF3, 0x20, 0x2F, 0x60, 0x74, 0xBE, 0x36, 0x10, 0x17, 0x34, 0xEB, 0xAC, 0x24, 0xA9, 0xB3, 0xF2,
+ 0xF9, 0x21, 0x14, 0x85, 0x59, 0x04, 0x39, 0x74, 0x9E, 0xB3, 0x2F, 0x27, 0xAA, 0x3B, 0x8C, 0xDF,
+ 0x74, 0x48, 0x97, 0xD5, 0xE2, 0x77, 0xEA, 0x46, 0x85, 0x66, 0xFA, 0x5D, 0xBB, 0xA5, 0x6F, 0x15,
+ 0x3C, 0x37, 0xF8, 0x2B, 0x38, 0x6E, 0x08, 0x5F, 0x03, 0xD4, 0x26, 0x3E, 0x19, 0x5D, 0xE8, 0xDF,
+ 0x45, 0x38, 0xB9, 0xB4, 0xB0, 0x89, 0xAE, 0x41, 0x48, 0x76, 0x1D, 0xCF, 0xC0, 0x62, 0xD5, 0x98,
+ 0x85, 0x40, 0x69, 0xFB, 0x8F, 0x19, 0x4E, 0xF2, 0x1A, 0xF8, 0xBE, 0x06, 0xA3, 0xDA, 0x4A, 0x33,
+ 0x7D, 0x3B, 0x2F, 0x7F, 0xB0, 0x06, 0x0F, 0xA3, 0x35, 0xC3, 0xFF, 0xF9, 0xEF, 0xB2, 0xA9, 0x19,
+ 0xFC, 0x7E, 0x66, 0x2C, 0x00, 0x30, 0x23, 0xDF, 0xBC, 0xD0, 0x81, 0x52, 0xDF, 0x0B, 0xA0, 0x14,
+ 0xB5, 0xC7, 0x76, 0x8E, 0xAA, 0xF2, 0xA4, 0x7D, 0xA8, 0x12, 0x77, 0xAA, 0xB1, 0x62, 0x6C, 0x72,
+ 0x1E, 0x98, 0xBE, 0x3D, 0x83, 0x52, 0xCD, 0xF2, 0xCC, 0xF9, 0x94, 0xB8, 0x61, 0xDB, 0xB0, 0xAC,
+ 0xAB, 0x1B, 0x38, 0x78, 0x8B, 0x33, 0xCC, 0x20, 0xF9, 0x7A, 0xED, 0xC5, 0x4F, 0xEF, 0x2E, 0xD9,
+ 0x3B, 0x2B, 0xDF, 0x82, 0xBC, 0x88, 0x55, 0x6B, 0x6A, 0xA3, 0xB9, 0xCB, 0xAA, 0xF7, 0x3A, 0xC1,
+ 0xB6, 0xEC, 0x3B, 0xA6, 0x37, 0x86, 0xAF, 0x0D, 0x8D, 0x80, 0xBC, 0xF6, 0x82, 0x50, 0xBB, 0xD0,
+ 0x22, 0x8C, 0x8E, 0x67, 0xD2, 0x77, 0xA2, 0xB4, 0x19, 0x5F, 0xBC, 0x25, 0x63, 0xFC, 0x17, 0xDF,
+ 0x81, 0xA6, 0x11, 0xD4, 0x81, 0x56, 0x3B, 0x3B, 0xED, 0xD6, 0xD0, 0xFE, 0xA2, 0x2E, 0x46, 0xF8,
+ 0x65, 0x52, 0x68, 0x57, 0x9F, 0xFB, 0x4E, 0x53, 0x33, 0x87, 0x0D, 0xF6, 0x9E, 0x51, 0x7A, 0x19,
+ 0xAF, 0x89, 0x17, 0x50, 0xB7, 0xC3, 0x09, 0x71, 0xEB, 0x31, 0x65, 0xE0, 0x0C, 0x33, 0xCF, 0x0D,
+ 0x12, 0x1F, 0x59, 0xB5, 0x47, 0xF1, 0xF5, 0x36, 0x14, 0xF4, 0xE1, 0x3C, 0xD0, 0x1E, 0x5E, 0x5C,
+ 0x68, 0x58, 0xE0, 0x26, 0xDE, 0x5F, 0x6A, 0x0E, 0xD3, 0xED, 0x9A, 0x5A, 0xEA, 0xC2, 0xCF, 0x10,
+ 0x1A, 0xA4, 0x37, 0x65, 0xDF, 0x6A, 0xC4, 0x49, 0xBD, 0xAA, 0x39, 0x02, 0xC0, 0x28, 0x52, 0x6F,
+ 0x24, 0x09, 0xAC, 0x5B, 0x46, 0x68, 0x34, 0x92, 0xEF, 0x4C, 0x85, 0x5E, 0x81, 0x92, 0xA6, 0x46,
+ 0x6F, 0xC9, 0x2F, 0x70, 0xBD, 0x6D, 0xB4, 0x41, 0x86, 0xC0, 0x6F, 0x04, 0x4D, 0x7C, 0x3F, 0xFD,
+ 0xF5, 0x58, 0x80, 0x6E, 0x75, 0x9B, 0x1A, 0xDE, 0x49, 0xC2, 0x4A, 0x44, 0x3E, 0x10, 0xD7, 0x84,
+ 0xD0, 0x8A, 0xD1, 0x2A, 0x50, 0x32, 0x74, 0xB7, 0x09, 0x15, 0x41, 0xEC, 0xF9, 0x40, 0xC6, 0x20,
+ 0xB1, 0x71, 0x93, 0x0F, 0xA0, 0x9B, 0x74, 0xF4, 0xDC, 0x64, 0x41, 0x51, 0xD2, 0xDA, 0xE1, 0x21,
+ 0xB8, 0x34, 0x04, 0x25, 0x02, 0x56, 0x31, 0xAE, 0xD7, 0xF8, 0x02, 0x26, 0x58, 0x54, 0xAD, 0xB3,
+ 0xAC, 0x1D, 0x00, 0x82, 0x76, 0xE8, 0x5D, 0x87, 0xBE, 0xED, 0x8E, 0x61, 0xE8, 0xD1, 0x88, 0xB1,
+ 0xD1, 0xDB, 0x88, 0x32, 0x75, 0x9F, 0x5E, 0xA7, 0x9D, 0xA4, 0x6F, 0xD4, 0xF9, 0xF5, 0x83, 0x5A,
+ 0xA3, 0xC6, 0x89, 0xA7, 0xE7, 0x60, 0x6E, 0x75, 0x76, 0xF0, 0x88, 0xD2, 0xD8, 0xD0, 0xCE, 0xCF,
+ 0x79, 0x37, 0xAC, 0x15, 0x5E, 0x84, 0x46, 0xF4, 0x4F, 0xEA, 0x56, 0x64, 0x8A, 0xBF, 0x7F, 0xFF,
+ 0x97, 0xB0, 0xD9, 0xDB, 0x43, 0xA0, 0xFA, 0x29, 0xCE, 0x20, 0x7C, 0xFF, 0x17, 0xFC, 0xFF, 0xF6,
+ 0x11, 0x9D, 0x36, 0xF8, 0xFE, 0x2F, 0xFC, 0x73, 0xFB, 0x08, 0x7A, 0x82, 0x63, 0xDA, 0xDF, 0xED,
+ 0xEF, 0x54, 0x0E, 0x59, 0xE9, 0x8D, 0x73, 0xA5, 0x17, 0x89, 0x6D, 0x6D, 0x9A, 0xC6, 0x05, 0x44,
+ 0xFD, 0x1E, 0xFB, 0x6F, 0xDD, 0xF4, 0x2C, 0x50, 0x4F, 0x08, 0x96, 0x2C, 0x94, 0xEE, 0x80, 0x4A,
+ 0x84, 0xA0, 0xA2, 0x97, 0x08, 0xDB, 0x23, 0xDA, 0x52, 0xE3, 0xAE, 0x12, 0x1B, 0x88, 0x68, 0x39,
+ 0x33, 0xFC, 0x80, 0xBC, 0x71, 0xC3, 0x7A, 0x98, 0x70, 0x8A, 0x1C, 0x89, 0x0F, 0x06, 0x09, 0x16,
+ 0xF0, 0x07, 0x70, 0xD0, 0xAE, 0xC6, 0x95, 0x16, 0x19, 0xDB, 0x83, 0xC8, 0x0E, 0x63, 0x4A, 0xD9,
+ 0xCD, 0x1C, 0x3B, 0xFC, 0x64, 0x3A, 0x5F, 0xEA, 0xF8, 0x5A, 0xD3, 0x74, 0xA8, 0xC8, 0x88, 0x08,
+ 0x1B, 0x3D, 0xC5, 0xFF, 0x81, 0x5C, 0xF0, 0x4F, 0xAE, 0x7E, 0x00, 0x2B, 0x2B, 0xE1, 0xEB, 0x74,
+ 0x0A, 0xE0, 0xF3, 0xB2, 0xA9, 0xB1, 0x83, 0x15, 0x78, 0x86, 0x6B, 0xE1, 0x39, 0xFE, 0x59, 0x09,
+ 0xED, 0xE1, 0x05, 0x7E, 0x04, 0xD7, 0x68, 0xCD, 0x8A, 0x97, 0xD8, 0x01, 0xB6, 0xA2, 0x35, 0x06,
+ 0x6D, 0xC5, 0x8E, 0xE0, 0x1A, 0xBE, 0xE2, 0x07, 0x6C, 0xB7, 0xA9, 0x0D, 0x6D, 0xD7, 0xA5, 0x07,
+ 0x25, 0xD4, 0xC7, 0xA9, 0xFE, 0x69, 0xB0, 0x04, 0x0E, 0x38, 0x69, 0xB7, 0x8F, 0x82, 0x55, 0x74,
+ 0xB6, 0xBA, 0x7D, 0x44, 0xF0, 0x1E, 0x25, 0x12, 0x8E, 0x57, 0xFC, 0x18, 0xAE, 0x03, 0x7D, 0x78,
+ 0x47, 0x10, 0x4C, 0x2F, 0xAC, 0xE2, 0x0B, 0xD0, 0x22, 0xC4, 0xFB, 0x9C, 0x78, 0x38, 0x5B, 0x45,
+ 0x67, 0x08, 0x4D, 0x61, 0x39, 0x1B, 0x70, 0xBA, 0x8A, 0x4F, 0xE1, 0x2E, 0x7D, 0x5D, 0x11, 0x12,
+ 0xC1, 0x78, 0xBA, 0x7D, 0xC4, 0x79, 0x82, 0x4B, 0xFC, 0x28, 0x2D, 0x6A, 0x8C, 0x09, 0x21, 0x8F,
+ 0x22, 0xCF, 0x59, 0x92, 0x96, 0xF2, 0x07, 0xF8, 0xC7, 0x95, 0x43, 0xF0, 0xF0, 0xF9, 0xEA, 0x8D,
+ 0x55, 0xAF, 0xF1, 0x05, 0xD9, 0x1A, 0xC6, 0x30, 0x19, 0xA6, 0xED, 0xB9, 0xA6, 0x63, 0x9B, 0xE8,
+ 0x28, 0xF5, 0x86, 0x76, 0x31, 0xE0, 0x71, 0x0C, 0x0D, 0x1A, 0x9A, 0xCB, 0x46, 0x9A, 0x8B, 0x5A,
+ 0x2C, 0x29, 0xD6, 0x1A, 0x6D, 0x6A, 0x87, 0xDC, 0xD6, 0x10, 0x05, 0x77, 0xC1, 0x6A, 0x38, 0xB0,
+ 0xB1, 0x02, 0x47, 0xC6, 0x5B, 0x0A, 0x91, 0xD0, 0xD6, 0x12, 0x16, 0x8A, 0x46, 0x0E, 0xB5, 0x9D,
+ 0x54, 0x94, 0x2D, 0xF0, 0x6A, 0xE1, 0xC0, 0x0F, 0xD3, 0x0E, 0x0C, 0xAA, 0xF2, 0xC3, 0x7A, 0xED,
+ 0x0A, 0x9F, 0xFB, 0xFF, 0xAD, 0x76, 0x80, 0x8D, 0x0E, 0x6A, 0xFF, 0x3A, 0xD3, 0x6A, 0x07, 0xB2,
+ 0x27, 0xDF, 0xA6, 0x5D, 0x8E, 0x69, 0x6C, 0x5C, 0x51, 0x63, 0x63, 0x49, 0x63, 0xE3, 0xBB, 0xD5,
+ 0x98, 0xBC, 0x10, 0xBC, 0x8D, 0xD6, 0xE4, 0x95, 0xD7, 0x02, 0xCD, 0x95, 0xC2, 0x73, 0xA5, 0x71,
+ 0x6D, 0x8D, 0x55, 0xDA, 0xDA, 0x44, 0x4D, 0x2C, 0xC5, 0x81, 0xF7, 0x10, 0xFF, 0xF5, 0xCF, 0xEF,
+ 0xDE, 0x62, 0xA8, 0x54, 0xAB, 0x2C, 0xD2, 0x58, 0xBA, 0x1C, 0x51, 0x60, 0xC0, 0xDC, 0x99, 0x08,
+ 0xDC, 0x89, 0x1C, 0x7A, 0x50, 0xD3, 0xEA, 0x14, 0x25, 0x66, 0xD0, 0x12, 0x43, 0xE0, 0x81, 0xB7,
+ 0x9A, 0xEF, 0x62, 0xB0, 0x15, 0xCE, 0x1B, 0x43, 0x15, 0xD8, 0x02, 0x02, 0x54, 0x52, 0x22, 0xC3,
+ 0x9C, 0x71, 0x18, 0x29, 0x27, 0xEC, 0xDC, 0x45, 0xA8, 0xBF, 0x06, 0x55, 0x83, 0x9A, 0x88, 0xE9,
+ 0x71, 0x6C, 0x0B, 0x4A, 0xA5, 0xC3, 0x23, 0x7F, 0x25, 0x01, 0xF1, 0x39, 0x6C, 0x85, 0x81, 0x8B,
+ 0x4C, 0x50, 0x09, 0x8D, 0x98, 0xBA, 0xCC, 0xC7, 0xB3, 0x5A, 0x07, 0xCF, 0x4A, 0x81, 0x87, 0x67,
+ 0x9E, 0x4A, 0x68, 0xF8, 0x44, 0x57, 0x2E, 0x96, 0x6A, 0xC4, 0xF0, 0xC9, 0x25, 0x15, 0x4F, 0x3C,
+ 0xD3, 0x55, 0xE3, 0x89, 0x4F, 0x8A, 0xE4, 0xE3, 0xA9, 0x28, 0x1B, 0x3E, 0x13, 0xA1, 0xB0, 0xE7,
+ 0x74, 0x35, 0xD2, 0x11, 0xFF, 0x6D, 0x5E, 0x7F, 0x8C, 0x0C, 0x88, 0x16, 0xF1, 0x9F, 0xBD, 0x78,
+ 0xC9, 0xF8, 0xA3, 0xA8, 0x16, 0x89, 0xA3, 0xCC, 0x06, 0xC4, 0x69, 0x1B, 0x21, 0xC4, 0x27, 0x18,
+ 0xC7, 0x93, 0xA0, 0x8D, 0x15, 0x6E, 0x24, 0xC6, 0xCC, 0xAD, 0xB6, 0x0B, 0x04, 0x50, 0x84, 0x8D,
+ 0xB3, 0x4E, 0xDA, 0x3C, 0x33, 0xB8, 0xD8, 0xE5, 0x3C, 0x74, 0xEC, 0x6E, 0x0E, 0x46, 0x9E, 0x61,
+ 0x92, 0x10, 0x78, 0x31, 0x0F, 0x1B, 0x1D, 0xC5, 0x48, 0xB8, 0x7A, 0xC7, 0xC7, 0xD9, 0x3C, 0xC3,
+ 0x3B, 0xE0, 0x5F, 0x4F, 0x43, 0x0C, 0x38, 0x1F, 0x15, 0x0F, 0xCD, 0x4C, 0x28, 0x04, 0xB5, 0x9A,
+ 0x58, 0xB2, 0xAB, 0x9D, 0x65, 0x2A, 0x6E, 0x80, 0xE0, 0x8B, 0x70, 0xDA, 0x53, 0x46, 0x63, 0xE2,
+ 0x9B, 0x20, 0x43, 0x18, 0x7C, 0x47, 0x9F, 0xFE, 0x62, 0xC8, 0xE8, 0x3E, 0x8A, 0x08, 0x13, 0xBB,
+ 0x86, 0x03, 0xD7, 0xD4, 0x25, 0xB6, 0xB6, 0xD3, 0xF2, 0x5C, 0xA2, 0xEE, 0x35, 0x51, 0xBF, 0xF3,
+ 0x8E, 0xF8, 0x19, 0x7F, 0x38, 0x3D, 0x06, 0xF3, 0x49, 0x38, 0xF7, 0x5D, 0x5E, 0xCF, 0x67, 0xEB,
+ 0x1B, 0xE5, 0x50, 0x72, 0x87, 0xB6, 0x79, 0x78, 0xA8, 0x3D, 0x0B, 0x43, 0x03, 0x14, 0x80, 0xEB,
+ 0x94, 0x13, 0x94, 0x8F, 0x66, 0xF0, 0x49, 0x09, 0xCF, 0x47, 0xA3, 0x64, 0x0F, 0x15, 0x13, 0xE6,
+ 0xB7, 0xF8, 0xA5, 0x34, 0xE1, 0xCE, 0x14, 0x55, 0xFB, 0xDF, 0x73, 0xE2, 0xAF, 0xAE, 0xA9, 0xC0,
+ 0x3C, 0xFF, 0x99, 0xE3, 0xD4, 0x6B, 0xED, 0x78, 0xD9, 0xB9, 0xC6, 0xC6, 0xE0, 0x6D, 0x40, 0x75,
+ 0x05, 0x7D, 0x80, 0x8E, 0x63, 0x9B, 0x67, 0xDC, 0x44, 0x7A, 0x87, 0x71, 0xD7, 0x05, 0x57, 0x46,
+ 0x7A, 0xD0, 0x0F, 0x2D, 0x3C, 0xF7, 0x0B, 0x59, 0xCD, 0x67, 0x20, 0xFE, 0x78, 0x18, 0x9F, 0x9A,
+ 0x58, 0xE0, 0xD2, 0x21, 0x6D, 0x68, 0x79, 0xC9, 0x07, 0x72, 0xDD, 0x23, 0x45, 0xA3, 0x58, 0x05,
+ 0xD4, 0x3A, 0xD1, 0x13, 0xB3, 0x1F, 0x92, 0xB9, 0x7D, 0xA0, 0x3E, 0x53, 0x4C, 0x81, 0x70, 0x02,
+ 0xB9, 0xF0, 0x44, 0xF2, 0x4A, 0xF5, 0x90, 0x9A, 0x9E, 0xB8, 0x6D, 0x3C, 0x88, 0x23, 0xC3, 0x7C,
+ 0x66, 0x19, 0x21, 0x49, 0x06, 0x87, 0xC8, 0x16, 0xC4, 0xCD, 0xA9, 0x17, 0x92, 0x54, 0xC4, 0xB0,
+ 0x71, 0x6F, 0x86, 0xE1, 0x7C, 0x8C, 0xAD, 0xF1, 0x5E, 0xDD, 0x5F, 0xE1, 0xE3, 0x6B, 0xF8, 0x7F,
+ 0x66, 0x0E, 0xA2, 0xDA, 0xB8, 0x39, 0x63, 0x21, 0x51, 0x3C, 0x88, 0xAD, 0x44, 0x96, 0x43, 0x22,
+ 0x2C, 0xF0, 0xFB, 0xA2, 0xA7, 0x87, 0x0F, 0xE9, 0xD1, 0x83, 0x48, 0x69, 0x22, 0x7A, 0x5C, 0x68,
+ 0xF1, 0x8D, 0x94, 0x82, 0xB3, 0xB8, 0x53, 0x38, 0x04, 0x72, 0x09, 0x03, 0xF3, 0xAD, 0x48, 0xBD,
+ 0x33, 0xA8, 0x36, 0xD1, 0x16, 0xFE, 0x3F, 0xEA, 0x7F, 0x45, 0x51, 0xFF, 0xFE, 0x42, 0x7C, 0x81,
+ 0x6D, 0xA7, 0x3C, 0x80, 0xC1, 0xA9, 0xA7, 0x05, 0x0F, 0x6A, 0x50, 0xED, 0x28, 0xE7, 0xFD, 0x78,
+ 0xE8, 0x8E, 0xED, 0x6B, 0x62, 0x5B, 0x8C, 0xE8, 0xD8, 0xB2, 0x50, 0x46, 0x38, 0x7D, 0x8F, 0x13,
+ 0xDC, 0x38, 0xDB, 0x5D, 0xAF, 0xB1, 0xB5, 0x05, 0x1A, 0x8F, 0x6F, 0xE3, 0x92, 0x64, 0xE2, 0x2D,
+ 0x8A, 0x20, 0x7D, 0x88, 0x3A, 0x37, 0x24, 0x05, 0x1C, 0x41, 0xF3, 0xED, 0x3C, 0xA5, 0x5D, 0x8B,
+ 0x6D, 0x3F, 0x3C, 0x19, 0x40, 0x03, 0x71, 0x05, 0x40, 0x43, 0x9F, 0x7A, 0x8D, 0x84, 0x96, 0xB8,
+ 0x65, 0x58, 0x05, 0x59, 0x85, 0x88, 0x69, 0x99, 0x97, 0xC4, 0xCC, 0x42, 0xE9, 0x1A, 0x41, 0x56,
+ 0xBE, 0x0C, 0x10, 0xC9, 0xD3, 0x0B, 0xCD, 0x9D, 0x3B, 0x0E, 0xD8, 0x20, 0xB2, 0x00, 0x36, 0x28,
+ 0xDF, 0x55, 0x86, 0xE8, 0xFF, 0xDC, 0x78, 0x16, 0x51, 0x9E, 0x90, 0xC0, 0xA3, 0x47, 0x49, 0x6C,
+ 0xB8, 0xC8, 0xC0, 0xCA, 0xF8, 0xA8, 0x37, 0xD6, 0xFE, 0xD2, 0x73, 0x47, 0xF6, 0x38, 0xCE, 0xB3,
+ 0x9C, 0x24, 0x48, 0xD6, 0x0F, 0x13, 0x82, 0x97, 0x6A, 0x1C, 0x20, 0xC4, 0xB6, 0xA8, 0x80, 0xE8,
+ 0x8B, 0x39, 0x33, 0xB3, 0xB1, 0x4F, 0xA9, 0xD5, 0xD7, 0x09, 0x7F, 0x65, 0x5F, 0x03, 0xE4, 0x8F,
+ 0xC6, 0x1C, 0x5F, 0x10, 0xF5, 0x4E, 0xD4, 0x95, 0x8C, 0x71, 0x9C, 0xC0, 0x88, 0x8C, 0xA5, 0xE8,
+ 0xC6, 0x1F, 0xC5, 0x87, 0x2F, 0xAF, 0xE2, 0x2F, 0xD0, 0x92, 0x3F, 0x02, 0x4A, 0x3B, 0x07, 0x34,
+ 0xF8, 0x82, 0x2D, 0x29, 0xB5, 0x67, 0x6B, 0x03, 0xDA, 0x30, 0x07, 0x09, 0xED, 0x20, 0x8B, 0xA4,
+ 0x90, 0x72, 0xF1, 0xF6, 0x62, 0x85, 0x40, 0x28, 0xBA, 0xC5, 0x10, 0x45, 0x41, 0x7B, 0x85, 0xC3,
+ 0x22, 0x54, 0xA9, 0x9D, 0x8F, 0x0A, 0x84, 0xCC, 0x11, 0xEB, 0x6C, 0x63, 0x1F, 0x1B, 0xA2, 0x23,
+ 0x72, 0xEE, 0x63, 0xC9, 0xEB, 0xB9, 0x3D, 0x69, 0xA9, 0x4D, 0xD2, 0x99, 0x7E, 0x06, 0x5A, 0xAB,
+ 0x2B, 0xA8, 0x87, 0xA6, 0xAF, 0xF0, 0x29, 0x81, 0x88, 0x87, 0xE8, 0x42, 0xB2, 0x7C, 0x15, 0x6E,
+ 0x1D, 0x4D, 0x5F, 0xCB, 0x76, 0xC6, 0x92, 0x6C, 0x9C, 0x61, 0x63, 0x43, 0xBE, 0xA3, 0x9C, 0xD3,
+ 0xD5, 0xE4, 0xEF, 0x0B, 0xCA, 0x99, 0x61, 0xCB, 0x74, 0x53, 0x80, 0x93, 0x2D, 0xEB, 0xA6, 0x91,
+ 0xCE, 0x87, 0x53, 0x3B, 0x54, 0x20, 0xAC, 0x75, 0x6B, 0xEB, 0x64, 0x2E, 0xD9, 0xCB, 0x59, 0xA4,
+ 0xA4, 0x45, 0x3D, 0x20, 0x4A, 0x4C, 0xC7, 0xD3, 0xEF, 0x71, 0x78, 0xCE, 0xD3, 0x1B, 0xC3, 0xC7,
+ 0x49, 0x76, 0x54, 0x70, 0x6A, 0xF1, 0x87, 0xA1, 0x60, 0xAB, 0x96, 0x14, 0x45, 0x72, 0xDD, 0x52,
+ 0xAC, 0x15, 0x26, 0xC7, 0x00, 0xF2, 0x62, 0xD9, 0xEF, 0x3E, 0x01, 0xB8, 0x00, 0x27, 0x35, 0xB4,
+ 0xEF, 0xFF, 0xA2, 0x28, 0x6E, 0xB5, 0x11, 0x44, 0x99, 0x60, 0x42, 0x2C, 0xBA, 0x24, 0x11, 0xE2,
+ 0x27, 0x39, 0x71, 0xC1, 0x27, 0xB1, 0x4E, 0x79, 0xFB, 0x7B, 0x64, 0x21, 0x51, 0x92, 0x2A, 0x1D,
+ 0xA6, 0xD0, 0xE5, 0xEC, 0xE2, 0x11, 0x0A, 0x2B, 0xEC, 0x15, 0x93, 0x52, 0xF8, 0x63, 0x11, 0xC8,
+ 0x69, 0x43, 0x35, 0x04, 0xDD, 0xFC, 0x08, 0x75, 0x4F, 0xCA, 0x4C, 0x1B, 0x7C, 0x80, 0x05, 0x1A,
+ 0xB0, 0x44, 0xA8, 0x64, 0x3A, 0xC2, 0x61, 0x14, 0x13, 0x53, 0x42, 0xC2, 0x8C, 0x19, 0xCE, 0x4B,
+ 0xF9, 0x5A, 0x2F, 0xAF, 0x1F, 0x22, 0x59, 0xFC, 0x11, 0xC0, 0xB0, 0xA8, 0xF1, 0x20, 0x12, 0x43,
+ 0x16, 0x07, 0x76, 0x20, 0x21, 0x48, 0x88, 0x28, 0x4F, 0x4C, 0xC9, 0xED, 0xD6, 0xB5, 0x38, 0x52,
+ 0xE5, 0x8E, 0xEA, 0x34, 0x39, 0xD3, 0xD2, 0x34, 0x4B, 0xFB, 0xFD, 0x8D, 0x9A, 0xCC, 0xBF, 0xF8,
+ 0x0C, 0x8C, 0x14, 0xF1, 0x1A, 0xEB, 0x90, 0x93, 0x19, 0x5C, 0x96, 0x90, 0x72, 0x87, 0x65, 0xB6,
+ 0xF8, 0x41, 0x78, 0xA3, 0xF8, 0xA0, 0x98, 0xCD, 0x0C, 0x2F, 0xE5, 0x5A, 0x30, 0x62, 0x30, 0x71,
+ 0x96, 0x1C, 0xED, 0x49, 0xE2, 0x51, 0xD6, 0x81, 0xB9, 0xE2, 0x62, 0xD6, 0xC5, 0xDC, 0xF5, 0xC6,
+ 0x26, 0x8B, 0xC2, 0x89, 0x57, 0xFA, 0x1C, 0x02, 0x95, 0x57, 0x0C, 0x70, 0x19, 0x3D, 0x77, 0x52,
+ 0x0A, 0x19, 0x3F, 0xA3, 0x22, 0xE1, 0xA0, 0x0F, 0xA0, 0x54, 0x5B, 0x17, 0xA1, 0x4D, 0x13, 0xA0,
+ 0x88, 0xB5, 0x1C, 0x36, 0xB1, 0x4B, 0x5D, 0x82, 0x97, 0x53, 0x4F, 0x11, 0xBC, 0xB4, 0x31, 0x5D,
+ 0x82, 0xA6, 0x7E, 0x5F, 0x0E, 0x2C, 0x3F, 0xED, 0x22, 0xD3, 0x6E, 0xDC, 0x54, 0x00, 0x8E, 0x1F,
+ 0xD1, 0x91, 0x40, 0x45, 0x36, 0x2B, 0x02, 0x8C, 0x5E, 0x8A, 0x52, 0x93, 0xF4, 0x1B, 0x84, 0xDE,
+ 0x8C, 0x6D, 0xCE, 0x4F, 0x85, 0xA1, 0x05, 0x9D, 0x25, 0x6D, 0xE3, 0xFD, 0x3A, 0x2F, 0xAE, 0x64,
+ 0xD9, 0x26, 0x97, 0x42, 0xE4, 0x4D, 0xFE, 0xB5, 0x64, 0x65, 0x4C, 0xA7, 0x59, 0x95, 0x3D, 0xA0,
+ 0xA5, 0xB4, 0x03, 0xDF, 0x64, 0xC9, 0x20, 0x7A, 0xA0, 0x05, 0x63, 0x15, 0x1E, 0xFE, 0xCE, 0xFA,
+ 0xC4, 0xE4, 0x9D, 0xB0, 0xA9, 0x46, 0x29, 0x2D, 0xDE, 0x2C, 0x4D, 0x4A, 0x3C, 0x15, 0xC5, 0xFC,
+ 0x3B, 0xC0, 0x2C, 0xC0, 0x5F, 0x90, 0xF0, 0x40, 0x93, 0xED, 0x2D, 0x27, 0x28, 0xC7, 0x62, 0xE2,
+ 0x51, 0x30, 0x49, 0xBC, 0x94, 0xC9, 0xD8, 0xD3, 0x50, 0x4F, 0x3F, 0x9B, 0x43, 0x48, 0x5E, 0x2F,
+ 0xC0, 0xF9, 0xC0, 0xDB, 0x17, 0xF5, 0xC6, 0x6D, 0x11, 0x3B, 0x4C, 0x5C, 0xB1, 0xED, 0x54, 0x25,
+ 0x82, 0xA6, 0x09, 0x35, 0xB6, 0x84, 0x7C, 0xD4, 0xE8, 0x64, 0x87, 0xB9, 0x72, 0xC5, 0xE0, 0x26,
+ 0x4F, 0xB0, 0x17, 0x59, 0xD1, 0xB2, 0xFA, 0x36, 0x81, 0x20, 0x4E, 0x00, 0x19, 0x62, 0x53, 0x25,
+ 0xAC, 0x64, 0x17, 0xA2, 0x81, 0xA0, 0x5D, 0xF6, 0xC1, 0x1C, 0xDA, 0x93, 0xD5, 0x7F, 0xAA, 0x5C,
+ 0x64, 0x02, 0x88, 0x9C, 0x29, 0x07, 0x05, 0x3E, 0x45, 0x65, 0x1A, 0xEE, 0x8D, 0x11, 0xC8, 0x4E,
+ 0x63, 0x02, 0x41, 0x21, 0xE1, 0x7E, 0x53, 0xD7, 0x59, 0x03, 0x9D, 0x3B, 0x00, 0x3B, 0x6B, 0xD3,
+ 0x6D, 0x27, 0x38, 0x8E, 0x41, 0x1B, 0xA0, 0x27, 0x89, 0xDB, 0xEC, 0x43, 0xD1, 0xE2, 0x3E, 0x3B,
+ 0x63, 0x0D, 0xA2, 0x5E, 0xF0, 0xD3, 0xCC, 0x6D, 0x63, 0x36, 0x23, 0xAE, 0x75, 0x39, 0xB1, 0x1D,
+ 0xAB, 0xCE, 0x40, 0xA3, 0x07, 0x6D, 0x7C, 0x8D, 0x7E, 0xE6, 0x98, 0x3E, 0xD4, 0xC1, 0xB1, 0x82,
+ 0x37, 0x5F, 0xB2, 0x6B, 0xF5, 0x5A, 0xCF, 0x12, 0xCF, 0xE4, 0xF0, 0x66, 0x6D, 0xCB, 0x37, 0x16,
+ 0x6F, 0xF0, 0x99, 0x3F, 0x6A, 0x0E, 0xCD, 0x4E, 0xB3, 0xC3, 0x1B, 0x84, 0x50, 0x6C, 0x09, 0x91,
+ 0x23, 0x5E, 0x7C, 0x36, 0xEA, 0x97, 0x0F, 0x6F, 0x63, 0xBC, 0xA1, 0xF7, 0x82, 0x5D, 0xAA, 0xD7,
+ 0xE8, 0x43, 0x83, 0x87, 0x7F, 0xCC, 0x70, 0xA9, 0x59, 0xA4, 0x19, 0x49, 0x8C, 0xF8, 0x3C, 0x20,
+ 0x8A, 0x8A, 0x35, 0xFF, 0x41, 0x46, 0x0A, 0x97, 0x5D, 0xC8, 0x13, 0x68, 0xEE, 0x75, 0x15, 0xA8,
+ 0x78, 0x5A, 0x10, 0xC1, 0x91, 0x93, 0x97, 0x30, 0xBC, 0xFD, 0x27, 0x31, 0x7C, 0xD0, 0xC7, 0x81,
+ 0x56, 0xD7, 0x3B, 0xFA, 0x41, 0x9D, 0x5E, 0x7F, 0x07, 0xEC, 0x4C, 0xEA, 0x8D, 0x83, 0x6E, 0xA3,
+ 0xD1, 0x0E, 0x40, 0x67, 0xA4, 0xDE, 0xEA, 0x89, 0x26, 0xF0, 0x87, 0xB6, 0x61, 0x9D, 0xE4, 0xDF,
+ 0x7F, 0xED, 0xCD, 0xFD, 0xA0, 0xA8, 0xC1, 0x3B, 0xDB, 0xC5, 0x4C, 0x5C, 0xD4, 0xE4, 0x1A, 0x06,
+ 0x2F, 0xAE, 0x95, 0x69, 0xA2, 0xD3, 0x87, 0x1C, 0xC5, 0x48, 0x93, 0x3E, 0xFB, 0x05, 0x25, 0xBF,
+ 0x54, 0xEC, 0xF3, 0x7A, 0x93, 0xE0, 0x4C, 0x79, 0x5D, 0xAC, 0x5D, 0xDD, 0xCA, 0xC6, 0x11, 0x57,
+ 0x74, 0x7C, 0xAE, 0x21, 0xA3, 0xFF, 0x54, 0xC0, 0xE2, 0x35, 0x52, 0x66, 0x0E, 0xBD, 0x4A, 0x19,
+ 0xAA, 0xAC, 0xAF, 0x0A, 0xEB, 0xD1, 0xE4, 0x44, 0x73, 0x7A, 0x8C, 0x9D, 0xAC, 0x3D, 0x2F, 0xE7,
+ 0xE0, 0xE3, 0x53, 0x11, 0x51, 0xD9, 0x35, 0x1C, 0x70, 0x46, 0xA1, 0x1F, 0x06, 0xA0, 0x45, 0xF9,
+ 0x08, 0x6E, 0x4B, 0x19, 0x8C, 0x8F, 0x56, 0x4B, 0x00, 0xA4, 0x57, 0x89, 0x4B, 0xB0, 0xD2, 0x28,
+ 0xB8, 0xB0, 0x5E, 0x48, 0xBF, 0xFC, 0x9A, 0xA2, 0x00, 0xAC, 0x59, 0xCE, 0x15, 0x51, 0x06, 0xDA,
+ 0x35, 0xA2, 0xA0, 0x87, 0x40, 0x7C, 0xD8, 0x26, 0x85, 0xBC, 0x9C, 0x61, 0x7D, 0x76, 0x48, 0x9F,
+ 0x8A, 0x85, 0x79, 0x43, 0xF9, 0xEC, 0x30, 0xFE, 0x56, 0x32, 0x10, 0xF1, 0x51, 0x81, 0x58, 0x84,
+ 0xA4, 0x58, 0xDE, 0x44, 0x96, 0xB7, 0x98, 0xCE, 0x28, 0x81, 0x90, 0xBF, 0x7D, 0xC0, 0xC4, 0x45,
+ 0x2A, 0x8A, 0x8B, 0x70, 0x71, 0x21, 0x40, 0x3C, 0xC2, 0x2D, 0x9F, 0x5B, 0x89, 0xEC, 0xFF, 0xD7,
+ 0xE7, 0x31, 0x67, 0x8B, 0x61, 0x21, 0x9D, 0x7C, 0xEE, 0x42, 0x62, 0xAF, 0x18, 0x20, 0xF1, 0x81,
+ 0x24, 0xC6, 0xD6, 0x62, 0x58, 0x8D, 0x2D, 0x31, 0xF7, 0x81, 0x00, 0x31, 0x5B, 0xEA, 0x19, 0x12,
+ 0xC1, 0x4A, 0xF4, 0xB2, 0x32, 0xCD, 0x70, 0x2D, 0x2D, 0xFA, 0x4C, 0x76, 0x44, 0x2C, 0x7B, 0xD3,
+ 0x57, 0x69, 0xB9, 0xC9, 0x9A, 0x49, 0x4C, 0x46, 0x73, 0x2C, 0xA5, 0xA0, 0x51, 0x4B, 0x09, 0x3A,
+ 0xA2, 0xA3, 0x10, 0x5A, 0x34, 0x62, 0x45, 0x63, 0x74, 0x5A, 0x49, 0x58, 0x51, 0xEB, 0xD8, 0x71,
+ 0x62, 0x04, 0x62, 0x8E, 0xE6, 0x38, 0x3D, 0xA7, 0xC7, 0x06, 0x2F, 0x8C, 0xD9, 0xD4, 0x10, 0x45,
+ 0x6E, 0x10, 0xB1, 0x94, 0x68, 0x13, 0x39, 0x08, 0x83, 0xCF, 0x23, 0xB3, 0x94, 0x14, 0xB6, 0xE6,
+ 0xA9, 0xBF, 0x77, 0x08, 0xCE, 0x87, 0xF0, 0x7D, 0x8C, 0xB8, 0x07, 0xD1, 0xF3, 0x35, 0xC7, 0x5B,
+ 0x10, 0x5C, 0xBF, 0x14, 0x8F, 0x9B, 0x68, 0x43, 0x02, 0x31, 0x95, 0xB0, 0x59, 0x2D, 0x8C, 0x41,
+ 0xE1, 0xC4, 0x0E, 0x60, 0x10, 0x8E, 0x9F, 0xB3, 0x24, 0x0F, 0xF5, 0x28, 0x21, 0x96, 0xB2, 0x97,
+ 0x9D, 0xED, 0x4F, 0x88, 0x93, 0xC1, 0xC4, 0xB2, 0x7C, 0xC8, 0x79, 0xCC, 0x04, 0xA2, 0xA2, 0x79,
+ 0xB4, 0x35, 0x44, 0x18, 0xDD, 0xFE, 0x6A, 0xA5, 0xA8, 0x66, 0xA0, 0x54, 0x90, 0x11, 0x58, 0x2C,
+ 0xCB, 0x98, 0xD7, 0x8C, 0x34, 0x55, 0x93, 0x95, 0x05, 0x1A, 0xC5, 0x39, 0x7B, 0x65, 0x94, 0xCF,
+ 0xD7, 0x0A, 0x93, 0x38, 0x4B, 0xAC, 0xEC, 0x77, 0x7E, 0x28, 0x76, 0x16, 0xB0, 0x33, 0x2C, 0x18,
+ 0x07, 0x0F, 0xCE, 0x0F, 0x27, 0xE1, 0xD4, 0x19, 0x3C, 0xF8, 0x5F, 0x94, 0x18, 0xA6, 0xBF, 0xBA,
+ 0xAB, 0x00, 0x00
+};
+
+
+//File: index_ov3660.html.gz, Size: 8887
+#define index_ov3660_html_gz_len 8887
+const uint8_t index_ov3660_html_gz[] = {
+ 0x1F, 0x8B, 0x08, 0x08, 0xA3, 0xFA, 0x69, 0x5E, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F,
+ 0x6F, 0x76, 0x33, 0x36, 0x36, 0x30, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x00, 0xED, 0x3D, 0x69, 0x73,
+ 0xDB, 0x46, 0xB2, 0xDF, 0xFD, 0x2B, 0x60, 0x24, 0x6B, 0x51, 0x65, 0x91, 0xE2, 0xAD, 0x23, 0x12,
+ 0xFD, 0x6C, 0x59, 0xB1, 0x53, 0x1B, 0x67, 0xBD, 0x71, 0xE2, 0x24, 0xB5, 0xB5, 0xE5, 0x80, 0xC4,
+ 0x90, 0x44, 0x0C, 0x02, 0x5C, 0x00, 0xD4, 0x91, 0x94, 0x7E, 0xC7, 0xFB, 0x41, 0xEF, 0x8F, 0xBD,
+ 0xEE, 0x39, 0x70, 0x71, 0x00, 0x0C, 0x00, 0x11, 0x52, 0xF2, 0x1E, 0x5D, 0x65, 0xE1, 0x98, 0xEE,
+ 0xE9, 0x7B, 0x7A, 0x7A, 0x06, 0xC0, 0xD9, 0x53, 0xD3, 0x9D, 0x05, 0xB7, 0x6B, 0xA2, 0x2D, 0x83,
+ 0x95, 0x3D, 0x79, 0x72, 0xC6, 0xFE, 0x68, 0xF0, 0x3B, 0x5B, 0x12, 0xC3, 0x64, 0x87, 0xF4, 0x74,
+ 0x45, 0x02, 0x43, 0x9B, 0x2D, 0x0D, 0xCF, 0x27, 0xC1, 0xB9, 0xBE, 0x09, 0xE6, 0xED, 0x63, 0x3D,
+ 0x7D, 0xDB, 0x31, 0x56, 0xE4, 0x5C, 0xBF, 0xB2, 0xC8, 0xF5, 0xDA, 0xF5, 0x02, 0x5D, 0x9B, 0xB9,
+ 0x4E, 0x40, 0x1C, 0x68, 0x7E, 0x6D, 0x99, 0xC1, 0xF2, 0xDC, 0x24, 0x57, 0xD6, 0x8C, 0xB4, 0xE9,
+ 0xC9, 0x81, 0xE5, 0x58, 0x81, 0x65, 0xD8, 0x6D, 0x7F, 0x66, 0xD8, 0xE4, 0xBC, 0x17, 0xC7, 0x15,
+ 0x58, 0x81, 0x4D, 0x26, 0x97, 0x1F, 0xDE, 0x0F, 0xFA, 0xDA, 0x3F, 0x3E, 0x0E, 0xC6, 0xE3, 0xEE,
+ 0xD9, 0x21, 0xBB, 0x16, 0xB5, 0xF1, 0x83, 0xDB, 0xF8, 0x39, 0xFE, 0xA6, 0xAE, 0x79, 0xAB, 0xFD,
+ 0x91, 0xB8, 0x84, 0xBF, 0x39, 0x10, 0xD1, 0x9E, 0x1B, 0x2B, 0xCB, 0xBE, 0x3D, 0xD5, 0x5E, 0x7A,
+ 0xD0, 0xE7, 0xC1, 0x5B, 0x62, 0x5F, 0x91, 0xC0, 0x9A, 0x19, 0x07, 0xBE, 0xE1, 0xF8, 0x6D, 0x9F,
+ 0x78, 0xD6, 0xFC, 0xAB, 0x2D, 0xC0, 0xA9, 0x31, 0xFB, 0xBC, 0xF0, 0xDC, 0x8D, 0x63, 0x9E, 0x6A,
+ 0x5F, 0xF4, 0x8E, 0xF1, 0xDF, 0x76, 0xA3, 0x99, 0x6B, 0xBB, 0x1E, 0xDC, 0xBF, 0xFC, 0x1A, 0xFF,
+ 0x6D, 0xDF, 0xA7, 0xBD, 0xFB, 0xD6, 0xEF, 0xE4, 0x54, 0xEB, 0x8D, 0xD7, 0x37, 0x89, 0xFB, 0x77,
+ 0x4F, 0x12, 0xA7, 0xCB, 0x7E, 0x16, 0xF5, 0x1C, 0xFE, 0x38, 0x1F, 0xDE, 0x27, 0xB3, 0xC0, 0x72,
+ 0x9D, 0xCE, 0xCA, 0xB0, 0x1C, 0x09, 0x26, 0xD3, 0xF2, 0xD7, 0xB6, 0x01, 0x32, 0x98, 0xDB, 0x24,
+ 0x17, 0xCF, 0x17, 0x2B, 0xE2, 0x6C, 0x0E, 0x0A, 0xB0, 0x21, 0x92, 0xB6, 0x69, 0x79, 0xAC, 0xD5,
+ 0x29, 0xCA, 0x61, 0xB3, 0x72, 0x0A, 0xD1, 0xE6, 0xD1, 0xE5, 0xB8, 0x0E, 0x91, 0x08, 0x10, 0x3B,
+ 0xBA, 0xF6, 0x8C, 0x35, 0x36, 0xC0, 0xBF, 0xDB, 0x4D, 0x56, 0x96, 0xC3, 0x8C, 0xEA, 0x54, 0x1B,
+ 0x0C, 0xBB, 0xEB, 0x9B, 0x02, 0x55, 0x0E, 0xC6, 0xF8, 0x6F, 0xBB, 0xD1, 0xDA, 0x30, 0x4D, 0xCB,
+ 0x59, 0x9C, 0x6A, 0xC7, 0x52, 0x14, 0xAE, 0x67, 0x12, 0xAF, 0xED, 0x19, 0xA6, 0xB5, 0xF1, 0x4F,
+ 0xB5, 0xA1, 0xAC, 0xCD, 0xCA, 0xF0, 0x16, 0x40, 0x4B, 0xE0, 0x02, 0xB1, 0xED, 0x9E, 0x94, 0x12,
+ 0xDE, 0xC4, 0xB3, 0x16, 0xCB, 0x00, 0x54, 0xBA, 0xD5, 0x26, 0x2D, 0x34, 0xEE, 0x42, 0x45, 0xFA,
+ 0xCC, 0x95, 0x9B, 0x5C, 0x6A, 0x86, 0x6D, 0x2D, 0x9C, 0xB6, 0x15, 0x90, 0x15, 0xB0, 0xE3, 0x07,
+ 0x1E, 0x09, 0x66, 0xCB, 0x3C, 0x52, 0xE6, 0xD6, 0x62, 0xE3, 0x11, 0x09, 0x21, 0xA1, 0xDC, 0x72,
+ 0x18, 0x86, 0x9B, 0xDB, 0xB7, 0xDA, 0xD7, 0x64, 0xFA, 0xD9, 0x0A, 0xDA, 0x5C, 0x26, 0x53, 0x32,
+ 0x77, 0x3D, 0x22, 0x6D, 0x29, 0x5A, 0xD8, 0xEE, 0xEC, 0x73, 0xDB, 0x0F, 0x0C, 0x2F, 0x50, 0x41,
+ 0x68, 0xCC, 0x03, 0xE2, 0x15, 0xE3, 0x23, 0x68, 0x15, 0xC5, 0xD8, 0xB2, 0xBB, 0xE5, 0x0D, 0x2C,
+ 0xC7, 0xB6, 0x1C, 0xA2, 0x4E, 0x5E, 0x56, 0xBF, 0x49, 0x74, 0xAC, 0x95, 0x82, 0x62, 0xAC, 0xD5,
+ 0x22, 0xCF, 0x4A, 0x28, 0xAF, 0xDB, 0x9D, 0x71, 0xBF, 0xE9, 0x75, 0xBB, 0x7F, 0xDB, 0xBE, 0xB9,
+ 0x24, 0xCC, 0x4C, 0x8D, 0x4D, 0xE0, 0xD6, 0xF7, 0x88, 0x2D, 0xB7, 0x4A, 0xF1, 0xF1, 0x5F, 0x2B,
+ 0x62, 0x5A, 0x86, 0xD6, 0x8A, 0xB9, 0xF3, 0x71, 0x17, 0x6C, 0x6A, 0x5F, 0x33, 0x1C, 0x53, 0x6B,
+ 0xB9, 0x9E, 0x05, 0x8E, 0x60, 0xD0, 0x70, 0x63, 0xC3, 0x15, 0x18, 0x38, 0xD6, 0x64, 0x5F, 0xC2,
+ 0x72, 0x8E, 0xCF, 0xC4, 0x25, 0x22, 0x77, 0x1B, 0xFC, 0x29, 0x84, 0x1C, 0xFC, 0x15, 0x3A, 0x90,
+ 0x84, 0x47, 0x8A, 0x3E, 0x4F, 0x5F, 0x71, 0x0A, 0xB3, 0x74, 0x86, 0xBF, 0x95, 0x71, 0xD3, 0xCE,
+ 0xD5, 0x9D, 0x68, 0x24, 0x74, 0x08, 0xC3, 0xEC, 0xAC, 0x05, 0x4D, 0xAF, 0x96, 0x5A, 0x5B, 0xC3,
+ 0x28, 0xB9, 0x2F, 0x87, 0xE1, 0x48, 0xE5, 0x2A, 0xC7, 0x5F, 0xDC, 0x28, 0x4A, 0xB0, 0x2B, 0x67,
+ 0x35, 0x8A, 0x1D, 0xEC, 0x9F, 0xCC, 0x86, 0x18, 0x27, 0x99, 0x51, 0x04, 0x7F, 0xEA, 0x91, 0x24,
+ 0x42, 0x56, 0x18, 0x4D, 0x24, 0x88, 0xB3, 0x23, 0xCA, 0x16, 0xDE, 0x2C, 0xEF, 0x96, 0x60, 0xCD,
+ 0x27, 0x41, 0x35, 0xBA, 0x48, 0x10, 0xE7, 0xD1, 0x50, 0x18, 0x65, 0xF0, 0x77, 0xA7, 0x90, 0x6F,
+ 0x7C, 0x31, 0xDD, 0x04, 0x81, 0xEB, 0xF8, 0xB5, 0x86, 0xA8, 0x2C, 0x3F, 0xFB, 0x6D, 0xE3, 0x07,
+ 0xD6, 0xFC, 0xB6, 0xCD, 0x5D, 0x1A, 0xFC, 0x6C, 0x6D, 0x40, 0x0A, 0x39, 0x25, 0xC1, 0x35, 0x21,
+ 0xF9, 0xE9, 0x86, 0x63, 0x5C, 0x41, 0xDC, 0x59, 0x2C, 0x6C, 0x99, 0xED, 0xCD, 0x36, 0x9E, 0x8F,
+ 0x79, 0xDB, 0xDA, 0xB5, 0x00, 0xB1, 0xB7, 0xDD, 0x71, 0xD2, 0x07, 0x15, 0x3B, 0x6A, 0xCF, 0xA6,
+ 0x92, 0xBE, 0xDC, 0x4D, 0x80, 0x32, 0x96, 0x6A, 0xC2, 0x05, 0x76, 0xAC, 0xE0, 0x56, 0x7A, 0x8F,
+ 0x7B, 0xA2, 0xE4, 0x8E, 0x70, 0xC1, 0xDC, 0x61, 0x21, 0x49, 0xD7, 0xE9, 0x6C, 0x49, 0x66, 0x9F,
+ 0x89, 0xF9, 0xBC, 0x30, 0x0D, 0x2B, 0x4A, 0x0F, 0x3B, 0x96, 0xB3, 0xDE, 0x04, 0x6D, 0x4C, 0xA7,
+ 0xD6, 0x3B, 0xD1, 0x39, 0x35, 0x48, 0xC1, 0x62, 0xBF, 0x9F, 0x97, 0x54, 0x8C, 0xD6, 0x37, 0xF9,
+ 0x42, 0x88, 0x13, 0x3B, 0xB1, 0x8D, 0x29, 0xB1, 0xF3, 0x48, 0xE6, 0xCE, 0x90, 0x11, 0x76, 0x79,
+ 0xAC, 0xCA, 0xCE, 0xDD, 0x28, 0x65, 0xD1, 0xE0, 0x35, 0x3C, 0xFA, 0x9B, 0xB2, 0x1C, 0xE9, 0xF1,
+ 0x41, 0xE2, 0x92, 0x4F, 0x6C, 0x70, 0xB0, 0xAC, 0xD4, 0x1B, 0xDA, 0x5C, 0x03, 0x0D, 0xB9, 0x1D,
+ 0x78, 0x86, 0xB3, 0x20, 0x10, 0x0B, 0x6E, 0x0E, 0xC4, 0x61, 0xFE, 0xC4, 0x40, 0x89, 0x7D, 0x0C,
+ 0xD5, 0xA3, 0xFC, 0x89, 0x08, 0x0B, 0x08, 0x07, 0x5A, 0x87, 0x1D, 0x54, 0xC8, 0x4A, 0x62, 0xFA,
+ 0xCD, 0x25, 0xA4, 0x27, 0xB5, 0x0E, 0x96, 0x98, 0x48, 0x3D, 0x27, 0x69, 0x5B, 0xD2, 0x44, 0xBF,
+ 0x30, 0x34, 0x88, 0x29, 0xDF, 0x7C, 0x5E, 0x34, 0x69, 0x9C, 0xCF, 0x07, 0xDD, 0xC1, 0xB0, 0x30,
+ 0x73, 0x92, 0x72, 0x99, 0x9A, 0x38, 0x4A, 0x42, 0x47, 0x18, 0x56, 0x72, 0x8D, 0xC0, 0x37, 0xAE,
+ 0xA4, 0x49, 0xBB, 0xEB, 0x5B, 0x6C, 0xE6, 0x66, 0x4C, 0x7D, 0x98, 0xBB, 0x05, 0x92, 0xA9, 0x17,
+ 0x37, 0xF4, 0xBE, 0x94, 0x3E, 0x9A, 0xD2, 0x49, 0x5D, 0x40, 0x88, 0x57, 0x4E, 0x76, 0x42, 0x03,
+ 0xF2, 0x26, 0x31, 0x05, 0x4B, 0x93, 0xCA, 0x80, 0xDC, 0x04, 0x6D, 0x93, 0xCC, 0x5C, 0x8F, 0x65,
+ 0x83, 0x19, 0x33, 0xC7, 0x94, 0x22, 0x8B, 0x2D, 0xF6, 0x74, 0xE9, 0x5E, 0x11, 0x4F, 0x22, 0xAC,
+ 0x94, 0x52, 0x87, 0x27, 0x43, 0x53, 0x01, 0x9B, 0x01, 0xC3, 0xA3, 0x54, 0xF6, 0x49, 0x74, 0xFD,
+ 0xDE, 0xAC, 0x9F, 0xEB, 0xC7, 0x0C, 0x5D, 0x07, 0x7C, 0xC6, 0x98, 0xDA, 0xC4, 0xCC, 0x19, 0xCD,
+ 0x4C, 0x32, 0x37, 0x36, 0x76, 0x50, 0x60, 0x95, 0x46, 0x17, 0xFF, 0xE5, 0xF5, 0x48, 0xC3, 0xD0,
+ 0xBF, 0xB0, 0x2E, 0x74, 0x4E, 0x03, 0xC7, 0xBF, 0x25, 0x7D, 0x8A, 0x54, 0xC3, 0x58, 0xAF, 0x89,
+ 0x01, 0xAD, 0x66, 0x24, 0x4B, 0x0F, 0x4A, 0x53, 0x0C, 0x79, 0x9C, 0x57, 0x9A, 0xB7, 0x17, 0x3A,
+ 0x6C, 0x98, 0x3C, 0x96, 0xE2, 0xF9, 0x74, 0xEE, 0xCE, 0x36, 0xB2, 0xAC, 0x46, 0xCD, 0xF1, 0xB6,
+ 0xF1, 0x9D, 0x0A, 0x91, 0xF9, 0xB6, 0x45, 0xDD, 0x7F, 0xE3, 0x38, 0xA8, 0xD1, 0x76, 0xE0, 0x01,
+ 0x9B, 0x92, 0x8E, 0xD4, 0x04, 0x57, 0x29, 0x86, 0x25, 0x04, 0x9B, 0x55, 0xBB, 0x4A, 0x85, 0x29,
+ 0x49, 0x38, 0x0D, 0x23, 0xAD, 0x06, 0x31, 0xC4, 0x32, 0x05, 0xAA, 0x7A, 0x72, 0x09, 0x96, 0x9B,
+ 0x95, 0x2C, 0x8F, 0x12, 0x9D, 0xF5, 0x60, 0xD0, 0x67, 0xDD, 0x79, 0x8B, 0xA9, 0xD1, 0xEA, 0x1E,
+ 0x74, 0x0F, 0x06, 0xF0, 0x9F, 0x64, 0x3E, 0x93, 0x6F, 0x5C, 0x5C, 0xBC, 0x19, 0x96, 0x97, 0x0A,
+ 0xD1, 0xC5, 0x65, 0xA5, 0xAC, 0x60, 0x5F, 0xA8, 0x0B, 0x75, 0x4F, 0x4A, 0xD6, 0x97, 0x7A, 0x9D,
+ 0x82, 0x71, 0x38, 0xC3, 0xA4, 0xCB, 0x1B, 0xA2, 0xC4, 0x5A, 0xCA, 0xAA, 0x78, 0xE5, 0xFE, 0xDE,
+ 0x66, 0x49, 0xC8, 0xFF, 0x79, 0x6B, 0x8F, 0x89, 0xE2, 0x2F, 0x6D, 0xE9, 0xA5, 0xE5, 0xE2, 0x3F,
+ 0xB4, 0x6D, 0x74, 0xB3, 0xB5, 0xDE, 0xE6, 0x59, 0x1F, 0x50, 0xE8, 0xC0, 0x1C, 0xD4, 0x83, 0xC9,
+ 0x68, 0x66, 0x66, 0x18, 0x6B, 0x53, 0x41, 0x06, 0x73, 0xCB, 0xB6, 0xDB, 0xB6, 0x7B, 0x5D, 0x9C,
+ 0x89, 0xE4, 0x5B, 0xF2, 0x96, 0x9D, 0x16, 0x9B, 0x7C, 0x55, 0x6A, 0x37, 0x10, 0xB9, 0xFE, 0x14,
+ 0xD4, 0xFE, 0xB5, 0x1D, 0x2E, 0xD7, 0x35, 0xAA, 0x0D, 0x14, 0x15, 0xEC, 0xB1, 0x5E, 0x47, 0x4A,
+ 0xA6, 0xC4, 0x32, 0xC1, 0xFC, 0x69, 0xCF, 0xB5, 0x15, 0xCC, 0x96, 0x15, 0xA6, 0x9E, 0xD1, 0xC4,
+ 0xC8, 0x23, 0xB6, 0x81, 0x19, 0x7C, 0xA5, 0x0A, 0x45, 0xE1, 0xF4, 0x2D, 0x0E, 0xAE, 0xC2, 0x09,
+ 0x15, 0xDD, 0xE3, 0xA9, 0x2E, 0x75, 0x58, 0xEE, 0x90, 0x1D, 0xAB, 0xE5, 0x66, 0x5D, 0x90, 0xEE,
+ 0x27, 0x3D, 0x43, 0xDE, 0xA8, 0x44, 0x44, 0x17, 0x41, 0x7B, 0xE1, 0x91, 0x5B, 0x05, 0x66, 0x0E,
+ 0xF8, 0xDF, 0x53, 0x56, 0x3F, 0xAE, 0x5E, 0x2A, 0xA1, 0x03, 0x00, 0xB7, 0xA2, 0xCE, 0xD0, 0x57,
+ 0xE8, 0x3A, 0xBB, 0x4B, 0x15, 0x7B, 0x0C, 0xAB, 0xA3, 0xBA, 0xAE, 0x10, 0x6E, 0x72, 0x86, 0x50,
+ 0xB9, 0xA9, 0x8A, 0xD1, 0x57, 0x3E, 0x9F, 0x27, 0xF3, 0x20, 0x63, 0xF1, 0x87, 0xE6, 0xA9, 0x83,
+ 0xFC, 0xE8, 0xD6, 0x8E, 0x55, 0x53, 0x0A, 0x23, 0x47, 0x58, 0xC4, 0xCC, 0xB6, 0x3E, 0x29, 0x66,
+ 0x8C, 0x9E, 0xA5, 0x91, 0x67, 0xAB, 0x44, 0xA4, 0xCF, 0x54, 0xCD, 0xD0, 0x66, 0xC5, 0x87, 0x7C,
+ 0x50, 0x0F, 0xF9, 0xB9, 0xD5, 0x1F, 0x4B, 0xD7, 0x56, 0x72, 0x1A, 0xE7, 0x91, 0x96, 0x59, 0x05,
+ 0xDC, 0x1E, 0xB2, 0x32, 0x27, 0xC8, 0xF1, 0x58, 0x24, 0x55, 0x54, 0xBE, 0x57, 0xE6, 0x45, 0x98,
+ 0xED, 0x4A, 0x56, 0xAE, 0xB1, 0x5B, 0x2B, 0x03, 0xD2, 0x5E, 0x34, 0x57, 0x03, 0x30, 0xCA, 0xF4,
+ 0xA7, 0x62, 0xEE, 0xB1, 0x1A, 0x6B, 0x6F, 0xDC, 0x2D, 0xE8, 0x72, 0x66, 0xBB, 0x7E, 0xCD, 0x02,
+ 0x58, 0x76, 0xFD, 0x4B, 0x7A, 0x47, 0x69, 0xE8, 0xCE, 0xF5, 0xA9, 0x7C, 0x77, 0x4C, 0xC9, 0xBC,
+ 0xD7, 0x95, 0x46, 0xDA, 0xDC, 0x2A, 0x25, 0xAD, 0xA0, 0xD1, 0xF5, 0xCB, 0x53, 0x6D, 0x46, 0xE4,
+ 0x61, 0x34, 0x59, 0xA8, 0x53, 0x29, 0x95, 0xE6, 0xEA, 0x61, 0x69, 0x99, 0x26, 0xC9, 0xAD, 0x05,
+ 0xE3, 0x9C, 0x57, 0x31, 0x79, 0x40, 0xFA, 0x65, 0x45, 0xA9, 0x9D, 0x38, 0x45, 0xEE, 0xB6, 0x86,
+ 0xDE, 0xAE, 0x3D, 0x86, 0x0F, 0x34, 0x59, 0x95, 0xF4, 0x64, 0x2A, 0x92, 0x4B, 0xAA, 0xD4, 0xB9,
+ 0xC3, 0x5A, 0x2B, 0x8A, 0x0C, 0xE4, 0x80, 0xAD, 0xB6, 0xA3, 0x79, 0x8A, 0x2A, 0xBA, 0x90, 0xD2,
+ 0xE1, 0x6B, 0x4B, 0x7C, 0x19, 0xB0, 0x9D, 0xB5, 0xBA, 0x72, 0x8F, 0x4B, 0x6D, 0xD4, 0x02, 0xD2,
+ 0xFD, 0x66, 0x8A, 0xE6, 0x81, 0x32, 0xA3, 0x1C, 0x22, 0xC3, 0x21, 0x46, 0x6C, 0xAE, 0x4A, 0xB6,
+ 0x2A, 0xEB, 0x1C, 0xE1, 0xF9, 0xD9, 0x61, 0x6C, 0x3B, 0xDC, 0xD9, 0x61, 0xB4, 0x73, 0xEF, 0x0C,
+ 0xF7, 0xC4, 0xC5, 0x77, 0xCD, 0xF1, 0x8E, 0x66, 0xB6, 0xE1, 0xFB, 0xE7, 0x3A, 0xEE, 0xED, 0xD2,
+ 0x93, 0x9B, 0xE8, 0xCE, 0x4C, 0xEB, 0x4A, 0xB3, 0xCC, 0x73, 0xDD, 0x76, 0x17, 0x6E, 0xEA, 0x1E,
+ 0xBD, 0xCF, 0xD4, 0x0C, 0x03, 0xD9, 0xB9, 0x9E, 0x58, 0x60, 0xD4, 0x29, 0x54, 0x74, 0x49, 0x9F,
+ 0x3C, 0xFB, 0xE2, 0xE4, 0xE8, 0x68, 0xFC, 0xD5, 0x33, 0x67, 0xEA, 0xAF, 0xF9, 0xFF, 0x3F, 0xB0,
+ 0xF5, 0x58, 0xB6, 0xA9, 0x0F, 0xC6, 0xB6, 0x20, 0x00, 0xDB, 0xF3, 0xCF, 0x0E, 0x29, 0xD2, 0x14,
+ 0x21, 0x87, 0x40, 0x49, 0x06, 0x6D, 0x3C, 0xDF, 0x91, 0x91, 0x27, 0x9A, 0xF8, 0x30, 0x84, 0x4F,
+ 0x0D, 0x4F, 0xD2, 0x84, 0x36, 0x63, 0xD9, 0x34, 0x8D, 0x25, 0x3A, 0x55, 0xCA, 0xD4, 0xBD, 0x49,
+ 0x73, 0x40, 0x99, 0xE2, 0x1A, 0xE3, 0xAD, 0x88, 0x99, 0x85, 0x10, 0xC0, 0x28, 0x38, 0xAE, 0xAE,
+ 0x42, 0x1B, 0x69, 0xA3, 0x84, 0x0A, 0xB0, 0xF1, 0xCD, 0xCC, 0xFE, 0x2C, 0x94, 0xAF, 0x0B, 0xA5,
+ 0x38, 0x6E, 0xC0, 0x62, 0x65, 0x46, 0x57, 0x09, 0x56, 0x39, 0x4C, 0x6C, 0xDD, 0x90, 0x71, 0x01,
+ 0xA2, 0x6D, 0x53, 0xEC, 0xEC, 0x5A, 0x3E, 0x26, 0x8A, 0x2D, 0xA6, 0x57, 0x01, 0xAC, 0x4F, 0x7E,
+ 0xBE, 0xF8, 0xF6, 0xEF, 0xDA, 0xBB, 0xB7, 0xBF, 0x4B, 0x35, 0x54, 0x44, 0x14, 0x06, 0x69, 0x85,
+ 0x9E, 0x29, 0x18, 0xD3, 0x87, 0x90, 0x89, 0xCE, 0x35, 0x43, 0x31, 0xE0, 0x70, 0x6F, 0x13, 0x67,
+ 0x11, 0x2C, 0xCF, 0xF5, 0x9E, 0x8E, 0x7B, 0x5A, 0xC4, 0x59, 0x5F, 0xD7, 0x30, 0x80, 0xD3, 0x83,
+ 0x2B, 0xC3, 0xDE, 0xE0, 0x51, 0x57, 0x85, 0xD7, 0x6D, 0xD3, 0x92, 0x36, 0xE3, 0x91, 0x25, 0x94,
+ 0x71, 0x2C, 0x12, 0x27, 0xA5, 0xAC, 0x4F, 0x3E, 0x90, 0xE0, 0xEC, 0x90, 0xDD, 0x2A, 0xD0, 0x5A,
+ 0x7E, 0xDF, 0xE0, 0xC9, 0xCC, 0x1C, 0xF2, 0x4C, 0x28, 0x4F, 0xF1, 0x73, 0xCF, 0x58, 0x11, 0x94,
+ 0x8A, 0x92, 0xE6, 0xE3, 0x5A, 0x0F, 0x21, 0xF5, 0xC9, 0xF7, 0x84, 0x66, 0x44, 0x40, 0x86, 0x92,
+ 0xE2, 0xCF, 0x78, 0x92, 0x9A, 0xE8, 0x3F, 0xB4, 0x67, 0xBE, 0x28, 0xD5, 0x36, 0x98, 0x99, 0x2B,
+ 0xC8, 0xFD, 0x69, 0xBB, 0xAD, 0x0D, 0xDE, 0xBD, 0xD7, 0xDA, 0x6D, 0x85, 0xC6, 0xEE, 0x9A, 0xBA,
+ 0x13, 0xD7, 0x7F, 0xEF, 0x48, 0x9F, 0xFC, 0xF3, 0xE7, 0x37, 0x2F, 0x5B, 0xFD, 0xEE, 0xF0, 0xF8,
+ 0xA6, 0x37, 0x1A, 0x0F, 0xF7, 0xCF, 0x0E, 0x59, 0x93, 0xF2, 0xB8, 0xC6, 0xFA, 0xE4, 0x3D, 0x12,
+ 0xD2, 0x3A, 0x1E, 0x0F, 0xEB, 0xE2, 0x1A, 0x21, 0xAE, 0xB7, 0xAF, 0x5B, 0x47, 0xFD, 0xEE, 0x4D,
+ 0xAF, 0x7F, 0xDC, 0xAD, 0x81, 0x6A, 0xA8, 0x4F, 0xBE, 0x06, 0x4C, 0xBD, 0x13, 0x44, 0xD5, 0x2D,
+ 0x87, 0x0A, 0x45, 0xDB, 0xAF, 0x28, 0xDA, 0x81, 0x3E, 0xF9, 0x11, 0x45, 0x0B, 0x39, 0x37, 0xF2,
+ 0xD0, 0xAD, 0xC3, 0x43, 0x1F, 0x5C, 0x86, 0xE2, 0x02, 0x51, 0x00, 0x13, 0xFD, 0x3A, 0xA2, 0xED,
+ 0xE9, 0x13, 0x14, 0x07, 0x62, 0x02, 0xE9, 0xD6, 0x40, 0x04, 0xB1, 0x83, 0xD2, 0x04, 0xE4, 0xDC,
+ 0x1C, 0x8D, 0x8F, 0xAB, 0x63, 0x3A, 0x01, 0xEE, 0x3E, 0x02, 0xA6, 0x63, 0x10, 0xD4, 0xB8, 0x8E,
+ 0x9C, 0x8E, 0xF5, 0x09, 0xE2, 0x19, 0x0F, 0xBB, 0x37, 0xC3, 0x3A, 0x36, 0x03, 0x5E, 0xF1, 0x16,
+ 0x11, 0x01, 0x92, 0x9B, 0x41, 0x1D, 0x19, 0x81, 0x4B, 0x5C, 0x7C, 0xF3, 0x75, 0x6B, 0x08, 0x8C,
+ 0xF5, 0x4F, 0xC6, 0xD5, 0xF1, 0x80, 0x3B, 0xFC, 0x13, 0x09, 0x02, 0x62, 0x6E, 0xFA, 0xC3, 0x1A,
+ 0x04, 0x81, 0x33, 0x00, 0x3C, 0xE2, 0xA8, 0x8C, 0x02, 0xEC, 0xFA, 0x2D, 0x25, 0x06, 0x11, 0xF5,
+ 0x8E, 0x6A, 0x70, 0x05, 0x56, 0xFD, 0x4F, 0x14, 0x0F, 0x20, 0xB9, 0xE9, 0x0D, 0xEB, 0xD8, 0x34,
+ 0x20, 0xA2, 0x24, 0x81, 0xAF, 0xA1, 0xAB, 0x55, 0xC7, 0x04, 0x36, 0x7D, 0x32, 0xBE, 0x39, 0x19,
+ 0xAB, 0x21, 0xC0, 0xE1, 0x07, 0x43, 0x79, 0xDE, 0x00, 0x95, 0x3F, 0x7E, 0xE5, 0x8D, 0x4D, 0xFF,
+ 0xD9, 0xC0, 0x94, 0x33, 0xB8, 0x2D, 0x3D, 0x32, 0x71, 0x38, 0x90, 0x09, 0x3B, 0x50, 0x1B, 0x94,
+ 0x62, 0x94, 0x84, 0xBB, 0x9F, 0xF4, 0xC9, 0x50, 0x61, 0xF0, 0x4F, 0x64, 0x87, 0x14, 0x36, 0x41,
+ 0x3F, 0xCD, 0x48, 0xD0, 0xF2, 0x30, 0x17, 0x01, 0x97, 0x18, 0xE8, 0xB1, 0x08, 0x52, 0x69, 0xD4,
+ 0x93, 0xD0, 0x6A, 0xDC, 0xE8, 0x93, 0xF1, 0xA0, 0x30, 0x5B, 0xA8, 0xAE, 0x8C, 0x29, 0x2D, 0x6E,
+ 0x38, 0xC4, 0xF7, 0x4B, 0xEB, 0x23, 0x02, 0xD5, 0x27, 0xAF, 0xC2, 0xE3, 0x3A, 0x5A, 0x69, 0x17,
+ 0x71, 0x4A, 0x61, 0x33, 0xD4, 0x12, 0x23, 0x87, 0x69, 0xA6, 0x3D, 0xE0, 0xAA, 0x89, 0x34, 0x73,
+ 0xBF, 0x8A, 0xD9, 0xA5, 0x5E, 0x70, 0x6E, 0xE3, 0x19, 0x7E, 0x50, 0x5A, 0x2B, 0x02, 0x10, 0x22,
+ 0x34, 0x3F, 0x7A, 0x30, 0x8D, 0x84, 0xA4, 0xFC, 0x05, 0xF4, 0xE1, 0x1B, 0xC1, 0x86, 0xED, 0x33,
+ 0x2B, 0xAD, 0x91, 0x08, 0x14, 0xF2, 0x81, 0xF0, 0xB8, 0x96, 0x56, 0xEA, 0x84, 0xAF, 0x18, 0x39,
+ 0x5C, 0x2F, 0x22, 0x84, 0x0D, 0x77, 0xA4, 0x97, 0x22, 0x6A, 0x6B, 0xE9, 0x65, 0x69, 0x78, 0xEB,
+ 0x4A, 0xE1, 0x2B, 0x84, 0x04, 0xAD, 0x88, 0xC3, 0x07, 0x73, 0x95, 0x88, 0x98, 0xBF, 0x80, 0xAF,
+ 0x98, 0xC4, 0x71, 0x2D, 0xBF, 0xFC, 0xD4, 0x93, 0xC3, 0xE9, 0x93, 0xD7, 0xA4, 0xFD, 0x1D, 0x1E,
+ 0xD5, 0x51, 0xC7, 0xCB, 0x4D, 0xE0, 0xD6, 0x50, 0x88, 0xA0, 0x85, 0xA9, 0xA3, 0xCB, 0xB5, 0x71,
+ 0xBC, 0x23, 0x6D, 0x1C, 0xEF, 0x50, 0x1B, 0x06, 0xF9, 0x64, 0x93, 0x2B, 0x62, 0x97, 0x56, 0x87,
+ 0x00, 0xD4, 0x27, 0x97, 0x37, 0x6B, 0xD7, 0xC7, 0xA7, 0x77, 0xBE, 0xC5, 0xF3, 0x5A, 0x4E, 0x32,
+ 0xAA, 0xA1, 0x93, 0x90, 0x20, 0xEE, 0x23, 0x23, 0xAE, 0x95, 0xD1, 0x8E, 0xB4, 0x52, 0x44, 0x6B,
+ 0x1D, 0xAD, 0x2C, 0x0C, 0xCB, 0x99, 0x11, 0xCB, 0xC6, 0x27, 0x09, 0xCA, 0x2A, 0x26, 0x06, 0xAB,
+ 0x4F, 0xDE, 0x44, 0x27, 0x75, 0x14, 0xD3, 0xAD, 0xA1, 0x97, 0x38, 0x3D, 0x49, 0x7F, 0x19, 0xC1,
+ 0xAC, 0x7C, 0x47, 0xBA, 0xE9, 0xF5, 0x76, 0x39, 0xAA, 0xAC, 0xC9, 0xCC, 0x32, 0xEC, 0x4F, 0x64,
+ 0x3E, 0x87, 0x69, 0x50, 0xF9, 0xA1, 0x25, 0x01, 0x0E, 0xE3, 0x0B, 0x3B, 0xD7, 0x2E, 0xE9, 0x79,
+ 0xE9, 0x62, 0x5A, 0x0A, 0x5D, 0xF5, 0x8A, 0x5A, 0x7A, 0x4E, 0xC8, 0x97, 0x95, 0x09, 0xAD, 0x61,
+ 0xB2, 0x23, 0x7D, 0xF2, 0x9D, 0x1B, 0xD2, 0x59, 0x7D, 0xDA, 0xFA, 0x1D, 0x59, 0xD0, 0x55, 0xDB,
+ 0x3A, 0x73, 0xE8, 0x37, 0x9E, 0x71, 0x4B, 0x5F, 0x0B, 0x50, 0x67, 0x4A, 0xFF, 0x3D, 0x31, 0xB5,
+ 0x1F, 0x2C, 0xA7, 0x3A, 0x33, 0x43, 0x24, 0x84, 0x10, 0xA7, 0x1E, 0x96, 0x11, 0x4C, 0x91, 0xE0,
+ 0xA0, 0x1E, 0x92, 0x31, 0x16, 0x98, 0xD7, 0x96, 0xF1, 0x18, 0x26, 0xF1, 0xC6, 0xF5, 0xB4, 0xFC,
+ 0x80, 0x72, 0x3D, 0x85, 0x71, 0xF9, 0xA7, 0x57, 0xDA, 0x25, 0xDD, 0x67, 0x5C, 0x3A, 0x5C, 0xB1,
+ 0x2D, 0x50, 0x2A, 0x86, 0x1E, 0xAD, 0x23, 0x60, 0x9F, 0x5B, 0x0B, 0x3C, 0x72, 0x07, 0x52, 0x5D,
+ 0xE4, 0x91, 0xB0, 0x27, 0x08, 0xA4, 0x3B, 0x46, 0xF4, 0x18, 0xB7, 0x6A, 0x3C, 0xEE, 0x30, 0x15,
+ 0x9B, 0x5D, 0x97, 0x4F, 0xC3, 0x66, 0xD7, 0xA0, 0x26, 0xF3, 0x0A, 0xB7, 0xA0, 0x9B, 0x1A, 0xE8,
+ 0xAB, 0x11, 0x45, 0x61, 0xAF, 0x0F, 0xA3, 0x28, 0xCA, 0xEF, 0x43, 0x2B, 0x0A, 0xAC, 0xE5, 0x13,
+ 0x8E, 0xA3, 0x55, 0x9C, 0x8A, 0x02, 0xEA, 0x93, 0x77, 0x86, 0xB3, 0x81, 0x41, 0xA6, 0x29, 0x85,
+ 0x85, 0x1D, 0x3F, 0x98, 0x7B, 0x71, 0xBE, 0x1F, 0x5A, 0x75, 0x40, 0xC8, 0xCA, 0x35, 0xCB, 0x4F,
+ 0x77, 0x38, 0x1C, 0x0B, 0x89, 0xEF, 0xE0, 0xA8, 0x74, 0x62, 0x20, 0x30, 0xEC, 0x38, 0x23, 0x60,
+ 0x53, 0xA9, 0xEA, 0xC9, 0xC0, 0x87, 0x8D, 0xE3, 0xDC, 0xD6, 0xC9, 0x04, 0x2E, 0x6C, 0x77, 0x63,
+ 0x56, 0xC7, 0x00, 0x69, 0xC0, 0x3F, 0xE6, 0x73, 0x6B, 0x56, 0x3D, 0x91, 0x80, 0x24, 0xE0, 0xAD,
+ 0xBB, 0x52, 0x84, 0xDF, 0xF1, 0xC0, 0x4B, 0x66, 0x15, 0x66, 0x72, 0x33, 0xD0, 0xE2, 0xE5, 0x45,
+ 0xA3, 0x03, 0x2F, 0xF4, 0xF9, 0x40, 0x91, 0x01, 0xB9, 0x7D, 0xE8, 0xA0, 0x00, 0x44, 0x7C, 0xA2,
+ 0xC6, 0x53, 0x45, 0x59, 0x0C, 0x32, 0x8C, 0xE8, 0x62, 0xFA, 0xFD, 0x50, 0xF3, 0xBB, 0x88, 0xA2,
+ 0xE4, 0xEC, 0xAE, 0x37, 0x1A, 0x8C, 0xC3, 0xE9, 0xDD, 0xA0, 0x7F, 0xBF, 0x13, 0x3C, 0x44, 0xBE,
+ 0x5B, 0xFD, 0xF4, 0xAB, 0xA8, 0x06, 0xA2, 0xD1, 0x77, 0xB8, 0xCE, 0x50, 0x22, 0x60, 0xD7, 0x77,
+ 0xA4, 0xFE, 0xC3, 0x79, 0x52, 0xFF, 0x11, 0xB8, 0xD2, 0xA2, 0x42, 0xC4, 0x5B, 0x60, 0xC4, 0x7B,
+ 0x73, 0xD1, 0x8C, 0x86, 0x16, 0x0F, 0x16, 0xEA, 0x16, 0x0F, 0x1A, 0xEA, 0x34, 0xBE, 0x43, 0x4D,
+ 0x48, 0xA1, 0x62, 0x06, 0xCB, 0x01, 0x59, 0x2D, 0xAB, 0x4E, 0x90, 0xEB, 0xDD, 0xD4, 0x89, 0x72,
+ 0x82, 0x8C, 0x64, 0x90, 0x1B, 0x47, 0xAB, 0x22, 0xA3, 0xFB, 0x5D, 0xD6, 0x1D, 0x16, 0x51, 0x5B,
+ 0xC7, 0x69, 0x3C, 0xE3, 0xFA, 0xD3, 0x62, 0x65, 0x94, 0x56, 0x06, 0x87, 0x03, 0x5D, 0xBC, 0x7B,
+ 0xD9, 0x64, 0xBA, 0x20, 0xFA, 0x7D, 0x18, 0x3F, 0x0A, 0xB9, 0x7E, 0xE8, 0x58, 0x67, 0x13, 0xA7,
+ 0x7C, 0xB0, 0x43, 0x20, 0x7D, 0xF2, 0x2D, 0x71, 0x7C, 0xED, 0xC2, 0xF5, 0xF8, 0xBB, 0x18, 0x1B,
+ 0xD1, 0x1A, 0xED, 0xF9, 0x61, 0x54, 0xC6, 0x98, 0x7E, 0x68, 0x7D, 0x2D, 0x57, 0x96, 0xE7, 0xB9,
+ 0x5E, 0x69, 0x95, 0x71, 0x38, 0x98, 0x56, 0xB4, 0xDF, 0xD1, 0xA3, 0x46, 0xD4, 0x25, 0x7A, 0x7D,
+ 0x18, 0x8D, 0x85, 0x3C, 0x3F, 0xB4, 0xD2, 0xAE, 0xE6, 0xB6, 0xB5, 0x2E, 0xAD, 0x32, 0x0A, 0xA5,
+ 0x4F, 0x3E, 0xB6, 0xBF, 0x86, 0xBF, 0x8D, 0xA8, 0x8B, 0xF5, 0xF8, 0x30, 0xCA, 0xE2, 0xDC, 0x3E,
+ 0xB4, 0xAA, 0xA6, 0xEB, 0xF2, 0xE1, 0x10, 0x60, 0xF4, 0xC9, 0xAB, 0xF7, 0xCD, 0xE4, 0x7E, 0xD8,
+ 0x99, 0xA2, 0x86, 0x6A, 0xE9, 0x83, 0x32, 0xF5, 0xD0, 0xDA, 0xB8, 0xAE, 0xA0, 0x8D, 0x6B, 0x24,
+ 0xFC, 0xA7, 0x86, 0xB4, 0x71, 0xAD, 0xAE, 0x8D, 0x7B, 0xF6, 0x97, 0xEB, 0xC7, 0xA0, 0x1F, 0xFA,
+ 0xB0, 0xDF, 0xD4, 0x28, 0x3F, 0x1C, 0x09, 0x40, 0xDC, 0x34, 0x06, 0x47, 0xDA, 0x2B, 0xA3, 0x99,
+ 0x01, 0x29, 0xEC, 0xB7, 0x09, 0x17, 0x8A, 0x98, 0x7C, 0x68, 0x3D, 0xD9, 0xC4, 0xAC, 0x90, 0xE4,
+ 0x99, 0x9F, 0xF0, 0xC9, 0x39, 0x7C, 0xA2, 0xFC, 0x16, 0xB2, 0xBD, 0xCB, 0xD7, 0xDA, 0x37, 0xE2,
+ 0xF4, 0xA1, 0x0A, 0x43, 0x49, 0x9A, 0x92, 0xF3, 0xA6, 0xFE, 0x68, 0x57, 0xDB, 0x32, 0x00, 0xF3,
+ 0x0E, 0x75, 0x33, 0x37, 0x66, 0xE4, 0x93, 0x49, 0x82, 0x2A, 0xEB, 0xFE, 0x31, 0x58, 0x7D, 0xF2,
+ 0x35, 0x9C, 0x68, 0xAF, 0xE9, 0x49, 0x53, 0xE9, 0x78, 0xBC, 0xFF, 0x26, 0x3C, 0x2A, 0xC1, 0xEF,
+ 0x43, 0x3B, 0x15, 0x25, 0x06, 0x26, 0x3F, 0xEE, 0xC2, 0xA9, 0xF4, 0xDC, 0x53, 0x02, 0x9C, 0xAB,
+ 0xEF, 0x7B, 0x76, 0xDE, 0xAC, 0x02, 0x23, 0x22, 0x1A, 0xD3, 0x61, 0x8C, 0xEF, 0x26, 0xD4, 0x18,
+ 0x7F, 0xF8, 0x91, 0xBF, 0x36, 0xB8, 0x48, 0x53, 0xFC, 0x21, 0x3C, 0xBA, 0xDD, 0x88, 0x04, 0x6D,
+ 0x3F, 0xB0, 0x6C, 0x5B, 0x9F, 0xBC, 0x21, 0x81, 0xF6, 0x01, 0x0F, 0x15, 0x9F, 0xBA, 0x8B, 0x61,
+ 0x11, 0xCF, 0xDC, 0x06, 0x1E, 0x31, 0x56, 0xFA, 0xE4, 0x03, 0xBE, 0x50, 0x19, 0x70, 0xE1, 0x59,
+ 0x79, 0x64, 0x54, 0x88, 0xC4, 0xF1, 0x5C, 0x20, 0x2A, 0x54, 0x12, 0x7F, 0x51, 0xA3, 0xAE, 0x89,
+ 0xA3, 0xD8, 0xB5, 0xC9, 0x25, 0x6D, 0xAC, 0xA1, 0x95, 0x15, 0x77, 0x17, 0x7F, 0x1C, 0x30, 0xDF,
+ 0x39, 0xE8, 0x03, 0xC0, 0xF8, 0x44, 0x6F, 0xF2, 0x7D, 0xEB, 0xA0, 0x56, 0xF6, 0x7C, 0xFF, 0xE4,
+ 0xCC, 0x5F, 0x1B, 0x8E, 0x68, 0x46, 0x1F, 0x7E, 0xBF, 0xE6, 0x4F, 0x33, 0x4F, 0x5D, 0xDB, 0xFC,
+ 0x2A, 0xB6, 0xF0, 0xFF, 0x21, 0x7C, 0x2C, 0x17, 0x41, 0xC0, 0x2E, 0x04, 0x86, 0x02, 0xE5, 0x2E,
+ 0x3D, 0x81, 0x9E, 0x3D, 0x41, 0x8D, 0x6F, 0xEB, 0xCA, 0xD1, 0x6E, 0xC6, 0x93, 0xC4, 0x1E, 0x59,
+ 0x84, 0x92, 0x94, 0x3D, 0x61, 0x2E, 0x7D, 0xAE, 0xF8, 0x7B, 0xB2, 0xB0, 0x7C, 0xA0, 0x51, 0x03,
+ 0xBB, 0x38, 0xA4, 0xCF, 0x62, 0x32, 0x5B, 0x56, 0x7B, 0xCE, 0x37, 0xDE, 0x25, 0x7F, 0x4D, 0x81,
+ 0xF4, 0xF1, 0xED, 0x52, 0xA9, 0x63, 0xFA, 0x59, 0xEB, 0x24, 0xC6, 0x22, 0xAB, 0x7F, 0xDA, 0x6E,
+ 0x2F, 0x87, 0xF8, 0x54, 0xA9, 0x26, 0x58, 0x3B, 0x3B, 0x5C, 0x0E, 0x8B, 0x9E, 0xDA, 0x2B, 0x7C,
+ 0x24, 0x18, 0x38, 0xAD, 0xFC, 0x44, 0x30, 0x4A, 0x69, 0x02, 0xD4, 0x1C, 0x68, 0xEF, 0x0C, 0xFF,
+ 0xF3, 0x81, 0xF6, 0x11, 0x87, 0xF8, 0x06, 0x1F, 0x0C, 0x46, 0xDA, 0x0D, 0xD3, 0xF4, 0x32, 0x1F,
+ 0x0E, 0x1E, 0x26, 0x1E, 0x0E, 0x1E, 0x8B, 0x87, 0x83, 0xA3, 0x95, 0xAA, 0xEE, 0xCD, 0xA0, 0xDB,
+ 0x3D, 0x56, 0x61, 0x5D, 0xF1, 0x01, 0xE1, 0x7B, 0xE1, 0x69, 0x05, 0xD2, 0x54, 0xE4, 0x69, 0x28,
+ 0x78, 0x8A, 0x6D, 0xD8, 0xBF, 0x99, 0xCF, 0x1F, 0x1B, 0x47, 0x7C, 0xC9, 0xB0, 0x3A, 0x4B, 0xDD,
+ 0x7E, 0xD3, 0x4F, 0x71, 0x53, 0xE3, 0xBE, 0xAF, 0x87, 0xB8, 0x69, 0x93, 0x74, 0x34, 0x1C, 0xE5,
+ 0x06, 0x43, 0x0A, 0xC2, 0x9C, 0xFE, 0xCD, 0x7D, 0x3A, 0xFD, 0xA2, 0x86, 0xD3, 0x2F, 0xB6, 0x9C,
+ 0xBE, 0x41, 0x6F, 0x17, 0x84, 0xFF, 0xD5, 0x3C, 0x5E, 0xF0, 0x55, 0xC2, 0xEB, 0xA5, 0x7C, 0x75,
+ 0xBB, 0xF7, 0xEA, 0xF7, 0x85, 0x4E, 0x12, 0x1A, 0xC3, 0x9B, 0xFB, 0x74, 0x92, 0x0C, 0xD3, 0xAD,
+ 0x64, 0xA7, 0x3C, 0xEC, 0x4C, 0x9A, 0x19, 0x97, 0x68, 0x36, 0x15, 0x57, 0x28, 0xEF, 0x1D, 0x1F,
+ 0xD7, 0x1D, 0x0C, 0x79, 0xEA, 0x74, 0x1F, 0xEA, 0x51, 0x7F, 0x61, 0x44, 0x66, 0x93, 0xFB, 0x49,
+ 0xCC, 0xD6, 0xB1, 0x14, 0x57, 0x39, 0x31, 0x7B, 0xFF, 0xED, 0xB7, 0xE5, 0x72, 0xB1, 0x78, 0x2F,
+ 0x8F, 0x24, 0x17, 0xCB, 0x2D, 0x53, 0xDF, 0xAE, 0xE1, 0x06, 0x52, 0x5D, 0xC9, 0x74, 0x23, 0x70,
+ 0x7D, 0xF2, 0x8A, 0x1E, 0x6B, 0x31, 0x89, 0x95, 0x32, 0x5E, 0xE5, 0x59, 0x27, 0x05, 0x8C, 0xD5,
+ 0xB1, 0x23, 0x12, 0xD2, 0xBA, 0x51, 0xC4, 0x95, 0x53, 0xBB, 0x8E, 0xB1, 0xA7, 0xCE, 0x54, 0x6D,
+ 0x9F, 0xA0, 0x4D, 0x8A, 0x52, 0xE1, 0xD5, 0xC6, 0xAE, 0xAC, 0x36, 0x0E, 0xAB, 0x4F, 0xDE, 0xC1,
+ 0x64, 0xDC, 0x5A, 0xDB, 0x16, 0xCC, 0x3C, 0x5A, 0x5D, 0xAD, 0xAD, 0x0D, 0x7A, 0xFB, 0x0D, 0x8E,
+ 0x91, 0x82, 0x8C, 0x92, 0x6F, 0xCB, 0xE9, 0x45, 0x0F, 0xB3, 0x0D, 0xEE, 0xE9, 0x75, 0x39, 0x75,
+ 0x15, 0xE2, 0xB9, 0x6E, 0x50, 0x59, 0x1B, 0x02, 0x18, 0x12, 0x15, 0x38, 0xD2, 0x22, 0x9D, 0xA8,
+ 0xAB, 0x22, 0xB6, 0xB5, 0x36, 0xC2, 0xA6, 0xA6, 0x0E, 0xA5, 0x8D, 0xB4, 0xB8, 0x3F, 0x45, 0x75,
+ 0x07, 0xAA, 0x04, 0x6B, 0x4F, 0x9F, 0xF4, 0x4B, 0x60, 0x28, 0xDE, 0x87, 0xCA, 0x5A, 0xD5, 0x77,
+ 0x22, 0xFF, 0xB6, 0x7A, 0xEC, 0xE3, 0xB0, 0x90, 0x76, 0xDF, 0x42, 0xAA, 0xBB, 0xD2, 0x5E, 0x43,
+ 0x5F, 0xD4, 0x89, 0x7A, 0xA3, 0x26, 0x9D, 0x48, 0x90, 0x51, 0xDD, 0x89, 0x7A, 0x8F, 0xC3, 0x87,
+ 0x50, 0x1F, 0x6B, 0x8F, 0x54, 0xD6, 0x07, 0x87, 0xD5, 0x27, 0xEF, 0x3D, 0x82, 0xCA, 0xA8, 0xE4,
+ 0x3D, 0x21, 0x92, 0x6A, 0xCE, 0x73, 0x0F, 0x8E, 0xD2, 0xEB, 0x8C, 0xEA, 0xE1, 0xE8, 0x97, 0x73,
+ 0x36, 0x09, 0x86, 0x81, 0x3C, 0x08, 0x0C, 0x1E, 0xA7, 0x0B, 0x13, 0xDB, 0x1C, 0x55, 0x77, 0x62,
+ 0x01, 0x8D, 0xB3, 0x67, 0x38, 0xAC, 0x6C, 0x38, 0x31, 0x44, 0x8F, 0x2A, 0xEE, 0xD6, 0xC4, 0x70,
+ 0x1F, 0xC6, 0x34, 0xE9, 0x97, 0x32, 0xE9, 0x66, 0x4C, 0x67, 0x8D, 0x2F, 0x17, 0x24, 0x6A, 0x7B,
+ 0x3E, 0x29, 0xB2, 0x78, 0xA4, 0x61, 0xB0, 0x10, 0x69, 0xE8, 0xEB, 0x05, 0xE9, 0x5E, 0xF7, 0x46,
+ 0x73, 0x5E, 0x41, 0xC0, 0xF6, 0x32, 0x4B, 0xF9, 0xAD, 0x01, 0x31, 0xE6, 0x64, 0x29, 0x70, 0xC8,
+ 0xEB, 0x63, 0xCB, 0x7F, 0x29, 0x61, 0x95, 0xC7, 0x0A, 0x0E, 0xCC, 0x55, 0x18, 0x0E, 0xDD, 0xCD,
+ 0xE6, 0xBF, 0x21, 0x15, 0x35, 0xC6, 0xEE, 0x06, 0x13, 0xE0, 0xD8, 0xB2, 0x11, 0x55, 0x00, 0x0B,
+ 0x9A, 0x01, 0x9B, 0xF1, 0x95, 0x58, 0x09, 0xCA, 0x6C, 0x72, 0x3F, 0xF3, 0xFC, 0x6B, 0xCB, 0x29,
+ 0x3F, 0xCF, 0xFF, 0xC9, 0x72, 0x4C, 0xF7, 0xBA, 0xDC, 0x54, 0x3F, 0xDE, 0xD1, 0x9F, 0x60, 0xAA,
+ 0x4F, 0x07, 0x4B, 0x5C, 0x2C, 0x6C, 0x7B, 0x44, 0xED, 0xA5, 0x33, 0x69, 0x21, 0x33, 0xE8, 0x1B,
+ 0x5C, 0x6A, 0x03, 0x14, 0xBE, 0x46, 0x97, 0x1E, 0x77, 0xED, 0x2F, 0x3F, 0x9F, 0xC6, 0x93, 0x5D,
+ 0x4E, 0x81, 0x9A, 0xC3, 0x0C, 0x25, 0x85, 0xC7, 0x07, 0xAF, 0xA5, 0xFE, 0xB2, 0xCD, 0xCF, 0xED,
+ 0x83, 0xF3, 0x73, 0x1F, 0x01, 0x99, 0x38, 0x66, 0x65, 0xCB, 0x42, 0xD8, 0xC8, 0xAE, 0x2E, 0x1D,
+ 0xB3, 0x51, 0xAB, 0x62, 0xBD, 0x57, 0xD6, 0x41, 0xBF, 0x7B, 0x74, 0xF2, 0xB8, 0xCC, 0x0A, 0x19,
+ 0xAA, 0x61, 0x54, 0xBD, 0xD1, 0xF0, 0xE8, 0xF1, 0xD8, 0x95, 0x3B, 0x9F, 0xB3, 0x15, 0xAE, 0x6A,
+ 0xA6, 0xC5, 0xC1, 0x6F, 0xE8, 0xA3, 0xB4, 0x3E, 0x69, 0x36, 0x5E, 0x85, 0x9D, 0xAB, 0xE9, 0x62,
+ 0x20, 0xD1, 0xC5, 0xF8, 0x71, 0x99, 0x16, 0xE7, 0x48, 0xD5, 0xBA, 0x24, 0x1C, 0xDD, 0x13, 0x43,
+ 0xF7, 0x61, 0x5A, 0x81, 0x1B, 0x18, 0x76, 0x65, 0xCB, 0x62, 0xD0, 0x60, 0x58, 0x3F, 0xE0, 0x81,
+ 0xF6, 0x01, 0xF8, 0x6C, 0xD4, 0xB8, 0x44, 0xFF, 0xD5, 0x03, 0xD7, 0xA0, 0xFB, 0xC8, 0xC6, 0x43,
+ 0xC6, 0x52, 0xAD, 0xD0, 0x35, 0x1E, 0x3E, 0x1E, 0xFB, 0x72, 0x37, 0x01, 0x5E, 0xAD, 0x1C, 0xBA,
+ 0x18, 0x38, 0x86, 0x2E, 0x7A, 0xD4, 0xBC, 0x89, 0x85, 0x14, 0xD4, 0x18, 0x1C, 0x87, 0x0F, 0xBF,
+ 0x7E, 0xFD, 0x8B, 0x84, 0xA7, 0x5A, 0x46, 0x36, 0x78, 0x2C, 0x41, 0x6C, 0x66, 0x28, 0xBF, 0x88,
+ 0x8D, 0x22, 0x8B, 0x67, 0xF3, 0x0C, 0x16, 0xE6, 0x70, 0xEC, 0xA0, 0xD1, 0x0A, 0x86, 0xE8, 0xFC,
+ 0xDE, 0x97, 0xEC, 0x42, 0xAE, 0x1E, 0x53, 0xBD, 0x62, 0x6A, 0x39, 0x4E, 0x55, 0x35, 0x71, 0x58,
+ 0x7D, 0xF2, 0x8A, 0x1D, 0x34, 0xBB, 0xB8, 0xCA, 0x3B, 0xBF, 0xFF, 0x95, 0x55, 0xC1, 0x55, 0xD3,
+ 0x6A, 0x4A, 0x15, 0x31, 0xBC, 0xF0, 0x4B, 0x11, 0x3A, 0xDF, 0xAD, 0x18, 0x7D, 0x39, 0xE2, 0xF1,
+ 0x94, 0x34, 0x16, 0xC6, 0x0A, 0x9F, 0x30, 0x2E, 0x5B, 0xD4, 0x78, 0x83, 0x60, 0xE5, 0x6A, 0x1A,
+ 0xC9, 0x9E, 0x1E, 0x77, 0x55, 0x63, 0x92, 0x7C, 0xB5, 0x24, 0x10, 0xDE, 0x9E, 0x5A, 0x86, 0x8F,
+ 0x4F, 0xE3, 0xC3, 0xB1, 0xF6, 0x0A, 0x8E, 0xB5, 0xF7, 0xF6, 0x26, 0x7C, 0x37, 0xAE, 0xCC, 0x21,
+ 0xE2, 0x3B, 0x9B, 0x22, 0x0C, 0x59, 0xDB, 0xD7, 0xE9, 0x86, 0x2E, 0xFE, 0x14, 0x16, 0x1C, 0xE3,
+ 0x3E, 0xA6, 0xD1, 0xF0, 0xB8, 0xAB, 0x6B, 0x2C, 0x2B, 0xE6, 0xCF, 0x90, 0xF8, 0x9F, 0xE9, 0x06,
+ 0xA7, 0x5E, 0x48, 0xA0, 0xCC, 0x01, 0xE2, 0xF4, 0x86, 0x04, 0x52, 0xFB, 0xAD, 0xB3, 0xEF, 0x68,
+ 0x5B, 0x22, 0x3D, 0x21, 0x8E, 0xAE, 0xD4, 0x10, 0x12, 0x2F, 0xC3, 0x64, 0xED, 0x55, 0x9E, 0x86,
+ 0x91, 0x0B, 0xA2, 0x27, 0x15, 0x04, 0xEE, 0xF3, 0xBA, 0x5F, 0x9E, 0xFA, 0x82, 0xA7, 0x9E, 0x1A,
+ 0x4F, 0xFD, 0x1A, 0x3C, 0xF5, 0x1B, 0xE2, 0x69, 0x20, 0x78, 0xEA, 0xAB, 0xF1, 0x34, 0xA8, 0xC1,
+ 0xD3, 0xA0, 0x21, 0x9E, 0x86, 0x82, 0xA7, 0x81, 0x1A, 0x4F, 0xC3, 0x1A, 0x3C, 0x0D, 0x1B, 0xE2,
+ 0x69, 0x24, 0x78, 0x1A, 0xAA, 0xF1, 0x34, 0xAA, 0xC1, 0xD3, 0xA8, 0x21, 0x9E, 0xC6, 0x82, 0xA7,
+ 0x91, 0x1A, 0x4F, 0xE3, 0x1A, 0x3C, 0x8D, 0x1B, 0xE2, 0xE9, 0x48, 0xF0, 0x34, 0x56, 0xE3, 0xE9,
+ 0xA8, 0x06, 0x4F, 0x47, 0x0D, 0xF1, 0x74, 0x2C, 0x78, 0x3A, 0x52, 0xE3, 0xE9, 0xB8, 0x06, 0x4F,
+ 0xC7, 0x0D, 0xF1, 0x74, 0x22, 0x78, 0x3A, 0x56, 0xE3, 0xE9, 0xA4, 0x06, 0x4F, 0x27, 0x0D, 0xF1,
+ 0x84, 0x8B, 0x72, 0x8C, 0xA9, 0x13, 0xC5, 0x41, 0xB7, 0x5B, 0x83, 0x2B, 0xA3, 0x29, 0xAE, 0xC2,
+ 0x54, 0xA2, 0xA7, 0x9A, 0x4B, 0xD4, 0x49, 0x26, 0xA6, 0x4D, 0xB1, 0x15, 0x65, 0x13, 0x8A, 0xE9,
+ 0x44, 0xAF, 0x4E, 0x3E, 0x31, 0x6B, 0x8A, 0xAD, 0x30, 0xA1, 0xE8, 0x29, 0x66, 0x14, 0xBD, 0x3A,
+ 0x29, 0x85, 0xD9, 0x14, 0x5B, 0x61, 0x4E, 0xD1, 0x53, 0x4C, 0x2A, 0x7A, 0x75, 0xB2, 0x0A, 0xD2,
+ 0x14, 0x5B, 0x61, 0x5A, 0xD1, 0x53, 0xCC, 0x2B, 0x7A, 0x75, 0x12, 0x8B, 0x79, 0x53, 0x6C, 0x85,
+ 0x99, 0x45, 0x4F, 0x31, 0xB5, 0xE8, 0xD5, 0xC8, 0x2D, 0x4E, 0xE4, 0x13, 0xB1, 0x7B, 0x65, 0x8B,
+ 0x04, 0x7C, 0x8A, 0x1C, 0x4D, 0xDA, 0x94, 0x1E, 0x3D, 0xE1, 0x40, 0xF8, 0x6C, 0x14, 0x13, 0xC8,
+ 0x85, 0xEB, 0xCC, 0xAD, 0x45, 0x58, 0x64, 0x78, 0x34, 0x4F, 0x49, 0xF8, 0xB1, 0xB7, 0xF2, 0x2A,
+ 0x17, 0x1A, 0x3E, 0xBC, 0xBE, 0x2C, 0x57, 0x66, 0x88, 0xF7, 0xF2, 0x27, 0x2A, 0x32, 0x00, 0xD9,
+ 0xFD, 0xF8, 0x27, 0x02, 0x94, 0xEA, 0x0A, 0x14, 0xA8, 0x4C, 0x45, 0x61, 0x14, 0xAF, 0x28, 0x8C,
+ 0x95, 0x2B, 0x0A, 0x8C, 0xB8, 0xDD, 0xD4, 0x12, 0x00, 0xF7, 0x80, 0x7D, 0xD7, 0x40, 0x9D, 0xE9,
+ 0x41, 0x75, 0xA6, 0x47, 0x65, 0x98, 0x1E, 0x54, 0x61, 0xBA, 0xC2, 0xD3, 0x8D, 0x8A, 0x72, 0x02,
+ 0x7A, 0xBF, 0xB6, 0x6E, 0x88, 0xA9, 0xFD, 0xA2, 0x2E, 0xAA, 0x5E, 0x75, 0x51, 0x1D, 0x95, 0x11,
+ 0x55, 0x6F, 0x87, 0xF6, 0x31, 0x12, 0x7C, 0xFF, 0xA8, 0xCE, 0xF7, 0xA8, 0x3A, 0xDF, 0x83, 0x32,
+ 0x7C, 0x8F, 0x76, 0xC8, 0xF7, 0x50, 0xF0, 0xFD, 0x51, 0x9D, 0xEF, 0x61, 0x75, 0xBE, 0x87, 0x65,
+ 0xF8, 0x1E, 0xEE, 0x90, 0xEF, 0x3E, 0x04, 0x9B, 0x1F, 0x3F, 0x6A, 0x3F, 0x2C, 0x3D, 0xE2, 0x2F,
+ 0x8B, 0x2B, 0x71, 0x0C, 0xA2, 0xEA, 0xD8, 0x3E, 0x6A, 0x60, 0xEE, 0x86, 0x14, 0x0E, 0xE2, 0x3C,
+ 0x15, 0xE6, 0xCD, 0x0C, 0x42, 0xE5, 0xC3, 0x41, 0x72, 0x9E, 0xE4, 0x33, 0xB7, 0x9E, 0x2A, 0x53,
+ 0xBB, 0x8B, 0x61, 0xC7, 0xFA, 0xE4, 0xED, 0xA6, 0xC4, 0xF8, 0x76, 0x5C, 0xDD, 0x9E, 0xD5, 0x2B,
+ 0xE6, 0x8C, 0xAE, 0x9D, 0xD9, 0xF3, 0x09, 0xE5, 0x19, 0xF2, 0x32, 0x5F, 0x41, 0xED, 0xD5, 0xAB,
+ 0x10, 0xA3, 0x06, 0xAA, 0xE4, 0x18, 0xE9, 0x8F, 0x18, 0x3B, 0x3F, 0x22, 0x43, 0x1A, 0x64, 0x2C,
+ 0x25, 0x06, 0xA3, 0xA3, 0x92, 0xDA, 0x3C, 0xAE, 0x18, 0x9D, 0x90, 0xC6, 0x9D, 0xA9, 0x13, 0xA7,
+ 0x1E, 0x28, 0x80, 0x8F, 0x15, 0x04, 0x30, 0xAE, 0x2E, 0x80, 0x52, 0x99, 0x0B, 0xD2, 0xB8, 0x3B,
+ 0x01, 0x74, 0x99, 0x00, 0x3E, 0x44, 0x6F, 0xA6, 0xCE, 0x31, 0xE8, 0x1A, 0x15, 0xA8, 0x51, 0x03,
+ 0x6B, 0x24, 0x18, 0x69, 0x7B, 0xC2, 0xA2, 0x81, 0xA3, 0x72, 0x0A, 0xED, 0x97, 0xCD, 0xAF, 0xE4,
+ 0xC5, 0x4F, 0x85, 0xFC, 0x7B, 0x97, 0x09, 0x56, 0xBF, 0x2B, 0x2C, 0xBA, 0xBC, 0x00, 0xBA, 0xD5,
+ 0x05, 0xD0, 0x2B, 0x25, 0x80, 0xEE, 0xE3, 0x4A, 0xC6, 0xC7, 0xDB, 0x1F, 0x13, 0x2E, 0x96, 0x56,
+ 0x59, 0xF7, 0x8F, 0x8D, 0x66, 0xFD, 0x32, 0xC2, 0xDA, 0xA9, 0xF7, 0x0F, 0x22, 0xCE, 0xB5, 0x5F,
+ 0xB4, 0xE4, 0xD6, 0xD7, 0xBC, 0x38, 0x50, 0xBD, 0x08, 0x38, 0x6A, 0x60, 0xBD, 0x0A, 0x29, 0x3C,
+ 0x91, 0x70, 0x56, 0x32, 0xC0, 0x9F, 0x54, 0x77, 0x87, 0x52, 0x1A, 0x46, 0x5A, 0x77, 0xA7, 0xE2,
+ 0x51, 0x42, 0x10, 0xEC, 0x43, 0xE6, 0x2A, 0x2A, 0xAE, 0x5E, 0x39, 0x1C, 0x35, 0xB0, 0xD4, 0x85,
+ 0x14, 0x1E, 0x4B, 0x38, 0x2B, 0xA9, 0xE2, 0xB2, 0x29, 0xE9, 0x71, 0xC5, 0xA9, 0x65, 0x6F, 0x97,
+ 0x39, 0x29, 0x56, 0xBB, 0x63, 0x82, 0x88, 0x7F, 0x65, 0x22, 0x4F, 0xC1, 0xD5, 0x2B, 0xDE, 0xA3,
+ 0x9A, 0xEB, 0xB3, 0xBB, 0x8B, 0xE4, 0x47, 0xB2, 0x4F, 0x90, 0x17, 0xDB, 0x41, 0xD9, 0x5C, 0xB6,
+ 0x5B, 0x71, 0xE0, 0xDB, 0x69, 0x2A, 0x0B, 0xBD, 0x43, 0xD6, 0xB3, 0xCD, 0x7D, 0x8E, 0x09, 0x54,
+ 0x5F, 0x79, 0x1B, 0x35, 0xB0, 0x3D, 0x04, 0x29, 0xEC, 0xEB, 0x93, 0x8F, 0x25, 0x99, 0xAA, 0x53,
+ 0x3F, 0xA8, 0xBC, 0x3F, 0xA4, 0xB9, 0xD2, 0xFB, 0x6C, 0x75, 0x53, 0xBE, 0xF4, 0x7E, 0xF1, 0xEE,
+ 0xE7, 0x72, 0xA5, 0xF7, 0x78, 0x2F, 0xCD, 0x95, 0xDE, 0xAB, 0xD9, 0x4C, 0xA9, 0x8D, 0xB2, 0xC0,
+ 0x18, 0xBE, 0x3F, 0x62, 0x66, 0xF9, 0xB4, 0x4B, 0x10, 0x8C, 0xF6, 0x5E, 0x9C, 0x86, 0x22, 0x8A,
+ 0x3D, 0xB1, 0x9F, 0x6C, 0x9F, 0x67, 0x3D, 0x83, 0x9C, 0xB0, 0xA0, 0xB6, 0x11, 0x76, 0xFB, 0x75,
+ 0x28, 0x9D, 0x31, 0xFF, 0x10, 0x57, 0x8D, 0x47, 0xEB, 0xB3, 0x5E, 0x1A, 0xD0, 0x39, 0x2A, 0x89,
+ 0x7B, 0xE7, 0x8F, 0xDC, 0x4F, 0x52, 0x8A, 0xEA, 0x51, 0xFD, 0xF4, 0xF0, 0x5C, 0xB9, 0x4E, 0x4E,
+ 0xC1, 0xCA, 0x44, 0xF3, 0x41, 0xBC, 0xD4, 0xA2, 0x1E, 0xCD, 0x19, 0x79, 0xBB, 0x89, 0xE6, 0x88,
+ 0x3B, 0xC1, 0x7B, 0x89, 0xAC, 0x86, 0xC1, 0x96, 0x13, 0x80, 0x7C, 0x13, 0x85, 0x82, 0x00, 0xB2,
+ 0x24, 0x70, 0x2F, 0x22, 0xE8, 0x53, 0x09, 0xF4, 0x53, 0xDA, 0xCF, 0x08, 0xFC, 0xB4, 0x7D, 0xD5,
+ 0xB8, 0x3F, 0x68, 0xA0, 0x36, 0x81, 0xE2, 0x4A, 0x70, 0x54, 0x52, 0xA7, 0xE5, 0x16, 0x07, 0x13,
+ 0x3A, 0x2D, 0x67, 0xD4, 0x3B, 0x5B, 0x1D, 0x04, 0xE4, 0x03, 0x2A, 0x80, 0x81, 0xB2, 0x4A, 0xAB,
+ 0x4F, 0x33, 0x07, 0x0D, 0xE4, 0x27, 0x28, 0xAD, 0x04, 0x47, 0x25, 0x55, 0x5A, 0x6E, 0xE9, 0x33,
+ 0xA1, 0x52, 0xF5, 0xF9, 0x25, 0x27, 0x72, 0x67, 0x2A, 0x1D, 0x52, 0x01, 0x0C, 0x95, 0x55, 0x5A,
+ 0x7D, 0xD6, 0x31, 0x68, 0x60, 0xF7, 0x2E, 0x4A, 0x2B, 0xC1, 0x51, 0x49, 0x95, 0x96, 0x5B, 0xB2,
+ 0x4B, 0xA8, 0x54, 0x7D, 0x3E, 0xC9, 0x89, 0xDC, 0x99, 0x4A, 0x47, 0x54, 0x00, 0x23, 0x65, 0x95,
+ 0x56, 0xAF, 0x14, 0x0C, 0x1A, 0x28, 0x06, 0xA1, 0xB4, 0x12, 0x1C, 0x95, 0x54, 0x69, 0xB9, 0xD5,
+ 0xE7, 0x84, 0x4A, 0xD5, 0xD7, 0x39, 0x38, 0x91, 0x3B, 0x53, 0xE9, 0x98, 0x0A, 0x60, 0xAC, 0xAC,
+ 0xD2, 0xEA, 0xFB, 0xAB, 0x06, 0x0D, 0xEC, 0xDD, 0x46, 0x69, 0x25, 0x38, 0x2A, 0xA9, 0xD2, 0x72,
+ 0xA5, 0xDB, 0x84, 0x4A, 0xD5, 0x57, 0x6E, 0x38, 0x91, 0x3B, 0x53, 0xE9, 0x11, 0x15, 0xC0, 0x91,
+ 0xB2, 0x4A, 0xAB, 0x6F, 0x5D, 0x1F, 0x34, 0x50, 0xCF, 0x43, 0x69, 0x25, 0x38, 0x2A, 0xA9, 0xD2,
+ 0x72, 0x15, 0x9C, 0x84, 0x4A, 0xD5, 0xF7, 0x4E, 0x71, 0x22, 0x77, 0xA6, 0xD2, 0x63, 0x2A, 0x80,
+ 0x63, 0x65, 0x95, 0x56, 0xDF, 0xB9, 0x3F, 0x68, 0x60, 0xE7, 0x3E, 0x4A, 0x2B, 0xC1, 0x51, 0x49,
+ 0x95, 0x96, 0xAB, 0xCD, 0x26, 0x54, 0xAA, 0xBE, 0xDD, 0x89, 0x13, 0xB9, 0x33, 0x95, 0x9E, 0x50,
+ 0x01, 0x9C, 0x28, 0xAB, 0xB4, 0xFA, 0x96, 0x81, 0x41, 0x03, 0x9B, 0x5F, 0x50, 0x5A, 0xDD, 0x38,
+ 0x47, 0x25, 0x55, 0x5A, 0x6E, 0x81, 0x71, 0x90, 0xB1, 0xF5, 0x45, 0x41, 0xA5, 0x59, 0x0B, 0x8C,
+ 0x8F, 0xA0, 0x7E, 0x67, 0x5C, 0x4F, 0x2B, 0x7C, 0xFA, 0xE5, 0xE5, 0x4F, 0xAF, 0xB2, 0x0B, 0xFB,
+ 0x99, 0x55, 0xBC, 0x44, 0x5F, 0x8F, 0xBD, 0x8C, 0x17, 0x97, 0x17, 0x12, 0x0E, 0x5A, 0x66, 0x2F,
+ 0x4D, 0xD4, 0xB6, 0x98, 0xCF, 0xB7, 0x34, 0x06, 0x5C, 0xC2, 0xD2, 0x06, 0xC3, 0xAE, 0x3C, 0x69,
+ 0x29, 0xB0, 0x34, 0x4E, 0xE5, 0x6E, 0x82, 0x07, 0x22, 0x87, 0xB9, 0x38, 0xF2, 0xFE, 0xBD, 0xD2,
+ 0x9A, 0x0E, 0x03, 0x48, 0x86, 0x8F, 0x61, 0xF7, 0x44, 0x31, 0x7E, 0x80, 0x0C, 0xB2, 0x36, 0xC6,
+ 0xDF, 0x63, 0x00, 0x41, 0x1A, 0x07, 0x8C, 0xA9, 0x37, 0xCA, 0x4C, 0xA5, 0xAB, 0x00, 0xA5, 0x98,
+ 0xCA, 0xAA, 0xEC, 0xDC, 0x33, 0x53, 0x43, 0xC6, 0x54, 0x8E, 0x93, 0xA6, 0x98, 0x4A, 0xCF, 0x83,
+ 0x4B, 0x31, 0x95, 0x35, 0x11, 0x8E, 0x98, 0x7A, 0x0C, 0x81, 0x8E, 0xCC, 0x8C, 0xC5, 0xAC, 0x42,
+ 0xA8, 0xBB, 0xBC, 0x38, 0x7C, 0xF9, 0xE6, 0x42, 0xA3, 0x4B, 0x9A, 0xAE, 0x5D, 0x32, 0xE2, 0x25,
+ 0x3B, 0xFD, 0x53, 0xC5, 0x3C, 0x4A, 0x7A, 0x2C, 0xEA, 0xBD, 0xB9, 0x50, 0x0D, 0x78, 0x1C, 0xB2,
+ 0x4C, 0xC8, 0x1B, 0x75, 0x07, 0x55, 0x2A, 0x84, 0x21, 0x91, 0x3B, 0x0A, 0x7A, 0x14, 0x7D, 0x3F,
+ 0x92, 0xC1, 0x65, 0x39, 0x19, 0x94, 0xAA, 0x92, 0x26, 0x65, 0x50, 0x22, 0xEC, 0x0B, 0x22, 0x77,
+ 0x29, 0x03, 0x8C, 0x92, 0x97, 0x17, 0xDA, 0xFB, 0xBF, 0x6B, 0x97, 0x37, 0x6B, 0xD7, 0xDF, 0x78,
+ 0xA4, 0x30, 0xAA, 0x70, 0xB8, 0x64, 0x5C, 0x19, 0x8F, 0x46, 0x03, 0xD5, 0xC0, 0x32, 0xCA, 0x1E,
+ 0x02, 0xE6, 0xDD, 0x7B, 0x8C, 0x97, 0x94, 0xD0, 0x61, 0xC8, 0xE0, 0xF7, 0x04, 0x34, 0xAD, 0x14,
+ 0x37, 0x39, 0x60, 0x92, 0xC3, 0x5E, 0x17, 0xB7, 0x57, 0x2B, 0x32, 0x28, 0xCF, 0x28, 0x07, 0xF7,
+ 0x3A, 0x1C, 0x50, 0x2A, 0x47, 0x21, 0x7B, 0x1F, 0x7F, 0xF8, 0xA0, 0xC6, 0x58, 0xBA, 0x8E, 0x56,
+ 0x4E, 0x75, 0x59, 0x8F, 0x8C, 0xDE, 0xD3, 0xA0, 0x20, 0xBD, 0x71, 0x76, 0x08, 0xA1, 0x77, 0x1B,
+ 0x26, 0x43, 0x92, 0x67, 0x73, 0x6B, 0x01, 0x76, 0x2C, 0xEF, 0x83, 0x8A, 0x96, 0xBD, 0xEC, 0x14,
+ 0xBF, 0x51, 0xD9, 0x9E, 0x41, 0xF4, 0x07, 0x93, 0x40, 0xA7, 0x13, 0x02, 0x5F, 0x19, 0x0B, 0x12,
+ 0x5D, 0xD7, 0x58, 0x6C, 0xCF, 0x8B, 0xD9, 0x06, 0x43, 0x68, 0x5C, 0x11, 0xFE, 0x41, 0x4D, 0x6D,
+ 0xE9, 0x91, 0xF9, 0xB9, 0xFE, 0x45, 0x88, 0x93, 0x3F, 0x95, 0x87, 0x4D, 0x74, 0xCD, 0x74, 0xAF,
+ 0x1D, 0xDB, 0x35, 0x70, 0x3C, 0x30, 0xD6, 0x01, 0x50, 0xDA, 0xF9, 0x6D, 0x8D, 0x2F, 0xBE, 0x32,
+ 0xF0, 0x21, 0x2E, 0x23, 0xA7, 0x9F, 0x98, 0x55, 0xCC, 0x6C, 0xD7, 0x17, 0xB3, 0x39, 0x3C, 0x0C,
+ 0x3F, 0xC0, 0xF9, 0x3F, 0xFF, 0x5D, 0xB4, 0x83, 0xC0, 0x5A, 0x2D, 0x62, 0x02, 0xD0, 0x35, 0xDF,
+ 0x9B, 0x9D, 0xEB, 0x40, 0xA9, 0xE7, 0xFA, 0xBE, 0xEB, 0x59, 0x0B, 0x2B, 0x43, 0x3B, 0x59, 0xD2,
+ 0x3E, 0x94, 0x89, 0x3B, 0xD5, 0x58, 0xA2, 0xF8, 0x33, 0x7F, 0xE6, 0x59, 0xEB, 0x60, 0xF2, 0xC4,
+ 0x74, 0x67, 0x9B, 0x15, 0x71, 0x82, 0x8E, 0x61, 0x9A, 0x97, 0x57, 0x70, 0xF0, 0x2D, 0x7E, 0xAC,
+ 0x0D, 0x24, 0xDF, 0xDA, 0x7B, 0xFD, 0x8F, 0x77, 0x38, 0x3A, 0xE3, 0x35, 0x90, 0x17, 0x31, 0xF7,
+ 0x0E, 0xB4, 0xF9, 0xC6, 0x61, 0x03, 0x64, 0x8B, 0x60, 0xDB, 0x7D, 0xED, 0x0F, 0xC0, 0x78, 0x65,
+ 0x78, 0xDA, 0xD4, 0xF0, 0xC9, 0x5B, 0xD7, 0x0F, 0xB4, 0x73, 0x2D, 0xC4, 0x68, 0xBB, 0x33, 0xBA,
+ 0x9D, 0xA3, 0xC3, 0xF8, 0xE2, 0x2D, 0x19, 0xE3, 0x3F, 0x7A, 0x36, 0x34, 0x0D, 0xA1, 0x9E, 0x6B,
+ 0x7B, 0xA7, 0xC7, 0xBD, 0x3D, 0xB4, 0xDD, 0xB0, 0x8B, 0x39, 0x81, 0xE8, 0x0F, 0xED, 0x5A, 0x1B,
+ 0xCF, 0x3E, 0xD0, 0x66, 0xD3, 0xFD, 0x3F, 0x28, 0xF5, 0xF4, 0x32, 0x5E, 0xDB, 0xE7, 0xCC, 0x74,
+ 0x82, 0x25, 0x71, 0x5A, 0x11, 0x65, 0x1E, 0xF1, 0xD7, 0xAE, 0xE3, 0x13, 0x46, 0x1C, 0xFB, 0x59,
+ 0xF3, 0xE8, 0x7A, 0xC7, 0x0F, 0x8C, 0x60, 0xE3, 0x6B, 0x4F, 0xCF, 0xCF, 0xB5, 0x7E, 0xB7, 0x1B,
+ 0x6F, 0xA6, 0x41, 0x37, 0xE9, 0x76, 0x07, 0x5A, 0xEA, 0xC2, 0x0F, 0xE4, 0x26, 0xD8, 0xFF, 0x2A,
+ 0x84, 0xB9, 0xD3, 0x88, 0xED, 0x93, 0x04, 0x92, 0x10, 0x00, 0x5F, 0x27, 0xD7, 0xDA, 0x4F, 0x12,
+ 0xD8, 0x32, 0x8D, 0xC0, 0xD8, 0xFF, 0x23, 0xA1, 0x2F, 0xE8, 0x15, 0x28, 0x39, 0xD0, 0xE8, 0xAD,
+ 0xAF, 0x62, 0xB7, 0xEE, 0xF6, 0x3B, 0x20, 0x43, 0xE0, 0x37, 0x84, 0x26, 0x9E, 0x97, 0xA4, 0x98,
+ 0x42, 0xB7, 0x7B, 0x07, 0x1A, 0xDE, 0x49, 0xC2, 0xC6, 0x88, 0x7C, 0x22, 0xAE, 0x09, 0xA1, 0xE5,
+ 0xA3, 0x95, 0xA0, 0x64, 0xE8, 0xEE, 0x12, 0x2A, 0x82, 0x38, 0xF4, 0x3D, 0x59, 0x80, 0xC4, 0x16,
+ 0x07, 0x3C, 0x2C, 0x1D, 0xD0, 0x98, 0x74, 0xC0, 0xC2, 0x59, 0x4C, 0x6B, 0xE0, 0xD0, 0xBE, 0x6B,
+ 0x13, 0xB0, 0x89, 0x45, 0x6B, 0x8F, 0x7F, 0x0A, 0x14, 0xEC, 0x69, 0xAF, 0x7B, 0xB3, 0xF7, 0x1C,
+ 0xC0, 0x3B, 0x81, 0xFB, 0x21, 0xF0, 0x2C, 0x67, 0xD1, 0xEA, 0x8D, 0xF7, 0x23, 0x5C, 0xF4, 0x36,
+ 0x22, 0x4C, 0xDD, 0xA7, 0xD7, 0x69, 0x17, 0xE9, 0x1B, 0x2D, 0x7E, 0xFD, 0xF9, 0xDE, 0xFE, 0x1E,
+ 0x27, 0x9D, 0x9E, 0x83, 0xB1, 0xB5, 0xD8, 0xC1, 0x33, 0x4A, 0xE1, 0xBE, 0x76, 0x76, 0xC6, 0xBB,
+ 0x61, 0xAD, 0xF0, 0x22, 0x34, 0xA2, 0x7F, 0x52, 0xB7, 0x42, 0x43, 0xFC, 0xF5, 0xCB, 0x3F, 0x84,
+ 0xC5, 0xDE, 0x1D, 0x02, 0xD5, 0x2F, 0x30, 0x2E, 0x7F, 0xF9, 0x07, 0xFC, 0x7F, 0xF7, 0x8C, 0x86,
+ 0xE2, 0x2F, 0xFF, 0xC0, 0x3F, 0x77, 0xCF, 0xA0, 0x27, 0x38, 0xA6, 0xFD, 0xDD, 0xFD, 0x4A, 0xA5,
+ 0xB0, 0x2D, 0xBB, 0x45, 0xA6, 0xEC, 0x42, 0xA1, 0x95, 0xA6, 0x69, 0x91, 0x43, 0xD4, 0xAF, 0x91,
+ 0xF7, 0xB6, 0x66, 0xAE, 0x09, 0xCA, 0x09, 0xC0, 0x8E, 0x85, 0xCA, 0x6D, 0x50, 0x89, 0x10, 0x54,
+ 0x57, 0xA8, 0xDC, 0x9A, 0xD3, 0x96, 0x1A, 0x77, 0x94, 0xC8, 0x3C, 0x44, 0xCB, 0xB5, 0xE1, 0xF9,
+ 0xE4, 0x1B, 0x27, 0x68, 0x05, 0x09, 0x97, 0xC8, 0x90, 0xF8, 0x64, 0x92, 0x60, 0x01, 0x7F, 0x00,
+ 0x07, 0xED, 0xF6, 0xB8, 0xD2, 0x42, 0x53, 0x7B, 0x12, 0x5A, 0x61, 0x44, 0x29, 0xBB, 0x99, 0x61,
+ 0x85, 0x3F, 0xCF, 0xEC, 0xCF, 0xAD, 0x1B, 0xF8, 0x2F, 0x1D, 0x28, 0xB6, 0x44, 0x84, 0x8D, 0x5E,
+ 0xE0, 0x7F, 0x20, 0x17, 0xFC, 0x93, 0xA9, 0x1F, 0xC0, 0xFA, 0xDE, 0xB6, 0x5B, 0xEC, 0xB3, 0x5F,
+ 0xA0, 0x9A, 0x0D, 0x04, 0x21, 0xFF, 0x16, 0xC3, 0x81, 0xEB, 0x06, 0x9F, 0x0E, 0xB4, 0xB5, 0x07,
+ 0x84, 0xD1, 0x2F, 0x7D, 0xC0, 0x31, 0x20, 0x22, 0x0E, 0xFB, 0x5B, 0x48, 0xC1, 0xDA, 0xB6, 0x5F,
+ 0x30, 0xAC, 0x40, 0x02, 0x3B, 0x00, 0x4D, 0x6D, 0xD0, 0x62, 0xE0, 0xFF, 0xBB, 0x67, 0xD0, 0x09,
+ 0x1C, 0xC2, 0xFF, 0x77, 0xCF, 0xB0, 0x2B, 0xD4, 0x25, 0xF6, 0x78, 0xF7, 0x0C, 0x7A, 0x84, 0x13,
+ 0xF8, 0x1F, 0xDA, 0x60, 0xBF, 0xD8, 0x0A, 0xFF, 0xC2, 0x1D, 0xDA, 0x3F, 0xDE, 0xA4, 0x07, 0xEC,
+ 0x02, 0x3F, 0xCD, 0x63, 0x90, 0xBD, 0xE9, 0xBE, 0x45, 0xDF, 0x3C, 0xFE, 0xE9, 0x06, 0xD8, 0xA1,
+ 0x07, 0xB7, 0xE0, 0xF8, 0x8E, 0x89, 0xE7, 0xF8, 0xE7, 0x56, 0x98, 0x27, 0x5E, 0xE0, 0x47, 0x70,
+ 0x8D, 0xBE, 0x9D, 0x15, 0x2F, 0xB1, 0x03, 0x6C, 0x45, 0xDF, 0xA5, 0x49, 0x5B, 0xB1, 0x23, 0xB8,
+ 0xC6, 0xDF, 0xC0, 0x78, 0xA0, 0xF1, 0x77, 0xFC, 0x15, 0x0A, 0x27, 0x7A, 0x07, 0xDF, 0x0B, 0xFF,
+ 0x06, 0x19, 0x64, 0xA4, 0xA1, 0x54, 0xC2, 0xB3, 0xDB, 0xBB, 0x67, 0x04, 0xEF, 0x51, 0x22, 0xE1,
+ 0xF8, 0x96, 0x1F, 0xC3, 0x75, 0xA0, 0x0F, 0xEF, 0x08, 0x82, 0xE9, 0x85, 0xDB, 0xE8, 0x02, 0xB4,
+ 0x08, 0xF0, 0x3E, 0x27, 0x1E, 0xCE, 0x6E, 0xC3, 0x33, 0x84, 0xA6, 0xB0, 0x9C, 0x0D, 0x38, 0xBD,
+ 0x8D, 0x4E, 0xE1, 0x2E, 0xF2, 0x82, 0x0A, 0xE0, 0x3C, 0xDD, 0x3D, 0xE3, 0x3C, 0xA1, 0x16, 0xD9,
+ 0x51, 0x5A, 0xD4, 0x18, 0xF4, 0x02, 0x1E, 0x24, 0x5F, 0xB1, 0x1C, 0x24, 0x36, 0x3C, 0x42, 0x00,
+ 0xB8, 0xB4, 0x09, 0x1E, 0xBE, 0xBA, 0xFD, 0xC6, 0x6C, 0xED, 0xF1, 0x4F, 0xB7, 0xEE, 0x61, 0x88,
+ 0x8E, 0xC3, 0x74, 0x5C, 0x67, 0x66, 0x5B, 0x33, 0x8C, 0x04, 0xAD, 0x7D, 0xED, 0x7C, 0xC2, 0xC3,
+ 0x34, 0x7A, 0x2C, 0x34, 0x8F, 0x7B, 0x61, 0x26, 0x6A, 0x8F, 0x7F, 0x7C, 0x74, 0x6F, 0xBF, 0x43,
+ 0x1D, 0x8D, 0x3B, 0x13, 0xA2, 0xE0, 0x31, 0x46, 0x0D, 0x07, 0x36, 0x96, 0xE0, 0xD8, 0x0A, 0x07,
+ 0xB9, 0x48, 0x68, 0xEB, 0x18, 0x16, 0x8A, 0x26, 0x3E, 0x92, 0x74, 0x53, 0x83, 0x48, 0x4E, 0xD8,
+ 0x12, 0x11, 0xEA, 0x69, 0x3A, 0x42, 0x81, 0xAA, 0xBC, 0xA0, 0xB5, 0x77, 0xE9, 0x79, 0xAE, 0xF7,
+ 0xAF, 0xBD, 0xE7, 0xD8, 0xE8, 0xF9, 0xDE, 0xBF, 0x4F, 0xB5, 0xBD, 0xE7, 0xF1, 0x50, 0x75, 0x97,
+ 0x8E, 0x29, 0x4C, 0x63, 0x0B, 0x45, 0x8D, 0x2D, 0x62, 0x1A, 0x5B, 0xDC, 0xAF, 0xC6, 0xE2, 0x9F,
+ 0x8C, 0xAD, 0xA3, 0xB5, 0xF8, 0x27, 0x5A, 0x73, 0x34, 0x57, 0x08, 0xCF, 0x95, 0xC6, 0xB5, 0xB5,
+ 0x90, 0x69, 0xAB, 0x8A, 0x9A, 0xD8, 0x18, 0x0E, 0xDE, 0x43, 0xBC, 0xB7, 0x3F, 0xBC, 0xFB, 0x16,
+ 0xC7, 0x02, 0xB9, 0xCA, 0x42, 0x8D, 0xA5, 0xB3, 0x2D, 0x09, 0x06, 0x4C, 0x0E, 0x12, 0x23, 0x53,
+ 0x22, 0x49, 0x78, 0xBE, 0xA7, 0xB5, 0x28, 0x4A, 0x4C, 0x11, 0x0A, 0x0C, 0x81, 0x8F, 0x2C, 0x6A,
+ 0xBE, 0x8B, 0xA3, 0x89, 0x70, 0xDE, 0x08, 0x2A, 0xC7, 0x16, 0x10, 0x40, 0x49, 0x89, 0x0C, 0xF3,
+ 0x96, 0xC3, 0xC4, 0x06, 0xBD, 0xC6, 0x5D, 0x84, 0xFA, 0xAB, 0xAF, 0x1A, 0xD4, 0x44, 0x4C, 0x8F,
+ 0x62, 0x9B, 0x5F, 0x28, 0x1D, 0x1E, 0xF9, 0x95, 0x04, 0xC4, 0x3F, 0x05, 0x22, 0x31, 0x70, 0x3E,
+ 0x62, 0x94, 0xC0, 0x72, 0x2B, 0xC1, 0x42, 0x47, 0x1A, 0x25, 0x1C, 0xF4, 0xF3, 0x11, 0x19, 0x18,
+ 0xD4, 0xA8, 0xA0, 0xDF, 0x6B, 0x90, 0x60, 0x10, 0x63, 0x9A, 0x12, 0x12, 0xF1, 0xAD, 0x81, 0x6C,
+ 0x3C, 0x6A, 0xC4, 0x88, 0x37, 0xFC, 0x4B, 0xF0, 0xF0, 0x31, 0x54, 0x09, 0x0D, 0x7F, 0x3B, 0x7D,
+ 0x26, 0x16, 0x35, 0x62, 0xF8, 0x0B, 0xE1, 0x65, 0x3C, 0xF1, 0x31, 0x5B, 0x8D, 0x27, 0xFE, 0x1E,
+ 0xF3, 0x6C, 0x3C, 0x8A, 0xB2, 0xE1, 0xEF, 0x0E, 0x97, 0x59, 0x1D, 0x4B, 0x11, 0x72, 0x1D, 0x83,
+ 0x35, 0x01, 0x60, 0x5E, 0x96, 0x7E, 0xD1, 0x3B, 0xED, 0x46, 0x18, 0x78, 0x46, 0x91, 0x87, 0x81,
+ 0x37, 0x49, 0x63, 0x10, 0xD1, 0xE1, 0x01, 0x72, 0xBB, 0x87, 0x88, 0x42, 0x90, 0xA3, 0xAB, 0x45,
+ 0x21, 0x48, 0xBB, 0x45, 0xF8, 0x09, 0x61, 0x32, 0xC2, 0x0F, 0x2D, 0x68, 0xB0, 0x2F, 0x18, 0xE7,
+ 0xC9, 0x3F, 0xFC, 0x20, 0xB0, 0x4C, 0x89, 0x88, 0x03, 0xD2, 0x79, 0x25, 0x4B, 0xE2, 0xDF, 0xBE,
+ 0x4D, 0x19, 0x12, 0x2D, 0x96, 0xDC, 0xFA, 0x6A, 0xA1, 0xEB, 0xD6, 0xCF, 0xC0, 0x40, 0xE7, 0x0E,
+ 0x6A, 0xB9, 0x19, 0xFF, 0x58, 0xAC, 0x04, 0x09, 0xCC, 0x39, 0x94, 0x50, 0xF0, 0x2F, 0x66, 0xCA,
+ 0x18, 0xA1, 0x1F, 0x54, 0x54, 0x62, 0x45, 0x7C, 0x3C, 0x51, 0x46, 0x07, 0x9D, 0xDE, 0xE4, 0x29,
+ 0x85, 0x7F, 0xA2, 0x2E, 0x4B, 0x23, 0x6B, 0xD5, 0x21, 0x57, 0x7C, 0x8E, 0x4D, 0x32, 0xEC, 0x56,
+ 0x9C, 0x15, 0x3E, 0xCC, 0x10, 0xBD, 0xF8, 0x28, 0xE6, 0xE2, 0xC4, 0x96, 0xA6, 0xA2, 0xC4, 0xEE,
+ 0x18, 0x01, 0x24, 0x47, 0xD3, 0x4D, 0x40, 0xFC, 0x0E, 0xD6, 0x0F, 0x42, 0xE1, 0x6C, 0xDD, 0xEA,
+ 0x38, 0x40, 0x00, 0x45, 0xB8, 0x1F, 0x8F, 0x55, 0x2C, 0x70, 0x6C, 0xE1, 0x62, 0x97, 0xB3, 0xD0,
+ 0xB1, 0xBB, 0x19, 0x18, 0x79, 0x7A, 0x9B, 0x84, 0xC0, 0x8B, 0x59, 0xD8, 0x68, 0x8D, 0x28, 0x86,
+ 0xAB, 0x3F, 0x1A, 0x6D, 0x27, 0xB9, 0xBC, 0x03, 0xB6, 0xAC, 0x84, 0x02, 0xE9, 0x60, 0x89, 0x3E,
+ 0x2A, 0x7B, 0xCD, 0x60, 0x16, 0xAA, 0xED, 0x89, 0x35, 0xA5, 0xBD, 0xD3, 0xAD, 0x7A, 0x06, 0x40,
+ 0x70, 0xAB, 0xD2, 0x5E, 0x30, 0x1A, 0x4F, 0xA3, 0x62, 0x89, 0xA6, 0x4D, 0x3D, 0x62, 0x7C, 0xFE,
+ 0x2A, 0x81, 0x8C, 0x56, 0xFF, 0x43, 0x4C, 0xEC, 0x1A, 0x16, 0x05, 0x53, 0x97, 0xD8, 0x13, 0x37,
+ 0x6D, 0xD7, 0x21, 0xF2, 0x5E, 0x13, 0xD5, 0x11, 0xDE, 0x11, 0x3F, 0x33, 0xC9, 0xDC, 0xD8, 0xD8,
+ 0x41, 0x04, 0xE6, 0x91, 0x60, 0xE3, 0x39, 0xBC, 0x5A, 0xB2, 0x3D, 0xB9, 0x92, 0x96, 0xE9, 0x1A,
+ 0xB4, 0xCD, 0xC3, 0x43, 0xED, 0x65, 0x10, 0x18, 0xA0, 0x00, 0x5C, 0x66, 0x5D, 0xA2, 0x7C, 0x34,
+ 0x83, 0x17, 0x7C, 0x5D, 0x0F, 0x8D, 0x12, 0xEB, 0xCF, 0x1E, 0x70, 0x4D, 0xBD, 0xD1, 0x07, 0x10,
+ 0xE1, 0xA4, 0x14, 0x55, 0xE7, 0x3F, 0x1B, 0xE2, 0xDD, 0x7E, 0xA0, 0x02, 0x73, 0xBD, 0x97, 0xE0,
+ 0x8B, 0x7B, 0x9D, 0x68, 0xA9, 0x64, 0x8F, 0xD5, 0x37, 0x3B, 0x80, 0xEA, 0x12, 0xFA, 0x00, 0x1D,
+ 0x47, 0x36, 0xCF, 0xB8, 0x09, 0xF5, 0xAE, 0x9D, 0x9F, 0x9F, 0x73, 0x65, 0xA4, 0x0B, 0xAA, 0xD0,
+ 0xC2, 0x75, 0x3E, 0x93, 0xDB, 0xCD, 0x1A, 0xC4, 0x1F, 0x95, 0x48, 0x53, 0x45, 0x5B, 0x2E, 0x1D,
+ 0xD2, 0x81, 0x96, 0x17, 0xBC, 0x4C, 0xD6, 0x1B, 0x48, 0x1A, 0x45, 0x2A, 0xA0, 0xD6, 0x89, 0x9E,
+ 0xF8, 0xD5, 0x56, 0xA3, 0xBB, 0x27, 0xF2, 0x33, 0x49, 0x79, 0x99, 0x13, 0xC8, 0x85, 0x27, 0x86,
+ 0xAE, 0x54, 0x0F, 0x4F, 0x92, 0xA8, 0xEE, 0xF6, 0x9F, 0x44, 0x91, 0x61, 0xB3, 0x36, 0x8D, 0x80,
+ 0x24, 0x83, 0x43, 0x68, 0x0B, 0xE2, 0xE6, 0xCA, 0x0D, 0x48, 0x2A, 0x62, 0x58, 0x8E, 0x15, 0x58,
+ 0x86, 0xFD, 0x31, 0xB2, 0xC6, 0x9D, 0xBA, 0xBF, 0xC4, 0xC7, 0x4B, 0xF8, 0xFF, 0x56, 0x85, 0x57,
+ 0xAD, 0x2A, 0xB9, 0x65, 0x21, 0x61, 0x3C, 0x88, 0xAC, 0x24, 0x2E, 0x87, 0x44, 0x58, 0xE0, 0xF7,
+ 0x45, 0x4F, 0x4F, 0x9F, 0xD2, 0xA3, 0x27, 0xA1, 0xD2, 0x44, 0xF4, 0x38, 0xD7, 0xA2, 0x1B, 0x29,
+ 0x05, 0x6F, 0xE3, 0x4E, 0xE1, 0x10, 0xC8, 0x63, 0x18, 0x98, 0x6F, 0x85, 0xEA, 0x5D, 0xC3, 0x54,
+ 0x17, 0x6D, 0xE1, 0xFF, 0xA3, 0xFE, 0x23, 0x8A, 0xFA, 0xBB, 0x0B, 0xF1, 0x39, 0xB6, 0x9D, 0xF2,
+ 0x00, 0x06, 0x27, 0x5F, 0x74, 0x79, 0xBE, 0x77, 0xA0, 0xC9, 0x57, 0x55, 0x52, 0x69, 0xC5, 0xD2,
+ 0x32, 0x19, 0xC9, 0x91, 0x5D, 0xA1, 0x84, 0x70, 0x61, 0x14, 0x97, 0x0E, 0x71, 0x1D, 0xB1, 0xB5,
+ 0xC7, 0x56, 0x6D, 0x69, 0x34, 0xBE, 0x8B, 0x12, 0x92, 0xA5, 0x7B, 0x9D, 0x07, 0xE9, 0x41, 0xCC,
+ 0xB9, 0x22, 0x29, 0xE0, 0x10, 0xDA, 0xB4, 0x7C, 0x63, 0x6A, 0x17, 0x77, 0xCD, 0xDB, 0x99, 0x7C,
+ 0x28, 0x80, 0x06, 0xE2, 0x0A, 0x80, 0x06, 0x1E, 0xF5, 0x99, 0x18, 0x5A, 0xE2, 0x14, 0x61, 0x15,
+ 0x64, 0xE5, 0x22, 0x9E, 0x1B, 0xE0, 0xC4, 0x49, 0xCC, 0x2C, 0x90, 0x96, 0x08, 0xB1, 0xF1, 0xCB,
+ 0x00, 0x91, 0x3C, 0x3D, 0xD7, 0x9C, 0x8D, 0x6D, 0x83, 0x05, 0x22, 0x0B, 0x60, 0x81, 0xF1, 0xBB,
+ 0xD2, 0x00, 0xFD, 0xE7, 0x8D, 0x66, 0x21, 0xE5, 0x09, 0x09, 0x3C, 0x7B, 0x96, 0xC4, 0x86, 0xCB,
+ 0xB7, 0x2C, 0x35, 0x0F, 0x7B, 0x63, 0xED, 0xD9, 0xDB, 0x74, 0xA3, 0x51, 0x96, 0x93, 0x04, 0x43,
+ 0xF5, 0xD3, 0x84, 0xE0, 0x63, 0x19, 0x0E, 0x10, 0x62, 0x99, 0x54, 0x40, 0xB8, 0x49, 0x43, 0xDF,
+ 0x5A, 0xE9, 0x7A, 0x41, 0xAD, 0xBE, 0x45, 0xF8, 0x1E, 0x9D, 0x7D, 0x90, 0x3F, 0x1A, 0x73, 0x74,
+ 0x41, 0x64, 0x3B, 0x61, 0x57, 0x71, 0x8C, 0x8B, 0x04, 0x46, 0x64, 0x2C, 0x45, 0x37, 0xFE, 0x68,
+ 0x07, 0xD0, 0x14, 0x77, 0xC8, 0xC4, 0x06, 0xEF, 0xED, 0xD1, 0x9F, 0x76, 0xBC, 0xDD, 0x30, 0x97,
+ 0x82, 0xEB, 0xE9, 0xA7, 0x05, 0x34, 0x97, 0x31, 0x46, 0xD1, 0x5D, 0x4F, 0x91, 0x25, 0x4A, 0x02,
+ 0x1C, 0xE6, 0xA1, 0x9A, 0x1B, 0x33, 0xF2, 0xC9, 0x23, 0x33, 0x77, 0xE1, 0x58, 0xBF, 0x13, 0x19,
+ 0x42, 0xE6, 0x50, 0x2D, 0xE2, 0x78, 0xAE, 0x98, 0x66, 0x23, 0x72, 0xEE, 0x2B, 0xC9, 0xEB, 0x99,
+ 0x3D, 0x69, 0x3A, 0xB8, 0xD5, 0x27, 0x0B, 0x37, 0x1F, 0xF8, 0x56, 0x70, 0xBB, 0xDD, 0xCF, 0x44,
+ 0x6B, 0xF7, 0x04, 0xF5, 0xD0, 0xF4, 0x0D, 0x6E, 0xD0, 0x09, 0x79, 0x08, 0x2F, 0x24, 0x93, 0x50,
+ 0xE1, 0x9E, 0xE1, 0x0A, 0x58, 0xDC, 0x5E, 0xD8, 0x50, 0x19, 0x8D, 0x93, 0x91, 0x41, 0xDE, 0xD3,
+ 0xC8, 0xD1, 0xC3, 0x61, 0x43, 0x1A, 0xDF, 0x6B, 0x0E, 0x1A, 0x39, 0x38, 0xD9, 0xC6, 0x97, 0x34,
+ 0xD2, 0xCD, 0x74, 0x65, 0x05, 0x12, 0x84, 0x7B, 0xBD, 0xBD, 0x32, 0xE3, 0x4F, 0xDC, 0x5B, 0x59,
+ 0xC4, 0xA3, 0xA9, 0x39, 0x20, 0x4A, 0xAC, 0xE8, 0xCD, 0xD8, 0x06, 0xCF, 0x17, 0x30, 0xFD, 0xC6,
+ 0x75, 0x3A, 0x54, 0x70, 0x6A, 0x81, 0x9C, 0xA1, 0x60, 0xFB, 0x3A, 0x28, 0x8A, 0xE4, 0xCE, 0x0E,
+ 0xB1, 0x9B, 0x22, 0x99, 0xC9, 0xC7, 0x37, 0x14, 0xFC, 0xEA, 0x11, 0x80, 0xF3, 0xB1, 0x9A, 0xA8,
+ 0x7D, 0xF9, 0x07, 0x45, 0x71, 0xA7, 0xCD, 0x21, 0x5A, 0xF8, 0x4B, 0x62, 0xD2, 0xCA, 0x57, 0xB0,
+ 0xF1, 0x4F, 0x35, 0x5C, 0x14, 0x4F, 0xEC, 0xE4, 0xB8, 0xFB, 0x35, 0xB4, 0x90, 0x70, 0xB0, 0x29,
+ 0x9C, 0x6C, 0xD0, 0x0D, 0x3F, 0xF9, 0xF3, 0x0C, 0x96, 0x9E, 0x4B, 0x0A, 0x4B, 0xF8, 0x63, 0x91,
+ 0xC4, 0xEE, 0x40, 0x4E, 0x03, 0xDD, 0x7C, 0x07, 0xD9, 0x4B, 0xCA, 0x4C, 0xF7, 0xF9, 0x34, 0x09,
+ 0x34, 0x60, 0x8A, 0x90, 0xC7, 0x74, 0x84, 0x93, 0x21, 0x26, 0xA6, 0x84, 0x84, 0x19, 0x33, 0x9C,
+ 0x97, 0xE2, 0xDD, 0x30, 0x3C, 0x0B, 0x08, 0x65, 0xF1, 0x9B, 0x0F, 0x93, 0x9B, 0xFD, 0x27, 0xA1,
+ 0x18, 0xB6, 0x71, 0x60, 0x07, 0x31, 0x04, 0x09, 0x11, 0x65, 0x89, 0x89, 0x1B, 0x4D, 0x72, 0x5E,
+ 0x96, 0x23, 0x33, 0xF6, 0x8B, 0x8D, 0x99, 0x74, 0xC0, 0xA4, 0x3D, 0xFF, 0x8B, 0x1A, 0xCD, 0xBF,
+ 0x0F, 0xD8, 0x20, 0x1B, 0x8B, 0x79, 0xFB, 0x65, 0x08, 0xDA, 0x9A, 0x24, 0x16, 0x12, 0x73, 0x6F,
+ 0xE9, 0xB2, 0xF8, 0x41, 0x80, 0xA3, 0xF8, 0x20, 0x29, 0xDD, 0x9A, 0x26, 0xC6, 0x73, 0xBA, 0x90,
+ 0x41, 0x89, 0x6C, 0x62, 0x73, 0x3C, 0x21, 0x1E, 0x69, 0x3E, 0x97, 0x29, 0x2E, 0x66, 0x5F, 0xCC,
+ 0x61, 0xAF, 0x2C, 0x72, 0x9D, 0x5B, 0x37, 0xA5, 0x7B, 0xB5, 0xA8, 0xBC, 0x22, 0x80, 0x8B, 0x70,
+ 0x6F, 0x5E, 0x21, 0x64, 0xB4, 0x8F, 0x2F, 0x86, 0x83, 0x6E, 0xD2, 0x53, 0x5B, 0x5C, 0xA5, 0x4D,
+ 0x13, 0xA0, 0x88, 0xB5, 0x18, 0x56, 0xEC, 0xDB, 0x4E, 0x93, 0x1F, 0x1F, 0x7C, 0xF2, 0xE0, 0xE9,
+ 0x28, 0xC7, 0x1A, 0xC7, 0xA0, 0xA9, 0xE7, 0x17, 0x03, 0xC7, 0x77, 0x04, 0xC6, 0x69, 0x37, 0xAE,
+ 0x14, 0x80, 0xA3, 0x6D, 0x8C, 0x31, 0x50, 0x31, 0x9E, 0xE5, 0x01, 0x42, 0x1B, 0xB6, 0x4D, 0x75,
+ 0x2F, 0xA6, 0x5F, 0x3F, 0x70, 0xD7, 0x1F, 0x28, 0x21, 0xA9, 0x40, 0x74, 0x4D, 0x17, 0x07, 0x3A,
+ 0x78, 0xBF, 0xC5, 0xD3, 0xA4, 0xB8, 0x6C, 0x93, 0xEB, 0xA9, 0x1F, 0x70, 0xE5, 0x40, 0x63, 0x78,
+ 0xF6, 0x92, 0x39, 0x2E, 0x5D, 0x54, 0x90, 0xF6, 0x80, 0x96, 0xD2, 0xF1, 0xBD, 0x19, 0x1B, 0x0E,
+ 0xC2, 0x4D, 0x7F, 0x18, 0xAD, 0xF0, 0xF0, 0x57, 0xD6, 0x27, 0x0E, 0xDF, 0x09, 0x9B, 0xDA, 0x2F,
+ 0xA4, 0xC5, 0x5D, 0xA7, 0x49, 0x89, 0x4A, 0x4A, 0xCC, 0xBF, 0x7D, 0x1C, 0x07, 0xD8, 0xD0, 0x87,
+ 0x11, 0x33, 0x66, 0x6F, 0x19, 0x61, 0x39, 0x12, 0x13, 0x8F, 0x83, 0x49, 0xE2, 0x63, 0x63, 0x19,
+ 0xDB, 0x31, 0xFA, 0xE2, 0xD3, 0x6C, 0x0A, 0xC3, 0xD7, 0x6B, 0x70, 0x3E, 0xF0, 0xF6, 0xEB, 0xD6,
+ 0xFE, 0x5D, 0x1E, 0x3B, 0x4C, 0x5C, 0x91, 0xED, 0xA8, 0x12, 0x41, 0x07, 0x0A, 0x39, 0xB6, 0x84,
+ 0x7C, 0xE4, 0xE8, 0xE2, 0x0E, 0x73, 0xE9, 0x88, 0x69, 0x4A, 0x96, 0x60, 0xCF, 0xB7, 0x45, 0xCB,
+ 0x32, 0xD5, 0x04, 0x82, 0x68, 0x08, 0xD8, 0x22, 0x36, 0x95, 0xA8, 0xC6, 0xEC, 0x42, 0x34, 0x10,
+ 0xB4, 0xC7, 0x7D, 0x30, 0x83, 0xF6, 0x64, 0x1E, 0x9F, 0x4A, 0x18, 0x99, 0x00, 0x42, 0x67, 0xCA,
+ 0x59, 0xC2, 0x99, 0x19, 0xCE, 0x95, 0x91, 0x58, 0xC2, 0x99, 0x01, 0x41, 0x01, 0xE1, 0x7E, 0xD3,
+ 0xD2, 0x59, 0x03, 0x9D, 0x3B, 0x00, 0x3B, 0xEB, 0xD0, 0x87, 0x61, 0x70, 0x46, 0x82, 0x36, 0x40,
+ 0x4F, 0x12, 0xB7, 0x97, 0x84, 0xBE, 0x80, 0x90, 0xDF, 0x67, 0x67, 0xAC, 0x41, 0xD8, 0xCB, 0xD4,
+ 0x35, 0x6F, 0x3B, 0xC6, 0x7A, 0x4D, 0x1C, 0xF3, 0x62, 0x69, 0xD9, 0x66, 0x8B, 0x81, 0xC6, 0xD6,
+ 0x31, 0x30, 0x2C, 0x12, 0xBA, 0xF5, 0x8D, 0x63, 0x05, 0x6F, 0xBE, 0x60, 0xD7, 0x5A, 0x7B, 0x7D,
+ 0x53, 0xEC, 0x5C, 0xE4, 0xCD, 0x3A, 0xA6, 0x67, 0x5C, 0x7F, 0x83, 0xFB, 0xA2, 0xA9, 0x39, 0x1C,
+ 0x74, 0x0F, 0xBA, 0xBC, 0x41, 0x00, 0xE9, 0x96, 0x10, 0x39, 0xE2, 0xC5, 0xFD, 0xA3, 0x3F, 0x7E,
+ 0xFF, 0x6D, 0x84, 0x37, 0x70, 0x5F, 0xB3, 0x4B, 0xAD, 0x3D, 0xBA, 0xB1, 0xFA, 0xF0, 0xB7, 0x35,
+ 0xEE, 0x57, 0x11, 0xC3, 0x4C, 0x4C, 0x8C, 0xB8, 0x67, 0x1A, 0x45, 0xC5, 0x9A, 0x7F, 0x15, 0x47,
+ 0x0A, 0x97, 0x1D, 0x18, 0x27, 0xD0, 0xDC, 0x5B, 0x32, 0x50, 0xB1, 0xA3, 0x1A, 0xC1, 0x91, 0x93,
+ 0xAF, 0x61, 0xA2, 0xFA, 0x0B, 0x31, 0x3C, 0xD0, 0xC7, 0x73, 0xAD, 0xA5, 0x77, 0xF5, 0xE7, 0x2D,
+ 0x7A, 0xFD, 0x1D, 0xB0, 0xB3, 0x6C, 0xED, 0x3F, 0xEF, 0xED, 0xEF, 0x77, 0x7C, 0xD0, 0x19, 0x69,
+ 0xB5, 0xFB, 0xA2, 0x09, 0xFC, 0xA1, 0x6D, 0x58, 0x27, 0xD9, 0xF7, 0xDF, 0xBA, 0x1B, 0xCF, 0xCF,
+ 0x6B, 0xF0, 0xCE, 0x72, 0x70, 0x24, 0xCE, 0x6B, 0xF2, 0x01, 0xA6, 0x2F, 0x8E, 0xB9, 0xD5, 0x44,
+ 0xA7, 0x1B, 0xC1, 0xC5, 0x9C, 0x91, 0xEE, 0x8F, 0x85, 0xA4, 0x3F, 0x96, 0xEE, 0xF3, 0x8C, 0x93,
+ 0x60, 0xC5, 0xBB, 0x25, 0x96, 0xA5, 0xEE, 0xE2, 0xC6, 0x11, 0xE5, 0x74, 0xBC, 0x6A, 0xB0, 0xA5,
+ 0xFF, 0x54, 0xC0, 0xE2, 0x59, 0xD2, 0x56, 0x2D, 0x5C, 0x25, 0x11, 0x95, 0x66, 0x58, 0xB9, 0x19,
+ 0x69, 0xB2, 0x60, 0x9C, 0x9E, 0x2D, 0x27, 0xB3, 0xCF, 0x8B, 0x0D, 0xF8, 0xF8, 0x4A, 0x44, 0x54,
+ 0x76, 0x0D, 0xA7, 0x9C, 0x61, 0xE8, 0x87, 0x29, 0x68, 0xDE, 0x78, 0x04, 0xB7, 0x63, 0x23, 0x18,
+ 0x9F, 0xAF, 0x16, 0x00, 0xD0, 0x49, 0x6A, 0x38, 0x8A, 0x69, 0x08, 0xB5, 0x4D, 0xB6, 0x24, 0x44,
+ 0x40, 0xBB, 0xFD, 0x30, 0x62, 0x21, 0x10, 0x9F, 0x75, 0x45, 0xBA, 0xDB, 0x9E, 0x5D, 0xA7, 0x03,
+ 0xD6, 0xD6, 0xAC, 0xFA, 0x2E, 0xA6, 0x2D, 0xF1, 0x70, 0x4E, 0xC4, 0x0F, 0xC9, 0x67, 0x9E, 0xC4,
+ 0x99, 0x17, 0x55, 0x82, 0x02, 0x88, 0x4F, 0x34, 0xC7, 0x8F, 0xB3, 0x4F, 0x14, 0xD9, 0x27, 0x9C,
+ 0x7D, 0x04, 0x88, 0x26, 0x9C, 0xC5, 0x25, 0x8B, 0xD0, 0x18, 0x7F, 0x7A, 0x15, 0x71, 0x76, 0x3D,
+ 0xCD, 0xA5, 0x93, 0x97, 0x12, 0x62, 0xEC, 0xE5, 0x03, 0x40, 0xFB, 0x15, 0xF8, 0x43, 0x9C, 0xAD,
+ 0xEB, 0xA9, 0x1A, 0x5B, 0xA2, 0x14, 0x81, 0x00, 0x11, 0x5B, 0xF2, 0x82, 0x85, 0x60, 0xE5, 0x35,
+ 0x09, 0xF8, 0x23, 0x7C, 0x86, 0x63, 0x6A, 0x73, 0xCF, 0x58, 0x11, 0xFC, 0x62, 0x7B, 0x48, 0xAC,
+ 0x49, 0xEF, 0x17, 0xE6, 0x7E, 0xAC, 0x59, 0x8C, 0xC9, 0xB0, 0xE4, 0x51, 0x08, 0x1A, 0xB6, 0x8C,
+ 0x41, 0x87, 0x74, 0xE4, 0x42, 0x8B, 0x46, 0x2C, 0x83, 0x0B, 0x4F, 0x95, 0x84, 0x15, 0xB6, 0x8E,
+ 0x1C, 0x21, 0x42, 0x20, 0x4A, 0x26, 0xA3, 0x74, 0xA9, 0x8C, 0xCD, 0x24, 0x18, 0xB3, 0xA9, 0xF9,
+ 0x42, 0xBC, 0x41, 0xC8, 0x52, 0xA2, 0x4D, 0xE8, 0x20, 0x0C, 0x3E, 0x8B, 0xCC, 0x42, 0x52, 0xD8,
+ 0x42, 0xA2, 0xFE, 0xDE, 0x26, 0x58, 0x9E, 0xE0, 0x2F, 0x65, 0xBC, 0xF8, 0xE6, 0x6B, 0xCD, 0xF5,
+ 0x34, 0xDB, 0xBD, 0x26, 0xB8, 0x28, 0x28, 0x36, 0x90, 0x69, 0x53, 0x02, 0x01, 0x8E, 0xB0, 0x22,
+ 0x13, 0xEE, 0x8F, 0x09, 0x96, 0x96, 0x0F, 0x73, 0x62, 0x7C, 0x75, 0x28, 0x79, 0xAA, 0x87, 0xA3,
+ 0x53, 0x21, 0x7B, 0xDB, 0x25, 0xF4, 0x84, 0x38, 0x19, 0x4C, 0x24, 0xCB, 0xA7, 0x9C, 0xC7, 0xAD,
+ 0xC0, 0x92, 0x57, 0xD6, 0x2A, 0x21, 0xC2, 0xF0, 0xF6, 0xA3, 0x95, 0xA2, 0x9C, 0x81, 0x42, 0x41,
+ 0x86, 0x60, 0x91, 0x2C, 0x23, 0x5E, 0xB7, 0xA4, 0x29, 0xAB, 0x1D, 0xE6, 0x68, 0x14, 0x4B, 0xE1,
+ 0xD2, 0x68, 0x9E, 0xAD, 0x15, 0x26, 0x71, 0x36, 0xCA, 0xB1, 0xDF, 0xD9, 0xA1, 0x78, 0x14, 0x8A,
+ 0x9D, 0x61, 0xF6, 0x36, 0x79, 0x72, 0x76, 0xB8, 0x0C, 0x56, 0xF6, 0xE4, 0xC9, 0xFF, 0x02, 0x49,
+ 0x60, 0xC8, 0xA8, 0x55, 0x0C, 0x01, 0x00
+};
+
+
+//File: index_ov5640.html.gz, Size: 9124
+#define index_ov5640_html_gz_len 9124
+const uint8_t index_ov5640_html_gz[] = {
+ 0x1F, 0x8B, 0x08, 0x08, 0xD9, 0x6C, 0x6A, 0x5E, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F,
+ 0x6F, 0x76, 0x35, 0x36, 0x34, 0x30, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x00, 0xED, 0x3D, 0x6B, 0x77,
+ 0xDB, 0xB6, 0x92, 0xDF, 0xF3, 0x2B, 0x18, 0xF5, 0x6E, 0x24, 0x9F, 0x58, 0xB6, 0xA8, 0x97, 0x1F,
+ 0xB1, 0x95, 0x4D, 0x1C, 0x27, 0xE9, 0xB9, 0x4D, 0x6F, 0x1A, 0xA7, 0x69, 0x7B, 0xBA, 0x3D, 0x29,
+ 0x25, 0x41, 0x12, 0x1B, 0x8A, 0xD4, 0x25, 0x29, 0xCB, 0x6E, 0x8E, 0x7F, 0xC7, 0xFE, 0xA0, 0xFD,
+ 0x63, 0x3B, 0x03, 0x80, 0x24, 0x48, 0x81, 0x24, 0x48, 0x4A, 0xB2, 0xDB, 0x5D, 0xE5, 0x9C, 0x98,
+ 0x0F, 0xCC, 0x60, 0xDE, 0x18, 0x0C, 0x40, 0xF2, 0xEC, 0xF1, 0xD8, 0x19, 0xF9, 0xB7, 0x0B, 0xA2,
+ 0xCD, 0xFC, 0xB9, 0x35, 0x78, 0x74, 0xC6, 0xFE, 0x68, 0xF0, 0x3B, 0x9B, 0x11, 0x63, 0xCC, 0x0E,
+ 0xE9, 0xE9, 0x9C, 0xF8, 0x86, 0x36, 0x9A, 0x19, 0xAE, 0x47, 0xFC, 0xF3, 0xDA, 0xD2, 0x9F, 0x34,
+ 0x8F, 0x6B, 0xC9, 0xDB, 0xB6, 0x31, 0x27, 0xE7, 0xB5, 0x6B, 0x93, 0xAC, 0x16, 0x8E, 0xEB, 0xD7,
+ 0xB4, 0x91, 0x63, 0xFB, 0xC4, 0x86, 0xE6, 0x2B, 0x73, 0xEC, 0xCF, 0xCE, 0xC7, 0xE4, 0xDA, 0x1C,
+ 0x91, 0x26, 0x3D, 0xD9, 0x37, 0x6D, 0xD3, 0x37, 0x0D, 0xAB, 0xE9, 0x8D, 0x0C, 0x8B, 0x9C, 0xEB,
+ 0x22, 0x2E, 0xDF, 0xF4, 0x2D, 0x32, 0xB8, 0xBC, 0x7A, 0xDF, 0x69, 0x6B, 0xFF, 0xFA, 0xD4, 0xEB,
+ 0x77, 0x5B, 0x67, 0x87, 0xEC, 0x5A, 0xD4, 0xC6, 0xF3, 0x6F, 0xC5, 0x73, 0xFC, 0x0D, 0x9D, 0xF1,
+ 0xAD, 0xF6, 0x35, 0x76, 0x09, 0x7F, 0x13, 0x20, 0xA2, 0x39, 0x31, 0xE6, 0xA6, 0x75, 0x7B, 0xAA,
+ 0xBD, 0x70, 0xA1, 0xCF, 0xFD, 0xB7, 0xC4, 0xBA, 0x26, 0xBE, 0x39, 0x32, 0xF6, 0x3D, 0xC3, 0xF6,
+ 0x9A, 0x1E, 0x71, 0xCD, 0xC9, 0xB3, 0x35, 0xC0, 0xA1, 0x31, 0xFA, 0x32, 0x75, 0x9D, 0xA5, 0x3D,
+ 0x3E, 0xD5, 0xBE, 0xD1, 0x8F, 0xF1, 0xDF, 0x7A, 0xA3, 0x91, 0x63, 0x39, 0x2E, 0xDC, 0xBF, 0x7C,
+ 0x8D, 0xFF, 0xD6, 0xEF, 0xD3, 0xDE, 0x3D, 0xF3, 0x4F, 0x72, 0xAA, 0xE9, 0xFD, 0xC5, 0x4D, 0xEC,
+ 0xFE, 0xDD, 0xA3, 0xD8, 0xE9, 0xAC, 0x9D, 0x46, 0x3D, 0x87, 0x3F, 0xCE, 0x86, 0xF7, 0xC8, 0xC8,
+ 0x37, 0x1D, 0xFB, 0x60, 0x6E, 0x98, 0xB6, 0x04, 0xD3, 0xD8, 0xF4, 0x16, 0x96, 0x01, 0x32, 0x98,
+ 0x58, 0x24, 0x13, 0xCF, 0x37, 0x73, 0x62, 0x2F, 0xF7, 0x73, 0xB0, 0x21, 0x92, 0xE6, 0xD8, 0x74,
+ 0x59, 0xAB, 0x53, 0x94, 0xC3, 0x72, 0x6E, 0xE7, 0xA2, 0xCD, 0xA2, 0xCB, 0x76, 0x6C, 0x22, 0x11,
+ 0x20, 0x76, 0xB4, 0x72, 0x8D, 0x05, 0x36, 0xC0, 0xBF, 0xEB, 0x4D, 0xE6, 0xA6, 0xCD, 0x8C, 0xEA,
+ 0x54, 0xEB, 0x74, 0x5B, 0x8B, 0x9B, 0x1C, 0x55, 0x76, 0xFA, 0xF8, 0x6F, 0xBD, 0xD1, 0xC2, 0x18,
+ 0x8F, 0x4D, 0x7B, 0x7A, 0xAA, 0x1D, 0x4B, 0x51, 0x38, 0xEE, 0x98, 0xB8, 0x4D, 0xD7, 0x18, 0x9B,
+ 0x4B, 0xEF, 0x54, 0xEB, 0xCA, 0xDA, 0xCC, 0x0D, 0x77, 0x0A, 0xB4, 0xF8, 0x0E, 0x10, 0xDB, 0xD4,
+ 0xA5, 0x94, 0xF0, 0x26, 0xAE, 0x39, 0x9D, 0xF9, 0xA0, 0xD2, 0xB5, 0x36, 0x49, 0xA1, 0x71, 0x17,
+ 0xCA, 0xD3, 0x67, 0xA6, 0xDC, 0xE4, 0x52, 0x33, 0x2C, 0x73, 0x6A, 0x37, 0x4D, 0x9F, 0xCC, 0x81,
+ 0x1D, 0xCF, 0x77, 0x89, 0x3F, 0x9A, 0x65, 0x91, 0x32, 0x31, 0xA7, 0x4B, 0x97, 0x48, 0x08, 0x09,
+ 0xE5, 0x96, 0xC1, 0x30, 0xDC, 0x5C, 0xBF, 0xD5, 0x5C, 0x91, 0xE1, 0x17, 0xD3, 0x6F, 0x72, 0x99,
+ 0x0C, 0xC9, 0xC4, 0x71, 0x89, 0xB4, 0x65, 0xD0, 0xC2, 0x72, 0x46, 0x5F, 0x9A, 0x9E, 0x6F, 0xB8,
+ 0xBE, 0x0A, 0x42, 0x63, 0xE2, 0x13, 0x37, 0x1F, 0x1F, 0x41, 0xAB, 0xC8, 0xC7, 0x96, 0xDE, 0x2D,
+ 0x6F, 0x60, 0xDA, 0x96, 0x69, 0x13, 0x75, 0xF2, 0xD2, 0xFA, 0x8D, 0xA3, 0x63, 0xAD, 0x14, 0x14,
+ 0x63, 0xCE, 0xA7, 0x59, 0x56, 0x42, 0x79, 0x5D, 0xEF, 0x8C, 0xFB, 0x8D, 0xDE, 0x6A, 0xFD, 0xC7,
+ 0xFA, 0xCD, 0x19, 0x61, 0x66, 0x6A, 0x2C, 0x7D, 0xA7, 0xBA, 0x47, 0xAC, 0xB9, 0x55, 0x82, 0x8F,
+ 0xFF, 0x9C, 0x93, 0xB1, 0x69, 0x68, 0x0D, 0xC1, 0x9D, 0x8F, 0x5B, 0x60, 0x53, 0x7B, 0x9A, 0x61,
+ 0x8F, 0xB5, 0x86, 0xE3, 0x9A, 0xE0, 0x08, 0x06, 0x0D, 0x37, 0x16, 0x5C, 0x81, 0x81, 0x63, 0x41,
+ 0xF6, 0x24, 0x2C, 0x67, 0xF8, 0x8C, 0x28, 0x11, 0xB9, 0xDB, 0xE0, 0x4F, 0x21, 0xE4, 0xE0, 0x2F,
+ 0xD7, 0x81, 0x24, 0x3C, 0x52, 0xF4, 0x59, 0xFA, 0x12, 0x29, 0x4C, 0xD3, 0x19, 0xFE, 0xE6, 0xC6,
+ 0x4D, 0x33, 0x53, 0x77, 0x41, 0xA3, 0x40, 0x87, 0x30, 0xCC, 0x8E, 0x1A, 0xD0, 0xF4, 0x7A, 0xA6,
+ 0x35, 0x35, 0x8C, 0x92, 0x7B, 0x72, 0x18, 0x8E, 0x54, 0xAE, 0x72, 0xFC, 0x89, 0x46, 0x51, 0x80,
+ 0x5D, 0x39, 0xAB, 0x51, 0xEC, 0x60, 0xFF, 0x64, 0x36, 0xC4, 0x38, 0x49, 0x8D, 0x22, 0xF8, 0x53,
+ 0x8F, 0x24, 0x11, 0xB2, 0xDC, 0x68, 0x22, 0x41, 0x9C, 0x1E, 0x51, 0xD6, 0xF0, 0xA6, 0x79, 0xB7,
+ 0x04, 0x6B, 0x36, 0x09, 0xAA, 0xD1, 0x45, 0x82, 0x38, 0x8B, 0x86, 0xDC, 0x28, 0x83, 0xBF, 0x3B,
+ 0x85, 0x7C, 0xE3, 0x9B, 0xE1, 0xD2, 0xF7, 0x1D, 0xDB, 0xAB, 0x34, 0x44, 0xA5, 0xF9, 0xD9, 0x1F,
+ 0x4B, 0xCF, 0x37, 0x27, 0xB7, 0x4D, 0xEE, 0xD2, 0xE0, 0x67, 0x0B, 0x03, 0x52, 0xC8, 0x21, 0xF1,
+ 0x57, 0x84, 0x64, 0xA7, 0x1B, 0xB6, 0x71, 0x0D, 0x71, 0x67, 0x3A, 0xB5, 0x64, 0xB6, 0x37, 0x5A,
+ 0xBA, 0x1E, 0xE6, 0x6D, 0x0B, 0xC7, 0x04, 0xC4, 0xEE, 0x7A, 0xC7, 0x71, 0x1F, 0x54, 0xEC, 0xA8,
+ 0x39, 0x1A, 0x4A, 0xFA, 0x72, 0x96, 0x3E, 0xCA, 0x58, 0xAA, 0x09, 0x07, 0xD8, 0x31, 0xFD, 0x5B,
+ 0xE9, 0x3D, 0xEE, 0x89, 0x92, 0x3B, 0x81, 0x0B, 0x66, 0x0E, 0x0B, 0x71, 0xBA, 0x4E, 0x47, 0x33,
+ 0x32, 0xFA, 0x42, 0xC6, 0x4F, 0x73, 0xD3, 0xB0, 0xBC, 0xF4, 0xF0, 0xC0, 0xB4, 0x17, 0x4B, 0xBF,
+ 0x89, 0xE9, 0xD4, 0x62, 0x2B, 0x3A, 0xA7, 0x06, 0x19, 0xB0, 0xD8, 0x6E, 0x67, 0x25, 0x15, 0xBD,
+ 0xC5, 0x4D, 0xB6, 0x10, 0x44, 0x62, 0x07, 0x96, 0x31, 0x24, 0x56, 0x16, 0xC9, 0xDC, 0x19, 0x52,
+ 0xC2, 0x2E, 0x8F, 0x55, 0xE9, 0xB9, 0x1B, 0xA5, 0x2C, 0x1A, 0xBC, 0xBA, 0x47, 0xFF, 0xA1, 0x2C,
+ 0x47, 0x7A, 0xBC, 0x1F, 0xBB, 0xE4, 0x11, 0x0B, 0x1C, 0x2C, 0x71, 0x6D, 0x61, 0xA4, 0x26, 0xE3,
+ 0xD0, 0x62, 0x05, 0x54, 0x65, 0x76, 0xE9, 0x1A, 0xF6, 0x94, 0x40, 0x74, 0xB8, 0xD9, 0x0F, 0x0E,
+ 0xB3, 0xA7, 0x0A, 0x4A, 0x02, 0xC1, 0xE0, 0xDD, 0xCB, 0x9E, 0x9A, 0xB0, 0x10, 0xB1, 0xAF, 0x1D,
+ 0xB0, 0x83, 0x12, 0x79, 0x8A, 0xA0, 0xF1, 0x4C, 0x42, 0x74, 0xA9, 0xBD, 0xB0, 0x54, 0x45, 0xEA,
+ 0x4B, 0x71, 0x6B, 0x93, 0xA6, 0xFE, 0xB9, 0xC1, 0x22, 0x98, 0x04, 0x4E, 0x26, 0x79, 0xD3, 0xC8,
+ 0xC9, 0xA4, 0xD3, 0xEA, 0x74, 0x73, 0x73, 0x29, 0x29, 0x97, 0x89, 0xA9, 0xA4, 0x24, 0x98, 0x84,
+ 0x81, 0x26, 0x5F, 0x17, 0xA7, 0x33, 0xE7, 0x9A, 0xB8, 0x12, 0x45, 0x24, 0xC8, 0xED, 0x9E, 0x74,
+ 0xC7, 0x0A, 0xD8, 0x0C, 0x18, 0x0A, 0xAE, 0x65, 0x81, 0x36, 0x8E, 0xAE, 0xAD, 0x8F, 0xDA, 0x99,
+ 0x16, 0xCA, 0xD0, 0x1D, 0x80, 0x35, 0x18, 0x43, 0x8B, 0x8C, 0x33, 0x22, 0xF7, 0x98, 0x4C, 0x8C,
+ 0xA5, 0xE5, 0xE7, 0xC8, 0xDB, 0x68, 0xE1, 0xBF, 0xAC, 0x1E, 0xA9, 0x7B, 0xFD, 0x8A, 0x35, 0x90,
+ 0x73, 0xEA, 0x12, 0xBF, 0x49, 0xFA, 0x0C, 0x86, 0x55, 0x63, 0xB1, 0x20, 0x06, 0xB4, 0x1A, 0x91,
+ 0xB4, 0xD9, 0xAA, 0x52, 0x3A, 0x2D, 0x8F, 0x69, 0x4A, 0x73, 0xD4, 0x5C, 0x53, 0x0C, 0x13, 0xA5,
+ 0x42, 0x3C, 0x9F, 0x4E, 0x9C, 0xD1, 0x52, 0x36, 0x82, 0xAB, 0x99, 0xD4, 0x3A, 0xBE, 0xD3, 0x40,
+ 0x64, 0x9E, 0x65, 0x52, 0xC3, 0x5E, 0xDA, 0x36, 0x6A, 0xB4, 0xE9, 0xBB, 0xC0, 0xA6, 0xA4, 0x23,
+ 0x35, 0xC1, 0x95, 0xF2, 0xCE, 0x98, 0x60, 0xD3, 0xEA, 0x34, 0x09, 0x07, 0x94, 0x04, 0x8A, 0x30,
+ 0x86, 0x68, 0x9E, 0x03, 0x4C, 0x05, 0xA8, 0xAA, 0xC9, 0xC5, 0x9F, 0x2D, 0xE7, 0xB2, 0x9C, 0x21,
+ 0xE8, 0x4C, 0x87, 0x01, 0x8E, 0x75, 0xE7, 0x4E, 0x87, 0x46, 0xA3, 0xB5, 0xDF, 0xDA, 0xEF, 0xC0,
+ 0x7F, 0x92, 0xDC, 0x3D, 0xDB, 0xB8, 0xB8, 0x78, 0x53, 0x2C, 0x2F, 0x11, 0x7C, 0xF2, 0x4B, 0x28,
+ 0x69, 0x61, 0x2C, 0x57, 0x17, 0xEA, 0x9E, 0x14, 0xAF, 0xA5, 0xE8, 0x07, 0x39, 0x23, 0x4C, 0x8A,
+ 0x49, 0x17, 0x37, 0x44, 0x89, 0xB5, 0x14, 0x55, 0xF1, 0xDC, 0xF9, 0xB3, 0xC9, 0x86, 0xD7, 0xFF,
+ 0xF3, 0xD6, 0x2E, 0x88, 0xE2, 0x6F, 0x6D, 0xE9, 0x85, 0xE5, 0xE2, 0xDD, 0xB7, 0x6D, 0xB4, 0xD2,
+ 0xB5, 0xDE, 0xE4, 0xF9, 0x0C, 0x50, 0x68, 0x43, 0xC6, 0xE9, 0xC2, 0xC4, 0x2B, 0x35, 0xE7, 0x11,
+ 0xDA, 0x94, 0x90, 0xC1, 0xC4, 0xB4, 0xAC, 0xA6, 0xE5, 0xAC, 0xF2, 0x33, 0x91, 0x6C, 0x4B, 0x5E,
+ 0xB3, 0xD3, 0x7C, 0x93, 0x2F, 0x4B, 0xED, 0x12, 0x22, 0xD7, 0x5F, 0x82, 0xDA, 0xBF, 0xB7, 0xC3,
+ 0x65, 0xBA, 0x46, 0xB9, 0x81, 0xA2, 0x84, 0x3D, 0x56, 0xEB, 0x48, 0xC9, 0x94, 0x58, 0x26, 0x98,
+ 0x39, 0xAB, 0xF3, 0x56, 0xA6, 0x3F, 0x9A, 0x95, 0x98, 0x54, 0x2D, 0x1C, 0xCF, 0x64, 0xCB, 0x37,
+ 0x2E, 0xB1, 0x0C, 0xCC, 0xE0, 0x4B, 0xCD, 0xC6, 0x73, 0x27, 0x26, 0x22, 0xB8, 0x0A, 0x27, 0x54,
+ 0x74, 0x0F, 0xA7, 0x92, 0x72, 0xC0, 0x72, 0x87, 0xF4, 0x58, 0x2D, 0x37, 0xEB, 0x9C, 0x74, 0x3F,
+ 0xEE, 0x19, 0xF2, 0x46, 0x05, 0x22, 0x7A, 0x10, 0xB4, 0xA7, 0x2E, 0xB9, 0x55, 0x60, 0x66, 0x9F,
+ 0xFF, 0x3D, 0x65, 0xB5, 0xD2, 0xF2, 0x45, 0x00, 0x3A, 0x00, 0x70, 0x2B, 0x3A, 0xE8, 0x7A, 0x0A,
+ 0x5D, 0xA7, 0x77, 0xA9, 0x62, 0x8F, 0x61, 0x25, 0xB0, 0x56, 0x53, 0x08, 0x37, 0x19, 0x43, 0xA8,
+ 0xDC, 0x54, 0x83, 0xD1, 0x57, 0x7A, 0xD3, 0x22, 0x13, 0x3F, 0x65, 0xA1, 0x83, 0xE6, 0xA9, 0x9D,
+ 0xEC, 0xE8, 0xD6, 0x14, 0xEA, 0x04, 0xB9, 0x91, 0x23, 0x2C, 0xD8, 0xA5, 0x5B, 0x9F, 0x14, 0x33,
+ 0x46, 0xCF, 0xC2, 0xC8, 0xD3, 0x55, 0x12, 0xA4, 0xCF, 0x54, 0xCD, 0xD0, 0x66, 0xCE, 0x87, 0x7C,
+ 0x50, 0x0F, 0xF9, 0xB9, 0xD1, 0xEE, 0x4B, 0xD7, 0x11, 0x32, 0x1A, 0x67, 0x91, 0xC6, 0x2A, 0x5E,
+ 0x4A, 0x43, 0x56, 0xEA, 0x04, 0x59, 0x8C, 0x45, 0x52, 0x45, 0x65, 0x7B, 0x65, 0x56, 0x84, 0x59,
+ 0xAF, 0xD1, 0x64, 0x1A, 0xBB, 0x39, 0x37, 0x20, 0xED, 0x45, 0x73, 0x35, 0x00, 0xA3, 0x4C, 0x7F,
+ 0x2A, 0xE6, 0x2E, 0xD4, 0x13, 0xF5, 0x7E, 0x2B, 0xA7, 0xCB, 0x91, 0xE5, 0x78, 0xD9, 0x7E, 0x65,
+ 0x0C, 0x41, 0x7E, 0x4B, 0x5F, 0xD2, 0x11, 0xAF, 0x6A, 0x4A, 0x2B, 0x4F, 0xD4, 0xB8, 0xA5, 0x77,
+ 0x94, 0x86, 0xEE, 0x4C, 0x9F, 0xCA, 0x76, 0xC7, 0x84, 0xCC, 0xF5, 0x96, 0x34, 0xD2, 0x66, 0xD6,
+ 0xDF, 0x7C, 0x72, 0x03, 0xF3, 0x4D, 0x5C, 0xAB, 0x3B, 0xD5, 0x46, 0x44, 0x1E, 0x46, 0x63, 0x83,
+ 0x9C, 0xAE, 0x52, 0x04, 0xCC, 0xD4, 0xC3, 0xCC, 0x1C, 0x8F, 0x49, 0x66, 0x95, 0x13, 0xE7, 0xBC,
+ 0xD9, 0xA1, 0xD2, 0x90, 0x96, 0xD3, 0x0A, 0x68, 0xB2, 0x9D, 0xAE, 0xCA, 0xCC, 0xE1, 0x2A, 0x25,
+ 0xF4, 0xC5, 0x24, 0x24, 0x6D, 0x22, 0x54, 0x61, 0xE5, 0x21, 0x12, 0x15, 0x31, 0x26, 0x23, 0xC7,
+ 0x65, 0x8B, 0xB8, 0x29, 0x13, 0xFF, 0x72, 0x33, 0x2B, 0x44, 0x2E, 0x2B, 0xDD, 0x6D, 0x25, 0x74,
+ 0x64, 0x6E, 0x74, 0xD0, 0xB7, 0x1D, 0x57, 0xF8, 0x70, 0x9C, 0x56, 0x49, 0x8F, 0x27, 0x6C, 0x99,
+ 0xA4, 0x4A, 0x43, 0x60, 0xA8, 0x46, 0x14, 0x19, 0xC8, 0x01, 0x5B, 0xAD, 0x2B, 0x34, 0x41, 0x15,
+ 0x5D, 0x5A, 0x39, 0xE0, 0xAB, 0x4D, 0x7C, 0x61, 0xB0, 0x99, 0xB6, 0xDE, 0xB2, 0xC1, 0xC5, 0x37,
+ 0x6A, 0x01, 0xC9, 0x7E, 0x53, 0x45, 0x73, 0x4F, 0xF9, 0x63, 0x06, 0x91, 0xE1, 0x40, 0x1C, 0x6C,
+ 0xB7, 0x8A, 0xB7, 0x2A, 0x1B, 0x42, 0xCE, 0x0E, 0x85, 0xFD, 0x71, 0x67, 0x87, 0xD1, 0x56, 0xBE,
+ 0x33, 0xDC, 0x24, 0x27, 0x6E, 0xA3, 0xE3, 0xFD, 0x8C, 0x2C, 0xC3, 0xF3, 0xCE, 0x6B, 0xB8, 0xD9,
+ 0xAB, 0x16, 0xDF, 0x55, 0x77, 0x36, 0x36, 0xAF, 0x35, 0x73, 0x7C, 0x5E, 0xB3, 0x9C, 0xA9, 0x93,
+ 0xB8, 0x47, 0xEF, 0x33, 0x2D, 0xC3, 0x68, 0x7F, 0x5E, 0x8B, 0xAD, 0x38, 0xD6, 0x28, 0x54, 0x74,
+ 0xA9, 0x36, 0x78, 0xF2, 0xCD, 0xC9, 0xD1, 0x51, 0xFF, 0xD9, 0x13, 0x7B, 0xE8, 0x2D, 0xF8, 0xFF,
+ 0x1F, 0xD9, 0x02, 0xAD, 0x47, 0x7C, 0x1F, 0x6C, 0xCE, 0x3B, 0x3B, 0xA4, 0xD8, 0x12, 0x14, 0x1C,
+ 0x02, 0x09, 0x29, 0x44, 0xF1, 0x6C, 0x50, 0x46, 0x57, 0xD0, 0xC4, 0x83, 0x04, 0x67, 0x68, 0xB8,
+ 0x92, 0x26, 0xB4, 0x19, 0x9B, 0x6B, 0xD0, 0x18, 0x52, 0xA3, 0xCA, 0x18, 0x3A, 0x37, 0x49, 0xD2,
+ 0x29, 0x37, 0x5C, 0x53, 0xBC, 0x15, 0x19, 0xA7, 0x21, 0x04, 0x30, 0x0A, 0x8E, 0xEB, 0xAC, 0xD0,
+ 0x46, 0xDA, 0x28, 0x26, 0x7B, 0x6C, 0x7C, 0x33, 0xB2, 0xBE, 0x04, 0x4A, 0xAF, 0x05, 0xDA, 0xB0,
+ 0x1D, 0x9F, 0x8D, 0x24, 0x29, 0x5D, 0xC5, 0x58, 0xE5, 0x30, 0xC2, 0x6A, 0x21, 0xE3, 0x02, 0x44,
+ 0xDB, 0xA4, 0xD8, 0xD9, 0xB5, 0x6C, 0x4C, 0x14, 0x9B, 0xA0, 0xD0, 0x00, 0xB8, 0x36, 0xF8, 0xF9,
+ 0xE2, 0xBB, 0x7F, 0x6A, 0xEF, 0xDE, 0xFE, 0x29, 0xD5, 0x50, 0x1E, 0x51, 0x18, 0x9C, 0x15, 0x7A,
+ 0xA6, 0x60, 0x4C, 0x1F, 0x81, 0x4C, 0x6A, 0x5C, 0x33, 0x14, 0x03, 0x26, 0x43, 0x16, 0xB1, 0xA7,
+ 0xFE, 0xEC, 0xBC, 0xA6, 0xD7, 0x70, 0x77, 0x4B, 0x70, 0xD6, 0xAE, 0x69, 0x18, 0xB8, 0xE9, 0xC1,
+ 0xB5, 0x61, 0x2D, 0xF1, 0xA8, 0xA5, 0xC2, 0xEB, 0xBA, 0x69, 0x49, 0x9B, 0xF1, 0x88, 0x12, 0xCA,
+ 0x58, 0x88, 0xC0, 0x71, 0x29, 0xD7, 0x06, 0x57, 0xC4, 0x3F, 0x3B, 0x64, 0xB7, 0x72, 0xB4, 0x96,
+ 0xDD, 0x37, 0xB8, 0x30, 0x33, 0x87, 0x2C, 0x13, 0xCA, 0x52, 0xFC, 0xC4, 0x35, 0xE6, 0x04, 0xA5,
+ 0xA2, 0xA4, 0x79, 0x51, 0xEB, 0x21, 0x64, 0x6D, 0xF0, 0x81, 0xD0, 0x2C, 0x03, 0xC8, 0x50, 0x52,
+ 0xFC, 0x19, 0x4F, 0xE1, 0x63, 0xFD, 0x87, 0xF6, 0xCC, 0x97, 0xEC, 0x9A, 0x06, 0x33, 0x73, 0x05,
+ 0xB9, 0x3F, 0x6E, 0x36, 0xB5, 0xDE, 0xBB, 0xF7, 0x5A, 0xB3, 0xA9, 0xD0, 0xD8, 0x59, 0x50, 0x77,
+ 0x0A, 0xF4, 0x0F, 0x16, 0xC2, 0xA8, 0x21, 0x54, 0x3F, 0xEC, 0xA8, 0x36, 0xF8, 0xE1, 0xEA, 0xE7,
+ 0x37, 0x2F, 0x1A, 0xED, 0x5E, 0xBF, 0x75, 0xA3, 0x9F, 0xB4, 0x5B, 0x7B, 0x67, 0x87, 0x0C, 0xAE,
+ 0x78, 0x07, 0x60, 0x60, 0xEF, 0xB5, 0xD7, 0x6F, 0x5F, 0x35, 0xF4, 0xD6, 0x71, 0x55, 0x64, 0xFA,
+ 0x49, 0x6D, 0xF0, 0xD3, 0x0F, 0x11, 0x65, 0xFD, 0x56, 0x15, 0x64, 0xC7, 0xC0, 0x26, 0xD0, 0xC5,
+ 0x50, 0x75, 0xBB, 0x85, 0x50, 0xA1, 0xC8, 0x3B, 0xE5, 0x44, 0xAE, 0x1F, 0x41, 0xBF, 0x94, 0x87,
+ 0x56, 0xF7, 0xF8, 0x46, 0xEF, 0xF5, 0xBB, 0x15, 0x78, 0xE8, 0xA3, 0x74, 0x81, 0x90, 0xC6, 0x71,
+ 0xBF, 0x5B, 0x15, 0x57, 0x0F, 0x71, 0x81, 0x40, 0x8E, 0xDA, 0x20, 0x8F, 0xF6, 0x71, 0x15, 0xD1,
+ 0x76, 0x6B, 0x03, 0xAA, 0xF2, 0x13, 0x44, 0xD5, 0x2A, 0x86, 0x0A, 0x45, 0xDB, 0x2E, 0x29, 0xDA,
+ 0x4E, 0x6D, 0xF0, 0x23, 0x8A, 0x16, 0x2D, 0x03, 0x78, 0xA8, 0x64, 0x1E, 0x6D, 0x88, 0x52, 0x14,
+ 0x57, 0x1B, 0xED, 0xB6, 0xD5, 0xAE, 0x22, 0x5A, 0xBD, 0x36, 0x40, 0x71, 0x20, 0xA6, 0xA3, 0x4A,
+ 0x0E, 0x00, 0xDE, 0x44, 0x69, 0x02, 0x72, 0x6E, 0x8E, 0xFA, 0xC7, 0xE5, 0x31, 0x81, 0x27, 0x5D,
+ 0x7D, 0x02, 0x4C, 0xC7, 0x20, 0xA8, 0x4A, 0x6E, 0x04, 0x5E, 0x84, 0x78, 0xFA, 0xDD, 0xD6, 0x4D,
+ 0xB7, 0x8A, 0xCD, 0x80, 0x57, 0xBC, 0x45, 0x44, 0x80, 0xE4, 0xA6, 0x53, 0x45, 0x46, 0xE0, 0x12,
+ 0x17, 0xDF, 0xBE, 0x6E, 0x74, 0x81, 0xB1, 0xF6, 0x49, 0xBF, 0x3C, 0x1E, 0x70, 0x87, 0x1F, 0x90,
+ 0x20, 0x20, 0xE6, 0xA6, 0x5D, 0x2C, 0x3A, 0xC4, 0x11, 0x81, 0x33, 0x00, 0x3C, 0xE2, 0x28, 0x8D,
+ 0x02, 0xEC, 0xFA, 0x2D, 0x25, 0x06, 0x11, 0xE9, 0x47, 0x15, 0xB8, 0x02, 0xAB, 0xFE, 0x01, 0xC5,
+ 0x03, 0x48, 0x30, 0xE8, 0x55, 0x30, 0x45, 0x40, 0x44, 0x49, 0xD2, 0xFB, 0xD4, 0xD5, 0xCA, 0x63,
+ 0x02, 0x9B, 0x3E, 0xE9, 0xDF, 0x9C, 0xF4, 0xD5, 0x10, 0xE0, 0x88, 0x8F, 0xA3, 0x54, 0x56, 0x4E,
+ 0x90, 0x9D, 0x32, 0x64, 0xA5, 0x03, 0xFF, 0x5E, 0x1A, 0x16, 0xCC, 0x6F, 0x0A, 0x27, 0x03, 0x1C,
+ 0x0E, 0x64, 0xC2, 0x0E, 0xD4, 0xF2, 0x00, 0x81, 0x92, 0x70, 0xA3, 0x59, 0x6D, 0xD0, 0x55, 0xC8,
+ 0xB7, 0x62, 0x09, 0x39, 0x85, 0x8D, 0xD1, 0x4F, 0x93, 0x40, 0xB4, 0x3C, 0x4C, 0xFF, 0xC0, 0x25,
+ 0x3A, 0x35, 0x21, 0x82, 0x94, 0x4A, 0x34, 0x24, 0xB4, 0x1A, 0x37, 0xB5, 0x41, 0xBF, 0x93, 0x9B,
+ 0xA0, 0x95, 0x57, 0xC6, 0x90, 0xD6, 0x68, 0x6C, 0xE2, 0x79, 0x85, 0xF5, 0x11, 0x81, 0xD6, 0x06,
+ 0x2F, 0xC3, 0xE3, 0x2A, 0x5A, 0x69, 0xE6, 0x71, 0x4A, 0x61, 0x53, 0xD4, 0x22, 0x90, 0xC3, 0x34,
+ 0xD3, 0xEC, 0x70, 0xD5, 0x44, 0x9A, 0xD9, 0xAC, 0x62, 0xB6, 0xA9, 0x17, 0x9C, 0x4E, 0xBA, 0x86,
+ 0xE7, 0x17, 0xD6, 0x4A, 0x00, 0x08, 0x11, 0x9A, 0x1F, 0xDD, 0x9B, 0x46, 0x42, 0x52, 0xFE, 0x06,
+ 0xFA, 0xF0, 0x0C, 0x7F, 0xC9, 0xAA, 0x85, 0x85, 0x35, 0x12, 0x81, 0x42, 0x3E, 0x10, 0x1E, 0x57,
+ 0xD2, 0x4A, 0x95, 0xF0, 0x25, 0x90, 0xC3, 0xF5, 0x12, 0x84, 0xB0, 0xEE, 0x96, 0xF4, 0x92, 0x47,
+ 0x6D, 0x25, 0xBD, 0xCC, 0x0C, 0x77, 0x51, 0x2A, 0x7C, 0x85, 0x90, 0xA0, 0x95, 0xE0, 0xF0, 0xDE,
+ 0x5C, 0x25, 0x22, 0xE6, 0x6F, 0xE0, 0x2B, 0x63, 0x62, 0x3B, 0xA6, 0x57, 0x7C, 0xB6, 0xCF, 0xE1,
+ 0x6A, 0x83, 0x57, 0xA4, 0xF9, 0x3D, 0x1E, 0x55, 0x51, 0xC7, 0x8B, 0xA5, 0xEF, 0x54, 0x50, 0x48,
+ 0x40, 0x0B, 0x53, 0x47, 0x8B, 0x6B, 0xE3, 0x78, 0x4B, 0xDA, 0x38, 0xDE, 0xA2, 0x36, 0x0C, 0xF2,
+ 0xD9, 0x22, 0xD7, 0xC4, 0x2A, 0xAC, 0x8E, 0x00, 0xB0, 0x36, 0xB8, 0xBC, 0x59, 0x38, 0x1E, 0x3E,
+ 0x3A, 0xF5, 0x1D, 0x9E, 0x57, 0x72, 0x92, 0x5E, 0x05, 0x9D, 0x84, 0x04, 0x71, 0x1F, 0xE9, 0x71,
+ 0xAD, 0xF4, 0xB6, 0xA4, 0x95, 0x3C, 0x5A, 0xAB, 0x68, 0x65, 0x6A, 0x98, 0xF6, 0x88, 0x98, 0x16,
+ 0x3E, 0xC6, 0x51, 0x54, 0x31, 0x02, 0x6C, 0x6D, 0xF0, 0x26, 0x3A, 0xA9, 0xA2, 0x98, 0x56, 0x05,
+ 0xBD, 0x88, 0xF4, 0xC4, 0xFD, 0xA5, 0x07, 0xB3, 0xF2, 0x2D, 0xE9, 0x46, 0xD7, 0xB7, 0x39, 0xAA,
+ 0x2C, 0xC8, 0xC8, 0x34, 0xAC, 0xCF, 0x64, 0x32, 0x81, 0x69, 0x50, 0xF1, 0xA1, 0x25, 0x06, 0x0E,
+ 0xE3, 0x0B, 0x3B, 0xD7, 0x2E, 0xE9, 0x79, 0xE1, 0xFA, 0x65, 0x02, 0x5D, 0xF9, 0x22, 0x66, 0x72,
+ 0x4E, 0x28, 0x2D, 0x4B, 0x7E, 0xEF, 0x84, 0x74, 0x96, 0x9F, 0xB6, 0x7E, 0x4F, 0xA6, 0x74, 0x1B,
+ 0x41, 0x95, 0x39, 0xF4, 0x1B, 0xD7, 0xB8, 0xA5, 0xEF, 0x64, 0xA8, 0x32, 0xA5, 0xFF, 0x40, 0xC6,
+ 0xDA, 0x47, 0xD3, 0x2E, 0xCF, 0x4C, 0x17, 0x09, 0x21, 0xC4, 0xAE, 0x86, 0xA5, 0x07, 0x53, 0x24,
+ 0x38, 0xA8, 0x86, 0xA4, 0x8F, 0x35, 0xFD, 0x85, 0x69, 0x3C, 0x84, 0x49, 0xBC, 0xB1, 0x1A, 0x16,
+ 0x1F, 0x50, 0x56, 0x43, 0x18, 0x97, 0x7F, 0x7A, 0xA9, 0x5D, 0xD2, 0x8D, 0xEF, 0x85, 0xC3, 0x15,
+ 0xDB, 0x93, 0xA7, 0x62, 0xE8, 0xD1, 0xD2, 0x0D, 0xF6, 0xB9, 0xB6, 0xA6, 0x26, 0x77, 0x20, 0xD5,
+ 0x75, 0x35, 0x09, 0x7B, 0x01, 0x81, 0x74, 0x0B, 0x53, 0x4D, 0xE0, 0x56, 0x8D, 0xC7, 0x2D, 0xA6,
+ 0x62, 0xA3, 0x55, 0xF1, 0x34, 0x6C, 0xB4, 0x02, 0x35, 0x8D, 0xAF, 0xF1, 0x99, 0x88, 0xB1, 0x06,
+ 0xFA, 0xDA, 0x89, 0xA2, 0xB0, 0xD7, 0xFB, 0x51, 0x14, 0xE5, 0xF7, 0xBE, 0x15, 0x05, 0xD6, 0xF2,
+ 0x19, 0xC7, 0xD1, 0x32, 0x4E, 0x45, 0x01, 0x6B, 0x83, 0x77, 0x86, 0xBD, 0x84, 0x41, 0x66, 0x57,
+ 0x0A, 0x0B, 0x3B, 0xBE, 0x37, 0xF7, 0xE2, 0x7C, 0xDF, 0xB7, 0xEA, 0x80, 0x90, 0xB9, 0x33, 0x2E,
+ 0x3E, 0xDD, 0xE1, 0x70, 0x2C, 0x24, 0xBE, 0x83, 0xA3, 0xC2, 0x89, 0x41, 0x80, 0x61, 0xCB, 0x19,
+ 0x01, 0x9B, 0x4A, 0x95, 0x4F, 0x06, 0xAE, 0x96, 0xB6, 0x7D, 0x5B, 0x25, 0x13, 0xB8, 0xB0, 0x9C,
+ 0xE5, 0xB8, 0x3C, 0x06, 0x48, 0x03, 0xFE, 0x35, 0x99, 0x98, 0xA3, 0xF2, 0x89, 0x04, 0x24, 0x01,
+ 0x6F, 0x9D, 0xB9, 0x22, 0xFC, 0x96, 0x07, 0x5E, 0x32, 0x2A, 0x31, 0x93, 0x1B, 0x81, 0x16, 0x2F,
+ 0x2F, 0x76, 0x3A, 0xF0, 0x42, 0x9F, 0xF7, 0x14, 0x19, 0x90, 0xDB, 0xFB, 0x0E, 0x0A, 0x40, 0xC4,
+ 0x67, 0x6A, 0x3C, 0x65, 0x94, 0xC5, 0x20, 0xC3, 0x88, 0x1E, 0x4C, 0xBF, 0xEF, 0x6B, 0x7E, 0x17,
+ 0x51, 0x14, 0x9F, 0xDD, 0xE1, 0xD2, 0x73, 0x38, 0xBD, 0xEB, 0xB4, 0x37, 0x3B, 0xC1, 0x43, 0xE4,
+ 0xDB, 0xD5, 0x4F, 0xBB, 0x8C, 0x6A, 0x20, 0x1A, 0x7D, 0x8F, 0xEB, 0x0C, 0x05, 0x02, 0x76, 0x75,
+ 0x47, 0x6A, 0xDF, 0x9F, 0x27, 0xB5, 0x1F, 0x80, 0x2B, 0x4D, 0x4B, 0x44, 0xBC, 0x29, 0x46, 0xBC,
+ 0x37, 0x17, 0xBB, 0xD1, 0xD0, 0xF4, 0xDE, 0x42, 0xDD, 0xF4, 0x5E, 0x43, 0x9D, 0xC6, 0x37, 0x05,
+ 0x06, 0x52, 0x28, 0x99, 0xC1, 0x72, 0x40, 0x56, 0xCB, 0xAA, 0x12, 0xE4, 0xF4, 0x9B, 0x2A, 0x51,
+ 0x2E, 0x20, 0x23, 0x1E, 0xE4, 0xFA, 0xD1, 0xAA, 0x48, 0x6F, 0xB3, 0xCB, 0xBA, 0xDD, 0x3C, 0x6A,
+ 0xAB, 0x38, 0x8D, 0x6B, 0xAC, 0x3E, 0x4F, 0xE7, 0x46, 0x61, 0x65, 0x70, 0x38, 0xD0, 0xC5, 0xBB,
+ 0x17, 0xBB, 0x4C, 0x17, 0x82, 0x7E, 0xEF, 0xC7, 0x8F, 0x42, 0xAE, 0xEF, 0x3B, 0xD6, 0x59, 0xC4,
+ 0x2E, 0x1E, 0xEC, 0x10, 0xA8, 0x36, 0xF8, 0x8E, 0xD8, 0x9E, 0x76, 0xE1, 0xB8, 0xFC, 0x45, 0x98,
+ 0x3B, 0xD1, 0x1A, 0xED, 0xF9, 0x7E, 0x54, 0xC6, 0x98, 0xBE, 0x6F, 0x7D, 0xCD, 0xE6, 0xA6, 0xEB,
+ 0x3A, 0x6E, 0x61, 0x95, 0x71, 0x38, 0x98, 0x56, 0x34, 0xDF, 0xD1, 0xA3, 0x9D, 0xA8, 0x2B, 0xE8,
+ 0xF5, 0x7E, 0x34, 0x16, 0xF2, 0x7C, 0xDF, 0x4A, 0xBB, 0x9E, 0x58, 0xE6, 0xA2, 0xB0, 0xCA, 0x28,
+ 0x54, 0x6D, 0xF0, 0xA9, 0xF9, 0x1A, 0xFE, 0xEE, 0x44, 0x5D, 0xAC, 0xC7, 0xFB, 0x51, 0x16, 0xE7,
+ 0xF6, 0xBE, 0x55, 0x35, 0x5C, 0x14, 0x0F, 0x87, 0x00, 0x53, 0x1B, 0xBC, 0x7C, 0xBF, 0x9B, 0xDC,
+ 0x0F, 0x3B, 0x53, 0xD4, 0x50, 0x25, 0x7D, 0x50, 0xA6, 0xEE, 0x5B, 0x1B, 0xAB, 0x12, 0xDA, 0x58,
+ 0x21, 0xE1, 0x3F, 0xED, 0x48, 0x1B, 0x2B, 0x75, 0x6D, 0x6C, 0xD8, 0x5F, 0x56, 0x0F, 0x41, 0x3F,
+ 0xF4, 0xE9, 0xD3, 0xA1, 0x51, 0x7C, 0x38, 0x0A, 0x00, 0x71, 0xD3, 0x18, 0x1C, 0x69, 0x2F, 0x8D,
+ 0xDD, 0x0C, 0x48, 0x61, 0xBF, 0xBB, 0x70, 0xA1, 0x88, 0xC9, 0xFB, 0xD6, 0xD3, 0xC4, 0x18, 0x91,
+ 0xCF, 0x63, 0xE2, 0x97, 0x59, 0x5B, 0x16, 0x60, 0x6B, 0x83, 0xD7, 0x70, 0xA2, 0xBD, 0xA2, 0x27,
+ 0xBB, 0x4A, 0xF9, 0xC4, 0xFE, 0x77, 0xA1, 0xB5, 0x18, 0xBF, 0x0F, 0x42, 0x71, 0x90, 0x60, 0x3B,
+ 0x53, 0xBB, 0xD4, 0xE3, 0x4C, 0x31, 0x70, 0xAE, 0xBE, 0x0F, 0xEC, 0x7C, 0xB7, 0x0A, 0x8C, 0x88,
+ 0xD8, 0x99, 0x0E, 0x05, 0xBE, 0x37, 0xA8, 0x46, 0xC5, 0xA7, 0x1A, 0xF9, 0x9B, 0x81, 0xF3, 0x74,
+ 0xC5, 0x9F, 0xAE, 0xA3, 0x9B, 0x5A, 0x88, 0xDF, 0xF4, 0x7C, 0xD3, 0xB2, 0x60, 0x2A, 0x4C, 0x7C,
+ 0xED, 0x0A, 0x0F, 0x15, 0x1F, 0xA7, 0x13, 0xB0, 0x04, 0x0F, 0xD1, 0xFA, 0x2E, 0x31, 0xE6, 0xB5,
+ 0xC1, 0x15, 0xBE, 0x33, 0x19, 0x70, 0xE1, 0x59, 0x71, 0x64, 0x54, 0x8C, 0xC4, 0x76, 0x1D, 0x20,
+ 0x2A, 0x54, 0x13, 0x7F, 0x3F, 0x65, 0x4D, 0x0B, 0x8E, 0x84, 0x6B, 0x83, 0x4B, 0xDA, 0x58, 0x43,
+ 0x3B, 0xCB, 0xEF, 0x4E, 0xF9, 0x39, 0x3F, 0xFA, 0x44, 0x2F, 0x3E, 0xA2, 0x1B, 0x7F, 0xA3, 0x3A,
+ 0xE8, 0x95, 0xBD, 0xD5, 0x60, 0x70, 0x46, 0xDF, 0x0E, 0xCB, 0x9B, 0xD1, 0x87, 0xD9, 0x57, 0xFC,
+ 0xE9, 0xE4, 0xA1, 0x63, 0x8D, 0x9F, 0x09, 0xAB, 0xCB, 0x57, 0xE1, 0xE3, 0xB6, 0x08, 0x02, 0x86,
+ 0x11, 0x60, 0xC8, 0x51, 0xFE, 0xCC, 0x0D, 0xD0, 0xB3, 0x27, 0xA2, 0xF1, 0x1D, 0x65, 0x19, 0xCA,
+ 0x4D, 0x79, 0x34, 0xD8, 0x25, 0xD3, 0x50, 0x90, 0xB2, 0x27, 0xC6, 0xA5, 0x0F, 0x0A, 0x7F, 0x20,
+ 0x53, 0xD3, 0x03, 0x1A, 0x35, 0x30, 0x8B, 0x43, 0xFA, 0x8C, 0x25, 0x33, 0x66, 0xB5, 0xE7, 0x77,
+ 0xC5, 0x2E, 0xF9, 0xCB, 0x19, 0xA4, 0x8F, 0x63, 0x17, 0xCA, 0x4F, 0x92, 0x0F, 0x4F, 0xC7, 0x31,
+ 0xE6, 0x19, 0xFD, 0xE3, 0x66, 0x73, 0xD6, 0xC5, 0xA7, 0x45, 0xB5, 0x80, 0xB5, 0xB3, 0xC3, 0x59,
+ 0x37, 0xEF, 0xD1, 0xB0, 0xDC, 0x47, 0x7D, 0x81, 0xD3, 0xD2, 0x4F, 0xFA, 0xA2, 0x94, 0x06, 0x40,
+ 0xCD, 0xBE, 0xF6, 0xCE, 0xF0, 0xBE, 0xEC, 0x6B, 0x9F, 0xB0, 0x00, 0xB7, 0xC3, 0x07, 0x7E, 0x91,
+ 0x76, 0x63, 0x3C, 0x76, 0x53, 0x1F, 0xFA, 0xED, 0xC6, 0x1E, 0xFA, 0xED, 0x07, 0x0F, 0xFD, 0xF6,
+ 0xA3, 0xDD, 0x6E, 0x37, 0x9D, 0x56, 0xEB, 0x58, 0x85, 0x75, 0xC5, 0x07, 0x7F, 0x37, 0xC2, 0xD3,
+ 0x1C, 0xA4, 0xA9, 0xC8, 0x53, 0x37, 0xE0, 0x49, 0xD8, 0x15, 0x7E, 0x33, 0x99, 0x3C, 0x34, 0x8E,
+ 0xF8, 0xBA, 0x54, 0x79, 0x96, 0x5A, 0xED, 0x5D, 0x3F, 0x9D, 0x4D, 0x8D, 0x7B, 0x53, 0x0F, 0x67,
+ 0xD3, 0x26, 0xC9, 0x68, 0xD8, 0xCB, 0x0C, 0x86, 0x14, 0x84, 0x39, 0xFD, 0x9B, 0x4D, 0x3A, 0xFD,
+ 0xB4, 0x82, 0xD3, 0x4F, 0xD7, 0x9C, 0x7E, 0x87, 0xDE, 0x1E, 0x10, 0xFE, 0x77, 0xF3, 0xF8, 0x80,
+ 0xAF, 0x02, 0x5E, 0x2F, 0xE5, 0xAB, 0xD5, 0xDA, 0xA8, 0xDF, 0xE7, 0x3A, 0x49, 0x68, 0x0C, 0x6F,
+ 0x36, 0xE9, 0x24, 0x29, 0xA6, 0x5B, 0xCA, 0x4E, 0x79, 0xD8, 0x19, 0xEC, 0x66, 0x5C, 0xA2, 0xD9,
+ 0x94, 0xA8, 0x50, 0xDE, 0x3B, 0x3E, 0x13, 0xDA, 0xE9, 0xF2, 0xD4, 0x69, 0x13, 0xEA, 0x51, 0x7F,
+ 0x11, 0x44, 0x6A, 0x93, 0xCD, 0x24, 0x66, 0x0B, 0x21, 0xC3, 0x55, 0x4E, 0xCC, 0xDE, 0x7F, 0xF7,
+ 0x5D, 0xB1, 0x5C, 0x4C, 0xEC, 0xE5, 0x81, 0xE4, 0x62, 0x99, 0xB5, 0xD0, 0xDB, 0x05, 0xDC, 0x40,
+ 0xAA, 0x4B, 0x99, 0x6E, 0x04, 0x5E, 0x1B, 0xBC, 0xA4, 0xC7, 0x9A, 0x20, 0xB1, 0x42, 0xC6, 0xAB,
+ 0x3C, 0xED, 0xA4, 0x80, 0x42, 0xB1, 0x34, 0x22, 0x21, 0xA9, 0x1B, 0x45, 0x5C, 0x19, 0x05, 0x52,
+ 0x81, 0x3D, 0x75, 0xA6, 0x2A, 0xFB, 0x04, 0x6D, 0x92, 0x97, 0x0A, 0x2F, 0x5C, 0x52, 0x5A, 0x6D,
+ 0x1C, 0xB6, 0x36, 0x78, 0xEF, 0x12, 0xED, 0x95, 0x79, 0xAD, 0xCE, 0x9B, 0xB0, 0x51, 0x30, 0x44,
+ 0xA2, 0x26, 0xE5, 0xE4, 0x0E, 0x3E, 0xE9, 0xAE, 0x40, 0x5C, 0x6C, 0x57, 0xDD, 0x4E, 0x27, 0xC1,
+ 0x0A, 0x69, 0x57, 0xBB, 0x1A, 0x86, 0x4E, 0x6D, 0xD0, 0xA9, 0x86, 0xA1, 0x5B, 0x1B, 0x74, 0xAB,
+ 0x61, 0xE8, 0x81, 0x1C, 0x0E, 0x7A, 0xD5, 0x70, 0xF4, 0x6B, 0x83, 0x7E, 0x35, 0x0C, 0x47, 0x20,
+ 0xCB, 0xAA, 0x54, 0x40, 0xE6, 0x72, 0x5C, 0x00, 0x43, 0xFE, 0x26, 0x47, 0xD6, 0xAA, 0xBA, 0xF3,
+ 0xCC, 0x97, 0x56, 0x69, 0xE7, 0xE1, 0xB0, 0xB5, 0xC1, 0xBB, 0xA5, 0xE5, 0x9B, 0x0B, 0xCB, 0x84,
+ 0x69, 0x7B, 0xA3, 0xAB, 0x35, 0xB5, 0x76, 0xAF, 0xBD, 0xB7, 0xC3, 0x0C, 0x33, 0xA0, 0x43, 0xED,
+ 0x1D, 0x52, 0x9D, 0x20, 0x09, 0xD3, 0x8F, 0xC5, 0x77, 0x0A, 0x3C, 0x88, 0x70, 0xE6, 0x3A, 0x8E,
+ 0x5F, 0x5A, 0x1D, 0x01, 0x30, 0xA4, 0xF9, 0x70, 0x54, 0x3A, 0x9A, 0x45, 0x68, 0xCA, 0x18, 0x7A,
+ 0xCA, 0x26, 0xE7, 0x8A, 0xE1, 0x4C, 0x2F, 0x16, 0xCE, 0x76, 0xE7, 0x3E, 0xDE, 0x6D, 0xF9, 0x94,
+ 0x81, 0xC3, 0xC2, 0x6C, 0xF5, 0x16, 0x66, 0x88, 0x73, 0x54, 0x98, 0xD6, 0x68, 0x81, 0xFB, 0xE8,
+ 0xBD, 0x5D, 0x7A, 0x4F, 0x40, 0x46, 0xC1, 0x37, 0xB0, 0x89, 0xDE, 0xF3, 0x30, 0x9C, 0x87, 0xEA,
+ 0x83, 0x58, 0xE3, 0x5E, 0x79, 0x8D, 0x04, 0xD0, 0x90, 0x0F, 0xE0, 0x7B, 0xF0, 0x2A, 0xF9, 0x91,
+ 0x80, 0xAC, 0x9C, 0x23, 0x55, 0x77, 0x1A, 0xA9, 0x2B, 0x56, 0xCC, 0x0B, 0xDA, 0x95, 0x47, 0xF5,
+ 0xCE, 0x43, 0x1C, 0x0B, 0x17, 0xF8, 0xEA, 0x44, 0xA2, 0xB6, 0xBD, 0x92, 0x22, 0x13, 0x93, 0x48,
+ 0x06, 0xCB, 0x8D, 0x86, 0x6D, 0x2B, 0xDF, 0x69, 0xE6, 0x1F, 0x10, 0xB0, 0xBE, 0xDA, 0x54, 0x7C,
+ 0x15, 0x5E, 0x60, 0x4E, 0x36, 0x11, 0x08, 0x79, 0x7D, 0x70, 0xB3, 0x00, 0x24, 0xAC, 0xF4, 0x34,
+ 0x80, 0x03, 0x73, 0x15, 0x86, 0x91, 0xB8, 0xA3, 0x17, 0x88, 0xC4, 0xE2, 0x8C, 0x20, 0xC4, 0x57,
+ 0x72, 0xB4, 0xBB, 0xF7, 0xF4, 0xBF, 0x2B, 0x0F, 0x1E, 0x15, 0x5D, 0xBF, 0x60, 0x1A, 0x2C, 0xC1,
+ 0x80, 0xEF, 0x0B, 0xD4, 0x8B, 0x24, 0xF4, 0x9B, 0x0B, 0x1F, 0xC2, 0x5A, 0x21, 0x35, 0x38, 0x3A,
+ 0x74, 0x13, 0x9F, 0xCD, 0xF3, 0x0B, 0x2C, 0xFF, 0xA5, 0x36, 0xD9, 0x4C, 0x75, 0x67, 0x65, 0xDA,
+ 0xC5, 0xAB, 0x3B, 0x3F, 0x99, 0xF6, 0xD8, 0x59, 0x15, 0x2B, 0xF0, 0x88, 0x1D, 0xFD, 0x05, 0x0A,
+ 0x3C, 0x34, 0x3D, 0xC0, 0x15, 0xE2, 0xA6, 0x4B, 0xD4, 0xDE, 0x67, 0x93, 0x14, 0x32, 0x83, 0xBE,
+ 0xC1, 0x05, 0x56, 0x40, 0xE1, 0x69, 0x74, 0xBD, 0x79, 0xDB, 0x99, 0xDA, 0xCF, 0xA7, 0x62, 0xAE,
+ 0xC6, 0x29, 0x50, 0xCB, 0xD5, 0xBA, 0x92, 0x72, 0xF3, 0xBD, 0x57, 0xD0, 0x7F, 0x59, 0xE7, 0xE7,
+ 0xF6, 0xDE, 0xF9, 0xD9, 0xC4, 0x00, 0x44, 0xEC, 0x71, 0x69, 0xCB, 0x42, 0xD8, 0xC8, 0xAE, 0x2E,
+ 0xED, 0xF1, 0x4E, 0xAD, 0x8A, 0xF5, 0x5E, 0x5A, 0x07, 0xED, 0x7E, 0xBB, 0xF3, 0xB0, 0xCC, 0x0A,
+ 0x19, 0xAA, 0x60, 0x54, 0xFA, 0x49, 0xEF, 0x01, 0x4D, 0x69, 0x9C, 0xC9, 0x84, 0xAD, 0x6B, 0x96,
+ 0x33, 0x2D, 0x0E, 0x7E, 0x43, 0x9F, 0xD2, 0xF5, 0xC8, 0x6E, 0xE3, 0x55, 0xD8, 0x79, 0xC1, 0xD2,
+ 0x8C, 0xA0, 0x8B, 0xFE, 0xC3, 0x32, 0x2D, 0xCE, 0x91, 0xAA, 0x75, 0x49, 0x38, 0xEA, 0x3E, 0x1C,
+ 0xD3, 0xF2, 0x1D, 0xDF, 0xB0, 0x4A, 0x5B, 0x16, 0x83, 0x06, 0xC3, 0xFA, 0x88, 0x07, 0xDA, 0x15,
+ 0xF0, 0xB9, 0x53, 0xE3, 0x0A, 0xFA, 0x2F, 0x1F, 0xB8, 0x8E, 0xBB, 0x1B, 0x52, 0x46, 0x05, 0x96,
+ 0x7E, 0x59, 0x67, 0xA9, 0x52, 0xE8, 0xEA, 0x6F, 0x68, 0x91, 0x7C, 0x23, 0xA1, 0x6B, 0xE9, 0xE3,
+ 0xD5, 0xD2, 0xA1, 0x8B, 0x81, 0x63, 0xE8, 0xA2, 0x47, 0xBB, 0x37, 0xB1, 0x90, 0x82, 0xF2, 0x36,
+ 0xD6, 0x3B, 0xD9, 0xE4, 0x16, 0x98, 0x4D, 0x44, 0x30, 0xC6, 0x53, 0x25, 0x23, 0xDB, 0x94, 0xDF,
+ 0x54, 0x36, 0xB2, 0x91, 0xA1, 0xFC, 0x8E, 0x37, 0x8A, 0x4C, 0xCC, 0xE6, 0x19, 0x2C, 0xCC, 0xE1,
+ 0xD8, 0xC1, 0x4E, 0x2B, 0x36, 0x41, 0xE7, 0x1B, 0x5F, 0xA8, 0x0D, 0xB9, 0x7A, 0x48, 0xF5, 0x99,
+ 0xA1, 0x69, 0xDB, 0x65, 0xD5, 0xC4, 0x61, 0x6B, 0x83, 0x97, 0xEC, 0x60, 0xB7, 0x4B, 0xEA, 0xBC,
+ 0xF3, 0xCD, 0xAF, 0xA7, 0x07, 0x5C, 0xED, 0x5A, 0x4D, 0x89, 0x22, 0x86, 0x1B, 0x7E, 0xF7, 0xA3,
+ 0xC6, 0xF7, 0xA8, 0x46, 0xDF, 0x01, 0x79, 0x38, 0x25, 0x8D, 0xA9, 0x31, 0xC7, 0x87, 0x97, 0x8B,
+ 0x16, 0x35, 0xDE, 0x20, 0x58, 0xB1, 0x9A, 0x46, 0xBC, 0xA7, 0x87, 0x5D, 0xD5, 0x18, 0xC4, 0xDF,
+ 0x5A, 0x09, 0x84, 0x37, 0x87, 0xA6, 0xE1, 0xE1, 0x83, 0xFE, 0x70, 0xAC, 0xBD, 0x84, 0x63, 0xED,
+ 0xBD, 0xB5, 0x0C, 0x5F, 0xBB, 0x2B, 0x73, 0x08, 0x71, 0x3F, 0x5B, 0x84, 0x21, 0xED, 0xA9, 0x05,
+ 0xBA, 0x8D, 0x8F, 0x3F, 0xE0, 0x05, 0xC7, 0xB8, 0x7B, 0xAD, 0xD7, 0x3D, 0x6E, 0xD5, 0x34, 0x96,
+ 0x15, 0xF3, 0xC7, 0xFA, 0xBD, 0x2F, 0x74, 0x5B, 0x9B, 0x1E, 0x12, 0x28, 0x73, 0x00, 0x91, 0xDE,
+ 0x90, 0x40, 0x6A, 0xBF, 0x55, 0x76, 0x9B, 0xAD, 0x4B, 0x44, 0x0F, 0xC4, 0xD1, 0x92, 0x1A, 0x42,
+ 0xEC, 0x3D, 0x9B, 0xAC, 0x7D, 0xFC, 0x05, 0x05, 0xED, 0x9E, 0xEC, 0xFD, 0xA7, 0x72, 0x41, 0xE8,
+ 0x52, 0x41, 0xE0, 0xEE, 0xBE, 0xCD, 0xF2, 0xD4, 0x0E, 0x78, 0xD2, 0xD5, 0x78, 0x6A, 0x57, 0xE0,
+ 0xA9, 0xBD, 0x23, 0x9E, 0x3A, 0x01, 0x4F, 0x6D, 0x35, 0x9E, 0x3A, 0x15, 0x78, 0xEA, 0xEC, 0x88,
+ 0xA7, 0x6E, 0xC0, 0x53, 0x47, 0x8D, 0xA7, 0x6E, 0x05, 0x9E, 0xBA, 0x3B, 0xE2, 0xA9, 0x17, 0xF0,
+ 0xD4, 0x55, 0xE3, 0xA9, 0x57, 0x81, 0xA7, 0xDE, 0x8E, 0x78, 0xEA, 0x07, 0x3C, 0xF5, 0xD4, 0x78,
+ 0xEA, 0x57, 0xE0, 0xA9, 0xBF, 0x23, 0x9E, 0x8E, 0x02, 0x9E, 0xFA, 0x6A, 0x3C, 0x1D, 0x55, 0xE0,
+ 0xE9, 0x68, 0x47, 0x3C, 0x1D, 0x07, 0x3C, 0x1D, 0xA9, 0xF1, 0x74, 0x5C, 0x81, 0xA7, 0xE3, 0x1D,
+ 0xF1, 0x74, 0x12, 0xF0, 0x74, 0xAC, 0xC6, 0xD3, 0x49, 0x05, 0x9E, 0x4E, 0x76, 0xC4, 0x13, 0xEE,
+ 0xA6, 0x62, 0x4C, 0x9D, 0x28, 0x0E, 0xBA, 0xAD, 0x0A, 0x5C, 0x19, 0xBB, 0xE2, 0x2A, 0x4C, 0x25,
+ 0x74, 0xD5, 0x5C, 0xA2, 0x4A, 0x32, 0x31, 0xDC, 0x15, 0x5B, 0x51, 0x36, 0xA1, 0x98, 0x4E, 0xE8,
+ 0x55, 0xF2, 0x89, 0xD1, 0xAE, 0xD8, 0x0A, 0x13, 0x0A, 0x5D, 0x31, 0xA3, 0xD0, 0xAB, 0xA4, 0x14,
+ 0xE3, 0x5D, 0xB1, 0x15, 0xE6, 0x14, 0xBA, 0x62, 0x52, 0xA1, 0x57, 0xC9, 0x2A, 0xC8, 0xAE, 0xD8,
+ 0x0A, 0xD3, 0x0A, 0x5D, 0x31, 0xAF, 0xD0, 0xAB, 0x24, 0x16, 0x93, 0x5D, 0xB1, 0x15, 0x66, 0x16,
+ 0xBA, 0x62, 0x6A, 0xA1, 0x57, 0xC8, 0x2D, 0x4E, 0xE4, 0x13, 0xB1, 0x8D, 0xB2, 0x45, 0x7C, 0x3E,
+ 0x45, 0x8E, 0x26, 0x6D, 0x4A, 0x0F, 0x1C, 0x71, 0x20, 0x7C, 0x22, 0x8E, 0x09, 0xE4, 0xC2, 0xB1,
+ 0x27, 0xE6, 0x34, 0x2C, 0x32, 0x3C, 0x98, 0x67, 0x63, 0x3C, 0xE1, 0x85, 0xBF, 0xCA, 0x85, 0x86,
+ 0xAB, 0x57, 0x97, 0xC5, 0xCA, 0x0C, 0x62, 0x2F, 0x7F, 0xA1, 0x22, 0x03, 0x90, 0xDD, 0x16, 0xBF,
+ 0x3E, 0xA0, 0x54, 0x57, 0xA0, 0x40, 0x45, 0x2A, 0x0A, 0x3D, 0xB1, 0xA2, 0xD0, 0x57, 0xAE, 0x28,
+ 0x30, 0xE2, 0xB6, 0x53, 0x4B, 0x00, 0xDC, 0x1D, 0xF6, 0xC9, 0x04, 0x75, 0xA6, 0x3B, 0xE5, 0x99,
+ 0xEE, 0x15, 0x61, 0xBA, 0x53, 0x86, 0xE9, 0x12, 0xCF, 0xB4, 0x2A, 0xCA, 0x09, 0xE8, 0x7D, 0x6D,
+ 0xDE, 0x90, 0xB1, 0xF6, 0x8B, 0xBA, 0xA8, 0xF4, 0xF2, 0xA2, 0x3A, 0x2A, 0x22, 0x2A, 0x7D, 0x8B,
+ 0xF6, 0xD1, 0x0B, 0xF8, 0xFE, 0x51, 0x9D, 0xEF, 0x5E, 0x79, 0xBE, 0x3B, 0x45, 0xF8, 0xEE, 0x6D,
+ 0x91, 0xEF, 0x6E, 0xC0, 0xF7, 0x27, 0x75, 0xBE, 0xBB, 0xE5, 0xF9, 0xEE, 0x16, 0xE1, 0xBB, 0xBB,
+ 0x45, 0xBE, 0xDB, 0x10, 0x6C, 0x7E, 0xFC, 0xA4, 0x7D, 0x9C, 0xB9, 0xC4, 0x9B, 0xE5, 0x57, 0xE2,
+ 0x18, 0x44, 0xD9, 0xB1, 0xBD, 0xB7, 0x83, 0xB9, 0x1B, 0x52, 0xD8, 0x11, 0x79, 0xCA, 0xCD, 0x9B,
+ 0x19, 0x84, 0xCA, 0x37, 0x89, 0xE4, 0x3C, 0xC9, 0x67, 0x6E, 0xBA, 0x2A, 0x53, 0xDB, 0x8B, 0x61,
+ 0xC7, 0xB5, 0xC1, 0xDB, 0x65, 0x81, 0xF1, 0xED, 0xB8, 0xBC, 0x3D, 0xAB, 0x57, 0xCC, 0x19, 0x5D,
+ 0x5B, 0xB3, 0xE7, 0x13, 0xCA, 0x33, 0xE4, 0x65, 0x9E, 0x82, 0xDA, 0xCB, 0x57, 0x21, 0x7A, 0x3B,
+ 0xA8, 0x92, 0x63, 0xA4, 0x3F, 0x62, 0xEC, 0xFC, 0x88, 0x0C, 0x69, 0x90, 0xB1, 0x14, 0x18, 0x8C,
+ 0x8E, 0x0A, 0x6A, 0xF3, 0xB8, 0x64, 0x74, 0x42, 0x1A, 0xB7, 0xA6, 0x4E, 0x9C, 0x7A, 0xA0, 0x00,
+ 0x3E, 0x95, 0x10, 0x40, 0xBF, 0xBC, 0x00, 0x0A, 0x65, 0x2E, 0x48, 0xE3, 0xF6, 0x04, 0xD0, 0x62,
+ 0x02, 0xB8, 0x8A, 0x5E, 0x7A, 0x9D, 0x61, 0xD0, 0x15, 0x2A, 0x50, 0xBD, 0x1D, 0xAC, 0x91, 0x60,
+ 0xA4, 0xD5, 0x03, 0x8B, 0x06, 0x8E, 0x8A, 0x29, 0xB4, 0x5D, 0x34, 0xBF, 0x92, 0x17, 0x3F, 0x15,
+ 0xF2, 0xEF, 0x6D, 0x26, 0x58, 0xED, 0x56, 0x60, 0xD1, 0xC5, 0x05, 0xD0, 0x2A, 0x2F, 0x00, 0xBD,
+ 0x90, 0x00, 0x5A, 0x0F, 0x2B, 0x19, 0xEF, 0xAF, 0x7F, 0xA7, 0x38, 0x5F, 0x5A, 0x45, 0xDD, 0x5F,
+ 0x18, 0xCD, 0xDA, 0x45, 0x84, 0xB5, 0x55, 0xEF, 0xEF, 0x44, 0x9C, 0x6B, 0xBF, 0x68, 0xF1, 0xAD,
+ 0xAF, 0x59, 0x71, 0xA0, 0x7C, 0x11, 0xB0, 0xB7, 0x83, 0xF5, 0x2A, 0xA4, 0xF0, 0x44, 0xC2, 0x59,
+ 0xC1, 0x00, 0x7F, 0x52, 0xDE, 0x1D, 0x0A, 0x69, 0x18, 0x69, 0xDD, 0x9E, 0x8A, 0x7B, 0x31, 0x41,
+ 0xB0, 0x6F, 0xA4, 0xAB, 0xA8, 0xB8, 0x7C, 0xE5, 0xB0, 0xB7, 0x83, 0xA5, 0x2E, 0xA4, 0xF0, 0x58,
+ 0xC2, 0x59, 0x41, 0x15, 0x17, 0x4D, 0x49, 0x8F, 0x4B, 0x4E, 0x2D, 0xF5, 0x6D, 0xE6, 0xA4, 0x58,
+ 0xED, 0x16, 0x04, 0x21, 0x7E, 0xC0, 0x22, 0x4B, 0xC1, 0xE5, 0x2B, 0xDE, 0xBD, 0x8A, 0xEB, 0xB3,
+ 0xDB, 0x8B, 0xE4, 0x47, 0xB2, 0xAF, 0x9B, 0xE7, 0xDB, 0x41, 0xD1, 0x5C, 0xB6, 0x55, 0x72, 0xE0,
+ 0xDB, 0x6A, 0x2A, 0x0B, 0xBD, 0x43, 0xD6, 0xB3, 0xCE, 0x7D, 0x86, 0x09, 0x94, 0x5F, 0x79, 0xEB,
+ 0xED, 0x60, 0x7B, 0x08, 0x52, 0xD8, 0xAE, 0x0D, 0x3E, 0x15, 0x64, 0xAA, 0x4A, 0xFD, 0xA0, 0xF4,
+ 0xFE, 0x90, 0xDD, 0x95, 0xDE, 0x47, 0xF3, 0x9B, 0xE2, 0xA5, 0xF7, 0x8B, 0x77, 0x3F, 0x17, 0x2B,
+ 0xBD, 0x8B, 0xBD, 0xEC, 0xAE, 0xF4, 0x5E, 0xCE, 0x66, 0x0A, 0x6D, 0x94, 0x05, 0xC6, 0xF0, 0x55,
+ 0x48, 0x23, 0xD3, 0xA3, 0x5D, 0x82, 0x60, 0xB4, 0xF7, 0xC1, 0x69, 0x28, 0x22, 0xE1, 0x19, 0xE5,
+ 0x78, 0xFB, 0x2C, 0xEB, 0xE9, 0x64, 0x84, 0x85, 0x52, 0xCF, 0xF0, 0xE2, 0x0B, 0x75, 0xFA, 0xFC,
+ 0x1B, 0x5F, 0x15, 0x9E, 0x05, 0x4E, 0x7B, 0xD7, 0xC8, 0xC1, 0x51, 0x41, 0xDC, 0x5B, 0x7F, 0xC5,
+ 0xC0, 0x20, 0xA1, 0x28, 0x9D, 0xEA, 0x47, 0xC7, 0x73, 0xE5, 0x3A, 0x39, 0x05, 0x2B, 0x12, 0xCD,
+ 0x3B, 0x62, 0xA9, 0x45, 0x3D, 0x9A, 0x33, 0xF2, 0xB6, 0x13, 0xCD, 0x11, 0x77, 0x8C, 0xF7, 0x02,
+ 0x59, 0x0D, 0x83, 0x2D, 0x26, 0x00, 0xF9, 0x26, 0x0A, 0x05, 0x01, 0xA4, 0x49, 0x60, 0x23, 0x22,
+ 0x68, 0x53, 0x09, 0xB4, 0x13, 0xDA, 0x4F, 0x09, 0xFC, 0xB4, 0x7D, 0xD9, 0xB8, 0xDF, 0xD9, 0x41,
+ 0x6D, 0x02, 0xC5, 0x15, 0xE3, 0xA8, 0xA0, 0x4E, 0x8B, 0x2D, 0x0E, 0xC6, 0x74, 0x5A, 0xCC, 0xA8,
+ 0xB7, 0xB6, 0x3A, 0x08, 0xC8, 0x3B, 0x54, 0x00, 0x1D, 0x65, 0x95, 0x96, 0x9F, 0x66, 0x76, 0x76,
+ 0x90, 0x9F, 0xA0, 0xB4, 0x62, 0x1C, 0x15, 0x54, 0x69, 0xB1, 0xA5, 0xCF, 0x98, 0x4A, 0xD5, 0xE7,
+ 0x97, 0x9C, 0xC8, 0xAD, 0xA9, 0xB4, 0x4B, 0x05, 0xD0, 0x55, 0x56, 0x69, 0xF9, 0x59, 0x47, 0x67,
+ 0x07, 0xBB, 0x77, 0x51, 0x5A, 0x31, 0x8E, 0x0A, 0xAA, 0xB4, 0xD8, 0x92, 0x5D, 0x4C, 0xA5, 0xEA,
+ 0xF3, 0x49, 0x4E, 0xE4, 0xD6, 0x54, 0xDA, 0xA3, 0x02, 0xE8, 0x29, 0xAB, 0xB4, 0x7C, 0xA5, 0xA0,
+ 0xB3, 0x83, 0x62, 0x10, 0x4A, 0x2B, 0xC6, 0x51, 0x41, 0x95, 0x16, 0x5B, 0x7D, 0x8E, 0xA9, 0x54,
+ 0x7D, 0x9D, 0x83, 0x13, 0xB9, 0x35, 0x95, 0xF6, 0xA9, 0x00, 0xFA, 0xCA, 0x2A, 0x2D, 0xBF, 0xBF,
+ 0xAA, 0xB3, 0x83, 0xBD, 0xDB, 0x28, 0xAD, 0x18, 0x47, 0x05, 0x55, 0x5A, 0xAC, 0x74, 0x1B, 0x53,
+ 0xA9, 0xFA, 0xCA, 0x0D, 0x27, 0x72, 0x6B, 0x2A, 0x3D, 0xA2, 0x02, 0x38, 0x52, 0x56, 0x69, 0xF9,
+ 0xAD, 0xEB, 0x9D, 0x1D, 0xD4, 0xF3, 0x50, 0x5A, 0x31, 0x8E, 0x0A, 0xAA, 0xB4, 0x58, 0x05, 0x27,
+ 0xA6, 0x52, 0xF5, 0xBD, 0x53, 0x9C, 0xC8, 0xAD, 0xA9, 0xF4, 0x98, 0x0A, 0xE0, 0x58, 0x59, 0xA5,
+ 0xE5, 0x77, 0xEE, 0x77, 0x76, 0xB0, 0x73, 0x1F, 0xA5, 0x15, 0xE3, 0xA8, 0xA0, 0x4A, 0x8B, 0xD5,
+ 0x66, 0x63, 0x2A, 0x55, 0xDF, 0xEE, 0xC4, 0x89, 0xDC, 0x9A, 0x4A, 0x4F, 0xA8, 0x00, 0x4E, 0x94,
+ 0x55, 0x5A, 0x7E, 0xCB, 0x40, 0x67, 0x07, 0x9B, 0x5F, 0x50, 0x5A, 0x2D, 0x91, 0xA3, 0x82, 0x2A,
+ 0x2D, 0xB6, 0xC0, 0xD8, 0x49, 0xD9, 0xFA, 0xA2, 0xA0, 0xD2, 0xB4, 0x05, 0xC6, 0x07, 0x50, 0xBF,
+ 0x33, 0x56, 0xC3, 0x12, 0x1F, 0xFC, 0x79, 0xF1, 0xD3, 0xCB, 0xF4, 0xC2, 0x7E, 0x6A, 0x15, 0x2F,
+ 0xD6, 0xD7, 0x43, 0x2F, 0xE3, 0x89, 0xF2, 0x42, 0xC2, 0x41, 0xCB, 0xEC, 0x25, 0x91, 0xDA, 0x1A,
+ 0xF3, 0xD9, 0x96, 0xC6, 0x80, 0x0B, 0x58, 0x5A, 0xA7, 0xDB, 0x92, 0x27, 0x2D, 0x39, 0x96, 0xC6,
+ 0xA9, 0xDC, 0x4E, 0xF0, 0x40, 0xE4, 0x30, 0x17, 0x47, 0xDE, 0x3F, 0x28, 0xAD, 0xE9, 0x30, 0x80,
+ 0x78, 0xF8, 0xE8, 0xB6, 0x4E, 0x14, 0xE3, 0x07, 0xC8, 0x20, 0x6D, 0x63, 0xFC, 0x06, 0x03, 0x08,
+ 0xD2, 0xD8, 0x61, 0x4C, 0xBD, 0x51, 0x66, 0x2A, 0x59, 0x05, 0x28, 0xC4, 0x54, 0x5A, 0x65, 0x67,
+ 0xC3, 0x4C, 0x75, 0x19, 0x53, 0x19, 0x4E, 0x9A, 0x60, 0x2A, 0x39, 0x0F, 0x2E, 0xC4, 0x54, 0xDA,
+ 0x44, 0x38, 0x62, 0xEA, 0x21, 0x04, 0x3A, 0x32, 0x32, 0xA6, 0xA3, 0x12, 0xA1, 0xEE, 0xF2, 0xE2,
+ 0xF0, 0xC5, 0x9B, 0x0B, 0x8D, 0x2E, 0x69, 0x3A, 0x56, 0xC1, 0x88, 0x17, 0xEF, 0xF4, 0x2F, 0x15,
+ 0xF3, 0x28, 0xE9, 0x42, 0xD4, 0x7B, 0x73, 0xA1, 0x1A, 0xF0, 0x38, 0x64, 0x91, 0x90, 0xD7, 0x6B,
+ 0x75, 0xCA, 0x54, 0x08, 0x43, 0x22, 0xB7, 0x14, 0xF4, 0x28, 0xFA, 0x76, 0x24, 0x83, 0xCB, 0x62,
+ 0x32, 0x28, 0x54, 0x25, 0x8D, 0xCB, 0xA0, 0x40, 0xD8, 0x0F, 0x88, 0xDC, 0xA6, 0x0C, 0x30, 0x4A,
+ 0x5E, 0x5E, 0x68, 0xEF, 0xFF, 0xA9, 0x5D, 0xDE, 0x2C, 0x1C, 0x6F, 0xE9, 0x92, 0xDC, 0xA8, 0xC2,
+ 0xE1, 0xE2, 0x71, 0xA5, 0xDF, 0xEB, 0x75, 0x54, 0x03, 0x4B, 0x2F, 0x7D, 0x08, 0x98, 0xB4, 0x36,
+ 0x18, 0x2F, 0x29, 0xA1, 0xDD, 0x90, 0xC1, 0x0F, 0x04, 0x34, 0xAD, 0x14, 0x37, 0x39, 0x60, 0x9C,
+ 0x43, 0xBD, 0x85, 0xDB, 0xAB, 0x15, 0x19, 0x94, 0x67, 0x94, 0x9D, 0x8D, 0x0E, 0x07, 0x94, 0xCA,
+ 0x5E, 0xC8, 0xDE, 0xA7, 0x8F, 0x57, 0x6A, 0x8C, 0x25, 0xEB, 0x68, 0xC5, 0x54, 0x97, 0xF6, 0xC8,
+ 0x68, 0xC1, 0x41, 0x41, 0xDE, 0xE8, 0xEC, 0x10, 0x62, 0xEC, 0xBA, 0x6C, 0x52, 0x44, 0x76, 0x36,
+ 0x31, 0xA7, 0x60, 0xB0, 0x72, 0x59, 0x52, 0x19, 0xB2, 0xB7, 0x9A, 0xE2, 0x17, 0x48, 0x9B, 0x23,
+ 0x08, 0xF3, 0xA0, 0x7B, 0xF4, 0xAE, 0x40, 0xB2, 0x73, 0x63, 0x4A, 0xA2, 0xEB, 0x1A, 0x0B, 0xE2,
+ 0x59, 0xC1, 0xD9, 0x60, 0x08, 0x8D, 0x6B, 0xC2, 0x3F, 0x97, 0xAA, 0xCD, 0x5C, 0x32, 0x39, 0xAF,
+ 0x7D, 0x13, 0xE2, 0xE4, 0x8F, 0xDF, 0x61, 0x93, 0x9A, 0x36, 0x76, 0x56, 0xB6, 0xE5, 0x18, 0x18,
+ 0xF8, 0x8D, 0x85, 0x0F, 0x94, 0x1E, 0xFC, 0xB1, 0xC0, 0x37, 0x5C, 0x19, 0xF8, 0xB4, 0x96, 0x91,
+ 0xD1, 0x8F, 0xA0, 0xFE, 0x91, 0xE5, 0x78, 0xC1, 0xB4, 0x0D, 0x0F, 0xC3, 0xCF, 0xAB, 0xFE, 0xCF,
+ 0x7F, 0xE7, 0x6D, 0x15, 0x30, 0xE7, 0x53, 0x41, 0x00, 0x35, 0xCD, 0x73, 0x47, 0xE7, 0x35, 0xA0,
+ 0xD4, 0x75, 0x3C, 0xCF, 0x71, 0xCD, 0xA9, 0x99, 0x32, 0x36, 0xA7, 0x49, 0xFB, 0x50, 0x26, 0xEE,
+ 0x44, 0x63, 0xC9, 0xB0, 0x7F, 0xE6, 0x8D, 0x5C, 0x73, 0xE1, 0x0F, 0x1E, 0x8D, 0x9D, 0xD1, 0x72,
+ 0x4E, 0x6C, 0xFF, 0xC0, 0x18, 0x8F, 0x2F, 0xAF, 0xE1, 0xE0, 0x3B, 0xFC, 0x16, 0x1F, 0x48, 0xBE,
+ 0x51, 0x7F, 0xF5, 0xAF, 0x77, 0x38, 0x0C, 0xE3, 0x35, 0x90, 0x17, 0x19, 0xD7, 0xF7, 0xB5, 0xC9,
+ 0xD2, 0x66, 0x23, 0x61, 0x83, 0x60, 0xDB, 0x3D, 0xED, 0x2B, 0x60, 0xBC, 0x36, 0x5C, 0x6D, 0x68,
+ 0x78, 0xE4, 0xAD, 0xE3, 0xF9, 0xDA, 0xB9, 0x16, 0x62, 0xB4, 0x9C, 0x11, 0xDD, 0xB7, 0x71, 0xC0,
+ 0xF8, 0xE2, 0x2D, 0x19, 0xE3, 0x3F, 0xBA, 0x16, 0x34, 0x0D, 0xA1, 0x9E, 0x6A, 0xF5, 0xD3, 0x63,
+ 0xBD, 0x8E, 0xF6, 0x17, 0x76, 0x31, 0x21, 0x10, 0xE6, 0xA1, 0x5D, 0x63, 0xE9, 0x5A, 0xFB, 0xDA,
+ 0x68, 0xB8, 0xF7, 0x95, 0x52, 0x4F, 0x2F, 0xE3, 0xB5, 0x3D, 0xCE, 0xCC, 0x81, 0x3F, 0x23, 0x76,
+ 0x23, 0xA2, 0xCC, 0x25, 0xDE, 0xC2, 0xB1, 0x3D, 0xC2, 0x88, 0x63, 0x3F, 0x73, 0x12, 0x5D, 0x3F,
+ 0xF0, 0x7C, 0xC3, 0x5F, 0x7A, 0xDA, 0xE3, 0xF3, 0x73, 0xAD, 0xDD, 0x6A, 0x89, 0xCD, 0x34, 0xE8,
+ 0x26, 0xD9, 0x6E, 0x5F, 0x4B, 0x5C, 0xF8, 0x48, 0x6E, 0xFC, 0xBD, 0x67, 0x21, 0xCC, 0x9D, 0x46,
+ 0x2C, 0x8F, 0xC4, 0x90, 0x84, 0x00, 0xF8, 0xDE, 0xB8, 0xC6, 0x5E, 0x9C, 0xC0, 0xC6, 0xD8, 0xF0,
+ 0x8D, 0xBD, 0xAF, 0x31, 0x7D, 0x41, 0xAF, 0x40, 0xC9, 0xBE, 0x46, 0x6F, 0x3D, 0x13, 0x6E, 0xDD,
+ 0xED, 0x1D, 0x80, 0x0C, 0x81, 0xDF, 0x10, 0x9A, 0xB8, 0x6E, 0x9C, 0x62, 0x0A, 0xDD, 0xD4, 0xF7,
+ 0x35, 0xBC, 0x13, 0x87, 0x15, 0x88, 0x7C, 0x14, 0x5C, 0x0B, 0x84, 0x96, 0x8D, 0x56, 0x82, 0x92,
+ 0xA1, 0xBB, 0x8B, 0xA9, 0x08, 0x02, 0xCE, 0x07, 0x32, 0x05, 0x89, 0x4D, 0xF7, 0x79, 0xFC, 0xD9,
+ 0xA7, 0xC1, 0x67, 0x9F, 0xC5, 0x2D, 0x41, 0x6B, 0x87, 0x87, 0xE0, 0xD2, 0x9E, 0x63, 0x11, 0xB0,
+ 0x8A, 0x69, 0xA3, 0xCE, 0xBF, 0xF5, 0x0A, 0x16, 0x55, 0x6F, 0xDD, 0xD4, 0x9F, 0x02, 0x82, 0x03,
+ 0xDF, 0xB9, 0xF2, 0x5D, 0xD3, 0x9E, 0x36, 0xF4, 0xFE, 0x5E, 0x84, 0x8D, 0xDE, 0x46, 0x94, 0x89,
+ 0xFB, 0xF4, 0x3A, 0xED, 0x24, 0x79, 0xA3, 0xC1, 0xAF, 0x3F, 0xAD, 0xEF, 0xD5, 0x39, 0xF1, 0xF4,
+ 0x1C, 0xCC, 0xAD, 0xC1, 0x0E, 0x9E, 0x50, 0x1A, 0xF7, 0xB4, 0xB3, 0x33, 0xDE, 0x0D, 0x6B, 0x85,
+ 0x17, 0xA1, 0x11, 0xFD, 0x93, 0xB8, 0x15, 0x9A, 0xE2, 0xEF, 0xFF, 0xF8, 0x1A, 0xD8, 0xEC, 0xDD,
+ 0x21, 0x50, 0xFD, 0x1C, 0x43, 0xF0, 0x3F, 0xBE, 0xC2, 0xFF, 0x77, 0x4F, 0x68, 0xD4, 0xFD, 0xC7,
+ 0x57, 0xFC, 0x73, 0xF7, 0x04, 0x7A, 0x82, 0x63, 0xDA, 0xDF, 0xDD, 0xEF, 0x54, 0x0E, 0xEB, 0xD2,
+ 0x9B, 0xA6, 0x4A, 0x2F, 0x14, 0x5B, 0x61, 0x9A, 0xA6, 0x19, 0x44, 0xFD, 0x1E, 0xF9, 0x6F, 0x63,
+ 0xE4, 0x8C, 0x41, 0x3D, 0x3E, 0x58, 0x72, 0xA0, 0x74, 0x0B, 0x54, 0x12, 0x08, 0xAA, 0x15, 0x28,
+ 0xDD, 0x9C, 0xD0, 0x96, 0x1A, 0x77, 0x95, 0xC8, 0x40, 0x82, 0x96, 0x0B, 0xC3, 0xF5, 0xC8, 0xB7,
+ 0xB6, 0xDF, 0xF0, 0x63, 0x4E, 0x91, 0x22, 0xF1, 0xC1, 0x20, 0xC6, 0x02, 0xFE, 0x00, 0x0E, 0xDA,
+ 0xD5, 0xB9, 0xD2, 0x42, 0x63, 0xE3, 0x7F, 0x13, 0x66, 0xF3, 0xA6, 0x90, 0xD9, 0x34, 0xA8, 0xD8,
+ 0xC2, 0x3E, 0xF7, 0x8A, 0x98, 0x10, 0x90, 0x25, 0x18, 0x10, 0x75, 0x88, 0x48, 0x64, 0xEC, 0x62,
+ 0x8A, 0x43, 0xFC, 0x3C, 0xB2, 0xBE, 0x34, 0x6E, 0xE0, 0xBF, 0x64, 0xCC, 0x5A, 0xD3, 0x15, 0x36,
+ 0x7A, 0x8E, 0xFF, 0x81, 0x82, 0xF0, 0x4F, 0xAA, 0xA1, 0x00, 0xD6, 0xF7, 0x96, 0xD5, 0x60, 0x1F,
+ 0x98, 0x03, 0x1B, 0x59, 0x42, 0x3C, 0xF4, 0x6E, 0x31, 0x32, 0x39, 0x8E, 0xFF, 0x79, 0x5F, 0x5B,
+ 0xB8, 0x40, 0x18, 0xFD, 0x96, 0x0A, 0x1C, 0x03, 0x22, 0x62, 0xB3, 0xBF, 0xB9, 0x14, 0x2C, 0x2C,
+ 0xEB, 0x39, 0xC3, 0x0A, 0x24, 0xB0, 0x03, 0x30, 0x99, 0x25, 0x9A, 0x2E, 0xFC, 0x7F, 0xF7, 0x04,
+ 0x3A, 0x81, 0x43, 0xF8, 0xFF, 0xEE, 0x09, 0x76, 0x85, 0x46, 0x85, 0x3D, 0xDE, 0x3D, 0x81, 0x1E,
+ 0xE1, 0x04, 0xFE, 0x87, 0x36, 0xD8, 0x2F, 0xB6, 0xC2, 0xBF, 0x70, 0x87, 0xF6, 0x8F, 0x37, 0xE9,
+ 0x01, 0xBB, 0xC0, 0x4F, 0xB3, 0x18, 0x64, 0x6F, 0xD7, 0x6F, 0xD0, 0xB7, 0x9D, 0x7F, 0xBE, 0x01,
+ 0x76, 0xE8, 0xC1, 0x2D, 0xC4, 0x20, 0x7B, 0x8C, 0xE7, 0xF8, 0xE7, 0x36, 0x50, 0x30, 0x5E, 0xE0,
+ 0x47, 0x70, 0x8D, 0xBE, 0x11, 0x16, 0x2F, 0xB1, 0x03, 0x6C, 0x45, 0xDF, 0xDF, 0x49, 0x5B, 0xB1,
+ 0x23, 0xB8, 0xC6, 0xDF, 0xFA, 0xB8, 0xAF, 0xF1, 0xF7, 0x0A, 0xE6, 0x0A, 0x27, 0x7A, 0xEF, 0xDF,
+ 0x73, 0xEF, 0x06, 0x19, 0x64, 0xA4, 0xA1, 0x54, 0xC2, 0xB3, 0xDB, 0xBB, 0x27, 0x04, 0xEF, 0x51,
+ 0x22, 0xE1, 0xF8, 0x96, 0x1F, 0xC3, 0x75, 0xA0, 0x0F, 0xEF, 0x04, 0x04, 0xD3, 0x0B, 0xB7, 0xD1,
+ 0x05, 0x68, 0xE1, 0xE3, 0x7D, 0x4E, 0x3C, 0x9C, 0xDD, 0x86, 0x67, 0x08, 0x4D, 0x61, 0x39, 0x1B,
+ 0x70, 0x7A, 0x1B, 0x9D, 0xC2, 0x5D, 0xE4, 0x05, 0x15, 0xC0, 0x79, 0xBA, 0x7B, 0xC2, 0x79, 0x42,
+ 0x2D, 0xB2, 0xA3, 0xB8, 0xA8, 0xE1, 0x7F, 0xF4, 0x23, 0x9F, 0x07, 0xEC, 0x4F, 0x81, 0x77, 0x12,
+ 0x6B, 0x4F, 0x3B, 0x1F, 0xF0, 0xB8, 0x8F, 0x01, 0x00, 0x3C, 0x0A, 0xAE, 0x13, 0xEB, 0xC0, 0xF0,
+ 0xC1, 0x21, 0x20, 0x6F, 0x22, 0xDE, 0x01, 0x46, 0x94, 0xD0, 0xCD, 0xD7, 0x6E, 0x1D, 0xD8, 0xE0,
+ 0x16, 0x14, 0xE1, 0xDE, 0x29, 0x0F, 0x1B, 0x88, 0x88, 0x71, 0xB9, 0x86, 0x8B, 0x5D, 0x4E, 0x43,
+ 0xC7, 0xEE, 0xA6, 0x60, 0xE4, 0xA1, 0x30, 0x0E, 0x81, 0x17, 0xD3, 0xB0, 0xD1, 0x51, 0x43, 0xC0,
+ 0xD5, 0xEE, 0xF5, 0x22, 0x6C, 0x89, 0x48, 0xC7, 0xE6, 0x94, 0x28, 0x90, 0x03, 0xCC, 0xCF, 0xA3,
+ 0xA1, 0x70, 0x04, 0xE6, 0xA0, 0xD5, 0x83, 0x09, 0x65, 0xFD, 0x74, 0x2D, 0xC2, 0x01, 0x04, 0x2F,
+ 0x20, 0x68, 0xCF, 0x19, 0x8D, 0xA7, 0x51, 0xF8, 0xD4, 0xB4, 0x21, 0x24, 0x3B, 0x5F, 0x9E, 0xC5,
+ 0x90, 0xD1, 0xD4, 0x3F, 0xC4, 0xC4, 0xAE, 0x61, 0xA2, 0x90, 0xB8, 0xC4, 0xB6, 0xDB, 0x35, 0x1D,
+ 0x9B, 0xC8, 0x7B, 0x8D, 0xC5, 0x4B, 0xDE, 0x11, 0x3F, 0x1B, 0x93, 0x89, 0xB1, 0xB4, 0xFC, 0x08,
+ 0xCC, 0x25, 0x90, 0xE8, 0xDA, 0x3C, 0x6C, 0xB1, 0x24, 0x3F, 0x77, 0xE8, 0xCE, 0x18, 0x2A, 0x82,
+ 0x51, 0xE1, 0x71, 0x72, 0x54, 0x00, 0xAB, 0x74, 0xFD, 0x46, 0xFD, 0xD2, 0x75, 0x1D, 0xF7, 0xD7,
+ 0xFA, 0x53, 0x6C, 0xF4, 0xB4, 0xFE, 0xDB, 0xA9, 0x46, 0xE3, 0xE9, 0x5E, 0x3C, 0xB8, 0x0B, 0xE1,
+ 0xF3, 0xF0, 0x50, 0x7B, 0xE1, 0xFB, 0x06, 0x28, 0x00, 0x6B, 0x2C, 0x33, 0x94, 0x8F, 0x66, 0xF0,
+ 0x24, 0xD0, 0x71, 0xD1, 0x28, 0xD9, 0xF7, 0xEE, 0x41, 0x22, 0x98, 0x58, 0x7A, 0x00, 0x12, 0x24,
+ 0x99, 0x14, 0xD5, 0xC1, 0xBF, 0x97, 0xC4, 0xBD, 0xBD, 0xA2, 0x02, 0x73, 0xDC, 0x17, 0x10, 0x2A,
+ 0xEB, 0x07, 0xD1, 0x3C, 0xA9, 0xCE, 0x72, 0x9E, 0x03, 0x40, 0x75, 0x09, 0x7D, 0x80, 0x8E, 0x23,
+ 0x9B, 0x67, 0xDC, 0x84, 0x7A, 0x87, 0x71, 0xEE, 0x9C, 0x2B, 0x23, 0x99, 0x64, 0x41, 0x0B, 0xC7,
+ 0xFE, 0x42, 0x6E, 0x97, 0x0B, 0x10, 0x7F, 0x94, 0x36, 0x25, 0x12, 0x39, 0x2E, 0x1D, 0x72, 0x00,
+ 0x2D, 0x2F, 0xF8, 0xC0, 0xA9, 0x77, 0x24, 0x8D, 0x22, 0x15, 0x50, 0xEB, 0x44, 0x4F, 0x7C, 0xB6,
+ 0xD6, 0xE8, 0xEE, 0x91, 0xFC, 0x4C, 0x92, 0x72, 0x72, 0x02, 0xB9, 0xF0, 0xC0, 0xB5, 0xA9, 0x63,
+ 0x27, 0x7A, 0x48, 0xA4, 0x83, 0x90, 0x0C, 0x46, 0x91, 0x61, 0xB9, 0x80, 0xE4, 0x93, 0xC4, 0x83,
+ 0x43, 0x68, 0x0B, 0xC1, 0xCD, 0xB9, 0xE3, 0x93, 0x44, 0xC4, 0x30, 0x6D, 0xD3, 0x37, 0x0D, 0xEB,
+ 0x53, 0x64, 0x8D, 0x5B, 0x75, 0x7F, 0x89, 0x8F, 0x17, 0xF0, 0xFF, 0xB5, 0x9C, 0x4F, 0x2D, 0x4F,
+ 0x59, 0xB3, 0x90, 0x30, 0x1E, 0x44, 0x56, 0x22, 0xCA, 0x21, 0x16, 0x16, 0xF8, 0xFD, 0xA0, 0xA7,
+ 0xC7, 0x8F, 0xE9, 0xD1, 0xA3, 0x50, 0x69, 0x41, 0xF4, 0x38, 0xD7, 0xA2, 0x1B, 0x09, 0x05, 0xAF,
+ 0xE3, 0x4E, 0xE0, 0x08, 0x90, 0x0B, 0x18, 0x12, 0x81, 0x7F, 0x01, 0xE9, 0x0D, 0xDA, 0xC2, 0xFF,
+ 0x47, 0xFD, 0x07, 0x14, 0xF5, 0xB7, 0x17, 0xE2, 0x33, 0x6C, 0x3B, 0xE1, 0x01, 0x0C, 0x4E, 0x9E,
+ 0x4F, 0x3F, 0x85, 0x44, 0x5B, 0x9E, 0x24, 0x87, 0xA1, 0x3B, 0x9C, 0xEC, 0xC3, 0x64, 0xE6, 0x92,
+ 0x85, 0xE7, 0x97, 0xB7, 0xDF, 0x8E, 0x1B, 0xF5, 0xF0, 0x8D, 0x46, 0xF5, 0x3D, 0x8C, 0x4B, 0x96,
+ 0x39, 0xFA, 0x12, 0x86, 0xA5, 0xC8, 0xF2, 0x20, 0xA5, 0xC1, 0xEC, 0x1F, 0x27, 0xD6, 0xE6, 0x88,
+ 0x9B, 0xEA, 0xAB, 0x0F, 0x2F, 0xDE, 0x7D, 0x7E, 0xF1, 0xF1, 0xE3, 0x07, 0x6D, 0x09, 0x36, 0xAB,
+ 0xF7, 0x3F, 0x63, 0xDA, 0x02, 0x93, 0x00, 0xF7, 0x33, 0xD0, 0xE7, 0x7D, 0xA6, 0x48, 0x5B, 0xBF,
+ 0xFE, 0xF6, 0x6B, 0xFB, 0x37, 0x00, 0xFD, 0xFA, 0x5F, 0x76, 0x9D, 0x31, 0x82, 0xA8, 0x9E, 0x02,
+ 0x2E, 0x3C, 0xFE, 0x5A, 0x7F, 0x1A, 0x18, 0x7C, 0x23, 0x9D, 0xC2, 0xF0, 0xF5, 0xBA, 0xF5, 0x3D,
+ 0x60, 0xF5, 0x6E, 0x1F, 0x50, 0xB1, 0x74, 0x10, 0xC6, 0x9C, 0x06, 0x96, 0x2A, 0x4C, 0xE8, 0x40,
+ 0x7F, 0x06, 0x7F, 0xCE, 0x34, 0xFD, 0x08, 0xFE, 0x3E, 0x7D, 0x1A, 0x99, 0x48, 0xC9, 0xEE, 0xEA,
+ 0x4F, 0x4D, 0xDA, 0x19, 0xCC, 0x4E, 0x1A, 0xE6, 0x19, 0x48, 0xF2, 0x79, 0x7D, 0xBF, 0x7E, 0x5A,
+ 0xAF, 0xC3, 0xB5, 0xA0, 0xFB, 0xBB, 0x18, 0x3B, 0x77, 0xCF, 0x42, 0x0E, 0xD9, 0xE8, 0x0A, 0x37,
+ 0x22, 0xF1, 0x8B, 0x59, 0xDD, 0x4B, 0x56, 0xE5, 0x3A, 0x4F, 0xD7, 0x09, 0x7B, 0x9B, 0xF5, 0x94,
+ 0x0E, 0x88, 0x22, 0x4C, 0x86, 0x82, 0x58, 0x68, 0x08, 0x7D, 0x2D, 0x15, 0x35, 0x1D, 0x6E, 0xC7,
+ 0x63, 0x17, 0xB4, 0x4D, 0xAD, 0x65, 0x6F, 0xCD, 0x85, 0xD5, 0x70, 0x60, 0x63, 0x09, 0x8E, 0xB5,
+ 0xE9, 0x66, 0x26, 0x12, 0xDA, 0x5A, 0xC0, 0xB2, 0x96, 0xF0, 0xB4, 0xEE, 0x2F, 0xD7, 0x61, 0x1A,
+ 0x9B, 0x2A, 0x6A, 0x6C, 0x2A, 0x68, 0x6C, 0xBA, 0x59, 0x8D, 0x71, 0xD4, 0x95, 0xB5, 0x16, 0xE0,
+ 0xC9, 0xD1, 0x5C, 0x2E, 0x3C, 0x57, 0x1A, 0xD7, 0xD6, 0x54, 0xA6, 0xAD, 0x32, 0x6A, 0x62, 0xB1,
+ 0x0B, 0x26, 0x45, 0xC4, 0x7D, 0xFB, 0xF1, 0xDD, 0x77, 0x18, 0x6D, 0xE4, 0x2A, 0x0B, 0x35, 0x96,
+ 0x4C, 0xAE, 0x24, 0x18, 0x30, 0x28, 0xC6, 0x2A, 0x1F, 0x89, 0xB0, 0xA9, 0x45, 0x15, 0x84, 0x1C,
+ 0x43, 0xE0, 0x05, 0x03, 0x35, 0xDF, 0xC5, 0x22, 0x41, 0xE0, 0xBC, 0x11, 0x54, 0x86, 0x2D, 0x20,
+ 0x80, 0x92, 0x12, 0x19, 0xE6, 0x35, 0x87, 0x11, 0x6A, 0x19, 0x3B, 0x77, 0x11, 0xEA, 0xAF, 0x9E,
+ 0x6A, 0x50, 0x0B, 0xA6, 0xEA, 0x51, 0x6C, 0xF3, 0x72, 0xA5, 0xC3, 0x27, 0xF4, 0x4A, 0x02, 0xE2,
+ 0x5F, 0x95, 0x93, 0x18, 0x38, 0x2F, 0x04, 0x14, 0xC0, 0x72, 0x2B, 0xC1, 0x42, 0x0B, 0x08, 0x4A,
+ 0x38, 0xE8, 0x97, 0xC8, 0x52, 0x30, 0xA8, 0x51, 0x41, 0x3F, 0xFD, 0x25, 0xC1, 0x10, 0x94, 0x2A,
+ 0x94, 0x90, 0x04, 0x9F, 0xAD, 0x4A, 0xC7, 0xA3, 0x46, 0x4C, 0xF0, 0xB1, 0x28, 0x09, 0x1E, 0x5E,
+ 0x1A, 0x51, 0x42, 0xC3, 0x3F, 0x74, 0x94, 0x8A, 0x45, 0x8D, 0x18, 0xFE, 0x6D, 0x21, 0x19, 0x4F,
+ 0xBC, 0x14, 0xA3, 0xC6, 0x13, 0xFF, 0x24, 0x4E, 0x3A, 0x1E, 0x45, 0xD9, 0xF0, 0xCF, 0xD0, 0xC8,
+ 0xAC, 0x8E, 0x55, 0x7E, 0x32, 0x1D, 0x83, 0x35, 0x01, 0x60, 0x9E, 0xAA, 0x3E, 0xD7, 0xC5, 0xCC,
+ 0x9A, 0x17, 0x8A, 0xB2, 0x30, 0xF0, 0x26, 0x49, 0x0C, 0x41, 0x74, 0xB8, 0x87, 0x92, 0xDD, 0x7D,
+ 0x44, 0xA1, 0xF7, 0x96, 0xA5, 0x16, 0x85, 0x16, 0x96, 0x15, 0x84, 0x9F, 0x10, 0x26, 0x25, 0xFC,
+ 0xD0, 0x25, 0x33, 0x5A, 0x6F, 0xCD, 0x94, 0x3F, 0x6D, 0xC1, 0xF0, 0xAE, 0x2B, 0x11, 0x71, 0xCC,
+ 0x97, 0x96, 0x92, 0x25, 0x41, 0x3B, 0x8E, 0x46, 0x34, 0x24, 0xBA, 0x1C, 0x77, 0xEB, 0xA9, 0x85,
+ 0xAE, 0x5B, 0x2F, 0x05, 0x03, 0x2D, 0x09, 0xAB, 0xE5, 0x66, 0xD0, 0x32, 0x05, 0xC9, 0xC2, 0x55,
+ 0x4B, 0xEF, 0xA0, 0x5D, 0x1A, 0x23, 0x58, 0x7F, 0x56, 0x63, 0x25, 0xF8, 0xEA, 0xB8, 0x8C, 0x0E,
+ 0x5A, 0xB5, 0xCE, 0x52, 0x0A, 0xFF, 0xBA, 0x73, 0x9A, 0x46, 0x16, 0xAA, 0x43, 0x6E, 0xF0, 0xFD,
+ 0x63, 0xC9, 0xB0, 0x5B, 0xB2, 0xD8, 0xBF, 0x7B, 0xE7, 0x30, 0xAE, 0x89, 0x82, 0x6B, 0x84, 0x2B,
+ 0xF3, 0x3C, 0xBB, 0x8B, 0xC0, 0x32, 0xBC, 0x63, 0x64, 0xD8, 0xD7, 0x46, 0xCC, 0x3B, 0x46, 0x30,
+ 0xFD, 0xF5, 0x09, 0x47, 0xDD, 0xA8, 0xB1, 0x06, 0x35, 0x4E, 0x23, 0x3B, 0x3B, 0xA0, 0x5B, 0xD6,
+ 0xB0, 0x10, 0x62, 0x92, 0x15, 0x3B, 0x89, 0xDD, 0x9E, 0x11, 0xFA, 0x9A, 0x10, 0x7E, 0x9F, 0x9D,
+ 0xB1, 0x06, 0x61, 0x2F, 0x43, 0x67, 0x7C, 0x7B, 0x60, 0x2C, 0x16, 0x10, 0xBC, 0x2E, 0x66, 0xA6,
+ 0x35, 0x6E, 0x30, 0x50, 0xC1, 0x44, 0x70, 0x6F, 0x02, 0xA1, 0xAB, 0x56, 0x1C, 0x2B, 0x30, 0x7C,
+ 0xC1, 0xAE, 0x35, 0xEA, 0xED, 0x71, 0xB0, 0x66, 0xC4, 0x9B, 0x1D, 0x8C, 0x5D, 0x63, 0xF5, 0x2D,
+ 0x6E, 0x6A, 0x68, 0x60, 0xA7, 0xFB, 0xAD, 0xFD, 0x16, 0x6F, 0xE0, 0xBB, 0xB7, 0x61, 0x96, 0x89,
+ 0x78, 0x71, 0xF1, 0xF7, 0xC7, 0x0F, 0xDF, 0x45, 0x78, 0x7D, 0xE7, 0x15, 0xBB, 0xD4, 0xA8, 0xD3,
+ 0x5D, 0x11, 0x87, 0x7F, 0x2C, 0x70, 0x2A, 0x10, 0x28, 0x45, 0x10, 0x23, 0x6E, 0x78, 0x40, 0x51,
+ 0xB1, 0xE6, 0xCF, 0x44, 0xA4, 0x70, 0xD9, 0x26, 0x2B, 0x0D, 0x30, 0x91, 0x86, 0x0C, 0x34, 0xD8,
+ 0x0E, 0x81, 0xE0, 0xC8, 0xC9, 0xEB, 0xA5, 0x65, 0xFD, 0x42, 0x0C, 0x17, 0xF4, 0xF1, 0x54, 0x6B,
+ 0xD4, 0x5A, 0xB5, 0xA7, 0x0D, 0x7A, 0xFD, 0x1D, 0xB0, 0x33, 0x6B, 0xEC, 0x3D, 0xD5, 0xF7, 0xF6,
+ 0x0E, 0x3C, 0xD0, 0x19, 0x69, 0x34, 0xDB, 0x41, 0x13, 0xF8, 0x43, 0xDB, 0xB0, 0x4E, 0xD2, 0xEF,
+ 0xBF, 0x75, 0x96, 0xAE, 0x97, 0xD5, 0xE0, 0x9D, 0x69, 0x63, 0x11, 0x27, 0xAB, 0xC9, 0x15, 0x01,
+ 0xC1, 0x8E, 0xD7, 0x9A, 0xD4, 0xE8, 0x2E, 0x0E, 0x5E, 0xFE, 0xD0, 0xE8, 0xE2, 0xB6, 0xD6, 0x10,
+ 0x2B, 0x3A, 0x7C, 0x19, 0x91, 0xA0, 0xA1, 0x37, 0x02, 0x8F, 0xBF, 0x13, 0x8D, 0x03, 0x5C, 0x16,
+ 0x0C, 0xE0, 0x7B, 0xF0, 0x80, 0x03, 0x97, 0xCC, 0x9D, 0x6B, 0xB2, 0xA6, 0x7F, 0x6C, 0x1E, 0x1A,
+ 0xFF, 0xCC, 0x1C, 0xB3, 0x32, 0x4D, 0x64, 0xB7, 0x58, 0x15, 0xC2, 0x0D, 0x22, 0xB8, 0x85, 0x02,
+ 0xF7, 0x53, 0x34, 0xEA, 0x6C, 0xF7, 0x0A, 0x1D, 0x15, 0xEE, 0x22, 0xB7, 0x99, 0x39, 0xAB, 0x2C,
+ 0x48, 0xD6, 0x7B, 0x02, 0x38, 0x84, 0x1E, 0x9B, 0x9E, 0x31, 0xB4, 0xF2, 0xBB, 0xE6, 0xED, 0xC6,
+ 0xBC, 0xFC, 0x0D, 0x0D, 0x82, 0x2B, 0x00, 0xEA, 0xBB, 0xB4, 0x4E, 0x28, 0xA0, 0x25, 0x76, 0x1E,
+ 0xD6, 0x80, 0xAC, 0x4C, 0xC4, 0x13, 0x03, 0x26, 0x4F, 0x71, 0xCC, 0xAC, 0x78, 0x5C, 0xA0, 0xAC,
+ 0x2C, 0x5E, 0x06, 0x88, 0xF8, 0x29, 0x98, 0x33, 0x58, 0xA8, 0xF6, 0x9C, 0xB2, 0xA0, 0x9D, 0xC6,
+ 0xEE, 0x86, 0xB9, 0x8D, 0x58, 0x30, 0x7D, 0xC4, 0xE2, 0xDF, 0x5F, 0xB0, 0x82, 0x1B, 0x52, 0x1E,
+ 0x93, 0xC0, 0x93, 0x27, 0x71, 0x6C, 0xB8, 0x8D, 0x85, 0x0D, 0x20, 0x61, 0x6F, 0xAC, 0x3D, 0x7B,
+ 0x7D, 0x78, 0xB4, 0xB2, 0xC0, 0x49, 0x82, 0xA1, 0xE0, 0x71, 0x4C, 0xF0, 0xC2, 0x18, 0x01, 0x84,
+ 0x98, 0x63, 0x2A, 0x20, 0xDC, 0x95, 0x56, 0x5B, 0x5B, 0xEF, 0x7F, 0x4E, 0xAD, 0xBE, 0x41, 0xF8,
+ 0xA6, 0xC4, 0x3D, 0x90, 0x3F, 0x1A, 0x73, 0x74, 0x21, 0x3E, 0x87, 0x4E, 0x60, 0x9C, 0xC6, 0x30,
+ 0x22, 0x63, 0x09, 0xBA, 0xF1, 0x77, 0x78, 0x48, 0x31, 0x4E, 0x0D, 0xD3, 0xBE, 0x20, 0x26, 0xA6,
+ 0x7F, 0x7B, 0xC2, 0x5D, 0xDA, 0x3D, 0x20, 0xC2, 0x0D, 0x83, 0xC2, 0x72, 0xC6, 0xFA, 0x7A, 0xC8,
+ 0xE1, 0x21, 0x6D, 0x9A, 0x82, 0x86, 0x76, 0xB1, 0x8E, 0x26, 0x93, 0xFA, 0xD5, 0xF0, 0x33, 0x62,
+ 0x93, 0x09, 0x85, 0xA2, 0x5B, 0x0D, 0x51, 0x1C, 0xB4, 0x57, 0x38, 0xCC, 0x42, 0x35, 0x31, 0x46,
+ 0xE4, 0xB3, 0x0B, 0x71, 0x6C, 0x6A, 0x9B, 0x7F, 0x12, 0x19, 0x42, 0xE6, 0x8C, 0x0D, 0x62, 0xBB,
+ 0x4E, 0x90, 0x48, 0x22, 0x72, 0xEE, 0x67, 0xF1, 0xEB, 0xF1, 0x21, 0x3A, 0x70, 0xBD, 0x70, 0x69,
+ 0x5D, 0xB4, 0x05, 0x56, 0xFA, 0x8F, 0x26, 0xC0, 0x91, 0xB1, 0x6D, 0xA8, 0x12, 0xAE, 0x63, 0x19,
+ 0x3C, 0x6C, 0x22, 0xD6, 0xAB, 0x2B, 0x16, 0xC1, 0x33, 0x70, 0xB2, 0xCD, 0x7D, 0x49, 0xA4, 0xCB,
+ 0xE1, 0xDC, 0xF4, 0x25, 0x08, 0xEB, 0x7A, 0x5D, 0x8A, 0x2B, 0xA5, 0x9E, 0x2E, 0x7A, 0x22, 0x8B,
+ 0x66, 0x74, 0xA9, 0x11, 0x10, 0xC5, 0xB6, 0x0A, 0x8C, 0xD8, 0x6E, 0xF5, 0xE7, 0x30, 0xE2, 0xE2,
+ 0x06, 0x00, 0x54, 0x75, 0x62, 0x0B, 0x10, 0x43, 0xC1, 0xF6, 0xAE, 0x51, 0x14, 0xF1, 0xDD, 0x6B,
+ 0xC1, 0x8E, 0xB1, 0xF8, 0xCA, 0xA4, 0xB8, 0xF7, 0xE5, 0x77, 0x97, 0x00, 0x9C, 0x87, 0xF3, 0x59,
+ 0xED, 0x1F, 0x5F, 0x29, 0x8A, 0x3B, 0x6D, 0x02, 0x91, 0xC0, 0x9B, 0x91, 0x31, 0x9D, 0x7B, 0xF9,
+ 0x4B, 0xEF, 0x54, 0xC3, 0x6D, 0x3F, 0xB1, 0xDD, 0x6A, 0x77, 0xBF, 0x87, 0x16, 0x12, 0x0E, 0x24,
+ 0xD1, 0x7A, 0x2B, 0x67, 0x7B, 0x6D, 0xDD, 0xF5, 0x91, 0xC2, 0x0A, 0x2B, 0x87, 0x55, 0x5A, 0x65,
+ 0x95, 0x2D, 0x4E, 0x26, 0xA3, 0x14, 0xCF, 0x31, 0x1F, 0xA9, 0xF4, 0x4D, 0x77, 0x5D, 0xAA, 0x74,
+ 0x29, 0xC9, 0x2E, 0xF1, 0xC7, 0xC2, 0x98, 0x25, 0x8C, 0xF9, 0x09, 0x3F, 0xDA, 0xE3, 0x72, 0x02,
+ 0x13, 0x19, 0x07, 0xF1, 0x96, 0x19, 0x11, 0xAE, 0x3E, 0x33, 0x3D, 0xC6, 0x4C, 0x80, 0x49, 0x9B,
+ 0x0B, 0x3B, 0x7F, 0x4B, 0x22, 0x5F, 0x76, 0x09, 0x95, 0xF5, 0x87, 0x07, 0x79, 0x7B, 0x28, 0x02,
+ 0x19, 0x0E, 0xEC, 0x40, 0x40, 0x10, 0x13, 0x51, 0x21, 0x15, 0x65, 0xC8, 0x8C, 0xFD, 0x84, 0x01,
+ 0x9B, 0x8E, 0xD6, 0xB4, 0xE7, 0x5F, 0xA9, 0x55, 0xFF, 0xB6, 0xCF, 0x46, 0x78, 0x21, 0x68, 0xEE,
+ 0x15, 0x21, 0x68, 0x6D, 0x55, 0x3E, 0x97, 0x98, 0x8D, 0xAD, 0x4F, 0x06, 0x3F, 0x88, 0xC5, 0x14,
+ 0xDF, 0xB9, 0xD6, 0x5A, 0x5B, 0x97, 0x17, 0x17, 0xD1, 0x42, 0x06, 0x25, 0xB2, 0x11, 0x16, 0xD5,
+ 0x03, 0xF1, 0x48, 0x17, 0xD0, 0x52, 0xC5, 0xC5, 0xEC, 0x8B, 0x45, 0x14, 0x9C, 0x16, 0x64, 0xCE,
+ 0x9F, 0xE8, 0x86, 0x59, 0x2A, 0xAF, 0x08, 0xE0, 0x22, 0xDC, 0x20, 0x9D, 0x0B, 0x19, 0x6D, 0xA6,
+ 0x16, 0x70, 0xD0, 0xF9, 0x98, 0xDA, 0xFA, 0x03, 0x9F, 0xBA, 0x09, 0xA0, 0x88, 0x35, 0x1F, 0x36,
+ 0x78, 0x4A, 0x26, 0x49, 0xBE, 0x38, 0x7A, 0x65, 0xC1, 0xD3, 0x61, 0x92, 0x35, 0x16, 0xA0, 0xA9,
+ 0xE7, 0xE7, 0x03, 0x8B, 0xDB, 0xB2, 0xEB, 0x82, 0xB0, 0x3D, 0xDF, 0x59, 0x5C, 0xD1, 0xAB, 0x89,
+ 0xA8, 0xB0, 0xA2, 0xC5, 0xAC, 0x03, 0xBC, 0x1F, 0xCC, 0x93, 0x44, 0x46, 0xE3, 0xF5, 0xFF, 0x2B,
+ 0xAC, 0x74, 0x69, 0x0C, 0x4F, 0x3D, 0x9E, 0xED, 0xD2, 0x22, 0x98, 0xB4, 0x07, 0x3A, 0xE7, 0xF4,
+ 0xDC, 0x11, 0x1B, 0x3C, 0xC2, 0x6D, 0xD0, 0x18, 0x3A, 0xF0, 0xF0, 0x77, 0xD6, 0x27, 0xA6, 0x12,
+ 0x31, 0x05, 0xEF, 0xE5, 0xD2, 0xE2, 0x2C, 0x92, 0xA4, 0x44, 0x01, 0x9E, 0x39, 0x9B, 0x87, 0xA3,
+ 0x06, 0x1B, 0x28, 0x31, 0x7C, 0x09, 0xCA, 0x4F, 0x89, 0x91, 0x91, 0x98, 0x78, 0x50, 0x8A, 0x13,
+ 0x2F, 0x8C, 0x7C, 0x6C, 0x0F, 0xFD, 0xF3, 0xCF, 0xA3, 0x21, 0x0C, 0x76, 0x38, 0x01, 0x04, 0xD7,
+ 0x5B, 0x35, 0xF6, 0xEE, 0xB2, 0xD8, 0x61, 0xE2, 0x8A, 0x14, 0xA9, 0x4A, 0x04, 0x8D, 0xDA, 0x72,
+ 0x6C, 0x31, 0xF9, 0xC8, 0xD1, 0x89, 0xD6, 0x7B, 0x69, 0x07, 0x13, 0x96, 0x34, 0xC1, 0x9E, 0xAF,
+ 0x8B, 0x96, 0xE5, 0xAC, 0x31, 0x04, 0x51, 0x3C, 0x5E, 0x23, 0x36, 0x91, 0x94, 0x0A, 0x76, 0x11,
+ 0x34, 0x08, 0x68, 0x17, 0x1D, 0x22, 0x85, 0xF6, 0xF8, 0x58, 0x99, 0x48, 0xFF, 0x02, 0x95, 0x5F,
+ 0x2C, 0x81, 0x88, 0x79, 0xA0, 0x72, 0x76, 0x0D, 0x33, 0xDC, 0xD0, 0x36, 0x21, 0xE3, 0xCD, 0xF2,
+ 0x19, 0xB8, 0x2D, 0x38, 0x1A, 0x4F, 0x8F, 0x73, 0x00, 0x68, 0x4E, 0xCC, 0x1E, 0x84, 0xA1, 0xB0,
+ 0x6C, 0xC3, 0xAE, 0xAF, 0x09, 0x89, 0x77, 0x66, 0x7C, 0x81, 0x66, 0x23, 0xD6, 0x4C, 0x40, 0x02,
+ 0x78, 0xD7, 0xD3, 0x05, 0x89, 0x20, 0xA0, 0xDD, 0x5E, 0xA8, 0x17, 0x04, 0xE2, 0x99, 0x68, 0xA4,
+ 0x95, 0xF4, 0xD9, 0xC4, 0xFA, 0x4C, 0x22, 0xA1, 0xB0, 0xF4, 0x19, 0xC4, 0xFA, 0xEC, 0xE1, 0x4E,
+ 0xD0, 0x42, 0xF0, 0xC4, 0x56, 0x24, 0x48, 0x92, 0x2D, 0x75, 0x22, 0x4A, 0x3D, 0x98, 0x49, 0xE5,
+ 0x40, 0x7C, 0xA6, 0xA9, 0x88, 0x28, 0x32, 0xA2, 0x28, 0x32, 0xC2, 0x45, 0x86, 0x00, 0x51, 0xE2,
+ 0x9E, 0x3F, 0xAD, 0x0B, 0xE3, 0xCA, 0x4F, 0x2F, 0x23, 0xCE, 0x56, 0xC3, 0x4C, 0x3A, 0xF9, 0x94,
+ 0x49, 0x60, 0x2F, 0x1B, 0x00, 0xDA, 0xCF, 0x61, 0xDC, 0x16, 0xD9, 0x5A, 0x0D, 0xD5, 0xD8, 0x0A,
+ 0xA6, 0x5C, 0x08, 0x10, 0xB1, 0x25, 0x9F, 0x98, 0x05, 0xAC, 0xBC, 0x22, 0x3E, 0x7F, 0xAE, 0xD3,
+ 0xB0, 0xC7, 0xDA, 0xC4, 0x35, 0xE6, 0xC4, 0x83, 0x09, 0x59, 0x48, 0xEC, 0x98, 0xDE, 0xCF, 0x1D,
+ 0xA2, 0x58, 0x33, 0x81, 0xC9, 0x70, 0x6A, 0x97, 0x0B, 0x1A, 0xB6, 0x14, 0xA0, 0x43, 0x3A, 0x32,
+ 0xA1, 0x83, 0x46, 0x6C, 0x6C, 0x0B, 0x4F, 0x95, 0x84, 0x15, 0xB6, 0x8E, 0x9C, 0x27, 0x42, 0xC0,
+ 0x26, 0x4A, 0x03, 0xAD, 0x97, 0x2C, 0x27, 0xB0, 0x84, 0x87, 0x31, 0x9B, 0x48, 0x6B, 0xC4, 0x06,
+ 0x21, 0x4B, 0xB1, 0x36, 0xA1, 0x83, 0x30, 0xF8, 0x34, 0x32, 0x73, 0x49, 0x61, 0xE5, 0xEA, 0xDA,
+ 0x7B, 0x8B, 0xE0, 0x34, 0x8F, 0xBF, 0xA9, 0xF3, 0xE2, 0xDB, 0xD7, 0x9A, 0xE3, 0x6A, 0x96, 0xB3,
+ 0x22, 0xB8, 0x59, 0x34, 0x58, 0x0A, 0xD6, 0x86, 0x04, 0x12, 0x4B, 0xC2, 0x26, 0xD3, 0x18, 0x87,
+ 0xFC, 0x99, 0xE9, 0x41, 0xEA, 0x8E, 0xEF, 0x93, 0x25, 0x8F, 0x6B, 0x61, 0x31, 0x34, 0x97, 0xBD,
+ 0xF5, 0xAD, 0x55, 0x31, 0x71, 0x32, 0x98, 0x48, 0x96, 0x8F, 0x39, 0x8F, 0x6B, 0xC1, 0x28, 0x6B,
+ 0xFA, 0x5E, 0x40, 0x84, 0xE1, 0xED, 0x07, 0x2B, 0x45, 0x39, 0x03, 0xB9, 0x82, 0x0C, 0xC1, 0x22,
+ 0x59, 0x46, 0xBC, 0xAE, 0x49, 0x53, 0x56, 0x23, 0xC9, 0xD0, 0x28, 0x96, 0x0B, 0xA5, 0x71, 0x3E,
+ 0x5D, 0x2B, 0x4C, 0xE2, 0x2C, 0x55, 0x67, 0xBF, 0xB3, 0xC3, 0xE0, 0xB1, 0x39, 0x76, 0x86, 0x8B,
+ 0x05, 0x83, 0x47, 0x67, 0x87, 0x33, 0x7F, 0x6E, 0x0D, 0x1E, 0xFD, 0x2F, 0x5E, 0x72, 0x0B, 0x89,
+ 0x42, 0x10, 0x01, 0x00
+};
+
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/camera_pins.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/camera_pins.h
new file mode 100644
index 0000000..e1be287
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.1_CameraWebServer/camera_pins.h
@@ -0,0 +1,273 @@
+
+#if defined(CAMERA_MODEL_WROVER_KIT)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 21
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 19
+#define Y4_GPIO_NUM 18
+#define Y3_GPIO_NUM 5
+#define Y2_GPIO_NUM 4
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_ESP_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 37
+#define Y7_GPIO_NUM 38
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 35
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 13
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_WIDE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_AI_THINKER)
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 0
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 21
+#define Y4_GPIO_NUM 19
+#define Y3_GPIO_NUM 18
+#define Y2_GPIO_NUM 5
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
+#define PWDN_GPIO_NUM 0
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+
+#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM 33
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 19
+#define Y7_GPIO_NUM 21
+#define Y6_GPIO_NUM 39
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 13
+#else
+#define Y5_GPIO_NUM 35
+#endif
+#define Y4_GPIO_NUM 14
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 35
+#else
+#define Y3_GPIO_NUM 13
+#endif
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 40
+#define SIOD_GPIO_NUM 17
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 39
+#define Y8_GPIO_NUM 41
+#define Y7_GPIO_NUM 42
+#define Y6_GPIO_NUM 12
+#define Y5_GPIO_NUM 3
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 47
+#define Y2_GPIO_NUM 13
+#define VSYNC_GPIO_NUM 21
+#define HREF_GPIO_NUM 38
+#define PCLK_GPIO_NUM 11
+
+#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 1
+#define RESET_GPIO_NUM 2
+#define XCLK_GPIO_NUM 42
+#define SIOD_GPIO_NUM 41
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 16
+#define Y8_GPIO_NUM 39
+#define Y7_GPIO_NUM 40
+#define Y6_GPIO_NUM 15
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 12
+#else
+#define Y5_GPIO_NUM 13
+#endif
+#define Y4_GPIO_NUM 5
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 13
+#else
+#define Y3_GPIO_NUM 12
+#endif
+#define Y2_GPIO_NUM 14
+#define VSYNC_GPIO_NUM 38
+#define HREF_GPIO_NUM 4
+#define PCLK_GPIO_NUM 3
+
+#elif defined(CAMERA_MODEL_ESP32S3_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 15
+#define SIOD_GPIO_NUM 4
+#define SIOC_GPIO_NUM 5
+
+#define Y2_GPIO_NUM 11
+#define Y3_GPIO_NUM 9
+#define Y4_GPIO_NUM 8
+#define Y5_GPIO_NUM 10
+#define Y6_GPIO_NUM 12
+#define Y7_GPIO_NUM 18
+#define Y8_GPIO_NUM 17
+#define Y9_GPIO_NUM 16
+
+#define VSYNC_GPIO_NUM 6
+#define HREF_GPIO_NUM 7
+#define PCLK_GPIO_NUM 13
+
+#else
+#error "Camera model not selected"
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/Sketch_07.2_As_VideoWebServer.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/Sketch_07.2_As_VideoWebServer.ino
new file mode 100644
index 0000000..3a4962d
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/Sketch_07.2_As_VideoWebServer.ino
@@ -0,0 +1,106 @@
+/**********************************************************************
+ Filename : Video Web Server
+ Description : The camera images captured by the ESP32S3 are displayed on the web page.
+ Auther : www.freenove.com
+ Modification: 2022/11/01
+**********************************************************************/
+#include "esp_camera.h"
+#include
+#include "sd_read_write.h"
+
+// Select camera model
+#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
+
+#include "camera_pins.h"
+
+const char* ssid = "********"; //input your wifi name
+const char* password = "********"; //input your wifi passwords
+
+void cameraInit(void);
+void startCameraServer();
+
+void setup() {
+ Serial.begin(115200);
+ Serial.setDebugOutput(true);
+ Serial.println();
+
+ cameraInit();
+ sdmmcInit();
+ removeDir(SD_MMC, "/video");
+ createDir(SD_MMC, "/video");
+
+ WiFi.begin(ssid, password);
+
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(500);
+ Serial.print(".");
+ }
+ Serial.println("");
+ Serial.println("WiFi connected");
+
+ startCameraServer();
+
+ Serial.print("Camera Ready! Use 'http://");
+ Serial.print(WiFi.localIP());
+ Serial.println("' to connect");
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ delay(10000);
+}
+
+void cameraInit(void){
+ camera_config_t config;
+ config.ledc_channel = LEDC_CHANNEL_0;
+ config.ledc_timer = LEDC_TIMER_0;
+ config.pin_d0 = Y2_GPIO_NUM;
+ config.pin_d1 = Y3_GPIO_NUM;
+ config.pin_d2 = Y4_GPIO_NUM;
+ config.pin_d3 = Y5_GPIO_NUM;
+ config.pin_d4 = Y6_GPIO_NUM;
+ config.pin_d5 = Y7_GPIO_NUM;
+ config.pin_d6 = Y8_GPIO_NUM;
+ config.pin_d7 = Y9_GPIO_NUM;
+ config.pin_xclk = XCLK_GPIO_NUM;
+ config.pin_pclk = PCLK_GPIO_NUM;
+ config.pin_vsync = VSYNC_GPIO_NUM;
+ config.pin_href = HREF_GPIO_NUM;
+ config.pin_sccb_sda = SIOD_GPIO_NUM;
+ config.pin_sccb_scl = SIOC_GPIO_NUM;
+ config.pin_pwdn = PWDN_GPIO_NUM;
+ config.pin_reset = RESET_GPIO_NUM;
+ config.xclk_freq_hz = 20000000;
+ config.frame_size = FRAMESIZE_UXGA;
+ config.pixel_format = PIXFORMAT_JPEG; // for streaming
+ config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
+ config.fb_location = CAMERA_FB_IN_PSRAM;
+ config.jpeg_quality = 12;
+ config.fb_count = 1;
+
+ // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
+ // for larger pre-allocated frame buffer.
+ if(psramFound()){
+ config.jpeg_quality = 10;
+ config.fb_count = 2;
+ config.grab_mode = CAMERA_GRAB_LATEST;
+ } else {
+ // Limit the frame size when PSRAM is not available
+ config.frame_size = FRAMESIZE_SVGA;
+ config.fb_location = CAMERA_FB_IN_DRAM;
+ }
+
+ // camera init
+ esp_err_t err = esp_camera_init(&config);
+ if (err != ESP_OK) {
+ Serial.printf("Camera init failed with error 0x%x", err);
+ return;
+ }
+
+ sensor_t * s = esp_camera_sensor_get();
+ // initial sensors are flipped vertically and colors are a bit saturated
+ s->set_vflip(s, 1); // flip it back
+ s->set_brightness(s, 1); // up the brightness just a bit
+ s->set_saturation(s, 0); // lower the saturation
+}
+
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/app_httpd.cpp b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/app_httpd.cpp
new file mode 100644
index 0000000..695cc24
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/app_httpd.cpp
@@ -0,0 +1,335 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "esp_http_server.h"
+#include "esp_timer.h"
+#include "esp_camera.h"
+#include "img_converters.h"
+#include "fb_gfx.h"
+#include "driver/ledc.h"
+
+#include "sdkconfig.h"
+
+#include "Arduino.h"
+#include "sd_read_write.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#define TAG ""
+#else
+#include "esp_log.h"
+static const char *TAG = "camera_httpd";
+#endif
+
+typedef struct
+{
+ httpd_req_t *req;
+ size_t len;
+} jpg_chunking_t;
+
+#define PART_BOUNDARY "123456789000000000000987654321"
+static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
+static const char *_STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
+static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\nX-Timestamp: %d.%06d\r\n\r\n";
+
+httpd_handle_t stream_httpd = NULL;
+httpd_handle_t camera_httpd = NULL;
+
+static int button_state = 1;
+
+typedef struct
+{
+ size_t size; // number of values used for filtering
+ size_t index; // current value index
+ size_t count; // value count
+ int sum;
+ int *values; // array to be filled with values
+} ra_filter_t;
+
+static ra_filter_t ra_filter;
+
+static ra_filter_t *ra_filter_init(ra_filter_t *filter, size_t sample_size)
+{
+ memset(filter, 0, sizeof(ra_filter_t));
+
+ filter->values = (int *)malloc(sample_size * sizeof(int));
+ if (!filter->values)
+ {
+ return NULL;
+ }
+ memset(filter->values, 0, sample_size * sizeof(int));
+
+ filter->size = sample_size;
+ return filter;
+}
+
+static int ra_filter_run(ra_filter_t *filter, int value)
+{
+ if (!filter->values)
+ {
+ return value;
+ }
+ filter->sum -= filter->values[filter->index];
+ filter->values[filter->index] = value;
+ filter->sum += filter->values[filter->index];
+ filter->index++;
+ filter->index = filter->index % filter->size;
+ if (filter->count < filter->size)
+ {
+ filter->count++;
+ }
+ return filter->sum / filter->count;
+}
+
+static esp_err_t stream_handler(httpd_req_t *req)
+{
+ camera_fb_t *fb = NULL;
+ struct timeval _timestamp;
+ esp_err_t res = ESP_OK;
+ size_t _jpg_buf_len = 0;
+ uint8_t *_jpg_buf = NULL;
+ char *part_buf[128];
+
+ static int64_t last_frame = 0;
+ if (!last_frame)
+ {
+ last_frame = esp_timer_get_time();
+ }
+
+ res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
+ if (res != ESP_OK)
+ {
+ return res;
+ }
+
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ httpd_resp_set_hdr(req, "X-Framerate", "60");
+
+ while (true)
+ {
+ fb = esp_camera_fb_get();
+ if (!fb)
+ {
+ ESP_LOGE(TAG, "Camera capture failed");
+ res = ESP_FAIL;
+ }
+ else
+ {
+ _timestamp.tv_sec = fb->timestamp.tv_sec;
+ _timestamp.tv_usec = fb->timestamp.tv_usec;
+ if (fb->format != PIXFORMAT_JPEG)
+ {
+ bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
+ esp_camera_fb_return(fb);
+ fb = NULL;
+ if (!jpeg_converted)
+ {
+ ESP_LOGE(TAG, "JPEG compression failed");
+ res = ESP_FAIL;
+ }
+ }
+ else
+ {
+ _jpg_buf_len = fb->len;
+ _jpg_buf = fb->buf;
+ }
+ }
+ if (res == ESP_OK)
+ {
+ res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
+ }
+ if (res == ESP_OK)
+ {
+ size_t hlen = snprintf((char *)part_buf, 128, _STREAM_PART, _jpg_buf_len, _timestamp.tv_sec, _timestamp.tv_usec);
+ res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
+ }
+ if (res == ESP_OK)
+ {
+ res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
+ }
+ if (fb)
+ {
+ esp_camera_fb_return(fb);
+ fb = NULL;
+ _jpg_buf = NULL;
+ }
+ else if (_jpg_buf)
+ {
+ free(_jpg_buf);
+ _jpg_buf = NULL;
+ }
+ if (res != ESP_OK)
+ {
+ ESP_LOGI(TAG, "res != ESP_OK : %d , break!", res);
+ break;
+ }
+ int64_t fr_end = esp_timer_get_time();
+
+ int64_t frame_time = fr_end - last_frame;
+ last_frame = fr_end;
+ frame_time /= 1000;
+ uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
+ /*
+ ESP_LOGI(TAG, "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)",
+ (uint32_t)(_jpg_buf_len),
+ (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
+ avg_frame_time, 1000.0 / avg_frame_time);
+ */
+ }
+ ESP_LOGI(TAG, "Stream exit!");
+ last_frame = 0;
+ return res;
+}
+
+static esp_err_t parse_get(httpd_req_t *req, char **obuf)
+{
+ char *buf = NULL;
+ size_t buf_len = 0;
+
+ buf_len = httpd_req_get_url_query_len(req) + 1;
+ if (buf_len > 1)
+ {
+ buf = (char *)malloc(buf_len);
+ if (!buf)
+ {
+ httpd_resp_send_500(req);
+ return ESP_FAIL;
+ }
+ if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
+ {
+ *obuf = buf;
+ return ESP_OK;
+ }
+ free(buf);
+ }
+ httpd_resp_send_404(req);
+ return ESP_FAIL;
+}
+const char index_web[]=R"rawliteral(
+
+
+ Video Streaming Demonstration
+
+
+ Video Streaming Demonstration
+ ![]()
+
+
+
+
+)rawliteral";
+
+
+static esp_err_t index_handler(httpd_req_t *req)
+{
+ esp_err_t err;
+ err = httpd_resp_set_type(req, "text/html");
+ sensor_t *s = esp_camera_sensor_get();
+ if (s != NULL)
+ {
+ err = httpd_resp_send(req, (const char *)index_web, sizeof(index_web));
+ }
+ else
+ {
+ ESP_LOGE(TAG, "Camera sensor not found");
+ err = httpd_resp_send_500(req);
+ }
+ return err;
+}
+
+static esp_err_t button_handler(httpd_req_t *req)
+{
+ esp_err_t err;
+ camera_fb_t * fb = NULL;
+ fb = esp_camera_fb_get();
+ if (!fb)
+ {
+ ESP_LOGE(TAG, "Camera capture failed");
+ err = ESP_FAIL;
+ }
+ else
+ {
+ String video = "/video";
+ int jpgCount=readFileNum(SD_MMC, video.c_str());
+ String path = video + "/" + String(jpgCount) +".jpg";
+ writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
+ esp_camera_fb_return(fb);
+ fb = NULL;
+ err=ESP_OK;
+ }
+ return err;
+}
+
+void startCameraServer()
+{
+ httpd_config_t config = HTTPD_DEFAULT_CONFIG();
+ config.max_uri_handlers = 16;
+
+ httpd_uri_t index_uri = {
+ .uri = "/",
+ .method = HTTP_GET,
+ .handler = index_handler,
+ .user_ctx = NULL};
+
+ httpd_uri_t stream_uri = {
+ .uri = "/stream",
+ .method = HTTP_GET,
+ .handler = stream_handler,
+ .user_ctx = NULL};
+
+ httpd_uri_t button_uri = {
+ .uri = "/button",
+ .method = HTTP_POST,
+ .handler = button_handler,
+ .user_ctx = NULL};
+
+ ra_filter_init(&ra_filter, 20);
+
+ ESP_LOGI(TAG, "Starting web server on port: '%d'", config.server_port);
+ if (httpd_start(&camera_httpd, &config) == ESP_OK)
+ {
+ httpd_register_uri_handler(camera_httpd, &index_uri);
+ httpd_register_uri_handler(camera_httpd, &button_uri);
+ // httpd_register_uri_handler(camera_httpd, &stream_uri);
+ }
+
+ config.server_port += 1;
+ config.ctrl_port += 1;
+ ESP_LOGI(TAG, "Starting stream server on port: '%d'", config.server_port);
+ if (httpd_start(&stream_httpd, &config) == ESP_OK)
+ {
+ httpd_register_uri_handler(stream_httpd, &stream_uri);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/camera_pins.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/camera_pins.h
new file mode 100644
index 0000000..e1be287
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/camera_pins.h
@@ -0,0 +1,273 @@
+
+#if defined(CAMERA_MODEL_WROVER_KIT)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 21
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 19
+#define Y4_GPIO_NUM 18
+#define Y3_GPIO_NUM 5
+#define Y2_GPIO_NUM 4
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_ESP_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 37
+#define Y7_GPIO_NUM 38
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 35
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 13
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_WIDE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_AI_THINKER)
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 0
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 21
+#define Y4_GPIO_NUM 19
+#define Y3_GPIO_NUM 18
+#define Y2_GPIO_NUM 5
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
+#define PWDN_GPIO_NUM 0
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+
+#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM 33
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 19
+#define Y7_GPIO_NUM 21
+#define Y6_GPIO_NUM 39
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 13
+#else
+#define Y5_GPIO_NUM 35
+#endif
+#define Y4_GPIO_NUM 14
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 35
+#else
+#define Y3_GPIO_NUM 13
+#endif
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 40
+#define SIOD_GPIO_NUM 17
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 39
+#define Y8_GPIO_NUM 41
+#define Y7_GPIO_NUM 42
+#define Y6_GPIO_NUM 12
+#define Y5_GPIO_NUM 3
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 47
+#define Y2_GPIO_NUM 13
+#define VSYNC_GPIO_NUM 21
+#define HREF_GPIO_NUM 38
+#define PCLK_GPIO_NUM 11
+
+#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 1
+#define RESET_GPIO_NUM 2
+#define XCLK_GPIO_NUM 42
+#define SIOD_GPIO_NUM 41
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 16
+#define Y8_GPIO_NUM 39
+#define Y7_GPIO_NUM 40
+#define Y6_GPIO_NUM 15
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 12
+#else
+#define Y5_GPIO_NUM 13
+#endif
+#define Y4_GPIO_NUM 5
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 13
+#else
+#define Y3_GPIO_NUM 12
+#endif
+#define Y2_GPIO_NUM 14
+#define VSYNC_GPIO_NUM 38
+#define HREF_GPIO_NUM 4
+#define PCLK_GPIO_NUM 3
+
+#elif defined(CAMERA_MODEL_ESP32S3_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 15
+#define SIOD_GPIO_NUM 4
+#define SIOC_GPIO_NUM 5
+
+#define Y2_GPIO_NUM 11
+#define Y3_GPIO_NUM 9
+#define Y4_GPIO_NUM 8
+#define Y5_GPIO_NUM 10
+#define Y6_GPIO_NUM 12
+#define Y7_GPIO_NUM 18
+#define Y8_GPIO_NUM 17
+#define Y9_GPIO_NUM 16
+
+#define VSYNC_GPIO_NUM 6
+#define HREF_GPIO_NUM 7
+#define PCLK_GPIO_NUM 13
+
+#else
+#error "Camera model not selected"
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/sd_read_write.cpp b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/sd_read_write.cpp
new file mode 100644
index 0000000..4022aca
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/sd_read_write.cpp
@@ -0,0 +1,211 @@
+#include "sd_read_write.h"
+
+void sdmmcInit(void){
+ SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
+ if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
+ Serial.println("Card Mount Failed");
+ return;
+ }
+ uint8_t cardType = SD_MMC.cardType();
+ if(cardType == CARD_NONE){
+ Serial.println("No SD_MMC card attached");
+ return;
+ }
+ Serial.print("SD_MMC Card Type: ");
+ if(cardType == CARD_MMC){
+ Serial.println("MMC");
+ } else if(cardType == CARD_SD){
+ Serial.println("SDSC");
+ } else if(cardType == CARD_SDHC){
+ Serial.println("SDHC");
+ } else {
+ Serial.println("UNKNOWN");
+ }
+ uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
+ Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
+ Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
+ Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
+}
+
+void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
+ Serial.printf("Listing directory: %s\n", dirname);
+
+ File root = fs.open(dirname);
+ if(!root){
+ Serial.println("Failed to open directory");
+ return;
+ }
+ if(!root.isDirectory()){
+ Serial.println("Not a directory");
+ return;
+ }
+
+ File file = root.openNextFile();
+ while(file){
+ if(file.isDirectory()){
+ Serial.print(" DIR : ");
+ Serial.println(file.name());
+ if(levels){
+ listDir(fs, file.path(), levels -1);
+ }
+ } else {
+ Serial.print(" FILE: ");
+ Serial.print(file.name());
+ Serial.print(" SIZE: ");
+ Serial.println(file.size());
+ }
+ file = root.openNextFile();
+ }
+}
+
+void createDir(fs::FS &fs, const char * path){
+ Serial.printf("Creating Dir: %s\n", path);
+ if(fs.mkdir(path)){
+ Serial.println("Dir created");
+ } else {
+ Serial.println("mkdir failed");
+ }
+}
+
+void removeDir(fs::FS &fs, const char * path){
+ Serial.printf("Removing Dir: %s\n", path);
+ if(fs.rmdir(path)){
+ Serial.println("Dir removed");
+ } else {
+ Serial.println("rmdir failed");
+ }
+}
+
+void readFile(fs::FS &fs, const char * path){
+ Serial.printf("Reading file: %s\n", path);
+
+ File file = fs.open(path);
+ if(!file){
+ Serial.println("Failed to open file for reading");
+ return;
+ }
+
+ Serial.print("Read from file: ");
+ while(file.available()){
+ Serial.write(file.read());
+ }
+}
+
+void writeFile(fs::FS &fs, const char * path, const char * message){
+ Serial.printf("Writing file: %s\n", path);
+
+ File file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+ if(file.print(message)){
+ Serial.println("File written");
+ } else {
+ Serial.println("Write failed");
+ }
+}
+
+void appendFile(fs::FS &fs, const char * path, const char * message){
+ Serial.printf("Appending to file: %s\n", path);
+
+ File file = fs.open(path, FILE_APPEND);
+ if(!file){
+ Serial.println("Failed to open file for appending");
+ return;
+ }
+ if(file.print(message)){
+ Serial.println("Message appended");
+ } else {
+ Serial.println("Append failed");
+ }
+}
+
+void renameFile(fs::FS &fs, const char * path1, const char * path2){
+ Serial.printf("Renaming file %s to %s\n", path1, path2);
+ if (fs.rename(path1, path2)) {
+ Serial.println("File renamed");
+ } else {
+ Serial.println("Rename failed");
+ }
+}
+
+void deleteFile(fs::FS &fs, const char * path){
+ Serial.printf("Deleting file: %s\n", path);
+ if(fs.remove(path)){
+ Serial.println("File deleted");
+ } else {
+ Serial.println("Delete failed");
+ }
+}
+
+void testFileIO(fs::FS &fs, const char * path){
+ File file = fs.open(path);
+ static uint8_t buf[512];
+ size_t len = 0;
+ uint32_t start = millis();
+ uint32_t end = start;
+ if(file){
+ len = file.size();
+ size_t flen = len;
+ start = millis();
+ while(len){
+ size_t toRead = len;
+ if(toRead > 512){
+ toRead = 512;
+ }
+ file.read(buf, toRead);
+ len -= toRead;
+ }
+ end = millis() - start;
+ Serial.printf("%u bytes read for %u ms\r\n", flen, end);
+ file.close();
+ } else {
+ Serial.println("Failed to open file for reading");
+ }
+
+ file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+
+ size_t i;
+ start = millis();
+ for(i=0; i<2048; i++){
+ file.write(buf, 512);
+ }
+ end = millis() - start;
+ Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
+ file.close();
+}
+
+void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
+ File file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+ file.write(buf, size);
+ Serial.printf("Saved file to path: %s\r\n", path);
+}
+
+int readFileNum(fs::FS &fs, const char * dirname){
+ File root = fs.open(dirname);
+ if(!root){
+ Serial.println("Failed to open directory");
+ return -1;
+ }
+ if(!root.isDirectory()){
+ Serial.println("Not a directory");
+ return -1;
+ }
+
+ File file = root.openNextFile();
+ int num=0;
+ while(file){
+ file = root.openNextFile();
+ num++;
+ }
+ return num;
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/sd_read_write.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/sd_read_write.h
new file mode 100644
index 0000000..9486d5d
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.2_As_VideoWebServer/sd_read_write.h
@@ -0,0 +1,27 @@
+#ifndef __SD_READ_WRITE_H
+#define __SD_READ_WRITE_H
+
+#include "Arduino.h"
+#include "FS.h"
+#include "SD_MMC.h"
+
+#define SD_MMC_CMD 38 //Please do not modify it.
+#define SD_MMC_CLK 39 //Please do not modify it.
+#define SD_MMC_D0 40 //Please do not modify it.
+
+void sdmmcInit(void);
+
+void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
+void createDir(fs::FS &fs, const char * path);
+void removeDir(fs::FS &fs, const char * path);
+void readFile(fs::FS &fs, const char * path);
+void writeFile(fs::FS &fs, const char * path, const char * message);
+void appendFile(fs::FS &fs, const char * path, const char * message);
+void renameFile(fs::FS &fs, const char * path1, const char * path2);
+void deleteFile(fs::FS &fs, const char * path);
+void testFileIO(fs::FS &fs, const char * path);
+
+void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size);
+int readFileNum(fs::FS &fs, const char * dirname);
+
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/Sketch_07.3_Camera_SDcard.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/Sketch_07.3_Camera_SDcard.ino
new file mode 100644
index 0000000..919e27f
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/Sketch_07.3_Camera_SDcard.ino
@@ -0,0 +1,114 @@
+/**********************************************************************
+ Filename : Camera and SDcard
+ Description : Use the onboard buttons to take photo and save them to an SD card.
+ Auther : www.freenove.com
+ Modification: 2022/11/02
+**********************************************************************/
+#include "esp_camera.h"
+#define CAMERA_MODEL_ESP32S3_EYE
+#include "camera_pins.h"
+#include "ws2812.h"
+#include "sd_read_write.h"
+
+#define BUTTON_PIN 0
+
+void setup() {
+ Serial.begin(115200);
+ Serial.setDebugOutput(false);
+ Serial.println();
+ pinMode(BUTTON_PIN, INPUT_PULLUP);
+ ws2812Init();
+ sdmmcInit();
+ //removeDir(SD_MMC, "/camera");
+ createDir(SD_MMC, "/camera");
+ listDir(SD_MMC, "/camera", 0);
+ if(cameraSetup()==1){
+ ws2812SetColor(2);
+ }
+ else{
+ ws2812SetColor(1);
+ return;
+ }
+}
+
+void loop() {
+ if(digitalRead(BUTTON_PIN)==LOW){
+ delay(20);
+ if(digitalRead(BUTTON_PIN)==LOW){
+ ws2812SetColor(3);
+ while(digitalRead(BUTTON_PIN)==LOW);
+ camera_fb_t * fb = NULL;
+ fb = esp_camera_fb_get();
+ if (fb != NULL) {
+ int photo_index = readFileNum(SD_MMC, "/camera");
+ if(photo_index!=-1)
+ {
+ String path = "/camera/" + String(photo_index) +".jpg";
+ writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
+ }
+ esp_camera_fb_return(fb);
+ }
+ else {
+ Serial.println("Camera capture failed.");
+ }
+ ws2812SetColor(2);
+ }
+ }
+}
+
+int cameraSetup(void) {
+ camera_config_t config;
+ config.ledc_channel = LEDC_CHANNEL_0;
+ config.ledc_timer = LEDC_TIMER_0;
+ config.pin_d0 = Y2_GPIO_NUM;
+ config.pin_d1 = Y3_GPIO_NUM;
+ config.pin_d2 = Y4_GPIO_NUM;
+ config.pin_d3 = Y5_GPIO_NUM;
+ config.pin_d4 = Y6_GPIO_NUM;
+ config.pin_d5 = Y7_GPIO_NUM;
+ config.pin_d6 = Y8_GPIO_NUM;
+ config.pin_d7 = Y9_GPIO_NUM;
+ config.pin_xclk = XCLK_GPIO_NUM;
+ config.pin_pclk = PCLK_GPIO_NUM;
+ config.pin_vsync = VSYNC_GPIO_NUM;
+ config.pin_href = HREF_GPIO_NUM;
+ config.pin_sccb_sda = SIOD_GPIO_NUM;
+ config.pin_sccb_scl = SIOC_GPIO_NUM;
+ config.pin_pwdn = PWDN_GPIO_NUM;
+ config.pin_reset = RESET_GPIO_NUM;
+ config.xclk_freq_hz = 20000000;
+ config.frame_size = FRAMESIZE_UXGA;
+ config.pixel_format = PIXFORMAT_JPEG; // for streaming
+ config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
+ config.fb_location = CAMERA_FB_IN_PSRAM;
+ config.jpeg_quality = 12;
+ config.fb_count = 1;
+
+ // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
+ // for larger pre-allocated frame buffer.
+ if(psramFound()){
+ config.jpeg_quality = 10;
+ config.fb_count = 2;
+ config.grab_mode = CAMERA_GRAB_LATEST;
+ } else {
+ // Limit the frame size when PSRAM is not available
+ config.frame_size = FRAMESIZE_SVGA;
+ config.fb_location = CAMERA_FB_IN_DRAM;
+ }
+
+ // camera init
+ esp_err_t err = esp_camera_init(&config);
+ if (err != ESP_OK) {
+ Serial.printf("Camera init failed with error 0x%x", err);
+ return 0;
+ }
+
+ sensor_t * s = esp_camera_sensor_get();
+ // initial sensors are flipped vertically and colors are a bit saturated
+ s->set_vflip(s, 1); // flip it back
+ s->set_brightness(s, 1); // up the brightness just a bit
+ s->set_saturation(s, 0); // lower the saturation
+
+ Serial.println("Camera configuration complete!");
+ return 1;
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/camera_pins.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/camera_pins.h
new file mode 100644
index 0000000..e1be287
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/camera_pins.h
@@ -0,0 +1,273 @@
+
+#if defined(CAMERA_MODEL_WROVER_KIT)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 21
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 19
+#define Y4_GPIO_NUM 18
+#define Y3_GPIO_NUM 5
+#define Y2_GPIO_NUM 4
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_ESP_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 37
+#define Y7_GPIO_NUM 38
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 35
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 13
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_WIDE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_AI_THINKER)
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 0
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 21
+#define Y4_GPIO_NUM 19
+#define Y3_GPIO_NUM 18
+#define Y2_GPIO_NUM 5
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
+#define PWDN_GPIO_NUM 0
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+
+#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM 33
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 19
+#define Y7_GPIO_NUM 21
+#define Y6_GPIO_NUM 39
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 13
+#else
+#define Y5_GPIO_NUM 35
+#endif
+#define Y4_GPIO_NUM 14
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 35
+#else
+#define Y3_GPIO_NUM 13
+#endif
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 40
+#define SIOD_GPIO_NUM 17
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 39
+#define Y8_GPIO_NUM 41
+#define Y7_GPIO_NUM 42
+#define Y6_GPIO_NUM 12
+#define Y5_GPIO_NUM 3
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 47
+#define Y2_GPIO_NUM 13
+#define VSYNC_GPIO_NUM 21
+#define HREF_GPIO_NUM 38
+#define PCLK_GPIO_NUM 11
+
+#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 1
+#define RESET_GPIO_NUM 2
+#define XCLK_GPIO_NUM 42
+#define SIOD_GPIO_NUM 41
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 16
+#define Y8_GPIO_NUM 39
+#define Y7_GPIO_NUM 40
+#define Y6_GPIO_NUM 15
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 12
+#else
+#define Y5_GPIO_NUM 13
+#endif
+#define Y4_GPIO_NUM 5
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 13
+#else
+#define Y3_GPIO_NUM 12
+#endif
+#define Y2_GPIO_NUM 14
+#define VSYNC_GPIO_NUM 38
+#define HREF_GPIO_NUM 4
+#define PCLK_GPIO_NUM 3
+
+#elif defined(CAMERA_MODEL_ESP32S3_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 15
+#define SIOD_GPIO_NUM 4
+#define SIOC_GPIO_NUM 5
+
+#define Y2_GPIO_NUM 11
+#define Y3_GPIO_NUM 9
+#define Y4_GPIO_NUM 8
+#define Y5_GPIO_NUM 10
+#define Y6_GPIO_NUM 12
+#define Y7_GPIO_NUM 18
+#define Y8_GPIO_NUM 17
+#define Y9_GPIO_NUM 16
+
+#define VSYNC_GPIO_NUM 6
+#define HREF_GPIO_NUM 7
+#define PCLK_GPIO_NUM 13
+
+#else
+#error "Camera model not selected"
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/sd_read_write.cpp b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/sd_read_write.cpp
new file mode 100644
index 0000000..4022aca
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/sd_read_write.cpp
@@ -0,0 +1,211 @@
+#include "sd_read_write.h"
+
+void sdmmcInit(void){
+ SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
+ if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
+ Serial.println("Card Mount Failed");
+ return;
+ }
+ uint8_t cardType = SD_MMC.cardType();
+ if(cardType == CARD_NONE){
+ Serial.println("No SD_MMC card attached");
+ return;
+ }
+ Serial.print("SD_MMC Card Type: ");
+ if(cardType == CARD_MMC){
+ Serial.println("MMC");
+ } else if(cardType == CARD_SD){
+ Serial.println("SDSC");
+ } else if(cardType == CARD_SDHC){
+ Serial.println("SDHC");
+ } else {
+ Serial.println("UNKNOWN");
+ }
+ uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
+ Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
+ Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
+ Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
+}
+
+void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
+ Serial.printf("Listing directory: %s\n", dirname);
+
+ File root = fs.open(dirname);
+ if(!root){
+ Serial.println("Failed to open directory");
+ return;
+ }
+ if(!root.isDirectory()){
+ Serial.println("Not a directory");
+ return;
+ }
+
+ File file = root.openNextFile();
+ while(file){
+ if(file.isDirectory()){
+ Serial.print(" DIR : ");
+ Serial.println(file.name());
+ if(levels){
+ listDir(fs, file.path(), levels -1);
+ }
+ } else {
+ Serial.print(" FILE: ");
+ Serial.print(file.name());
+ Serial.print(" SIZE: ");
+ Serial.println(file.size());
+ }
+ file = root.openNextFile();
+ }
+}
+
+void createDir(fs::FS &fs, const char * path){
+ Serial.printf("Creating Dir: %s\n", path);
+ if(fs.mkdir(path)){
+ Serial.println("Dir created");
+ } else {
+ Serial.println("mkdir failed");
+ }
+}
+
+void removeDir(fs::FS &fs, const char * path){
+ Serial.printf("Removing Dir: %s\n", path);
+ if(fs.rmdir(path)){
+ Serial.println("Dir removed");
+ } else {
+ Serial.println("rmdir failed");
+ }
+}
+
+void readFile(fs::FS &fs, const char * path){
+ Serial.printf("Reading file: %s\n", path);
+
+ File file = fs.open(path);
+ if(!file){
+ Serial.println("Failed to open file for reading");
+ return;
+ }
+
+ Serial.print("Read from file: ");
+ while(file.available()){
+ Serial.write(file.read());
+ }
+}
+
+void writeFile(fs::FS &fs, const char * path, const char * message){
+ Serial.printf("Writing file: %s\n", path);
+
+ File file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+ if(file.print(message)){
+ Serial.println("File written");
+ } else {
+ Serial.println("Write failed");
+ }
+}
+
+void appendFile(fs::FS &fs, const char * path, const char * message){
+ Serial.printf("Appending to file: %s\n", path);
+
+ File file = fs.open(path, FILE_APPEND);
+ if(!file){
+ Serial.println("Failed to open file for appending");
+ return;
+ }
+ if(file.print(message)){
+ Serial.println("Message appended");
+ } else {
+ Serial.println("Append failed");
+ }
+}
+
+void renameFile(fs::FS &fs, const char * path1, const char * path2){
+ Serial.printf("Renaming file %s to %s\n", path1, path2);
+ if (fs.rename(path1, path2)) {
+ Serial.println("File renamed");
+ } else {
+ Serial.println("Rename failed");
+ }
+}
+
+void deleteFile(fs::FS &fs, const char * path){
+ Serial.printf("Deleting file: %s\n", path);
+ if(fs.remove(path)){
+ Serial.println("File deleted");
+ } else {
+ Serial.println("Delete failed");
+ }
+}
+
+void testFileIO(fs::FS &fs, const char * path){
+ File file = fs.open(path);
+ static uint8_t buf[512];
+ size_t len = 0;
+ uint32_t start = millis();
+ uint32_t end = start;
+ if(file){
+ len = file.size();
+ size_t flen = len;
+ start = millis();
+ while(len){
+ size_t toRead = len;
+ if(toRead > 512){
+ toRead = 512;
+ }
+ file.read(buf, toRead);
+ len -= toRead;
+ }
+ end = millis() - start;
+ Serial.printf("%u bytes read for %u ms\r\n", flen, end);
+ file.close();
+ } else {
+ Serial.println("Failed to open file for reading");
+ }
+
+ file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+
+ size_t i;
+ start = millis();
+ for(i=0; i<2048; i++){
+ file.write(buf, 512);
+ }
+ end = millis() - start;
+ Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
+ file.close();
+}
+
+void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
+ File file = fs.open(path, FILE_WRITE);
+ if(!file){
+ Serial.println("Failed to open file for writing");
+ return;
+ }
+ file.write(buf, size);
+ Serial.printf("Saved file to path: %s\r\n", path);
+}
+
+int readFileNum(fs::FS &fs, const char * dirname){
+ File root = fs.open(dirname);
+ if(!root){
+ Serial.println("Failed to open directory");
+ return -1;
+ }
+ if(!root.isDirectory()){
+ Serial.println("Not a directory");
+ return -1;
+ }
+
+ File file = root.openNextFile();
+ int num=0;
+ while(file){
+ file = root.openNextFile();
+ num++;
+ }
+ return num;
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/sd_read_write.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/sd_read_write.h
new file mode 100644
index 0000000..9486d5d
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/sd_read_write.h
@@ -0,0 +1,27 @@
+#ifndef __SD_READ_WRITE_H
+#define __SD_READ_WRITE_H
+
+#include "Arduino.h"
+#include "FS.h"
+#include "SD_MMC.h"
+
+#define SD_MMC_CMD 38 //Please do not modify it.
+#define SD_MMC_CLK 39 //Please do not modify it.
+#define SD_MMC_D0 40 //Please do not modify it.
+
+void sdmmcInit(void);
+
+void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
+void createDir(fs::FS &fs, const char * path);
+void removeDir(fs::FS &fs, const char * path);
+void readFile(fs::FS &fs, const char * path);
+void writeFile(fs::FS &fs, const char * path, const char * message);
+void appendFile(fs::FS &fs, const char * path, const char * message);
+void renameFile(fs::FS &fs, const char * path1, const char * path2);
+void deleteFile(fs::FS &fs, const char * path);
+void testFileIO(fs::FS &fs, const char * path);
+
+void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size);
+int readFileNum(fs::FS &fs, const char * dirname);
+
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/ws2812.cpp b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/ws2812.cpp
new file mode 100644
index 0000000..7ffcd95
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/ws2812.cpp
@@ -0,0 +1,35 @@
+
+#include "ws2812.h"
+
+Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(1, WS2812_PIN, 1, TYPE_GRB);
+
+void ws2812Init(void)
+{
+ strip.begin();
+ strip.setBrightness(10);
+ ws2812SetColor(0);
+}
+void ws2812SetColor(int color)
+{
+ if(color==0)
+ {
+ strip.setLedColorData(0, 0, 0, 0);
+ }
+ else if(color==1)
+ {
+ strip.setLedColorData(0, 255, 0, 0);
+ }
+ else if(color==2)
+ {
+ strip.setLedColorData(0, 0, 255, 0);
+ }
+ else if(color==3)
+ {
+ strip.setLedColorData(0, 0, 0, 255);
+ }
+ strip.show();
+}
+
+
+
+
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/ws2812.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/ws2812.h
new file mode 100644
index 0000000..91f9e41
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_07.3_Camera_SDcard/ws2812.h
@@ -0,0 +1,12 @@
+#ifndef __WS2812_H
+#define __WS2812_H
+
+#include "Freenove_WS2812_Lib_for_ESP32.h"
+
+#define WS2812_PIN 48
+
+void ws2812Init(void);
+void ws2812SetColor(int color);
+
+#endif
+
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_08.1_CameraTcpServer/Sketch_08.1_CameraTcpServer.ino b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_08.1_CameraTcpServer/Sketch_08.1_CameraTcpServer.ino
new file mode 100644
index 0000000..166cd62
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_08.1_CameraTcpServer/Sketch_08.1_CameraTcpServer.ino
@@ -0,0 +1,182 @@
+/**********************************************************************
+ Filename : Camera Tcp Serrver
+ Description : Users use Freenove's APP to view images from ESP32S3's camera
+ Auther : www.freenove.com
+ Modification: 2024/07/01
+**********************************************************************/
+#include "esp_camera.h"
+#include
+#include
+#include
+
+#define CAMERA_MODEL_ESP32S3_EYE
+#include "camera_pins.h"
+#define LED_BUILT_IN 2
+
+const char* ssid_Router = "********";
+const char* password_Router = "********";
+const char *ssid_AP = "********";
+const char *password_AP = "********";
+
+WiFiServer server_Cmd(5000);
+WiFiServer server_Camera(8000);
+extern TaskHandle_t loopTaskHandle;
+
+void setup() {
+ Serial.begin(115200);
+ Serial.setDebugOutput(false);
+ Serial.println();
+ pinMode(LED_BUILT_IN, OUTPUT);
+ cameraSetup();
+
+ WiFi.softAP(ssid_AP, password_AP);
+ IPAddress myIP = WiFi.softAPIP();
+ Serial.print("AP IP address: ");
+ Serial.println(myIP);
+ server_Camera.begin(8000);
+ server_Cmd.begin(5000);
+ /////////////////////////////////////////////////////
+ WiFi.begin(ssid_Router, password_Router);
+ Serial.print("Connecting ");
+ Serial.print(ssid_Router);
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(500);
+ Serial.print(".");
+ }
+ while (WiFi.STA.hasIP() != true) {
+ Serial.print(".");
+ delay(500);
+ }
+ Serial.println("");
+ Serial.println("WiFi connected");
+ /////////////////////////////////////////////////////
+ Serial.print("Camera Ready! Use '");
+ Serial.print(WiFi.softAPIP());
+ Serial.print(" or ");
+ Serial.print(WiFi.localIP());
+ Serial.println("' to connect in Freenove app.");
+
+ disableCore0WDT();
+ xTaskCreateUniversal(loopTask_Cmd, "loopTask_Cmd", 8192, NULL, 1, &loopTaskHandle, 0); //loopTask_Cmd uses core 0.
+ xTaskCreateUniversal(loopTask_Blink, "loopTask_Blink", 8192, NULL, 1, &loopTaskHandle, 0);//loopTask_Blink uses core 0.
+}
+//task loop uses core 1.
+void loop() {
+ WiFiClient client = server_Camera.accept(); // listen for incoming clients
+ if (client) { // if you get a client,
+ Serial.println("Camera Server connected to a client.");// print a message out the serial port
+ String currentLine = ""; // make a String to hold incoming data from the client
+ while (client.connected()) { // loop while the client's connected
+ camera_fb_t * fb = NULL;
+ while (client.connected()) {
+ fb = esp_camera_fb_get();
+ if (fb != NULL) {
+ uint8_t slen[4];
+ slen[0] = fb->len >> 0;
+ slen[1] = fb->len >> 8;
+ slen[2] = fb->len >> 16;
+ slen[3] = fb->len >> 24;
+ client.write(slen, 4);
+ client.write(fb->buf, fb->len);
+ esp_camera_fb_return(fb);
+ }
+ else {
+ Serial.println("Camera Error");
+ }
+ }
+ }
+ // close the connection:
+ client.stop();
+ Serial.println("Camera Client Disconnected.");
+ }
+}
+
+void loopTask_Cmd(void *pvParameters) {
+ Serial.println("Task Cmd_Server is starting ... ");
+ while (1) {
+ WiFiClient client = server_Cmd.accept(); // listen for incoming clients
+ if (client) { // if you get a client,
+ Serial.println("Command Server connected to a client.");// print a message out the serial port
+ String currentLine = ""; // make a String to hold incoming data from the client
+ while (client.connected()) { // loop while the client's connected
+ if (client.available()) { // if there's bytes to read from the client,
+ char c = client.read(); // read a byte, then
+ client.write(c);
+ Serial.write(c); // print it out the serial monitor
+ if (c == '\n') { // if the byte is a newline character
+ currentLine = "";
+ }
+ else {
+ currentLine += c; // add it to the end of the currentLine
+ }
+ }
+ }
+ // close the connection:
+ client.stop();
+ Serial.println("Command Client Disconnected.");
+ }
+ }
+}
+void loopTask_Blink(void *pvParameters) {
+ Serial.println("Task Blink is starting ... ");
+ while (1) {
+ digitalWrite(LED_BUILT_IN, !digitalRead(LED_BUILT_IN));
+ delay(1000);
+ }
+}
+
+void cameraSetup() {
+ camera_config_t config;
+ config.ledc_channel = LEDC_CHANNEL_0;
+ config.ledc_timer = LEDC_TIMER_0;
+ config.pin_d0 = Y2_GPIO_NUM;
+ config.pin_d1 = Y3_GPIO_NUM;
+ config.pin_d2 = Y4_GPIO_NUM;
+ config.pin_d3 = Y5_GPIO_NUM;
+ config.pin_d4 = Y6_GPIO_NUM;
+ config.pin_d5 = Y7_GPIO_NUM;
+ config.pin_d6 = Y8_GPIO_NUM;
+ config.pin_d7 = Y9_GPIO_NUM;
+ config.pin_xclk = XCLK_GPIO_NUM;
+ config.pin_pclk = PCLK_GPIO_NUM;
+ config.pin_vsync = VSYNC_GPIO_NUM;
+ config.pin_href = HREF_GPIO_NUM;
+ config.pin_sccb_sda = SIOD_GPIO_NUM;
+ config.pin_sccb_scl = SIOC_GPIO_NUM;
+ config.pin_pwdn = PWDN_GPIO_NUM;
+ config.pin_reset = RESET_GPIO_NUM;
+ config.xclk_freq_hz = 20000000;
+ config.frame_size = FRAMESIZE_UXGA;
+ config.pixel_format = PIXFORMAT_JPEG; // for streaming
+ config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
+ config.fb_location = CAMERA_FB_IN_PSRAM;
+ config.jpeg_quality = 12;
+ config.fb_count = 1;
+
+ // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
+ // for larger pre-allocated frame buffer.
+ if(psramFound()){
+ config.jpeg_quality = 10;
+ config.fb_count = 2;
+ config.grab_mode = CAMERA_GRAB_LATEST;
+ } else {
+ // Limit the frame size when PSRAM is not available
+ config.frame_size = FRAMESIZE_SVGA;
+ config.fb_location = CAMERA_FB_IN_DRAM;
+ }
+
+ // camera init
+ esp_err_t err = esp_camera_init(&config);
+ if (err != ESP_OK) {
+ Serial.printf("Camera init failed with error 0x%x", err);
+ return;
+ }
+
+ sensor_t * s = esp_camera_sensor_get();
+ // initial sensors are flipped vertically and colors are a bit saturated
+ s->set_vflip(s, 1); // flip it back
+ s->set_brightness(s, 1); // up the brightness just a bit
+ s->set_saturation(s, 0); // lower the saturation
+
+ Serial.println("Camera configuration complete!");
+}
diff --git a/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_08.1_CameraTcpServer/camera_pins.h b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_08.1_CameraTcpServer/camera_pins.h
new file mode 100644
index 0000000..e1be287
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/C/Sketches/Sketch_08.1_CameraTcpServer/camera_pins.h
@@ -0,0 +1,273 @@
+
+#if defined(CAMERA_MODEL_WROVER_KIT)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 21
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 19
+#define Y4_GPIO_NUM 18
+#define Y3_GPIO_NUM 5
+#define Y2_GPIO_NUM 4
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_ESP_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 37
+#define Y7_GPIO_NUM 38
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 35
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 13
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_WIDE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 22
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 32
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+#elif defined(CAMERA_MODEL_AI_THINKER)
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 0
+#define SIOD_GPIO_NUM 26
+#define SIOC_GPIO_NUM 27
+
+#define Y9_GPIO_NUM 35
+#define Y8_GPIO_NUM 34
+#define Y7_GPIO_NUM 39
+#define Y6_GPIO_NUM 36
+#define Y5_GPIO_NUM 21
+#define Y4_GPIO_NUM 19
+#define Y3_GPIO_NUM 18
+#define Y2_GPIO_NUM 5
+#define VSYNC_GPIO_NUM 25
+#define HREF_GPIO_NUM 23
+#define PCLK_GPIO_NUM 22
+
+#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
+#define PWDN_GPIO_NUM 0
+#define RESET_GPIO_NUM 15
+#define XCLK_GPIO_NUM 27
+#define SIOD_GPIO_NUM 25
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 19
+#define Y8_GPIO_NUM 36
+#define Y7_GPIO_NUM 18
+#define Y6_GPIO_NUM 39
+#define Y5_GPIO_NUM 5
+#define Y4_GPIO_NUM 34
+#define Y3_GPIO_NUM 35
+#define Y2_GPIO_NUM 17
+#define VSYNC_GPIO_NUM 22
+#define HREF_GPIO_NUM 26
+#define PCLK_GPIO_NUM 21
+
+
+#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 32
+#define RESET_GPIO_NUM 33
+#define XCLK_GPIO_NUM 4
+#define SIOD_GPIO_NUM 18
+#define SIOC_GPIO_NUM 23
+
+#define Y9_GPIO_NUM 36
+#define Y8_GPIO_NUM 19
+#define Y7_GPIO_NUM 21
+#define Y6_GPIO_NUM 39
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 13
+#else
+#define Y5_GPIO_NUM 35
+#endif
+#define Y4_GPIO_NUM 14
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 35
+#else
+#define Y3_GPIO_NUM 13
+#endif
+#define Y2_GPIO_NUM 34
+#define VSYNC_GPIO_NUM 5
+#define HREF_GPIO_NUM 27
+#define PCLK_GPIO_NUM 25
+
+#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 40
+#define SIOD_GPIO_NUM 17
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 39
+#define Y8_GPIO_NUM 41
+#define Y7_GPIO_NUM 42
+#define Y6_GPIO_NUM 12
+#define Y5_GPIO_NUM 3
+#define Y4_GPIO_NUM 14
+#define Y3_GPIO_NUM 47
+#define Y2_GPIO_NUM 13
+#define VSYNC_GPIO_NUM 21
+#define HREF_GPIO_NUM 38
+#define PCLK_GPIO_NUM 11
+
+#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
+// The 18 pin header on the board has Y5 and Y3 swapped
+#define USE_BOARD_HEADER 0
+#define PWDN_GPIO_NUM 1
+#define RESET_GPIO_NUM 2
+#define XCLK_GPIO_NUM 42
+#define SIOD_GPIO_NUM 41
+#define SIOC_GPIO_NUM 18
+
+#define Y9_GPIO_NUM 16
+#define Y8_GPIO_NUM 39
+#define Y7_GPIO_NUM 40
+#define Y6_GPIO_NUM 15
+#if USE_BOARD_HEADER
+#define Y5_GPIO_NUM 12
+#else
+#define Y5_GPIO_NUM 13
+#endif
+#define Y4_GPIO_NUM 5
+#if USE_BOARD_HEADER
+#define Y3_GPIO_NUM 13
+#else
+#define Y3_GPIO_NUM 12
+#endif
+#define Y2_GPIO_NUM 14
+#define VSYNC_GPIO_NUM 38
+#define HREF_GPIO_NUM 4
+#define PCLK_GPIO_NUM 3
+
+#elif defined(CAMERA_MODEL_ESP32S3_EYE)
+#define PWDN_GPIO_NUM -1
+#define RESET_GPIO_NUM -1
+#define XCLK_GPIO_NUM 15
+#define SIOD_GPIO_NUM 4
+#define SIOC_GPIO_NUM 5
+
+#define Y2_GPIO_NUM 11
+#define Y3_GPIO_NUM 9
+#define Y4_GPIO_NUM 8
+#define Y5_GPIO_NUM 10
+#define Y6_GPIO_NUM 12
+#define Y7_GPIO_NUM 18
+#define Y8_GPIO_NUM 17
+#define Y9_GPIO_NUM 16
+
+#define VSYNC_GPIO_NUM 6
+#define HREF_GPIO_NUM 7
+#define PCLK_GPIO_NUM 13
+
+#else
+#error "Camera model not selected"
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/Linux/Linux.png b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/Linux.png
new file mode 100644
index 0000000..887fcf0
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/Linux.png differ
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux.zip b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux.zip
new file mode 100644
index 0000000..f9464a1
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux.zip differ
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/README.md b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/README.md
new file mode 100644
index 0000000..55d9984
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/README.md
@@ -0,0 +1,29 @@
+# ch343 linux serial driver
+
+## Description
+
+ USB to UART(s) chip ch342/ch343/ch344/ch347/ch9101/ch9102/ch9103 are fully compliant to the Communications Device Class (CDC) standard, they will work with a standard CDC-ACM driver (CDC - Abstract Control Model). Linux operating systems supply a default CDC-ACM driver that can be used with these USB UART devices. In Linux, this driver file name is cdc-acm.
+
+ The CDC-ACM driver has limited capabilities to control specific devices. This generic driver does not have any knowledge about specific device protocols. Because of this, device manufacturers can create an alternate, or custom driver that is capable of accessing the device specific function sets, such as hardware flow control or GPIO functions.
+
+ If you use this VCP driver, please check that the CDC-ACM driver was not installed for the USB UART devices mentioned above. You can use command "ls /dev/ttyACM*" to confirm that, to remove the CDC-ACM driver, use command "rmmod cdc-acm".
+
+ This directory contains 2 parts, ch343 driver and gpio testing utility. This driver and application support USB to single serial port chip ch343/ch347/ch9101/ch9102, USB to dual serial ports chip ch342/ch347/ch9103, USB to quad serial ports chip ch344, etc.
+
+1. Open "Terminal"
+2. Switch to "driver" directory
+3. Compile the driver using "make", you will see the module "ch343.ko" if successful
+4. Type "sudo make load" or "sudo insmod ch343.ko" to load the driver dynamically
+5. Type "sudo make unload" or "sudo rmmod ch343.ko" to unload the driver
+6. Type "sudo make install" to make the driver work permanently
+7. Type "sudo make uninstall" to remove the driver
+8. You can refer to the link below to acquire uart application, you can use gcc or Cross-compile with cross-gcc
+ https://github.com/WCHSoftGroup/tty_uart
+
+ Before the driver works, you should make sure that the usb device has been plugged in and is working properly, you can use shell command "lsusb" or "dmesg" to confirm that, USB VID of these devices are [1A86], you can view all IDs from the id table which defined in "ch343.c".
+
+ If the device works well, the driver will created tty devices named "ttyCH343USBx" in /dev directory. Operating the device in the /dev directory under Linux requires root permission by default, if users want to access the device in a non root mode, they can create udev rule file related to the device.
+
+## Note
+
+ Any question, you can send feedback to mail: tech@wch.cn
\ No newline at end of file
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/Makefile b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/Makefile
new file mode 100644
index 0000000..0535ecb
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/Makefile
@@ -0,0 +1,22 @@
+ifeq ($(KERNELRELEASE), )
+KERNELDIR := /lib/modules/$(shell uname -r)/build
+PWD :=$(shell pwd)
+default:
+ $(MAKE) -C $(KERNELDIR) M=$(PWD)
+clean:
+ rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
+load:
+ insmod ch343.ko
+unload:
+ rmmod ch343
+install: default
+ mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial
+ cp -f ./ch343.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial
+ echo "ch343\n" >> /etc/modules
+ depmod -a
+uninstall:
+ rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch343.ko
+ depmod -a
+else
+ obj-m := ch343.o
+endif
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/ch343.c b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/ch343.c
new file mode 100644
index 0000000..5466302
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/ch343.c
@@ -0,0 +1,2000 @@
+/*
+ * USB serial driver for USB to UART(s) chip ch342/ch343/ch344/ch347/ch9101/ch9102/ch9103/ch9104, etc.
+ *
+ * Copyright (C) 2022 Nanjing Qinheng Microelectronics Co., Ltd.
+ * Web: http://wch.cn
+ * Author: WCH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * System required:
+ * Kernel version beyond 3.4.x
+ * Update Log:
+ * V1.0 - initial version
+ * V1.1 - added support of chip ch344, ch9101 and ch9103
+ * V1.2 - added gpio support of chip ch344
+ * V1.3 - added support of chip ch347
+ * V1.4 - added support of chip ch9104
+ * V1.5 - added gpio character device
+ * - added supports for kernel version beyond 5.14.x
+ * - removed the gpio ioctl commands
+ */
+
+#define DEBUG
+#define VERBOSE_DEBUG
+
+#undef DEBUG
+#undef VERBOSE_DEBUG
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
+#include
+#endif
+
+#include "ch343.h"
+
+#define DRIVER_AUTHOR "WCH"
+#define DRIVER_DESC "USB serial driver for ch342/ch343/ch344/ch347/ch9101/ch9102/ch9103/ch9104, etc."
+#define VERSION_DESC "V1.5 On 2022.12"
+
+#define IOCTL_MAGIC 'W'
+#define IOCTL_CMD_GETCHIPTYPE _IOR(IOCTL_MAGIC, 0x84, u16)
+#define IOCTL_CMD_CTRLIN _IOWR(IOCTL_MAGIC, 0x90, u16)
+#define IOCTL_CMD_CTRLOUT _IOW(IOCTL_MAGIC, 0x91, u16)
+#define IOCTL_CMD_GICOUNT _IOR(IOCTL_MAGIC, 0x92, u16)
+
+static struct usb_driver ch343_driver;
+static struct tty_driver *ch343_tty_driver;
+static struct usb_interface *g_intf;
+
+static DEFINE_IDR(ch343_minors);
+static DEFINE_MUTEX(ch343_minors_lock);
+
+static void ch343_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old);
+
+/*
+ * Look up an ch343 structure by minor. If found and not disconnected, increment
+ * its refcount and return it with its mutex held.
+ */
+static struct ch343 *ch343_get_by_minor(unsigned int minor)
+{
+ struct ch343 *ch343;
+
+ mutex_lock(&ch343_minors_lock);
+ ch343 = idr_find(&ch343_minors, minor);
+ if (ch343) {
+ mutex_lock(&ch343->mutex);
+ if (ch343->disconnected) {
+ mutex_unlock(&ch343->mutex);
+ ch343 = NULL;
+ } else {
+ tty_port_get(&ch343->port);
+ mutex_unlock(&ch343->mutex);
+ }
+ }
+ mutex_unlock(&ch343_minors_lock);
+ return ch343;
+}
+
+/*
+ * Try to find an available minor number and if found, associate it with 'ch343'.
+ */
+static int ch343_alloc_minor(struct ch343 *ch343)
+{
+ int minor;
+
+ mutex_lock(&ch343_minors_lock);
+ minor = idr_alloc(&ch343_minors, ch343, 0, CH343_TTY_MINORS, GFP_KERNEL);
+ mutex_unlock(&ch343_minors_lock);
+
+ return minor;
+}
+
+/* Release the minor number associated with 'ch343'. */
+static void ch343_release_minor(struct ch343 *ch343)
+{
+ mutex_lock(&ch343_minors_lock);
+ idr_remove(&ch343_minors, ch343->minor);
+ mutex_unlock(&ch343_minors_lock);
+}
+
+/*
+ * Functions for CH343 control messages.
+ */
+static int ch343_control_out(struct ch343 *ch343, u8 request, u16 value, u16 index)
+{
+ int retval;
+
+ retval = usb_autopm_get_interface(ch343->control);
+ if (retval)
+ return retval;
+
+ retval = usb_control_msg(ch343->dev, usb_sndctrlpipe(ch343->dev, 0), request,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, value, index, NULL, 0, DEFAULT_TIMEOUT);
+
+ usb_autopm_put_interface(ch343->control);
+
+ return retval;
+}
+
+static int ch343_control_in(struct ch343 *ch343, u8 request, u16 value, u16 index, char *buf, unsigned bufsize)
+{
+ int retval;
+
+ retval = usb_autopm_get_interface(ch343->control);
+ if (retval)
+ return retval;
+
+ retval =
+ usb_control_msg(ch343->dev, usb_rcvctrlpipe(ch343->dev, 0), request,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, value, index, buf, bufsize, DEFAULT_TIMEOUT);
+
+ usb_autopm_put_interface(ch343->control);
+
+ return retval;
+}
+
+static int ch343_control_msg_out(struct ch343 *ch343, u8 request, u8 requesttype, u16 value, u16 index, void *buf,
+ unsigned bufsize)
+{
+ int retval;
+ char *buffer;
+
+ buffer = kmalloc(bufsize, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ retval = copy_from_user(buffer, (char __user *)buf, bufsize);
+ if (retval)
+ goto out;
+
+ retval = usb_autopm_get_interface(ch343->control);
+ if (retval)
+ goto out;
+
+ retval = usb_control_msg(ch343->dev, usb_sndctrlpipe(ch343->dev, 0), request, requesttype, value, index, buf,
+ bufsize, DEFAULT_TIMEOUT);
+
+ usb_autopm_put_interface(ch343->control);
+
+out:
+ kfree(buffer);
+ return retval;
+}
+
+static int ch343_control_msg_in(struct ch343 *ch343, u8 request, u8 requesttype, u16 value, u16 index, void *buf,
+ unsigned bufsize)
+{
+ int retval;
+ char *buffer;
+
+ buffer = kmalloc(bufsize, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ retval = usb_autopm_get_interface(ch343->control);
+ if (retval)
+ goto out;
+
+ retval = usb_control_msg(ch343->dev, usb_rcvctrlpipe(ch343->dev, 0), request, requesttype, value, index, buffer,
+ bufsize, DEFAULT_TIMEOUT);
+ if (retval > 0) {
+ if (copy_to_user((char __user *)buf, buffer, retval)) {
+ retval = -EFAULT;
+ }
+ }
+
+ usb_autopm_put_interface(ch343->control);
+
+out:
+ kfree(buffer);
+ return retval;
+}
+
+static inline int ch343_set_control(struct ch343 *ch343, int control)
+{
+ if (ch343->iface <= 1)
+ return ch343_control_out(ch343, CMD_C2 + ch343->iface, ~control, 0x0000);
+ else if (ch343->iface <= 3)
+ return ch343_control_out(ch343, CMD_C2 + 0x10 + (ch343->iface - 2), ~control, 0x0000);
+ else
+ return -1;
+}
+
+static inline int ch343_set_line(struct ch343 *ch343, struct usb_cdc_line_coding *line)
+{
+ return 0;
+}
+
+static int ch343_get_status(struct ch343 *ch343)
+{
+ char *buffer;
+ int retval;
+ const unsigned size = 2;
+ unsigned long flags;
+
+ buffer = kmalloc(size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ retval = ch343_control_in(ch343, CMD_R, CMD_C3 + ch343->iface, 0, buffer, size);
+ if (retval != size)
+ goto out;
+
+ /* setup the private status if available */
+ spin_lock_irqsave(&ch343->read_lock, flags);
+ ch343->ctrlin = (~(*buffer)) & CH343_CTI_ST;
+ spin_unlock_irqrestore(&ch343->read_lock, flags);
+
+out:
+ kfree(buffer);
+ return retval;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static int ch343_configure(struct ch343 *ch343)
+{
+ char *buffer;
+ int r;
+ const unsigned size = 2;
+ u8 chiptype;
+
+ buffer = kmalloc(size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ r = ch343_control_in(ch343, CMD_C6, 0, 0, buffer, size);
+ if (r != size)
+ goto out;
+
+ chiptype = buffer[1];
+
+ switch (ch343->idProduct) {
+ case 0x55D2:
+ if (chiptype == 0x48)
+ ch343->chiptype = CHIP_CH342F;
+ else if (chiptype == 0x41)
+ ch343->chiptype = CHIP_CH342K;
+ break;
+ case 0x55D3:
+ if (chiptype == 0x08)
+ ch343->chiptype = CHIP_CH343GP;
+ else if (chiptype == 0x02)
+ ch343->chiptype = CHIP_CH343J;
+ else if (chiptype == 0x01)
+ ch343->chiptype = CHIP_CH343K;
+ else if (chiptype == 0x18)
+ ch343->chiptype = CHIP_CH343G_AUTOBAUD;
+ break;
+ case 0x55D4:
+ if (chiptype == 0x08)
+ ch343->chiptype = CHIP_CH9102F;
+ else if (chiptype == 0x09)
+ ch343->chiptype = CHIP_CH9102X;
+ break;
+ case 0x55D5:
+ if (chiptype == 0xC0) {
+ if ((buffer[0] & 0xF0) == 0x40)
+ ch343->chiptype = CHIP_CH344L;
+ else
+ ch343->chiptype = CHIP_CH344L_V2;
+ } else
+ ch343->chiptype = CHIP_CH344Q;
+ break;
+ case 0x55D7:
+ if (chiptype == 0x4B)
+ ch343->chiptype = CHIP_CH9103M;
+ break;
+ case 0x55D8:
+ if (chiptype == 0x08)
+ ch343->chiptype = CHIP_CH9101UH;
+ else if (chiptype == 0x0A)
+ ch343->chiptype = CHIP_CH9101RY;
+ break;
+ case 0x55DA:
+ case 0x55DB:
+ case 0x55DD:
+ ch343->chiptype = CHIP_CH347T;
+ break;
+ case 0x55DF:
+ ch343->chiptype = CHIP_CH9104L;
+ break;
+ default:
+ break;
+ }
+
+ if (ch343->chiptype != CHIP_CH344L && ch343->chiptype != CHIP_CH344L_V2 && ch343->chiptype != CHIP_CH9104L) {
+ r = ch343_get_status(ch343);
+ if (r < 0)
+ goto out;
+ }
+
+ dev_dbg(&ch343->data->dev, "%s - chip hver : 0x%2x, sver : 0x%2x, chip : %d\n", __func__, buffer[0], buffer[1],
+ ch343->chiptype);
+out:
+ kfree(buffer);
+ return r < 0 ? r : 0;
+}
+
+/*
+ * Write buffer management.
+ * All of these assume proper locks taken by the caller.
+ */
+static int ch343_wb_alloc(struct ch343 *ch343)
+{
+ int i, wbn;
+ struct ch343_wb *wb;
+
+ wbn = 0;
+ i = 0;
+ for (;;) {
+ wb = &ch343->wb[wbn];
+ if (!wb->use) {
+ wb->use = 1;
+ return wbn;
+ }
+ wbn = (wbn + 1) % CH343_NW;
+ if (++i >= CH343_NW)
+ return -1;
+ }
+}
+
+static int ch343_wb_is_avail(struct ch343 *ch343)
+{
+ int i, n;
+ unsigned long flags;
+
+ n = CH343_NW;
+ spin_lock_irqsave(&ch343->write_lock, flags);
+ for (i = 0; i < CH343_NW; i++)
+ n -= ch343->wb[i].use;
+ spin_unlock_irqrestore(&ch343->write_lock, flags);
+ return n;
+}
+
+/*
+ * Finish write. Caller must hold ch343->write_lock
+ */
+static void ch343_write_done(struct ch343 *ch343, struct ch343_wb *wb)
+{
+ wb->use = 0;
+ ch343->transmitting--;
+ usb_autopm_put_interface_async(ch343->control);
+}
+
+/*
+ * Poke write.
+ *
+ * the caller is responsible for locking
+ */
+static int ch343_start_wb(struct ch343 *ch343, struct ch343_wb *wb)
+{
+ int rc;
+
+ ch343->transmitting++;
+
+ wb->urb->transfer_buffer = wb->buf;
+ wb->urb->transfer_dma = wb->dmah;
+ wb->urb->transfer_buffer_length = wb->len;
+ wb->urb->dev = ch343->dev;
+
+ rc = usb_submit_urb(wb->urb, GFP_ATOMIC);
+ if (rc < 0) {
+ dev_err(&ch343->data->dev, "%s - usb_submit_urb(write bulk) failed: %d\n", __func__, rc);
+ ch343_write_done(ch343, wb);
+ }
+ return rc;
+}
+
+static void ch343_update_status(struct ch343 *ch343, unsigned char *data, size_t len)
+{
+ unsigned long flags;
+ u8 status;
+ u8 difference;
+ u8 type = data[0];
+ u8 handled = 0;
+
+ if (len < 4)
+ return;
+
+ if (ch343->chiptype == CHIP_CH344L) {
+ if (data[0] != 0x00)
+ return;
+ type = data[1];
+ } else if (ch343->chiptype == CHIP_CH344Q || ch343->chiptype == CHIP_CH344L_V2 || ch343->chiptype == CHIP_CH9104L) {
+ type = data[1];
+ }
+
+ if (type & CH343_CTT_M) {
+ status = ~data[len - 1] & CH343_CTI_ST;
+ if (ch343->chiptype == CHIP_CH344L || ch343->chiptype == CHIP_CH344L_V2)
+ status &= CH343_CTI_C;
+
+ if (!ch343->clocal && (ch343->ctrlin & status & CH343_CTI_DC)) {
+ tty_port_tty_hangup(&ch343->port, false);
+ }
+
+ spin_lock_irqsave(&ch343->read_lock, flags);
+ difference = status ^ ch343->ctrlin;
+ ch343->ctrlin = status;
+ ch343->oldcount = ch343->iocount;
+
+ if (difference) {
+ if (difference & CH343_CTI_C) {
+ ch343->iocount.cts++;
+ }
+ if (difference & CH343_CTI_DS) {
+ ch343->iocount.dsr++;
+ }
+ if (difference & CH343_CTI_R) {
+ ch343->iocount.rng++;
+ }
+ if (difference & CH343_CTI_DC) {
+ ch343->iocount.dcd++;
+ }
+ spin_unlock_irqrestore(&ch343->read_lock, flags);
+ wake_up_interruptible(&ch343->wioctl);
+ } else
+ spin_unlock_irqrestore(&ch343->read_lock, flags);
+ handled = 1;
+ }
+ if (type & CH343_CTT_O) {
+ spin_lock_irqsave(&ch343->read_lock, flags);
+ ch343->oldcount = ch343->iocount;
+ ch343->iocount.overrun++;
+ spin_unlock_irqrestore(&ch343->read_lock, flags);
+ handled = 1;
+ }
+ if ((type & CH343_CTT_F) == CH343_CTT_F) {
+ spin_lock_irqsave(&ch343->read_lock, flags);
+ ch343->oldcount = ch343->iocount;
+ ch343->iocount.frame++;
+ spin_unlock_irqrestore(&ch343->read_lock, flags);
+ handled = 1;
+ } else if (type & CH343_CTT_P) {
+ spin_lock_irqsave(&ch343->read_lock, flags);
+ ch343->oldcount = ch343->iocount;
+ ch343->iocount.parity++;
+ spin_unlock_irqrestore(&ch343->read_lock, flags);
+ handled = 1;
+ }
+ if (!handled)
+ dev_err(&ch343->control->dev,
+ "%s - unknown status received:"
+ "len:%d, data0:0x%x, data1:0x%x\n",
+ __func__, (int)len, data[0], data[1]);
+}
+
+/* Reports status changes with "interrupt" transfers */
+static void ch343_ctrl_irq(struct urb *urb)
+{
+ struct ch343 *ch343 = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned int len = urb->actual_length;
+ int status = urb->status;
+ int retval;
+
+ switch (status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dev_dbg(&ch343->control->dev, "%s - urb shutting down with status: %d\n", __func__, status);
+ return;
+ default:
+ dev_dbg(&ch343->control->dev, "%s - nonzero urb status received: %d\n", __func__, status);
+ goto exit;
+ }
+
+ usb_mark_last_busy(ch343->dev);
+ ch343_update_status(ch343, data, len);
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval && retval != -EPERM)
+ dev_err(&ch343->control->dev, "%s - usb_submit_urb failed: %d\n", __func__, retval);
+}
+
+static int ch343_submit_read_urb(struct ch343 *ch343, int index, gfp_t mem_flags)
+{
+ int res;
+
+ if (!test_and_clear_bit(index, &ch343->read_urbs_free))
+ return 0;
+
+ dev_vdbg(&ch343->data->dev, "%s - urb %d\n", __func__, index);
+
+ res = usb_submit_urb(ch343->read_urbs[index], mem_flags);
+ if (res) {
+ if (res != -EPERM) {
+ dev_err(&ch343->data->dev, "%s - usb_submit_urb failed: %d\n", __func__, res);
+ }
+ set_bit(index, &ch343->read_urbs_free);
+ return res;
+ }
+
+ return 0;
+}
+
+static int ch343_submit_read_urbs(struct ch343 *ch343, gfp_t mem_flags)
+{
+ int res;
+ int i;
+
+ for (i = 0; i < ch343->rx_buflimit; ++i) {
+ res = ch343_submit_read_urb(ch343, i, mem_flags);
+ if (res)
+ return res;
+ }
+
+ return 0;
+}
+
+static void ch343_process_read_urb(struct ch343 *ch343, struct urb *urb)
+{
+ if (!urb->actual_length)
+ return;
+
+ tty_insert_flip_string(&ch343->port, urb->transfer_buffer, urb->actual_length);
+ tty_flip_buffer_push(&ch343->port);
+}
+
+static void ch343_read_bulk_callback(struct urb *urb)
+{
+ struct ch343_rb *rb = urb->context;
+ struct ch343 *ch343 = rb->instance;
+ int status = urb->status;
+
+ dev_vdbg(&ch343->data->dev, "%s - urb %d, len %d\n", __func__, rb->index, urb->actual_length);
+
+ if (!ch343->dev) {
+ set_bit(rb->index, &ch343->read_urbs_free);
+ dev_dbg(&ch343->data->dev, "%s - disconnected\n", __func__);
+ return;
+ }
+
+ if (status) {
+ set_bit(rb->index, &ch343->read_urbs_free);
+ dev_dbg(&ch343->data->dev, "%s - non-zero urb status: %d\n", __func__, status);
+ return;
+ }
+
+ usb_mark_last_busy(ch343->dev);
+ ch343_process_read_urb(ch343, urb);
+ set_bit(rb->index, &ch343->read_urbs_free);
+ ch343_submit_read_urb(ch343, rb->index, GFP_ATOMIC);
+}
+
+/* data interface wrote those outgoing bytes */
+static void ch343_write_bulk(struct urb *urb)
+{
+ struct ch343_wb *wb = urb->context;
+ struct ch343 *ch343 = wb->instance;
+ unsigned long flags;
+ int status = urb->status;
+
+ dev_vdbg(&ch343->data->dev, "%s, len %d\n", __func__, urb->actual_length);
+ if (status || (urb->actual_length != urb->transfer_buffer_length))
+ dev_vdbg(&ch343->data->dev, "%s - len %d/%d, status %d\n", __func__, urb->actual_length,
+ urb->transfer_buffer_length, status);
+
+ spin_lock_irqsave(&ch343->write_lock, flags);
+ ch343_write_done(ch343, wb);
+ spin_unlock_irqrestore(&ch343->write_lock, flags);
+ schedule_work(&ch343->work);
+}
+
+static void ch343_softint(struct work_struct *work)
+{
+ struct ch343 *ch343 = container_of(work, struct ch343, work);
+
+ dev_dbg(&ch343->data->dev, "%s\n", __func__);
+
+ tty_port_tty_wakeup(&ch343->port);
+}
+
+/*
+ * TTY handlers
+ */
+static int ch343_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct ch343 *ch343;
+ int retval;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
+ ch343 = ch343_get_by_minor(tty->index);
+ if (!ch343)
+ return -ENODEV;
+
+ retval = tty_standard_install(driver, tty);
+ if (retval)
+ goto error_init_termios;
+
+ tty->driver_data = ch343;
+
+ return 0;
+
+error_init_termios:
+ tty_port_put(&ch343->port);
+ return retval;
+}
+
+static int ch343_tty_open(struct tty_struct *tty, struct file *filp)
+{
+ struct ch343 *ch343 = tty->driver_data;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
+ return tty_port_open(&ch343->port, tty, filp);
+}
+
+static void ch343_port_dtr_rts(struct tty_port *port, int raise)
+{
+ struct ch343 *ch343 = container_of(port, struct ch343, port);
+ int res;
+
+ dev_dbg(&ch343->data->dev, "%s, raise:%d\n", __func__, raise);
+
+ if (raise)
+ ch343->ctrlout |= CH343_CTO_D | CH343_CTO_R;
+ else
+ ch343->ctrlout &= ~(CH343_CTO_D | CH343_CTO_R);
+
+ res = ch343_set_control(ch343, ch343->ctrlout);
+ if (res)
+ dev_err(&ch343->control->dev, "failed to set dtr/rts\n");
+}
+
+static int ch343_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+ struct ch343 *ch343 = container_of(port, struct ch343, port);
+ int retval = -ENODEV;
+ int i;
+
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+
+ mutex_lock(&ch343->mutex);
+ if (ch343->disconnected)
+ goto disconnected;
+
+ retval = usb_autopm_get_interface(ch343->control);
+ if (retval)
+ goto error_get_interface;
+
+ /*
+ * FIXME: Why do we need this? Allocating 64K of physically contiguous
+ * memory is really nasty...
+ */
+ set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
+ ch343->control->needs_remote_wakeup = 1;
+
+ // retval = ch343_configure(ch343);
+ // if (retval)
+ // goto error_configure;
+
+ ch343_tty_set_termios(tty, NULL);
+
+ retval = usb_submit_urb(ch343->ctrlurb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&ch343->control->dev, "%s - usb_submit_urb(ctrl cmd) failed\n", __func__);
+ goto error_submit_urb;
+ }
+
+ retval = ch343_submit_read_urbs(ch343, GFP_KERNEL);
+ if (retval)
+ goto error_submit_read_urbs;
+ usb_autopm_put_interface(ch343->control);
+
+ mutex_unlock(&ch343->mutex);
+
+ return 0;
+
+error_submit_read_urbs:
+ for (i = 0; i < ch343->rx_buflimit; i++)
+ usb_kill_urb(ch343->read_urbs[i]);
+error_submit_urb:
+ usb_kill_urb(ch343->ctrlurb);
+ // error_configure:
+ usb_autopm_put_interface(ch343->control);
+error_get_interface:
+disconnected:
+ mutex_unlock(&ch343->mutex);
+
+ return usb_translate_errors(retval);
+}
+
+static void ch343_port_destruct(struct tty_port *port)
+{
+ struct ch343 *ch343 = container_of(port, struct ch343, port);
+
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+
+ ch343_release_minor(ch343);
+ usb_put_intf(ch343->control);
+ kfree(ch343);
+}
+
+static void ch343_port_shutdown(struct tty_port *port)
+{
+ struct ch343 *ch343 = container_of(port, struct ch343, port);
+ struct urb *urb;
+ struct ch343_wb *wb;
+ int i;
+
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+
+ usb_autopm_get_interface_no_resume(ch343->control);
+ ch343->control->needs_remote_wakeup = 0;
+ usb_autopm_put_interface(ch343->control);
+
+ for (;;) {
+ urb = usb_get_from_anchor(&ch343->delayed);
+ if (!urb)
+ break;
+ wb = urb->context;
+ wb->use = 0;
+ usb_autopm_put_interface_async(ch343->control);
+ }
+
+ usb_kill_urb(ch343->ctrlurb);
+ for (i = 0; i < CH343_NW; i++)
+ usb_kill_urb(ch343->wb[i].urb);
+ for (i = 0; i < ch343->rx_buflimit; i++)
+ usb_kill_urb(ch343->read_urbs[i]);
+}
+
+static void ch343_tty_cleanup(struct tty_struct *tty)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+ tty_port_put(&ch343->port);
+}
+
+static void ch343_tty_hangup(struct tty_struct *tty)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+ tty_port_hangup(&ch343->port);
+}
+
+static void ch343_tty_close(struct tty_struct *tty, struct file *filp)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+ tty_port_close(&ch343->port, tty, filp);
+}
+
+static int ch343_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ int stat;
+ unsigned long flags;
+ int wbn;
+ struct ch343_wb *wb;
+
+ if (!count)
+ return 0;
+
+ dev_vdbg(&ch343->data->dev, "%s - count %d\n", __func__, count);
+
+ spin_lock_irqsave(&ch343->write_lock, flags);
+ wbn = ch343_wb_alloc(ch343);
+ if (wbn < 0) {
+ spin_unlock_irqrestore(&ch343->write_lock, flags);
+ return 0;
+ }
+ wb = &ch343->wb[wbn];
+
+ if (!ch343->dev) {
+ wb->use = 0;
+ spin_unlock_irqrestore(&ch343->write_lock, flags);
+ return -ENODEV;
+ }
+
+ count = (count > ch343->writesize) ? ch343->writesize : count;
+
+ memcpy(wb->buf, buf, count);
+ wb->len = count;
+
+ stat = usb_autopm_get_interface_async(ch343->control);
+ if (stat) {
+ wb->use = 0;
+ spin_unlock_irqrestore(&ch343->write_lock, flags);
+ return stat;
+ }
+
+ if (ch343->susp_count) {
+ usb_anchor_urb(wb->urb, &ch343->delayed);
+ spin_unlock_irqrestore(&ch343->write_lock, flags);
+ return count;
+ }
+
+ stat = ch343_start_wb(ch343, wb);
+ spin_unlock_irqrestore(&ch343->write_lock, flags);
+
+ if (stat < 0)
+ return stat;
+ return count;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+static unsigned int ch343_tty_write_room(struct tty_struct *tty)
+#else
+static int ch343_tty_write_room(struct tty_struct *tty)
+#endif
+{
+ struct ch343 *ch343 = tty->driver_data;
+ /*
+ * Do not let the line discipline to know that we have a reserve,
+ * or it might get too enthusiastic.
+ */
+ return ch343_wb_is_avail(ch343) ? ch343->writesize : 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+static unsigned int ch343_tty_chars_in_buffer(struct tty_struct *tty)
+#else
+static int ch343_tty_chars_in_buffer(struct tty_struct *tty)
+#endif
+{
+ struct ch343 *ch343 = tty->driver_data;
+ /*
+ * if the device was unplugged then any remaining characters fell out
+ * of the connector ;)
+ */
+ if (ch343->disconnected)
+ return 0;
+ /*
+ * This is inaccurate (overcounts), but it works.
+ */
+ return (CH343_NW - ch343_wb_is_avail(ch343)) * ch343->writesize;
+}
+
+static int ch343_tty_break_ctl(struct tty_struct *tty, int state)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ int retval;
+ uint16_t reg_contents;
+ uint8_t *regbuf;
+
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+
+ regbuf = kmalloc(2, GFP_KERNEL);
+ if (!regbuf)
+ return -1;
+
+ if (state != 0) {
+ if ((ch343->chiptype == CHIP_CH344L) || (ch343->chiptype == CHIP_CH344Q) ||
+ (ch343->chiptype == CHIP_CH344L_V2) || (ch343->chiptype == CHIP_CH9104L)) {
+ regbuf[0] = ch343->iface;
+ regbuf[1] = 0x01;
+ } else {
+ regbuf[0] = CH343_N_B;
+ regbuf[1] = 0x00;
+ }
+ } else {
+ if ((ch343->chiptype == CHIP_CH344L) || (ch343->chiptype == CHIP_CH344Q) ||
+ (ch343->chiptype == CHIP_CH344L_V2) || (ch343->chiptype == CHIP_CH9104L)) {
+ regbuf[0] = ch343->iface;
+ regbuf[1] = 0x00;
+ } else {
+ regbuf[0] = CH343_N_B | CH343_N_AB;
+ regbuf[1] = 0x00;
+ }
+ }
+ reg_contents = get_unaligned_le16(regbuf);
+
+ if ((ch343->chiptype == CHIP_CH344L) || (ch343->chiptype == CHIP_CH344Q) || (ch343->chiptype == CHIP_CH344L_V2) ||
+ (ch343->chiptype == CHIP_CH9104L)) {
+ retval = ch343_control_out(ch343, CMD_C4, reg_contents, 0x00);
+ } else {
+ if (ch343->iface)
+ retval = ch343_control_out(ch343, CMD_C4, 0x00, reg_contents);
+ else
+ retval = ch343_control_out(ch343, CMD_C4, reg_contents, 0x00);
+ }
+
+ if (retval < 0)
+ dev_err(&ch343->control->dev, "%s - USB control write error (%d)\n", __func__, retval);
+
+ kfree(regbuf);
+
+ return retval;
+}
+
+static int ch343_tty_tiocmget(struct tty_struct *tty)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ unsigned long flags;
+ unsigned int result;
+
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+
+ spin_lock_irqsave(&ch343->read_lock, flags);
+ result = (ch343->ctrlout & CH343_CTO_D ? TIOCM_DTR : 0) | (ch343->ctrlout & CH343_CTO_R ? TIOCM_RTS : 0) |
+ (ch343->ctrlin & CH343_CTI_C ? TIOCM_CTS : 0) | (ch343->ctrlin & CH343_CTI_DS ? TIOCM_DSR : 0) |
+ (ch343->ctrlin & CH343_CTI_R ? TIOCM_RI : 0) | (ch343->ctrlin & CH343_CTI_DC ? TIOCM_CD : 0);
+ spin_unlock_irqrestore(&ch343->read_lock, flags);
+
+ return result;
+}
+
+static int ch343_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ unsigned int newctrl;
+
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+
+ newctrl = ch343->ctrlout;
+ set = (set & TIOCM_DTR ? CH343_CTO_D : 0) | (set & TIOCM_RTS ? CH343_CTO_R : 0);
+ clear = (clear & TIOCM_DTR ? CH343_CTO_D : 0) | (clear & TIOCM_RTS ? CH343_CTO_R : 0);
+
+ newctrl = (newctrl & ~clear) | set;
+
+ if (ch343->ctrlout == newctrl) {
+ return 0;
+ }
+
+ return ch343_set_control(ch343, ch343->ctrlout = newctrl);
+}
+
+static int ch343_get_serial_info(struct ch343 *ch343, struct serial_struct __user *info)
+{
+ struct serial_struct tmp;
+
+ if (!info)
+ return -EINVAL;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.flags = ASYNC_LOW_LATENCY;
+ tmp.xmit_fifo_size = ch343->writesize;
+ tmp.baud_base = le32_to_cpu(ch343->line.dwDTERate);
+ tmp.close_delay = ch343->port.close_delay / 10;
+ tmp.closing_wait =
+ ch343->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : ch343->port.closing_wait / 10;
+
+ if (copy_to_user(info, &tmp, sizeof(tmp)))
+ return -EFAULT;
+ else
+ return 0;
+}
+
+static int ch343_set_serial_info(struct ch343 *ch343, struct serial_struct __user *newinfo)
+{
+ struct serial_struct new_serial;
+ unsigned int closing_wait, close_delay;
+ int retval = 0;
+
+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+ return -EFAULT;
+
+ close_delay = new_serial.close_delay * 10;
+ closing_wait =
+ new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
+
+ mutex_lock(&ch343->port.mutex);
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((close_delay != ch343->port.close_delay) || (closing_wait != ch343->port.closing_wait))
+ retval = -EPERM;
+ else
+ retval = -EOPNOTSUPP;
+ } else {
+ ch343->port.close_delay = close_delay;
+ ch343->port.closing_wait = closing_wait;
+ }
+
+ mutex_unlock(&ch343->port.mutex);
+ return retval;
+}
+
+static int ch343_wait_serial_change(struct ch343 *ch343, unsigned long arg)
+{
+ int rv = 0;
+ DECLARE_WAITQUEUE(wait, current);
+ struct async_icount old, new;
+
+ do {
+ spin_lock_irq(&ch343->read_lock);
+ old = ch343->oldcount;
+ new = ch343->iocount;
+ ch343->oldcount = new;
+ spin_unlock_irq(&ch343->read_lock);
+
+ if ((arg & TIOCM_CTS) && old.cts != new.cts)
+ break;
+ if ((arg & TIOCM_DSR) && old.dsr != new.dsr)
+ break;
+ if ((arg & TIOCM_RI) && old.rng != new.rng)
+ break;
+ if ((arg & TIOCM_CD) && old.dcd != new.dcd)
+ break;
+
+ add_wait_queue(&ch343->wioctl, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ remove_wait_queue(&ch343->wioctl, &wait);
+ if (ch343->disconnected) {
+ if (arg & TIOCM_CD)
+ break;
+ else
+ rv = -ENODEV;
+ } else {
+ if (signal_pending(current))
+ rv = -ERESTARTSYS;
+ }
+ } while (!rv);
+
+ return rv;
+}
+
+static int ch343_get_serial_usage(struct ch343 *ch343, struct serial_icounter_struct __user *count)
+{
+ struct serial_icounter_struct icount;
+ int rv = 0;
+
+ memset(&icount, 0, sizeof(icount));
+ icount.cts = ch343->iocount.cts;
+ icount.dsr = ch343->iocount.dsr;
+ icount.rng = ch343->iocount.rng;
+ icount.dcd = ch343->iocount.dcd;
+ icount.frame = ch343->iocount.frame;
+ icount.overrun = ch343->iocount.overrun;
+ icount.parity = ch343->iocount.parity;
+ icount.brk = ch343->iocount.brk;
+
+ if (copy_to_user(count, &icount, sizeof(icount)) > 0)
+ rv = -EFAULT;
+
+ return rv;
+}
+
+static int ch343_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ int rv = 0;
+ unsigned long arg1, arg2, arg3, arg4, arg5, arg6;
+ u32 __user *argval = (u32 __user *)arg;
+ u8 *buffer;
+
+ dev_dbg(&ch343->control->dev, "%s\n", __func__);
+
+ buffer = kmalloc(512, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ switch (cmd) {
+ case TIOCGSERIAL: /* gets serial port data */
+ rv = ch343_get_serial_info(ch343, (struct serial_struct __user *)arg);
+ break;
+ case TIOCSSERIAL:
+ rv = ch343_set_serial_info(ch343, (struct serial_struct __user *)arg);
+ break;
+ case TIOCMIWAIT:
+ rv = usb_autopm_get_interface(ch343->control);
+ if (rv < 0) {
+ rv = -EIO;
+ break;
+ }
+ rv = ch343_wait_serial_change(ch343, arg);
+ usb_autopm_put_interface(ch343->control);
+ break;
+ case IOCTL_CMD_GICOUNT:
+ case TIOCGICOUNT:
+ rv = ch343_get_serial_usage(ch343, (struct serial_icounter_struct __user *)arg);
+ break;
+ case IOCTL_CMD_GETCHIPTYPE:
+ if (put_user(ch343->chiptype, argval)) {
+ rv = -EFAULT;
+ goto out;
+ }
+ break;
+ case IOCTL_CMD_CTRLIN:
+ get_user(arg1, (u8 __user *)arg);
+ get_user(arg2, ((u8 __user *)arg + 1));
+ get_user(arg3, (u16 __user *)((u8 *)arg + 2));
+ get_user(arg4, (u16 __user *)((u8 *)arg + 4));
+ get_user(arg5, (u16 __user *)((u8 *)arg + 6));
+ arg6 = (unsigned long)((u8 __user *)arg + 8);
+ rv = ch343_control_msg_in(ch343, (u8)arg1, (u8)arg2, (u16)arg3, (u16)arg4, (u8 __user *)arg6, (u16)arg5);
+ break;
+ case IOCTL_CMD_CTRLOUT:
+ get_user(arg1, (u8 __user *)arg);
+ get_user(arg2, ((u8 __user *)arg + 1));
+ get_user(arg3, (u16 __user *)((u8 *)arg + 2));
+ get_user(arg4, (u16 __user *)((u8 *)arg + 4));
+ get_user(arg5, (u16 __user *)((u8 *)arg + 6));
+ arg6 = (unsigned long)((u8 __user *)arg + 8);
+ rv = ch343_control_msg_out(ch343, (u8)arg1, (u8)arg2, (u16)arg3, (u16)arg4, (u8 __user *)arg6, (u16)arg5);
+ if (rv != (u16)arg5) {
+ rv = -EINVAL;
+ goto out;
+ }
+ break;
+ default:
+ rv = -ENOIOCTLCMD;
+ break;
+ }
+
+out:
+ kfree(buffer);
+ return rv < 0 ? rv : 0;
+}
+
+static int ch343_get(CHIPTYPE chiptype, unsigned int bval, unsigned char *fct, unsigned char *dvs)
+{
+ unsigned char a;
+ unsigned char b;
+ unsigned long c;
+
+ if (((chiptype == CHIP_CH347T) || (chiptype == CHIP_CH344Q) || (chiptype == CHIP_CH9104L)) && bval >= 2000000) {
+ *fct = (unsigned char)(bval / 200);
+ *dvs = (unsigned char)((bval / 200) >> 8);
+ }
+
+ switch (bval) {
+ case 6000000:
+ case 4000000:
+ case 2400000:
+ case 921600:
+ case 307200:
+ case 256000:
+ b = 7;
+ c = 12000000;
+ break;
+ default:
+ if (bval > 6000000 / 255) {
+ b = 3;
+ c = 6000000;
+ } else if (bval > 750000 / 255) {
+ b = 2;
+ c = 750000;
+ } else if (bval > 93750 / 255) {
+ b = 1;
+ c = 93750;
+ } else {
+ b = 0;
+ c = 11719;
+ }
+ break;
+ }
+ a = (unsigned char)(c / bval);
+ if (a == 0 || a == 0xFF)
+ return -EINVAL;
+ if ((c / a - bval) > (bval - c / (a + 1)))
+ a++;
+ a = 256 - a;
+
+ *fct = a;
+ *dvs = b;
+
+ return 0;
+}
+
+static void ch343_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old)
+{
+ struct ch343 *ch343 = tty->driver_data;
+ struct ktermios *termios = &tty->termios;
+ struct usb_ch343_line_coding newline;
+ int newctrl = ch343->ctrlout;
+
+ unsigned char dvs = 0;
+ unsigned char reg_count = 0;
+ unsigned char fct = 0;
+ unsigned char reg_value = 0;
+ unsigned short value = 0;
+ unsigned short index = 0;
+
+ dev_dbg(tty->dev, "%s\n", __func__);
+
+ if (termios_old && !tty_termios_hw_change(&tty->termios, termios_old)) {
+ return;
+ }
+
+ newline.dwDTERate = tty_get_baud_rate(tty);
+
+ if (newline.dwDTERate == 0)
+ newline.dwDTERate = 9600;
+ ch343_get(ch343->chiptype, newline.dwDTERate, &fct, &dvs);
+
+ newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 1;
+ if (newline.bCharFormat == 2)
+ reg_value |= CH343_L_SB;
+
+ newline.bParityType =
+ termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
+
+ switch (newline.bParityType) {
+ case 0x01:
+ reg_value |= CH343_L_P_O;
+ break;
+ case 0x02:
+ reg_value |= CH343_L_P_E;
+ break;
+ case 0x03:
+ reg_value |= CH343_L_P_M;
+ break;
+ case 0x04:
+ reg_value |= CH343_L_P_S;
+ break;
+ default:
+ break;
+ }
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ newline.bDataBits = 5;
+ reg_value |= CH343_L_C5;
+ break;
+ case CS6:
+ newline.bDataBits = 6;
+ reg_value |= CH343_L_C6;
+ break;
+ case CS7:
+ newline.bDataBits = 7;
+ reg_value |= CH343_L_C7;
+ break;
+ case CS8:
+ default:
+ newline.bDataBits = 8;
+ reg_value |= CH343_L_C8;
+ break;
+ }
+
+ /* FIXME: Needs to clear unsupported bits in the termios */
+ ch343->clocal = ((termios->c_cflag & CLOCAL) != 0);
+
+ if (C_BAUD(tty) == B0) {
+ newline.dwDTERate = ch343->line.dwDTERate;
+ newctrl &= ~CH343_CTO_D;
+ } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) {
+ newctrl |= CH343_CTO_D;
+ }
+
+ reg_value |= CH343_L_E_R | CH343_L_E_T;
+ reg_count |= CH343_L_R_CT | CH343_L_R_CL | CH343_L_R_T;
+
+ value |= reg_count;
+ value |= (unsigned short)reg_value << 8;
+
+ index |= 0x00 | dvs;
+ index |= (unsigned short)fct << 8;
+ if (ch343->iface <= 1)
+ ch343_control_out(ch343, CMD_C1 + ch343->iface, value, index);
+ else if (ch343->iface <= 3)
+ ch343_control_out(ch343, CMD_C1 + 0x10 + (ch343->iface - 2), value, index);
+
+ if (memcmp(&ch343->line, &newline, sizeof newline)) {
+ memcpy(&ch343->line, &newline, sizeof newline);
+ dev_dbg(&ch343->control->dev, "%s - set line: %d %d %d %d\n", __func__, newline.dwDTERate, newline.bCharFormat,
+ newline.bParityType, newline.bDataBits);
+ }
+
+ if (C_CRTSCTS(tty)) {
+ newctrl |= CH343_CTO_A | CH343_CTO_R;
+ } else
+ newctrl &= ~CH343_CTO_A;
+
+ if (newctrl != ch343->ctrlout)
+ ch343_set_control(ch343, ch343->ctrlout = newctrl);
+}
+
+static const struct tty_port_operations ch343_port_ops = {
+ .dtr_rts = ch343_port_dtr_rts,
+ .shutdown = ch343_port_shutdown,
+ .activate = ch343_port_activate,
+ .destruct = ch343_port_destruct,
+};
+
+/* Little helpers: write/read buffers free */
+static void ch343_write_buffers_free(struct ch343 *ch343)
+{
+ int i;
+ struct ch343_wb *wb;
+ struct usb_device *usb_dev = interface_to_usbdev(ch343->control);
+
+ for (wb = &ch343->wb[0], i = 0; i < CH343_NW; i++, wb++)
+ usb_free_coherent(usb_dev, ch343->writesize, wb->buf, wb->dmah);
+}
+
+static void ch343_read_buffers_free(struct ch343 *ch343)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ch343->control);
+ int i;
+
+ for (i = 0; i < ch343->rx_buflimit; i++)
+ usb_free_coherent(usb_dev, ch343->readsize, ch343->read_buffers[i].base, ch343->read_buffers[i].dma);
+}
+
+/* Little helper: write buffers allocate */
+static int ch343_write_buffers_alloc(struct ch343 *ch343)
+{
+ int i;
+ struct ch343_wb *wb;
+
+ for (wb = &ch343->wb[0], i = 0; i < CH343_NW; i++, wb++) {
+ wb->buf = usb_alloc_coherent(ch343->dev, ch343->writesize, GFP_KERNEL, &wb->dmah);
+ if (!wb->buf) {
+ while (i != 0) {
+ --i;
+ --wb;
+ usb_free_coherent(ch343->dev, ch343->writesize, wb->buf, wb->dmah);
+ }
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+static int ch343_open(struct inode *inode, struct file *file)
+{
+ struct ch343 *ch343;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+
+ subminor = iminor(inode);
+
+ interface = usb_find_interface(&ch343_driver, subminor);
+ if (!interface) {
+ pr_err("%s - error, can't find device for minor %d\n", __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ ch343 = usb_get_intfdata(interface);
+ if (!ch343) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ /* save our object in the file's private structure */
+ file->private_data = ch343;
+
+exit:
+ return retval;
+}
+
+static int ch343_release(struct inode *inode, struct file *file)
+{
+ struct ch343 *ch343;
+
+ ch343 = file->private_data;
+ if (ch343 == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
+static long ch343_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct ch343 *ch343;
+ int rv = 0;
+ u8 *buffer;
+ unsigned long arg1, arg2, arg3, arg4, arg5, arg6;
+ u32 __user *argval = (u32 __user *)arg;
+
+ ch343 = file->private_data;
+ if (ch343 == NULL)
+ return -ENODEV;
+
+ buffer = kmalloc(512, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ switch (cmd) {
+ case IOCTL_CMD_GETCHIPTYPE:
+ if (put_user(ch343->chiptype, argval)) {
+ rv = -EFAULT;
+ goto out;
+ }
+ break;
+ case IOCTL_CMD_CTRLIN:
+ get_user(arg1, (u8 __user *)arg);
+ get_user(arg2, ((u8 __user *)arg + 1));
+ get_user(arg3, (u16 __user *)((u8 *)arg + 2));
+ get_user(arg4, (u16 __user *)((u8 *)arg + 4));
+ get_user(arg5, (u16 __user *)((u8 *)arg + 6));
+ arg6 = (unsigned long)((u8 __user *)arg + 8);
+ rv = ch343_control_msg_in(ch343, (u8)arg1, (u8)arg2, (u16)arg3, (u16)arg4, (u8 __user *)arg6, (u16)arg5);
+ break;
+ case IOCTL_CMD_CTRLOUT:
+ get_user(arg1, (u8 __user *)arg);
+ get_user(arg2, ((u8 __user *)arg + 1));
+ get_user(arg3, (u16 __user *)((u8 *)arg + 2));
+ get_user(arg4, (u16 __user *)((u8 *)arg + 4));
+ get_user(arg5, (u16 __user *)((u8 *)arg + 6));
+ arg6 = (unsigned long)((u8 __user *)arg + 8);
+ rv = ch343_control_msg_out(ch343, (u8)arg1, (u8)arg2, (u16)arg3, (u16)arg4, (u8 __user *)arg6, (u16)arg5);
+ if (rv != (u16)arg5) {
+ rv = -EINVAL;
+ goto out;
+ }
+ break;
+ default:
+ rv = -ENOIOCTLCMD;
+ break;
+ }
+
+out:
+ kfree(buffer);
+ return rv;
+}
+
+static const struct file_operations ch343_fops = {
+ .owner = THIS_MODULE,
+ .open = ch343_open,
+ .unlocked_ioctl = ch343_ioctl,
+ .release = ch343_release,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+static struct usb_class_driver ch343_class = {
+ .name = "ch343_iodev%d",
+ .fops = &ch343_fops,
+ .minor_base = USB_MINOR_BASE,
+};
+
+/*
+ * USB probe and disconnect routines.
+ */
+static int ch343_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_cdc_union_desc *union_header = NULL;
+ unsigned char *buffer = intf->altsetting->extra;
+ int buflen = intf->altsetting->extralen;
+ struct usb_interface *control_interface;
+ struct usb_interface *data_interface;
+ struct usb_endpoint_descriptor *epctrl = NULL;
+ struct usb_endpoint_descriptor *epread = NULL;
+ struct usb_endpoint_descriptor *epwrite = NULL;
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ struct ch343 *ch343;
+ int minor;
+ int ctrlsize, readsize;
+ u8 *buf;
+ unsigned long quirks;
+ int num_rx_buf = CH343_NR;
+ int i;
+ unsigned int elength = 0;
+ struct device *tty_dev;
+ int rv = -ENOMEM;
+
+ /* normal quirks */
+ quirks = (unsigned long)id->driver_info;
+ if (!buffer) {
+ dev_err(&intf->dev, "Weird descriptor references\n");
+ return -EINVAL;
+ }
+
+ while (buflen > 0) {
+ elength = buffer[0];
+ if (!elength) {
+ dev_err(&intf->dev, "skipping garbage byte\n");
+ elength = 1;
+ goto next_desc;
+ }
+ if (buffer[1] != USB_DT_CS_INTERFACE) {
+ dev_err(&intf->dev, "skipping garbage\n");
+ goto next_desc;
+ }
+
+ switch (buffer[2]) {
+ case USB_CDC_UNION_TYPE: /* we've found it */
+ if (elength < sizeof(struct usb_cdc_union_desc))
+ goto next_desc;
+ if (union_header) {
+ dev_err(&intf->dev,
+ "More than one "
+ "union descriptor, skipping ...\n");
+ goto next_desc;
+ }
+ union_header = (struct usb_cdc_union_desc *)buffer;
+ break;
+ default:
+ /*
+ * there are LOTS more CDC descriptors that
+ * could legitimately be found here.
+ */
+ break;
+ }
+ next_desc:
+ buflen -= elength;
+ buffer += elength;
+ }
+
+ control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
+ data_interface = usb_ifnum_to_if(usb_dev, union_header->bSlaveInterface0);
+
+ if (intf != control_interface)
+ return -ENODEV;
+
+ if (usb_interface_claimed(data_interface)) {
+ dev_dbg(&intf->dev, "The data interface isn't available\n");
+ return -EBUSY;
+ }
+
+ if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 ||
+ control_interface->cur_altsetting->desc.bNumEndpoints == 0)
+ return -EINVAL;
+
+ epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
+ epwrite = &data_interface->cur_altsetting->endpoint[0].desc;
+ epread = &data_interface->cur_altsetting->endpoint[1].desc;
+
+ /* workaround for switched endpoints */
+ if (!usb_endpoint_dir_in(epread)) {
+ /* descriptors are swapped */
+ dev_dbg(&intf->dev, "The data interface has switched endpoints\n");
+ swap(epread, epwrite);
+ }
+
+ ch343 = kzalloc(sizeof(struct ch343), GFP_KERNEL);
+ if (ch343 == NULL)
+ goto alloc_fail;
+
+ ch343->idVendor = id->idVendor;
+ ch343->idProduct = id->idProduct;
+ ch343->iface = control_interface->cur_altsetting->desc.bInterfaceNumber / 2;
+
+ minor = ch343_alloc_minor(ch343);
+ if (minor < 0) {
+ dev_err(&intf->dev, "no more free ch343 devices\n");
+ kfree(ch343);
+ return -ENODEV;
+ }
+
+ ctrlsize = usb_endpoint_maxp(epctrl);
+ readsize = usb_endpoint_maxp(epread);
+ ch343->writesize = usb_endpoint_maxp(epwrite) * 20;
+ ch343->control = control_interface;
+ ch343->data = data_interface;
+ ch343->minor = minor;
+ ch343->dev = usb_dev;
+ ch343->ctrlsize = ctrlsize;
+ ch343->readsize = readsize;
+ ch343->rx_buflimit = num_rx_buf;
+
+ dev_dbg(&intf->dev, "ep%d ctrl: %d, ep%d read: %d, ep%d write: %d\n", usb_endpoint_num(epctrl),
+ usb_endpoint_maxp(epctrl), usb_endpoint_num(epread), usb_endpoint_maxp(epread), usb_endpoint_num(epwrite),
+ usb_endpoint_maxp(epwrite));
+
+ INIT_WORK(&ch343->work, ch343_softint);
+ init_waitqueue_head(&ch343->wioctl);
+ spin_lock_init(&ch343->write_lock);
+ spin_lock_init(&ch343->read_lock);
+ mutex_init(&ch343->mutex);
+ ch343->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
+ tty_port_init(&ch343->port);
+ ch343->port.ops = &ch343_port_ops;
+ init_usb_anchor(&ch343->delayed);
+ ch343->quirks = quirks;
+
+ buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &ch343->ctrl_dma);
+ if (!buf)
+ goto alloc_fail2;
+ ch343->ctrl_buffer = buf;
+
+ if (ch343_write_buffers_alloc(ch343) < 0)
+ goto alloc_fail4;
+
+ ch343->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ch343->ctrlurb)
+ goto alloc_fail5;
+
+ for (i = 0; i < num_rx_buf; i++) {
+ struct ch343_rb *rb = &(ch343->read_buffers[i]);
+ struct urb *urb;
+
+ rb->base = usb_alloc_coherent(ch343->dev, readsize, GFP_KERNEL, &rb->dma);
+ if (!rb->base)
+ goto alloc_fail6;
+ rb->index = i;
+ rb->instance = ch343;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ goto alloc_fail6;
+
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ urb->transfer_dma = rb->dma;
+ usb_fill_bulk_urb(urb, ch343->dev, ch343->rx_endpoint, rb->base, ch343->readsize, ch343_read_bulk_callback, rb);
+
+ ch343->read_urbs[i] = urb;
+ __set_bit(i, &ch343->read_urbs_free);
+ }
+ for (i = 0; i < CH343_NW; i++) {
+ struct ch343_wb *snd = &(ch343->wb[i]);
+
+ snd->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (snd->urb == NULL)
+ goto alloc_fail7;
+
+ usb_fill_bulk_urb(snd->urb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), NULL,
+ ch343->writesize, ch343_write_bulk, snd);
+ snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ snd->instance = ch343;
+ }
+
+ usb_set_intfdata(intf, ch343);
+
+ usb_fill_int_urb(ch343->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), ch343->ctrl_buffer,
+ ctrlsize, ch343_ctrl_irq, ch343, epctrl->bInterval ? epctrl->bInterval : 16);
+ ch343->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ ch343->ctrlurb->transfer_dma = ch343->ctrl_dma;
+
+ dev_info(&intf->dev, "ttyCH343USB%d: usb to uart device\n", minor);
+
+ usb_driver_claim_interface(&ch343_driver, data_interface, ch343);
+ usb_set_intfdata(data_interface, ch343);
+ usb_get_intf(control_interface);
+
+ rv = ch343_configure(ch343);
+ if (rv)
+ goto alloc_fail7;
+
+ if (ch343->iface == 0) {
+ /* register the device now, as it is ready */
+ rv = usb_register_dev(intf, &ch343_class);
+ if (rv) {
+ /* error when registering this driver */
+ dev_err(&intf->dev, "Not able to get a minor for this device.\n");
+ } else {
+ g_intf = intf;
+ }
+ }
+
+ tty_dev = tty_port_register_device(&ch343->port, ch343_tty_driver, minor, &control_interface->dev);
+ if (IS_ERR(tty_dev)) {
+ rv = PTR_ERR(tty_dev);
+ goto alloc_fail7;
+ }
+
+ return 0;
+
+alloc_fail7:
+ usb_set_intfdata(intf, NULL);
+ for (i = 0; i < CH343_NW; i++)
+ usb_free_urb(ch343->wb[i].urb);
+alloc_fail6:
+ for (i = 0; i < num_rx_buf; i++)
+ usb_free_urb(ch343->read_urbs[i]);
+ ch343_read_buffers_free(ch343);
+ usb_free_urb(ch343->ctrlurb);
+alloc_fail5:
+ ch343_write_buffers_free(ch343);
+alloc_fail4:
+ usb_free_coherent(usb_dev, ctrlsize, ch343->ctrl_buffer, ch343->ctrl_dma);
+alloc_fail2:
+ ch343_release_minor(ch343);
+ kfree(ch343);
+alloc_fail:
+ return rv;
+}
+
+static void stop_data_traffic(struct ch343 *ch343)
+{
+ int i;
+
+ usb_kill_urb(ch343->ctrlurb);
+ for (i = 0; i < CH343_NW; i++)
+ usb_kill_urb(ch343->wb[i].urb);
+ for (i = 0; i < ch343->rx_buflimit; i++)
+ usb_kill_urb(ch343->read_urbs[i]);
+ cancel_work_sync(&ch343->work);
+}
+
+static void ch343_disconnect(struct usb_interface *intf)
+{
+ struct ch343 *ch343 = usb_get_intfdata(intf);
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ struct tty_struct *tty;
+ int i;
+
+ dev_dbg(&intf->dev, "%s\n", __func__);
+
+ /* sibling interface is already cleaning up */
+ if (!ch343)
+ return;
+
+ /* give back minor */
+ if ((ch343->iface == 0) && (g_intf != NULL)) {
+ usb_deregister_dev(g_intf, &ch343_class);
+ }
+
+ mutex_lock(&ch343->mutex);
+ ch343->disconnected = true;
+ wake_up_all(&ch343->wioctl);
+ usb_set_intfdata(ch343->control, NULL);
+ usb_set_intfdata(ch343->data, NULL);
+ mutex_unlock(&ch343->mutex);
+
+ tty = tty_port_tty_get(&ch343->port);
+ if (tty) {
+ tty_vhangup(tty);
+ tty_kref_put(tty);
+ }
+
+ stop_data_traffic(ch343);
+
+ tty_unregister_device(ch343_tty_driver, ch343->minor);
+
+ usb_free_urb(ch343->ctrlurb);
+ for (i = 0; i < CH343_NW; i++)
+ usb_free_urb(ch343->wb[i].urb);
+ for (i = 0; i < ch343->rx_buflimit; i++)
+ usb_free_urb(ch343->read_urbs[i]);
+ ch343_write_buffers_free(ch343);
+ usb_free_coherent(usb_dev, ch343->ctrlsize, ch343->ctrl_buffer, ch343->ctrl_dma);
+ ch343_read_buffers_free(ch343);
+
+ usb_driver_release_interface(&ch343_driver, intf == ch343->control ? ch343->data : ch343->control);
+
+ tty_port_put(&ch343->port);
+ dev_info(&intf->dev, "%s\n", "ch343 usb device disconnect.");
+}
+
+#ifdef CONFIG_PM
+static int ch343_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct ch343 *ch343 = usb_get_intfdata(intf);
+ int cnt;
+
+ dev_dbg(&intf->dev, "%s\n", __func__);
+
+ spin_lock_irq(&ch343->write_lock);
+ if (PMSG_IS_AUTO(message)) {
+ if (ch343->transmitting) {
+ spin_unlock_irq(&ch343->write_lock);
+ return -EBUSY;
+ }
+ }
+ cnt = ch343->susp_count++;
+ spin_unlock_irq(&ch343->write_lock);
+
+ if (cnt)
+ return 0;
+
+ stop_data_traffic(ch343);
+
+ return 0;
+}
+
+static int ch343_resume(struct usb_interface *intf)
+{
+ struct ch343 *ch343 = usb_get_intfdata(intf);
+ struct urb *urb;
+ int rv = 0;
+
+ dev_dbg(&intf->dev, "%s\n", __func__);
+
+ spin_lock_irq(&ch343->write_lock);
+
+ if (--ch343->susp_count)
+ goto out;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
+ if (tty_port_initialized(&ch343->port)) {
+#else
+ if (test_bit(ASYNCB_INITIALIZED, &ch343->port.flags)) {
+#endif
+ rv = usb_submit_urb(ch343->ctrlurb, GFP_ATOMIC);
+
+ for (;;) {
+ urb = usb_get_from_anchor(&ch343->delayed);
+ if (!urb)
+ break;
+
+ ch343_start_wb(ch343, urb->context);
+ }
+
+ /*
+ * delayed error checking because we must
+ * do the write path at all cost
+ */
+ if (rv < 0)
+ goto out;
+
+ rv = ch343_submit_read_urbs(ch343, GFP_ATOMIC);
+ }
+out:
+ spin_unlock_irq(&ch343->write_lock);
+
+ return rv;
+}
+
+static int ch343_reset_resume(struct usb_interface *intf)
+{
+ struct ch343 *ch343 = usb_get_intfdata(intf);
+
+ dev_dbg(&intf->dev, "%s\n", __func__);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
+ if (tty_port_initialized(&ch343->port))
+#else
+ if (test_bit(ASYNCB_INITIALIZED, &ch343->port.flags))
+#endif
+ tty_port_tty_hangup(&ch343->port, false);
+
+ return ch343_resume(intf);
+}
+
+#endif /* CONFIG_PM */
+
+/*
+ * USB driver structure.
+ */
+
+static const struct usb_device_id ch343_ids[] = {{USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55D2, /* ch342 chip */
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55D3, /* ch343 chip */
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55D5, /* ch344 chip */
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55DA, /* ch347 chip mode0*/
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55DB, /* ch347 chip mode1*/
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55DD, /* ch347 chip mode3*/
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55D8, /* ch9101 chip */
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55D4, /* ch9102 chip */
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55D7, /* ch9103 chip */
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {USB_DEVICE_INTERFACE_PROTOCOL(0x1a86, 0x55DF, /* ch9104 chip */
+ USB_CDC_ACM_PROTO_AT_V25TER)},
+
+ {}};
+
+MODULE_DEVICE_TABLE(usb, ch343_ids);
+
+static struct usb_driver ch343_driver = {
+ .name = "usb_ch343",
+ .probe = ch343_probe,
+ .disconnect = ch343_disconnect,
+#ifdef CONFIG_PM
+ .suspend = ch343_suspend,
+ .resume = ch343_resume,
+ .reset_resume = ch343_reset_resume,
+#endif
+ .id_table = ch343_ids,
+#ifdef CONFIG_PM
+ .supports_autosuspend = 1,
+#endif
+ .disable_hub_initiated_lpm = 1,
+};
+
+/*
+ * TTY driver structures.
+ */
+static const struct tty_operations ch343_ops = {
+ .install = ch343_tty_install,
+ .open = ch343_tty_open,
+ .close = ch343_tty_close,
+ .cleanup = ch343_tty_cleanup,
+ .hangup = ch343_tty_hangup,
+ .write = ch343_tty_write,
+ .write_room = ch343_tty_write_room,
+ .ioctl = ch343_tty_ioctl,
+ .chars_in_buffer = ch343_tty_chars_in_buffer,
+ .break_ctl = ch343_tty_break_ctl,
+ .set_termios = ch343_tty_set_termios,
+ .tiocmget = ch343_tty_tiocmget,
+ .tiocmset = ch343_tty_tiocmset,
+};
+
+/*
+ * Init / exit.
+ */
+static int __init ch343_init(void)
+{
+ int retval;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+ ch343_tty_driver = tty_alloc_driver(CH343_TTY_MINORS, TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(ch343_tty_driver))
+ return PTR_ERR(ch343_tty_driver);
+#else
+ ch343_tty_driver = alloc_tty_driver(CH343_TTY_MINORS);
+ if (!ch343_tty_driver)
+ return -ENOMEM;
+#endif
+ ch343_tty_driver->driver_name = "usbch343", ch343_tty_driver->name = "ttyCH343USB",
+ ch343_tty_driver->major = CH343_TTY_MAJOR, ch343_tty_driver->minor_start = 0,
+ ch343_tty_driver->type = TTY_DRIVER_TYPE_SERIAL, ch343_tty_driver->subtype = SERIAL_TYPE_NORMAL,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
+ ch343_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+#endif
+ ch343_tty_driver->init_termios = tty_std_termios;
+ ch343_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty_set_operations(ch343_tty_driver, &ch343_ops);
+
+ retval = tty_register_driver(ch343_tty_driver);
+ if (retval) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+ tty_driver_kref_put(ch343_tty_driver);
+#else
+ put_tty_driver(ch343_tty_driver);
+#endif
+ return retval;
+ }
+
+ retval = usb_register(&ch343_driver);
+ if (retval) {
+ tty_unregister_driver(ch343_tty_driver);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+ tty_driver_kref_put(ch343_tty_driver);
+#else
+ put_tty_driver(ch343_tty_driver);
+#endif
+ return retval;
+ }
+
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
+ printk(KERN_INFO KBUILD_MODNAME ": " VERSION_DESC "\n");
+
+ return 0;
+}
+
+static void __exit ch343_exit(void)
+{
+ usb_deregister(&ch343_driver);
+ tty_unregister_driver(ch343_tty_driver);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+ tty_driver_kref_put(ch343_tty_driver);
+#else
+ put_tty_driver(ch343_tty_driver);
+#endif
+ idr_destroy(&ch343_minors);
+ printk(KERN_INFO KBUILD_MODNAME
+ ": "
+ "ch343 driver exit.\n");
+}
+
+module_init(ch343_init);
+module_exit(ch343_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(VERSION_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(CH343_TTY_MAJOR);
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/ch343.h b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/ch343.h
new file mode 100644
index 0000000..c53a875
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/CH343/Linux/ch343ser_linux/driver/ch343.h
@@ -0,0 +1,243 @@
+#ifndef _CH343_H
+#define _CH343_H
+
+/*
+ * Baud rate and default timeout
+ */
+#define DEFAULT_BAUD_RATE 9600
+#define DEFAULT_TIMEOUT 2000
+
+/*
+ * CMSPAR, some architectures can't have space and mark parity.
+ */
+
+#ifndef CMSPAR
+#define CMSPAR 0
+#endif
+
+/*
+ * Major and minor numbers.
+ */
+
+#define CH343_TTY_MAJOR 170
+#define CH343_TTY_MINORS 256
+
+#define USB_MINOR_BASE 70
+
+/*
+ * Requests.
+ */
+
+#define USB_RT_CH343 (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
+
+#define CMD_R 0x95
+#define CMD_W 0x9A
+#define CMD_C1 0xA1
+#define CMD_C2 0xA4
+#define CMD_C3 0x05
+#define CMD_C4 0xA8
+#define CMD_C5 0x5E
+#define CMD_C6 0x5F
+
+#define CH343_CTO_O 0x10
+#define CH343_CTO_D 0x20
+#define CH343_CTO_R 0x40
+#define CH343_CTO_A 0x80
+#define CH343_CTI_C 0x01
+#define CH343_CTI_DS 0x02
+#define CH343_CTI_R 0x04
+#define CH343_CTI_DC 0x08
+#define CH343_CTI_ST 0x0f
+
+#define CH343_CTT_M 0x08
+#define CH343_CTT_F 0x44
+#define CH343_CTT_P 0x04
+#define CH343_CTT_O 0x02
+
+#define CH343_LO 0x02
+#define CH343_LE 0x04
+#define CH343_LB
+#define CH343_LP 0x00
+#define CH343_LF 0x40
+#define CH343_LM 0x08
+
+#define CH343_L_R_CT 0x80
+#define CH343_L_R_CL 0x04
+#define CH343_L_R_T 0x08
+
+#define CH343_L_E_R 0x80
+#define CH343_L_E_T 0x40
+#define CH343_L_P_S 0x38
+#define CH343_L_P_M 0x28
+#define CH343_L_P_E 0x18
+#define CH343_L_P_O 0x08
+#define CH343_L_SB 0x04
+#define CH343_L_C8 0x03
+#define CH343_L_C7 0x02
+#define CH343_L_C6 0x01
+#define CH343_L_C5 0x00
+
+#define CH343_N_B 0x80
+#define CH343_N_AB 0x10
+
+/*
+ * Internal driver structures.
+ */
+
+/*
+ * The only reason to have several buffers is to accommodate assumptions
+ * in line disciplines. They ask for empty space amount, receive our URB size,
+ * and proceed to issue several 1-character writes, assuming they will fit.
+ * The very first write takes a complete URB. Fortunately, this only happens
+ * when processing onlcr, so we only need 2 buffers. These values must be
+ * powers of 2.
+ */
+#define CH343_NW 16
+#define CH343_NR 16
+
+struct ch343_wb {
+ unsigned char *buf;
+ dma_addr_t dmah;
+ int len;
+ int use;
+ struct urb *urb;
+ struct ch343 *instance;
+};
+
+struct ch343_rb {
+ int size;
+ unsigned char *base;
+ dma_addr_t dma;
+ int index;
+ struct ch343 *instance;
+};
+
+struct usb_ch343_line_coding {
+ __u32 dwDTERate;
+ __u8 bCharFormat;
+#define USB_CH343_1_STOP_BITS 0
+#define USB_CH343_1_5_STOP_BITS 1
+#define USB_CH343_2_STOP_BITS 2
+
+ __u8 bParityType;
+#define USB_CH343_NO_PARITY 0
+#define USB_CH343_ODD_PARITY 1
+#define USB_CH343_EVEN_PARITY 2
+#define USB_CH343_MARK_PARITY 3
+#define USB_CH343_SPACE_PARITY 4
+
+ __u8 bDataBits;
+} __attribute__((packed));
+
+typedef enum {
+ CHIP_CH342F = 0x00,
+ CHIP_CH342K,
+ CHIP_CH343GP,
+ CHIP_CH343G_AUTOBAUD,
+ CHIP_CH343K,
+ CHIP_CH343J,
+ CHIP_CH344L,
+ CHIP_CH344L_V2,
+ CHIP_CH344Q,
+ CHIP_CH347T,
+ CHIP_CH9101UH,
+ CHIP_CH9101RY,
+ CHIP_CH9102F,
+ CHIP_CH9102X,
+ CHIP_CH9103M,
+ CHIP_CH9104L,
+} CHIPTYPE;
+
+struct gpioinfo {
+ int group;
+ int pin;
+};
+
+struct ch343_gpio {
+ int gpiocount;
+ struct gpioinfo io[64];
+};
+
+struct ch343_gpio ch343_gpios[] = {
+ { 0, {}},
+ { 0, {}},
+ { 0, {}},
+ { 0, {}},
+ { 0, {}},
+ { 0, {}},
+ /* CH344L */
+ { 8, {}},
+ /* CH344L-V2 */
+ { 8, {}},
+ /* CH344Q */
+ { 8, {}},
+ /* CH347T */
+ { 4, {}},
+ /* CH9101UH */
+ { 5, {{3, 2}, {3, 3}, {1, 3}, {1, 2}, {1, 5}, {2, 4}}},
+ /* CH9101RY */
+ { 4, {{1, 3}, {3, 3}, {3, 2}, {2, 4}}},
+ /* CH9102F */
+ { 5, {{2, 1}, {2, 7}, {2, 4}, {2, 6}, {2, 3}}},
+ /* CH9102X */
+ { 6, {{2, 3}, {2, 5}, {2, 1}, {2, 7}, {3, 0}, {2, 2}}},
+ /* CH9103M */
+ {12, {{1, 3}, {1, 2}, {3, 2}, {2, 6}, {1, 0}, {1, 6}, {2, 3}, {2, 5}, {3, 0}, {2, 2}, {1, 5}, {2, 4}}},
+ /* CH9104L */
+ {24, {}},
+};
+
+struct ch343 {
+ struct usb_device *dev; /* the corresponding usb device */
+ struct usb_interface *control; /* control interface */
+ struct usb_interface *data; /* data interface */
+ struct tty_port port; /* our tty port data */
+ struct urb *ctrlurb; /* urbs */
+ u8 *ctrl_buffer; /* buffers of urbs */
+ dma_addr_t ctrl_dma; /* dma handles of buffers */
+ struct ch343_wb wb[CH343_NW];
+ unsigned long read_urbs_free;
+ struct urb *read_urbs[CH343_NR];
+ struct ch343_rb read_buffers[CH343_NR];
+ int rx_buflimit;
+ int rx_endpoint;
+ spinlock_t read_lock;
+ int write_used; /* number of non-empty write buffers */
+ int transmitting;
+ spinlock_t write_lock;
+ struct mutex mutex;
+ bool disconnected;
+ struct usb_ch343_line_coding line; /* bits, stop, parity */
+ struct work_struct work; /* work queue entry for line discipline waking up */
+ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
+ unsigned int ctrlout; /* output control lines (DTR, RTS) */
+ struct async_icount iocount; /* counters for control line changes */
+ struct async_icount oldcount; /* for comparison of counter */
+ wait_queue_head_t wioctl; /* for ioctl */
+ unsigned int writesize; /* max packet size for the output bulk endpoint */
+ unsigned int readsize, ctrlsize; /* buffer sizes for freeing */
+ unsigned int minor; /* ch343 minor number */
+ unsigned char clocal; /* termios CLOCAL */
+ unsigned int susp_count; /* number of suspended interfaces */
+ u8 bInterval;
+ struct usb_anchor delayed; /* writes queued for a device about to be woken */
+ unsigned long quirks;
+ u8 iface;
+ CHIPTYPE chiptype;
+ u16 idVendor;
+ u16 idProduct;
+ u8 gpio5dir;
+};
+
+#define CDC_DATA_INTERFACE_TYPE 0x0a
+
+/* constants describing various quirks and errors */
+#define NO_UNION_NORMAL BIT(0)
+#define SINGLE_RX_URB BIT(1)
+#define NO_CAP_LINE BIT(2)
+#define NO_DATA_INTERFACE BIT(4)
+#define IGNORE_DEVICE BIT(5)
+#define QUIRK_CONTROL_LINE_STATE BIT(6)
+#define CLEAR_HALT_CONDITIONS BIT(7)
+
+#endif
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/MAC/CH34XSER_MAC.ZIP b/doc/Freenove ESP32-S3-Wroom/CH343/MAC/CH34XSER_MAC.ZIP
new file mode 100644
index 0000000..1eabc47
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/CH343/MAC/CH34XSER_MAC.ZIP differ
diff --git a/doc/Freenove ESP32-S3-Wroom/CH343/MAC/ReadMeFirst.txt b/doc/Freenove ESP32-S3-Wroom/CH343/MAC/ReadMeFirst.txt
new file mode 100644
index 0000000..9b6f9f6
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/CH343/MAC/ReadMeFirst.txt
@@ -0,0 +1,5 @@
+For MAC users, the CH343 driver will always need to go to the official website to download the latest version,
+as older versions may not be suitable.
+
+Below is the official download link:
+http://www.wch-ic.com/search?t=all&q=ch343
\ No newline at end of file
diff --git a/doc/Freenove ESP32-S3-Wroom/Datasheet/74HC595.pdf b/doc/Freenove ESP32-S3-Wroom/Datasheet/74HC595.pdf
new file mode 100644
index 0000000..0dac860
Binary files /dev/null and b/doc/Freenove ESP32-S3-Wroom/Datasheet/74HC595.pdf differ
diff --git a/doc/Freenove ESP32-S3-Wroom/Datasheet/ESP32-S3 Pinout.pdf b/doc/Freenove ESP32-S3-Wroom/Datasheet/ESP32-S3 Pinout.pdf
new file mode 100644
index 0000000..3b2fc1c
--- /dev/null
+++ b/doc/Freenove ESP32-S3-Wroom/Datasheet/ESP32-S3 Pinout.pdf
@@ -0,0 +1,2532 @@
+%PDF-1.5
%
+1 0 obj
<>/OCGs[6 0 R 49 0 R 91 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<>stream
+
+
+
+
+ 2023-04-06T10:04:32+08:00
+ 2023-04-06T10:05:25+08:00
+ 2023-04-06T10:05:25+08:00
+ Adobe Illustrator CS6 (Windows)
+
+
+
+ 256
+ 116
+ JPEG
+ /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAdAEAAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AkUn5N+YZPI2k2qaZYHVb
vWDcXaSWXFo4UgvlRr2RZqz/ABzJxYceNRscFMrRHl/yNrkWuW91f6JdyOmhWVnBcXdtDdypdQ29
xHMpuWkVoaO60ZFbkKeGKCULov5e+botC8p2+k6XLpWtaRcG9ubhrSG0jNzDpriNZmilkM6SXCCK
SQ0LK/TGk2ti/Lzzinl+ztpdCup9X/Q+n2vlq7E0ajSLyGeRrl5WLx+mSGjYsinmF4+2K2iPM35a
+a7mw8xab+jHuNP0Z0i8soAk3rQajrEOoXPCNmUEQQwrHRiKioxQCn3nHyfcXvkrydY2OhP9U0/U
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
KuxV2KuxV2Kv/9k=
+
+
+
+
+
+ uuid:f6f902fa-7019-428a-a7c9-4bd3356e59b8
+ xmp.did:5c4bb5af-f394-4ff8-b967-e7649e496c1a
+ xmp.did:F13915551FD4ED119B21824070DFCF55
+ proof:pdf
+
+ xmp.iid:F03915551FD4ED119B21824070DFCF55
+ xmp.did:F03915551FD4ED119B21824070DFCF55
+ xmp.did:5c4bb5af-f394-4ff8-b967-e7649e496c1a
+ proof:pdf
+
+
+
+
+ converted
+ from application/x-indesign to application/pdf
+ Adobe InDesign 16.0 (Macintosh)
+ /
+ 2021-03-05T12:52:19Z
+
+
+ saved
+ xmp.iid:0f285f92-6b59-6d47-9f29-262fa81e0f04
+ 2021-08-30T17:36:46+08:00
+ Adobe Illustrator 24.0 (Windows)
+ /
+
+
+ saved
+ xmp.iid:F13915551FD4ED119B21824070DFCF55
+ 2023-04-06T10:04:32+08:00
+ Adobe Illustrator CS6 (Windows)
+ /
+
+
+
+
+
+ application/pdf
+
+
+ ESP32-S3 Pinout
+
+
+
+
+ Adobe PDF library 10.01
+ False
+
+
+ 1
+ False
+ True
+
+ 173.801794
+ 77.577866
+ Millimeters
+
+
+
+
+ 3ds
+ 3ds
+ Regular
+ TrueType
+ Version 1.000
+ False
+ 3ds Regular.ttf
+
+
+
+
+
+ Cyan
+ Magenta
+ Yellow
+ Black
+
+
+
+
+
+ 默认色板组
+ 0
+
+
+
+
+
+ AIRobin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endstream
endobj
3 0 obj
<>
endobj
8 0 obj
<>/Resources<>/Font<>/ProcSet[/PDF/Text]/Properties<>>>/Thumb 97 0 R/TrimBox[0.0 0.0 492.667 219.906]/Type/Page>>
endobj
93 0 obj
<>stream
+HWM
s.5S9l $HU3bmk`XDOo7xkrbKe-&.5ƴ\ۇ.]u1k5?Υ˛?/yybGi9řՒF~\1]
\[.W/ծ&7[r}&Cg̉Lm|]erAx+oZ̊|^ecy}E"DyJx3<-+f[-B~rΐ=לDf0kԉ_.0_8QnWe0xYJ|,:D2b7G$
+g7>s|,Q(I|# ),aIInb;>RػIAGVЁ"h+ʊq-=(cZ-/F"&Z1kN
+Llb"$7A8jM5=%RxtSE
+\"Y)Jq/)DќHA s&LVLVXQ<Ia_JpnRPG
+_+Rt^4Dqξ!^s&+&+vV8bKibcuk2~֊o6IIk
+WB|x12!`7t!
gϡyiP$7K)PL&)&)vRx2yLMRdgG;Iё"d$$EO
+LB"")bD9h92I1Iѓi&NRLRHA KMVLVXQG
+?IRAqMd>YWAGZЁEExȟX{hUZxa;^ewE]GBe]d3kqYa_ʊӲ9DS
+^8__o1Η̟hbcEüNVnMgOVk`wDJk|@S2 O:~֔V\K:ƅl*ZN"*aoQi%U$!-8N늎 Np
X@OpPqwx+Io+Io+YqVdZVw\
guǕ8;e5bJ#S:ޥ}wy]x!ޥ~wC~KP?_p#x@ǀxǁ o=Zmwaͭ.9*#6hK(,vB/<ţ>Gͅk.lw\;/OklGQa6X;<>P+wǥJmkYk++YmUn|KXпI_Uք~2 բA]q
+L?~4SDǪ$= *&V7cP{0PKb>^Yclnt
πgRӊڐx4ٍ-5
%+]6k6R)'7#E]WbUJ_iSdט
+}bx#s[Uݺ(*
+OT:H7(u"<&a~ܝqh,0Cj:~9kptXƲzp ,W.q_mU1*|{e::hUW[Yn.Ɏ}'HL#cv9de
+Ӏ=Y[ED8SS/)o*9$ZQ8(UٌU$USK¹8e55ۂt0qSҤ4Сj`rt%-M5q*$B6ÁρWV< #ϙLO4l>5ES#&Rtԑw
Ͳ2ZQ`4`_kN5=4Q'&wzCA9dOpfR4
+s9۬@ cL5mc;*km'Z-dQ
s u;GLm(8YCݒp&H:h
t'nĉA̠rbP]-G^3Ix@950Tt6k mGzݠm#j`:3(D \#u6}ksCu}ߤat쨕{lפq{3𐾺 vyjj+FO}R ZmUZ -(Nb5Mޠ6fa+e)zlͲ<ç)yp~=k8_iB)f]nP[-klyfpp֑G~Cv-\lL+0x)K7l3dž%tAh.D8u-Vز̓iɠMirYrIZ/g2#QW#VK V1.uWjk4ۗjJ\nq6yn_%|{%oܱZSMpi .;A|7OAlš>6`ZUdG~DQI8kKuzkMQe$a#-y B![uW⻁mTU܆ĥ'WOD5 grѶr-}ѩso+>%d|0'Fꂑ`=kH#-NmVo+``w:Sg|}`dnIH"