Co-authored-by: James Young <18669334+noroadsleft@users.noreply.github.com> Co-authored-by: Erovia <Erovia@users.noreply.github.com>pull/11250/head
@ -0,0 +1,221 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 "5x6_right_trackball.h" | |||
#ifndef TRACKBALL_DPI_OPTIONS | |||
# define TRACKBALL_DPI_OPTIONS { 1200, 1600, 2400 } | |||
# ifndef TRACKBALL_DPI_DEFAULT | |||
# define TRACKBALL_DPI_DEFAULT 1 | |||
# endif | |||
#endif | |||
#ifndef TRACKBALL_DPI_DEFAULT | |||
# define TRACKBALL_DPI_DEFAULT 0 | |||
#endif | |||
keyboard_config_t keyboard_config; | |||
uint16_t dpi_array[] = TRACKBALL_DPI_OPTIONS; | |||
#define DPI_OPTION_SIZE (sizeof(dpi_array) / sizeof(uint16_t)) | |||
bool BurstState = false; // init burst state for Trackball module | |||
uint16_t MotionStart = 0; // Timer for accel, 0 is resting state | |||
__attribute__((weak)) void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) { | |||
mouse_report->x = x; | |||
mouse_report->y = y; | |||
} | |||
__attribute__((weak)) void process_mouse(report_mouse_t* mouse_report) { | |||
report_pmw_t data = pmw_read_burst(); | |||
if (data.isOnSurface && data.isMotion) { | |||
// Reset timer if stopped moving | |||
if (!data.isMotion) { | |||
if (MotionStart != 0) MotionStart = 0; | |||
return; | |||
} | |||
// Set timer if new motion | |||
if ((MotionStart == 0) && data.isMotion) { | |||
if (debug_mouse) dprintf("Starting motion.\n"); | |||
MotionStart = timer_read(); | |||
} | |||
if (debug_mouse) { | |||
dprintf("Delt] d: %d t: %u\n", abs(data.dx) + abs(data.dy), MotionStart); | |||
} | |||
if (debug_mouse) { | |||
dprintf("Pre ] X: %d, Y: %d\n", data.dx, data.dy); | |||
} | |||
#if defined(PROFILE_LINEAR) | |||
float scale = float(timer_elaspsed(MotionStart)) / 1000.0; | |||
data.dx *= scale; | |||
data.dy *= scale; | |||
#elif defined(PROFILE_INVERSE) | |||
// TODO | |||
#else | |||
// no post processing | |||
#endif | |||
// Wrap to HID size | |||
data.dx = constrain(data.dx, -127, 127); | |||
data.dy = constrain(data.dy, -127, 127); | |||
if (debug_mouse) dprintf("Cons] X: %d, Y: %d\n", data.dx, data.dy); | |||
// dprintf("Elapsed:%u, X: %f Y: %\n", i, pgm_read_byte(firmware_data+i)); | |||
mouse_report->x = -data.dx; | |||
mouse_report->y = data.dy; | |||
} | |||
} | |||
bool process_record_kb(uint16_t keycode, keyrecord_t* record) { | |||
if (!process_record_user(keycode, record)) { return false; } | |||
#ifdef POINTING_DEVICE_ENABLE | |||
if (keycode == DPI_CONFIG && record->event.pressed) { | |||
keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE; | |||
eeconfig_update_kb(keyboard_config.raw); | |||
trackball_set_cpi(dpi_array[keyboard_config.dpi_config]); | |||
} | |||
#endif | |||
/* If Mousekeys is disabled, then use handle the mouse button | |||
* keycodes. This makes things simpler, and allows usage of | |||
* the keycodes in a consistent manner. But only do this if | |||
* Mousekeys is not enable, so it's not handled twice. | |||
*/ | |||
#ifndef MOUSEKEY_ENABLE | |||
if (IS_MOUSEKEY_BUTTON(keycode)) { | |||
report_mouse_t currentReport = pointing_device_get_report(); | |||
if (record->event.pressed) { | |||
currentReport.buttons |= 1 << (keycode - KC_MS_BTN1); | |||
} else { | |||
currentReport.buttons &= ~(1 << (keycode - KC_MS_BTN1)); | |||
} | |||
pointing_device_set_report(currentReport); | |||
pointing_device_send(); | |||
} | |||
#endif | |||
return true; | |||
} | |||
// Hardware Setup | |||
void keyboard_pre_init_kb(void) { | |||
// debug_enable = true; | |||
// debug_matrix = true; | |||
// debug_mouse = true; | |||
// debug_encoder = true; | |||
/* Ground all output pins connected to ground. This provides additional | |||
* pathways to ground. If you're messing with this, know this: driving ANY | |||
* of these pins high will cause a short. On the MCU. Ka-blooey. | |||
*/ | |||
// This is the debug LED. | |||
#if defined(DEBUG_LED_PIN) | |||
setPinOutput(DEBUG_LED_PIN); | |||
writePin(DEBUG_LED_PIN, debug_enable); | |||
#endif | |||
keyboard_pre_init_user(); | |||
} | |||
#ifdef POINTING_DEVICE_ENABLE | |||
void pointing_device_init(void) { | |||
if (!is_keyboard_left()) { | |||
// initialize ball sensor | |||
pmw_spi_init(); | |||
} | |||
trackball_set_cpi(dpi_array[keyboard_config.dpi_config]); | |||
} | |||
static bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { | |||
return (new.buttons != old.buttons) || | |||
(new.x && new.x != old.x) || | |||
(new.y && new.y != old.y) || | |||
(new.h && new.h != old.h) || | |||
(new.v && new.v != old.v); | |||
} | |||
void pointing_device_task(void) { | |||
report_mouse_t mouse_report = pointing_device_get_report(); | |||
if (!is_keyboard_left()) { | |||
process_mouse(&mouse_report); | |||
} | |||
pointing_device_set_report(mouse_report); | |||
pointing_device_send(); | |||
} | |||
#endif | |||
void eeconfig_init_kb(void) { | |||
keyboard_config.dpi_config = TRACKBALL_DPI_DEFAULT; | |||
trackball_set_cpi(dpi_array[keyboard_config.dpi_config]); | |||
eeconfig_update_kb(keyboard_config.raw); | |||
} | |||
void matrix_init_kb(void) { | |||
// is safe to just read DPI setting since matrix init | |||
// comes before pointing device init. | |||
keyboard_config.raw = eeconfig_read_kb(); | |||
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) { | |||
eeconfig_init_kb(); | |||
} | |||
matrix_init_user(); | |||
} | |||
#ifdef POINTING_DEVICE_ENABLE | |||
void pointing_device_send(void) { | |||
static report_mouse_t old_report = {}; | |||
report_mouse_t mouseReport = pointing_device_get_report(); | |||
if (is_keyboard_master()) { | |||
int8_t x = mouseReport.x, y = mouseReport.y; | |||
mouseReport.x = 0; | |||
mouseReport.y = 0; | |||
process_mouse_user(&mouseReport, x, y); | |||
if (has_mouse_report_changed(mouseReport, old_report)) { | |||
host_mouse_send(&mouseReport); | |||
} | |||
} else { | |||
master_mouse_send(mouseReport.x, mouseReport.y); | |||
} | |||
mouseReport.x = 0; | |||
mouseReport.y = 0; | |||
mouseReport.v = 0; | |||
mouseReport.h = 0; | |||
old_report = mouseReport; | |||
pointing_device_set_report(mouseReport); | |||
} | |||
#endif | |||
#ifdef SWAP_HANDS_ENABLE | |||
const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { | |||
/* Left hand, matrix positions */ | |||
{{5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}}, | |||
{{5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7}, {0, 7}}, | |||
{{5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8}}, | |||
{{5, 9}, {4, 9}, {3, 9}, {2, 9}, {1, 9}, {0, 9}}, | |||
{{5, 10}, {4, 10}, {3, 10}, {2, 10}, {1, 10}, {0, 10}}, | |||
{{5, 11}, {4, 11}, {3, 11}, {2, 11}, {1, 11}, {0, 11}}, | |||
/* Right hand, matrix positions */ | |||
{{5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, | |||
{{5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, | |||
{{5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, | |||
{{5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}}, | |||
{{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}, | |||
{{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}} | |||
}; | |||
#endif |
@ -0,0 +1,73 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 "dactyl_manuform.h" | |||
#include "quantum.h" | |||
#include "spi_master.h" | |||
#include "pmw3360.h" | |||
#include "pointing_device.h" | |||
#define ___ KC_NO | |||
#define LAYOUT_5x6_right_trackball(\ | |||
L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \ | |||
L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \ | |||
L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \ | |||
L30, L31, L32, L33, L34, L35, R30, R31, R32, R33, R34, R35, \ | |||
L42, L43, R42, R43, \ | |||
L44, L45, R41, \ | |||
L54, L55, R51, \ | |||
L52, L53, R52, R53 \ | |||
) \ | |||
{ \ | |||
{ L00, L01, L02, L03, L04, L05 }, \ | |||
{ L10, L11, L12, L13, L14, L15 }, \ | |||
{ L20, L21, L22, L23, L24, L25 }, \ | |||
{ L30, L31, L32, L33, L34, L35 }, \ | |||
{ ___, ___, L42, L43, L44, L45 }, \ | |||
{ ___, ___, L52, L53, L54, L55 }, \ | |||
\ | |||
{ R00, R01, R02, R03, R04, R05 }, \ | |||
{ R10, R11, R12, R13, R14, R15 }, \ | |||
{ R20, R21, R22, R23, R24, R25 }, \ | |||
{ R30, R31, R32, R33, R34, R35 }, \ | |||
{ ___, R41, R42, R43, ___, ___ }, \ | |||
{ ___, R51, R52, R53, ___, ___ } \ | |||
} | |||
void process_wheel(report_mouse_t* mouse_report); | |||
void process_wheel_user(report_mouse_t* mouse_report, int16_t h, int16_t v); | |||
typedef union { | |||
uint32_t raw; | |||
struct { | |||
uint8_t dpi_config; | |||
}; | |||
} keyboard_config_t; | |||
extern keyboard_config_t keyboard_config; | |||
enum ploopy_keycodes { | |||
DPI_CONFIG = SAFE_RANGE, | |||
KEYMAP_SAFE_RANGE, | |||
}; | |||
void master_mouse_send(int8_t x, int8_t y); | |||
void trackball_set_cpi(uint16_t cpi); |
@ -0,0 +1,67 @@ | |||
/* | |||
Copyright 2012 Jun Wako <wakojun@gmail.com> | |||
Copyright 2015 Jack Humbert | |||
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 "config_common.h" | |||
#define PRODUCT_ID 0x3536 | |||
#define DEVICE_VER 0x0001 | |||
#define PRODUCT Tractyl-Manuform (5x6 with right side Trackball) | |||
/* key matrix size */ | |||
// Rows are doubled-up | |||
#define MATRIX_ROWS 12 | |||
#define MATRIX_COLS 6 | |||
// wiring of each half | |||
#define MATRIX_COL_PINS { C0, C1, C2, C3, C4, C5 } | |||
#define MATRIX_ROW_PINS { F7, F6, F5, F4, F3, F2 } | |||
#define DIODE_DIRECTION COL2ROW | |||
// WS2812 RGB LED strip input and number of LEDs | |||
#define RGB_DI_PIN D3 | |||
#define RGBLED_NUM 8 | |||
#define RGBLIGHT_SPLIT | |||
#define RGBLED_SPLIT { 0 , 8 } | |||
#define RGBLIGHT_SLEEP | |||
#define RGBW | |||
#define RGBLIGHT_LIMIT_VAL 150 | |||
/* define if matrix has ghost */ | |||
//#define MATRIX_HAS_GHOST | |||
/* number of backlight levels */ | |||
// #define BACKLIGHT_LEVELS 3 | |||
#define DEBUG_LED_PIN D6 | |||
#define USB_POLLING_INTERVAL_MS 1 | |||
#define ROTATIONAL_TRANSFORM_ANGLE -25 | |||
/* Bootmagic Lite key configuration */ | |||
#define BOOTMAGIC_LITE_ROW 0 | |||
#define BOOTMAGIC_LITE_COLUMN 0 | |||
#define BOOTMAGIC_LITE_ROW_RIGHT 6 | |||
#define BOOTMAGIC_LITE_COLUMN_RIGHT 5 | |||
#define C6_AUDIO | |||
#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095 | |||
#define DYNAMIC_KEYMAP_LAYER_COUNT 16 |
@ -0,0 +1,75 @@ | |||
{ | |||
"keyboard_name": "Dactyl Manuform 5x6", | |||
"url": "", | |||
"maintainer": "qmk", | |||
"width": 17, | |||
"height": 8, | |||
"layouts": { | |||
"LAYOUT_5x6": { | |||
"layout": [ | |||
{"label":"L00", "x":0, "y":0}, | |||
{"label":"L01", "x":1, "y":0}, | |||
{"label":"L02", "x":2, "y":0}, | |||
{"label":"L03", "x":3, "y":0}, | |||
{"label":"L04", "x":4, "y":0}, | |||
{"label":"L05", "x":5, "y":0}, | |||
{"label":"R00", "x":11, "y":0}, | |||
{"label":"R01", "x":12, "y":0}, | |||
{"label":"R02", "x":13, "y":0}, | |||
{"label":"R03", "x":14, "y":0}, | |||
{"label":"R04", "x":15, "y":0}, | |||
{"label":"R05", "x":16, "y":0}, | |||
{"label":"L10", "x":0, "y":1}, | |||
{"label":"L11", "x":1, "y":1}, | |||
{"label":"L12", "x":2, "y":1}, | |||
{"label":"L13", "x":3, "y":1}, | |||
{"label":"L14", "x":4, "y":1}, | |||
{"label":"L15", "x":5, "y":1}, | |||
{"label":"R10", "x":11, "y":1}, | |||
{"label":"R11", "x":12, "y":1}, | |||
{"label":"R12", "x":13, "y":1}, | |||
{"label":"R13", "x":14, "y":1}, | |||
{"label":"R14", "x":15, "y":1}, | |||
{"label":"R15", "x":16, "y":1}, | |||
{"label":"L20", "x":0, "y":2}, | |||
{"label":"L21", "x":1, "y":2}, | |||
{"label":"L22", "x":2, "y":2}, | |||
{"label":"L23", "x":3, "y":2}, | |||
{"label":"L24", "x":4, "y":2}, | |||
{"label":"L25", "x":5, "y":2}, | |||
{"label":"R20", "x":11, "y":2}, | |||
{"label":"R21", "x":12, "y":2}, | |||
{"label":"R22", "x":13, "y":2}, | |||
{"label":"R23", "x":14, "y":2}, | |||
{"label":"R24", "x":15, "y":2}, | |||
{"label":"R25", "x":16, "y":2}, | |||
{"label":"L30", "x":0, "y":3}, | |||
{"label":"L31", "x":1, "y":3}, | |||
{"label":"L32", "x":2, "y":3}, | |||
{"label":"L33", "x":3, "y":3}, | |||
{"label":"L34", "x":4, "y":3}, | |||
{"label":"L35", "x":5, "y":3}, | |||
{"label":"R30", "x":11, "y":3}, | |||
{"label":"R31", "x":12, "y":3}, | |||
{"label":"R32", "x":13, "y":3}, | |||
{"label":"R33", "x":14, "y":3}, | |||
{"label":"R34", "x":15, "y":3}, | |||
{"label":"R35", "x":16, "y":3}, | |||
{"label":"L42", "x":2, "y":4}, | |||
{"label":"L43", "x":3, "y":4}, | |||
{"label":"R42", "x":13, "y":4}, | |||
{"label":"R43", "x":14, "y":4}, | |||
{"label":"L44", "x":4, "y":5}, | |||
{"label":"L45", "x":5, "y":5}, | |||
{"label":"R41", "x":12, "y":5}, | |||
{"label":"L54", "x":6, "y":6}, | |||
{"label":"L55", "x":7, "y":6}, | |||
{"label":"R51", "x":10, "y":6}, | |||
{"label":"L52", "x":6, "y":7}, | |||
{"label":"L53", "x":7, "y":7}, | |||
{"label":"R52", "x":9, "y":7}, | |||
{"label":"R53", "x":10, "y":7} | |||
] | |||
} | |||
} | |||
} |
@ -0,0 +1,27 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 | |||
#define USE_SERIAL | |||
#define MASTER_LEFT | |||
// #define MASTER_RIGHT | |||
//#define EE_HANDS | |||
// Rows are doubled-up |
@ -0,0 +1,63 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 | |||
#define _QWERTY 0 | |||
#define _LOWER 1 | |||
#define _RAISE 2 | |||
#define RAISE MO(_RAISE) | |||
#define LOWER MO(_LOWER) | |||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
[_QWERTY] = LAYOUT_5x6_right_trackball( | |||
KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 ,KC_BSPC, | |||
KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P ,KC_MINS, | |||
KC_LSFT, KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L ,KC_SCLN,KC_QUOT, | |||
KC_LCTL, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M ,KC_COMM,KC_DOT ,KC_SLSH,KC_BSLASH, | |||
KC_LBRC,KC_RBRC, KC_EQL, | |||
RAISE,KC_SPC, LOWER, | |||
KC_TAB,KC_HOME, KC_END, KC_DEL, | |||
KC_BSPC, KC_GRV, KC_LGUI, KC_LALT | |||
), | |||
[_LOWER] = LAYOUT_5x6_right_trackball( | |||
KC_TILD,KC_EXLM, KC_AT ,KC_HASH,KC_DLR ,KC_PERC, KC_CIRC,KC_AMPR,KC_ASTR,KC_LPRN,KC_RPRN,KC_DEL, | |||
_______,_______,_______,_______,_______,KC_LBRC, KC_RBRC, KC_P7 , KC_P8 , KC_P9 ,_______,KC_PLUS, | |||
_______,KC_HOME,KC_PGUP,KC_PGDN,KC_END ,KC_LPRN, KC_RPRN, KC_P4 , KC_P5 , KC_P6 ,KC_MINS,KC_PIPE, | |||
_______,_______,_______,_______,_______,_______, _______, KC_P1 , KC_P2 , KC_P3 ,KC_EQL ,KC_UNDS, | |||
_______,KC_PSCR, KC_P0, | |||
_______,_______, _______, | |||
_______,_______, _______,_______, | |||
_______,_______, _______,_______ | |||
), | |||
[_RAISE] = LAYOUT_5x6_right_trackball( | |||
KC_F12 , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 ,KC_F10 ,KC_F11 , | |||
_______,_______,_______,_______,_______,KC_LBRC, KC_RBRC,_______,KC_NLCK,KC_INS ,KC_SLCK,KC_MUTE, | |||
_______,KC_LEFT,KC_UP ,KC_DOWN,KC_RGHT,KC_LPRN, KC_RPRN,KC_MPRV,KC_MPLY,KC_MNXT,_______,KC_VOLU, | |||
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,KC_VOLD, | |||
_______,_______, _______, | |||
_______,_______, _______, | |||
_______,_______, _______,_______, | |||
_______,_______, _______,_______ | |||
), | |||
}; |
@ -0,0 +1,28 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 | |||
// #define USE_I2C | |||
#define EE_HANDS | |||
#define TRACKBALL_DPI_OPTIONS \ | |||
{ 1200, 1800, 2600, 3400 } | |||
#define RGBLIGHT_EFFECT_TWINKLE_LIFE 50 | |||
#define RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 1/63 | |||
#define SOLENOID_PIN F1 |
@ -0,0 +1,197 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 "drashna.h" | |||
#define TG_DBLO TG(_DIABLO) | |||
#define _MOUSE _MEDIA | |||
// clang-format off | |||
#define LAYOUT_5x6_right_trackball_wrapper(...) LAYOUT_5x6_right_trackball(__VA_ARGS__) | |||
#define LAYOUT_5x6_right_trackball_base( \ | |||
K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, \ | |||
K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, \ | |||
K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A \ | |||
) \ | |||
LAYOUT_5x6_right_trackball_wrapper( \ | |||
KC_GRV, ________________NUMBER_LEFT________________, ________________NUMBER_RIGHT_______________, KC_MINS, \ | |||
KC_ESC, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, KC_BSLS, \ | |||
LALT_T(KC_TAB), K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, RALT_T(KC_QUOT), \ | |||
OS_LSFT, CTL_T(K21), K22, K23, K24, K25, K26, K27, K28, K29, RCTL_T(K2A), OS_RSFT, \ | |||
OS_LALT, OS_LGUI, TG_GAME, TG_DBLO, \ | |||
OS_LGUI, KC_GRV, OS_RGUI, \ | |||
KC_SPC, _______, KC_ENT, \ | |||
BK_LWER, MO(_MOUSE), MO(_MOUSE), DL_RAIS \ | |||
) | |||
#define LAYOUT_5x6_right_trackball_base_wrapper(...) LAYOUT_5x6_right_trackball_base(__VA_ARGS__) | |||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
[_QWERTY] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_________________QWERTY_L1_________________, _________________QWERTY_R1_________________, | |||
_________________QWERTY_L2_________________, _________________QWERTY_R2_________________, | |||
_________________QWERTY_L3_________________, _________________QWERTY_R3_________________ | |||
), | |||
[_COLEMAK] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_________________COLEMAK_L1________________, _________________COLEMAK_R1________________, | |||
_________________COLEMAK_L2________________, _________________COLEMAK_R2________________, | |||
_________________COLEMAK_L3________________, _________________COLEMAK_R3________________ | |||
), | |||
[_DVORAK] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_________________DVORAK_L1_________________, _________________DVORAK_R1_________________, | |||
_________________DVORAK_L2_________________, _________________DVORAK_R2_________________, | |||
_________________DVORAK_L3_________________, _________________DVORAK_R3_________________ | |||
), | |||
[_WORKMAN] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_________________WORKMAN_L1________________, _________________WORKMAN_R1________________, | |||
_________________WORKMAN_L2________________, _________________WORKMAN_R2________________, | |||
_________________WORKMAN_L3________________, _________________WORKMAN_R3________________ | |||
), | |||
[_NORMAN] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_________________NORMAN_L1_________________, _________________NORMAN_L1_________________, | |||
_________________NORMAN_L2_________________, _________________NORMAN_R2_________________, | |||
_________________NORMAN_L3_________________, _________________NORMAN_R3_________________ | |||
), | |||
[_MALTRON] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_________________MALTRON_L1________________, _________________MALTRON_R1________________, | |||
_________________MALTRON_L2________________, _________________MALTRON_R2________________, | |||
_________________MALTRON_L3________________, _________________MALTRON_R3________________ | |||
), | |||
[_EUCALYN] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_________________EUCALYN_L1________________, _________________EUCALYN_R1________________, | |||
_________________EUCALYN_L2________________, _________________EUCALYN_R2________________, | |||
_________________EUCALYN_L3________________, _________________EUCALYN_R3________________ | |||
), | |||
[_CARPLAX] = LAYOUT_5x6_right_trackball_base_wrapper( | |||
_____________CARPLAX_QFMLWY_L1_____________, _____________CARPLAX_QFMLWY_R1_____________, | |||
_____________CARPLAX_QFMLWY_L2_____________, _____________CARPLAX_QFMLWY_R2_____________, | |||
_____________CARPLAX_QFMLWY_L3_____________, _____________CARPLAX_QFMLWY_R3_____________ | |||
), | |||
[_MOUSE] = LAYOUT_5x6_right_trackball( | |||
_______, _______, _______, _______, _______, _______, DPI_CONFIG, _______, _______, _______, _______, _______, | |||
_______, _______, _______, _______, _______, _______, KC_WH_U, _______, _______, _______, _______, _______, | |||
_______, _______, _______, _______, _______, _______, KC_WH_D, KC_BTN1, KC_BTN3, KC_BTN2, _______, _______, | |||
_______, _______, _______, _______, _______, _______, _______, KC_BTN4, KC_BTN5, _______, _______, _______, | |||
_______, _______, _______, _______, | |||
_______, _______, _______, | |||
_______, _______, _______, | |||
_______, _______, _______, _______ | |||
), | |||
[_GAMEPAD] = LAYOUT_5x6_right_trackball( | |||
KC_ESC, KC_NO, KC_1, KC_2, KC_3, KC_4, DPI_CONFIG, _______, _______, _______, _______, _______, | |||
KC_F1, KC_K, KC_Q, KC_W, KC_E, KC_R, KC_WH_U, _______, _______, _______, _______, _______, | |||
KC_TAB, KC_G, KC_A, KC_S, KC_D, KC_F, KC_WH_D, KC_BTN1, KC_BTN3, KC_BTN2, _______, _______, | |||
KC_LCTL, KC_LSFT, KC_Z, KC_X, KC_C, KC_H, _______, KC_BTN4, KC_BTN5, _______, _______, _______, | |||
KC_I, KC_T, TG_GAME, KC_NO, | |||
KC_V, KC_O, _______, | |||
KC_SPC, KC_P, _______, | |||
KC_H, KC_LGUI, _______, _______ | |||
), | |||
[_DIABLO] = LAYOUT_5x6_right_trackball( | |||
KC_ESC, KC_V, KC_D, KC_LALT, KC_NO, KC_NO, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, | |||
KC_TAB, KC_S, KC_I, KC_F, KC_M, KC_T, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, | |||
KC_Q, KC_1, KC_2, KC_3, KC_4, KC_G, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, | |||
KC_LCTL, KC_D3_1, KC_D3_2, KC_D3_3, KC_D3_4, KC_Z, KC_NO, KC_N, KC_M, KC_NO, KC_NO, KC_NO, | |||
KC_F, KC_L, KC_NO, TG_DBLO, | |||
SFT_T(KC_SPC), KC_F, _______, | |||
ALT_T(KC_Q), KC_J, _______, | |||
KC_DIABLO_CLEAR, KC_LGUI, _______, _______ | |||
), | |||
[_LOWER] = LAYOUT_5x6_right_trackball_wrapper( | |||
KC_F12, _________________FUNC_LEFT_________________, _________________FUNC_RIGHT________________, KC_F11, | |||
_______, _________________LOWER_L1__________________, _________________LOWER_R1__________________, _______, | |||
_______, _________________LOWER_L2__________________, _________________LOWER_R2__________________, KC_PIPE, | |||
_______, _________________LOWER_L3__________________, _________________LOWER_R3__________________, _______, | |||
_______, _______, _______, _______, | |||
_______, _______, _______, | |||
_______, _______, _______, | |||
_______, _______, _______, _______ | |||
), | |||
[_RAISE] = LAYOUT_5x6_right_trackball_wrapper( | |||
KC_F12, _________________FUNC_LEFT_________________, _________________FUNC_RIGHT________________, KC_F11, | |||
KC_GRV, _________________RAISE_L1__________________, _________________RAISE_R1__________________, _______, | |||
_______, _________________RAISE_L2__________________, _________________RAISE_R2__________________, KC_BSLS, | |||
_______, _________________RAISE_L3__________________, _________________RAISE_R3__________________, _______, | |||
_______, _______, _______, _______, | |||
_______, _______, _______, | |||
_______, _______, _______, | |||
_______, _______, _______, _______ | |||
), | |||
[_ADJUST] = LAYOUT_5x6_right_trackball_wrapper( | |||
KC_MAKE, ___________________BLANK___________________, _________________ADJUST_R1_________________, KC_RST, | |||
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EEP_RST, | |||
_______, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS, | |||
_______, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY, | |||
HPT_DWLI, HPT_DWLD, _______, _______, | |||
HPT_TOG, HPT_BUZ, KC_NUKE, | |||
_______, _______, _______, | |||
_______, _______, KC_NUKE, _______ | |||
), | |||
}; | |||
// clang-format off | |||
#ifdef POINTING_DEVICE_ENABLE | |||
static uint16_t mouse_timer = 0; | |||
static uint16_t mouse_debounce_timer = 0; | |||
static uint8_t mouse_keycode_tracker = 0; | |||
void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) { | |||
if ((x || y) && timer_elapsed(mouse_timer) > 125) { | |||
mouse_timer = timer_read(); | |||
if (!layer_state_is(_MOUSE) && !layer_state_is(_GAMEPAD) && timer_elapsed(mouse_debounce_timer) > 125) { | |||
layer_on(_MOUSE); | |||
} | |||
} | |||
if (timer_elapsed(mouse_debounce_timer) > 125 || layer_state_is(_GAMEPAD) ) { | |||
mouse_report->x = x; | |||
mouse_report->y = y; | |||
} | |||
} | |||
void matrix_scan_keymap(void) { | |||
if (timer_elapsed(mouse_timer) > 750 && layer_state_is(_MOUSE) && !mouse_keycode_tracker) { | |||
layer_off(_MOUSE); | |||
} | |||
} | |||
bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { | |||
switch(keycode){ | |||
case MO(_MOUSE): | |||
case DPI_CONFIG: | |||
case KC_MS_UP...KC_MS_WH_RIGHT: | |||
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--; | |||
mouse_timer = timer_read(); | |||
break; | |||
default: | |||
if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) { | |||
layer_off(_MOUSE); | |||
} | |||
mouse_debounce_timer = timer_read(); | |||
break; | |||
} | |||
return true; | |||
} | |||
#endif |
@ -0,0 +1,2 @@ | |||
RGBLIGHT_STARTUP_ANIMATION = yes | |||
HAPTIC_ENABLE = SOLENOID |
@ -0,0 +1,225 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* Copyright 2019 Sunjun Kim | |||
* Copyright 2020 Ploopy Corporation | |||
* | |||
* 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 "pmw3360.h" | |||
#include "pmw3360_firmware.h" | |||
#ifdef CONSOLE_ENABLE | |||
# include "print.h" | |||
#endif | |||
bool _inBurst = false; | |||
#ifndef PMW_CPI | |||
# define PMW_CPI 1600 | |||
#endif | |||
#ifndef SPI_DIVISOR | |||
# define SPI_DIVISOR 2 | |||
#endif | |||
#ifndef ROTATIONAL_TRANSFORM_ANGLE | |||
# define ROTATIONAL_TRANSFORM_ANGLE 0x00 | |||
#endif | |||
#ifdef CONSOLE_ENABLE | |||
void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); } | |||
#endif | |||
bool spi_start_adv(void) { | |||
bool status = spi_start(SPI_SS_PIN, false, 3, SPI_DIVISOR); | |||
wait_us(1); | |||
return status; | |||
} | |||
void spi_stop_adv(void) { | |||
wait_us(1); | |||
spi_stop(); | |||
} | |||
spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) { | |||
if (reg_addr != REG_Motion_Burst) { | |||
_inBurst = false; | |||
} | |||
spi_start_adv(); | |||
// send address of the register, with MSBit = 1 to indicate it's a write | |||
spi_status_t status = spi_write(reg_addr | 0x80); | |||
status = spi_write(data); | |||
// tSCLK-NCS for write operation | |||
wait_us(20); | |||
// tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound | |||
wait_us(100); | |||
spi_stop(); | |||
return status; | |||
} | |||
uint8_t spi_read_adv(uint8_t reg_addr) { | |||
spi_start_adv(); | |||
// send adress of the register, with MSBit = 0 to indicate it's a read | |||
spi_write(reg_addr & 0x7f); | |||
uint8_t data = spi_read(); | |||
// tSCLK-NCS for read operation is 120ns | |||
wait_us(1); | |||
// tSRW/tSRR (=20us) minus tSCLK-NCS | |||
wait_us(19); | |||
spi_stop(); | |||
return data; | |||
} | |||
void pmw_set_cpi(uint16_t cpi) { | |||
int cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119 | |||
spi_start_adv(); | |||
spi_write_adv(REG_Config1, cpival); | |||
spi_stop(); | |||
} | |||
bool pmw_spi_init(void) { | |||
spi_init(); | |||
_inBurst = false; | |||
spi_stop(); | |||
spi_start_adv(); | |||
spi_stop(); | |||
spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first | |||
wait_ms(300); | |||
spi_start_adv(); | |||
wait_us(40); | |||
spi_stop_adv(); | |||
wait_us(40); | |||
spi_write_adv(REG_Power_Up_Reset, 0x5a); | |||
wait_ms(50); | |||
spi_read_adv(REG_Motion); | |||
spi_read_adv(REG_Delta_X_L); | |||
spi_read_adv(REG_Delta_X_H); | |||
spi_read_adv(REG_Delta_Y_L); | |||
spi_read_adv(REG_Delta_Y_H); | |||
pmw_upload_firmware(); | |||
spi_stop_adv(); | |||
wait_ms(10); | |||
pmw_set_cpi(PMW_CPI); | |||
wait_ms(1); | |||
return pmw_check_signature(); | |||
} | |||
void pmw_upload_firmware(void) { | |||
spi_write_adv(REG_Config2, 0x00); | |||
spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30)); | |||
spi_write_adv(REG_SROM_Enable, 0x1d); | |||
wait_ms(10); | |||
spi_write_adv(REG_SROM_Enable, 0x18); | |||
spi_start_adv(); | |||
spi_write(REG_SROM_Load_Burst | 0x80); | |||
wait_us(15); | |||
unsigned char c; | |||
for (int i = 0; i < firmware_length; i++) { | |||
c = (unsigned char)pgm_read_byte(firmware_data + i); | |||
spi_write(c); | |||
wait_us(15); | |||
} | |||
wait_us(200); | |||
spi_read_adv(REG_SROM_ID); | |||
spi_write_adv(REG_Config2, 0x00); | |||
spi_stop(); | |||
wait_ms(10); | |||
} | |||
bool pmw_check_signature(void) { | |||
uint8_t pid = spi_read_adv(REG_Product_ID); | |||
uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID); | |||
uint8_t SROM_ver = spi_read_adv(REG_SROM_ID); | |||
return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04 | |||
} | |||
report_pmw_t pmw_read_burst(void) { | |||
if (!_inBurst) { | |||
#ifdef CONSOLE_ENABLE | |||
dprintf("burst on"); | |||
#endif | |||
spi_write_adv(REG_Motion_Burst, 0x00); | |||
_inBurst = true; | |||
} | |||
spi_start_adv(); | |||
spi_write(REG_Motion_Burst); | |||
wait_us(35); // waits for tSRAD | |||
report_pmw_t data; | |||
data.motion = 0; | |||
data.dx = 0; | |||
data.mdx = 0; | |||
data.dy = 0; | |||
data.mdx = 0; | |||
data.motion = spi_read(); | |||
spi_write(0x00); // skip Observation | |||
data.dx = spi_read(); | |||
data.mdx = spi_read(); | |||
data.dy = spi_read(); | |||
data.mdy = spi_read(); | |||
spi_stop(); | |||
#ifdef CONSOLE_ENABLE | |||
print_byte(data.motion); | |||
print_byte(data.dx); | |||
print_byte(data.mdx); | |||
print_byte(data.dy); | |||
print_byte(data.mdy); | |||
dprintf("\n"); | |||
#endif | |||
data.isMotion = (data.motion & 0x80) != 0; | |||
data.isOnSurface = (data.motion & 0x08) == 0; | |||
data.dx |= (data.mdx << 8); | |||
data.dx = data.dx * -1; | |||
data.dy |= (data.mdy << 8); | |||
data.dy = data.dy * -1; | |||
spi_stop(); | |||
if (data.motion & 0b111) { // panic recovery, sometimes burst mode works weird. | |||
_inBurst = false; | |||
} | |||
return data; | |||
} |
@ -0,0 +1,103 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* Copyright 2019 Sunjun Kim | |||
* Copyright 2020 Ploopy Corporation | |||
* | |||
* 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 "spi_master.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_Raw_Data_Sum 0x08 | |||
#define REG_Maximum_Raw_data 0x09 | |||
#define REG_Minimum_Raw_data 0x0A | |||
#define REG_Shutter_Lower 0x0B | |||
#define REG_Shutter_Upper 0x0C | |||
#define REG_Control 0x0D | |||
#define REG_Config1 0x0F | |||
#define REG_Config2 0x10 | |||
#define REG_Angle_Tune 0x11 | |||
#define REG_Frame_Capture 0x12 | |||
#define REG_SROM_Enable 0x13 | |||
#define REG_Run_Downshift 0x14 | |||
#define REG_Rest1_Rate_Lower 0x15 | |||
#define REG_Rest1_Rate_Upper 0x16 | |||
#define REG_Rest1_Downshift 0x17 | |||
#define REG_Rest2_Rate_Lower 0x18 | |||
#define REG_Rest2_Rate_Upper 0x19 | |||
#define REG_Rest2_Downshift 0x1A | |||
#define REG_Rest3_Rate_Lower 0x1B | |||
#define REG_Rest3_Rate_Upper 0x1C | |||
#define REG_Observation 0x24 | |||
#define REG_Data_Out_Lower 0x25 | |||
#define REG_Data_Out_Upper 0x26 | |||
#define REG_Raw_Data_Dump 0x29 | |||
#define REG_SROM_ID 0x2A | |||
#define REG_Min_SQ_Run 0x2B | |||
#define REG_Raw_Data_Threshold 0x2C | |||
#define REG_Config5 0x2F | |||
#define REG_Power_Up_Reset 0x3A | |||
#define REG_Shutdown 0x3B | |||
#define REG_Inverse_Product_ID 0x3F | |||
#define REG_LiftCutoff_Tune3 0x41 | |||
#define REG_Angle_Snap 0x42 | |||
#define REG_LiftCutoff_Tune1 0x4A | |||
#define REG_Motion_Burst 0x50 | |||
#define REG_LiftCutoff_Tune_Timeout 0x58 | |||
#define REG_LiftCutoff_Tune_Min_Length 0x5A | |||
#define REG_SROM_Load_Burst 0x62 | |||
#define REG_Lift_Config 0x63 | |||
#define REG_Raw_Data_Burst 0x64 | |||
#define REG_LiftCutoff_Tune2 0x65 | |||
#ifdef CONSOLE_ENABLE | |||
void print_byte(uint8_t byte); | |||
#endif | |||
typedef struct { | |||
int8_t motion; | |||
bool isMotion; // True if a motion is detected. | |||
bool isOnSurface; // True when a chip is on a surface | |||
int16_t dx; // displacement on x directions. Unit: Count. (CPI * Count = Inch value) | |||
int8_t mdx; | |||
int16_t dy; // displacement on y directions. | |||
int8_t mdy; | |||
} report_pmw_t; | |||
bool spi_start_adv(void); | |||
void spi_stop_adv(void); | |||
spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data); | |||
uint8_t spi_read_adv(uint8_t reg_addr); | |||
bool pmw_spi_init(void); | |||
void pmw_set_cpi(uint16_t cpi); | |||
void pmw_upload_firmware(void); | |||
bool pmw_check_signature(void); | |||
report_pmw_t pmw_read_burst(void); | |||
#define degToRad(angleInDegrees) ((angleInDegrees)*M_PI / 180.0) | |||
#define radToDeg(angleInRadians) ((angleInRadians)*180.0 / M_PI) | |||
#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt))) |
@ -0,0 +1,300 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* Copyright 2019 Sunjun Kim | |||
* Copyright 2020 Ploopy Corporation | |||
* | |||
* 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 | |||
// clang-format off | |||
// Firmware Blob foor PMW3360 | |||
const uint16_t firmware_length = 4094; | |||
// clang-format off | |||
const uint8_t firmware_data[] PROGMEM = { // SROM 0x04 | |||
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 }; | |||
// clang-format off |
@ -0,0 +1,375 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 <string.h> | |||
#include <stddef.h> | |||
#include "matrix.h" | |||
#include QMK_KEYBOARD_H | |||
#define ROWS_PER_HAND (MATRIX_ROWS / 2) | |||
#ifdef RGBLIGHT_ENABLE | |||
# include "rgblight.h" | |||
#endif | |||
#ifdef BACKLIGHT_ENABLE | |||
# include "backlight.h" | |||
#endif | |||
#ifdef ENCODER_ENABLE | |||
# include "encoder.h" | |||
static pin_t encoders_pad[] = ENCODERS_PAD_A; | |||
# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) | |||
#endif | |||
#ifdef POINTING_DEVICE_ENABLE | |||
static uint16_t device_cpi = 0; | |||
static int8_t split_mouse_x = 0, split_mouse_y = 0; | |||
#endif | |||
#if defined(USE_I2C) | |||
# include "i2c_master.h" | |||
# include "i2c_slave.h" | |||
typedef struct _I2C_slave_buffer_t { | |||
matrix_row_t smatrix[ROWS_PER_HAND]; | |||
uint8_t backlight_level; | |||
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | |||
rgblight_syncinfo_t rgblight_sync; | |||
# endif | |||
# ifdef ENCODER_ENABLE | |||
uint8_t encoder_state[NUMBER_OF_ENCODERS]; | |||
# endif | |||
# ifdef WPM_ENABLE | |||
uint8_t current_wpm; | |||
# endif | |||
int8_t mouse_x; | |||
int8_t mouse_y; | |||
uint16_t device_cpi; | |||
} I2C_slave_buffer_t; | |||
static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; | |||
# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) | |||
# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) | |||
# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, mmatrix) | |||
# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) | |||
# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) | |||
# define I2C_MOUSE_X_START offsetof(I2C_slave_buffer_t, mouse_x) | |||
# define I2C_MOUSE_Y_START offsetof(I2C_slave_buffer_t, mouse_y) | |||
# define I2C_MOUSE_DPI_START offsetof(I2C_slave_buffer_t, device_cpi) | |||
# define TIMEOUT 100 | |||
# ifndef SLAVE_I2C_ADDRESS | |||
# define SLAVE_I2C_ADDRESS 0x32 | |||
# endif | |||
// Get rows from other half over i2c | |||
bool transport_master(matrix_row_t matrix[]) { | |||
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); | |||
// write backlight info | |||
# ifdef BACKLIGHT_ENABLE | |||
uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; | |||
if (level != i2c_buffer->backlight_level) { | |||
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { | |||
i2c_buffer->backlight_level = level; | |||
} | |||
} | |||
# endif | |||
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | |||
if (rgblight_get_change_flags()) { | |||
rgblight_syncinfo_t rgblight_sync; | |||
rgblight_get_syncinfo(&rgblight_sync); | |||
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { | |||
rgblight_clear_change_flags(); | |||
} | |||
} | |||
# endif | |||
# ifdef ENCODER_ENABLE | |||
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); | |||
encoder_update_raw(i2c_buffer->encoder_state); | |||
# endif | |||
# ifdef WPM_ENABLE | |||
uint8_t current_wpm = get_current_wpm(); | |||
if (current_wpm != i2c_buffer->current_wpm) { | |||
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)¤t_wpm, sizeof(current_wpm), TIMEOUT) >= 0) { | |||
i2c_buffer->current_wpm = current_wpm; | |||
} | |||
} | |||
# endif | |||
# ifdef POINTING_DEVICE_ENABLE | |||
if (is_keyboard_left()) { | |||
report_mouse_t temp_report = pointing_device_get_report(); | |||
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT); | |||
temp_report.x = i2c_buffer->mouse_x; | |||
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT); | |||
temp_report.y = i2c_buffer->mouse_y; | |||
pointing_device_set_report(temp_report); | |||
if (device_cpi != i2c_buffer->device_cpi) { | |||
if(i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_DPI_START, (void *)&device_cpi, sizeof(device_cpi), TIMEOUT) >= 0) { | |||
i2c_buffer->device_cpi = device_cpi | |||
} | |||
} | |||
} | |||
# endif | |||
return true; | |||
} | |||
void transport_slave(matrix_row_t matrix[]) { | |||
// Copy matrix to I2C buffer | |||
memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); | |||
// Read Backlight Info | |||
# ifdef BACKLIGHT_ENABLE | |||
backlight_set(i2c_buffer->backlight_level); | |||
# endif | |||
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | |||
// Update the RGB with the new data | |||
if (i2c_buffer->rgblight_sync.status.change_flags != 0) { | |||
rgblight_update_sync(&i2c_buffer->rgblight_sync, false); | |||
i2c_buffer->rgblight_sync.status.change_flags = 0; | |||
} | |||
# endif | |||
# ifdef ENCODER_ENABLE | |||
encoder_state_raw(i2c_buffer->encoder_state); | |||
# endif | |||
# ifdef WPM_ENABLE | |||
set_current_wpm(i2c_buffer->current_wpm); | |||
# endif | |||
# ifdef POINTING_DEVICE_ENABLE | |||
if (!is_keyboard_left()) { | |||
static uint16_t cpi; | |||
if (cpi != i2c_buffer->device_cpi) { | |||
cpi = i2c_buffer->device_cpi; | |||
pmw_set_cpi(cpi); | |||
} | |||
i2c_buffer->mouse_x = split_mouse_x; | |||
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT); | |||
i2c_buffer->mouse_y = split_mouse_y; | |||
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT); | |||
} | |||
# endif | |||
} | |||
void transport_master_init(void) { i2c_init(); } | |||
void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } | |||
#else // USE_SERIAL | |||
# include "serial.h" | |||
typedef struct _Serial_s2m_buffer_t { | |||
// TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack | |||
matrix_row_t smatrix[ROWS_PER_HAND]; | |||
# ifdef ENCODER_ENABLE | |||
uint8_t encoder_state[NUMBER_OF_ENCODERS]; | |||
# endif | |||
int8_t mouse_x; | |||
int8_t mouse_y; | |||
} Serial_s2m_buffer_t; | |||
typedef struct _Serial_m2s_buffer_t { | |||
# ifdef BACKLIGHT_ENABLE | |||
uint8_t backlight_level; | |||
# endif | |||
# ifdef WPM_ENABLE | |||
uint8_t current_wpm; | |||
# endif | |||
uint16_t device_cpi; | |||
} Serial_m2s_buffer_t; | |||
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | |||
// When MCUs on both sides drive their respective RGB LED chains, | |||
// it is necessary to synchronize, so it is necessary to communicate RGB | |||
// information. In that case, define RGBLIGHT_SPLIT with info on the number | |||
// of LEDs on each half. | |||
// | |||
// Otherwise, if the master side MCU drives both sides RGB LED chains, | |||
// there is no need to communicate. | |||
typedef struct _Serial_rgblight_t { | |||
rgblight_syncinfo_t rgblight_sync; | |||
} Serial_rgblight_t; | |||
volatile Serial_rgblight_t serial_rgblight = {}; | |||
uint8_t volatile status_rgblight = 0; | |||
# endif | |||
volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; | |||
volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; | |||
uint8_t volatile status0 = 0; | |||
enum serial_transaction_id { | |||
GET_SLAVE_MATRIX = 0, | |||
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | |||
PUT_RGBLIGHT, | |||
# endif | |||
}; | |||
SSTD_t transactions[] = { | |||
[GET_SLAVE_MATRIX] = | |||
{ | |||
(uint8_t *)&status0, | |||
sizeof(serial_m2s_buffer), | |||
(uint8_t *)&serial_m2s_buffer, | |||
sizeof(serial_s2m_buffer), | |||
(uint8_t *)&serial_s2m_buffer, | |||
}, | |||
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | |||
[PUT_RGBLIGHT] = | |||
{ | |||
(uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer | |||
}, | |||
# endif | |||
}; | |||
void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } | |||
void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } | |||
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | |||
// rgblight synchronization information communication. | |||
void transport_rgblight_master(void) { | |||
if (rgblight_get_change_flags()) { | |||
rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); | |||
if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { | |||
rgblight_clear_change_flags(); | |||
} | |||
} | |||
} | |||
void transport_rgblight_slave(void) { | |||
if (status_rgblight == TRANSACTION_ACCEPTED) { | |||
rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false); | |||
status_rgblight = TRANSACTION_END; | |||
} | |||
} | |||
# else | |||
# define transport_rgblight_master() | |||
# define transport_rgblight_slave() | |||
# endif | |||
bool transport_master(matrix_row_t matrix[]) { | |||
# ifndef SERIAL_USE_MULTI_TRANSACTION | |||
if (soft_serial_transaction() != TRANSACTION_END) { | |||
return false; | |||
} | |||
# else | |||
transport_rgblight_master(); | |||
if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { | |||
return false; | |||
} | |||
# endif | |||
// TODO: if MATRIX_COLS > 8 change to unpack() | |||
for (int i = 0; i < ROWS_PER_HAND; ++i) { | |||
matrix[i] = serial_s2m_buffer.smatrix[i]; | |||
} | |||
# ifdef BACKLIGHT_ENABLE | |||
// Write backlight level for slave to read | |||
serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0; | |||
# endif | |||
# ifdef ENCODER_ENABLE | |||
encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); | |||
# endif | |||
# ifdef WPM_ENABLE | |||
// Write wpm to slave | |||
serial_m2s_buffer.current_wpm = get_current_wpm(); | |||
# endif | |||
# ifdef POINTING_DEVICE_ENABLE | |||
if (is_keyboard_left()) { | |||
report_mouse_t temp_report = pointing_device_get_report(); | |||
temp_report.x = serial_s2m_buffer.mouse_x; | |||
temp_report.y = serial_s2m_buffer.mouse_y; | |||
pointing_device_set_report(temp_report); | |||
serial_m2s_buffer.device_cpi = device_cpi; | |||
} | |||
# endif | |||
return true; | |||
} | |||
void transport_slave(matrix_row_t matrix[]) { | |||
transport_rgblight_slave(); | |||
// TODO: if MATRIX_COLS > 8 change to pack() | |||
for (int i = 0; i < ROWS_PER_HAND; ++i) { | |||
serial_s2m_buffer.smatrix[i] = matrix[i]; | |||
} | |||
# ifdef BACKLIGHT_ENABLE | |||
backlight_set(serial_m2s_buffer.backlight_level); | |||
# endif | |||
# ifdef ENCODER_ENABLE | |||
encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); | |||
# endif | |||
# ifdef WPM_ENABLE | |||
set_current_wpm(serial_m2s_buffer.current_wpm); | |||
# endif | |||
# ifdef POINTING_DEVICE_ENABLE | |||
if (!is_keyboard_left()) { | |||
static uint16_t cpi; | |||
if (cpi != serial_m2s_buffer.device_cpi) { | |||
cpi = serial_m2s_buffer.device_cpi; | |||
pmw_set_cpi(cpi); | |||
} | |||
serial_s2m_buffer.mouse_x = split_mouse_x; | |||
serial_s2m_buffer.mouse_y = split_mouse_y; | |||
} | |||
# endif | |||
} | |||
#endif | |||
#ifdef POINTING_DEVICE_ENABLE | |||
void master_mouse_send(int8_t x, int8_t y) { | |||
split_mouse_x = x; | |||
split_mouse_y = y; | |||
} | |||
void trackball_set_cpi(uint16_t cpi) { | |||
if (!is_keyboard_left()) { | |||
pmw_set_cpi(cpi); | |||
} else { | |||
device_cpi = cpi * 1.5; | |||
} | |||
} | |||
#endif |
@ -0,0 +1,33 @@ | |||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | |||
* | |||
* 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 | |||
#ifndef MOUSEKEY_WHEEL_DELTA | |||
# define MOUSEKEY_WHEEL_DELTA 1 | |||
#endif | |||
#ifndef MOUSEKEY_WHEEL_DELAY | |||
# define MOUSEKEY_WHEEL_DELAY 200 | |||
#endif | |||
#ifndef MOUSEKEY_WHEEL_INTERVAL | |||
# define MOUSEKEY_WHEEL_INTERVAL 50 | |||
#endif | |||
#ifndef MOUSEKEY_WHEEL_MAX_SPEED | |||
# define MOUSEKEY_WHEEL_MAX_SPEED 8 | |||
#endif | |||
#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX | |||
# define MOUSEKEY_WHEEL_TIME_TO_MAX 80 | |||
#endif |
@ -0,0 +1,21 @@ | |||
# Drashna's Dactyl Manuform (5x6) with a right side trackball | |||
![](https://preview.redd.it/zwt91036m3y51.jpg?width=960&crop=smart&auto=webp&s=e030deb7d8285c95a1a30c69a7e7a71f750e87bb) | |||
It's a Dactyl Manuform with an integrated thumb based trackball, using the pmw3360 optical sensor. | |||
It's powered by 2x Teensy++ 2.0's, using Drashna's [Teensy VBUS Hack](https://docs.qmk.fm/#/feature_split_keyboard?id=hardware-considerations-and-mods) for better detection. | |||
* Keyboard Maintainer: [Drashna Jael're](https://github.com/drashna) | |||
* Hardware Supported: [Design files](https://gitlab.com/keyboards1/dm_r_track/-/tree/master/boolean), [Teensy++ 2.0 (2x)](https://www.pjrc.com/store/teensypp.html), [PMW3360 Optical Sensor](https://www.tindie.com/products/jkicklighter/pmw3360-motion-sensor/) | |||
Make example for this keyboard (after setting up your build environment): | |||
make handwired/dactyl_manuform/5x6_right_trackball:default | |||
Flashing example for this keyboard: | |||
make handwired/dactyl_manuform/5x6_right_trackball:default:flash | |||
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). |
@ -0,0 +1,30 @@ | |||
# MCU name | |||
MCU = at90usb1286 | |||
# Bootloader selection | |||
BOOTLOADER = halfkay | |||
# Build Options | |||
# change yes to no to disable | |||
# | |||
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration | |||
MOUSEKEY_ENABLE = yes # Mouse keys | |||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||
CONSOLE_ENABLE = no # Console for debug | |||
COMMAND_ENABLE = yes # 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 | |||
NKRO_ENABLE = no # USB Nkey Rollover | |||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality | |||
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow | |||
BLUETOOTH_ENABLE = no # Enable Bluetooth | |||
AUDIO_ENABLE = no # Audio output | |||
SWAP_HANDS_ENABLE = yes | |||
POINTING_DEVICE_ENABLE = yes | |||
SPLIT_KEYBOARD = yes | |||
SPLIT_TRANSPORT = custom | |||
SRC += pointer_transport.c pmw3360.c | |||
QUANTUM_LIB_SRC += serial.c i2c_master.c i2c_slave.c spi_master.c |