~ruther/qmk_firmware

ffd8ff642d4257fa588d9f42144d923bd570bbbd — Alexander Tulloh 4 years ago 6edbd84
[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>
D keyboards/oddball/adns.c => keyboards/oddball/adns.c +0 -270
@@ 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();
}

A keyboards/oddball/adns/adns.c => keyboards/oddball/adns/adns.c +219 -0
@@ 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;
}

A keyboards/oddball/adns/adns.h => keyboards/oddball/adns/adns.h +35 -0
@@ 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);

A keyboards/oddball/adns/adns9800_srom_A6.h => keyboards/oddball/adns/adns9800_srom_A6.h +3078 -0
@@ 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,
0x40,
0x21,
0xb4,
0x67,
0x05,
0xa8,
0xe2,
0xf3,
0x72,
0x87,
0x4c,
0x7d,
0xd9,
0x1b,
0x65,
0x97,
0xf3,
0xc2,
0xe3,
0xe4,
0xc8,
0xd2,
0xde,
0xf6,
0xef,
0xdc,
0xbb,
0x44,
0x08,
0x5e,
0xe2,
0x45,
0x27,
0x01,
0xb0,
0xf6,
0x43,
0xe7,
0x3a,
0xf6,
0xdc,
0x9d,
0xed,
0xf3,
0xc5,
0x0c,
0xb8,
0x9c,
0x98,
0x3a,
0xd8,
0x36,
0xee,
0x96,
0x72,
0x67,
0xe7,
0x81,
0x91,
0xd5,
0x05,
0x0a,
0xe0,
0x82,
0xd5,
0x8f,
0xe8,
0xf9,
0xb0,
0xc9,
0xcf,
0x93,
0xe7,
0x04,
0xc5,
0xbc,
0x2b,
0x43,
0x56,
0x7e,
0xe8,
0x67,
0x7c,
0xe5,
0xfb,
0x49,
0xad,
0x5e,
0x9f,
0x25,
0x13,
0xde,
0x6e,
0x6e,
0xe9,
0xf1,
0xec,
0x87,
0x0b,
0x59,
0x81,
0x76,
0x84,
0x76,
0xb3,
0x24,
0xaf,
0x30,
0xfd,
0x27,
0x8b,
0xab,
0xd8,
0x00,
0x8b,
0x9b,
0x0c,
0xd2,
0xb2,
0x4e,
0x5e,
0x9d,
0x1d,
0x96,
0x01,
0x00,
0x67,
0xc1,
0x5f,
0x02,
0x20,
0xfd,
0x45,
0x6a,
0x01,
0x60,
0x58,
0x45,
0xca,
0x47,
0x21,
0x90,
0x5a,
0xc4,
0x43,
0x26,
0x1a,
0xd7,
0xa5,
0x4a,
0xb2,
0x5d,
0x2b,
0x35,
0x49,
0xfb,
0xa5,
0x17,
0x92,
0x21,
0x1e,
0x93,
0x96,
0x67,
0xa2,
0x7e,
0x36,
0x7a,
0xde,
0x5f,
0xbe,
0x7a,
0x58,
0x9d,
0xf8,
0x78,
0xa3,
0xfa,
0xc8,
0xd5,
0x17,
0xf0,
0x21,
0x97,
0x8c,
0x80,
0xb5,
0x4b,
0x3b,
0xbd,
0xbb,
0x41,
0x21,
0xa8,
0x50,
0x67,
0xf7,
0xe7,
0x19,
0x80,
0x10,
0x8e,
0xce,
0x04,
0x18,
0x3f,
0x51,
0x6b,
0x77,
0xd8,
0x9e,
0x16,
0xaf,
0xec,
0xef,
0x48,
0x16,
0x4d,
0x9e,
0x85,
0x38,
0x18,
0x3e,
0xd4,
0x28,
0x87,
0x60,
0x2a,
0xf6,
0x7f,
0x09,
0x86,
0x6f,
0x9c,
0x3c,
0x3a,
0xff,
0xab,
0xd0,
0x61,
0xa2,
0x97,
0x0d,
0x71,
0x94,
0x7e,
0xfd,
0xb9,
0x80,
0x02,
0x89,
0x6a,
0xb3,
0x84,
0x6c,
0x2a,
0x77,
0x62,
0xbe,
0x0b,
0xf4,
0xaf,
0xac,
0x7b,
0x7c,
0x8e,
0xca,
0x01,
0xba,
0x71,
0x78,
0x94,
0xfd,
0xb5,
0x39,
0xa4,
0x4d,
0x2f,
0x78,
0xcf,
0xca,
0x92,
0x0c,
0x1a,
0x99,
0x48,
0x4c,
0x11,
0x96,
0xb5,
0x4e,
0x41,
0x28,
0xe4,
0xa6,
0xfe,
0x4b,
0x72,
0x91,
0xe7,
0xd4,
0xdd,
0x9f,
0x12,
0xe6,
0x29,
0x38,
0xce,
0x45,
0xae,
0x02,
0xb8,
0x24,
0xae,
0xbd,
0xe9,
0x66,
0x08,
0x62,
0xa2,
0x2c,
0x2b,
0x00,
0xe2,
0x23,
0xd9,
0xc4,
0x48,
0xe4,
0xd3,
0xac,
0xbb,
0x34,
0xc7,
0xf0,
0xe3,
0x4f,
0xb9,
0x30,
0xea,
0xa2,
0x12,
0xf1,
0x30,
0x2c,
0x36,
0xde,
0x48,
0xf2,
0xb0,
0x4c,
0x43,
0x3f,
0x2e,
0x58,
0xe4,
0x20,
0xe3,
0x58,
0xcd,
0x31,
0x22,
0xf0,
0xa2,
0x2a,
0xe6,
0x19,
0x90,
0x55,
0x86,
0xf6,
0x55,
0x79,
0xd1,
0xd7,
0x46,
0x2f,
0xc0,
0xdc,
0x99,
0xe8,
0xf3,
0x6a,
0xdf,
0x7f,
0xeb,
0x24,
0x4a,
0x1e,
0x5a,
0x75,
0xde,
0x2f,
0x5c,
0x19,
0x61,
0x03,
0x53,
0x54,
0x6a,
0x3b,
0x18,
0x70,
0xb6,
0x4f,
0xf1,
0x9c,
0x0a,
0x59,
0x9d,
0x19,
0x92,
0x65,
0x8c,
0x83,
0x14,
0x2d,
0x44,
0x8a,
0x75,
0xa9,
0xf5,
0x90,
0xd2,
0x66,
0x4e,
0xfa,
0x69,
0x0f,
0x5b,
0x0b,
0x98,
0x65,
0xc8,
0x11,
0x42,
0x59,
0x7f,
0xdd,
0x1b,
0x75,
0x17,
0x31,
0x4c,
0x75,
0x58,
0xeb,
0x58,
0x63,
0x7d,
0xf2,
0xa6,
0xc2,
0x6e,
0xb7,
0x3f,
0x3e,
0x5e,
0x47,
0xad,
0xb7,
0x04,
0xe8,
0x05,
0xf8,
0xb2,
0xcf,
0x19,
0xf3,
0xd2,
0x85,
0xfe,
0x3e,
0x3e,
0xb1,
0x62,
0x08,
0x2c,
0x10,
0x07,
0x0d,
0x73,
0x90,
0x17,
0xfa,
0x9b,
0x56,
0x02,
0x75,
0xf9,
0x51,
0xe0,
0xe9,
0x1a,
0x7b,
0x9f,
0xb3,
0xf3,
0x98,
0xb8,
0x1c,
0x9c,
0xe1,
0xd5,
0x35,
0xae,
0xc8,
0x60,
0x48,
0x11,
0x09,
0x94,
0x6b,
0xd0,
0x8b,
0x15,
0xbc,
0x05,
0x68,
0xd3,
0x54,
0x8a,
0x51,
0x39,
0x5c,
0x42,
0x76,
0xce,
0xd8,
0xad,
0x89,
0x30,
0xc9,
0x05,
0x1c,
0xcc,
0x94,
0x3f,
0x0f,
0x90,
0x6f,
0x72,
0x2d,
0x85,
0x64,
0x9a,
0xb9,
0x23,
0xf9,
0x0b,
0xc3,
0x7c,
0x39,
0x0f,
0x97,
0x07,
0x97,
0xda,
0x58,
0x48,
0x33,
0x05,
0x23,
0xb8,
0x82,
0xe8,
0xd3,
0x53,
0x89,
0xaf,
0x33,
0x80,
0x22,
0x84,
0x0c,
0x95,
0x5c,
0x67,
0xb8,
0x77,
0x0c,
0x5c,
0xa2,
0x5f,
0x3d,
0x58,
0x0f,
0x27,
0xf3,
0x2f,
0xae,
0x48,
0xbd,
0x0b,
0x6f,
0x54,
0xfb,
0x67,
0x4c,
0xea,
0x32,
0x27,
0xf1,
0xfa,
0xe2,
0xb0,
0xec,
0x0b,
0x15,
0xb4,
0x70,
0xf6,
0x5c,
0xdd,
0x71,
0x60,
0xc3,
0xc1,
0xa8,
0x32,
0x65,
0xac,
0x7a,
0x77,
0x41,
0xe5,
0xa9,
0x6b,
0x11,
0x81,
0xfa,
0x34,
0x8d,
0xfb,
0xc1,
0x80,
0x6e,
0xc4,
0x60,
0x30,
0x07,
0xd4,
0x8b,
0x67,
0xbd,
0xaa,
0x8c,
0x9c,
0x64,
0xac,
0xdb,
0x0b,
0x24,
0x8b,
0x63,
0x6f,
0xe6,
0xbc,
0xe7,
0x33,
0xa4,
0x4a,
0x4c,
0xa7,
0x9f,
0x43,
0x53,
0xd2,
0xbb,
0x8f,
0x43,
0xc7,
0x3d,
0x78,
0x68,
0x3f,
0xa5,
0x3d,
0xca,
0x69,
0x84,
0xa6,
0x97,
0x2d,
0xc0,
0x7d,
0x31,
0x34,
0x55,
0x1d,
0x07,
0xb1,
0x5f,
0x40,
0x5c,
0x93,
0xb0,
0xbc,
0x7c,
0xb0,
0xbc,
0xe7,
0x12,
0xee,
0x6b,
0x2b,
0xd3,
0x4d,
0x67,
0x70,
0x3a,
0x9a,
0xf2,
0x3c,
0x7c,
0x81,
0xfa,
0xd7,
0xd9,
0x90,
0x91,
0x81,
0xb8,
0xb1,
0xf3,
0x48,
0x6a,
0x26,
0x4f,
0x0c,
0xce,
0xb0,
0x9e,
0xfd,
0x4a,
0x3a,
0xaf,
0xac,
0x5b,
0x3f,
0xbf,
0x44,
0x5a,
0xa3,
0x19,
0x1e,
0x4b,
0xe7,
0x36,
0x6a,
0xd7,
0x20,
0xae,
0xd7,
0x7d,
0x3b,
0xe7,
0xff,
0x3a,
0x86,
0x2e,
0xd0,
0x4a,
0x3e,
0xaf,
0x9f,
0x8e,
0x01,
0xbf,
0xf8,
0x4f,
0xc1,
0xe8,
0x6f,
0x74,
0xe1,
0x45,
0xd3,
0xf7,
0x04,
0x6a,
0x4b,
0x9d,
0xec,
0x33,
0x27,
0x76,
0xd7,
0xc5,
0xe1,
0xb0,
0x3b,
0x0e,
0x23,
0xec,
0xf0,
0x86,
0xd2,
0x1a,
0xbf,
0x3d,
0x04,
0x62,
0xb3,
0x6c,
0xb2,
0xeb,
0x17,
0x05,
0xa6,
0x0a,
0x8a,
0x7e,
0x83,
0x1c,
0xb6,
0x37,
0x09,
0xc6,
0x0b,
0x70,
0x3c,
0xb5,
0x93,
0x81,
0xd8,
0x93,
0xa0,
0x5f,
0x1e,
0x08,
0xe2,
0xc6,
0xe5,
0xc9,
0x72,
0xf1,
0xf1,
0xc1,
0xed,
0xd5,
0x58,
0x93,
0x83,
0xf8,
0x65,
0x67,
0x2e,
0x0d,
0xa9,
0xf1,
0x64,
0x12,
0xe6,
0x4c,
0xea,
0x15,
0x3f,
0x8c,
0x1a,
0xb6,
0xbf,
0xf6,
0xb9,
0x52,
0x35,
0x09,
0xb0,
0xe6,
0xf7,
0xcd,
0xf1,
0xa5,
0xaa,
0x81,
0xd1,
0x81,
0x6f,
0xb4,
0xa9,
0x66,
0x1f,
0xfc,
0x48,
0xc0,
0xb6,
0xd1,
0x8b,
0x06,
0x2f,
0xf6,
0xef,
0x1f,
0x0a,
0xe6,
0xce,
0x3a,
0x4a,
0x55,
0xbf,
0x6d,
0xf9,
0x4d,
0xd4,
0x08,
0x45,
0x4b,
0xc3,
0x66,
0x19,
0x92,
0x10,
0xe1,
0x17,
0x8e,
0x28,
0x91,
0x16,
0xbf,
0x3c,
0xee,
0xa3,
0xa6,
0x99,
0x92,
0x10,
0xe1,
0xf6,
0xcc,
0xac,
0xb8,
0x65,
0x0b,
0x43,
0x66,
0xf8,
0xe3,
0xe5,
0x3f,
0x24,
0x89,
0x47,
0x5d,
0x78,
0x43,
0xd0,
0x61,
0x17,
0xbd,
0x5b,
0x64,
0x54,
0x08,
0x45,
0x59,
0x93,
0xf6,
0x95,
0x8a,
0x41,
0x51,
0x62,
0x4b,
0x51,
0x02,
0x30,
0x73,
0xc7,
0x87,
0xc5,
0x4b,
0xa2,
0x97,
0x0f,
0xe8,
0x46,
0x5f,
0x7e,
0x2a,
0xe1,
0x30,
0x20,
0xb0,
0xfa,
0xe7,
0xce,
0x61,
0x42,
0x57,
0x6e,
0x21,
0xf3,
0x7a,
0xec,
0xe3,
0x25,
0xc7,
0x25,
0xf3,
0x67,
0xa7,
0x57,
0x40,
0x00,
0x02,
0xcf,
0x1c,
0x80,
0x77,
0x67,
0xbd,
0x70,
0xa1,
0x19,
0x92,
0x31,
0x75,
0x93,
0x27,
0x27,
0xb6,
0x82,
0xe4,
0xeb,
0x1d,
0x78,
0x48,
0xe7,
0xa5,
0x5e,
0x57,
0xef,
0x64,
0x28,
0x64,
0x1b,
0xf6,
0x11,
0xb2,
0x03,
0x9d,
0xb9,
0x18,
0x02,
0x27,
0xf7,
0xbe,
0x9d,
0x55,
0xfc,
0x00,
0xd2,
0xc7,
0xae,
0xad,
0x0b,
0xc5,
0xe9,
0x42,
0x41,
0x48,
0xd8,
0x32,
0xcf,
0xf6,
0x0f,
0xf5,
0xbc,
0x97,
0xc6,
0x99,
0x47,
0x76,
0xbd,
0x89,
0x06,
0x0f,
0x63,
0x0c,
0x51,
0xd4,
0x5e,
0xea,
0x48,
0xa8,
0xa2,
0x56,
0x1c,
0x79,
0x84,
0x86,
0x40,
0x88,
0x41,
0x76,
0x55,
0xfc,
0xc2,
0xd7,
0xfd,
0xc9,
0xc7,
0x80,
0x61,
0x35,
0xa7,
0x43,
0x20,
0xf7,
0xeb,
0x6c,
0x66,
0x13,
0xb0,
0xec,
0x02,
0x75,
0x3e,
0x4b,
0xaf,
0xb9,
0x5d,
0x40,
0xda,
0xd6,
0x6e,
0x2d,
0x39,
0x54,
0xc2,
0x95,
0x35,
0x54,
0x25,
0x72,
0xe1,
0x78,
0xb8,
0xeb,
0xc1,
0x16,
0x58,
0x0f,
0x9c,
0x9b,
0xb4,
0xea,
0x37,
0xec,
0x3b,
0x11,
0xba,
0xd5,
0x8a,
0xa9,
0xe3,
0x98,
0x00,
0x51,
0x1c,
0x14,
0xe0,
0x40,
0x96,
0xe5,
0xe9,
0xf2,
0x21,
0x22,
0xb1,
0x23,
0x60,
0x78,
0xd3,
0x17,
0xf8,
0x7a,
0xa5,
0xa8,
0xba,
0x20,
0xd3,
0x15,
0x1e,
0x32,
0xe4,
0x5e,
0x15,
0x48,
0xae,
0xa9,
0xe5,
0xb8,
0x33,
0xec,
0xe8,
0xa2,
0x42,
0xac,
0xbf,
0x10,
0x84,
0x53,
0x87,
0x19,
0xb4,
0x5f,
0x76,
0x4d,
0x01,
0x9d,
0x56,
0x74,
0xd9,
0x5c,
0x97,
0xe7,
0x88,
0xea,
0x3a,
0xbf,
0xdc,
0x4c,
0x33,
0x8a,
0x16,
0xb9,
0x5b,
0xfa,
0xd8,
0x42,
0xa7,
0xbb,
0x3c,
0x04,
0x27,
0x78,
0x49,
0x81,
0x2a,
0x5a,
0x7d,
0x7c,
0x23,
0xa8,
0xba,
0xf7,
0x9a,
0x9f,
0xd2,
0x66,
0x3e,
0x38,
0x3c,
0x75,
0xf9,
0xd1,
0x30,
0x26,
0x30,
0x6e,
0x5a,
0x6e,
0xdc,
0x6a,
0x69,
0x32,
0x50,
0x33,
0x47,
0x9e,
0xa4,
0xa8,
0x64,
0x66,
0xf0,
0x8a,
0xe4,
0xfd,
0x27,
0x6f,
0x51,
0x25,
0x8b,
0x43,
0x74,
0xc9,
0x8e,
0xbd,
0x88,
0x31,
0xbe,
0xec,
0x65,
0xd2,
0xcb,
0x8d,
0x5a,
0x13,
0x48,
0x16,
0x8c,
0x61,
0x0b,
0x11,
0xf6,
0xc6,
0x66,
0xae,
0xc3,
0xcc,
0x0c,
0xd2,
0xe1,
0x9f,
0x82,
0x41,
0x3f,
0x56,
0xf9,
0x73,
0xef,
0xdc,
0x30,
0x50,
0xcf,
0xb6,
0x7f,
0xbc,
0xd0,
0xb3,
0x10,
0xab,
0x24,
0xe4,
0xec,
0xad,
0x18,
0x8c,
0x39,
0x2d,
0x30,
0x4c,
0xc5,
0x40,
0x0d,
0xf6,
0xac,
0xd6,
0x18,
0x5d,
0x96,
0xbf,
0x5f,
0x71,
0x75,
0x96,
0x22,
0x97,
0x0f,
0x02,
0x94,
0x6e,
0xa6,
0xae,
0x6d,
0x8f,
0x1e,
0xca,
0x12,
0x9b,
0x2a,
0x1c,
0xce,
0xa9,
0xee,
0xfd,
0x12,
0x8e,
0xfc,
0xed,
0x09,
0x33,
0xba,
0xf4,
0x1a,
0x15,
0xf6,
0x9d,
0x87,
0x16,
0x43,
0x7c,
0x78,
0x57,
0xe1,
0x44,
0xc9,
0xeb,
0x1f,
0x58,
0x4d,
0xc1,
0x49,
0x11,
0x5c,
0xb2,
0x11,
0xa8,
0x55,
0x16,
0xf1,
0xc6,
0x50,
0xe9,
0x87,
0x89,
0xf6,
0xcf,
0xd8,
0x9c,
0x51,
0xa7,
0xbc,
0x5b,
0x31,
0x6d,
0x4d,
0x51,
0xd0,
0x4c,
0xbc,
0x0d,
0x58,
0x2d,
0x7b,
0x88,
0x7a,
0xf9,
0x8e,
0xd6,
0x40,
0x4d,
0xbb,
0xbe,
0xc4,
0xe5,
0x07,
0xfc,
0xd9,
0x7b,
0x6d,
0xa6,
0x42,
0x57,
0x8f,
0x02,
0x94,
0x4f,
0xe4,
0x2a,
0x65,
0xe2,
0x19,
0x5a,
0x50,
0xe1,
0x25,
0x65,
0x4a,
0x60,
0xc2,
0xcd,
0xa8,
0xec,
0x05,
0x2e,
0x87,
0x7b,
0x95,
0xb7,
0x4f,
0xa0,
0x0b,
0x1b,
0x4a,
0x7f,
0x92,
0xc8,
0x90,
0xee,
0x89,
0x1e,
0x10,
0xd2,
0x85,
0xe4,
0x9f,
0x63,
0xc8,
0x12,
0xbb,
0x4e,
0xb8,
0xcf,
0x0a,
0xec,
0x18,
0x4e,
0xe6,
0x7c,
0xb3,
0x33,
0x26,
0xc7,
0x1f,
0xd2,
0x04,
0x23,
0xea,
0x07,
0x0c,
0x5f,
0x90,
0xbd,
0xa7,
0x6a,
0x0f,
0x4a,
0xd6,
0x10,
0x01,
0x3c,
0x12,
0x29,
0x2e,
0x96,
0xc0,
0x4d,
0xbb,
0xbe,
0xe5,
0xa7,
0x83,
0xd5,
0x6a,
0x3c,
0xe3,
0x5b,
0xb8,
0xf2,
0x5c,
0x6d,
0x1f,
0xa6,
0xf3,
0x12,
0x24,
0xf6,
0xd6,
0x3b,
0x10,
0x14,
0x09,
0x07,
0x82,
0xe8,
0x30,
0x6a,
0x99,
0xdc,
0x95,
0x01,
0x9c,
0xd4,
0x68,
0x3b,
0xca,
0x98,
0x12,
0xab,
0x77,
0x25,
0x15,
0x7d,
0x10,
0x32,
0x45,
0x98,
0xcd,
0x7a,
0xdf,
0x71,
0x8a,
0x75,
0xc1,
0x1c,
0xd4,
0x68,
0x25,
0xeb,
0xbb,
0x54,
0x27,
0x6f,
0x2a,
0xf7,
0xb9,
0x98,
0x03,
0x27,
0xde,
0x24,
0xa8,
0xbb,
0x98,
0xc2,
0x84,
0xff,
0x9b,
0x51,
0xd8,
0x53,
0x50,
0xda,
0xf5,
0x88,
0xaa,
0x87,
0x2f,
0xae,
0xd6,
0xea,
0x6b,
0xde,
0xc8,
0xd7,
0xa7,
0x28,
0x65,
0x81,
0xe8,
0xb2,
0x3b,
0x1d,
0x4f,
0x75,
0x8f,
0x9f,
0x7a,
0x74,
0x8e,
0xc1,
0x5f,
0x9a,
0xa8,
0x9d,
0xfa,
0x03,
0xa3,
0x71,
0x9b,
0x37,
0x6d,
0xd5,
0x0b,
0xf5,
0xe1,
0xa1,
0x1b,
0x01,
0x6a,
0xc6,
0x67,
0xaa,
0xea,
0x2c,
0x9d,
0xa4,
0xd2,
0x6e,
0xfc,
0xde,
0x2e,
0x7f,
0x94,
0x69,
0xe5,
0x4a,
0xe0,
0x01,
0x48,
0x3c,
0x6b,
0xf7,
0x1e,
0xb6,
0x0b,
0x5f,
0xf9,
0x2e,
0x07,
0xc5,
0xe8,
0xae,
0x37,
0x1b,
0xbc,
0x3c,
0xd8,
0xd5,
0x0b,
0x91,
0x9e,
0x80,
0x24,
0xf5,
0x06,
0x0c,
0x0e,
0x98,
0x07,
0x96,
0x2d,
0x19,
0xdc,
0x58,
0x93,
0xcc,
0xfb,
0x4e,
0xeb,
0xbd,
0x0f,
0xf5,
0xaf,
0x01,
0xfa,
0xf1,
0x7c,
0x43,
0x8c,
0xb8,
0x56,
0x3e,
0xbe,
0x77,
0x4e,
0x2b,
0xf7,
0xbb,
0xb7,
0x45,
0x47,
0xcd,
0xcc,
0xa6,
0x4c,
0x72,
0x7b,
0x6a,
0x2a,
0x70,
0x13,
0x07,
0xfd,
0xb8,
0x9c,
0x98,
0x3a,
0xd8,
0x23,
0x67,
0x5b,
0x34,
0xd5,
0x14,
0x0c,
0xab,
0x77,
0x1f,
0xf8,
0x3d,
0x5a,
0x9f,
0x92,
0xb7,
0x2c,
0xad,
0x31,
0xde,
0x61,
0x07,
0xb3,
0x6b,
0xf7,
0x38,
0x15,
0x95,
0x46,
0x14,
0x48,
0x53,
0x69,
0x52,
0x66,
0x07,
0x6d,
0x83,
0x71,
0x8a,
0x67,
0x25,
0x20,
0x0f,
0xfe,
0xd7,
0x02,
0xd7,
0x6e,
0x2c,
0xd2,
0x1a,
0x0a,
0x5d,
0xfd,
0x0f,
0x74,
0xe3,
0xa4,
0x36,
0x07,
0x9a,
0xdf,
0xd4,
0x79,
0xbf,
0xef,
0x59,
0xc0,
0x44,
0x52,
0x87,
0x9a,
0x6e,
0x1d,
0x0e,
0xee,
0xde,
0x2e,
0x1a,
0xa9,
0x8f,
0x3a,
0xc9,
0xba,
0xec,
0x99,
0x78,
0x2d,
0x55,
0x6b,
0x14,
0xc2,
0x06,
0xd5,
0xfc,
0x93,
0x53,
0x4d,
0x11,
0x8c,
0xf8,
0xfa,
0x79,
0x7c,
0xa6,
0x64,
0xae,
0x61,
0xb8,
0x7b,
0x94,
0x56,
0xa6,
0x39,
0x78,
0x9a,
0xe5,
0xc7,
0xdf,
0x18,
0x63,
0x23,
0x9c,
0xfa,
0x66,
0xbb,
0xb7,
0x5a,
0x27,
0x4c,
0xd1,
0xa1,
0x83,
0x22,
0xb3,
0x52,
0x49,
0x35,
0xb0,
0x22,
0x83,
0x59,
0x12,
0x00,
0x16,
0x98,
0xdd,
0xad,
0xc2,
0x94,
0xf9,
0xd3,
0x7b,
0x64,
0x7f,
0x44,
0x3e,
0x3c,
0x8b,
0x9a,
0x83,
0x9c,
0x69,
0x6b,
0xe4,
0xdf,
0x9f,
0xed,
0x54,
0x1f,
0xe5,
0x5d,
0x7a,
0x05,
0x82,
0xb3,
0xdd,
0xef,
0xfc,
0x53,
0x96,
0xb0,
0x2c,
0x5a,
0xf8,
0xdf,
0x9c,
0x8b,
0x16,
0x4e,
0xdf,
0xda,
0x4d,
0x09,
0x09,
0x69,
0x50,
0x03,
0x65,
0xd8,
0x73,
0x70,
0xe8,
0x86,
0xbf,
0xbb,
0x35,
0xce,
0xb2,
0x46,
0xcb,
0x02,
0x00,
0x5b,
0xb4,
0xe2,
0xc6,
0x8f,
0x2f,
0x98,
0xaf,
0x87,
0x4b,
0x48,
0x45,
0xed,
0xcc,
0x1d,
0xe6,
0x58,
0xd6,
0xf2,
0x50,
0x25,
0x9f,
0x52,
0xc7,
0xcb,
0x8a,
0x17,
0x9d,
0x5b,
0xe5,
0xc8,
0xd7,
0x72,
0xb7,
0x52,
0xb2,
0xc4,
0x98,
0xe3,
0x7a,
0x17,
0x3e,
0xc6,
0x60,
0xa7,
0x97,
0xb0,
0xcf,
0x18,
0x81,
0x53,
0x84,
0x4c,
0xd5,
0x17,
0x32,
0x03,
0x13,
0x39,
0x51,
0x09,
0x10,
0xe3,
0x77,
0x49,
0x4f,
0x62,
0x01,
0xbf,
0x8c,
0x9a,
0xe0,
0x41,
0x9e,
0x89,
0x74,
0x36,
0xf9,
0x96,
0x86,
0x2e,
0x96,
0x1c,
0x4a,
0xb7,
0x2b,
0x4a,
0x97,
0xbc,
0x99,
0x40,
0xa3,
0xe0,
0x3d,
0xc8,
0xad,
0x2f,
0xdf,
0x4f,
0x2c,
0xc4,
0x69,
0x82,
0x9f,
0x9b,
0x81,
0x0c,
0x61,
0x5c,
0xa5,
0x9d,
0x8c,
0x89,
0xc0,
0x2c,
0xb4,
0x4a,
0x33,
0x4e,
0xeb,
0xa2,
0x56,
0x40,
0xc0,
0xc2,
0x46,
0xaf,
0x6a,
0xfc,
0x67,
0xd1,
0x80,
0x5e,
0xc5,
0x6d,
0x84,
0x43,
0x27,
0x3f,
0x55,
0x15,
0x96,
0x6a,
0xa0,
0xa5,
0xda,
0xb7,
0xff,
0xb7,
0x75,
0x6e,
0x4c,
0x49,
0x91,
0x9d,
0x22,
0xa3,
0x46,
0xea,
0xed,
0x9a,
0x00,
0xe2,
0x32,
0xc3,
0xd6,
0xa9,
0x71,
0x20,
0x55,
0xa3,
0x19,
0xed,
0xf8,
0x4f,
0xa7,
0x12,
0x9c,
0x66,
0x87,
0xaf,
0x4e,
0xb7,
0xf0,
0xdb,
0xbf,
0xef,
0xf0,
0xf6,
0xaf,
0xea,
0xda,
0x09,
0xfe,
0xde,
0x38,
0x5c,
0xa5,
0xa2,
0xdf,
0x99,
0x45,
0xa8,
0xe4,
0xe7,
0x92,
0xac,
0x67,
0xaa,
0x4f,
0xbf,
0x77,
0x3e,
0xa2,
0x40,
0x49,
0x22,
0x4a,
0x1e,
0x3b,
0xaa,
0x70,
0x7f,
0x95,
0xaf,
0x37,
0x4b,
0xfc,
0x99,
0xe2,
0xe0,
0xba,
0xd7,
0x34,
0xce,
0x55,
0x88,
0x5b,
0x84,
0x1b,
0x57,
0xc4,
0x80,
0x03,
0x53,
0xc9,
0x2f,
0x93,
0x04,
0x4d,
0xd5,
0x96,
0xe5,
0x70,
0xa6,
0x6e,
0x63,
0x5d,
0x9d,
0x6c,
0xdb,
0x02,
0x0a,
0xa9,
0xda,
0x8b,
0x53,
0xdc,
0xd9,
0x9a,
0xc5,
0x94,
0x2c,
0x91,
0x92,
0x2a,
0xde,
0xbb,
0x8b,
0x13,
0xb9,
0x19,
0x96,
0x64,
0xcc,
0xf2,
0x64,
0x39,
0xb7,
0x75,
0x49,
0xe9,
0x86,
0xc2,
0x86,
0x62,
0xd9,
0x24,
0xd3,
0x81,
0x35,
0x49,
0xfc,
0xa0,
0xa5,
0xa0,
0x93,
0x05,
0x64,
0xb4,
0x1a,
0x57,
0xce,
0x0c,
0x90,
0x02,
0x27,
0xc5,
0x7a,
0x2b,
0x5d,
0xae,
0x3e,
0xd5,
0xdd,
0x10,
0x7c,
0x14,
0xea,
0x3a,
0x08,
0xac,
0x72,
0x4e,
0x90,
0x3d,
0x3b,
0x7c,
0x86,
0x2e,
0xeb,
0xd4,
0x06,
0x70,
0xe6,
0xc7,
0xfb,
0x5f,
0xbd,
0x18,
0xf4,
0x11,
0xa4,
0x1a,
0x93,
0xc3,
0xbe,
0xd9,
0xfb,
0x26,
0x48,
0x2f,
0x37,
0x3c,
0xd0,
0x03,
0x47,
0x1a,
0xf7,
0x62,
0x19,
0x24,
0x5c,
0xf4,
0xa8,
0x92,
0x20,
0x7a,
0xf2,
0x9e,
0x2a,
0xc5,
0x95,
0xa2,
0xfb,
0xa4,
0xea,
0x85,
0xd8,
0x56,
0xb7,
0x70,
0xd1,
0x60,
0x30,
0xa5,
0x30,
0x82,
0x70,
0xdc,
0x7a,
0x65,
0x8a,
0x36,
0x3f,
0x5b,
0x0c,
0xae,
0x54,
0x7c,
0xd3,
0x57,
0x84,
0x7b,
0x3a,
0x65,
0x18,
0x81,
0xee,
0x05,
0x9b,
0x44,
0x4d,
0xb8,
0xda,
0xa2,
0xa1,
0xc9,
0x15,
0xd3,
0x73,
0x03,
0x0e,
0x43,
0xe9,
0x8e,
0x15,
0xf9,
0xbe,
0xc6,
0xc5,
0x8a,
0xe5,
0xc0,
0x1e,
0xc2,
0x37,
0x9e,
0x2a,
0x26,
0xa5,
0xa0,
0xbd,
0x24,
0x5f,
0xb9,
0xc1,
0xab,
0x34,
0x48,
0xb9,
0x5d,
0x98,
0xb4,
0x65,
0x18,
0xf3,
0x63,
0x19,
0x44,
0x1b,
0x11,
0x16,
0xff,
0xdc,
0xf1,
0x79,
0x08,
0x86,
0x0f,
0x52,
0x98,
0x73,
0xc4,
0x92,
0x90,
0x2b,
0x47,
0x09,
0xd0,
0x43,
0x6c,
0x2f,
0x20,
0xeb,
0xdc,
0xda,
0xc5,
0x08,
0x7b,
0x94,
0x42,
0x30,
0x6a,
0xc7,
0xda,
0x8c,
0xc3,
0x76,
0xa7,
0xa5,
0xcc,
0x62,
0x13,
0x00,
0x60,
0x31,
0x58,
0x44,
0x9b,
0xf5,
0x64,
0x14,
0xf5,
0x11,
0xc5,
0x54,
0x52,
0x83,
0xd4,
0x73,
0x01,
0x16,
0x0e,
0xb3,
0x7a,
0x29,
0x69,
0x35,
0x56,
0xd4,
0xee,
0x8a,
0x17,
0xa2,
0x99,
0x24,
0x9c,
0xd7,
0x8f,
0xdb,
0x55,
0xb5,
0x3e
};

