summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Tulloh <alexandertulloh@gmail.com>2021-01-11 14:13:47 +1100
committerGitHub <noreply@github.com>2021-01-10 19:13:47 -0800
commitffd8ff642d4257fa588d9f42144d923bd570bbbd (patch)
tree5be7f83988113066a9a0b46383839082235c2be8
parent6edbd845ebda0b67e9d56a21977381949476930a (diff)
[Keyboard] Oddball keyboard and optical sensor update (#10450)
* Add oddballl v2 - add CPI options - add scroll support - add click-and-drag support - PMW3360 implementation - ADNS9800 improvements * Set default make directory * Update readme with PMW config * Change bootloader * Update unused pins on v2 * Remove diode switch * Move bootloader selection to keyboard version level * Change default keyboard folder to v1 * Move sensor selection to keymap * Remove PK debounce * Change to only send mouse report on change * Change CPI function cpi type * Remove EEPROM state check * Update CPI to only change on key down * Fix incorrect F8 in keymap * Add v2.1 with more convenient controller pinout * Add keyboard readmes * Update keyboards/oddball/pmw/pmw3360_srom_0x04.h Remove direct AVR reference Co-authored-by: Ryan <fauxpark@gmail.com> * Remove direct AVR reference Co-authored-by: Ryan <fauxpark@gmail.com> Co-authored-by: Alexander Tulloh <alex@riberry.io> Co-authored-by: Ryan <fauxpark@gmail.com>
-rw-r--r--keyboards/oddball/adns.c270
-rw-r--r--keyboards/oddball/adns/adns.c219
-rw-r--r--keyboards/oddball/adns/adns.h35
-rw-r--r--keyboards/oddball/adns/adns9800_srom_A6.h3078
-rw-r--r--keyboards/oddball/adns9800_srom_A4.h212
-rw-r--r--keyboards/oddball/config.h186
-rw-r--r--keyboards/oddball/keymaps/default/config.h1
-rw-r--r--keyboards/oddball/keymaps/default/keymap.c9
-rw-r--r--keyboards/oddball/keymaps/pmw3360/config.h1
-rw-r--r--keyboards/oddball/keymaps/pmw3360/keymap.c47
-rw-r--r--keyboards/oddball/oddball.c152
-rw-r--r--keyboards/oddball/oddball.h22
-rw-r--r--keyboards/oddball/optical_sensor/optical_sensor.h53
-rw-r--r--keyboards/oddball/pmw/pmw.c226
-rw-r--r--keyboards/oddball/pmw/pmw.h35
-rw-r--r--keyboards/oddball/pmw/pmw3360_srom_0x04.h280
-rw-r--r--keyboards/oddball/readme.md13
-rw-r--r--keyboards/oddball/rules.mk26
-rw-r--r--keyboards/oddball/v1/config.h31
-rw-r--r--keyboards/oddball/v1/readme.md12
-rw-r--r--keyboards/oddball/v1/rules.mk2
-rw-r--r--keyboards/oddball/v1/v1.c17
-rw-r--r--keyboards/oddball/v1/v1.h19
-rw-r--r--keyboards/oddball/v2/config.h31
-rw-r--r--keyboards/oddball/v2/readme.md12
-rw-r--r--keyboards/oddball/v2/rules.mk2
-rw-r--r--keyboards/oddball/v2/v2.c17
-rw-r--r--keyboards/oddball/v2/v2.h19
-rw-r--r--keyboards/oddball/v2_1/config.h31
-rw-r--r--keyboards/oddball/v2_1/readme.md12
-rw-r--r--keyboards/oddball/v2_1/rules.mk2
-rw-r--r--keyboards/oddball/v2_1/v2_1.c17
-rw-r--r--keyboards/oddball/v2_1/v2_1.h19
33 files changed, 4430 insertions, 678 deletions
diff --git a/keyboards/oddball/adns.c b/keyboards/oddball/adns.c
deleted file mode 100644
index 4582be1f2c..0000000000
--- a/keyboards/oddball/adns.c
+++ /dev/null
@@ -1,270 +0,0 @@
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include "quantum.h"
-#include "pointing_device.h"
-#include "adns9800_srom_A4.h"
-#include <LUFA/Drivers/Peripheral/SPI.h>
-
-// registers
-#define REG_Product_ID 0x00
-#define REG_Revision_ID 0x01
-#define REG_Motion 0x02
-#define REG_Delta_X_L 0x03
-#define REG_Delta_X_H 0x04
-#define REG_Delta_Y_L 0x05
-#define REG_Delta_Y_H 0x06
-#define REG_SQUAL 0x07
-#define REG_Pixel_Sum 0x08
-#define REG_Maximum_Pixel 0x09
-#define REG_Minimum_Pixel 0x0a
-#define REG_Shutter_Lower 0x0b
-#define REG_Shutter_Upper 0x0c
-#define REG_Frame_Period_Lower 0x0d
-#define REG_Frame_Period_Upper 0x0e
-#define REG_Configuration_I 0x0f
-#define REG_Configuration_II 0x10
-#define REG_Frame_Capture 0x12
-#define REG_SROM_Enable 0x13
-#define REG_Run_Downshift 0x14
-#define REG_Rest1_Rate 0x15
-#define REG_Rest1_Downshift 0x16
-#define REG_Rest2_Rate 0x17
-#define REG_Rest2_Downshift 0x18
-#define REG_Rest3_Rate 0x19
-#define REG_Frame_Period_Max_Bound_Lower 0x1a
-#define REG_Frame_Period_Max_Bound_Upper 0x1b
-#define REG_Frame_Period_Min_Bound_Lower 0x1c
-#define REG_Frame_Period_Min_Bound_Upper 0x1d
-#define REG_Shutter_Max_Bound_Lower 0x1e
-#define REG_Shutter_Max_Bound_Upper 0x1f
-#define REG_LASER_CTRL0 0x20
-#define REG_Observation 0x24
-#define REG_Data_Out_Lower 0x25
-#define REG_Data_Out_Upper 0x26
-#define REG_SROM_ID 0x2a
-#define REG_Lift_Detection_Thr 0x2e
-#define REG_Configuration_V 0x2f
-#define REG_Configuration_IV 0x39
-#define REG_Power_Up_Reset 0x3a
-#define REG_Shutdown 0x3b
-#define REG_Inverse_Product_ID 0x3f
-#define REG_Motion_Burst 0x50
-#define REG_SROM_Load_Burst 0x62
-#define REG_Pixel_Burst 0x64
-
-// pins
-#define NCS 0
-
-extern const uint16_t firmware_length;
-extern const uint8_t firmware_data[];
-
-enum motion_burst_property{
- motion = 0,
- observation,
- delta_x_l,
- delta_x_h,
- delta_y_l,
- delta_y_h,
- squal,
- pixel_sum,
- maximum_pixel,
- minimum_pixel,
- shutter_upper,
- shutter_lower,
- frame_period_upper,
- frame_period_lower,
- end_data
-};
-
-// used to track the motion delta between updates
-volatile int32_t delta_x;
-volatile int32_t delta_y;
-
-void adns_begin(void){
- PORTB &= ~ (1 << NCS);
-}
-
-void adns_end(void){
- PORTB |= (1 << NCS);
-}
-
-void adns_write(uint8_t reg_addr, uint8_t data){
-
- adns_begin();
-
- //send address of the register, with MSBit = 1 to indicate it's a write
- SPI_TransferByte(reg_addr | 0x80 );
- SPI_TransferByte(data);
-
- // tSCLK-NCS for write operation
- wait_us(20);
-
- adns_end();
-
- // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
- wait_us(100);
-}
-
-uint8_t adns_read(uint8_t reg_addr){
-
- adns_begin();
-
- // send adress of the register, with MSBit = 0 to indicate it's a read
- SPI_TransferByte(reg_addr & 0x7f );
- uint8_t data = SPI_TransferByte(0);
-
- // tSCLK-NCS for read operation is 120ns
- wait_us(1);
-
- adns_end();
-
- // tSRW/tSRR (=20us) minus tSCLK-NCS
- wait_us(19);
-
- return data;
-}
-
-void pointing_device_init(void) {
-
- if(!is_keyboard_master())
- return;
-
- // interrupt 2
- EICRA &= ~(1 << 4);
- EICRA |= (1 << 5);
- EIMSK |= (1<<INT2);
-
- // mode 3
- SPI_Init(
- SPI_SPEED_FCPU_DIV_8 |
- SPI_ORDER_MSB_FIRST |
- SPI_SCK_LEAD_FALLING |
- SPI_SAMPLE_TRAILING |
- SPI_MODE_MASTER);
-
- // set B0 output
- DDRB |= (1 << 0);
-
- // reset serial port
- adns_end();
- adns_begin();
- adns_end();
-
- // reboot
- adns_write(REG_Power_Up_Reset, 0x5a);
- wait_ms(50);
-
- // read registers and discard
- adns_read(REG_Motion);
- adns_read(REG_Delta_X_L);
- adns_read(REG_Delta_X_H);
- adns_read(REG_Delta_Y_L);
- adns_read(REG_Delta_Y_H);
-
- // upload firmware
-
- // set the configuration_IV register in 3k firmware mode
- // bit 1 = 1 for 3k mode, other bits are reserved
- adns_write(REG_Configuration_IV, 0x02);
-
- // write 0x1d in SROM_enable reg for initializing
- adns_write(REG_SROM_Enable, 0x1d);
-
- // wait for more than one frame period
- // assume that the frame rate is as low as 100fps... even if it should never be that low
- wait_ms(10);
-
- // write 0x18 to SROM_enable to start SROM download
- adns_write(REG_SROM_Enable, 0x18);
-
- // write the SROM file (=firmware data)
- adns_begin();
-
- // write burst destination adress
- SPI_TransferByte(REG_SROM_Load_Burst | 0x80);
- wait_us(15);
-
- // send all bytes of the firmware
- unsigned char c;
- for(int i = 0; i < firmware_length; i++){
- c = (unsigned char)pgm_read_byte(firmware_data + i);
- SPI_TransferByte(c);
- wait_us(15);
- }
-
- adns_end();
-
- wait_ms(10);
-
- // enable laser(bit 0 = 0b), in normal mode (bits 3,2,1 = 000b)
- // reading the actual value of the register is important because the real
- // default value is different from what is said in the datasheet, and if you
- // change the reserved bytes (like by writing 0x00...) it would not work.
- uint8_t laser_ctrl0 = adns_read(REG_LASER_CTRL0);
- adns_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
-
- wait_ms(1);
-
- // set the configuration_I register to set the CPI
- // 0x01 = 50, minimum
- // 0x44 = 3400, default
- // 0x8e = 7100
- // 0xA4 = 8200, maximum
- adns_write(REG_Configuration_I, 0x04);
-
- wait_ms(100);
-}
-
-void pointing_device_task(void) {
-
- if(!is_keyboard_master())
- return;
-
- report_mouse_t report = pointing_device_get_report();
-
- // clamp deltas from -127 to 127
- report.x = delta_x < -127 ? 127 : delta_x > 127 ? 127 : delta_x;
- report.x = -report.x;
-
- report.y = delta_y < -127 ? 127 : delta_y > 127 ? 127 : delta_y;
-
- // reset deltas
- delta_x = 0;
- delta_y = 0;
-
- pointing_device_set_report(report);
- pointing_device_send();
-}
-
-int16_t convertDeltaToInt(uint8_t high, uint8_t low){
-
- // join bytes into twos compliment
- uint16_t twos_comp = (high << 8) | low;
-
- // convert twos comp to int
- if (twos_comp & 0x8000)
- return -1 * ((twos_comp ^ 0xffff) + 1);
-
- return twos_comp;
-}
-
-ISR(INT2_vect) {
- // called on interrupt 2 when sensed motion
- // copy burst data from the respective registers
-
- adns_begin();
-
- // send adress of the register, with MSBit = 1 to indicate it's a write
- SPI_TransferByte(REG_Motion_Burst & 0x7f);
-
- uint8_t burst_data[pixel_sum];
-
- for (int i = 0; i < pixel_sum; ++i) {
- burst_data[i] = SPI_TransferByte(0);
- }
-
- delta_x += convertDeltaToInt(burst_data[delta_x_h], burst_data[delta_x_l]);
- delta_y += convertDeltaToInt(burst_data[delta_y_h], burst_data[delta_y_l]);
-
- adns_end();
-}
diff --git a/keyboards/oddball/adns/adns.c b/keyboards/oddball/adns/adns.c
new file mode 100644
index 0000000000..9338808ff7
--- /dev/null
+++ b/keyboards/oddball/adns/adns.c
@@ -0,0 +1,219 @@
+/* Copyright 2020 Alexander Tulloh
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "spi_master.h"
+#include "quantum.h"
+#include "adns9800_srom_A6.h"
+#include "adns.h"
+
+// registers
+#define REG_Product_ID 0x00
+#define REG_Revision_ID 0x01
+#define REG_Motion 0x02
+#define REG_Delta_X_L 0x03
+#define REG_Delta_X_H 0x04
+#define REG_Delta_Y_L 0x05
+#define REG_Delta_Y_H 0x06
+#define REG_SQUAL 0x07
+#define REG_Pixel_Sum 0x08
+#define REG_Maximum_Pixel 0x09
+#define REG_Minimum_Pixel 0x0a
+#define REG_Shutter_Lower 0x0b
+#define REG_Shutter_Upper 0x0c
+#define REG_Frame_Period_Lower 0x0d
+#define REG_Frame_Period_Upper 0x0e
+#define REG_Configuration_I 0x0f
+#define REG_Configuration_II 0x10
+#define REG_Frame_Capture 0x12
+#define REG_SROM_Enable 0x13
+#define REG_Run_Downshift 0x14
+#define REG_Rest1_Rate 0x15
+#define REG_Rest1_Downshift 0x16
+#define REG_Rest2_Rate 0x17
+#define REG_Rest2_Downshift 0x18
+#define REG_Rest3_Rate 0x19
+#define REG_Frame_Period_Max_Bound_Lower 0x1a
+#define REG_Frame_Period_Max_Bound_Upper 0x1b
+#define REG_Frame_Period_Min_Bound_Lower 0x1c
+#define REG_Frame_Period_Min_Bound_Upper 0x1d
+#define REG_Shutter_Max_Bound_Lower 0x1e
+#define REG_Shutter_Max_Bound_Upper 0x1f
+#define REG_LASER_CTRL0 0x20
+#define REG_Observation 0x24
+#define REG_Data_Out_Lower 0x25
+#define REG_Data_Out_Upper 0x26
+#define REG_SROM_ID 0x2a
+#define REG_Lift_Detection_Thr 0x2e
+#define REG_Configuration_V 0x2f
+#define REG_Configuration_IV 0x39
+#define REG_Power_Up_Reset 0x3a
+#define REG_Shutdown 0x3b
+#define REG_Inverse_Product_ID 0x3f
+#define REG_Motion_Burst 0x50
+#define REG_SROM_Load_Burst 0x62
+#define REG_Pixel_Burst 0x64
+
+#define ADNS_CLOCK_SPEED 2000000
+#define MIN_CPI 200
+#define MAX_CPI 8200
+#define CPI_STEP 200
+#define CLAMP_CPI(value) value < MIN_CPI ? MIN_CPI : value > MAX_CPI ? MAX_CPI : value
+#define SPI_MODE 3
+#define SPI_DIVISOR (F_CPU / ADNS_CLOCK_SPEED)
+#define US_BETWEEN_WRITES 120
+#define US_BETWEEN_READS 20
+#define US_BEFORE_MOTION 100
+#define MSB1 0x80
+
+extern const uint16_t adns_firmware_length;
+extern const uint8_t adns_firmware_data[];
+
+void adns_spi_start(void){
+ spi_start(SPI_SS_PIN, false, SPI_MODE, SPI_DIVISOR);
+}
+
+void adns_write(uint8_t reg_addr, uint8_t data){
+
+ adns_spi_start();
+ spi_write(reg_addr | MSB1);
+ spi_write(data);
+ spi_stop();
+ wait_us(US_BETWEEN_WRITES);
+}
+
+uint8_t adns_read(uint8_t reg_addr){
+
+ adns_spi_start();
+ spi_write(reg_addr & 0x7f );
+ uint8_t data = spi_read();
+ spi_stop();
+ wait_us(US_BETWEEN_READS);
+
+ return data;
+}
+
+void adns_init() {
+
+ setPinOutput(SPI_SS_PIN);
+
+ spi_init();
+
+ // reboot
+ adns_write(REG_Power_Up_Reset, 0x5a);
+ wait_ms(50);
+
+ // read registers and discard
+ adns_read(REG_Motion);
+ adns_read(REG_Delta_X_L);
+ adns_read(REG_Delta_X_H);
+ adns_read(REG_Delta_Y_L);
+ adns_read(REG_Delta_Y_H);
+
+ // upload firmware
+
+ // 3k firmware mode
+ adns_write(REG_Configuration_IV, 0x02);
+
+ // enable initialisation
+ adns_write(REG_SROM_Enable, 0x1d);
+
+ // wait a frame
+ wait_ms(10);
+
+ // start SROM download
+ adns_write(REG_SROM_Enable, 0x18);
+
+ // write the SROM file
+
+ adns_spi_start();
+
+ spi_write(REG_SROM_Load_Burst | 0x80);
+ wait_us(15);
+
+ // send all bytes of the firmware
+ unsigned char c;
+ for(int i = 0; i < adns_firmware_length; i++){
+ c = (unsigned char)pgm_read_byte(adns_firmware_data + i);
+ spi_write(c);
+ wait_us(15);
+ }
+
+ spi_stop();
+
+ wait_ms(10);
+
+ // enable laser
+ uint8_t laser_ctrl0 = adns_read(REG_LASER_CTRL0);
+ adns_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
+}
+
+config_adns_t adns_get_config(void) {
+ uint8_t config_1 = adns_read(REG_Configuration_I);
+ return (config_adns_t){ (config_1 & 0xFF) * CPI_STEP };
+}
+
+void adns_set_config(config_adns_t config) {
+ uint8_t config_1 = (CLAMP_CPI(config.cpi) / CPI_STEP) & 0xFF;
+ adns_write(REG_Configuration_I, config_1);
+}
+
+static int16_t convertDeltaToInt(uint8_t high, uint8_t low){
+
+ // join bytes into twos compliment
+ uint16_t twos_comp = (high << 8) | low;
+
+ // convert twos comp to int
+ if (twos_comp & 0x8000)
+ return -1 * (~twos_comp + 1);
+
+ return twos_comp;
+}
+
+report_adns_t adns_get_report(void) {
+
+ report_adns_t report = {0, 0};
+
+ adns_spi_start();
+
+ // start burst mode
+ spi_write(REG_Motion_Burst & 0x7f);
+
+ wait_us(US_BEFORE_MOTION);
+
+ uint8_t motion = spi_read();
+
+ if(motion & 0x80) {
+
+ // clear observation register
+ spi_read();
+
+ // delta registers
+ uint8_t delta_x_l = spi_read();
+ uint8_t delta_x_h = spi_read();
+ uint8_t delta_y_l = spi_read();
+ uint8_t delta_y_h = spi_read();
+
+ report.x = convertDeltaToInt(delta_x_h, delta_x_l);
+ report.y = convertDeltaToInt(delta_y_h, delta_y_l);
+ }
+
+ // clear residual motion
+ spi_write(REG_Motion & 0x7f);
+
+ spi_stop();
+
+ return report;
+}
diff --git a/keyboards/oddball/adns/adns.h b/keyboards/oddball/adns/adns.h
new file mode 100644
index 0000000000..2f50b8f1be
--- /dev/null
+++ b/keyboards/oddball/adns/adns.h
@@ -0,0 +1,35 @@
+/* Copyright 2020 Alexander Tulloh
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+typedef struct {
+ /* 200 - 8200 CPI supported */
+ uint16_t cpi;
+} config_adns_t;
+
+typedef struct {
+ int16_t x;
+ int16_t y;
+} report_adns_t;
+
+void adns_init(void);
+config_adns_t adns_get_config(void);
+void adns_set_config(config_adns_t);
+/* Reads and clears the current delta values on the ADNS sensor */
+report_adns_t adns_get_report(void);
diff --git a/keyboards/oddball/adns/adns9800_srom_A6.h b/keyboards/oddball/adns/adns9800_srom_A6.h
new file mode 100644
index 0000000000..f5b3abeb62
--- /dev/null
+++ b/keyboards/oddball/adns/adns9800_srom_A6.h
@@ -0,0 +1,3078 @@
+#pragma once
+
+#include "progmem.h"
+
+const uint16_t adns_firmware_length = 3070;
+
+const uint8_t adns_firmware_data[] PROGMEM = {
+0x03,
+0xa6,
+0x68,
+0x1e,
+0x7d,
+0x10,
+0x7e,
+0x7e,
+0x5f,
+0x1c,
+0xb8,
+0xf2,
+0x47,
+0x0c,
+0x7b,
+0x74,
+0x4b,
+0x14,
+0x8b,
+0x75,
+0x66,
+0x51,
+0x0b,
+0x8c,
+0x76,
+0x74,
+0x4b,
+0x14,
+0xaa,
+0xd6,
+0x0f,
+0x9c,
+0xba,
+0xf6,
+0x6e,
+0x3f,
+0xdd,
+0x38,
+0xd5,
+0x02,
+0x80,
+0x9b,
+0x82,
+0x6d,
+0x58,
+0x13,
+0xa4,
+0xab,
+0xb5,
+0xc9,
+0x10,
+0xa2,
+0xc6,
+0x0a,
+0x7f,
+0x5d,
+0x19,
+0x91,
+0xa0,
+0xa3,
+0xce,
+0xeb,
+0x3e,
+0xc9,
+0xf1,
+0x60,
+0x42,
+0xe7,
+0x4c,
+0xfb,
+0x74,
+0x6a,
+0x56,
+0x2e,
+0xbf,
+0xdd,
+0x38,
+0xd3,
+0x05,
+0x88,
+0x92,
+0xa6,
+0xce,
+0xff,
+0x5d,
+0x38,
+0xd1,
+0xcf,
+0xef,
+0x58,
+0xcb,
+0x65,
+0x48,
+0xf0,
+0x35,
+0x85,
+0xa9,
+0xb2,
+0x8f,
+0x5e,
+0xf3,
+0x80,
+0x94,
+0x97,
+0x7e,
+0x75,
+0x97,
+0x87,
+0x73,
+0x13,
+0xb0,
+0x8a,
+0x69,
+0xd4,
+0x0a,
+0xde,
+0xc1,
+0x79,
+0x59,
+0x36,
+0xdb,
+0x9d,
+0xd6,
+0xb8,
+0x15,
+0x6f,
+0xce,
+0x3c,
+0x72,
+0x32,
+0x45,
+0x88,
+0xdf,
+0x6c,
+0xa5,
+0x6d,
+0xe8,
+0x76,
+0x96,
+0x14,
+0x74,
+0x20,
+0xdc,
+0xf4,
+0xfa,
+0x37,
+0x6a,
+0x27,
+0x32,
+0xe3,
+0x29,
+0xbf,
+0xc4,
+0xc7,
+0x06,
+0x9d,
+0x58,
+0xe7,
+0x87,
+0x7c,
+0x2e,
+0x9f,
+0x6e,
+0x49,
+0x07,
+0x5d,
+0x23,
+0x64,
+0x54,
+0x83,
+0x6e,
+0xcb,
+0xb7,
+0x77,
+0xf7,
+0x2b,
+0x6e,
+0x0f,
+0x2e,
+0x66,
+0x12,
+0x60,
+0x55,
+0x65,
+0xfc,
+0x43,
+0xb3,
+0x58,
+0x73,
+0x5b,
+0xe8,
+0x67,
+0x04,
+0x43,
+0x02,
+0xde,
+0xb3,
+0x89,
+0xa0,
+0x6d,
+0x3a,
+0x27,
+0x79,
+0x64,
+0x5b,
+0x0c,
+0x16,
+0x9e,
+0x66,
+0xb1,
+0x8b,
+0x87,
+0x0c,
+0x5d,
+0xf2,
+0xb6,
+0x3d,
+0x71,
+0xdf,
+0x42,
+0x03,
+0x8a,
+0x06,
+0x8d,
+0xef,
+0x1d,
+0xa8,
+0x96,
+0x5c,
+0xed,
+0x31,
+0x61,
+0x5c,
+0xa1,
+0x34,
+0xf6,
+0x8c,
+0x08,
+0x60,
+0x33,
+0x07,
+0x00,
+0x3e,
+0x79,
+0x95,
+0x1b,
+0x43,
+0x7f,
+0xfe,
+0xb6,
+0xa6,
+0xd4,
+0x9d,
+0x76,
+0x72,
+0xbf,
+0xad,
+0xc0,
+0x15,
+0xe8,
+0x37,
+0x31,
+0xa3,
+0x72,
+0x63,
+0x52,
+0x1d,
+0x1c,
+0x5d,
+0x51,
+0x1b,
+0xe1,
+0xa9,
+0xed,
+0x60,
+0x32,
+0x3e,
+0xa9,
+0x50,
+0x28,
+0x53,
+0x06,
+0x59,
+0xe2,
+0xfc,
+0xe7,
+0x02,
+0x64,
+0x39,
+0x21,
+0x56,
+0x4a,
+0xa5,
+0x40,
+0x80,
+0x81,
+0xd5,
+0x5a,
+0x60,
+0x7b,
+0x68,
+0x84,
+0xf1,
+0xe0,
+0xb1,
+0xb6,
+0x5b,
+0xdf,
+0xa8,
+0x1d,
+0x6d,
+0x65,
+0x20,
+0xc0,
+0xa2,
+0xb9,
+0xd9,
+0xbb,
+0x00,
+0xa6,
+0xdb,
+0x8b,
+0x01,
+0x53,
+0x91,
+0xfe,
+0xc4,
+0x51,
+0x85,
+0xb0,
+0x96,
+0x7f,
+0xfd,
+0x51,
+0xdd,
+0x14,
+0x03,
+0x67,
+0x2e,
+0x75,
+0x1c,
+0x76,
+0xd3,
+0x6e,
+0xdd,
+0x99,
+0x55,
+0x76,
+0xe5,
+0xab,
+0x23,
+0xfc,
+0x4a,
+0xd5,
+0xc6,
+0xe8,
+0x2e,
+0xca,
+0x8a,
+0xb3,
+0xf6,
+0x8c,
+0x6c,
+0xb0,
+0xe9,
+0xf2,
+0xe7,
+0x9e,
+0x69,
+0x41,
+0xed,
+0xf1,
+0x6d,
+0xd2,
+0x86,
+0xd8,
+0x7e,
+0xcb,
+0x5d,
+0x47,
+0x6c,
+0x85,
+0x6a,
+0x23,
+0xed,
+0x20,
+0x40,
+0x93,
+0xb4,
+0x20,
+0xc7,
+0xa5,
+0xc9,
+0xaf,
+0x03,
+0x15,
+0xac,
+0x19,
+0xe5,
+0x2a,
+0x36,
+0xdf,
+0x6d,
+0xc5,
+0x8c,
+0x80,
+0x07,
+0xce,
+0x92,
+0x0c,
+0xd8,
+0x06,
+0x62,
+0x0f,
+0xdd,
+0x48,
+0x46,
+0x1a,
+0x53,
+0xc7,
+0x8a,
+0x8c,
+0x5d,
+0x5d,
+0xb4,
+0xa1,
+0x02,
+0xd3,
+0xa9,
+0xb8,
+0xf3,
+0x94,
+0x8f,
+0x3f,
+0xe5,
+0x54,
+0xd4,
+0x11,
+0x65,
+0xb2,
+0x5e,
+0x09,
+0x0b,
+0x81,
+0xe3,
+0x75,
+0xa7,
+0x89,
+0x81,
+0x39,
+0x6c,
+0x46,
+0xf6,
+0x06,
+0x9f,
+0x27,
+0x3b,
+0xb6,
+0x2d,
+0x5f,
+0x1d,
+0x4b,
+0xd4,
+0x7b,
+0x1d,
+0x61,
+0x74,
+0x89,
+0xe4,
+0xe3,
+0xbd,
+0x98,
+0x1b,
+0xc4,
+0x51,
+0x3b,
+0xa4,
+0xfa,
+0xe0,
+0x92,
+0xf7,
+0xbe,
+0xf2,
+0x4d,
+0xbb,
+0xff,
+0xad,
+0x4f,
+0x6d,
+0x68,
+0xc2,
+0x79,
+0x40,
+0xaa,
+0x9b,
+0x8f,
+0x0c,
+0x32,
+0x4b,
+0x5f,
+0x3e,
+0xab,
+0x59,
+0x98,
+0xb3,
+0xf5,
+0x1d,
+0xac,
+0x5e,
+0xbc,
+0x78,
+0xd3,
+0x01,
+0x6c,
+0x64,
+0x15,
+0x2f,
+0xd8,
+0x71,
+0xa6,
+0x2d,
+0x45,
+0xe1,
+0x22,
+0x42,
+0xe4,
+0x4e,
+0x04,
+0x3c,
+0x7d,
+0xf4,