aboutsummaryrefslogtreecommitdiff
path: root/drivers/sensors
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sensors')
-rw-r--r--drivers/sensors/adns5050.c193
-rw-r--r--drivers/sensors/adns5050.h79
-rw-r--r--drivers/sensors/adns9800.c219
-rw-r--r--drivers/sensors/adns9800.h35
-rw-r--r--drivers/sensors/adns9800_srom_A6.h3078
-rw-r--r--drivers/sensors/pimoroni_trackball.c140
-rw-r--r--drivers/sensors/pimoroni_trackball.h35
-rw-r--r--drivers/sensors/pmw3360.c237
-rw-r--r--drivers/sensors/pmw3360.h104
-rw-r--r--drivers/sensors/pmw3360_firmware.h300
10 files changed, 4420 insertions, 0 deletions
diff --git a/drivers/sensors/adns5050.c b/drivers/sensors/adns5050.c
new file mode 100644
index 000000000..e7273977d
--- /dev/null
+++ b/drivers/sensors/adns5050.c
@@ -0,0 +1,193 @@
1/* Copyright 2021 Colin Lam (Ploopy Corporation)
2 * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
3 * Copyright 2019 Sunjun Kim
4 * Copyright 2019 Hiroyuki Okada
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21#include "adns5050.h"
22#include "wait.h"
23#include "debug.h"
24#include "print.h"
25#include "gpio.h"
26
27#ifndef OPTIC_ROTATED
28# define OPTIC_ROTATED false
29#endif
30
31// Definitions for the ADNS serial line.
32#ifndef ADNS_SCLK_PIN
33# define ADNS_SCLK_PIN B7
34#endif
35
36#ifndef ADNS_SDIO_PIN
37# define ADNS_SDIO_PIN C6
38#endif
39
40#ifndef ADNS_CS_PIN
41# define ADNS_CS_PIN B4
42#endif
43
44#ifdef CONSOLE_ENABLE
45void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
46#endif
47
48// Initialize the ADNS serial pins.
49void adns_init(void) {
50 setPinOutput(ADNS_SCLK_PIN);
51 setPinOutput(ADNS_SDIO_PIN);
52 setPinOutput(ADNS_CS_PIN);
53}
54
55// Perform a synchronization with the ADNS.
56// Just as with the serial protocol, this is used by the slave to send a
57// synchronization signal to the master.
58void adns_sync(void) {
59 writePinLow(ADNS_CS_PIN);
60 wait_us(1);
61 writePinHigh(ADNS_CS_PIN);
62}
63
64void adns_cs_select(void) {
65 writePinLow(ADNS_CS_PIN);
66}
67
68void adns_cs_deselect(void) {
69 writePinHigh(ADNS_CS_PIN);
70}
71
72uint8_t adns_serial_read(void) {
73 setPinInput(ADNS_SDIO_PIN);
74 uint8_t byte = 0;
75
76 for (uint8_t i = 0; i < 8; ++i) {
77 writePinLow(ADNS_SCLK_PIN);
78 wait_us(1);
79
80 byte = (byte << 1) | readPin(ADNS_SDIO_PIN);
81
82 writePinHigh(ADNS_SCLK_PIN);
83 wait_us(1);
84 }
85
86 return byte;
87}
88
89void adns_serial_write(uint8_t data) {
90 setPinOutput(ADNS_SDIO_PIN);
91
92 for (int8_t b = 7; b >= 0; b--) {
93 writePinLow(ADNS_SCLK_PIN);
94
95 if (data & (1 << b))
96 writePinHigh(ADNS_SDIO_PIN);
97 else
98 writePinLow(ADNS_SDIO_PIN);
99
100 wait_us(2);
101
102 writePinHigh(ADNS_SCLK_PIN);
103 }
104
105 // tSWR. See page 15 of the ADNS spec sheet.
106 // Technically, this is only necessary if the next operation is an SDIO
107 // read. This is not guaranteed to be the case, but we're being lazy.
108 wait_us(4);
109
110 // Note that tSWW is never necessary. All write operations require at
111 // least 32us, which exceeds tSWW, so there's never a need to wait for it.
112}
113
114// Read a byte of data from a register on the ADNS.
115// Don't forget to use the register map (as defined in the header file).
116uint8_t adns_read_reg(uint8_t reg_addr) {
117 adns_cs_select();
118
119 adns_serial_write(reg_addr);
120
121 // We don't need a minimum tSRAD here. That's because a 4ms wait time is
122 // already included in adns_serial_write(), so we're good.
123 // See page 10 and 15 of the ADNS spec sheet.
124 //wait_us(4);
125
126 uint8_t byte = adns_serial_read();
127
128 // tSRW & tSRR. See page 15 of the ADNS spec sheet.
129 // Technically, this is only necessary if the next operation is an SDIO
130 // read or write. This is not guaranteed to be the case.
131 // Honestly, this wait could probably be removed.
132 wait_us(1);
133
134 adns_cs_deselect();
135
136 return byte;
137}
138
139void adns_write_reg(uint8_t reg_addr, uint8_t data) {
140 adns_cs_select();
141 adns_serial_write( 0b10000000 | reg_addr );
142 adns_serial_write(data);
143 adns_cs_deselect();
144}
145
146report_adns_t adns_read_burst(void) {
147 adns_cs_select();
148
149 report_adns_t data;
150 data.dx = 0;
151 data.dy = 0;
152
153 adns_serial_write(REG_MOTION_BURST);
154
155 // We don't need a minimum tSRAD here. That's because a 4ms wait time is
156 // already included in adns_serial_write(), so we're good.
157 // See page 10 and 15 of the ADNS spec sheet.
158 //wait_us(4);
159
160 uint8_t x = adns_serial_read();
161 uint8_t y = adns_serial_read();
162
163 // Burst mode returns a bunch of other shit that we don't really need.
164 // Setting CS to high ends burst mode early.
165 adns_cs_deselect();
166
167 data.dx = convert_twoscomp(x);
168 data.dy = convert_twoscomp(y);
169
170 return data;
171}
172
173// Convert a two's complement byte from an unsigned data type into a signed
174// data type.
175int8_t convert_twoscomp(uint8_t data) {
176 if ((data & 0x80) == 0x80)
177 return -128 + (data & 0x7F);
178 else
179 return data;
180}
181
182// Don't forget to use the definitions for CPI in the header file.
183void adns_set_cpi(uint8_t cpi) {
184 adns_write_reg(REG_MOUSE_CONTROL2, cpi);
185}
186
187bool adns_check_signature(void) {
188 uint8_t pid = adns_read_reg(REG_PRODUCT_ID);
189 uint8_t rid = adns_read_reg(REG_REVISION_ID);
190 uint8_t pid2 = adns_read_reg(REG_PRODUCT_ID2);
191
192 return (pid == 0x12 && rid == 0x01 && pid2 == 0x26);
193}
diff --git a/drivers/sensors/adns5050.h b/drivers/sensors/adns5050.h
new file mode 100644
index 000000000..ff8e8f78e
--- /dev/null
+++ b/drivers/sensors/adns5050.h
@@ -0,0 +1,79 @@
1/* Copyright 2021 Colin Lam (Ploopy Corporation)
2 * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
3 * Copyright 2019 Sunjun Kim
4 * Copyright 2019 Hiroyuki Okada
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include <stdbool.h>
23
24// Registers
25#define REG_PRODUCT_ID 0x00
26#define REG_REVISION_ID 0x01
27#define REG_MOTION 0x02
28#define REG_DELTA_X 0x03
29#define REG_DELTA_Y 0x04
30#define REG_SQUAL 0x05
31#define REG_SHUTTER_UPPER 0x06
32#define REG_SHUTTER_LOWER 0x07
33#define REG_MAXIMUM_PIXEL 0x08
34#define REG_PIXEL_SUM 0x09
35#define REG_MINIMUM_PIXEL 0x0a
36#define REG_PIXEL_GRAB 0x0b
37#define REG_MOUSE_CONTROL 0x0d
38#define REG_MOUSE_CONTROL2 0x19
39#define REG_LED_DC_MODE 0x22
40#define REG_CHIP_RESET 0x3a
41#define REG_PRODUCT_ID2 0x3e
42#define REG_INV_REV_ID 0x3f
43#define REG_MOTION_BURST 0x63
44
45// CPI values
46#define CPI125 0x11
47#define CPI250 0x12
48#define CPI375 0x13
49#define CPI500 0x14
50#define CPI625 0x15
51#define CPI750 0x16
52#define CPI875 0x17
53#define CPI1000 0x18
54#define CPI1125 0x19
55#define CPI1250 0x1a
56#define CPI1375 0x1b
57
58#ifdef CONSOLE_ENABLE
59void print_byte(uint8_t byte);
60#endif
61
62typedef struct {
63 int8_t dx;
64 int8_t dy;
65} report_adns_t;
66
67// A bunch of functions to implement the ADNS5050-specific serial protocol.
68// Note that the "serial.h" driver is insufficient, because it does not
69// manually manipulate a serial clock signal.
70void adns_init(void);
71void adns_sync(void);
72uint8_t adns_serial_read(void);
73void adns_serial_write(uint8_t data);
74uint8_t adns_read_reg(uint8_t reg_addr);
75void adns_write_reg(uint8_t reg_addr, uint8_t data);
76report_adns_t adns_read_burst(void);
77int8_t convert_twoscomp(uint8_t data);
78void adns_set_cpi(uint8_t cpi);
79bool adns_check_signature(void);
diff --git a/drivers/sensors/adns9800.c b/drivers/sensors/adns9800.c
new file mode 100644
index 000000000..36213179f
--- /dev/null
+++ b/drivers/sensors/adns9800.c
@@ -0,0 +1,219 @@
1/* Copyright 2020 Alexander Tulloh
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "spi_master.h"
18#include "quantum.h"
19#include "adns9800_srom_A6.h"
20#include "adns9800.h"
21
22// registers
23#define REG_Product_ID 0x00
24#define REG_Revision_ID 0x01
25#define REG_Motion 0x02
26#define REG_Delta_X_L 0x03
27#define REG_Delta_X_H 0x04
28#define REG_Delta_Y_L 0x05
29#define REG_Delta_Y_H 0x06
30#define REG_SQUAL 0x07
31#define REG_Pixel_Sum 0x08
32#define REG_Maximum_Pixel 0x09
33#define REG_Minimum_Pixel 0x0a
34#define REG_Shutter_Lower 0x0b
35#define REG_Shutter_Upper 0x0c
36#define REG_Frame_Period_Lower 0x0d
37#define REG_Frame_Period_Upper 0x0e
38#define REG_Configuration_I 0x0f
39#define REG_Configuration_II 0x10
40#define REG_Frame_Capture 0x12
41#define REG_SROM_Enable 0x13
42#define REG_Run_Downshift 0x14
43#define REG_Rest1_Rate 0x15
44#define REG_Rest1_Downshift 0x16
45#define REG_Rest2_Rate 0x17
46#define REG_Rest2_Downshift 0x18
47#define REG_Rest3_Rate 0x19
48#define REG_Frame_Period_Max_Bound_Lower 0x1a
49#define REG_Frame_Period_Max_Bound_Upper 0x1b
50#define REG_Frame_Period_Min_Bound_Lower 0x1c
51#define REG_Frame_Period_Min_Bound_Upper 0x1d
52#define REG_Shutter_Max_Bound_Lower 0x1e
53#define REG_Shutter_Max_Bound_Upper 0x1f
54#define REG_LASER_CTRL0 0x20
55#define REG_Observation 0x24
56#define REG_Data_Out_Lower 0x25
57#define REG_Data_Out_Upper 0x26
58#define REG_SROM_ID 0x2a
59#define REG_Lift_Detection_Thr 0x2e
60#define REG_Configuration_V 0x2f
61#define REG_Configuration_IV 0x39
62#define REG_Power_Up_Reset 0x3a
63#define REG_Shutdown 0x3b
64#define REG_Inverse_Product_ID 0x3f
65#define REG_Motion_Burst 0x50
66#define REG_SROM_Load_Burst 0x62
67#define REG_Pixel_Burst 0x64
68
69#define ADNS_CLOCK_SPEED 2000000
70#define MIN_CPI 200
71#define MAX_CPI 8200
72#define CPI_STEP 200
73#define CLAMP_CPI(value) value < MIN_CPI ? MIN_CPI : value > MAX_CPI ? MAX_CPI : value
74#define SPI_MODE 3
75#define SPI_DIVISOR (F_CPU / ADNS_CLOCK_SPEED)
76#define US_BETWEEN_WRITES 120
77#define US_BETWEEN_READS 20
78#define US_BEFORE_MOTION 100
79#define MSB1 0x80
80
81extern const uint16_t adns_firmware_length;
82extern const uint8_t adns_firmware_data[];
83
84void adns_spi_start(void){
85 spi_start(SPI_SS_PIN, false, SPI_MODE, SPI_DIVISOR);
86}
87
88void adns_write(uint8_t reg_addr, uint8_t data){
89
90 adns_spi_start();
91 spi_write(reg_addr | MSB1);
92 spi_write(data);
93 spi_stop();
94 wait_us(US_BETWEEN_WRITES);
95}
96
97uint8_t adns_read(uint8_t reg_addr){
98
99 adns_spi_start();
100 spi_write(reg_addr & 0x7f );
101 uint8_t data = spi_read();
102 spi_stop();
103 wait_us(US_BETWEEN_READS);
104
105 return data;
106}
107
108void adns_init() {
109
110 setPinOutput(SPI_SS_PIN);
111
112 spi_init();
113
114 // reboot
115 adns_write(REG_Power_Up_Reset, 0x5a);
116 wait_ms(50);
117
118 // read registers and discard
119 adns_read(REG_Motion);
120 adns_read(REG_Delta_X_L);
121 adns_read(REG_Delta_X_H);
122 adns_read(REG_Delta_Y_L);
123 adns_read(REG_Delta_Y_H);
124
125 // upload firmware
126
127 // 3k firmware mode
128 adns_write(REG_Configuration_IV, 0x02);
129
130 // enable initialisation
131 adns_write(REG_SROM_Enable, 0x1d);
132
133 // wait a frame
134 wait_ms(10);
135
136 // start SROM download
137 adns_write(REG_SROM_Enable, 0x18);
138
139 // write the SROM file
140
141 adns_spi_start();
142
143 spi_write(REG_SROM_Load_Burst | 0x80);
144 wait_us(15);
145
146 // send all bytes of the firmware
147 unsigned char c;
148 for(int i = 0; i < adns_firmware_length; i++){
149 c = (unsigned char)pgm_read_byte(adns_firmware_data + i);
150 spi_write(c);
151 wait_us(15);
152 }
153
154 spi_stop();
155
156 wait_ms(10);
157
158 // enable laser
159 uint8_t laser_ctrl0 = adns_read(REG_LASER_CTRL0);
160 adns_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
161}
162
163config_adns_t adns_get_config(void) {
164 uint8_t config_1 = adns_read(REG_Configuration_I);
165 return (config_adns_t){ (config_1 & 0xFF) * CPI_STEP };
166}
167
168void adns_set_config(config_adns_t config) {
169 uint8_t config_1 = (CLAMP_CPI(config.cpi) / CPI_STEP) & 0xFF;
170 adns_write(REG_Configuration_I, config_1);
171}
172
173static int16_t convertDeltaToInt(uint8_t high, uint8_t low){
174
175 // join bytes into twos compliment
176 uint16_t twos_comp = (high << 8) | low;
177
178 // convert twos comp to int
179 if (twos_comp & 0x8000)
180 return -1 * (~twos_comp + 1);
181
182 return twos_comp;
183}
184
185report_adns_t adns_get_report(void) {
186
187 report_adns_t report = {0, 0};
188
189 adns_spi_start();
190
191 // start burst mode
192 spi_write(REG_Motion_Burst & 0x7f);
193
194 wait_us(US_BEFORE_MOTION);
195
196 uint8_t motion = spi_read();
197
198 if(motion & 0x80) {
199
200 // clear observation register
201 spi_read();
202
203 // delta registers
204 uint8_t delta_x_l = spi_read();
205 uint8_t delta_x_h = spi_read();
206 uint8_t delta_y_l = spi_read();
207 uint8_t delta_y_h = spi_read();
208
209 report.x = convertDeltaToInt(delta_x_h, delta_x_l);
210 report.y = convertDeltaToInt(delta_y_h, delta_y_l);
211 }
212
213 // clear residual motion
214 spi_write(REG_Motion & 0x7f);
215
216 spi_stop();
217
218 return report;
219}
diff --git a/drivers/sensors/adns9800.h b/drivers/sensors/adns9800.h
new file mode 100644
index 000000000..2f50b8f1b
--- /dev/null
+++ b/drivers/sensors/adns9800.h
@@ -0,0 +1,35 @@
1/* Copyright 2020 Alexander Tulloh
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include <stdint.h>
20
21typedef struct {
22 /* 200 - 8200 CPI supported */
23 uint16_t cpi;
24} config_adns_t;
25
26typedef struct {
27 int16_t x;
28 int16_t y;
29} report_adns_t;
30
31void adns_init(void);
32config_adns_t adns_get_config(void);
33void adns_set_config(config_adns_t);
34/* Reads and clears the current delta values on the ADNS sensor */
35report_adns_t adns_get_report(void);
diff --git a/drivers/sensors/adns9800_srom_A6.h b/drivers/sensors/adns9800_srom_A6.h
new file mode 100644
index 000000000..f5b3abeb6
--- /dev/null
+++ b/drivers/sensors/adns9800_srom_A6.h
@@ -0,0 +1,3078 @@
1#pragma once
2
3#include "progmem.h"
4
5const uint16_t adns_firmware_length = 3070;
6
7const uint8_t adns_firmware_data[] PROGMEM = {
80x03,
90xa6,
100x68,
110x1e,
120x7d,
130x10,
140x7e,
150x7e,
160x5f,
170x1c,
180xb8,
190xf2,
200x47,
210x0c,
220x7b,
230x74,
240x4b,
250x14,
260x8b,
270x75,
280x66,
290x51,
300x0b,
310x8c,
320x76,
330x74,
340x4b,
350x14,
360xaa,
370xd6,
380x0f,
390x9c,
400xba,
410xf6,
420x6e,
430x3f,
440xdd,
450x38,
460xd5,
470x02,
480x80,
490x9b,
500x82,
510x6d,
520x58,
530x13,
540xa4,
550xab,
560xb5,
570xc9,
580x10,
590xa2,
600xc6,
610x0a,
620x7f,
630x5d,
640x19,
650x91,
660xa0,
670xa3,
680xce,
690xeb,
700x3e,
710xc9,
720xf1,
730x60,
740x42,
750xe7,
760x4c,
770xfb,
780x74,
790x6a,
800x56,
810x2e,
820xbf,
830xdd,
840x38,
850xd3,
860x05,
870x88,
880x92,
890xa6,
900xce,
910xff,
920x5d,
930x38,
940xd1,
950xcf,
960xef,
970x58,
980xcb,
990x65,
1000x48,
1010xf0,
1020x35,
1030x85,
1040xa9,
1050xb2,
1060x8f,
1070x5e,
1080xf3,
1090x80,
1100x94,
1110x97,
1120x7e,
1130x75,
1140x97,
1150x87,
1160x73,
1170x13,
1180xb0,
1190x8a,
1200x69,
1210xd4,
1220x0a,
1230xde,
1240xc1,
1250x79,
1260x59,
1270x36,
1280xdb,
1290x9d,
1300xd6,
1310xb8,
1320x15,
1330x6f,
1340xce,
1350x3c,
1360x72,
1370x32,
1380x45,
1390x88,
1400xdf,
1410x6c,
1420xa5,
1430x6d,
1440xe8,
1450x76,
1460x96,
1470x14,
1480x74,
1490x20,
1500xdc,
1510xf4,
1520xfa,
1530x37,
1540x6a,
1550x27,
1560x32,
1570xe3,
1580x29,
1590xbf,
1600xc4,
1610xc7,
1620x06,
1630x9d,
1640x58,
1650xe7,
1660x87,
1670x7c,
1680x2e,
1690x9f,
1700x6e,
1710x49,
1720x07,
1730x5d,
1740x23,
1750x64,
1760x54,
1770x83,
1780x6e,
1790xcb,
1800xb7,
1810x77,
1820xf7,
1830x2b,
1840x6e,
1850x0f,
1860x2e,
1870x66,
1880x12,
1890x60,
1900x55,
1910x65,
1920xfc,
1930x43,
1940xb3,
1950x58,
1960x73,
1970x5b,
1980xe8,
1990x67,
2000x04,
2010x43,
2020x02,
2030xde,
2040xb3,
2050x89,
2060xa0,
2070x6d,
2080x3a,
2090x27,
2100x79,
2110x64,
2120x5b,
2130x0c,
2140x16,
2150x9e,
2160x66,
2170xb1,
2180x8b,
2190x87,
2200x0c,
2210x5d,
2220xf2,
2230xb6,
2240x3d,
2250x71,
2260xdf,
2270x42,
2280x03,
2290x8a,
2300x06,
2310x8d,
2320xef,
2330x1d,
2340xa8,
2350x96,
2360x5c,
2370xed,
2380x31,
2390x61,
2400x5c,
2410xa1,
2420x34,
2430xf6,
2440x8c,
2450x08,
2460x60,
2470x33,
2480x07,
2490x00,
2500x3e,
2510x79,
2520x95,
2530x1b,
2540x43,
2550x7f,
2560xfe,
2570xb6,
2580xa6,
2590xd4,
2600x9d,
2610x76,
2620x72,
2630xbf,
2640xad,
2650xc0,
2660x15,
2670xe8,
2680x37,
2690x31,
2700xa3,
2710x72,
2720x63,
2730x52,
2740x1d,
2750x1c,
2760x5d,
2770x51,
2780x1b,
2790xe1,
2800xa9,
2810xed,
2820x60,
2830x32,
2840x3e,
2850xa9,
2860x50,
2870x28,
2880x53,
2890x06,
2900x59,
2910xe2,
2920xfc,
2930xe7,
2940x02,
2950x64,
2960x39,
2970x21,
2980x56,
2990x4a,
3000xa5,
3010x40,
3020x80,
3030x81,
3040xd5,
3050x5a,
3060x60,
3070x7b,
3080x68,
3090x84,
3100xf1,
3110xe0,
3120xb1,
3130xb6,
3140x5b,
3150xdf,
3160xa8,
3170x1d,
3180x6d,
3190x65,
3200x20,
3210xc0,
3220xa2,
3230xb9,
3240xd9,
3250xbb,
3260x00,
3270xa6,
3280xdb,
3290x8b,
3300x01,
3310x53,
3320x91,
3330xfe,
3340xc4,
3350x51,
3360x85,
3370xb0,
3380x96,
3390x7f,
3400xfd,
3410x51,
3420xdd,
3430x14,
3440x03,
3450x67,
3460x2e,
3470x75,
3480x1c,
3490x76,
3500xd3,
3510x6e,
3520xdd,
3530x99,
3540x55,
3550x76,
3560xe5,
3570xab,
3580x23,
3590xfc,
3600x4a,
3610xd5,
3620xc6,
3630xe8,
3640x2e,
3650xca,
3660x8a,
3670xb3,
3680xf6,
3690x8c,
3700x6c,
3710xb0,
3720xe9,
3730xf2,
3740xe7,
3750x9e,
3760x69,
3770x41,
3780xed,
3790xf1,
3800x6d,
3810xd2,
3820x86,
3830xd8,
3840x7e,
3850xcb,
3860x5d,
3870x47,
3880x6c,
3890x85,
3900x6a,
3910x23,
3920xed,
3930x20,
3940x40,
3950x93,
3960xb4,
3970x20,
3980xc7,
3990xa5,
4000xc9,
4010xaf,
4020x03,
4030x15,
4040xac,
4050x19,
4060xe5,
4070x2a,
4080x36,
4090xdf,
4100x6d,
4110xc5,
4120x8c,
4130x80,
4140x07,
4150xce,
4160x92,
4170x0c,
4180xd8,
4190x06,
4200x62,
4210x0f,
4220xdd,
4230x48,
4240x46,
4250x1a,
4260x53,
4270xc7,
4280x8a,
4290x8c,
4300x5d,
4310x5d,
4320xb4,
4330xa1,
4340x02,
4350xd3,
4360xa9,
4370xb8,
4380xf3,
4390x94,
4400x8f,
4410x3f,
4420xe5,
4430x54,
4440xd4,
4450x11,
4460x65,
4470xb2,
4480x5e,
4490x09,
4500x0b,
4510x81,
4520xe3,
4530x75,
4540xa7,
4550x89,
4560x81,
4570x39,
4580x6c,
4590x46,
4600xf6,
4610x06,
4620x9f,
4630x27,
4640x3b,
4650xb6,
4660x2d,
4670x5f,
4680x1d,
4690x4b,
4700xd4,
4710x7b,
4720x1d,
4730x61,
4740x74,
4750x89,
4760xe4,
4770xe3,
4780xbd,
4790x98,
4800x1b,
4810xc4,
4820x51,
4830x3b,
4840xa4,
4850xfa,
4860xe0,
4870x92,
4880xf7,
4890xbe,
4900xf2,
4910x4d,
4920xbb,
4930xff,
4940xad,
4950x4f,
4960x6d,
4970x68,
4980xc2,
4990x79,
5000x40,
5010xaa,
5020x9b,
5030x8f,
5040x0c,
5050x32,
5060x4b,
5070x5f,
5080x3e,
5090xab,
5100x59,
5110x98,
5120xb3,
5130xf5,
5140x1d,
5150xac,
5160x5e,
5170xbc,
5180x78,
5190xd3,
5200x01,
5210x6c,
5220x64,
5230x15,
5240x2f,
5250xd8,
5260x71,
5270xa6,
5280x2d,
5290x45,
5300xe1,
5310x22,
5320x42,
5330xe4,
5340x4e,
5350x04,
5360x3c,
5370x7d,
5380xf4,
5390x40,
5400x21,
5410xb4,
5420x67,
5430x05,
5440xa8,
5450xe2,
5460xf3,
5470x72,
5480x87,
5490x4c,
5500x7d,
5510xd9,
5520x1b,
5530x65,
5540x97,
5550xf3,
5560xc2,
5570xe3,
5580xe4,
5590xc8,
5600xd2,
5610xde,
5620xf6,
5630xef,
5640xdc,
5650xbb,
5660x44,
5670x08,
5680x5e,
5690xe2,
5700x45,
5710x27,
5720x01,
5730xb0,
5740xf6,
5750x43,
5760xe7,
5770x3a,
5780xf6,
5790xdc,
5800x9d,
5810xed,
5820xf3,
5830xc5,
5840x0c,
5850xb8,
5860x9c,
5870x98,
5880x3a,
5890xd8,
5900x36,
5910xee,
5920x96,
5930x72,
5940x67,
5950xe7,
5960x81,
5970x91,
5980xd5,
5990x05,
6000x0a,
6010xe0,
6020x82,
6030xd5,
6040x8f,
6050xe8,
6060xf9,
6070xb0,
6080xc9,
6090xcf,
6100x93,
6110xe7,
6120x04,
6130xc5,
6140xbc,
6150x2b,
6160x43,
6170x56,
6180x7e,
6190xe8,
6200x67,
6210x7c,
6220xe5,
6230xfb,
6240x49,
6250xad,
6260x5e,
6270x9f,
6280x25,
6290x13,
6300xde,
6310x6e,
6320x6e,
6330xe9,
6340xf1,
6350xec,
6360x87,
6370x0b,
6380x59,
6390x81,
6400x76,
6410x84,
6420x76,
6430xb3,
6440x24,
6450xaf,
6460x30,
6470xfd,
6480x27,
6490x8b,
6500xab,
6510xd8,
6520x00,
6530x8b,
6540x9b,
6550x0c,
6560xd2,
6570xb2,
6580x4e,
6590x5e,
6600x9d,
6610x1d,
6620x96,
6630x01,
6640x00,
6650x67,
6660xc1,
6670x5f,
6680x02,
6690x20,
6700xfd,
6710x45,
6720x6a,
6730x01,
6740x60,
6750x58,
6760x45,
6770xca,
6780x47,
6790x21,
6800x90,
6810x5a,
6820xc4,
6830x43,
6840x26,
6850x1a,
6860xd7,
6870xa5,
6880x4a,
6890xb2,
6900x5d,
6910x2b,
6920x35,
6930x49,
6940xfb,
6950xa5,
6960x17,
6970x92,
6980x21,
6990x1e,
7000x93,
7010x96,
7020x67,
7030xa2,
7040x7e,
7050x36,
7060x7a,
7070xde,
7080x5f,
7090xbe,
7100x7a,
7110x58,
7120x9d,
7130xf8,
7140x78,
7150xa3,
7160xfa,
7170xc8,
7180xd5,
7190x17,
7200xf0,
7210x21,
7220x97,
7230x8c,
7240x80,
7250xb5,
7260x4b,
7270x3b,
7280xbd,
7290xbb,
7300x41,
7310x21,
7320xa8,
7330x50,
7340x67,
7350xf7,
7360xe7,
7370x19,
7380x80,
7390x10,
7400x8e,
7410xce,
7420x04,
7430x18,
7440x3f,
7450x51,
7460x6b,
7470x77,
7480xd8,
7490x9e,
7500x16,
7510xaf,
7520xec,
7530xef,
7540x48,
7550x16,
7560x4d,
7570x9e,
7580x85,
7590x38,
7600x18,
7610x3e,
7620xd4,
7630x28,
7640x87,
7650x60,
7660x2a,
7670xf6,
7680x7f,
7690x09,
7700x86,
7710x6f,
7720x9c,
7730x3c,
7740x3a,
7750xff,
7760xab,
7770xd0,
7780x61,
7790xa2,
7800x97,
7810x0d,
7820x71,
7830x94,
7840x7e,
7850xfd,
7860xb9,
7870x80,
7880x02,
7890x89,
7900x6a,
7910xb3,
7920x84,
7930x6c,
7940x2a,
7950x77,
7960x62,
7970xbe,
7980x0b,
7990xf4,
8000xaf,
8010xac,
8020x7b,
8030x7c,
8040x8e,
8050xca,
8060x01,
8070xba,
8080x71,
8090x78,
8100x94,
8110xfd,
8120xb5,
8130x39,
8140xa4,
8150x4d,
8160x2f,
8170x78,
8180xcf,
8190xca,
8200x92,
8210x0c,
8220x1a,
8230x99,
8240x48,
8250x4c,
8260x11,
8270x96,
8280xb5,
8290x4e,
8300x41,
8310x28,
8320xe4,
8330xa6,
8340xfe,
8350x4b,
8360x72,
8370x91,
8380xe7,
8390xd4,
8400xdd,
8410x9f,
8420x12,
8430xe6,
8440x29,
8450x38,
8460xce,
8470x45,
8480xae,
8490x02,
8500xb8,
8510x24,
8520xae,
8530xbd,
8540xe9,
8550x66,
8560x08,
8570x62,
8580xa2,
8590x2c,
8600x2b,
8610x00,
8620xe2,
8630x23,
8640xd9,
8650xc4,
8660x48,
8670xe4,
8680xd3,
8690xac,
8700xbb,
8710x34,
8720xc7,
8730xf0,
8740xe3,
8750x4f,
8760xb9,
8770x30,
8780xea,
8790xa2,
8800x12,
8810xf1,
8820x30,
8830x2c,
8840x36,
8850xde,
8860x48,
8870xf2,
8880xb0,
8890x4c,
8900x43,
8910x3f,
8920x2e,
8930x58,
8940xe4,
8950x20,
8960xe3,
8970x58,
8980xcd,
8990x31,
9000x22,
9010xf0,
9020xa2,
9030x2a,
9040xe6,
9050x19,
9060x90,
9070x55,
9080x86,
9090xf6,
9100x55,
9110x79,
9120xd1,
9130xd7,
9140x46,
9150x2f,
9160xc0,
9170xdc,
9180x99,
9190xe8,
9200xf3,
9210x6a,
9220xdf,
9230x7f,
9240xeb,
9250x24,
9260x4a,
9270x1e,
9280x5a,
9290x75,
9300xde,
9310x2f,
9320x5c,
9330x19,
9340x61,
9350x03,
9360x53,
9370x54,
9380x6a,
9390x3b,
9400x18,
9410x70,
9420xb6,
9430x4f,
9440xf1,
9450x9c,
9460x0a,
9470x59,
9480x9d,
9490x19,
9500x92,
9510x65,
9520x8c,
9530x83,
9540x14,
9550x2d,
9560x44,
9570x8a,
9580x75,
9590xa9,
9600xf5,
9610x90,
9620xd2,
9630x66,
9640x4e,
9650xfa,
9660x69,
9670x0f,
9680x5b,
9690x0b,
9700x98,
9710x65,
9720xc8,
9730x11,
9740x42,
9750x59,
9760x7f,
9770xdd,
9780x1b,
9790x75,
9800x17,
9810x31,
9820x4c,
9830x75,
9840x58,
9850xeb,
9860x58,
9870x63,
9880x7d,
9890xf2,
9900xa6,
9910xc2,
9920x6e,
9930xb7,
9940x3f,
9950x3e,
9960x5e,
9970x47,
9980xad,
9990xb7,
10000x04,
10010xe8,
10020x05,
10030xf8,
10040xb2,
10050xcf,
10060x19,
10070xf3,
10080xd2,
10090x85,
10100xfe,
10110x3e,
10120x3e,
10130xb1,
10140x62,
10150x08,
10160x2c,
10170x10,
10180x07,
10190x0d,
10200x73,
10210x90,
10220x17,
10230xfa,
10240x9b,
10250x56,
10260x02,
10270x75,
10280xf9,
10290x51,
10300xe0,
10310xe9,
10320x1a,
10330x7b,
10340x9f,
10350xb3,
10360xf3,
10370x98,
10380xb8,
10390x1c,
10400x9c,
10410xe1,
10420xd5,
10430x35,
10440xae,
10450xc8,
10460x60,
10470x48,
10480x11,
10490x09,
10500x94,
10510x6b,
10520xd0,
10530x8b,
10540x15,
10550xbc,
10560x05,
10570x68,
10580xd3,
10590x54,
10600x8a,
10610x51,
10620x39,
10630x5c,
10640x42,
10650x76,
10660xce,
10670xd8,
10680xad,
10690x89,
10700x30,
10710xc9,
10720x05,
10730x1c,
10740xcc,
10750x94,
10760x3f,
10770x0f,
10780x90,
10790x6f,
10800x72,
10810x2d,
10820x85,
10830x64,
10840x9a,
10850xb9,
10860x23,
10870xf9,
10880x0b,
10890xc3,
10900x7c,
10910x39,
10920x0f,
10930x97,
10940x07,
10950x97,
10960xda,
10970x58,
10980x48,
10990x33,
11000x05,
11010x23,
11020xb8,
11030x82,
11040xe8,
11050xd3,
11060x53,
11070x89,
11080xaf,
11090x33,
11100x80,
11110x22,
11120x84,
11130x0c,
11140x95,
11150x5c,
11160x67,
11170xb8,
11180x77,
11190x0c,
11200x5c,
11210xa2,
11220x5f,
11230x3d,
11240x58,
11250x0f,
11260x27,
11270xf3,
11280x2f,
11290xae,
11300x48,
11310xbd,
11320x0b,
11330x6f,
11340x54,
11350xfb,
11360x67,
11370x4c,
11380xea,
11390x32,
11400x27,
11410xf1,
11420xfa,
11430xe2,
11440xb0,
11450xec,
11460x0b,
11470x15,
11480xb4,
11490x70,
11500xf6,
11510x5c,
11520xdd,
11530x71,
11540x60,
11550xc3,
11560xc1,
11570xa8,
11580x32,
11590x65,
11600xac,
11610x7a,
11620x77,
11630x41,
11640xe5,
11650xa9,
11660x6b,
11670x11,
11680x81,
11690xfa,
11700x34,
11710x8d,
11720xfb,
11730xc1,
11740x80,
11750x6e,
11760xc4,
11770x60,
11780x30,
11790x07,
11800xd4,
11810x8b,
11820x67,
11830xbd,
11840xaa,
11850x8c,
11860x9c,
11870x64,
11880xac,
11890xdb,
11900x0b,
11910x24,
11920x8b,
11930x63,
11940x6f,
11950xe6,
11960xbc,
11970xe7,
11980x33,
11990xa4,
12000x4a,
12010x4c,
12020xa7,
12030x9f,
12040x43,
12050x53,
12060xd2,
12070xbb,
12080x8f,
12090x43,
12100xc7,
12110x3d,
12120x78,
12130x68,
12140x3f,
12150xa5,
12160x3d,
12170xca,
12180x69,
12190x84,
12200xa6,
12210x97,
12220x2d,
12230xc0,
12240x7d,
12250x31,
12260x34,
12270x55,
12280x1d,
12290x07,
12300xb1,
12310x5f,
12320x40,
12330x5c,
12340x93,
12350xb0,
12360xbc,
12370x7c,
12380xb0,
12390xbc,
12400xe7,
12410x12,
12420xee,
12430x6b,
12440x2b,
12450xd3,
12460x4d,
12470x67,
12480x70,
12490x3a,
12500x9a,
12510xf2,
12520x3c,
12530x7c,
12540x81,
12550xfa,
12560xd7,
12570xd9,
12580x90,
12590x91,
12600x81,
12610xb8,
12620xb1,
12630xf3,
12640x48,
12650x6a,
12660x26,
12670x4f,
12680x0c,
12690xce,
12700xb0,
12710x9e,
12720xfd,
12730x4a,
12740x3a,
12750xaf,
12760xac,
12770x5b,
12780x3f,
12790xbf,
12800x44,
12810x5a,
12820xa3,
12830x19,
12840x1e,
12850x4b,
12860xe7,
12870x36,
12880x6a,
12890xd7,
12900x20,
12910xae,
12920xd7,
12930x7d,
12940x3b,
12950xe7,
12960xff,
12970x3a,
12980x86,
12990x2e,
13000xd0,
13010x4a,
13020x3e,
13030xaf,
13040x9f,
13050x8e,
13060x01,
13070xbf,
13080xf8,
13090x4f,
13100xc1,
13110xe8,
13120x6f,
13130x74,
13140xe1,
13150x45,
13160xd3,
13170xf7,
13180x04,
13190x6a,
13200x4b,
13210x9d,
13220xec,
13230x33,
13240x27,
13250x76,
13260xd7,
13270xc5,
13280xe1,
13290xb0,
13300x3b,
13310x0e,
13320x23,
13330xec,
13340xf0,
13350x86,
13360xd2,
13370x1a,
13380xbf,
13390x3d,
13400x04,
13410x62,
13420xb3,
13430x6c,
13440xb2,
13450xeb,
13460x17,
13470x05,
13480xa6,
13490x0a,
13500x8a,
13510x7e,
13520x83,
13530x1c,
13540xb6,
13550x37,
13560x09,
13570xc6,
13580x0b,
13590x70,
13600x3c,
13610xb5,
13620x93,
13630x81,
13640xd8,
13650x93,
13660xa0,
13670x5f,
13680x1e,
13690x08,
13700xe2,
13710xc6,
13720xe5,
13730xc9,
13740x72,
13750xf1,
13760xf1,
13770xc1,
13780xed,
13790xd5,
13800x58,
13810x93,
13820x83,
13830xf8,
13840x65,
13850x67,
13860x2e,
13870x0d,
13880xa9,
13890xf1,
13900x64,
13910x12,
13920xe6,
13930x4c,
13940xea,
13950x15,
13960x3f,
13970x8c,
13980x1a,
13990xb6,
14000xbf,
14010xf6,
14020xb9,
14030x52,
14040x35,
14050x09,
14060xb0,
14070xe6,
14080xf7,
14090xcd,
14100xf1,
14110xa5,
14120xaa,
14130x81,
14140xd1,
14150x81,
14160x6f,
14170xb4,
14180xa9,
14190x66,
14200x1f,
14210xfc,
14220x48,
14230xc0,
14240xb6,
14250xd1,
14260x8b,
14270x06,
14280x2f,
14290xf6,
14300xef,
14310x1f,
14320x0a,
14330xe6,
14340xce,
14350x3a,
14360x4a,
14370x55,
14380xbf,
14390x6d,
14400xf9,
14410x4d,
14420xd4,
14430x08,
14440x45,
14450x4b,
14460xc3,
14470x66,
14480x19,
14490x92,
14500x10,
14510xe1,
14520x17,
14530x8e,
14540x28,
14550x91,
14560x16,
14570xbf,
14580x3c,
14590xee,
14600xa3,
14610xa6,
14620x99,
14630x92,
14640x10,
14650xe1,
14660xf6,
14670xcc,
14680xac,
14690xb8,
14700x65,
14710x0b,
14720x43,
14730x66,
14740xf8,
14750xe3,
14760xe5,
14770x3f,
14780x24,
14790x89,
14800x47,
14810x5d,
14820x78,
14830x43,
14840xd0,
14850x61,
14860x17,
14870xbd,
14880x5b,
14890x64,
14900x54,
14910x08,
14920x45,
14930x59,
14940x93,
14950xf6,
14960x95,
14970x8a,
14980x41,
14990x51,
15000x62,
15010x4b,
15020x51,
15030x02,
15040x30,
15050x73,
15060xc7,
15070x87,
15080xc5,
15090x4b,
15100xa2,
15110x97,
15120x0f,
15130xe8,
15140x46,
15150x5f,
15160x7e,
15170x2a,
15180xe1,
15190x30,
15200x20,
15210xb0,
15220xfa,
15230xe7,
15240xce,
15250x61,
15260x42,
15270x57,
15280x6e,
15290x21,
15300xf3,
15310x7a,
15320xec,
15330xe3,
15340x25,
15350xc7,
15360x25,
15370xf3,
15380x67,
15390xa7,
15400x57,
15410x40,
15420x00,
15430x02,
15440xcf,
15450x1c,
15460x80,
15470x77,
15480x67,
15490xbd,
15500x70,
15510xa1,
15520x19,
15530x92,
15540x31,
15550x75,
15560x93,
15570x27,
15580x27,
15590xb6,
15600x82,
15610xe4,
15620xeb,
15630x1d,
15640x78,
15650x48,
15660xe7,
15670xa5,
15680x5e,
15690x57,
15700xef,
15710x64,
15720x28,
15730x64,
15740x1b,
15750xf6,
15760x11,
15770xb2,
15780x03,
15790x9d,
15800xb9,
15810x18,
15820x02,
15830x27,
15840xf7,
15850xbe,
15860x9d,
15870x55,
15880xfc,
15890x00,
15900xd2,
15910xc7,
15920xae,
15930xad,
15940x0b,
15950xc5,
15960xe9,
15970x42,
15980x41,
15990x48,
16000xd8,
16010x32,
16020xcf,
16030xf6,
16040x0f,
16050xf5,
16060xbc,
16070x97,
16080xc6,
16090x99,
16100x47,
16110x76,
16120xbd,
16130x89,
16140x06,
16150x0f,
16160x63,
16170x0c,
16180x51,
16190xd4,
16200x5e,
16210xea,
16220x48,
16230xa8,
16240xa2,
16250x56,
16260x1c,
16270x79,
16280x84,
16290x86,
16300x40,
16310x88,
16320x41,
16330x76,
16340x55,
16350xfc,
16360xc2,
16370xd7,
16380xfd,
16390xc9,
16400xc7,
16410x80,
16420x61,
16430x35,
16440xa7,
16450x43,
16460x20,
16470xf7,
16480xeb,
16490x6c,
16500x66,
16510x13,
16520xb0,
16530xec,
16540x02,
16550x75,
16560x3e,
16570x4b,
16580xaf,
16590xb9,
16600x5d,
16610x40,
16620xda,
16630xd6,
16640x6e,
16650x2d,
16660x39,
16670x54,
16680xc2,
16690x95,
16700x35,
16710x54,
16720x25,
16730x72,
16740xe1,
16750x78,
16760xb8,
16770xeb,
16780xc1,
16790x16,
16800x58,
16810x0f,
16820x9c,
16830x9b,
16840xb4,
16850xea,
16860x37,
16870xec,
16880x3b,
16890x11,
16900xba,
16910xd5,
16920x8a,
16930xa9,
16940xe3,
16950x98,
16960x00,
16970x51,
16980x1c,
16990x14,
17000xe0,
17010x40,
17020x96,
17030xe5,
17040xe9,
17050xf2,
17060x21,
17070x22,
17080xb1,
17090x23,
17100x60,
17110x78,
17120xd3,
17130x17,
17140xf8,
17150x7a,
17160xa5,
17170xa8,
17180xba,
17190x20,
17200xd3,
17210x15,
17220x1e,
17230x32,
17240xe4,
17250x5e,
17260x15,
17270x48,
17280xae,
17290xa9,
17300xe5,
17310xb8,
17320x33,
17330xec,
17340xe8,
17350xa2,
17360x42,
17370xac,
17380xbf,
17390x10,
17400x84,
17410x53,
17420x87,
17430x19,
17440xb4,
17450x5f,
17460x76,
17470x4d,
17480x01,
17490x9d,
17500x56,
17510x74,
17520xd9,
17530x5c,
17540x97,
17550xe7,
17560x88,
17570xea,
17580x3a,
17590xbf,
17600xdc,
17610x4c,
17620x33,
17630x8a,
17640x16,
17650xb9,
17660x5b,
17670xfa,
17680xd8,
17690x42,
17700xa7,
17710xbb,
17720x3c,
17730x04,
17740x27,
17750x78,
17760x49,
17770x81,
17780x2a,
17790x5a,
17800x7d,
17810x7c,
17820x23,
17830xa8,
17840xba,
17850xf7,
17860x9a,
17870x9f,
17880xd2,
17890x66,
17900x3e,
17910x38,
17920x3c,
17930x75,
17940xf9,
17950xd1,
17960x30,
17970x26,
17980x30,
17990x6e,
18000x5a,
18010x6e,
18020xdc,
18030x6a,
18040x69,
18050x32,
18060x50,
18070x33,
18080x47,
18090x9e,
18100xa4,
18110xa8,
18120x64,
18130x66,
18140xf0,
18150x8a,
18160xe4,
18170xfd,
18180x27,
18190x6f,
18200x51,
18210x25,
18220x8b,
18230x43,
18240x74,
18250xc9,
18260x8e,
18270xbd,
18280x88,
18290x31,
18300xbe,
18310xec,
18320x65,
18330xd2,
18340xcb,
18350x8d,
18360x5a,
18370x13,
18380x48,
18390x16,
18400x8c,
18410x61,
18420x0b,
18430x11,
18440xf6,
18450xc6,
18460x66,
18470xae,
18480xc3,
18490xcc,
18500x0c,
18510xd2,
18520xe1,
18530x9f,
18540x82,
18550x41,
18560x3f,
18570x56,
18580xf9,
18590x73,
18600xef,
18610xdc,
18620x30,
18630x50,
18640xcf,
18650xb6,
18660x7f,
18670xbc,
18680xd0,
18690xb3,
18700x10,
18710xab,
18720x24,
18730xe4,
18740xec,
18750xad,
18760x18,
18770x8c,
18780x39,
18790x2d,
18800x30,
18810x4c,
18820xc5,
18830x40,
18840x0d,
18850xf6,
18860xac,
18870xd6,
18880x18,
18890x5d,
18900x96,
18910xbf,
18920x5f,
18930x71,
18940x75,
18950x96,
18960x22,
18970x97,
18980x0f,
18990x02,
19000x94,
19010x6e,
19020xa6,
19030xae,
19040x6d,
19050x8f,
19060x1e,
19070xca,
19080x12,
19090x9b,
19100x2a,
19110x1c,
19120xce,
19130xa9,
19140xee,
19150xfd,
19160x12,
19170x8e,
19180xfc,
19190xed,
19200x09,
19210x33,
19220xba,
19230xf4,
19240x1a,
19250x15,
19260xf6,
19270x9d,
19280x87,
19290x16,
19300x43,
19310x7c,
19320x78,
19330x57,
19340xe1,
19350x44,
19360xc9,
19370xeb,
19380x1f,
19390x58,
19400x4d,
19410xc1,
19420x49,
19430x11,
19440x5c,
19450xb2,
19460x11,
19470xa8,
19480x55,
19490x16,
19500xf1,
19510xc6,
19520x50,
19530xe9,
19540x87,
19550x89,
19560xf6,
19570xcf,
19580xd8,
19590x9c,
19600x51,
19610xa7,
19620xbc,
19630x5b,
19640x31,
19650x6d,
19660x4d,
19670x51,
19680xd0,
19690x4c,
19700xbc,
19710x0d,
19720x58,
19730x2d,
19740x7b,
19750x88,
19760x7a,
19770xf9,
19780x8e,
19790xd6,
19800x40,
19810x4d,
19820xbb,
19830xbe,
19840xc4,
19850xe5,
19860x07,
19870xfc,
19880xd9,
19890x7b,
19900x6d,
19910xa6,
19920x42,
19930x57,
19940x8f,
19950x02,
19960x94,
19970x4f,
19980xe4,
19990x2a,
20000x65,
20010xe2,
20020x19,
20030x5a,
20040x50,
20050xe1,
20060x25,
20070x65,
20080x4a,
20090x60,
20100xc2,
20110xcd,
20120xa8,
20130xec,
20140x05,
20150x2e,
20160x87,
20170x7b,
20180x95,
20190xb7,
20200x4f,
20210xa0,
20220x0b,
20230x1b,
20240x4a,
20250x7f,
20260x92,
20270xc8,
20280x90,
20290xee,
20300x89,
20310x1e,
20320x10,
20330xd2,
20340x85,
20350xe4,
20360x9f,
20370x63,
20380xc8,
20390x12,
20400xbb,
20410x4e,
20420xb8,
20430xcf,
20440x0a,
20450xec,
20460x18,
20470x4e,
20480xe6,
20490x7c,
20500xb3,
20510x33,
20520x26,
20530xc7,
20540x1f,
20550xd2,
20560x04,
20570x23,
20580xea,
20590x07,
20600x0c,
20610x5f,
20620x90,
20630xbd,
20640xa7,
20650x6a,
20660x0f,
20670x4a,
20680xd6,
20690x10,
20700x01,
20710x3c,
20720x12,
20730x29,
20740x2e,
20750x96,
20760xc0,
20770x4d,
20780xbb,
20790xbe,
20800xe5,
20810xa7,
20820x83,
20830xd5,
20840x6a,
20850x3c,
20860xe3,
20870x5b,
20880xb8,
20890xf2,
20900x5c,
20910x6d,
20920x1f,
20930xa6,
20940xf3,
20950x12,
20960x24,
20970xf6,
20980xd6,
20990x3b,
21000x10,
21010x14,
21020x09,
21030x07,
21040x82,
21050xe8,
21060x30,
21070x6a,
21080x99,
21090xdc,
21100x95,
21110x01,
21120x9c,
21130xd4,
21140x68,
21150x3b,
21160xca,
21170x98,
21180x12,
21190xab,
21200x77,
21210x25,
21220x15,
21230x7d,
21240x10,
21250x32,
21260x45,
21270x98,
21280xcd,
21290x7a,
21300xdf,
21310x71,
21320x8a,
21330x75,
21340xc1,
21350x1c,
21360xd4,
21370x68,
21380x25,
21390xeb,
21400xbb,
21410x54,
21420x27,
21430x6f,
21440x2a,
21450xf7,
21460xb9,
21470x98,
21480x03,
21490x27,
21500xde,
21510x24,
21520xa8,
21530xbb,
21540x98,
21550xc2,
21560x84,
21570xff,
21580x9b,
21590x51,
21600xd8,
21610x53,
21620x50,
21630xda,
21640xf5,
21650x88,
21660xaa,
21670x87,
21680x2f,
21690xae,
21700xd6,
21710xea,
21720x6b,
21730xde,
21740xc8,
21750xd7,
21760xa7,
21770x28,
21780x65,
21790x81,
21800xe8,
21810xb2,
21820x3b,
21830x1d,
21840x4f,
21850x75,
21860x8f,
21870x9f,
21880x7a,
21890x74,
21900x8e,
21910xc1,
21920x5f,
21930x9a,
21940xa8,
21950x9d,
21960xfa,
21970x03,
21980xa3,
21990x71,
22000x9b,
22010x37,
22020x6d,
22030xd5,
22040x0b,
22050xf5,
22060xe1,
22070xa1,
22080x1b,
22090x01,
22100x6a,
22110xc6,
22120x67,
22130xaa,
22140xea,
22150x2c,
22160x9d,
22170xa4,
22180xd2,
22190x6e,
22200xfc,
22210xde,
22220x2e,
22230x7f,
22240x94,
22250x69,
22260xe5,
22270x4a,
22280xe0,
22290x01,
22300x48,
22310x3c,
22320x6b,
22330xf7,
22340x1e,
22350xb6,
22360x0b,
22370x5f,
22380xf9,
22390x2e,
22400x07,
22410xc5,
22420xe8,
22430xae,
22440x37,
22450x1b,
22460xbc,
22470x3c,
22480xd8,
22490xd5,
22500x0b,
22510x91,
22520x9e,
22530x80,
22540x24,
22550xf5,
22560x06,
22570x0c,
22580x0e,
22590x98,
22600x07,
22610x96,
22620x2d,
22630x19,
22640xdc,
22650x58,
22660x93,
22670xcc,
22680xfb,
22690x4e,
22700xeb,
22710xbd,
22720x0f,
22730xf5,
22740xaf,
22750x01,
22760xfa,
22770xf1,
22780x7c,
22790x43,
22800x8c,
22810xb8,
22820x56,
22830x3e,
22840xbe,
22850x77,
22860x4e,
22870x2b,
22880xf7,
22890xbb,
22900xb7,
22910x45,
22920x47,
22930xcd,
22940xcc,
22950xa6,
22960x4c,
22970x72,
22980x7b,
22990x6a,
23000x2a,
23010x70,
23020x13,
23030x07,
23040xfd,
23050xb8,
23060x9c,
23070x98,
23080x3a,
23090xd8,
23100x23,
23110x67,
23120x5b,
23130x34,
23140xd5,
23150x14,
23160x0c,
23170xab,
23180x77,
23190x1f,
23200xf8,
23210x3d,
23220x5a,
23230x9f,
23240x92,
23250xb7,
23260x2c,
23270xad,
23280x31,
23290xde,
23300x61,
23310x07,
23320xb3,
23330x6b,
23340xf7,
23350x38,
23360x15,
23370x95,
23380x46,
23390x14,
23400x48,
23410x53,
23420x69,
23430x52,
23440x66,
23450x07,
23460x6d,
23470x83,
23480x71,
23490x8a,
23500x67,
23510x25,
23520x20,
23530x0f,
23540xfe,
23550xd7,
23560x02,
23570xd7,
23580x6e,
23590x2c,
23600xd2,
23610x1a,
23620x0a,
23630x5d,
23640xfd,
23650x0f,
23660x74,
23670xe3,
23680xa4,
23690x36,
23700x07,
23710x9a,
23720xdf,
23730xd4,
23740x79,
23750xbf,
23760xef,
23770x59,
23780xc0,
23790x44,
23800x52,
23810x87,
23820x9a,
23830x6e,
23840x1d,
23850x0e,
23860xee,
23870xde,
23880x2e,
23890x1a,
23900xa9,
23910x8f,
23920x3a,
23930xc9,
23940xba,
23950xec,
23960x99,
23970x78,
23980x2d,
23990x55,
24000x6b,
24010x14,
24020xc2,
24030x06,
24040xd5,
24050xfc,
24060x93,
24070x53,
24080x4d,
24090x11,
24100x8c,
24110xf8,
24120xfa,
24130x79,
24140x7c,
24150xa6,
24160x64,
24170xae,
24180x61,
24190xb8,
24200x7b,
24210x94,
24220x56,
24230xa6,
24240x39,
24250x78,
24260x9a,
24270xe5,
24280xc7,
24290xdf,
24300x18,
24310x63,
24320x23,
24330x9c,
24340xfa,
24350x66,
24360xbb,
24370xb7,
24380x5a,
24390x27,
24400x4c,
24410xd1,
24420xa1,
24430x83,
24440x22,
24450xb3,
24460x52,
24470x49,
24480x35,
24490xb0,
24500x22,
24510x83,
24520x59,
24530x12,
24540x00,
24550x16,
24560x98,
24570xdd,
24580xad,
24590xc2,
24600x94,
24610xf9,
24620xd3,
24630x7b,
24640x64,
24650x7f,
24660x44,
24670x3e,
24680x3c,
24690x8b,
24700x9a,
24710x83,
24720x9c,
24730x69,
24740x6b,
24750xe4,
24760xdf,
24770x9f,
24780xed,
24790x54,
24800x1f,
24810xe5,
24820x5d,
24830x7a,
24840x05,
24850x82,
24860xb3,
24870xdd,
24880xef,
24890xfc,
24900x53,
24910x96,
24920xb0,
24930x2c,
24940x5a,
24950xf8,
24960xdf,
24970x9c,
24980x8b,
24990x16,
25000x4e,
25010xdf,
25020xda,
25030x4d,
25040x09,
25050x09,
25060x69,
25070x50,
25080x03,
25090x65,
25100xd8,
25110x73,
25120x70,
25130xe8,
25140x86,
25150xbf,
25160xbb,
25170x35,
25180xce,
25190xb2,
25200x46,
25210xcb,
25220x02,
25230x00,
25240x5b,
25250xb4,
25260xe2,
25270xc6,
25280x8f,
25290x2f,
25300x98,
25310xaf,
25320x87,
25330x4b,
25340x48,
25350x45,
25360xed,
25370xcc,
25380x1d,
25390xe6,
25400x58,
25410xd6,
25420xf2,
25430x50,
25440x25,
25450x9f,
25460x52,
25470xc7,
25480xcb,
25490x8a,
25500x17,
25510x9d,
25520x5b,
25530xe5,
25540xc8,
25550xd7,
25560x72,
25570xb7,
25580x52,
25590xb2,
25600xc4,
25610x98,
25620xe3,
25630x7a,
25640x17,
25650x3e,
25660xc6,
25670x60,
25680xa7,
25690x97,
25700xb0,
25710xcf,
25720x18,
25730x81,
25740x53,
25750x84,
25760x4c,
25770xd5,
25780x17,
25790x32,
25800x03,
25810x13,
25820x39,
25830x51,
25840x09,
25850x10,
25860xe3,
25870x77,
25880x49,
25890x4f,
25900x62,
25910x01,
25920xbf,
25930x8c,
25940x9a,
25950xe0,
25960x41,
25970x9e,
25980x89,
25990x74,
26000x36,
26010xf9,
26020x96,
26030x86,
26040x2e,
26050x96,
26060x1c,
26070x4a,
26080xb7,
26090x2b,
26100x4a,
26110x97,
26120xbc,
26130x99,
26140x40,
26150xa3,
26160xe0,
26170x3d,
26180xc8,
26190xad,
26200x2f,
26210xdf,
26220x4f,
26230x2c,
26240xc4,
26250x69,
26260x82,
26270x9f,
26280x9b,
26290x81,
26300x0c,
26310x61,
26320x5c,
26330xa5,
26340x9d,
26350x8c,
26360x89,
26370xc0,
26380x2c,
26390xb4,
26400x4a,
26410x33,
26420x4e,
26430xeb,
26440xa2,
26450x56,
26460x40,
26470xc0,
26480xc2,
26490x46,
26500xaf,
26510x6a,
26520xfc,
26530x67,
26540xd1,
26550x80,
26560x5e,
26570xc5,
26580x6d,
26590x84,
26600x43,
26610x27,
26620x3f,
26630x55,
26640x15,
26650x96,
26660x6a,
26670xa0,
26680xa5,
26690xda,
26700xb7,
26710xff,
26720xb7,
26730x75,
26740x6e,
26750x4c,
26760x49,
26770x91,
26780x9d,
26790x22,
26800xa3,
26810x46,
26820xea,
26830xed,
26840x9a,
26850x00,
26860xe2,
26870x32,
26880xc3,
26890xd6,
26900xa9,
26910x71,
26920x20,
26930x55,
26940xa3,
26950x19,
26960xed,
26970xf8,
26980x4f,
26990xa7,
27000x12,
27010x9c,
27020x66,
27030x87,
27040xaf,
27050x4e,
27060xb7,
27070xf0,
27080xdb,
27090xbf,
27100xef,
27110xf0,
27120xf6,
27130xaf,
27140xea,
27150xda,
27160x09,
27170xfe,
27180xde,
27190x38,
27200x5c,
27210xa5,
27220xa2,
27230xdf,
27240x99,
27250x45,
27260xa8,
27270xe4,
27280xe7,
27290x92,
27300xac,
27310x67,
27320xaa,
27330x4f,
27340xbf,
27350x77,
27360x3e,
27370xa2,
27380x40,
27390x49,
27400x22,
27410x4a,
27420x1e,
27430x3b,
27440xaa,
27450x70,
27460x7f,
27470x95,
27480xaf,
27490x37,
27500x4b,
27510xfc,
27520x99,
27530xe2,
27540xe0,
27550xba,
27560xd7,
27570x34,
27580xce,
27590x55,
27600x88,
27610x5b,
27620x84,
27630x1b,
27640x57,
27650xc4,
27660x80,
27670x03,
27680x53,
27690xc9,
27700x2f,
27710x93,
27720x04,
27730x4d,
27740xd5,
27750x96,
27760xe5,
27770x70,
27780xa6,
27790x6e,
27800x63,
27810x5d,
27820x9d,
27830x6c,
27840xdb,
27850x02,
27860x0a,
27870xa9,
27880xda,
27890x8b,
27900x53,
27910xdc,
27920xd9,
27930x9a,
27940xc5,
27950x94,
27960x2c,
27970x91,
27980x92,
27990x2a,
28000xde,
28010xbb,
28020x8b,
28030x13,
28040xb9,
28050x19,
28060x96,
28070x64,
28080xcc,
28090xf2,
28100x64,
28110x39,
28120xb7,
28130x75,
28140x49,
28150xe9,
28160x86,
28170xc2,
28180x86,
28190x62,
28200xd9,
28210x24,
28220xd3,
28230x81,
28240x35,
28250x49,
28260xfc,
28270xa0,
28280xa5,
28290xa0,
28300x93,
28310x05,
28320x64,
28330xb4,
28340x1a,
28350x57,
28360xce,
28370x0c,
28380x90,
28390x02,
28400x27,
28410xc5,
28420x7a,
28430x2b,
28440x5d,
28450xae,
28460x3e,
28470xd5,
28480xdd,
28490x10,
28500x7c,
28510x14,
28520xea,
28530x3a,
28540x08,
28550xac,
28560x72,
28570x4e,
28580x90,
28590x3d,
28600x3b,
28610x7c,
28620x86,
28630x2e,
28640xeb,
28650xd4,
28660x06,
28670x70,
28680xe6,
28690xc7,
28700xfb,
28710x5f,
28720xbd,
28730x18,
28740xf4,
28750x11,
28760xa4,
28770x1a,
28780x93,
28790xc3,
28800xbe,
28810xd9,
28820xfb,
28830x26,
28840x48,
28850x2f,
28860x37,
28870x3c,
28880xd0,
28890x03,
28900x47,
28910x1a,
28920xf7,
28930x62,
28940x19,
28950x24,
28960x5c,
28970xf4,
28980xa8,
28990x92,
29000x20,
29010x7a,
29020xf2,
29030x9e,
29040x2a,
29050xc5,
29060x95,
29070xa2,
29080xfb,
29090xa4,
29100xea,
29110x85,
29120xd8,
29130x56,
29140xb7,
29150x70,
29160xd1,
29170x60,
29180x30,
29190xa5,
29200x30,
29210x82,
29220x70,
29230xdc,
29240x7a,
29250x65,
29260x8a,
29270x36,
29280x3f,
29290x5b,
29300x0c,
29310xae,
29320x54,
29330x7c,
29340xd3,
29350x57,
29360x84,
29370x7b,
29380x3a,
29390x65,
29400x18,
29410x81,
29420xee,
29430x05,
29440x9b,
29450x44,
29460x4d,
29470xb8,
29480xda,
29490xa2,
29500xa1,
29510xc9,
29520x15,
29530xd3,
29540x73,
29550x03,
29560x0e,
29570x43,
29580xe9,
29590x8e,
29600x15,
29610xf9,
29620xbe,
29630xc6,
29640xc5,
29650x8a,
29660xe5,
29670xc0,
29680x1e,
29690xc2,
29700x37,
29710x9e,
29720x2a,
29730x26,
29740xa5,
29750xa0,
29760xbd,
29770x24,
29780x5f,
29790xb9,
29800xc1,
29810xab,
29820x34,
29830x48,
29840xb9,
29850x5d,
29860x98,
29870xb4,
29880x65,
29890x18,
29900xf3,
29910x63,
29920x19,
29930x44,
29940x1b,
29950x11,
29960x16,
29970xff,
29980xdc,
29990xf1,
30000x79,
30010x08,
30020x86,
30030x0f,
30040x52,
30050x98,
30060x73,
30070xc4,
30080x92,
30090x90,
30100x2b,
30110x47,
30120x09,
30130xd0,
30140x43,
30150x6c,
30160x2f,
30170x20,
30180xeb,
30190xdc,
30200xda,
30210xc5,
30220x08,
30230x7b,
30240x94,
30250x42,
30260x30,
30270x6a,
30280xc7,
30290xda,
30300x8c,
30310xc3,
30320x76,
30330xa7,
30340xa5,
30350xcc,
30360x62,
30370x13,
30380x00,
30390x60,
30400x31,
30410x58,
30420x44,
30430x9b,
30440xf5,
30450x64,
30460x14,
30470xf5,
30480x11,
30490xc5,
30500x54,
30510x52,
30520x83,
30530xd4,
30540x73,
30550x01,
30560x16,
30570x0e,
30580xb3,
30590x7a,
30600x29,
30610x69,
30620x35,
30630x56,
30640xd4,
30650xee,
30660x8a,
30670x17,
30680xa2,
30690x99,
30700x24,
30710x9c,
30720xd7,
30730x8f,
30740xdb,
30750x55,
30760xb5,
30770x3e
3078};
diff --git a/drivers/sensors/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c
new file mode 100644
index 000000000..c0ac644f7
--- /dev/null
+++ b/drivers/sensors/pimoroni_trackball.c
@@ -0,0 +1,140 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "pimoroni_trackball.h"
18#include "i2c_master.h"
19
20static uint8_t scrolling = 0;
21static int16_t x_offset = 0;
22static int16_t y_offset = 0;
23static int16_t h_offset = 0;
24static int16_t v_offset = 0;
25static float precisionSpeed = 1;
26
27static uint16_t i2c_timeout_timer;
28
29#ifndef PIMORONI_I2C_TIMEOUT
30# define PIMORONI_I2C_TIMEOUT 100
31#endif
32#ifndef I2C_WAITCHECK
33# define I2C_WAITCHECK 1000
34#endif
35#ifndef MOUSE_DEBOUNCE
36# define MOUSE_DEBOUNCE 5
37#endif
38
39void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
40 uint8_t data[] = {0x00, red, green, blue, white};
41 i2c_transmit(TRACKBALL_WRITE, data, sizeof(data), PIMORONI_I2C_TIMEOUT);
42}
43
44int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) {
45 int16_t offset = (int16_t)positive - (int16_t)negative;
46 int16_t magnitude = (int16_t)(scale * offset * offset * precisionSpeed);
47 return offset < 0 ? -magnitude : magnitude;
48}
49
50void update_member(int8_t* member, int16_t* offset) {
51 if (*offset > 127) {
52 *member = 127;
53 *offset -= 127;
54 } else if (*offset < -127) {
55 *member = -127;
56 *offset += 127;
57 } else {
58 *member = *offset;
59 *offset = 0;
60 }
61}
62
63__attribute__((weak)) void trackball_check_click(bool pressed, report_mouse_t* mouse) {
64 if (pressed) {
65 mouse->buttons |= MOUSE_BTN1;
66 } else {
67 mouse->buttons &= ~MOUSE_BTN1;
68 }
69}
70
71float trackball_get_precision(void) { return precisionSpeed; }
72void trackball_set_precision(float precision) { precisionSpeed = precision; }
73bool trackball_is_scrolling(void) { return scrolling; }
74void trackball_set_scrolling(bool scroll) { scrolling = scroll; }
75
76__attribute__((weak)) void pointing_device_init(void) { i2c_init(); trackball_set_rgbw(0x00, 0x00, 0x00, 0x00); }
77
78void pointing_device_task(void) {
79 static bool debounce;
80 static uint16_t debounce_timer;
81 uint8_t state[5] = {};
82 if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) {
83 if (i2c_readReg(TRACKBALL_READ, 0x04, state, 5, PIMORONI_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
84 if (!state[4] && !debounce) {
85 if (scrolling) {
86#ifdef PIMORONI_TRACKBALL_INVERT_X
87 h_offset += mouse_offset(state[2], state[3], 1);
88#else
89 h_offset -= mouse_offset(state[2], state[3], 1);
90#endif
91#ifdef PIMORONI_TRACKBALL_INVERT_Y
92 v_offset += mouse_offset(state[1], state[0], 1);
93#else
94 v_offset -= mouse_offset(state[1], state[0], 1);
95#endif
96 } else {
97#ifdef PIMORONI_TRACKBALL_INVERT_X
98 x_offset -= mouse_offset(state[2], state[3], 5);
99#else
100 x_offset += mouse_offset(state[2], state[3], 5);
101#endif
102#ifdef PIMORONI_TRACKBALL_INVERT_Y
103 y_offset -= mouse_offset(state[1], state[0], 5);
104#else
105 y_offset += mouse_offset(state[1], state[0], 5);
106#endif
107 }
108 } else {
109 if (state[4]) {
110 debounce = true;
111 debounce_timer = timer_read();
112 }
113 }
114 } else {
115 i2c_timeout_timer = timer_read();
116 }
117 }
118
119 if (timer_elapsed(debounce_timer) > MOUSE_DEBOUNCE) debounce = false;
120
121 report_mouse_t mouse = pointing_device_get_report();
122
123#ifdef PIMORONI_TRACKBALL_CLICK
124 trackball_check_click(state[4] & (1 << 7), &mouse);
125#endif
126
127#ifndef PIMORONI_TRACKBALL_ROTATE
128 update_member(&mouse.x, &x_offset);
129 update_member(&mouse.y, &y_offset);
130 update_member(&mouse.h, &h_offset);
131 update_member(&mouse.v, &v_offset);
132#else
133 update_member(&mouse.x, &y_offset);
134 update_member(&mouse.y, &x_offset);
135 update_member(&mouse.h, &v_offset);
136 update_member(&mouse.v, &h_offset);
137#endif
138 pointing_device_set_report(mouse);
139 pointing_device_send();
140}
diff --git a/drivers/sensors/pimoroni_trackball.h b/drivers/sensors/pimoroni_trackball.h
new file mode 100644
index 000000000..9e3c64c19
--- /dev/null
+++ b/drivers/sensors/pimoroni_trackball.h
@@ -0,0 +1,35 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include "quantum.h"
20#include "pointing_device.h"
21
22#ifndef TRACKBALL_ADDRESS
23# define TRACKBALL_ADDRESS 0x0A
24#endif
25#define TRACKBALL_WRITE ((TRACKBALL_ADDRESS << 1) | I2C_WRITE)
26#define TRACKBALL_READ (TRACKBALL_ADDRESS << 1)
27
28void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
29void trackball_check_click(bool pressed, report_mouse_t *mouse);
30void trackball_register_button(bool pressed, enum mouse_buttons button);
31
32float trackball_get_precision(void);
33void trackball_set_precision(float precision);
34bool trackball_is_scrolling(void);
35void trackball_set_scrolling(bool scroll);
diff --git a/drivers/sensors/pmw3360.c b/drivers/sensors/pmw3360.c
new file mode 100644
index 000000000..91ee87b95
--- /dev/null
+++ b/drivers/sensors/pmw3360.c
@@ -0,0 +1,237 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "wait.h"
20#include "debug.h"
21#include "print.h"
22#include "pmw3360.h"
23#include "pmw3360_firmware.h"
24
25bool _inBurst = false;
26
27#ifndef PMW_CPI
28# define PMW_CPI 1600
29#endif
30#ifndef PMW_CLOCK_SPEED
31# define PMW_CLOCK_SPEED 70000000
32#endif
33#ifndef SPI_MODE
34# define SPI_MODE 3
35#endif
36#ifndef SPI_DIVISOR
37# define SPI_DIVISOR (F_CPU / PMW_CLOCK_SPEED)
38#endif
39#ifndef ROTATIONAL_TRANSFORM_ANGLE
40# define ROTATIONAL_TRANSFORM_ANGLE 0x00
41#endif
42#ifndef PMW_CS_PIN
43# define PMW_CS_PIN SPI_SS_PIN
44#endif
45
46void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
47
48bool spi_start_adv(void) {
49 bool status = spi_start(PMW_CS_PIN, false, SPI_MODE, SPI_DIVISOR);
50 wait_us(1);
51 return status;
52}
53
54void spi_stop_adv(void) {
55 wait_us(1);
56 spi_stop();
57}
58
59spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) {
60 if (reg_addr != REG_Motion_Burst) {
61 _inBurst = false;
62 }
63
64 spi_start_adv();
65 // send address of the register, with MSBit = 1 to indicate it's a write
66 spi_status_t status = spi_write(reg_addr | 0x80);
67 status = spi_write(data);
68
69 // tSCLK-NCS for write operation
70 wait_us(20);
71
72 // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
73 wait_us(100);
74 spi_stop();
75 return status;
76}
77
78uint8_t spi_read_adv(uint8_t reg_addr) {
79 spi_start_adv();
80 // send adress of the register, with MSBit = 0 to indicate it's a read
81 spi_write(reg_addr & 0x7f);
82
83 uint8_t data = spi_read();
84
85 // tSCLK-NCS for read operation is 120ns
86 wait_us(1);
87
88 // tSRW/tSRR (=20us) minus tSCLK-NCS
89 wait_us(19);
90
91 spi_stop();
92 return data;
93}
94
95void pmw_set_cpi(uint16_t cpi) {
96 uint8_t cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119
97
98 spi_start_adv();
99 spi_write_adv(REG_Config1, cpival);
100 spi_stop();
101}
102
103uint16_t pmw_get_cpi(void) {
104 uint8_t cpival = spi_read_adv(REG_Config1);
105 return (uint16_t)(cpival & 0xFF) * 100;
106}
107
108bool pmw_spi_init(void) {
109 setPinOutput(PMW_CS_PIN);
110
111 spi_init();
112 _inBurst = false;
113
114 spi_stop();
115 spi_start_adv();
116 spi_stop();
117
118 spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first
119 wait_ms(300);
120
121 spi_start_adv();
122 wait_us(40);
123 spi_stop_adv();
124 wait_us(40);
125
126 spi_write_adv(REG_Power_Up_Reset, 0x5a);
127 wait_ms(50);
128
129 spi_read_adv(REG_Motion);
130 spi_read_adv(REG_Delta_X_L);
131 spi_read_adv(REG_Delta_X_H);
132 spi_read_adv(REG_Delta_Y_L);
133 spi_read_adv(REG_Delta_Y_H);
134
135 pmw_upload_firmware();
136
137 spi_stop_adv();
138
139 wait_ms(10);
140 pmw_set_cpi(PMW_CPI);
141
142 wait_ms(1);
143
144 spi_write_adv(REG_Config2, 0x00);
145
146 spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
147
148 bool init_success = pmw_check_signature();
149
150 writePinLow(PMW_CS_PIN);
151
152 return init_success;
153}
154
155void pmw_upload_firmware(void) {
156 spi_write_adv(REG_SROM_Enable, 0x1d);
157
158 wait_ms(10);
159
160 spi_write_adv(REG_SROM_Enable, 0x18);
161
162 spi_start_adv();
163 spi_write(REG_SROM_Load_Burst | 0x80);
164 wait_us(15);
165
166 unsigned char c;
167 for (int i = 0; i < firmware_length; i++) {
168 c = (unsigned char)pgm_read_byte(firmware_data + i);
169 spi_write(c);
170 wait_us(15);
171 }
172 wait_us(200);
173
174 spi_read_adv(REG_SROM_ID);
175
176 spi_write_adv(REG_Config2, 0x00);
177
178 spi_stop();
179 wait_ms(10);
180}
181
182bool pmw_check_signature(void) {
183 uint8_t pid = spi_read_adv(REG_Product_ID);
184 uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID);
185 uint8_t SROM_ver = spi_read_adv(REG_SROM_ID);
186 return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04
187}
188
189report_pmw_t pmw_read_burst(void) {
190 if (!_inBurst) {
191 dprintf("burst on");
192 spi_write_adv(REG_Motion_Burst, 0x00);
193 _inBurst = true;
194 }
195
196 spi_start_adv();
197 spi_write(REG_Motion_Burst);
198 wait_us(35); // waits for tSRAD
199
200 report_pmw_t data;
201 data.motion = 0;
202 data.dx = 0;
203 data.mdx = 0;
204 data.dy = 0;
205 data.mdx = 0;
206
207 data.motion = spi_read();
208 spi_write(0x00); // skip Observation
209 data.dx = spi_read();
210 data.mdx = spi_read();
211 data.dy = spi_read();
212 data.mdy = spi_read();
213
214 spi_stop();
215
216 print_byte(data.motion);
217 print_byte(data.dx);
218 print_byte(data.mdx);
219 print_byte(data.dy);
220 print_byte(data.mdy);
221 dprintf("\n");
222
223 data.isMotion = (data.motion & 0x80) != 0;
224 data.isOnSurface = (data.motion & 0x08) == 0;
225 data.dx |= (data.mdx << 8);
226 data.dx = data.dx * -1;
227 data.dy |= (data.mdy << 8);
228 data.dy = data.dy * -1;
229
230 spi_stop();
231
232 if (data.motion & 0b111) { // panic recovery, sometimes burst mode works weird.
233 _inBurst = false;
234 }
235
236 return data;
237}
diff --git a/drivers/sensors/pmw3360.h b/drivers/sensors/pmw3360.h
new file mode 100644
index 000000000..d5b174179
--- /dev/null
+++ b/drivers/sensors/pmw3360.h
@@ -0,0 +1,104 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include "spi_master.h"
22
23// Registers
24#define REG_Product_ID 0x00
25#define REG_Revision_ID 0x01
26#define REG_Motion 0x02
27#define REG_Delta_X_L 0x03
28#define REG_Delta_X_H 0x04
29#define REG_Delta_Y_L 0x05
30#define REG_Delta_Y_H 0x06
31#define REG_SQUAL 0x07
32#define REG_Raw_Data_Sum 0x08
33#define REG_Maximum_Raw_data 0x09
34#define REG_Minimum_Raw_data 0x0A
35#define REG_Shutter_Lower 0x0B
36#define REG_Shutter_Upper 0x0C
37#define REG_Control 0x0D
38#define REG_Config1 0x0F
39#define REG_Config2 0x10
40#define REG_Angle_Tune 0x11
41#define REG_Frame_Capture 0x12
42#define REG_SROM_Enable 0x13
43#define REG_Run_Downshift 0x14
44#define REG_Rest1_Rate_Lower 0x15
45#define REG_Rest1_Rate_Upper 0x16
46#define REG_Rest1_Downshift 0x17
47#define REG_Rest2_Rate_Lower 0x18
48#define REG_Rest2_Rate_Upper 0x19
49#define REG_Rest2_Downshift 0x1A
50#define REG_Rest3_Rate_Lower 0x1B
51#define REG_Rest3_Rate_Upper 0x1C
52#define REG_Observation 0x24
53#define REG_Data_Out_Lower 0x25
54#define REG_Data_Out_Upper 0x26
55#define REG_Raw_Data_Dump 0x29
56#define REG_SROM_ID 0x2A
57#define REG_Min_SQ_Run 0x2B
58#define REG_Raw_Data_Threshold 0x2C
59#define REG_Config5 0x2F
60#define REG_Power_Up_Reset 0x3A
61#define REG_Shutdown 0x3B
62#define REG_Inverse_Product_ID 0x3F
63#define REG_LiftCutoff_Tune3 0x41
64#define REG_Angle_Snap 0x42
65#define REG_LiftCutoff_Tune1 0x4A
66#define REG_Motion_Burst 0x50
67#define REG_LiftCutoff_Tune_Timeout 0x58
68#define REG_LiftCutoff_Tune_Min_Length 0x5A
69#define REG_SROM_Load_Burst 0x62
70#define REG_Lift_Config 0x63
71#define REG_Raw_Data_Burst 0x64
72#define REG_LiftCutoff_Tune2 0x65
73
74#ifdef CONSOLE_ENABLE
75void print_byte(uint8_t byte);
76#endif
77
78typedef struct {
79 int8_t motion;
80 bool isMotion; // True if a motion is detected.
81 bool isOnSurface; // True when a chip is on a surface
82 int16_t dx; // displacement on x directions. Unit: Count. (CPI * Count = Inch value)
83 int8_t mdx;
84 int16_t dy; // displacement on y directions.
85 int8_t mdy;
86} report_pmw_t;
87
88
89
90bool spi_start_adv(void);
91void spi_stop_adv(void);
92spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
93uint8_t spi_read_adv(uint8_t reg_addr);
94bool pmw_spi_init(void);
95void pmw_set_cpi(uint16_t cpi);
96uint16_t pmw_get_cpi(void);
97void pmw_upload_firmware(void);
98bool pmw_check_signature(void);
99report_pmw_t pmw_read_burst(void);
100
101
102#define degToRad(angleInDegrees) ((angleInDegrees)*M_PI / 180.0)
103#define radToDeg(angleInRadians) ((angleInRadians)*180.0 / M_PI)
104#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
diff --git a/drivers/sensors/pmw3360_firmware.h b/drivers/sensors/pmw3360_firmware.h
new file mode 100644
index 000000000..cca5a6a4d
--- /dev/null
+++ b/drivers/sensors/pmw3360_firmware.h
@@ -0,0 +1,300 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21// clang-format off
22// Firmware Blob foor PMW3360
23const uint16_t firmware_length = 4094;
24// clang-format off
25const uint8_t firmware_data[] PROGMEM = { // SROM 0x04
260x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
270xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
280xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
290x97, 0x8d, 0x79, 0x51, 0x20, 0xc7, 0x06, 0x8e, 0x7c, 0x7c, 0x7a, 0x76, 0x4f, 0xfd, 0x59,
300x30, 0xe2, 0x46, 0x0e, 0x9e, 0xbe, 0xdf, 0x1d, 0x99, 0x91, 0xa0, 0xa5, 0xa1, 0xa9, 0xd0,
310x22, 0xc6, 0xef, 0x5c, 0x1b, 0x95, 0x89, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x55, 0x28, 0xb3,
320xe4, 0x4a, 0xf7, 0x6c, 0x3b, 0xf4, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x05,
330x88, 0x92, 0xa6, 0xce, 0x1e, 0xbe, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x07,
340x11, 0x5d, 0x98, 0x0b, 0x9d, 0x94, 0x97, 0xee, 0x4e, 0x45, 0x33, 0x6b, 0x44, 0xc7, 0x29,
350x56, 0x27, 0x30, 0xc6, 0xa7, 0xd5, 0xf2, 0x56, 0xdf, 0xb4, 0x38, 0x62, 0xcb, 0xa0, 0xb6,
360xe3, 0x0f, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6f, 0x76, 0x89, 0xb5, 0x77, 0x41, 0x27, 0x82,
370x66, 0x65, 0x82, 0xcc, 0xd5, 0xe6, 0x20, 0xd5, 0x27, 0x17, 0xc5, 0xf8, 0x03, 0x23, 0x7c,
380x5f, 0x64, 0xa5, 0x1d, 0xc1, 0xd6, 0x36, 0xcb, 0x4c, 0xd4, 0xdb, 0x66, 0xd7, 0x8b, 0xb1,
390x99, 0x7e, 0x6f, 0x4c, 0x36, 0x40, 0x06, 0xd6, 0xeb, 0xd7, 0xa2, 0xe4, 0xf4, 0x95, 0x51,
400x5a, 0x54, 0x96, 0xd5, 0x53, 0x44, 0xd7, 0x8c, 0xe0, 0xb9, 0x40, 0x68, 0xd2, 0x18, 0xe9,
410xdd, 0x9a, 0x23, 0x92, 0x48, 0xee, 0x7f, 0x43, 0xaf, 0xea, 0x77, 0x38, 0x84, 0x8c, 0x0a,
420x72, 0xaf, 0x69, 0xf8, 0xdd, 0xf1, 0x24, 0x83, 0xa3, 0xf8, 0x4a, 0xbf, 0xf5, 0x94, 0x13,
430xdb, 0xbb, 0xd8, 0xb4, 0xb3, 0xa0, 0xfb, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71,
440xa2, 0xd3, 0x13, 0xe7, 0xfa, 0xe7, 0xce, 0x0f, 0x63, 0x15, 0x0b, 0x6b, 0x94, 0xbb, 0x37,
450x83, 0x26, 0x05, 0x9d, 0xfb, 0x46, 0x92, 0xfc, 0x0a, 0x15, 0xd1, 0x0d, 0x73, 0x92, 0xd6,
460x8c, 0x1b, 0x8c, 0xb8, 0x55, 0x8a, 0xce, 0xbd, 0xfe, 0x8e, 0xfc, 0xed, 0x09, 0x12, 0x83,
470x91, 0x82, 0x51, 0x31, 0x23, 0xfb, 0xb4, 0x0c, 0x76, 0xad, 0x7c, 0xd9, 0xb4, 0x4b, 0xb2,
480x67, 0x14, 0x09, 0x9c, 0x7f, 0x0c, 0x18, 0xba, 0x3b, 0xd6, 0x8e, 0x14, 0x2a, 0xe4, 0x1b,
490x52, 0x9f, 0x2b, 0x7d, 0xe1, 0xfb, 0x6a, 0x33, 0x02, 0xfa, 0xac, 0x5a, 0xf2, 0x3e, 0x88,
500x7e, 0xae, 0xd1, 0xf3, 0x78, 0xe8, 0x05, 0xd1, 0xe3, 0xdc, 0x21, 0xf6, 0xe1, 0x9a, 0xbd,
510x17, 0x0e, 0xd9, 0x46, 0x9b, 0x88, 0x03, 0xea, 0xf6, 0x66, 0xbe, 0x0e, 0x1b, 0x50, 0x49,
520x96, 0x40, 0x97, 0xf1, 0xf1, 0xe4, 0x80, 0xa6, 0x6e, 0xe8, 0x77, 0x34, 0xbf, 0x29, 0x40,
530x44, 0xc2, 0xff, 0x4e, 0x98, 0xd3, 0x9c, 0xa3, 0x32, 0x2b, 0x76, 0x51, 0x04, 0x09, 0xe7,
540xa9, 0xd1, 0xa6, 0x32, 0xb1, 0x23, 0x53, 0xe2, 0x47, 0xab, 0xd6, 0xf5, 0x69, 0x5c, 0x3e,
550x5f, 0xfa, 0xae, 0x45, 0x20, 0xe5, 0xd2, 0x44, 0xff, 0x39, 0x32, 0x6d, 0xfd, 0x27, 0x57,
560x5c, 0xfd, 0xf0, 0xde, 0xc1, 0xb5, 0x99, 0xe5, 0xf5, 0x1c, 0x77, 0x01, 0x75, 0xc5, 0x6d,
570x58, 0x92, 0xf2, 0xb2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7a, 0x30, 0xff, 0xb7, 0xf0, 0xef,
580x77, 0xc1, 0x8a, 0x5d, 0xdc, 0xc0, 0xd1, 0x29, 0x30, 0x1e, 0x77, 0x38, 0x7a, 0x94, 0xf1,
590xb8, 0x7a, 0x7e, 0xef, 0xa4, 0xd1, 0xac, 0x31, 0x4a, 0xf2, 0x5d, 0x64, 0x3d, 0xb2, 0xe2,
600xf0, 0x08, 0x99, 0xfc, 0x70, 0xee, 0x24, 0xa7, 0x7e, 0xee, 0x1e, 0x20, 0x69, 0x7d, 0x44,
610xbf, 0x87, 0x42, 0xdf, 0x88, 0x3b, 0x0c, 0xda, 0x42, 0xc9, 0x04, 0xf9, 0x45, 0x50, 0xfc,
620x83, 0x8f, 0x11, 0x6a, 0x72, 0xbc, 0x99, 0x95, 0xf0, 0xac, 0x3d, 0xa7, 0x3b, 0xcd, 0x1c,
630xe2, 0x88, 0x79, 0x37, 0x11, 0x5f, 0x39, 0x89, 0x95, 0x0a, 0x16, 0x84, 0x7a, 0xf6, 0x8a,
640xa4, 0x28, 0xe4, 0xed, 0x83, 0x80, 0x3b, 0xb1, 0x23, 0xa5, 0x03, 0x10, 0xf4, 0x66, 0xea,
650xbb, 0x0c, 0x0f, 0xc5, 0xec, 0x6c, 0x69, 0xc5, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0x99,
660x88, 0x76, 0x08, 0xa0, 0xa8, 0x95, 0x7c, 0xd8, 0x38, 0x6d, 0xcd, 0x59, 0x02, 0x51, 0x4b,
670xf1, 0xb5, 0x2b, 0x50, 0xe3, 0xb6, 0xbd, 0xd0, 0x72, 0xcf, 0x9e, 0xfd, 0x6e, 0xbb, 0x44,
680xc8, 0x24, 0x8a, 0x77, 0x18, 0x8a, 0x13, 0x06, 0xef, 0x97, 0x7d, 0xfa, 0x81, 0xf0, 0x31,
690xe6, 0xfa, 0x77, 0xed, 0x31, 0x06, 0x31, 0x5b, 0x54, 0x8a, 0x9f, 0x30, 0x68, 0xdb, 0xe2,
700x40, 0xf8, 0x4e, 0x73, 0xfa, 0xab, 0x74, 0x8b, 0x10, 0x58, 0x13, 0xdc, 0xd2, 0xe6, 0x78,
710xd1, 0x32, 0x2e, 0x8a, 0x9f, 0x2c, 0x58, 0x06, 0x48, 0x27, 0xc5, 0xa9, 0x5e, 0x81, 0x47,
720x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xa4, 0x3e, 0x88, 0x9c, 0xda, 0x33, 0x0a, 0xce, 0xbc,
730x8b, 0x8e, 0xcf, 0x9f, 0xd3, 0x71, 0x80, 0x43, 0xcf, 0x6b, 0xa9, 0x51, 0x83, 0x76, 0x30,
740x82, 0xc5, 0x6a, 0x85, 0x39, 0x11, 0x50, 0x1a, 0x82, 0xdc, 0x1e, 0x1c, 0xd5, 0x7d, 0xa9,
750x71, 0x99, 0x33, 0x47, 0x19, 0x97, 0xb3, 0x5a, 0xb1, 0xdf, 0xed, 0xa4, 0xf2, 0xe6, 0x26,
760x84, 0xa2, 0x28, 0x9a, 0x9e, 0xdf, 0xa6, 0x6a, 0xf4, 0xd6, 0xfc, 0x2e, 0x5b, 0x9d, 0x1a,
770x2a, 0x27, 0x68, 0xfb, 0xc1, 0x83, 0x21, 0x4b, 0x90, 0xe0, 0x36, 0xdd, 0x5b, 0x31, 0x42,
780x55, 0xa0, 0x13, 0xf7, 0xd0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xc5, 0xf3, 0x21,
790xf8, 0x37, 0x2f, 0x40, 0xf3, 0xd4, 0xaf, 0x16, 0x08, 0x36, 0x02, 0xfc, 0x77, 0xc5, 0x8b,
800x04, 0x90, 0x56, 0xb9, 0xc9, 0x67, 0x9a, 0x99, 0xe8, 0x00, 0xd3, 0x86, 0xff, 0x97, 0x2d,
810x08, 0xe9, 0xb7, 0xb3, 0x91, 0xbc, 0xdf, 0x45, 0xc6, 0xed, 0x0f, 0x8c, 0x4c, 0x1e, 0xe6,
820x5b, 0x6e, 0x38, 0x30, 0xe4, 0xaa, 0xe3, 0x95, 0xde, 0xb9, 0xe4, 0x9a, 0xf5, 0xb2, 0x55,
830x9a, 0x87, 0x9b, 0xf6, 0x6a, 0xb2, 0xf2, 0x77, 0x9a, 0x31, 0xf4, 0x7a, 0x31, 0xd1, 0x1d,
840x04, 0xc0, 0x7c, 0x32, 0xa2, 0x9e, 0x9a, 0xf5, 0x62, 0xf8, 0x27, 0x8d, 0xbf, 0x51, 0xff,
850xd3, 0xdf, 0x64, 0x37, 0x3f, 0x2a, 0x6f, 0x76, 0x3a, 0x7d, 0x77, 0x06, 0x9e, 0x77, 0x7f,
860x5e, 0xeb, 0x32, 0x51, 0xf9, 0x16, 0x66, 0x9a, 0x09, 0xf3, 0xb0, 0x08, 0xa4, 0x70, 0x96,
870x46, 0x30, 0xff, 0xda, 0x4f, 0xe9, 0x1b, 0xed, 0x8d, 0xf8, 0x74, 0x1f, 0x31, 0x92, 0xb3,
880x73, 0x17, 0x36, 0xdb, 0x91, 0x30, 0xd6, 0x88, 0x55, 0x6b, 0x34, 0x77, 0x87, 0x7a, 0xe7,
890xee, 0x06, 0xc6, 0x1c, 0x8c, 0x19, 0x0c, 0x48, 0x46, 0x23, 0x5e, 0x9c, 0x07, 0x5c, 0xbf,
900xb4, 0x7e, 0xd6, 0x4f, 0x74, 0x9c, 0xe2, 0xc5, 0x50, 0x8b, 0xc5, 0x8b, 0x15, 0x90, 0x60,
910x62, 0x57, 0x29, 0xd0, 0x13, 0x43, 0xa1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xc7, 0x4d, 0x19,
920x86, 0xcc, 0x2f, 0x2a, 0x75, 0x5a, 0xfc, 0xeb, 0x97, 0x2a, 0x70, 0xe3, 0x78, 0xd8, 0x91,
930xb0, 0x4f, 0x99, 0x07, 0xa3, 0x95, 0xea, 0x24, 0x21, 0xd5, 0xde, 0x51, 0x20, 0x93, 0x27,
940x0a, 0x30, 0x73, 0xa8, 0xff, 0x8a, 0x97, 0xe9, 0xa7, 0x6a, 0x8e, 0x0d, 0xe8, 0xf0, 0xdf,
950xec, 0xea, 0xb4, 0x6c, 0x1d, 0x39, 0x2a, 0x62, 0x2d, 0x3d, 0x5a, 0x8b, 0x65, 0xf8, 0x90,
960x05, 0x2e, 0x7e, 0x91, 0x2c, 0x78, 0xef, 0x8e, 0x7a, 0xc1, 0x2f, 0xac, 0x78, 0xee, 0xaf,
970x28, 0x45, 0x06, 0x4c, 0x26, 0xaf, 0x3b, 0xa2, 0xdb, 0xa3, 0x93, 0x06, 0xb5, 0x3c, 0xa5,
980xd8, 0xee, 0x8f, 0xaf, 0x25, 0xcc, 0x3f, 0x85, 0x68, 0x48, 0xa9, 0x62, 0xcc, 0x97, 0x8f,
990x7f, 0x2a, 0xea, 0xe0, 0x15, 0x0a, 0xad, 0x62, 0x07, 0xbd, 0x45, 0xf8, 0x41, 0xd8, 0x36,
1000xcb, 0x4c, 0xdb, 0x6e, 0xe6, 0x3a, 0xe7, 0xda, 0x15, 0xe9, 0x29, 0x1e, 0x12, 0x10, 0xa0,
1010x14, 0x2c, 0x0e, 0x3d, 0xf4, 0xbf, 0x39, 0x41, 0x92, 0x75, 0x0b, 0x25, 0x7b, 0xa3, 0xce,
1020x39, 0x9c, 0x15, 0x64, 0xc8, 0xfa, 0x3d, 0xef, 0x73, 0x27, 0xfe, 0x26, 0x2e, 0xce, 0xda,
1030x6e, 0xfd, 0x71, 0x8e, 0xdd, 0xfe, 0x76, 0xee, 0xdc, 0x12, 0x5c, 0x02, 0xc5, 0x3a, 0x4e,
1040x4e, 0x4f, 0xbf, 0xca, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x41, 0xf1, 0x10, 0xe0, 0x4f, 0x7e,
1050x97, 0x7f, 0x1c, 0xae, 0x47, 0x8e, 0x6b, 0xb1, 0x25, 0x31, 0xb0, 0x73, 0xc7, 0x1b, 0x97,
1060x79, 0xf9, 0x80, 0xd3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1e, 0xe4, 0xd0, 0x80, 0x21, 0xd6,
1070xee, 0x6b, 0x6c, 0x4f, 0xbf, 0xf5, 0xb7, 0xd9, 0x09, 0x87, 0x2f, 0xa9, 0x14, 0xbe, 0x27,
1080xd9, 0x72, 0x50, 0x01, 0xd4, 0x13, 0x73, 0xa6, 0xa7, 0x51, 0x02, 0x75, 0x25, 0xe1, 0xb3,
1090x45, 0x34, 0x7d, 0xa8, 0x8e, 0xeb, 0xf3, 0x16, 0x49, 0xcb, 0x4f, 0x8c, 0xa1, 0xb9, 0x36,
1100x85, 0x39, 0x75, 0x5d, 0x08, 0x00, 0xae, 0xeb, 0xf6, 0xea, 0xd7, 0x13, 0x3a, 0x21, 0x5a,
1110x5f, 0x30, 0x84, 0x52, 0x26, 0x95, 0xc9, 0x14, 0xf2, 0x57, 0x55, 0x6b, 0xb1, 0x10, 0xc2,
1120xe1, 0xbd, 0x3b, 0x51, 0xc0, 0xb7, 0x55, 0x4c, 0x71, 0x12, 0x26, 0xc7, 0x0d, 0xf9, 0x51,
1130xa4, 0x38, 0x02, 0x05, 0x7f, 0xb8, 0xf1, 0x72, 0x4b, 0xbf, 0x71, 0x89, 0x14, 0xf3, 0x77,
1140x38, 0xd9, 0x71, 0x24, 0xf3, 0x00, 0x11, 0xa1, 0xd8, 0xd4, 0x69, 0x27, 0x08, 0x37, 0x35,
1150xc9, 0x11, 0x9d, 0x90, 0x1c, 0x0e, 0xe7, 0x1c, 0xff, 0x2d, 0x1e, 0xe8, 0x92, 0xe1, 0x18,
1160x10, 0x95, 0x7c, 0xe0, 0x80, 0xf4, 0x96, 0x43, 0x21, 0xf9, 0x75, 0x21, 0x64, 0x38, 0xdd,
1170x9f, 0x1e, 0x95, 0x16, 0xda, 0x56, 0x1d, 0x4f, 0x9a, 0x53, 0xb2, 0xe2, 0xe4, 0x18, 0xcb,
1180x6b, 0x1a, 0x65, 0xeb, 0x56, 0xc6, 0x3b, 0xe5, 0xfe, 0xd8, 0x26, 0x3f, 0x3a, 0x84, 0x59,
1190x72, 0x66, 0xa2, 0xf3, 0x75, 0xff, 0xfb, 0x60, 0xb3, 0x22, 0xad, 0x3f, 0x2d, 0x6b, 0xf9,
1200xeb, 0xea, 0x05, 0x7c, 0xd8, 0x8f, 0x6d, 0x2c, 0x98, 0x9e, 0x2b, 0x93, 0xf1, 0x5e, 0x46,
1210xf0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xd7, 0x7f, 0xf9, 0xf0, 0xe5, 0x7d, 0xdb, 0x1d, 0x75,
1220x19, 0xf3, 0xc4, 0x58, 0x9b, 0x17, 0x88, 0xa8, 0x92, 0xe0, 0xbe, 0xbd, 0x8b, 0x1d, 0x8d,
1230x9f, 0x56, 0x76, 0xad, 0xaf, 0x29, 0xe2, 0xd9, 0xd5, 0x52, 0xf6, 0xb5, 0x56, 0x35, 0x57,
1240x3a, 0xc8, 0xe1, 0x56, 0x43, 0x19, 0x94, 0xd3, 0x04, 0x9b, 0x6d, 0x35, 0xd8, 0x0b, 0x5f,
1250x4d, 0x19, 0x8e, 0xec, 0xfa, 0x64, 0x91, 0x0a, 0x72, 0x20, 0x2b, 0xbc, 0x1a, 0x4a, 0xfe,
1260x8b, 0xfd, 0xbb, 0xed, 0x1b, 0x23, 0xea, 0xad, 0x72, 0x82, 0xa1, 0x29, 0x99, 0x71, 0xbd,
1270xf0, 0x95, 0xc1, 0x03, 0xdd, 0x7b, 0xc2, 0xb2, 0x3c, 0x28, 0x54, 0xd3, 0x68, 0xa4, 0x72,
1280xc8, 0x66, 0x96, 0xe0, 0xd1, 0xd8, 0x7f, 0xf8, 0xd1, 0x26, 0x2b, 0xf7, 0xad, 0xba, 0x55,
1290xca, 0x15, 0xb9, 0x32, 0xc3, 0xe5, 0x88, 0x97, 0x8e, 0x5c, 0xfb, 0x92, 0x25, 0x8b, 0xbf,
1300xa2, 0x45, 0x55, 0x7a, 0xa7, 0x6f, 0x8b, 0x57, 0x5b, 0xcf, 0x0e, 0xcb, 0x1d, 0xfb, 0x20,
1310x82, 0x77, 0xa8, 0x8c, 0xcc, 0x16, 0xce, 0x1d, 0xfa, 0xde, 0xcc, 0x0b, 0x62, 0xfe, 0xcc,
1320xe1, 0xb7, 0xf0, 0xc3, 0x81, 0x64, 0x73, 0x40, 0xa0, 0xc2, 0x4d, 0x89, 0x11, 0x75, 0x33,
1330x55, 0x33, 0x8d, 0xe8, 0x4a, 0xfd, 0xea, 0x6e, 0x30, 0x0b, 0xd7, 0x31, 0x2c, 0xde, 0x47,
1340xe3, 0xbf, 0xf8, 0x55, 0x42, 0xe2, 0x7f, 0x59, 0xe5, 0x17, 0xef, 0x99, 0x34, 0x69, 0x91,
1350xb1, 0x23, 0x8e, 0x20, 0x87, 0x2d, 0xa8, 0xfe, 0xd5, 0x8a, 0xf3, 0x84, 0x3a, 0xf0, 0x37,
1360xe4, 0x09, 0x00, 0x54, 0xee, 0x67, 0x49, 0x93, 0xe4, 0x81, 0x70, 0xe3, 0x90, 0x4d, 0xef,
1370xfe, 0x41, 0xb7, 0x99, 0x7b, 0xc1, 0x83, 0xba, 0x62, 0x12, 0x6f, 0x7d, 0xde, 0x6b, 0xaf,
1380xda, 0x16, 0xf9, 0x55, 0x51, 0xee, 0xa6, 0x0c, 0x2b, 0x02, 0xa3, 0xfd, 0x8d, 0xfb, 0x30,
1390x17, 0xe4, 0x6f, 0xdf, 0x36, 0x71, 0xc4, 0xca, 0x87, 0x25, 0x48, 0xb0, 0x47, 0xec, 0xea,
1400xb4, 0xbf, 0xa5, 0x4d, 0x9b, 0x9f, 0x02, 0x93, 0xc4, 0xe3, 0xe4, 0xe8, 0x42, 0x2d, 0x68,
1410x81, 0x15, 0x0a, 0xeb, 0x84, 0x5b, 0xd6, 0xa8, 0x74, 0xfb, 0x7d, 0x1d, 0xcb, 0x2c, 0xda,
1420x46, 0x2a, 0x76, 0x62, 0xce, 0xbc, 0x5c, 0x9e, 0x8b, 0xe7, 0xcf, 0xbe, 0x78, 0xf5, 0x7c,
1430xeb, 0xb3, 0x3a, 0x9c, 0xaa, 0x6f, 0xcc, 0x72, 0xd1, 0x59, 0xf2, 0x11, 0x23, 0xd6, 0x3f,
1440x48, 0xd1, 0xb7, 0xce, 0xb0, 0xbf, 0xcb, 0xea, 0x80, 0xde, 0x57, 0xd4, 0x5e, 0x97, 0x2f,
1450x75, 0xd1, 0x50, 0x8e, 0x80, 0x2c, 0x66, 0x79, 0xbf, 0x72, 0x4b, 0xbd, 0x8a, 0x81, 0x6c,
1460xd3, 0xe1, 0x01, 0xdc, 0xd2, 0x15, 0x26, 0xc5, 0x36, 0xda, 0x2c, 0x1a, 0xc0, 0x27, 0x94,
1470xed, 0xb7, 0x9b, 0x85, 0x0b, 0x5e, 0x80, 0x97, 0xc5, 0xec, 0x4f, 0xec, 0x88, 0x5d, 0x50,
1480x07, 0x35, 0x47, 0xdc, 0x0b, 0x3b, 0x3d, 0xdd, 0x60, 0xaf, 0xa8, 0x5d, 0x81, 0x38, 0x24,
1490x25, 0x5d, 0x5c, 0x15, 0xd1, 0xde, 0xb3, 0xab, 0xec, 0x05, 0x69, 0xef, 0x83, 0xed, 0x57,
1500x54, 0xb8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xda, 0x9f, 0x2d, 0x7f, 0x36, 0xbb, 0x44,
1510x5a, 0x34, 0xe8, 0x7f, 0xbf, 0x03, 0xeb, 0x00, 0x7f, 0x59, 0x68, 0x22, 0x79, 0xcf, 0x73,
1520x6c, 0x2c, 0x29, 0xa7, 0xa1, 0x5f, 0x38, 0xa1, 0x1d, 0xf0, 0x20, 0x53, 0xe0, 0x1a, 0x63,
1530x14, 0x58, 0x71, 0x10, 0xaa, 0x08, 0x0c, 0x3e, 0x16, 0x1a, 0x60, 0x22, 0x82, 0x7f, 0xba,
1540xa4, 0x43, 0xa0, 0xd0, 0xac, 0x1b, 0xd5, 0x6b, 0x64, 0xb5, 0x14, 0x93, 0x31, 0x9e, 0x53,
1550x50, 0xd0, 0x57, 0x66, 0xee, 0x5a, 0x4f, 0xfb, 0x03, 0x2a, 0x69, 0x58, 0x76, 0xf1, 0x83,
1560xf7, 0x4e, 0xba, 0x8c, 0x42, 0x06, 0x60, 0x5d, 0x6d, 0xce, 0x60, 0x88, 0xae, 0xa4, 0xc3,
1570xf1, 0x03, 0xa5, 0x4b, 0x98, 0xa1, 0xff, 0x67, 0xe1, 0xac, 0xa2, 0xb8, 0x62, 0xd7, 0x6f,
1580xa0, 0x31, 0xb4, 0xd2, 0x77, 0xaf, 0x21, 0x10, 0x06, 0xc6, 0x9a, 0xff, 0x1d, 0x09, 0x17,
1590x0e, 0x5f, 0xf1, 0xaa, 0x54, 0x34, 0x4b, 0x45, 0x8a, 0x87, 0x63, 0xa6, 0xdc, 0xf9, 0x24,
1600x30, 0x67, 0xc6, 0xb2, 0xd6, 0x61, 0x33, 0x69, 0xee, 0x50, 0x61, 0x57, 0x28, 0xe7, 0x7e,
1610xee, 0xec, 0x3a, 0x5a, 0x73, 0x4e, 0xa8, 0x8d, 0xe4, 0x18, 0xea, 0xec, 0x41, 0x64, 0xc8,
1620xe2, 0xe8, 0x66, 0xb6, 0x2d, 0xb6, 0xfb, 0x6a, 0x6c, 0x16, 0xb3, 0xdd, 0x46, 0x43, 0xb9,
1630x73, 0x00, 0x6a, 0x71, 0xed, 0x4e, 0x9d, 0x25, 0x1a, 0xc3, 0x3c, 0x4a, 0x95, 0x15, 0x99,
1640x35, 0x81, 0x14, 0x02, 0xd6, 0x98, 0x9b, 0xec, 0xd8, 0x23, 0x3b, 0x84, 0x29, 0xaf, 0x0c,
1650x99, 0x83, 0xa6, 0x9a, 0x34, 0x4f, 0xfa, 0xe8, 0xd0, 0x3c, 0x4b, 0xd0, 0xfb, 0xb6, 0x68,
1660xb8, 0x9e, 0x8f, 0xcd, 0xf7, 0x60, 0x2d, 0x7a, 0x22, 0xe5, 0x7d, 0xab, 0x65, 0x1b, 0x95,
1670xa7, 0xa8, 0x7f, 0xb6, 0x77, 0x47, 0x7b, 0x5f, 0x8b, 0x12, 0x72, 0xd0, 0xd4, 0x91, 0xef,
1680xde, 0x19, 0x50, 0x3c, 0xa7, 0x8b, 0xc4, 0xa9, 0xb3, 0x23, 0xcb, 0x76, 0xe6, 0x81, 0xf0,
1690xc1, 0x04, 0x8f, 0xa3, 0xb8, 0x54, 0x5b, 0x97, 0xac, 0x19, 0xff, 0x3f, 0x55, 0x27, 0x2f,
1700xe0, 0x1d, 0x42, 0x9b, 0x57, 0xfc, 0x4b, 0x4e, 0x0f, 0xce, 0x98, 0xa9, 0x43, 0x57, 0x03,
1710xbd, 0xe7, 0xc8, 0x94, 0xdf, 0x6e, 0x36, 0x73, 0x32, 0xb4, 0xef, 0x2e, 0x85, 0x7a, 0x6e,
1720xfc, 0x6c, 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xf3, 0xe4, 0x9f, 0x3e, 0xdc, 0x68, 0xf3,
1730xb5, 0xf3, 0x19, 0x80, 0x92, 0x06, 0x99, 0xa2, 0xe8, 0x6f, 0xff, 0x2e, 0x7f, 0xae, 0x42,
1740xa4, 0x5f, 0xfb, 0xd4, 0x0e, 0x81, 0x2b, 0xc3, 0x04, 0xff, 0x2b, 0xb3, 0x74, 0x4e, 0x36,
1750x5b, 0x9c, 0x15, 0x00, 0xc6, 0x47, 0x2b, 0xe8, 0x8b, 0x3d, 0xf1, 0x9c, 0x03, 0x9a, 0x58,
1760x7f, 0x9b, 0x9c, 0xbf, 0x85, 0x49, 0x79, 0x35, 0x2e, 0x56, 0x7b, 0x41, 0x14, 0x39, 0x47,
1770x83, 0x26, 0xaa, 0x07, 0x89, 0x98, 0x11, 0x1b, 0x86, 0xe7, 0x73, 0x7a, 0xd8, 0x7d, 0x78,
1780x61, 0x53, 0xe9, 0x79, 0xf5, 0x36, 0x8d, 0x44, 0x92, 0x84, 0xf9, 0x13, 0x50, 0x58, 0x3b,
1790xa4, 0x6a, 0x36, 0x65, 0x49, 0x8e, 0x3c, 0x0e, 0xf1, 0x6f, 0xd2, 0x84, 0xc4, 0x7e, 0x8e,
1800x3f, 0x39, 0xae, 0x7c, 0x84, 0xf1, 0x63, 0x37, 0x8e, 0x3c, 0xcc, 0x3e, 0x44, 0x81, 0x45,
1810xf1, 0x4b, 0xb9, 0xed, 0x6b, 0x36, 0x5d, 0xbb, 0x20, 0x60, 0x1a, 0x0f, 0xa3, 0xaa, 0x55,
1820x77, 0x3a, 0xa9, 0xae, 0x37, 0x4d, 0xba, 0xb8, 0x86, 0x6b, 0xbc, 0x08, 0x50, 0xf6, 0xcc,
1830xa4, 0xbd, 0x1d, 0x40, 0x72, 0xa5, 0x86, 0xfa, 0xe2, 0x10, 0xae, 0x3d, 0x58, 0x4b, 0x97,
1840xf3, 0x43, 0x74, 0xa9, 0x9e, 0xeb, 0x21, 0xb7, 0x01, 0xa4, 0x86, 0x93, 0x97, 0xee, 0x2f,
1850x4f, 0x3b, 0x86, 0xa1, 0x41, 0x6f, 0x41, 0x26, 0x90, 0x78, 0x5c, 0x7f, 0x30, 0x38, 0x4b,
1860x3f, 0xaa, 0xec, 0xed, 0x5c, 0x6f, 0x0e, 0xad, 0x43, 0x87, 0xfd, 0x93, 0x35, 0xe6, 0x01,
1870xef, 0x41, 0x26, 0x90, 0x99, 0x9e, 0xfb, 0x19, 0x5b, 0xad, 0xd2, 0x91, 0x8a, 0xe0, 0x46,
1880xaf, 0x65, 0xfa, 0x4f, 0x84, 0xc1, 0xa1, 0x2d, 0xcf, 0x45, 0x8b, 0xd3, 0x85, 0x50, 0x55,
1890x7c, 0xf9, 0x67, 0x88, 0xd4, 0x4e, 0xe9, 0xd7, 0x6b, 0x61, 0x54, 0xa1, 0xa4, 0xa6, 0xa2,
1900xc2, 0xbf, 0x30, 0x9c, 0x40, 0x9f, 0x5f, 0xd7, 0x69, 0x2b, 0x24, 0x82, 0x5e, 0xd9, 0xd6,
1910xa7, 0x12, 0x54, 0x1a, 0xf7, 0x55, 0x9f, 0x76, 0x50, 0xa9, 0x95, 0x84, 0xe6, 0x6b, 0x6d,
1920xb5, 0x96, 0x54, 0xd6, 0xcd, 0xb3, 0xa1, 0x9b, 0x46, 0xa7, 0x94, 0x4d, 0xc4, 0x94, 0xb4,
1930x98, 0xe3, 0xe1, 0xe2, 0x34, 0xd5, 0x33, 0x16, 0x07, 0x54, 0xcd, 0xb7, 0x77, 0x53, 0xdb,
1940x4f, 0x4d, 0x46, 0x9d, 0xe9, 0xd4, 0x9c, 0x8a, 0x36, 0xb6, 0xb8, 0x38, 0x26, 0x6c, 0x0e,
1950xff, 0x9c, 0x1b, 0x43, 0x8b, 0x80, 0xcc, 0xb9, 0x3d, 0xda, 0xc7, 0xf1, 0x8a, 0xf2, 0x6d,
1960xb8, 0xd7, 0x74, 0x2f, 0x7e, 0x1e, 0xb7, 0xd3, 0x4a, 0xb4, 0xac, 0xfc, 0x79, 0x48, 0x6c,
1970xbc, 0x96, 0xb6, 0x94, 0x46, 0x57, 0x2d, 0xb0, 0xa3, 0xfc, 0x1e, 0xb9, 0x52, 0x60, 0x85,
1980x2d, 0x41, 0xd0, 0x43, 0x01, 0x1e, 0x1c, 0xd5, 0x7d, 0xfc, 0xf3, 0x96, 0x0d, 0xc7, 0xcb,
1990x2a, 0x29, 0x9a, 0x93, 0xdd, 0x88, 0x2d, 0x37, 0x5d, 0xaa, 0xfb, 0x49, 0x68, 0xa0, 0x9c,
2000x50, 0x86, 0x7f, 0x68, 0x56, 0x57, 0xf9, 0x79, 0x18, 0x39, 0xd4, 0xe0, 0x01, 0x84, 0x33,
2010x61, 0xca, 0xa5, 0xd2, 0xd6, 0xe4, 0xc9, 0x8a, 0x4a, 0x23, 0x44, 0x4e, 0xbc, 0xf0, 0xdc,
2020x24, 0xa1, 0xa0, 0xc4, 0xe2, 0x07, 0x3c, 0x10, 0xc4, 0xb5, 0x25, 0x4b, 0x65, 0x63, 0xf4,
2030x80, 0xe7, 0xcf, 0x61, 0xb1, 0x71, 0x82, 0x21, 0x87, 0x2c, 0xf5, 0x91, 0x00, 0x32, 0x0c,
2040xec, 0xa9, 0xb5, 0x9a, 0x74, 0x85, 0xe3, 0x36, 0x8f, 0x76, 0x4f, 0x9c, 0x6d, 0xce, 0xbc,
2050xad, 0x0a, 0x4b, 0xed, 0x76, 0x04, 0xcb, 0xc3, 0xb9, 0x33, 0x9e, 0x01, 0x93, 0x96, 0x69,
2060x7d, 0xc5, 0xa2, 0x45, 0x79, 0x9b, 0x04, 0x5c, 0x84, 0x09, 0xed, 0x88, 0x43, 0xc7, 0xab,
2070x93, 0x14, 0x26, 0xa1, 0x40, 0xb5, 0xce, 0x4e, 0xbf, 0x2a, 0x42, 0x85, 0x3e, 0x2c, 0x3b,
2080x54, 0xe8, 0x12, 0x1f, 0x0e, 0x97, 0x59, 0xb2, 0x27, 0x89, 0xfa, 0xf2, 0xdf, 0x8e, 0x68,
2090x59, 0xdc, 0x06, 0xbc, 0xb6, 0x85, 0x0d, 0x06, 0x22, 0xec, 0xb1, 0xcb, 0xe5, 0x04, 0xe6,
2100x3d, 0xb3, 0xb0, 0x41, 0x73, 0x08, 0x3f, 0x3c, 0x58, 0x86, 0x63, 0xeb, 0x50, 0xee, 0x1d,
2110x2c, 0x37, 0x74, 0xa9, 0xd3, 0x18, 0xa3, 0x47, 0x6e, 0x93, 0x54, 0xad, 0x0a, 0x5d, 0xb8,
2120x2a, 0x55, 0x5d, 0x78, 0xf6, 0xee, 0xbe, 0x8e, 0x3c, 0x76, 0x69, 0xb9, 0x40, 0xc2, 0x34,
2130xec, 0x2a, 0xb9, 0xed, 0x7e, 0x20, 0xe4, 0x8d, 0x00, 0x38, 0xc7, 0xe6, 0x8f, 0x44, 0xa8,
2140x86, 0xce, 0xeb, 0x2a, 0xe9, 0x90, 0xf1, 0x4c, 0xdf, 0x32, 0xfb, 0x73, 0x1b, 0x6d, 0x92,
2150x1e, 0x95, 0xfe, 0xb4, 0xdb, 0x65, 0xdf, 0x4d, 0x23, 0x54, 0x89, 0x48, 0xbf, 0x4a, 0x2e,
2160x70, 0xd6, 0xd7, 0x62, 0xb4, 0x33, 0x29, 0xb1, 0x3a, 0x33, 0x4c, 0x23, 0x6d, 0xa6, 0x76,
2170xa5, 0x21, 0x63, 0x48, 0xe6, 0x90, 0x5d, 0xed, 0x90, 0x95, 0x0b, 0x7a, 0x84, 0xbe, 0xb8,
2180x0d, 0x5e, 0x63, 0x0c, 0x62, 0x26, 0x4c, 0x14, 0x5a, 0xb3, 0xac, 0x23, 0xa4, 0x74, 0xa7,
2190x6f, 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xa0, 0x28, 0xb7, 0xee, 0x19, 0x38, 0xf1, 0x64,
2200x80, 0x82, 0x43, 0xe1, 0x41, 0x27, 0x1f, 0x1f, 0x90, 0x54, 0x7a, 0xd5, 0x23, 0x2e, 0xd1,
2210x3d, 0xcb, 0x28, 0xba, 0x58, 0x7f, 0xdc, 0x7c, 0x91, 0x24, 0xe9, 0x28, 0x51, 0x83, 0x6e,
2220xc5, 0x56, 0x21, 0x42, 0xed, 0xa0, 0x56, 0x22, 0xa1, 0x40, 0x80, 0x6b, 0xa8, 0xf7, 0x94,
2230xca, 0x13, 0x6b, 0x0c, 0x39, 0xd9, 0xfd, 0xe9, 0xf3, 0x6f, 0xa6, 0x9e, 0xfc, 0x70, 0x8a,
2240xb3, 0xbc, 0x59, 0x3c, 0x1e, 0x1d, 0x6c, 0xf9, 0x7c, 0xaf, 0xf9, 0x88, 0x71, 0x95, 0xeb,
2250x57, 0x00, 0xbd, 0x9f, 0x8c, 0x4f, 0xe1, 0x24, 0x83, 0xc5, 0x22, 0xea, 0xfd, 0xd3, 0x0c,
2260xe2, 0x17, 0x18, 0x7c, 0x6a, 0x4c, 0xde, 0x77, 0xb4, 0x53, 0x9b, 0x4c, 0x81, 0xcd, 0x23,
2270x60, 0xaa, 0x0e, 0x25, 0x73, 0x9c, 0x02, 0x79, 0x32, 0x30, 0xdf, 0x74, 0xdf, 0x75, 0x19,
2280xf4, 0xa5, 0x14, 0x5c, 0xf7, 0x7a, 0xa8, 0xa5, 0x91, 0x84, 0x7c, 0x60, 0x03, 0x06, 0x3b,
2290xcd, 0x50, 0xb6, 0x27, 0x9c, 0xfe, 0xb1, 0xdd, 0xcc, 0xd3, 0xb0, 0x59, 0x24, 0xb2, 0xca,
2300xe2, 0x1c, 0x81, 0x22, 0x9d, 0x07, 0x8f, 0x8e, 0xb9, 0xbe, 0x4e, 0xfa, 0xfc, 0x39, 0x65,
2310xba, 0xbf, 0x9d, 0x12, 0x37, 0x5e, 0x97, 0x7e, 0xf3, 0x89, 0xf5, 0x5d, 0xf5, 0xe3, 0x09,
2320x8c, 0x62, 0xb5, 0x20, 0x9d, 0x0c, 0x53, 0x8a, 0x68, 0x1b, 0xd2, 0x8f, 0x75, 0x17, 0x5d,
2330xd4, 0xe5, 0xda, 0x75, 0x62, 0x19, 0x14, 0x6a, 0x26, 0x2d, 0xeb, 0xf8, 0xaf, 0x37, 0xf0,
2340x6c, 0xa4, 0x55, 0xb1, 0xbc, 0xe2, 0x33, 0xc0, 0x9a, 0xca, 0xb0, 0x11, 0x49, 0x4f, 0x68,
2350x9b, 0x3b, 0x6b, 0x3c, 0xcc, 0x13, 0xf6, 0xc7, 0x85, 0x61, 0x68, 0x42, 0xae, 0xbb, 0xdd,
2360xcd, 0x45, 0x16, 0x29, 0x1d, 0xea, 0xdb, 0xc8, 0x03, 0x94, 0x3c, 0xee, 0x4f, 0x82, 0x11,
2370xc3, 0xec, 0x28, 0xbd, 0x97, 0x05, 0x99, 0xde, 0xd7, 0xbb, 0x5e, 0x22, 0x1f, 0xd4, 0xeb,
2380x64, 0xd9, 0x92, 0xd9, 0x85, 0xb7, 0x6a, 0x05, 0x6a, 0xe4, 0x24, 0x41, 0xf1, 0xcd, 0xf0,
2390xd8, 0x3f, 0xf8, 0x9e, 0x0e, 0xcd, 0x0b, 0x7a, 0x70, 0x6b, 0x5a, 0x75, 0x0a, 0x6a, 0x33,
2400x88, 0xec, 0x17, 0x75, 0x08, 0x70, 0x10, 0x2f, 0x24, 0xcf, 0xc4, 0xe9, 0x42, 0x00, 0x61,
2410x94, 0xca, 0x1f, 0x3a, 0x76, 0x06, 0xfa, 0xd2, 0x48, 0x81, 0xf0, 0x77, 0x60, 0x03, 0x45,
2420xd9, 0x61, 0xf4, 0xa4, 0x6f, 0x3d, 0xd9, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec,
2430x3b, 0xf4, 0x4b, 0xf5, 0x68, 0x52, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5,
2440xa9, 0xb1, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xa5, 0xa9, 0xb1,
2450xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0xeb, 0x54, 0x0b,
2460x75, 0x68, 0x52, 0x07, 0x8c, 0x9a, 0x97, 0x8d, 0x79, 0x70, 0x62, 0x46, 0xef, 0x5c, 0x1b,
2470x95, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x67, 0x4c, 0x1a, 0xb6,
2480xcf, 0xfd, 0x78, 0x53, 0x24, 0xab, 0xb5, 0xc9, 0xf1, 0x60, 0x23, 0xa5, 0xc8, 0x12, 0x87,
2490x6d, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xc7, 0x0c, 0x9a, 0x97, 0xac,
2500xda, 0x36, 0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x47,
2510xed, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8c, 0x7b, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef,
2520x3d, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xdf,
2530x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x53, 0x05, 0x69,
2540x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x27, 0xcc, 0xfb, 0x74,
2550x4b, 0x14, 0x8b, 0x94, 0x8b, 0x75, 0x68, 0x33, 0xc5, 0x08, 0x92, 0x87, 0x8c, 0x9a, 0xb6,
2560xcf, 0x1c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0x89, 0x71, 0x60,
2570x23, 0xc4, 0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xf6, 0x6e, 0x3f, 0xfc, 0x5b, 0x15, 0xa8, 0xd2,
2580x26, 0xaf, 0xbd, 0xf8, 0x72, 0x66, 0x2f, 0xdc, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa,
2590xb7, 0xcd, 0xf9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6f, 0x3d, 0xd9, 0x30, 0xe2, 0x27, 0xcc,
2600xfb, 0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x70, 0x43, 0x04, 0x6b, 0x35, 0xc9, 0xf1,
2610x60, 0x23, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xe6, 0x2f, 0xbd,
2620xf8, 0x72, 0x66, 0x4e, 0x1e, 0xbe, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x1d, 0x99, 0x91, 0xa0,
2630xa3, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93, 0xa4, 0xab, 0xd4, 0x0b, 0x75, 0x49, 0x10, 0xa2,
2640xc6, 0xef, 0x3d, 0xf8, 0x53, 0x24, 0xab, 0xb5, 0xe8, 0x33, 0xe4, 0x4a, 0x16, 0xae, 0xde,
2650x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xb3, 0xc5, 0x08, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0xe1, 0x21,
2660xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x5c, 0x3a, 0xd7, 0x0d, 0x98, 0x93, 0xa4, 0xca,
2670x16, 0xae, 0xde, 0x1f, 0x9d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x72, 0x47, 0x0c,
2680x9a, 0xb6, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87,
2690x6d, 0x39, 0xf0, 0x43, 0x04, 0x8a, 0x96, 0xae, 0xde, 0x3e, 0xdf, 0x1d, 0x99, 0x91, 0xa0,
2700xc2, 0x06, 0x6f, 0x3d, 0xf8, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0x8d, 0x98, 0x93, 0x85, 0x88,
2710x73, 0x45, 0xe9, 0x31, 0xe0, 0x23, 0xa5, 0xa9, 0xd0, 0x03, 0x84, 0x8a, 0x96, 0xae, 0xde,
2720x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xd2, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x82,
2730x67, 0x2d, 0xd8, 0x13, 0xa4, 0xab, 0xd4, 0x0b, 0x94, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20,
2740xa3, 0xa5, 0xc8, 0xf3, 0x45, 0xe9, 0x50, 0x22, 0xc6, 0xef, 0x5c, 0x3a, 0xd7, 0x0d, 0x98,
2750x93, 0x85, 0x88, 0x73, 0x64, 0x4a, 0xf7, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0x0a, 0x96,
2760xae, 0xde, 0x3e, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x78, 0x72,
2770x66, 0x2f, 0xbd, 0xd9, 0x30, 0xc3, 0xe5, 0x48, 0x12, 0x87, 0x8c, 0x7b, 0x55, 0x28, 0xd2,
2780x07, 0x8c, 0x9a, 0x97, 0xac, 0xda, 0x17, 0x8d, 0x79, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x54,
2790x0b, 0x94, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xfc, 0x5b, 0x15, 0xa8, 0xd2, 0x26, 0xaf,
2800xdc, 0x1b, 0xb4, 0xea, 0x37, 0xec, 0x3b, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0x93, 0x85, 0x69,
2810x31, 0xc1, 0xe1, 0x40, 0xe3, 0x25, 0xc8, 0x12, 0x87, 0x8c, 0x9a, 0xb6, 0xcf, 0xfd, 0x59,
2820x11, 0xa0, 0xc2, 0x06, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x37,
2830xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0x95, 0x89, 0x71, 0x41,
2840x00, 0x63, 0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x0f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0x93, 0x85,
2850x69, 0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x9e, 0xbe, 0xdf, 0x3c, 0xfa, 0x57, 0x2c, 0xda,
2860x36, 0xee, 0x3f, 0xfc, 0x5b, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d,
2870x38, 0xf2, 0x47, 0xed, 0x58, 0x13, 0xa4, 0xca, 0xf7, 0x4d, 0xf9, 0x51, 0x01, 0x80, 0x63,
2880x44, 0xeb, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xa9, 0xb1,
2890xe0, 0x42, 0x06, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0x0a, 0x96, 0x8f, 0x7d,
2900x78, 0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0xbc, 0xfa, 0x57, 0x0d,
2910x79, 0x51, 0x01, 0x61, 0x21, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xc1, 0xe1, 0x40, 0x02,
2920x67, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xd6, 0x0f, 0x9c, 0x9b,
2930xb4, 0xcb, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x35, 0xc9, 0xf1,
2940x60, 0x42, 0x06, 0x8e, 0x7f, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xfc, 0x7a, 0x76, 0x6e, 0x5e,
2950x3e, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xc0, 0xe3, 0x44,
2960xeb, 0x54, 0x2a, 0xb7, 0xcd, 0xf9, 0x70, 0x62, 0x27, 0xad, 0xd8, 0x32, 0xc7, 0x0c, 0x7b,
2970x74, 0x4b, 0x14, 0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x39, 0xd1, 0x20,
2980xc2, 0xe7, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0xb2, 0xc7, 0x0c, 0x59, 0x28, 0xf3, 0x9b };
299
300// clang-format off