D keyboards/oddball/adns9800_srom_A4.h => keyboards/oddball/adns9800_srom_A4.h +0 -212
@@ 1,212 0,0 @@
#pragma once

#include <avr/pgmspace.h>

const uint16_t firmware_length = 3070;

const uint8_t firmware_data[] PROGMEM = {
0x03, 0xa4, 0x6e, 0x16, 0x6d, 0x89, 0x3e, 0xfe, 0x5f, 0x1c, 0xb8, 0xf2, 0x47, 0x0c, 0x7b,
0x74, 0x6a, 0x56, 0x0f, 0x7d, 0x76, 0x71, 0x4b, 0x0c, 0x97, 0xb6, 0xcf, 0xfd, 0x78, 0x72,
0x66, 0x2f, 0xbd, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2c, 0xb0, 0xe4, 0x32, 0xf1, 0x6a, 0x56,
0x2e, 0xbf, 0xfc, 0x7a, 0x57, 0x0d, 0x79, 0x70, 0x66, 0x46, 0x0e, 0x7f, 0x5d, 0x19, 0x91,
0xaa, 0xc2, 0x0d, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x3a, 0xd7, 0x2c,
0xbb, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0xb2, 0xc7, 0x0c, 0x9a, 0x97, 0x8f, 0x52, 0xfd, 0x0d,
0xb8, 0x41, 0x00, 0x9e, 0x8e, 0x9a, 0x1e, 0x6d, 0x0c, 0xe2, 0xaa, 0x13, 0x93, 0xb8, 0xc1,
0x2a, 0x29, 0xbb, 0x0b, 0xe3, 0x71, 0x08, 0x6d, 0xfd, 0xb6, 0xd9, 0xcf, 0x65, 0x21, 0x27,
0x45, 0x1b, 0xbe, 0xe2, 0x61, 0x86, 0x3c, 0xbf, 0x68, 0x9c, 0xd6, 0x75, 0x01, 0x5e, 0xe0,
0xc6, 0x92, 0x79, 0xf4, 0x6a, 0xa9, 0xbb, 0x2a, 0x79, 0xd0, 0xe1, 0x5c, 0x32, 0xb1, 0x5a,
0x1b, 0xba, 0xaf, 0x11, 0xea, 0x24, 0x6a, 0x83, 0x4f, 0x8d, 0xed, 0x19, 0x62, 0x70, 0x54,
0xfb, 0x0e, 0x1f, 0x83, 0xcc, 0xf0, 0xb7, 0xae, 0x05, 0xd3, 0x42, 0x5d, 0x48, 0xa0, 0x7a,
0x0b, 0x73, 0xb3, 0xc8, 0xa6, 0xb7, 0x1b, 0x08, 0x13, 0x9b, 0x89, 0x44, 0x42, 0xae, 0xd8,
0x6a, 0xba, 0x9b, 0x84, 0x25, 0x8b, 0xa4, 0x5e, 0x0b, 0x85, 0xb0, 0x8f, 0x8d, 0x80, 0x9c,
0xd1, 0x52, 0xc7, 0xcb, 0xff, 0x8d, 0x8b, 0xdd, 0x87, 0xf2, 0x63, 0xca, 0xe7, 0x4f, 0x4a,
0x57, 0x3c, 0xdf, 0xaf, 0xcb, 0x5c, 0xbb, 0x39, 0x0b, 0x01, 0x9c, 0x79, 0x22, 0x15, 0xb8,
0xa0, 0xd3, 0x72, 0x02, 0x35, 0x20, 0x40, 0xe0, 0x17, 0xde, 0x89, 0x88, 0xce, 0xe9, 0x2b,
0x75, 0xba, 0xa0, 0x96, 0x24, 0x1e, 0x71, 0xb5, 0x15, 0x00, 0x61, 0xe0, 0x5c, 0x93, 0x4e,
0xea, 0x53, 0xd0, 0xfc, 0xef, 0xae, 0x2b, 0xeb, 0x8f, 0xc7, 0x69, 0x68, 0xc7, 0xfc, 0x1a,
0x1f, 0x41, 0x0d, 0xd0, 0xc1, 0x03, 0xaf, 0xc9, 0xfd, 0xe4, 0x21, 0x43, 0xc4, 0xef, 0xc2,
0xdd, 0x7b, 0x73, 0xbc, 0xca, 0xf4, 0xa5, 0x2e, 0x83, 0x90, 0x1f, 0x78, 0x41, 0xc3, 0x13,
0x8e, 0x95, 0x0a, 0x57, 0xdf, 0x0a, 0x87, 0x40, 0x2b, 0xd9, 0xba, 0x56, 0x59, 0x9d, 0x2c,
0xb2, 0xb8, 0xb3, 0xfb, 0x77, 0x78, 0x3a, 0xef, 0xbf, 0x2d, 0xc8, 0xb9, 0x94, 0x62, 0x47,
0x92, 0x98, 0x42, 0x23, 0x07, 0xd9, 0x39, 0x46, 0x5e, 0x6f, 0xe0, 0x46, 0x14, 0x0e, 0x3d,
0x74, 0x40, 0x21, 0xb4, 0x67, 0x05, 0xa8, 0xe2, 0x12, 0x93, 0x41, 0xc2, 0x80, 0xb9, 0x56,
0x4b, 0xf9, 0x5a, 0x15, 0x9c, 0x37, 0xc4, 0x4b, 0x05, 0xad, 0x5a, 0xaf, 0xa1, 0x3e, 0xe4,
0x6e, 0xc5, 0x91, 0xb6, 0x75, 0x7d, 0x1b, 0xe4, 0xc5, 0x4d, 0x28, 0x6b, 0xe9, 0xad, 0x20,
0x8b, 0x64, 0x91, 0x57, 0x4f, 0xdf, 0x9a, 0x97, 0x7e, 0xbe, 0x8e, 0xd6, 0xd6, 0x3b, 0x17,
0xf9, 0x19, 0x28, 0xb2, 0x2e, 0x8f, 0x26, 0xb4, 0x9b, 0xe5, 0xde, 0x0f, 0x8d, 0x0a, 0x9a,
0x9d, 0x1b, 0xde, 0x6f, 0xcb, 0x84, 0xba, 0x26, 0xd0, 0x12, 0xef, 0x30, 0x38, 0x43, 0xac,
0xb7, 0xa7, 0xef, 0x09, 0x7c, 0x52, 0x27, 0xfc, 0x2e, 0xab, 0x50, 0xa0, 0x21, 0x40, 0xe7,
0xc1, 0x5f, 0x02, 0x41, 0x84, 0xa8, 0x54, 0xa8, 0x2e, 0x37, 0x6f, 0xd8, 0xb1, 0xa4, 0xd0,
0x75, 0xef, 0x31, 0xca, 0x54, 0x1e, 0x33, 0xad, 0x19, 0xa1, 0x94, 0xbc, 0x1b, 0x34, 0x6c,
0xfb, 0x5f, 0xcc, 0x45, 0x76, 0xc8, 0x96, 0xce, 0x1c, 0x3a, 0x0e, 0x77, 0xed, 0xd8, 0xd2,
0x96, 0xac, 0x77, 0x30, 0xe1, 0xef, 0xb0, 0x33, 0xf0, 0x6e, 0x3d, 0xce, 0x5e, 0x6d, 0xde,
0x8a, 0xdc, 0x9b, 0x91, 0x63, 0x2a, 0x95, 0x20, 0x0d, 0xfd, 0x78, 0xba, 0xcb, 0x15, 0x43,
0xc9, 0x20, 0x96, 0x83, 0x06, 0xd9, 0x11, 0xf3, 0xe2, 0x13, 0xcf, 0x9c, 0x91, 0x7f, 0x33,
0x46, 0xa7, 0xe2, 0xd3, 0x75, 0xff, 0x4f, 0x0c, 0x0c, 0xaf, 0xcd, 0xa6, 0x9c, 0xa6, 0x73,
0xe2, 0x6d, 0x17, 0x16, 0xb5, 0x99, 0x80, 0x35, 0xd9, 0x61, 0xf3, 0x48, 0x23, 0xff, 0xae,
0x53, 0x89, 0xfa, 0x55, 0x1c, 0x37, 0xa5, 0xe8, 0x62, 0x12, 0xb2, 0x22, 0x04, 0xed, 0x42,
0xb6, 0x65, 0xc4, 0x41, 0x42, 0x72, 0xca, 0x7e, 0x5e, 0x2f, 0x69, 0x46, 0xef, 0xbd, 0x7e,
0xdf, 0x35, 0x1e, 0x5b, 0x77, 0xaf, 0x8d, 0x39, 0xf8, 0xa7, 0xd8, 0x31, 0x00, 0xd3, 0x85,
0x66, 0xd5, 0xcd, 0x59, 0xd6, 0x5e, 0x9f, 0xb2, 0x3f, 0x09, 0xd1, 0xc4, 0x5b, 0x74, 0x62,
0xd3, 0x30, 0x35, 0xf3, 0xe3, 0x7d, 0x7f, 0xab, 0x38, 0xc2, 0x33, 0x42, 0xd0, 0x67, 0xd0,
0xf4, 0xcf, 0x97, 0xec, 0x35, 0x31, 0xfe, 0x94, 0x9c, 0xa1, 0x66, 0x91, 0xc8, 0x05, 0x45,
0x19, 0x85, 0x0f, 0x4a, 0xb0, 0x3a, 0x20, 0x44, 0xa4, 0x6b, 0x33, 0x0c, 0xa6, 0xb4, 0x4c,
0x46, 0x30, 0x15, 0x2d, 0xbb, 0x04, 0x3c, 0x9d, 0x48, 0xf6, 0x84, 0x9a, 0x62, 0x07, 0xe9,
0x6c, 0x8f, 0xde, 0x29, 0x28, 0x5a, 0x17, 0xec, 0x56, 0xf3, 0xc4, 0xe0, 0x86, 0x2f, 0xb5,
0x1c, 0x8f, 0xaa, 0xc6, 0xc0, 0xcf, 0x0d, 0xcf, 0x1d, 0x4f, 0xb2, 0xbf, 0x26, 0x5c, 0x7c,
0x8d, 0xd3, 0xe4, 0x56, 0xd1, 0xe8, 0x90, 0x94, 0x6a, 0xba, 0x27, 0xba, 0xf7, 0xba, 0x39,
0xc8, 0x08, 0x03, 0x25, 0x7f, 0x16, 0x8f, 0x61, 0xbf, 0xdf, 0x45, 0x88, 0x7d, 0x90, 0x80,
0x55, 0x58, 0x72, 0x4f, 0xf8, 0xd0, 0x94, 0xbb, 0x55, 0x2a, 0x47, 0x4f, 0xaa, 0x87, 0x2d,
0xd4, 0xe7, 0xaf, 0x08, 0x33, 0xc9, 0xec, 0x0b, 0x5b, 0xb8, 0x53, 0x27, 0x2e, 0xfb, 0xad,
0x69, 0xb6, 0x53, 0x64, 0x48, 0x13, 0x41, 0xf8, 0x02, 0x06, 0x6f, 0xb8, 0xcc, 0x64, 0xec,
0x65, 0x65, 0x7e, 0xdf, 0x3f, 0x1e, 0xe1, 0xee, 0xde, 0x3c, 0x1a, 0xe8, 0x0f, 0xf0, 0x2c,
0xea, 0x6e, 0x52, 0x77, 0x34, 0x41, 0xa1, 0xcc, 0x72, 0x8f, 0x6e, 0x9c, 0x3b, 0x8d, 0x39,
0xdf, 0xd4, 0x08, 0x24, 0xba, 0x36, 0xc7, 0x09, 0xf2, 0xf1, 0xa2, 0xd1, 0xe0, 0xa3, 0x6a,
0x5c, 0xc7, 0xb2, 0x0d, 0x1c, 0xfb, 0x5f, 0xc8, 0x86, 0xd8, 0x3e, 0x1c, 0xb7, 0x1f, 0x2d,
0xd8, 0xf2, 0xcd, 0x52, 0xeb, 0xde, 0x50, 0x14, 0xb7, 0xc7, 0xa2, 0x8b, 0x78, 0x70, 0x11,
0x87, 0x1a, 0xc5, 0xb8, 0xe5, 0x5e, 0xa5, 0xc9, 0x94, 0x22, 0x66, 0x7b, 0x8b, 0x74, 0xab,
0x85, 0x28, 0x95, 0x90, 0x6e, 0x07, 0xdd, 0x79, 0x57, 0xb3, 0x75, 0xc8, 0x18, 0x67, 0x39,
0x06, 0x21, 0x55, 0xba, 0xba, 0xda, 0xf9, 0x3b, 0xe9, 0x5d, 0xc9, 0x1f, 0x6f, 0x61, 0x3b,
0xc2, 0x7e, 0x3d, 0x07, 0xa6, 0x84, 0x91, 0xb7, 0x63, 0x7e, 0x5f, 0xfc, 0xd1, 0x7d, 0x08,
0xdd, 0x79, 0x07, 0xe1, 0x9e, 0x11, 0x25, 0xe8, 0x10, 0x05, 0x66, 0xfa, 0xca, 0xc3, 0x41,
0x01, 0x27, 0x54, 0xd2, 0x46, 0xae, 0xe3, 0xff, 0x43, 0xae, 0x8d, 0x0e, 0x31, 0x13, 0x1f,
0x95, 0x79, 0x82, 0x86, 0x7e, 0xfb, 0xd4, 0x17, 0x57, 0xb8, 0x25, 0xe7, 0x1d, 0x18, 0x8f,
0x06, 0x1a, 0xe5, 0xef, 0x55, 0x28, 0x72, 0x42, 0xae, 0xdf, 0x9e, 0xbb, 0x14, 0xab, 0xd8,
0x36, 0x4f, 0x46, 0x4b, 0x35, 0x92, 0x64, 0x6d, 0xbb, 0x60, 0xc2, 0x0b, 0x6f, 0x57, 0x5e,
0x3a, 0x8f, 0x3d, 0xcb, 0xe5, 0xda, 0x6c, 0x5c, 0x85, 0x8f, 0x9d, 0xa6, 0x7e, 0x1e, 0x49,
0x1a, 0xcc, 0xc9, 0xec, 0x04, 0xab, 0x35, 0xf2, 0x9b, 0xe7, 0xb3, 0x52, 0xb1, 0x1c, 0xc1,
0xfe, 0x5c, 0x0b, 0xf5, 0x72, 0x0b, 0xec, 0x8e, 0xcd, 0x67, 0x98, 0xbf, 0xa5, 0x28, 0xca,
0x48, 0x9b, 0x60, 0x1c, 0xee, 0x00, 0xde, 0x01, 0xbc, 0xa4, 0x02, 0xd2, 0x19, 0xb6, 0x05,
0xd6, 0x52, 0x78, 0xdb, 0x20, 0xbd, 0x3f, 0x95, 0x97, 0xb1, 0x59, 0x3d, 0x9d, 0x83, 0xc2,
0xfd, 0x23, 0xa5, 0xfd, 0xd8, 0x20, 0x92, 0x27, 0xee, 0x3c, 0xe9, 0x5a, 0x61, 0x11, 0xe1,
0x31, 0xb4, 0x4c, 0xb4, 0xa9, 0xe2, 0x6d, 0x2e, 0xae, 0x5f, 0x37, 0x8e, 0x07, 0xfd, 0xed,
0x85, 0x07, 0x79, 0x43, 0x7e, 0xfa, 0xd6, 0x03, 0xe8, 0x5b, 0x65, 0x2a, 0xe4, 0xf9, 0x36,
0x9e, 0xff, 0x53, 0x6d, 0x51, 0x50, 0x61, 0x72, 0x18, 0xcd, 0x3d, 0xe4, 0xb6, 0x27, 0x10,
0x4a, 0xdd, 0xfd, 0xa3, 0x36, 0x67, 0xac, 0xc7, 0x85, 0x1c, 0xd3, 0xe7, 0x17, 0x74, 0xe2,
0x8e, 0xee, 0xa6, 0xf4, 0xb6, 0x86, 0x24, 0xcf, 0x40, 0xdf, 0x35, 0x08, 0x0f, 0x55, 0xdd,
0x51, 0xe9, 0x7c, 0x39, 0x78, 0x5c, 0xdf, 0x20, 0x2a, 0xeb, 0xed, 0x35, 0x10, 0x26, 0x98,
0x77, 0x69, 0x4e, 0x51, 0x7a, 0xb2, 0x9f, 0x1d, 0xbc, 0x06, 0xcd, 0xcf, 0x4d, 0xb9, 0xfa,
0xb7, 0xaf, 0x6a, 0x07, 0x0c, 0x96, 0x42, 0x57, 0x6c, 0x3d, 0xa5, 0xfe, 0x91, 0xe3, 0x76,
0x9f, 0xdd, 0x3c, 0x83, 0x25, 0xab, 0x24, 0x89, 0x47, 0x7c, 0xba, 0xd7, 0x7d, 0x72, 0x90,
0x80, 0xb0, 0x03, 0xa4, 0xef, 0x04, 0x0a, 0x9e, 0x5a, 0x14, 0x1c, 0xab, 0x75, 0x47, 0x05,
0xcb, 0xa2, 0x97, 0x0d, 0x6a, 0xa5, 0x7c, 0xa4, 0x40, 0x90, 0xe2, 0x6c, 0xfa, 0xd4, 0xbd,
0x69, 0xd0, 0x06, 0x53, 0x67, 0xfa, 0xe7, 0xcc, 0x06, 0x42, 0x45, 0xbe, 0xbd, 0x6f, 0x3e,
0x48, 0x70, 0xf5, 0x2b, 0x83, 0xc7, 0xba, 0x54, 0x9c, 0xab, 0x54, 0x1f, 0x81, 0xe2, 0x11,
0x82, 0x51, 0x02, 0x51, 0x63, 0x13, 0x86, 0x38, 0xb1, 0x56, 0x0c, 0x4d, 0x68, 0xf3, 0x53,
0x1d, 0xfb, 0xe3, 0x15, 0xe8, 0x42, 0xf3, 0x27, 0x9b, 0xa5, 0x4a, 0x86, 0x90, 0xe1, 0x17,
0xdc, 0x99, 0xe2, 0x5c, 0x79, 0xc6, 0x5f, 0x7e, 0x33, 0xc0, 0x41, 0xb6, 0x9e, 0xfc, 0x10,
0x8a, 0xf4, 0xfd, 0xe9, 0xd2, 0x52, 0x53, 0x54, 0x89, 0x04, 0xbd, 0x69, 0xd2, 0x54, 0x32,
0x96, 0xec, 0x44, 0x08, 0xc3, 0x86, 0x10, 0xd1, 0x3e, 0x32, 0xb5, 0x4f, 0x52, 0x49, 0x58,
0x49, 0xf2, 0x8d, 0x83, 0x89, 0xf3, 0x24, 0x83, 0x65, 0x72, 0x53, 0xaf, 0x2d, 0x90, 0x61,
0x99, 0x92, 0x31, 0x75, 0x93, 0x46, 0xe5, 0xd3, 0x48, 0x11, 0x01, 0xc9, 0x10, 0x98, 0x66,
0x86, 0x79, 0x19, 0x73, 0x7d, 0xda, 0xa1, 0xb0, 0x41, 0x9e, 0xcd, 0xdc, 0xc2, 0x66, 0x86,
0xdd, 0xb8, 0xc9, 0xe3, 0xe7, 0x80, 0x96, 0xf5, 0x38, 0x72, 0xa5, 0xda, 0xe5, 0x38, 0x13,
0x57, 0x2b, 0xbd, 0x32, 0xc7, 0x44, 0xe0, 0xe3, 0x2d, 0xed, 0x54, 0x40, 0x74, 0x9d, 0x02,
0x55, 0x38, 0x45, 0x89, 0x6f, 0x14, 0x40, 0xf6, 0x7b, 0x41, 0x1e, 0x04, 0xdb, 0xa4, 0xd9,
0xf3, 0x90, 0xae, 0x10, 0xc9, 0xc3, 0x72, 0x5d, 0x0d, 0x01, 0x51, 0xf1, 0xd1, 0x96, 0x43,
0xc6, 0x1a, 0x98, 0x3d, 0xbd, 0xcd, 0xdf, 0x44, 0x82, 0xd0, 0x17, 0xa2, 0x9e, 0x6c, 0x0c,
0x2f, 0x46, 0xeb, 0xd8, 0x4a, 0xce, 0xfe, 0xbe, 0xcd, 0xf9, 0xd4, 0xe3, 0x36, 0xf3, 0xd8,
0x1c, 0x00, 0x24, 0xf2, 0xac, 0x03, 0x11, 0xb6, 0x18, 0x8f, 0x9c, 0xba, 0xf6, 0x4f, 0xfd,
0x78, 0x72, 0x83, 0xbf, 0x3e, 0x5c, 0x24, 0xf9, 0x4d, 0xea, 0x85, 0x74, 0x25, 0xe3, 0x46,
0x7b, 0x5e, 0xfe, 0xbd, 0xbf, 0x5e, 0x68, 0x51, 0xe5, 0x53, 0x85, 0x9a, 0x03, 0x4c, 0x09,
0xf0, 0x6b, 0xc2, 0x97, 0xfc, 0xcc, 0x96, 0x2c, 0xaf, 0xf7, 0x8c, 0x26, 0xd8, 0xc7, 0xfc,
0xda, 0x1f, 0x0e, 0x0f, 0x39, 0x1a, 0xb2, 0x0a, 0x98, 0x1a, 0x15, 0xdc, 0x3e, 0x4b, 0x9e,
0x9d, 0x40, 0x3e, 0x71, 0x5b, 0x66, 0xc3, 0x88, 0xf8, 0x57, 0x14, 0x06, 0xc7, 0x2c, 0xcd,
0x31, 0x8e, 0x1e, 0x88, 0x79, 0x9f, 0x33, 0x94, 0xea, 0x21, 0x08, 0x0d, 0x35, 0x7d, 0xa2,
0x57, 0x46, 0xe3, 0x0f, 0xb9, 0xa9, 0xbc, 0xd2, 0x06, 0xb8, 0xfa, 0xf9, 0xb0, 0xf3, 0xc3,
0x8a, 0x38, 0x82, 0x06, 0x7f, 0xd9, 0xce, 0x92, 0xa2, 0x9e, 0xfc, 0x2a, 0xc8, 0x51, 0xb7,
0x7d, 0xdb, 0x47, 0x37, 0xaf, 0x8b, 0xb8, 0x6d, 0x70, 0x21, 0x02, 0x63, 0x5e, 0xbd, 0x38,
0xf1, 0xe1, 0x9f, 0xe3, 0xe2, 0x79, 0x3b, 0x42, 0x05, 0xe2, 0xc6, 0x13, 0x7a, 0xe2, 0x91,
0x73, 0xe2, 0x79, 0x8b, 0x2f, 0x7f, 0x88, 0x02, 0x06, 0x4e, 0xb8, 0x66, 0xb8, 0xc0, 0xc4,
0x3b, 0x1c, 0x3e, 0x96, 0x0f, 0xbb, 0x7f, 0xe8, 0x85, 0x5b, 0xb2, 0xf6, 0xa7, 0x48, 0x5b,
0x95, 0x83, 0x57, 0xe0, 0xe8, 0x22, 0x67, 0x07, 0x3c, 0x27, 0x65, 0x66, 0xe8, 0x84, 0xab,
0xea, 0xf5, 0xb5, 0x00, 0xec, 0xa4, 0xa3, 0xe8, 0x25, 0x77, 0xd1, 0x81, 0x9c, 0x87, 0xd3,
0x1a, 0x31, 0x58, 0xa4, 0x0a, 0xa8, 0x71, 0x9c, 0x52, 0x88, 0x4d, 0x50, 0xff, 0xdb, 0x41,
0x81, 0x04, 0xc3, 0x84, 0xaa, 0x72, 0x79, 0x2f, 0x9b, 0x2d, 0x2f, 0x1c, 0xa5, 0x6b, 0x68,
0x9b, 0x3b, 0x6b, 0x1c, 0x67, 0xeb, 0x42, 0xe0, 0xe3, 0x2c, 0x7b, 0x52, 0x8e, 0xc1, 0x7e,
0xd8, 0xab, 0x02, 0x46, 0xd1, 0x83, 0x38, 0x1a, 0x18, 0xad, 0x90, 0x7f, 0xdb, 0x22, 0xc1,
0x80, 0xea, 0xf7, 0x67, 0x1d, 0xa7, 0xb2, 0x40, 0xdb, 0xc3, 0xc4, 0xd5, 0x8b, 0x49, 0xf8,
0xdc, 0x25, 0x80, 0x7e, 0xfa, 0x64, 0xac, 0x36, 0x4d, 0x74, 0x6f, 0x3e, 0x57, 0x23, 0xb4,
0x49, 0x7c, 0x6f, 0x3e, 0x7c, 0xa7, 0x34, 0xb7, 0x6b, 0x66, 0xf8, 0xd1, 0x69, 0x6d, 0x83,
0xc5, 0x8a, 0xe2, 0x42, 0x3f, 0x8b, 0x5e, 0x5a, 0xd5, 0xcd, 0x47, 0x64, 0xeb, 0x4e, 0xef,
0x62, 0x19, 0x37, 0xd3, 0x8e, 0x68, 0x51, 0x4a, 0x96, 0xbb, 0x5b, 0xa0, 0x34, 0xd8, 0xb4,
0xf4, 0xb0, 0x99, 0x53, 0xb1, 0x70, 0xc3, 0x1d, 0x6e, 0x2b, 0x03, 0x76, 0xc9, 0x00, 0x0b,
0x10, 0xca, 0xb7, 0xf3, 0xbe, 0x4b, 0xe2, 0xb4, 0x6c, 0x4a, 0x9f, 0x59, 0x39, 0x30, 0xc7,
0xc3, 0x88, 0x38, 0x63, 0xc4, 0xcf, 0xd1, 0xfd, 0xf0, 0x6d, 0xfe, 0x68, 0x92, 0x98, 0x11,
0x7d, 0x90, 0x0c, 0x64, 0x23, 0xe8, 0x25, 0x77, 0xd1, 0x81, 0x75, 0xa4, 0xf4, 0x35, 0x6f,
0xe4, 0x9c, 0x7a, 0x48, 0xd0, 0xde, 0x37, 0x42, 0xf8, 0x5b, 0xe9, 0x16, 0xba, 0x16, 0x4b,
0x7c, 0xdb, 0x2c, 0x0e, 0xa0, 0xbc, 0x5c, 0x82, 0x71, 0xa0, 0x9d, 0x3a, 0x0a, 0x7e, 0xd0,
0xdc, 0x93, 0x79, 0xf6, 0x78, 0xb5, 0x89, 0xd9, 0x70, 0x5d, 0xe0, 0x9d, 0xe7, 0xea, 0xee,
0x88, 0x52, 0x18, 0x11, 0x7d, 0xf1, 0xce, 0xc1, 0x69, 0x8d, 0x3f, 0xea, 0x51, 0xc1, 0x49,
0xb1, 0xc4, 0xa6, 0xf0, 0xdc, 0xbd, 0x61, 0xb7, 0x2c, 0x85, 0x4a, 0xcb, 0xdd, 0x96, 0x50,
0x8b, 0x68, 0xf7, 0x7e, 0xb9, 0x1c, 0x19, 0xfb, 0x5c, 0x79, 0xf8, 0x7d, 0xe9, 0xf3, 0x0e,
0xc7, 0x6e, 0x1c, 0x67, 0xb4, 0xb7, 0x4a, 0xc5, 0xbe, 0x3c, 0x8c, 0x94, 0x36, 0x02, 0x8f,
0x81, 0x57, 0xe7, 0x4b, 0xd6, 0x2b, 0x10, 0xbe, 0x3c, 0x97, 0xbb, 0x41, 0x88, 0x6f, 0x13,
0xe6, 0x27, 0x13, 0x4b, 0xd5, 0x44, 0xa9, 0xd9, 0x2d, 0xcd, 0x51, 0x91, 0x03, 0x14, 0xd5,
0x6b, 0x3d, 0xb5, 0x98, 0xf0, 0x09, 0xaa, 0x42, 0x8e, 0x82, 0xe8, 0xf1, 0x36, 0xec, 0xb5,
0x48, 0x5f, 0x9f, 0xca, 0x16, 0x5a, 0x3f, 0x4d, 0xbb, 0xa6, 0xd4, 0x08, 0x1a, 0xfb, 0xe5,
0xeb, 0x40, 0x04, 0xe8, 0x40, 0x84, 0xc4, 0x8e, 0x74, 0xae, 0x47, 0x4d, 0xfc, 0xb5, 0x91,
0xe2, 0x33, 0xf2, 0xf7, 0xae, 0xcd, 0x10, 0x47, 0xb1, 0x4b, 0xe2, 0xa2, 0x8d, 0x7c, 0x2c,
0x32, 0x6f, 0xdd, 0xc4, 0xc2, 0xf1, 0x09, 0x56, 0x2d, 0x1e, 0x9d, 0x7d, 0x67, 0x32, 0x61,
0x7f, 0x12, 0xe4, 0x3f, 0xfa, 0xe2, 0x7d, 0x7b, 0xd4, 0x67, 0x4e, 0x7f, 0x14, 0x6a, 0x6c,
0x8e, 0x74, 0x9b, 0xbc, 0x3d, 0xc4, 0x70, 0xc4, 0x37, 0xd5, 0x60, 0xe0, 0x87, 0xbd, 0xb8,
0x1a, 0x75, 0x9d, 0x7a, 0x80, 0xc1, 0xa9, 0x1f, 0xad, 0x7b, 0x27, 0xe5, 0x4c, 0xb0, 0x06,
0xd0, 0xfb, 0x1c, 0x5a, 0xeb, 0xbd, 0x2e, 0x96, 0x49, 0x13, 0x43, 0x06, 0x8b, 0xcb, 0x6a,
0xf0, 0x5d, 0x56, 0x6c, 0x4e, 0x18, 0x26, 0xd4, 0xc8, 0x53, 0x48, 0x70, 0xe2, 0x0f, 0x9c,
0xa1, 0x35, 0x01, 0x96, 0xc7, 0x0b, 0xc9, 0x4b, 0xd3, 0x19, 0xe8, 0x5a, 0x75, 0xad, 0xc8,
0x52, 0xce, 0x3c, 0x2e, 0xfd, 0x5f, 0x04, 0xcf, 0x9e, 0xd6, 0x33, 0xdb, 0x08, 0x34, 0xba,
0x34, 0x9b, 0xf4, 0x25, 0xaa, 0x7f, 0x52, 0x37, 0x4f, 0x8b, 0x94, 0x95, 0x94, 0x2d, 0x88,
0x10, 0xd1, 0x05, 0x07, 0xcf, 0xd4, 0x04, 0xdb, 0x95, 0xbe, 0x36, 0xd0, 0x1c, 0x1c, 0xa4,
0x85, 0x0a, 0x02, 0x80, 0xde, 0xb1, 0x1b, 0x56, 0xaf, 0x51, 0x22, 0xa7, 0xa4, 0x4a, 0x2c,
0x2f, 0x17, 0x7c, 0x13, 0x4c, 0x36, 0xad, 0x90, 0x8c, 0xea, 0xd4, 0x58, 0x3a, 0xca, 0xea,
0x1d, 0x5c, 0x6c, 0x93, 0xad, 0x59, 0xed, 0xb1, 0x17, 0xa4, 0x22, 0x95, 0x67, 0xbe, 0xbb,
0x25, 0xaf, 0x65, 0xc8, 0xe5, 0x90, 0xe1, 0x17, 0xdc, 0x7a, 0x47, 0xe9, 0x8f, 0xc3, 0xc3,
0x5a, 0xdc, 0x20, 0x20, 0x4a, 0x09, 0xfc, 0x39, 0x51, 0x29, 0x31, 0xfb, 0xa0, 0x0a, 0x61,
0x08, 0x9b, 0xb9, 0xb3, 0x6c, 0x95, 0xc5, 0x94, 0x00, 0x66, 0xf1, 0xb9, 0x79, 0x90, 0x7f,
0x95, 0x5f, 0x55, 0xe1, 0x13, 0x6b, 0x87, 0xa8, 0x62, 0x21, 0x98, 0xf2, 0x57, 0x19, 0x92,
0x10, 0xb3, 0x24, 0x81, 0x12, 0x21, 0xff, 0xd6, 0xf9, 0x73, 0x71, 0xc2, 0x62, 0x09, 0x31,
0xeb, 0xe0, 0x7a, 0x35, 0x60, 0x8d, 0xc9, 0xb1, 0xe5, 0xa7, 0x8b, 0xca, 0xbc, 0x2d, 0xfa,
0x63, 0xc7, 0x68, 0x1d, 0x19, 0xb5, 0x61, 0x78, 0xd0, 0x8b, 0xdb, 0xc0, 0x39, 0x22, 0x55,
0x6a, 0x28, 0xc2, 0x52, 0x1e, 0x6b, 0xf7, 0x1d, 0xb6, 0xfa, 0x4f, 0xcf, 0x27, 0x7c, 0xaf,
0x7f, 0x0c, 0x96, 0xba, 0xce, 0x2a, 0x54, 0x59, 0x5b, 0x20, 0xfb, 0x42, 0x87, 0x44, 0xd9,
0x2e, 0x10, 0x43, 0xab, 0x58, 0x92, 0xb6, 0x8d, 0x78, 0xf3, 0xa3, 0xde, 0x0e, 0x07, 0x75,
0x68, 0x52, 0x26, 0x3f, 0x3d, 0xec, 0xd0, 0x36, 0xdf, 0x1a, 0x16, 0x88, 0x5f, 0xbd, 0x1c,
0x4d, 0x9e, 0x27, 0x4c, 0x12, 0x07, 0x0d, 0x2b, 0xb1, 0xdc, 0x00, 0x45, 0x54, 0x3d, 0xfc,
0xcf, 0xfa, 0xc9, 0x06, 0x4b, 0x08, 0x64, 0xac, 0x8d, 0x17, 0x4d, 0xdf, 0x83, 0x24, 0xfb,
0xf6, 0x9e, 0x5f, 0xf9, 0x0f, 0x8d, 0x07, 0x18, 0xb1, 0xb2, 0x37, 0xd2, 0x66, 0x9c, 0x82,
0x09, 0x75, 0x52, 0x5b, 0x19, 0x74, 0x59, 0xa3, 0x64, 0x6d, 0x17, 0x93, 0x3a, 0x13, 0xd2,
0xda, 0x97, 0xa4, 0x2b, 0x55, 0x7a, 0x32, 0xf9, 0x2f, 0x9b, 0xaa, 0x87, 0x6d, 0xce, 0x1d,
0x07, 0x9a, 0x52, 0xfa, 0x40, 0xc5, 0x20, 0x43, 0xcc, 0xa8, 0xc3, 0x84, 0x2c, 0x44, 0x8b,
0x44, 0x88, 0x62, 0xe7, 0x68, 0x4c, 0x2a, 0x69, 0xa7, 0xcf, 0x6f, 0x4d, 0x06, 0xed, 0x8a,
0x8f, 0x9a, 0x62, 0xca, 0xed, 0xa5, 0x57, 0x18, 0x86, 0x9d, 0xe8, 0x7c, 0x14, 0xeb, 0x71,
0xeb, 0xc0, 0xf4, 0x3a, 0x98, 0x11, 0x01, 0xc0, 0xa3, 0x53, 0xaf, 0x20, 0x7e, 0xde, 0x22,
0x5c, 0x1f, 0x60, 0x8b, 0xb7, 0x5f, 0x74, 0x76, 0xd0, 0x87, 0xfa, 0x11, 0xd3, 0xa5, 0xba,
0x5c, 0x82, 0xe1, 0x52, 0x54, 0x6b, 0x69, 0xeb, 0x31, 0x43, 0x01, 0x1a, 0x55, 0x7f, 0xdc,
0x2f, 0xd8, 0x01, 0x26, 0x6f, 0x1c, 0x2d, 0x72, 0x7b, 0xc8, 0x93, 0x99, 0x2a, 0x08, 0xa8,
0x6f, 0xb4, 0x28, 0x40, 0x8a, 0x8a, 0x4e, 0xd5, 0x3b, 0x39, 0x45, 0xa8, 0xe4, 0xe7, 0x73,
0x8f, 0x00, 0x64, 0xd3, 0xc7, 0x87, 0xde, 0x43, 0x82, 0x2c, 0xe8, 0x57, 0x17, 0x29, 0xce,
0xb8, 0x47, 0xd6, 0x08, 0x79, 0xd7, 0xc4, 0xe9, 0x23, 0x43, 0x9d, 0xb8, 0xcb, 0x78, 0x08,
0x32, 0xf1, 0xec, 0x84, 0x80, 0x1e, 0xb9, 0x29, 0x12, 0x0c, 0x29, 0xcc, 0x9c, 0xd0, 0x10,
0xa7, 0xd6, 0x8a, 0xe9, 0xf6, 0xfa, 0x8d, 0x7e, 0x95, 0x2e, 0x57, 0xcf, 0x8e, 0x38, 0x6b,
0x35, 0xf0, 0xbc, 0xa6, 0x4e, 0x13, 0x7b, 0x41, 0x19, 0x15, 0x5d, 0x99, 0xbd, 0x22, 0x40,
0x6a, 0x07, 0x2d, 0xd5, 0xd6, 0xff, 0x1d, 0x7b, 0xa6, 0xc4, 0xaa, 0x77, 0x44, 0x78, 0x2f,
0x55, 0x9f, 0x7d, 0x53, 0xf0, 0x2b, 0x2b, 0xba, 0x36, 0xc2, 0xf8, 0x6d, 0xf0, 0x2b, 0xbb,
0x6b, 0x97, 0x05, 0xb4, 0x4a, 0xc2, 0x86, 0x62, 0xb8, 0x76, 0xe7, 0xbb, 0xdf, 0x9c, 0x5a,
0x70, 0x19, 0x95, 0x59, 0x15, 0xcf, 0xa6, 0xa9, 0x7a, 0x24, 0x4c, 0xc6, 0x65, 0xb9, 0xda,
0x17, 0x6f, 0x2b, 0x55, 0x07, 0x32, 0x72, 0xd1, 0xee, 0x9c, 0x3a, 0x51, 0x98, 0x36, 0x37,
0xf8, 0x61, 0xfc, 0x91, 0xbc, 0xcb, 0x34, 0xd8, 0x43, 0xa0, 0x7a, 0xea, 0xc4, 0x8a, 0x64,
0x4d, 0xe0, 0x03, 0x93, 0xfb, 0xb4, 0xd8, 0x11, 0x21, 0x11, 0x66, 0x97, 0xb9, 0xba, 0x81,
0x29, 0xc2, 0x8f, 0x8c, 0x14, 0x18, 0x22, 0x94, 0xc4, 0xb0, 0xf1, 0x10, 0xc4, 0x8b, 0x5d,
0x8d, 0x7f, 0x14, 0xaf, 0x46, 0x19, 0x36, 0xa4, 0x36, 0x22, 0x18, 0x18, 0xe3, 0xab, 0x2c,
0x91, 0x03, 0xf7, 0xc5, 0xf5, 0xf5, 0x59, 0xc2, 0xd2, 0xf7, 0xc7, 0x64, 0x54, 0x76, 0xfb,
0x71, 0x70, 0xe8, 0xb2, 0x44, 0xa1, 0x2d, 0x59, 0x17, 0x02, 0xd6, 0x6f, 0x7a, 0xeb, 0xe0,
0x53, 0x81, 0xf6, 0x5e, 0x7f, 0x37, 0xd4, 0x52, 0x13, 0x04, 0x44, 0xd5, 0xc8, 0xd3, 0xdd,
0x6f, 0xd5, 0xfb, 0x71, 0x20, 0xe3, 0x0d, 0x0c, 0x47, 0x25, 0xa1, 0x41, 0xd2, 0xc7, 0xe5,
0xc9, 0xd9, 0x27, 0xa5, 0x38, 0xe4, 0x30, 0xbb, 0x86, 0x07, 0x84, 0xef, 0x24, 0x9f, 0xf9,
0x52, 0x74, 0xd2, 0x50, 0x73, 0xc4, 0x27, 0x73, 0x3b, 0x8d, 0x9c, 0xa6, 0xf6, 0x4b, 0x25,
0x91, 0xc5, 0x9e, 0x1e, 0xb2, 0x78, 0x0c, 0x23, 0x80, 0xdd, 0xa3, 0x21, 0xf5, 0xa9, 0x9e,
0x00, 0x16, 0x19, 0xbc, 0xd9, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef, 0x3d, 0xf8, 0x72, 0x66,
0x2f, 0xdc, 0x3a, 0xf6, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x27, 0xcc, 0xfb, 0x55, 0x09, 0x71,
0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xd0, 0x22, 0xc6, 0xef, 0x5c, 0x1b,
0xb4, 0xea, 0x56, 0x2e, 0xbf, 0xfc, 0x5b, 0x34, 0xcb, 0x14, 0x8b, 0x94, 0xaa, 0xb7, 0xec,
0x5a, 0x36, 0xcf, 0x1c, 0xba, 0xf6, 0x4d, 0xdb, 0x35, 0xf3 };

M keyboards/oddball/config.h => keyboards/oddball/config.h +22 -164
@@ 1,19 1,18 @@
/*
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/>.
*/
/* 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



@@ 31,173 30,32 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_ROWS 8
#define MATRIX_COLS 6

/*
 * Keyboard Matrix Assignments
 *
 * Change this to how you wired your keyboard
 * COLS: AVR pins used for columns, left to right
 * ROWS: AVR pins used for rows, top to bottom
 * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
 *                  ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
 *
 */
#define MATRIX_ROW_PINS { F6, B5, B6, F7 }
#define MATRIX_COL_PINS { D6, D7, B4, D3, C6, C7 }
#define UNUSED_PINS { B7, D4, D5, E6, F0, F1, F4, F5 }

/* COL2ROW, ROW2COL*/
#define DIODE_DIRECTION COL2ROW

/*
 * Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk, and define SOFT_SERIAL_PIN.
 */
// #define SOFT_SERIAL_PIN D0  // or D1, D2, D3, E6
/* Split Keyboard specific options */
#define USE_I2C
#define SPLIT_USB_DETECT
#define MASTER_RIGHT

// #define BACKLIGHT_PIN B7
// #define BACKLIGHT_BREATHING
// #define BACKLIGHT_LEVELS 3

// #define RGB_DI_PIN E2
// #ifdef RGB_DI_PIN
//   #define RGBLED_NUM 16
//   #define RGBLIGHT_HUE_STEP 8
//   #define RGBLIGHT_SAT_STEP 8
//   #define RGBLIGHT_VAL_STEP 8
//   #define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */
//   #define RGBLIGHT_SLEEP  /* If defined, the RGB lighting will be switched off when the host goes to sleep */
// /*== all animations enable ==*/
//   #define RGBLIGHT_ANIMATIONS
// /*== or choose animations ==*/
//   #define RGBLIGHT_EFFECT_BREATHING
//   #define RGBLIGHT_EFFECT_RAINBOW_MOOD
//   #define RGBLIGHT_EFFECT_RAINBOW_SWIRL
//   #define RGBLIGHT_EFFECT_SNAKE
//   #define RGBLIGHT_EFFECT_KNIGHT
//   #define RGBLIGHT_EFFECT_CHRISTMAS
//   #define RGBLIGHT_EFFECT_STATIC_GRADIENT
//   #define RGBLIGHT_EFFECT_RGB_TEST
//   #define RGBLIGHT_EFFECT_ALTERNATING
// /*== customize breathing effect ==*/
//   /*==== (DEFAULT) use fixed table instead of exp() and sin() ====*/
//   #define RGBLIGHT_BREATHE_TABLE_SIZE 256      // 256(default) or 128 or 64
//   /*==== use exp() and sin() ====*/
//   #define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85  // 1 to 2.7
//   #define RGBLIGHT_EFFECT_BREATHE_MAX    255   // 0 to 255
// #endif

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5

/* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST

/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE

/* If defined, GRAVE_ESC will always act as ESC when CTRL is held.
 * This is userful for the Windows task manager shortcut (ctrl+shift+esc).
 */
// #define GRAVE_ESC_CTRL_OVERRIDE

/*
 * Force NKRO
 *
 * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
 * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
 * makefile for this to work.)
 *
 * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
 * until the next keyboard reset.
 *
 * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
 * fully operational during normal computer usage.
 *
 * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
 * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
 * bootmagic, NKRO mode will always be enabled until it is toggled again during a
 * power-up.
 *
 */
//#define FORCE_NKRO

/*
 * Magic Key Options
 *
 * Magic keys are hotkey commands that allow control over firmware functions of
 * the keyboard. They are best used in combination with the HID Listen program,
 * found here: https://www.pjrc.com/teensy/hid_listen.html
 *
 * The options below allow the magic key functionality to be changed. This is
 * useful if your keyboard/keypad is missing keys and you want magic key support.
 *
 */

/* key combination for magic key command */
/* defined by default; to change, uncomment and set to the combination you want */
// #define IS_COMMAND() (get_mods() == MOD_MASK_SHIFT)

/* control how magic key switches layers */
//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS  true
//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS  true
//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false

/* override magic key keymap */
//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
//#define MAGIC_KEY_HELP           H
//#define MAGIC_KEY_HELP_ALT       SLASH
//#define MAGIC_KEY_DEBUG          D
//#define MAGIC_KEY_DEBUG_MATRIX   X
//#define MAGIC_KEY_DEBUG_KBD      K
//#define MAGIC_KEY_DEBUG_MOUSE    M
//#define MAGIC_KEY_VERSION        V
//#define MAGIC_KEY_STATUS         S
//#define MAGIC_KEY_CONSOLE        C
//#define MAGIC_KEY_LAYER0         0
//#define MAGIC_KEY_LAYER0_ALT     GRAVE
//#define MAGIC_KEY_LAYER1         1
//#define MAGIC_KEY_LAYER2         2
//#define MAGIC_KEY_LAYER3         3
//#define MAGIC_KEY_LAYER4         4
//#define MAGIC_KEY_LAYER5         5
//#define MAGIC_KEY_LAYER6         6
//#define MAGIC_KEY_LAYER7         7
//#define MAGIC_KEY_LAYER8         8
//#define MAGIC_KEY_LAYER9         9
//#define MAGIC_KEY_BOOTLOADER     B
//#define MAGIC_KEY_BOOTLOADER_ALT ESC
//#define MAGIC_KEY_LOCK           CAPS
//#define MAGIC_KEY_EEPROM         E
//#define MAGIC_KEY_EEPROM_CLEAR   BSPACE
//#define MAGIC_KEY_NKRO           N
//#define MAGIC_KEY_SLEEP_LED      Z

/*
 * Feature disable options
 *  These options are also useful to firmware size reduction.
 */

/* disable debug print */
//#define NO_DEBUG

/* disable print */
//#define NO_PRINT

/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT

/* disable these deprecated features by default */
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION

/* optical sensor settings */
#define SCROLL_DIVIDER 12
#define CPI_1 2000
#define CPI_2 4000
#define CPI_3 8000

/*
 * MIDI options
 */

A keyboards/oddball/keymaps/default/config.h => keyboards/oddball/keymaps/default/config.h +1 -0
@@ 0,0 1,1 @@
#define ADNS_9800

M keyboards/oddball/keymaps/default/keymap.c => keyboards/oddball/keymaps/default/keymap.c +5 -4
@@ 13,6 13,7 @@
 * 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 QMK_KEYBOARD_H

enum layer_names {


@@ 32,15 33,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {

  [_LOWER] = LAYOUT(
     KC_DEL,    KC_EXLM, KC_AT,   KC_LCBR, KC_RCBR, KC_BTN3,       KC_DQUO,  KC_7,    KC_8,    KC_9,    KC_ASTR, KC_UNDS,
     _______,   KC_HASH, KC_DLR,  KC_LPRN, KC_RPRN, KC_BTN2,       KC_QUOT,  KC_4,    KC_5,    KC_6,    KC_PLUS, KC_ENT,
     KC_SCROLL, KC_HASH, KC_DLR,  KC_LPRN, KC_RPRN, KC_BTN2,       KC_QUOT,  KC_4,    KC_5,    KC_6,    KC_PLUS, KC_ENT,
     _______,   KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_BTN1,       KC_0,     KC_1,    KC_2,    KC_3,    KC_MINS, _______,
                                           _______, _______,       _______,  _______
  ),

  [_RAISE] = LAYOUT(
     _______,   KC_ESC,  KC_F7,   KC_F9,   KC_F9,   KC_F10,        KC_PIPE,  KC_PGUP, KC_UP,   KC_PGDN, KC_GRAVE, _______,
     _______,   KC_LGUI, KC_F4,   KC_F5,   KC_F6,   KC_F11,        KC_AMPR,  KC_LEFT, KC_DOWN, KC_RGHT, KC_TILD,  _______,
     _______,   KC_INS,  KC_F1,   KC_F2,   KC_F3,   KC_F12,        KC_EQUAL, KC_HOME, _______, KC_END,  KC_BSLS,  _______,
     _______,   KC_ESC,  KC_F7,   KC_F8,   KC_F9,   KC_F10,        KC_PIPE,  KC_PGUP, KC_UP,   KC_PGDN, KC_GRAVE, KC_CPI_1,
     _______,   KC_LGUI, KC_F4,   KC_F5,   KC_F6,   KC_F11,        KC_AMPR,  KC_LEFT, KC_DOWN, KC_RGHT, KC_TILD,  KC_CPI_2,
     _______,   KC_INS,  KC_F1,   KC_F2,   KC_F3,   KC_F12,        KC_EQUAL, KC_HOME, KC_MPLY, KC_END,  KC_BSLS,  KC_CPI_3,
                                           _______, _______,       _______,  _______
  )
};

A keyboards/oddball/keymaps/pmw3360/config.h => keyboards/oddball/keymaps/pmw3360/config.h +1 -0
@@ 0,0 1,1 @@
#define PMW_3360

A keyboards/oddball/keymaps/pmw3360/keymap.c => keyboards/oddball/keymaps/pmw3360/keymap.c +47 -0
@@ 0,0 1,47 @@
/* 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 QMK_KEYBOARD_H

enum layer_names {
    _QWERTY,
    _LOWER,
    _RAISE
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {

  [_QWERTY] = LAYOUT(
     KC_BSPC,   KC_Q,    KC_W,    KC_E,    KC_R,       KC_T,          KC_Y,     KC_U,     KC_I,    KC_O,    KC_P,    KC_TAB,
     KC_LALT,   KC_A,    KC_S,    KC_D,    KC_F,       KC_G,          KC_H,     KC_J,     KC_K,    KC_L,    KC_SCLN, KC_SPC,
     KC_LSFT,   KC_Z,    KC_X,    KC_C,    KC_V,       KC_B,          KC_N,     KC_M,     KC_COMM, KC_DOT,  KC_SLSH, KC_RSFT,
                                           MO(_LOWER), KC_LCTL,       _______,  MO(_RAISE)
  ),

  [_LOWER] = LAYOUT(
     KC_DEL,    KC_EXLM, KC_AT,   KC_LCBR, KC_RCBR, KC_BTN3,       KC_DQUO,  KC_7,    KC_8,    KC_9,    KC_ASTR, KC_UNDS,
     KC_SCROLL, KC_HASH, KC_DLR,  KC_LPRN, KC_RPRN, KC_BTN2,       KC_QUOT,  KC_4,    KC_5,    KC_6,    KC_PLUS, KC_ENT,
     _______,   KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_BTN1,       KC_0,     KC_1,    KC_2,    KC_3,    KC_MINS, _______,
                                           _______, _______,       _______,  _______
  ),

  [_RAISE] = LAYOUT(
     _______,   KC_ESC,  KC_F7,   KC_F8,   KC_F9,   KC_F10,        KC_PIPE,  KC_PGUP, KC_UP,   KC_PGDN, KC_GRAVE, KC_CPI_1,
     _______,   KC_LGUI, KC_F4,   KC_F5,   KC_F6,   KC_F11,        KC_AMPR,  KC_LEFT, KC_DOWN, KC_RGHT, KC_TILD,  KC_CPI_2,
     _______,   KC_INS,  KC_F1,   KC_F2,   KC_F3,   KC_F12,        KC_EQUAL, KC_HOME, KC_MPLY, KC_END,  KC_BSLS,  KC_CPI_3,
                                           _______, _______,       _______,  _______
  )
};

M keyboards/oddball/oddball.c => keyboards/oddball/oddball.c +152 -0
@@ 15,3 15,155 @@
 */

#include "oddball.h"
#include "pointing_device.h"
#include "optical_sensor/optical_sensor.h"

#define CLAMP_HID(value) value < -127 ? -127 : value > 127 ? 127 : value

static bool scroll_pressed;
static bool mouse_buttons_dirty;
static int8_t scroll_h;
static int8_t scroll_v;

void pointing_device_init(void){
    if(!is_keyboard_master())
        return;

    optical_sensor_init();

    // read config from EEPROM and update if needed

    config_oddball_t kb_config;
    kb_config.raw = eeconfig_read_kb();

    if(!kb_config.cpi) {
        kb_config.cpi = CPI_2;
        eeconfig_update_kb(kb_config.raw);
    }

    optical_sensor_set_config((config_optical_sensor_t){ kb_config.cpi });
}

void pointing_device_task(void){
    if(!is_keyboard_master())
        return;

    report_mouse_t mouse_report = pointing_device_get_report();
    report_optical_sensor_t sensor_report = optical_sensor_get_report();

    int8_t clamped_x = CLAMP_HID(sensor_report.x);
    int8_t clamped_y = CLAMP_HID(sensor_report.y);

    if(scroll_pressed) {

        // accumulate scroll
        scroll_h += clamped_x;
        scroll_v += clamped_y;

        int8_t scaled_scroll_h = scroll_h / SCROLL_DIVIDER;
        int8_t scaled_scroll_v = scroll_v / SCROLL_DIVIDER;

        // clear accumulated scroll on assignment

        if(scaled_scroll_h != 0){
            mouse_report.h = -scaled_scroll_h;
            scroll_h = 0;
        }

        if(scaled_scroll_v != 0){
            mouse_report.v = -scaled_scroll_v;
            scroll_v = 0;
        }
    }
    else {
        mouse_report.x = -clamped_x;
        mouse_report.y = clamped_y;
    }

    pointing_device_set_report(mouse_report);

    // only send report on change as even sending report with no change is treated as movement
    if(mouse_buttons_dirty ||
       mouse_report.x != 0 ||
       mouse_report.y != 0 ||
       mouse_report.h != 0 ||
       mouse_report.v != 0){

        mouse_buttons_dirty = false;
        pointing_device_send();
    }
}

static void on_cpi_button(uint16_t cpi, keyrecord_t *record) {

    if(!record->event.pressed)
        return;

    optical_sensor_set_config((config_optical_sensor_t){ cpi });

    config_oddball_t kb_config;
    kb_config.cpi = cpi;
    eeconfig_update_kb(kb_config.raw);
}

static void on_mouse_button(uint8_t mouse_button, keyrecord_t *record) {

    report_mouse_t report = pointing_device_get_report();

    if(record->event.pressed)
        report.buttons |= mouse_button;
    else
        report.buttons &= ~mouse_button;

    pointing_device_set_report(report);
    mouse_buttons_dirty = true;
}

bool process_record_kb(uint16_t keycode, keyrecord_t *record) {

    if(!process_record_user(keycode, record))
        return false;

    // handle mouse drag and scroll

    switch (keycode) {
        case KC_BTN1:
            on_mouse_button(MOUSE_BTN1, record);
            return false;

        case KC_BTN2:
            on_mouse_button(MOUSE_BTN2, record);
            return false;

        case KC_BTN3:
            on_mouse_button(MOUSE_BTN3, record);
            return false;

        case KC_BTN4:
            on_mouse_button(MOUSE_BTN4, record);
            return false;

        case KC_BTN5:
            on_mouse_button(MOUSE_BTN5, record);
            return false;

        case KC_SCROLL:
            scroll_pressed = record->event.pressed;
            return false;

        case KC_CPI_1:
            on_cpi_button(CPI_1, record);
            return false;

        case KC_CPI_2:
            on_cpi_button(CPI_2, record);
            return false;

        case KC_CPI_3:
            on_cpi_button(CPI_3, record);
            return false;

        default:
            return true;
  }
}

M keyboards/oddball/oddball.h => keyboards/oddball/oddball.h +14 -8
@@ 18,14 18,6 @@

#include "quantum.h"

/* This is a shortcut to help you visually see your layout.
 *
 * The first section contains all of the arguments representing the physical
 * layout of the board and position of the keys.
 *
 * The second converts the arguments into a two-dimensional array which
 * represents the switch matrix.
 */
#define LAYOUT( \
    L00, L01, L02, L03, L04, L05,   R00, R01, R02, R03, R04, R05, \
    L10, L11, L12, L13, L14, L15,   R10, R11, R12, R13, R14, R15, \


@@ 42,3 34,17 @@
        { R25, R24, R23, R22, R21, R20 }, \
        { KC_NO, KC_NO, KC_NO, KC_NO, RT2, RT1 } \
    }

enum custom_keycodes {
    KC_SCROLL = SAFE_RANGE,
    KC_CPI_1,
    KC_CPI_2,
    KC_CPI_3
};

typedef union {
  uint32_t raw;
  struct {
    uint16_t cpi;
  };
} config_oddball_t;

A keyboards/oddball/optical_sensor/optical_sensor.h => keyboards/oddball/optical_sensor/optical_sensor.h +53 -0
@@ 0,0 1,53 @@
/* 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/>.
 */

/* common interface for opitcal sensors */

#if defined ADNS_9800
    #include "../adns/adns.h"
    #define config_optical_sensor_t config_adns_t
    #define report_optical_sensor_t report_adns_t
    #define optical_sensor_init adns_init
    #define optical_sensor_get_config adns_get_config
    #define optical_sensor_set_config adns_set_config
    #define optical_sensor_get_report adns_get_report
#elif defined PMW_3360
    #include "../pmw/pmw.h"
    #define config_optical_sensor_t config_pmw_t
    #define report_optical_sensor_t report_pmw_t
    #define optical_sensor_init pmw_init
    #define optical_sensor_get_config pmw_get_config
    #define optical_sensor_set_config pmw_set_config
    #define optical_sensor_get_report pmw_get_report
#else
    /* fallback stub */

    #include <stdint.h>

    typedef struct {
        uint16_t cpi;
    } config_optical_sensor_t;

    typedef struct {
        int16_t x;
        int16_t y;
    } report_optical_sensor_t;

    #define optical_sensor_init(){ }
    #define optical_sensor_get_config() (config_optical_sensor_t){ }
    #define optical_sensor_set_config(config_optical_sensor_t){ }
    #define optical_sensor_get_report() (report_optical_sensor_t){ }
#endif

A keyboards/oddball/pmw/pmw.c => keyboards/oddball/pmw/pmw.c +226 -0
@@ 0,0 1,226 @@
/* 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 "pmw3360_srom_0x04.h"
#include "pmw.h"

// registers
#define Product_ID  0x00
#define Revision_ID 0x01
#define Motion  0x02
#define Delta_X_L 0x03
#define Delta_X_H 0x04
#define Delta_Y_L 0x05
#define Delta_Y_H 0x06
#define SQUAL 0x07
#define Raw_Data_Sum  0x08
#define Maximum_Raw_data  0x09
#define Minimum_Raw_data  0x0A
#define Shutter_Lower 0x0B
#define Shutter_Upper 0x0C
#define Control 0x0D
#define Config1 0x0F
#define Config2 0x10
#define Angle_Tune  0x11
#define Frame_Capture 0x12
#define SROM_Enable 0x13
#define Run_Downshift 0x14
#define Rest1_Rate_Lower  0x15
#define Rest1_Rate_Upper  0x16
#define Rest1_Downshift 0x17
#define Rest2_Rate_Lower  0x18
#define Rest2_Rate_Upper  0x19
#define Rest2_Downshift 0x1A
#define Rest3_Rate_Lower  0x1B
#define Rest3_Rate_Upper  0x1C
#define Observation 0x24
#define Data_Out_Lower  0x25
#define Data_Out_Upper  0x26
#define Raw_Data_Dump 0x29
#define SROM_ID 0x2A
#define Min_SQ_Run  0x2B
#define Raw_Data_Threshold  0x2C
#define Config5 0x2F
#define Power_Up_Reset  0x3A
#define Shutdown  0x3B
#define Inverse_Product_ID  0x3F
#define LiftCutoff_Tune3  0x41
#define Angle_Snap  0x42
#define LiftCutoff_Tune1  0x4A
#define Motion_Burst  0x50
#define LiftCutoff_Tune_Timeout 0x58
#define LiftCutoff_Tune_Min_Length  0x5A
#define SROM_Load_Burst 0x62
#define Lift_Config 0x63
#define Raw_Data_Burst  0x64
#define LiftCutoff_Tune2  0x65

#define PMW_CLOCK_SPEED 70000000
#define MIN_CPI 100
#define MAX_CPI 12000
#define CPI_STEP 100
#define CLAMP_CPI(value) value < MIN_CPI ? MIN_CPI : value > MAX_CPI ? MAX_CPI : value
#define SPI_MODE 3
#define SPI_DIVISOR (F_CPU / PMW_CLOCK_SPEED)
#define US_BETWEEN_WRITES 180
#define US_BETWEEN_READS 20
#define US_BEFORE_MOTION 35

#define MSB1 0x80

extern const uint16_t pmw_firmware_length;
extern const uint8_t pmw_firmware_data[];

void pmw_spi_start(void){
    spi_start(SPI_SS_PIN, false, SPI_MODE, SPI_DIVISOR);
}

void pmw_write(uint8_t reg_addr, uint8_t data){

    pmw_spi_start();
    spi_write(reg_addr | MSB1 );
    spi_write(data);
    spi_stop();
    wait_us(US_BETWEEN_WRITES);
}

uint8_t pmw_read(uint8_t reg_addr){

    pmw_spi_start();
    spi_write(reg_addr & 0x7f );
    uint8_t data = spi_read();
    spi_stop();
    wait_us(US_BETWEEN_READS);

    return data;
}

void pmw_init() {

    setPinOutput(SPI_SS_PIN);

    spi_init();

    // reboot
    pmw_write(Power_Up_Reset, 0x5a);
    wait_ms(50);

    // read registers and discard
    pmw_read(Motion);
    pmw_read(Delta_X_L);
    pmw_read(Delta_X_H);
    pmw_read(Delta_Y_L);
    pmw_read(Delta_Y_H);

    // upload firmware

    // disable rest mode
    pmw_write(Config2, 0x20);

    // enable initialisation
    pmw_write(SROM_Enable, 0x1d);

    // wait a frame
    wait_ms(10);

    // start SROM download
    pmw_write(SROM_Enable, 0x18);

    // write the SROM file

    pmw_spi_start();

    spi_write(SROM_Load_Burst | 0x80);
    wait_us(15);

    // send all bytes of the firmware
    unsigned char c;
    for(int i = 0; i < pmw_firmware_length; i++){
        c = (unsigned char)pgm_read_byte(pmw_firmware_data + i);
        spi_write(c);
        wait_us(15);
    }

    spi_stop();
    wait_us(US_BETWEEN_WRITES);

    // read id
    pmw_read(SROM_ID);

    // wired mouse
    pmw_write(Config2, 0x00);

    // first motion burst; write anything
    pmw_write(Motion_Burst, 0xFF);
    writePinLow(SPI_SS_PIN);
}

config_pmw_t pmw_get_config(void) {
    uint8_t config_1 = pmw_read(Config1);
    return (config_pmw_t){ (config_1 & 0xFF) * CPI_STEP };
}

void pmw_set_config(config_pmw_t config) {
    uint8_t config_1 = (CLAMP_CPI(config.cpi) / CPI_STEP) & 0xFF;
    pmw_write(Config1, 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_pmw_t pmw_get_report(void) {

    report_pmw_t report = {0, 0};

    pmw_spi_start();

    // start burst mode
    spi_write(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);
    }

    spi_stop();

    return report;
}

A keyboards/oddball/pmw/pmw.h => keyboards/oddball/pmw/pmw.h +35 -0
@@ 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 {
    /* 100 - 12000 CPI supported */
    uint16_t cpi;
} config_pmw_t;

typedef struct {
    int16_t x;
    int16_t y;
} report_pmw_t;

void pmw_init(void);
config_pmw_t pmw_get_config(void);
void pmw_set_config(config_pmw_t);
/* Reads and clears the current delta values on the PMW sensor */
report_pmw_t pmw_get_report(void);

A keyboards/oddball/pmw/pmw3360_srom_0x04.h => keyboards/oddball/pmw/pmw3360_srom_0x04.h +280 -0
@@ 0,0 1,280 @@
#pragma once

#include "progmem.h"

const uint16_t pmw_firmware_length = 4094;

const uint8_t pmw_firmware_data[] PROGMEM = {
0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
0xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
0xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
0x97, 0x8d, 0x79, 0x51, 0x20, 0xc7, 0x06, 0x8e, 0x7c, 0x7c, 0x7a, 0x76, 0x4f, 0xfd, 0x59,
0x30, 0xe2, 0x46, 0x0e, 0x9e, 0xbe, 0xdf, 0x1d, 0x99, 0x91, 0xa0, 0xa5, 0xa1, 0xa9, 0xd0,
0x22, 0xc6, 0xef, 0x5c, 0x1b, 0x95, 0x89, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x55, 0x28, 0xb3,
0xe4, 0x4a, 0xf7, 0x6c, 0x3b, 0xf4, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x05,
0x88, 0x92, 0xa6, 0xce, 0x1e, 0xbe, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x07,
0x11, 0x5d, 0x98, 0x0b, 0x9d, 0x94, 0x97, 0xee, 0x4e, 0x45, 0x33, 0x6b, 0x44, 0xc7, 0x29,
0x56, 0x27, 0x30, 0xc6, 0xa7, 0xd5, 0xf2, 0x56, 0xdf, 0xb4, 0x38, 0x62, 0xcb, 0xa0, 0xb6,
0xe3, 0x0f, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6f, 0x76, 0x89, 0xb5, 0x77, 0x41, 0x27, 0x82,
0x66, 0x65, 0x82, 0xcc, 0xd5, 0xe6, 0x20, 0xd5, 0x27, 0x17, 0xc5, 0xf8, 0x03, 0x23, 0x7c,
0x5f, 0x64, 0xa5, 0x1d, 0xc1, 0xd6, 0x36, 0xcb, 0x4c, 0xd4, 0xdb, 0x66, 0xd7, 0x8b, 0xb1,
0x99, 0x7e, 0x6f, 0x4c, 0x36, 0x40, 0x06, 0xd6, 0xeb, 0xd7, 0xa2, 0xe4, 0xf4, 0x95, 0x51,
0x5a, 0x54, 0x96, 0xd5, 0x53, 0x44, 0xd7, 0x8c, 0xe0, 0xb9, 0x40, 0x68, 0xd2, 0x18, 0xe9,
0xdd, 0x9a, 0x23, 0x92, 0x48, 0xee, 0x7f, 0x43, 0xaf, 0xea, 0x77, 0x38, 0x84, 0x8c, 0x0a,
0x72, 0xaf, 0x69, 0xf8, 0xdd, 0xf1, 0x24, 0x83, 0xa3, 0xf8, 0x4a, 0xbf, 0xf5, 0x94, 0x13,
0xdb, 0xbb, 0xd8, 0xb4, 0xb3, 0xa0, 0xfb, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71,
0xa2, 0xd3, 0x13, 0xe7, 0xfa, 0xe7, 0xce, 0x0f, 0x63, 0x15, 0x0b, 0x6b, 0x94, 0xbb, 0x37,
0x83, 0x26, 0x05, 0x9d, 0xfb, 0x46, 0x92, 0xfc, 0x0a, 0x15, 0xd1, 0x0d, 0x73, 0x92, 0xd6,
0x8c, 0x1b, 0x8c, 0xb8, 0x55, 0x8a, 0xce, 0xbd, 0xfe, 0x8e, 0xfc, 0xed, 0x09, 0x12, 0x83,
0x91, 0x82, 0x51, 0x31, 0x23, 0xfb, 0xb4, 0x0c, 0x76, 0xad, 0x7c, 0xd9, 0xb4, 0x4b, 0xb2,
0x67, 0x14, 0x09, 0x9c, 0x7f, 0x0c, 0x18, 0xba, 0x3b, 0xd6, 0x8e, 0x14, 0x2a, 0xe4, 0x1b,
0x52, 0x9f, 0x2b, 0x7d, 0xe1, 0xfb, 0x6a, 0x33, 0x02, 0xfa, 0xac, 0x5a, 0xf2, 0x3e, 0x88,
0x7e, 0xae, 0xd1, 0xf3, 0x78, 0xe8, 0x05, 0xd1, 0xe3, 0xdc, 0x21, 0xf6, 0xe1, 0x9a, 0xbd,
0x17, 0x0e, 0xd9, 0x46, 0x9b, 0x88, 0x03, 0xea, 0xf6, 0x66, 0xbe, 0x0e, 0x1b, 0x50, 0x49,
0x96, 0x40, 0x97, 0xf1, 0xf1, 0xe4, 0x80, 0xa6, 0x6e, 0xe8, 0x77, 0x34, 0xbf, 0x29, 0x40,
0x44, 0xc2, 0xff, 0x4e, 0x98, 0xd3, 0x9c, 0xa3, 0x32, 0x2b, 0x76, 0x51, 0x04, 0x09, 0xe7,
0xa9, 0xd1, 0xa6, 0x32, 0xb1, 0x23, 0x53, 0xe2, 0x47, 0xab, 0xd6, 0xf5, 0x69, 0x5c, 0x3e,
0x5f, 0xfa, 0xae, 0x45, 0x20, 0xe5, 0xd2, 0x44, 0xff, 0x39, 0x32, 0x6d, 0xfd, 0x27, 0x57,
0x5c, 0xfd, 0xf0, 0xde, 0xc1, 0xb5, 0x99, 0xe5, 0xf5, 0x1c, 0x77, 0x01, 0x75, 0xc5, 0x6d,
0x58, 0x92, 0xf2, 0xb2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7a, 0x30, 0xff, 0xb7, 0xf0, 0xef,
0x77, 0xc1, 0x8a, 0x5d, 0xdc, 0xc0, 0xd1, 0x29, 0x30, 0x1e, 0x77, 0x38, 0x7a, 0x94, 0xf1,
0xb8, 0x7a, 0x7e, 0xef, 0xa4, 0xd1, 0xac, 0x31, 0x4a, 0xf2, 0x5d, 0x64, 0x3d, 0xb2, 0xe2,
0xf0, 0x08, 0x99, 0xfc, 0x70, 0xee, 0x24, 0xa7, 0x7e, 0xee, 0x1e, 0x20, 0x69, 0x7d, 0x44,
0xbf, 0x87, 0x42, 0xdf, 0x88, 0x3b, 0x0c, 0xda, 0x42, 0xc9, 0x04, 0xf9, 0x45, 0x50, 0xfc,
0x83, 0x8f, 0x11, 0x6a, 0x72, 0xbc, 0x99, 0x95, 0xf0, 0xac, 0x3d, 0xa7, 0x3b, 0xcd, 0x1c,
0xe2, 0x88, 0x79, 0x37, 0x11, 0x5f, 0x39, 0x89, 0x95, 0x0a, 0x16, 0x84, 0x7a, 0xf6, 0x8a,
0xa4, 0x28, 0xe4, 0xed, 0x83, 0x80, 0x3b, 0xb1, 0x23, 0xa5, 0x03, 0x10, 0xf4, 0x66, 0xea,
0xbb, 0x0c, 0x0f, 0xc5, 0xec, 0x6c, 0x69, 0xc5, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0x99,
0x88, 0x76, 0x08, 0xa0, 0xa8, 0x95, 0x7c, 0xd8, 0x38, 0x6d, 0xcd, 0x59, 0x02, 0x51, 0x4b,
0xf1, 0xb5, 0x2b, 0x50, 0xe3, 0xb6, 0xbd, 0xd0, 0x72, 0xcf, 0x9e, 0xfd, 0x6e, 0xbb, 0x44,
0xc8, 0x24, 0x8a, 0x77, 0x18, 0x8a, 0x13, 0x06, 0xef, 0x97, 0x7d, 0xfa, 0x81, 0xf0, 0x31,
0xe6, 0xfa, 0x77, 0xed, 0x31, 0x06, 0x31, 0x5b, 0x54, 0x8a, 0x9f, 0x30, 0x68, 0xdb, 0xe2,
0x40, 0xf8, 0x4e, 0x73, 0xfa, 0xab, 0x74, 0x8b, 0x10, 0x58, 0x13, 0xdc, 0xd2, 0xe6, 0x78,
0xd1, 0x32, 0x2e, 0x8a, 0x9f, 0x2c, 0x58, 0x06, 0x48, 0x27, 0xc5, 0xa9, 0x5e, 0x81, 0x47,
0x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xa4, 0x3e, 0x88, 0x9c, 0xda, 0x33, 0x0a, 0xce, 0xbc,
0x8b, 0x8e, 0xcf, 0x9f, 0xd3, 0x71, 0x80, 0x43, 0xcf, 0x6b, 0xa9, 0x51, 0x83, 0x76, 0x30,
0x82, 0xc5, 0x6a, 0x85, 0x39, 0x11, 0x50, 0x1a, 0x82, 0xdc, 0x1e, 0x1c, 0xd5, 0x7d, 0xa9,
0x71, 0x99, 0x33, 0x47, 0x19, 0x97, 0xb3, 0x5a, 0xb1, 0xdf, 0xed, 0xa4, 0xf2, 0xe6, 0x26,
0x84, 0xa2, 0x28, 0x9a, 0x9e, 0xdf, 0xa6, 0x6a, 0xf4, 0xd6, 0xfc, 0x2e, 0x5b, 0x9d, 0x1a,
0x2a, 0x27, 0x68, 0xfb, 0xc1, 0x83, 0x21, 0x4b, 0x90, 0xe0, 0x36, 0xdd, 0x5b, 0x31, 0x42,
0x55, 0xa0, 0x13, 0xf7, 0xd0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xc5, 0xf3, 0x21,
0xf8, 0x37, 0x2f, 0x40, 0xf3, 0xd4, 0xaf, 0x16, 0x08, 0x36, 0x02, 0xfc, 0x77, 0xc5, 0x8b,
0x04, 0x90, 0x56, 0xb9, 0xc9, 0x67, 0x9a, 0x99, 0xe8, 0x00, 0xd3, 0x86, 0xff, 0x97, 0x2d,
0x08, 0xe9, 0xb7, 0xb3, 0x91, 0xbc, 0xdf, 0x45, 0xc6, 0xed, 0x0f, 0x8c, 0x4c, 0x1e, 0xe6,
0x5b, 0x6e, 0x38, 0x30, 0xe4, 0xaa, 0xe3, 0x95, 0xde, 0xb9, 0xe4, 0x9a, 0xf5, 0xb2, 0x55,
0x9a, 0x87, 0x9b, 0xf6, 0x6a, 0xb2, 0xf2, 0x77, 0x9a, 0x31, 0xf4, 0x7a, 0x31, 0xd1, 0x1d,
0x04, 0xc0, 0x7c, 0x32, 0xa2, 0x9e, 0x9a, 0xf5, 0x62, 0xf8, 0x27, 0x8d, 0xbf, 0x51, 0xff,
0xd3, 0xdf, 0x64, 0x37, 0x3f, 0x2a, 0x6f, 0x76, 0x3a, 0x7d, 0x77, 0x06, 0x9e, 0x77, 0x7f,
0x5e, 0xeb, 0x32, 0x51, 0xf9, 0x16, 0x66, 0x9a, 0x09, 0xf3, 0xb0, 0x08, 0xa4, 0x70, 0x96,
0x46, 0x30, 0xff, 0xda, 0x4f, 0xe9, 0x1b, 0xed, 0x8d, 0xf8, 0x74, 0x1f, 0x31, 0x92, 0xb3,
0x73, 0x17, 0x36, 0xdb, 0x91, 0x30, 0xd6, 0x88, 0x55, 0x6b, 0x34, 0x77, 0x87, 0x7a, 0xe7,
0xee, 0x06, 0xc6, 0x1c, 0x8c, 0x19, 0x0c, 0x48, 0x46, 0x23, 0x5e, 0x9c, 0x07, 0x5c, 0xbf,
0xb4, 0x7e, 0xd6, 0x4f, 0x74, 0x9c, 0xe2, 0xc5, 0x50, 0x8b, 0xc5, 0x8b, 0x15, 0x90, 0x60,
0x62, 0x57, 0x29, 0xd0, 0x13, 0x43, 0xa1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xc7, 0x4d, 0x19,
0x86, 0xcc, 0x2f, 0x2a, 0x75, 0x5a, 0xfc, 0xeb, 0x97, 0x2a, 0x70, 0xe3, 0x78, 0xd8, 0x91,
0xb0, 0x4f, 0x99, 0x07, 0xa3, 0x95, 0xea, 0x24, 0x21, 0xd5, 0xde, 0x51, 0x20, 0x93, 0x27,
0x0a, 0x30, 0x73, 0xa8, 0xff, 0x8a, 0x97, 0xe9, 0xa7, 0x6a, 0x8e, 0x0d, 0xe8, 0xf0, 0xdf,
0xec, 0xea, 0xb4, 0x6c, 0x1d, 0x39, 0x2a, 0x62, 0x2d, 0x3d, 0x5a, 0x8b, 0x65, 0xf8, 0x90,
0x05, 0x2e, 0x7e, 0x91, 0x2c, 0x78, 0xef, 0x8e, 0x7a, 0xc1, 0x2f, 0xac, 0x78, 0xee, 0xaf,
0x28, 0x45, 0x06, 0x4c, 0x26, 0xaf, 0x3b, 0xa2, 0xdb, 0xa3, 0x93, 0x06, 0xb5, 0x3c, 0xa5,
0xd8, 0xee, 0x8f, 0xaf, 0x25, 0xcc, 0x3f, 0x85, 0x68, 0x48, 0xa9, 0x62, 0xcc, 0x97, 0x8f,
0x7f, 0x2a, 0xea, 0xe0, 0x15, 0x0a, 0xad, 0x62, 0x07, 0xbd, 0x45, 0xf8, 0x41, 0xd8, 0x36,
0xcb, 0x4c, 0xdb, 0x6e, 0xe6, 0x3a, 0xe7, 0xda, 0x15, 0xe9, 0x29, 0x1e, 0x12, 0x10, 0xa0,
0x14, 0x2c, 0x0e, 0x3d, 0xf4, 0xbf, 0x39, 0x41, 0x92, 0x75, 0x0b, 0x25, 0x7b, 0xa3, 0xce,
0x39, 0x9c, 0x15, 0x64, 0xc8, 0xfa, 0x3d, 0xef, 0x73, 0x27, 0xfe, 0x26, 0x2e, 0xce, 0xda,
0x6e, 0xfd, 0x71, 0x8e, 0xdd, 0xfe, 0x76, 0xee, 0xdc, 0x12, 0x5c, 0x02, 0xc5, 0x3a, 0x4e,
0x4e, 0x4f, 0xbf, 0xca, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x41, 0xf1, 0x10, 0xe0, 0x4f, 0x7e,
0x97, 0x7f, 0x1c, 0xae, 0x47, 0x8e, 0x6b, 0xb1, 0x25, 0x31, 0xb0, 0x73, 0xc7, 0x1b, 0x97,
0x79, 0xf9, 0x80, 0xd3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1e, 0xe4, 0xd0, 0x80, 0x21, 0xd6,
0xee, 0x6b, 0x6c, 0x4f, 0xbf, 0xf5, 0xb7, 0xd9, 0x09, 0x87, 0x2f, 0xa9, 0x14, 0xbe, 0x27,
0xd9, 0x72, 0x50, 0x01, 0xd4, 0x13, 0x73, 0xa6, 0xa7, 0x51, 0x02, 0x75, 0x25, 0xe1, 0xb3,
0x45, 0x34, 0x7d, 0xa8, 0x8e, 0xeb, 0xf3, 0x16, 0x49, 0xcb, 0x4f, 0x8c, 0xa1, 0xb9, 0x36,
0x85, 0x39, 0x75, 0x5d, 0x08, 0x00, 0xae, 0xeb, 0xf6, 0xea, 0xd7, 0x13, 0x3a, 0x21, 0x5a,
0x5f, 0x30, 0x84, 0x52, 0x26, 0x95, 0xc9, 0x14, 0xf2, 0x57, 0x55, 0x6b, 0xb1, 0x10, 0xc2,
0xe1, 0xbd, 0x3b, 0x51, 0xc0, 0xb7, 0x55, 0x4c, 0x71, 0x12, 0x26, 0xc7, 0x0d, 0xf9, 0x51,
0xa4, 0x38, 0x02, 0x05, 0x7f, 0xb8, 0xf1, 0x72, 0x4b, 0xbf, 0x71, 0x89, 0x14, 0xf3, 0x77,
0x38, 0xd9, 0x71, 0x24, 0xf3, 0x00, 0x11, 0xa1, 0xd8, 0xd4, 0x69, 0x27, 0x08, 0x37, 0x35,
0xc9, 0x11, 0x9d, 0x90, 0x1c, 0x0e, 0xe7, 0x1c, 0xff, 0x2d, 0x1e, 0xe8, 0x92, 0xe1, 0x18,
0x10, 0x95, 0x7c, 0xe0, 0x80, 0xf4, 0x96, 0x43, 0x21, 0xf9, 0x75, 0x21, 0x64, 0x38, 0xdd,
0x9f, 0x1e, 0x95, 0x16, 0xda, 0x56, 0x1d, 0x4f, 0x9a, 0x53, 0xb2, 0xe2, 0xe4, 0x18, 0xcb,
0x6b, 0x1a, 0x65, 0xeb, 0x56, 0xc6, 0x3b, 0xe5, 0xfe, 0xd8, 0x26, 0x3f, 0x3a, 0x84, 0x59,
0x72, 0x66, 0xa2, 0xf3, 0x75, 0xff, 0xfb, 0x60, 0xb3, 0x22, 0xad, 0x3f, 0x2d, 0x6b, 0xf9,
0xeb, 0xea, 0x05, 0x7c, 0xd8, 0x8f, 0x6d, 0x2c, 0x98, 0x9e, 0x2b, 0x93, 0xf1, 0x5e, 0x46,
0xf0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xd7, 0x7f, 0xf9, 0xf0, 0xe5, 0x7d, 0xdb, 0x1d, 0x75,
0x19, 0xf3, 0xc4, 0x58, 0x9b, 0x17, 0x88, 0xa8, 0x92, 0xe0, 0xbe, 0xbd, 0x8b, 0x1d, 0x8d,
0x9f, 0x56, 0x76, 0xad, 0xaf, 0x29, 0xe2, 0xd9, 0xd5, 0x52, 0xf6, 0xb5, 0x56, 0x35, 0x57,
0x3a, 0xc8, 0xe1, 0x56, 0x43, 0x19, 0x94, 0xd3, 0x04, 0x9b, 0x6d, 0x35, 0xd8, 0x0b, 0x5f,
0x4d, 0x19, 0x8e, 0xec, 0xfa, 0x64, 0x91, 0x0a, 0x72, 0x20, 0x2b, 0xbc, 0x1a, 0x4a, 0xfe,
0x8b, 0xfd, 0xbb, 0xed, 0x1b, 0x23, 0xea, 0xad, 0x72, 0x82, 0xa1, 0x29, 0x99, 0x71, 0xbd,
0xf0, 0x95, 0xc1, 0x03, 0xdd, 0x7b, 0xc2, 0xb2, 0x3c, 0x28, 0x54, 0xd3, 0x68, 0xa4, 0x72,
0xc8, 0x66, 0x96, 0xe0, 0xd1, 0xd8, 0x7f, 0xf8, 0xd1, 0x26, 0x2b, 0xf7, 0xad, 0xba, 0x55,
0xca, 0x15, 0xb9, 0x32, 0xc3, 0xe5, 0x88, 0x97, 0x8e, 0x5c, 0xfb, 0x92, 0x25, 0x8b, 0xbf,
0xa2, 0x45, 0x55, 0x7a, 0xa7, 0x6f, 0x8b, 0x57, 0x5b, 0xcf, 0x0e, 0xcb, 0x1d, 0xfb, 0x20,
0x82, 0x77, 0xa8, 0x8c, 0xcc, 0x16, 0xce, 0x1d, 0xfa, 0xde, 0xcc, 0x0b, 0x62, 0xfe, 0xcc,
0xe1, 0xb7, 0xf0, 0xc3, 0x81, 0x64, 0x73, 0x40, 0xa0, 0xc2, 0x4d, 0x89, 0x11, 0x75, 0x33,
0x55, 0x33, 0x8d, 0xe8, 0x4a, 0xfd, 0xea, 0x6e, 0x30, 0x0b, 0xd7, 0x31, 0x2c, 0xde, 0x47,
0xe3, 0xbf, 0xf8, 0x55, 0x42, 0xe2, 0x7f, 0x59, 0xe5, 0x17, 0xef, 0x99, 0x34, 0x69, 0x91,
0xb1, 0x23, 0x8e, 0x20, 0x87, 0x2d, 0xa8, 0xfe, 0xd5, 0x8a, 0xf3, 0x84, 0x3a, 0xf0, 0x37,
0xe4, 0x09, 0x00, 0x54, 0xee, 0x67, 0x49, 0x93, 0xe4, 0x81, 0x70, 0xe3, 0x90, 0x4d, 0xef,
0xfe, 0x41, 0xb7, 0x99, 0x7b, 0xc1, 0x83, 0xba, 0x62, 0x12, 0x6f, 0x7d, 0xde, 0x6b, 0xaf,
0xda, 0x16, 0xf9, 0x55, 0x51, 0xee, 0xa6, 0x0c, 0x2b, 0x02, 0xa3, 0xfd, 0x8d, 0xfb, 0x30,
0x17, 0xe4, 0x6f, 0xdf, 0x36, 0x71, 0xc4, 0xca, 0x87, 0x25, 0x48, 0xb0, 0x47, 0xec, 0xea,
0xb4, 0xbf, 0xa5, 0x4d, 0x9b, 0x9f, 0x02, 0x93, 0xc4, 0xe3, 0xe4, 0xe8, 0x42, 0x2d, 0x68,
0x81, 0x15, 0x0a, 0xeb, 0x84, 0x5b, 0xd6, 0xa8, 0x74, 0xfb, 0x7d, 0x1d, 0xcb, 0x2c, 0xda,
0x46, 0x2a, 0x76, 0x62, 0xce, 0xbc, 0x5c, 0x9e, 0x8b, 0xe7, 0xcf, 0xbe, 0x78, 0xf5, 0x7c,
0xeb, 0xb3, 0x3a, 0x9c, 0xaa, 0x6f, 0xcc, 0x72, 0xd1, 0x59, 0xf2, 0x11, 0x23, 0xd6, 0x3f,
0x48, 0xd1, 0xb7, 0xce, 0xb0, 0xbf, 0xcb, 0xea, 0x80, 0xde, 0x57, 0xd4, 0x5e, 0x97, 0x2f,
0x75, 0xd1, 0x50, 0x8e, 0x80, 0x2c, 0x66, 0x79, 0xbf, 0x72, 0x4b, 0xbd, 0x8a, 0x81, 0x6c,
0xd3, 0xe1, 0x01, 0xdc, 0xd2, 0x15, 0x26, 0xc5, 0x36, 0xda, 0x2c, 0x1a, 0xc0, 0x27, 0x94,
0xed, 0xb7, 0x9b, 0x85, 0x0b, 0x5e, 0x80, 0x97, 0xc5, 0xec, 0x4f, 0xec, 0x88, 0x5d, 0x50,
0x07, 0x35, 0x47, 0xdc, 0x0b, 0x3b, 0x3d, 0xdd, 0x60, 0xaf, 0xa8, 0x5d, 0x81, 0x38, 0x24,
0x25, 0x5d, 0x5c, 0x15, 0xd1, 0xde, 0xb3, 0xab, 0xec, 0x05, 0x69, 0xef, 0x83, 0xed, 0x57,
0x54, 0xb8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xda, 0x9f, 0x2d, 0x7f, 0x36, 0xbb, 0x44,
0x5a, 0x34, 0xe8, 0x7f, 0xbf, 0x03, 0xeb, 0x00, 0x7f, 0x59, 0x68, 0x22, 0x79, 0xcf, 0x73,
0x6c, 0x2c, 0x29, 0xa7, 0xa1, 0x5f, 0x38, 0xa1, 0x1d, 0xf0, 0x20, 0x53, 0xe0, 0x1a, 0x63,
0x14, 0x58, 0x71, 0x10, 0xaa, 0x08, 0x0c, 0x3e, 0x16, 0x1a, 0x60, 0x22, 0x82, 0x7f, 0xba,
0xa4, 0x43, 0xa0, 0xd0, 0xac, 0x1b, 0xd5, 0x6b, 0x64, 0xb5, 0x14, 0x93, 0x31, 0x9e, 0x53,
0x50, 0xd0, 0x57, 0x66, 0xee, 0x5a, 0x4f, 0xfb, 0x03, 0x2a, 0x69, 0x58, 0x76, 0xf1, 0x83,
0xf7, 0x4e, 0xba, 0x8c, 0x42, 0x06, 0x60, 0x5d, 0x6d, 0xce, 0x60, 0x88, 0xae, 0xa4, 0xc3,
0xf1, 0x03, 0xa5, 0x4b, 0x98, 0xa1, 0xff, 0x67, 0xe1, 0xac, 0xa2, 0xb8, 0x62, 0xd7, 0x6f,
0xa0, 0x31, 0xb4, 0xd2, 0x77, 0xaf, 0x21, 0x10, 0x06, 0xc6, 0x9a, 0xff, 0x1d, 0x09, 0x17,
0x0e, 0x5f, 0xf1, 0xaa, 0x54, 0x34, 0x4b, 0x45, 0x8a, 0x87, 0x63, 0xa6, 0xdc, 0xf9, 0x24,
0x30, 0x67, 0xc6, 0xb2, 0xd6, 0x61, 0x33, 0x69, 0xee, 0x50, 0x61, 0x57, 0x28, 0xe7, 0x7e,
0xee, 0xec, 0x3a, 0x5a, 0x73, 0x4e, 0xa8, 0x8d, 0xe4, 0x18, 0xea, 0xec, 0x41, 0x64, 0xc8,
0xe2, 0xe8, 0x66, 0xb6, 0x2d, 0xb6, 0xfb, 0x6a, 0x6c, 0x16, 0xb3, 0xdd, 0x46, 0x43, 0xb9,
0x73, 0x00, 0x6a, 0x71, 0xed, 0x4e, 0x9d, 0x25, 0x1a, 0xc3, 0x3c, 0x4a, 0x95, 0x15, 0x99,
0x35, 0x81, 0x14, 0x02, 0xd6, 0x98, 0x9b, 0xec, 0xd8, 0x23, 0x3b, 0x84, 0x29, 0xaf, 0x0c,
0x99, 0x83, 0xa6, 0x9a, 0x34, 0x4f, 0xfa, 0xe8, 0xd0, 0x3c, 0x4b, 0xd0, 0xfb, 0xb6, 0x68,
0xb8, 0x9e, 0x8f, 0xcd, 0xf7, 0x60, 0x2d, 0x7a, 0x22, 0xe5, 0x7d, 0xab, 0x65, 0x1b, 0x95,
0xa7, 0xa8, 0x7f, 0xb6, 0x77, 0x47, 0x7b, 0x5f, 0x8b, 0x12, 0x72, 0xd0, 0xd4, 0x91, 0xef,
0xde, 0x19, 0x50, 0x3c, 0xa7, 0x8b, 0xc4, 0xa9, 0xb3, 0x23, 0xcb, 0x76, 0xe6, 0x81, 0xf0,
0xc1, 0x04, 0x8f, 0xa3, 0xb8, 0x54, 0x5b, 0x97, 0xac, 0x19, 0xff, 0x3f, 0x55, 0x27, 0x2f,
0xe0, 0x1d, 0x42, 0x9b, 0x57, 0xfc, 0x4b, 0x4e, 0x0f, 0xce, 0x98, 0xa9, 0x43, 0x57, 0x03,
0xbd, 0xe7, 0xc8, 0x94, 0xdf, 0x6e, 0x36, 0x73, 0x32, 0xb4, 0xef, 0x2e, 0x85, 0x7a, 0x6e,
0xfc, 0x6c, 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xf3, 0xe4, 0x9f, 0x3e, 0xdc, 0x68, 0xf3,
0xb5, 0xf3, 0x19, 0x80, 0x92, 0x06, 0x99, 0xa2, 0xe8, 0x6f, 0xff, 0x2e, 0x7f, 0xae, 0x42,
0xa4, 0x5f, 0xfb, 0xd4, 0x0e, 0x81, 0x2b, 0xc3, 0x04, 0xff, 0x2b, 0xb3, 0x74, 0x4e, 0x36,
0x5b, 0x9c, 0x15, 0x00, 0xc6, 0x47, 0x2b, 0xe8, 0x8b, 0x3d, 0xf1, 0x9c, 0x03, 0x9a, 0x58,
0x7f, 0x9b, 0x9c, 0xbf, 0x85, 0x49, 0x79, 0x35, 0x2e, 0x56, 0x7b, 0x41, 0x14, 0x39, 0x47,
0x83, 0x26, 0xaa, 0x07, 0x89, 0x98, 0x11, 0x1b, 0x86, 0xe7, 0x73, 0x7a, 0xd8, 0x7d, 0x78,
0x61, 0x53, 0xe9, 0x79, 0xf5, 0x36, 0x8d, 0x44, 0x92, 0x84, 0xf9, 0x13, 0x50, 0x58, 0x3b,
0xa4, 0x6a, 0x36, 0x65, 0x49, 0x8e, 0x3c, 0x0e, 0xf1, 0x6f, 0xd2, 0x84, 0xc4, 0x7e, 0x8e,
0x3f, 0x39, 0xae, 0x7c, 0x84, 0xf1, 0x63, 0x37, 0x8e, 0x3c, 0xcc, 0x3e, 0x44, 0x81, 0x45,
0xf1, 0x4b, 0xb9, 0xed, 0x6b, 0x36, 0x5d, 0xbb, 0x20, 0x60, 0x1a, 0x0f, 0xa3, 0xaa, 0x55,
0x77, 0x3a, 0xa9, 0xae, 0x37, 0x4d, 0xba, 0xb8, 0x86, 0x6b, 0xbc, 0x08, 0x50, 0xf6, 0xcc,
0xa4, 0xbd, 0x1d, 0x40, 0x72, 0xa5, 0x86, 0xfa, 0xe2, 0x10, 0xae, 0x3d, 0x58, 0x4b, 0x97,
0xf3, 0x43, 0x74, 0xa9, 0x9e, 0xeb, 0x21, 0xb7, 0x01, 0xa4, 0x86, 0x93, 0x97, 0xee, 0x2f,
0x4f, 0x3b, 0x86, 0xa1, 0x41, 0x6f, 0x41, 0x26, 0x90, 0x78, 0x5c, 0x7f, 0x30, 0x38, 0x4b,
0x3f, 0xaa, 0xec, 0xed, 0x5c, 0x6f, 0x0e, 0xad, 0x43, 0x87, 0xfd, 0x93, 0x35, 0xe6, 0x01,
0xef, 0x41, 0x26, 0x90, 0x99, 0x9e, 0xfb, 0x19, 0x5b, 0xad, 0xd2, 0x91, 0x8a, 0xe0, 0x46,
0xaf, 0x65, 0xfa, 0x4f, 0x84, 0xc1, 0xa1, 0x2d, 0xcf, 0x45, 0x8b, 0xd3, 0x85, 0x50, 0x55,
0x7c, 0xf9, 0x67, 0x88, 0xd4, 0x4e, 0xe9, 0xd7, 0x6b, 0x61, 0x54, 0xa1, 0xa4, 0xa6, 0xa2,
0xc2, 0xbf, 0x30, 0x9c, 0x40, 0x9f, 0x5f, 0xd7, 0x69, 0x2b, 0x24, 0x82, 0x5e, 0xd9, 0xd6,
0xa7, 0x12, 0x54, 0x1a, 0xf7, 0x55, 0x9f, 0x76, 0x50, 0xa9, 0x95, 0x84, 0xe6, 0x6b, 0x6d,
0xb5, 0x96, 0x54, 0xd6, 0xcd, 0xb3, 0xa1, 0x9b, 0x46, 0xa7, 0x94, 0x4d, 0xc4, 0x94, 0xb4,
0x98, 0xe3, 0xe1, 0xe2, 0x34, 0xd5, 0x33, 0x16, 0x07, 0x54, 0xcd, 0xb7, 0x77, 0x53, 0xdb,
0x4f, 0x4d, 0x46, 0x9d, 0xe9, 0xd4, 0x9c, 0x8a, 0x36, 0xb6, 0xb8, 0x38, 0x26, 0x6c, 0x0e,
0xff, 0x9c, 0x1b, 0x43, 0x8b, 0x80, 0xcc, 0xb9, 0x3d, 0xda, 0xc7, 0xf1, 0x8a, 0xf2, 0x6d,
0xb8, 0xd7, 0x74, 0x2f, 0x7e, 0x1e, 0xb7, 0xd3, 0x4a, 0xb4, 0xac, 0xfc, 0x79, 0x48, 0x6c,
0xbc, 0x96, 0xb6, 0x94, 0x46, 0x57, 0x2d, 0xb0, 0xa3, 0xfc, 0x1e, 0xb9, 0x52, 0x60, 0x85,
0x2d, 0x41, 0xd0, 0x43, 0x01, 0x1e, 0x1c, 0xd5, 0x7d, 0xfc, 0xf3, 0x96, 0x0d, 0xc7, 0xcb,
0x2a, 0x29, 0x9a, 0x93, 0xdd, 0x88, 0x2d, 0x37, 0x5d, 0xaa, 0xfb, 0x49, 0x68, 0xa0, 0x9c,
0x50, 0x86, 0x7f, 0x68, 0x56, 0x57, 0xf9, 0x79, 0x18, 0x39, 0xd4, 0xe0, 0x01, 0x84, 0x33,
0x61, 0xca, 0xa5, 0xd2, 0xd6, 0xe4, 0xc9, 0x8a, 0x4a, 0x23, 0x44, 0x4e, 0xbc, 0xf0, 0xdc,
0x24, 0xa1, 0xa0, 0xc4, 0xe2, 0x07, 0x3c, 0x10, 0xc4, 0xb5, 0x25, 0x4b, 0x65, 0x63, 0xf4,
0x80, 0xe7, 0xcf, 0x61, 0xb1, 0x71, 0x82, 0x21, 0x87, 0x2c, 0xf5, 0x91, 0x00, 0x32, 0x0c,
0xec, 0xa9, 0xb5, 0x9a, 0x74, 0x85, 0xe3, 0x36, 0x8f, 0x76, 0x4f, 0x9c, 0x6d, 0xce, 0xbc,
0xad, 0x0a, 0x4b, 0xed, 0x76, 0x04, 0xcb, 0xc3, 0xb9, 0x33, 0x9e, 0x01, 0x93, 0x96, 0x69,
0x7d, 0xc5, 0xa2, 0x45, 0x79, 0x9b, 0x04, 0x5c, 0x84, 0x09, 0xed, 0x88, 0x43, 0xc7, 0xab,
0x93, 0x14, 0x26, 0xa1, 0x40, 0xb5, 0xce, 0x4e, 0xbf, 0x2a, 0x42, 0x85, 0x3e, 0x2c, 0x3b,
0x54, 0xe8, 0x12, 0x1f, 0x0e, 0x97, 0x59, 0xb2, 0x27, 0x89, 0xfa, 0xf2, 0xdf, 0x8e, 0x68,
0x59, 0xdc, 0x06, 0xbc, 0xb6, 0x85, 0x0d, 0x06, 0x22, 0xec, 0xb1, 0xcb, 0xe5, 0x04, 0xe6,
0x3d, 0xb3, 0xb0, 0x41, 0x73, 0x08, 0x3f, 0x3c, 0x58, 0x86, 0x63, 0xeb, 0x50, 0xee, 0x1d,
0x2c, 0x37, 0x74, 0xa9, 0xd3, 0x18, 0xa3, 0x47, 0x6e, 0x93, 0x54, 0xad, 0x0a, 0x5d, 0xb8,
0x2a, 0x55, 0x5d, 0x78, 0xf6, 0xee, 0xbe, 0x8e, 0x3c, 0x76, 0x69, 0xb9, 0x40, 0xc2, 0x34,
0xec, 0x2a, 0xb9, 0xed, 0x7e, 0x20, 0xe4, 0x8d, 0x00, 0x38, 0xc7, 0xe6, 0x8f, 0x44, 0xa8,
0x86, 0xce, 0xeb, 0x2a, 0xe9, 0x90, 0xf1, 0x4c, 0xdf, 0x32, 0xfb, 0x73, 0x1b, 0x6d, 0x92,
0x1e, 0x95, 0xfe, 0xb4, 0xdb, 0x65, 0xdf, 0x4d, 0x23, 0x54, 0x89, 0x48, 0xbf, 0x4a, 0x2e,
0x70, 0xd6, 0xd7, 0x62, 0xb4, 0x33, 0x29, 0xb1, 0x3a, 0x33, 0x4c, 0x23, 0x6d, 0xa6, 0x76,
0xa5, 0x21, 0x63, 0x48, 0xe6, 0x90, 0x5d, 0xed, 0x90, 0x95, 0x0b, 0x7a, 0x84, 0xbe, 0xb8,
0x0d, 0x5e, 0x63, 0x0c, 0x62, 0x26, 0x4c, 0x14, 0x5a, 0xb3, 0xac, 0x23, 0xa4, 0x74, 0xa7,
0x6f, 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xa0, 0x28, 0xb7, 0xee, 0x19, 0x38, 0xf1, 0x64,
0x80, 0x82, 0x43, 0xe1, 0x41, 0x27, 0x1f, 0x1f, 0x90, 0x54, 0x7a, 0xd5, 0x23, 0x2e, 0xd1,
0x3d, 0xcb, 0x28, 0xba, 0x58, 0x7f, 0xdc, 0x7c, 0x91, 0x24, 0xe9, 0x28, 0x51, 0x83, 0x6e,
0xc5, 0x56, 0x21, 0x42, 0xed, 0xa0, 0x56, 0x22, 0xa1, 0x40, 0x80, 0x6b, 0xa8, 0xf7, 0x94,
0xca, 0x13, 0x6b, 0x0c, 0x39, 0xd9, 0xfd, 0xe9, 0xf3, 0x6f, 0xa6, 0x9e, 0xfc, 0x70, 0x8a,
0xb3, 0xbc, 0x59, 0x3c, 0x1e, 0x1d, 0x6c, 0xf9, 0x7c, 0xaf, 0xf9, 0x88, 0x71, 0x95, 0xeb,
0x57, 0x00, 0xbd, 0x9f, 0x8c, 0x4f, 0xe1, 0x24, 0x83, 0xc5, 0x22, 0xea, 0xfd, 0xd3, 0x0c,
0xe2, 0x17, 0x18, 0x7c, 0x6a, 0x4c, 0xde, 0x77, 0xb4, 0x53, 0x9b, 0x4c, 0x81, 0xcd, 0x23,
0x60, 0xaa, 0x0e, 0x25, 0x73, 0x9c, 0x02, 0x79, 0x32, 0x30, 0xdf, 0x74, 0xdf, 0x75, 0x19,
0xf4, 0xa5, 0x14, 0x5c, 0xf7, 0x7a, 0xa8, 0xa5, 0x91, 0x84, 0x7c, 0x60, 0x03, 0x06, 0x3b,
0xcd, 0x50, 0xb6, 0x27, 0x9c, 0xfe, 0xb1, 0xdd, 0xcc, 0xd3, 0xb0, 0x59, 0x24, 0xb2, 0xca,
0xe2, 0x1c, 0x81, 0x22, 0x9d, 0x07, 0x8f, 0x8e, 0xb9, 0xbe, 0x4e, 0xfa, 0xfc, 0x39, 0x65,
0xba, 0xbf, 0x9d, 0x12, 0x37, 0x5e, 0x97, 0x7e, 0xf3, 0x89, 0xf5, 0x5d, 0xf5, 0xe3, 0x09,
0x8c, 0x62, 0xb5, 0x20, 0x9d, 0x0c, 0x53, 0x8a, 0x68, 0x1b, 0xd2, 0x8f, 0x75, 0x17, 0x5d,
0xd4, 0xe5, 0xda, 0x75, 0x62, 0x19, 0x14, 0x6a, 0x26, 0x2d, 0xeb, 0xf8, 0xaf, 0x37, 0xf0,
0x6c, 0xa4, 0x55, 0xb1, 0xbc, 0xe2, 0x33, 0xc0, 0x9a, 0xca, 0xb0, 0x11, 0x49, 0x4f, 0x68,
0x9b, 0x3b, 0x6b, 0x3c, 0xcc, 0x13, 0xf6, 0xc7, 0x85, 0x61, 0x68, 0x42, 0xae, 0xbb, 0xdd,
0xcd, 0x45, 0x16, 0x29, 0x1d, 0xea, 0xdb, 0xc8, 0x03, 0x94, 0x3c, 0xee, 0x4f, 0x82, 0x11,
0xc3, 0xec, 0x28, 0xbd, 0x97, 0x05, 0x99, 0xde, 0xd7, 0xbb, 0x5e, 0x22, 0x1f, 0xd4, 0xeb,
0x64, 0xd9, 0x92, 0xd9, 0x85, 0xb7, 0x6a, 0x05, 0x6a, 0xe4, 0x24, 0x41, 0xf1, 0xcd, 0xf0,
0xd8, 0x3f, 0xf8, 0x9e, 0x0e, 0xcd, 0x0b, 0x7a, 0x70, 0x6b, 0x5a, 0x75, 0x0a, 0x6a, 0x33,
0x88, 0xec, 0x17, 0x75, 0x08, 0x70, 0x10, 0x2f, 0x24, 0xcf, 0xc4, 0xe9, 0x42, 0x00, 0x61,
0x94, 0xca, 0x1f, 0x3a, 0x76, 0x06, 0xfa, 0xd2, 0x48, 0x81, 0xf0, 0x77, 0x60, 0x03, 0x45,
0xd9, 0x61, 0xf4, 0xa4, 0x6f, 0x3d, 0xd9, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec,
0x3b, 0xf4, 0x4b, 0xf5, 0x68, 0x52, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5,
0xa9, 0xb1, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xa5, 0xa9, 0xb1,
0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0xeb, 0x54, 0x0b,
0x75, 0x68, 0x52, 0x07, 0x8c, 0x9a, 0x97, 0x8d, 0x79, 0x70, 0x62, 0x46, 0xef, 0x5c, 0x1b,
0x95, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x67, 0x4c, 0x1a, 0xb6,
0xcf, 0xfd, 0x78, 0x53, 0x24, 0xab, 0xb5, 0xc9, 0xf1, 0x60, 0x23, 0xa5, 0xc8, 0x12, 0x87,
0x6d, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xc7, 0x0c, 0x9a, 0x97, 0xac,
0xda, 0x36, 0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x47,
0xed, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8c, 0x7b, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef,
0x3d, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xdf,
0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x53, 0x05, 0x69,
0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x27, 0xcc, 0xfb, 0x74,
0x4b, 0x14, 0x8b, 0x94, 0x8b, 0x75, 0x68, 0x33, 0xc5, 0x08, 0x92, 0x87, 0x8c, 0x9a, 0xb6,
0xcf, 0x1c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0x89, 0x71, 0x60,
0x23, 0xc4, 0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xf6, 0x6e, 0x3f, 0xfc, 0x5b, 0x15, 0xa8, 0xd2,
0x26, 0xaf, 0xbd, 0xf8, 0x72, 0x66, 0x2f, 0xdc, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa,
0xb7, 0xcd, 0xf9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6f, 0x3d, 0xd9, 0x30, 0xe2, 0x27, 0xcc,
0xfb, 0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x70, 0x43, 0x04, 0x6b, 0x35, 0xc9, 0xf1,
0x60, 0x23, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xe6, 0x2f, 0xbd,
0xf8, 0x72, 0x66, 0x4e, 0x1e, 0xbe, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x1d, 0x99, 0x91, 0xa0,
0xa3, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93, 0xa4, 0xab, 0xd4, 0x0b, 0x75, 0x49, 0x10, 0xa2,
0xc6, 0xef, 0x3d, 0xf8, 0x53, 0x24, 0xab, 0xb5, 0xe8, 0x33, 0xe4, 0x4a, 0x16, 0xae, 0xde,
0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xb3, 0xc5, 0x08, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0xe1, 0x21,
0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x5c, 0x3a, 0xd7, 0x0d, 0x98, 0x93, 0xa4, 0xca,
0x16, 0xae, 0xde, 0x1f, 0x9d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x72, 0x47, 0x0c,
0x9a, 0xb6, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87,
0x6d, 0x39, 0xf0, 0x43, 0x04, 0x8a, 0x96, 0xae, 0xde, 0x3e, 0xdf, 0x1d, 0x99, 0x91, 0xa0,
0xc2, 0x06, 0x6f, 0x3d, 0xf8, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0x8d, 0x98, 0x93, 0x85, 0x88,
0x73, 0x45, 0xe9, 0x31, 0xe0, 0x23, 0xa5, 0xa9, 0xd0, 0x03, 0x84, 0x8a, 0x96, 0xae, 0xde,
0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xd2, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x82,
0x67, 0x2d, 0xd8, 0x13, 0xa4, 0xab, 0xd4, 0x0b, 0x94, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20,
0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0xe9, 0x50, 0x22, 0xc6, 0xef, 0x5c, 0x3a, 0xd7, 0x0d, 0x98,
0x93, 0x85, 0x88, 0x73, 0x64, 0x4a, 0xf7, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0x0a, 0x96,
0xae, 0xde, 0x3e, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x78, 0x72,
0x66, 0x2f, 0xbd, 0xd9, 0x30, 0xc3, 0xe5, 0x48, 0x12, 0x87, 0x8c, 0x7b, 0x55, 0x28, 0xd2,
0x07, 0x8c, 0x9a, 0x97, 0xac, 0xda, 0x17, 0x8d, 0x79, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x54,
0x0b, 0x94, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xfc, 0x5b, 0x15, 0xa8, 0xd2, 0x26, 0xaf,
0xdc, 0x1b, 0xb4, 0xea, 0x37, 0xec, 0x3b, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0x93, 0x85, 0x69,
0x31, 0xc1, 0xe1, 0x40, 0xe3, 0x25, 0xc8, 0x12, 0x87, 0x8c, 0x9a, 0xb6, 0xcf, 0xfd, 0x59,
0x11, 0xa0, 0xc2, 0x06, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x37,
0xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0x95, 0x89, 0x71, 0x41,
0x00, 0x63, 0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x0f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0x93, 0x85,
0x69, 0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x9e, 0xbe, 0xdf, 0x3c, 0xfa, 0x57, 0x2c, 0xda,
0x36, 0xee, 0x3f, 0xfc, 0x5b, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d,
0x38, 0xf2, 0x47, 0xed, 0x58, 0x13, 0xa4, 0xca, 0xf7, 0x4d, 0xf9, 0x51, 0x01, 0x80, 0x63,
0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xa9, 0xb1,
0xe0, 0x42, 0x06, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0x0a, 0x96, 0x8f, 0x7d,
0x78, 0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0xbc, 0xfa, 0x57, 0x0d,
0x79, 0x51, 0x01, 0x61, 0x21, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xc1, 0xe1, 0x40, 0x02,
0x67, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xd6, 0x0f, 0x9c, 0x9b,
0xb4, 0xcb, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x35, 0xc9, 0xf1,
0x60, 0x42, 0x06, 0x8e, 0x7f, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xfc, 0x7a, 0x76, 0x6e, 0x5e,
0x3e, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xc0, 0xe3, 0x44,
0xeb, 0x54, 0x2a, 0xb7, 0xcd, 0xf9, 0x70, 0x62, 0x27, 0xad, 0xd8, 0x32, 0xc7, 0x0c, 0x7b,
0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x39, 0xd1, 0x20,
0xc2, 0xe7, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0xb2, 0xc7, 0x0c, 0x59, 0x28, 0xf3, 0x9b };

M keyboards/oddball/readme.md => keyboards/oddball/readme.md +10 -3
@@ 3,11 3,18 @@
A split keyboard with trackball support.

* Keyboard Maintainer: [Alexander Tulloh](https://github.com/atulloh)
* Hardware Supported: Oddball PCB and plates, and using an [ADNS9800 and breakout board for mouse](https://www.tindie.com/products/jkicklighter/adns-9800-laser-motion-sensor/)
* Hardware Supported: Oddball PCB and plates, and using an [ADNS9800](https://www.tindie.com/products/jkicklighter/adns-9800-laser-motion-sensor/) or a [PMW3360](https://www.tindie.com/products/jkicklighter/pmw3360-motion-sensor/) breakout board for mouse
* Hardware Availability: [atulloh.github.io/oddball](https://atulloh.github.io/oddball)

Make example for this keyboard (after setting up your build environment):
Make examples for this keyboard (after setting up your build environment):

    make oddball:default
```
# with ADNS sensor
make oddball/v2:default
```
```
# with PMW sensor
make oddball/v2:pmw3360
```

See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

M keyboards/oddball/rules.mk => keyboards/oddball/rules.mk +9 -17
@@ 1,24 1,14 @@
# MCU name
MCU = atmega32u4

# Bootloader selection
#   Teensy       halfkay
#   Pro Micro    caterina
#   Atmel DFU    atmel-dfu
#   LUFA DFU     lufa-dfu
#   QMK DFU      qmk-dfu
#   ATmega32A    bootloadHID
#   ATmega328P   USBasp
BOOTLOADER = halfkay

# Build Options
#   change yes to no to disable
#
BOOTMAGIC_ENABLE = no       # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes       # Mouse keys
MOUSEKEY_ENABLE = no        # Mouse keys
EXTRAKEY_ENABLE = yes       # Audio control and System control
CONSOLE_ENABLE = no        # Console for debug
COMMAND_ENABLE = yes        # Commands for debug and configuration
CONSOLE_ENABLE = no         # Console for debug
COMMAND_ENABLE = no         # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no       # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work


@@ 30,9 20,11 @@ BLUETOOTH_ENABLE = no       # Enable Bluetooth with the Adafruit EZ-Key HID
AUDIO_ENABLE = no           # Audio output on port C6
FAUXCLICKY_ENABLE = no      # Use buzzer to emulate clicky switches

DEBOUNCE_TYPE = eager_pk
SPLIT_KEYBOARD = yes

# Add trackball support
POINTING_DEVICE_ENABLE = yes
SRC += adns.c

DEFAULT_FOLDER = oddball/v1

SRC += spi_master.c
SRC += adns/adns.c
SRC += pmw/pmw.c

A keyboards/oddball/v1/config.h => keyboards/oddball/v1/config.h +31 -0
@@ 0,0 1,31 @@
/* 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

/*
 * Keyboard Matrix Assignments
 *
 * Change this to how you wired your keyboard
 * COLS: AVR pins used for columns, left to right
 * ROWS: AVR pins used for rows, top to bottom
 * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
 *                  ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
 *
 */
#define MATRIX_ROW_PINS { F6, B5, B6, F7 }
#define MATRIX_COL_PINS { D6, D7, B4, D3, C6, C7 }
#define UNUSED_PINS { B7, D4, D5, E6, F0, F1, F4, F5 }

A keyboards/oddball/v1/readme.md => keyboards/oddball/v1/readme.md +12 -0
@@ 0,0 1,12 @@
# Oddball v1

Make examples for this keyboard (after setting up your build environment):

```
# with ADNS sensor
make oddball/v1:default
```
```
# with PMW sensor
make oddball/v1:pmw3360
```

A keyboards/oddball/v1/rules.mk => keyboards/oddball/v1/rules.mk +2 -0
@@ 0,0 1,2 @@
# Teensy 2.0
BOOTLOADER = halfkay

A keyboards/oddball/v1/v1.c => keyboards/oddball/v1/v1.c +17 -0
@@ 0,0 1,17 @@
/* 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 "v1.h"

A keyboards/oddball/v1/v1.h => keyboards/oddball/v1/v1.h +19 -0
@@ 0,0 1,19 @@
/* 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 "oddball.h"

A keyboards/oddball/v2/config.h => keyboards/oddball/v2/config.h +31 -0
@@ 0,0 1,31 @@
/* 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

/*
 * Keyboard Matrix Assignments
 *
 * Change this to how you wired your keyboard
 * COLS: AVR pins used for columns, left to right
 * ROWS: AVR pins used for rows, top to bottom
 * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
 *                  ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
 *
 */
#define MATRIX_ROW_PINS { D4, E6, D7, C6 }
#define MATRIX_COL_PINS { B7, B5, B4, F5, F6, F7 }
#define UNUSED_PINS { D3, D5, C7, F1, F0, B6, F4 }

A keyboards/oddball/v2/readme.md => keyboards/oddball/v2/readme.md +12 -0
@@ 0,0 1,12 @@
# Oddball v2

Make examples for this keyboard (after setting up your build environment):

```
# with ADNS sensor
make oddball/v2:default
```
```
# with PMW sensor
make oddball/v2:pmw3360
```

A keyboards/oddball/v2/rules.mk => keyboards/oddball/v2/rules.mk +2 -0
@@ 0,0 1,2 @@
# Elite C
BOOTLOADER = qmk-dfu

A keyboards/oddball/v2/v2.c => keyboards/oddball/v2/v2.c +17 -0
@@ 0,0 1,17 @@
/* 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 "v2.h"

A keyboards/oddball/v2/v2.h => keyboards/oddball/v2/v2.h +19 -0
@@ 0,0 1,19 @@
/* 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 "oddball.h"

A keyboards/oddball/v2_1/config.h => keyboards/oddball/v2_1/config.h +31 -0
@@ 0,0 1,31 @@
/* 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

/*
 * Keyboard Matrix Assignments
 *
 * Change this to how you wired your keyboard
 * COLS: AVR pins used for columns, left to right
 * ROWS: AVR pins used for rows, top to bottom
 * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
 *                  ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
 *
 */
#define MATRIX_ROW_PINS { D4, E6, D7, C6 }
#define MATRIX_COL_PINS { B6, B5, B4, F5, F6, F7 }
#define UNUSED_PINS { D3, D5, C7, F1, F0, B7, F4 }

A keyboards/oddball/v2_1/readme.md => keyboards/oddball/v2_1/readme.md +12 -0
@@ 0,0 1,12 @@
# Oddball v2.1

Make examples for this keyboard (after setting up your build environment):

```
# with ADNS sensor
make oddball/v2_1:default
```
```
# with PMW sensor
make oddball/v2_1:pmw3360
```

A keyboards/oddball/v2_1/rules.mk => keyboards/oddball/v2_1/rules.mk +2 -0
@@ 0,0 1,2 @@
# Elite C
BOOTLOADER = qmk-dfu

A keyboards/oddball/v2_1/v2_1.c => keyboards/oddball/v2_1/v2_1.c +17 -0
@@ 0,0 1,17 @@
/* 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 "v2_1.h"

A keyboards/oddball/v2_1/v2_1.h => keyboards/oddball/v2_1/v2_1.h +19 -0
@@ 0,0 1,19 @@
/* 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 "oddball.h"