aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrashna Jaelre <drashna@live.com>2020-12-19 10:43:00 -0800
committerGitHub <noreply@github.com>2020-12-19 19:43:00 +0100
commit5619b1d3db335750bed394b0d27980d67f4f50c5 (patch)
tree854f8fa7cb055193aa481e1e601ae58403e9ee9f
parentbded5f473c887fb36a2ca9d473635c1b84d0a04b (diff)
downloadqmk_firmware-5619b1d3db335750bed394b0d27980d67f4f50c5.tar.gz
qmk_firmware-5619b1d3db335750bed394b0d27980d67f4f50c5.zip
[Keyboard] Add drashna's dactyl manuform 5x6 with trackball (#11062)
Co-authored-by: James Young <18669334+noroadsleft@users.noreply.github.com> Co-authored-by: Erovia <Erovia@users.noreply.github.com>
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c221
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h73
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/config.h67
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/info.json75
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/config.h27
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/keymap.c63
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/config.h28
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/keymap.c197
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/rules.mk2
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.c225
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.h103
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360_firmware.h300
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/pointer_transport.c375
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/post_config.h33
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/readme.md21
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk30
-rw-r--r--keyboards/handwired/dactyl_manuform/dactyl_manuform.h2
17 files changed, 1842 insertions, 0 deletions
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c
new file mode 100644
index 000000000..c40e4173d
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c
@@ -0,0 +1,221 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "5x6_right_trackball.h"
18
19#ifndef TRACKBALL_DPI_OPTIONS
20# define TRACKBALL_DPI_OPTIONS { 1200, 1600, 2400 }
21# ifndef TRACKBALL_DPI_DEFAULT
22# define TRACKBALL_DPI_DEFAULT 1
23# endif
24#endif
25#ifndef TRACKBALL_DPI_DEFAULT
26# define TRACKBALL_DPI_DEFAULT 0
27#endif
28
29keyboard_config_t keyboard_config;
30uint16_t dpi_array[] = TRACKBALL_DPI_OPTIONS;
31#define DPI_OPTION_SIZE (sizeof(dpi_array) / sizeof(uint16_t))
32
33bool BurstState = false; // init burst state for Trackball module
34uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
35
36__attribute__((weak)) void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) {
37 mouse_report->x = x;
38 mouse_report->y = y;
39}
40
41__attribute__((weak)) void process_mouse(report_mouse_t* mouse_report) {
42 report_pmw_t data = pmw_read_burst();
43 if (data.isOnSurface && data.isMotion) {
44 // Reset timer if stopped moving
45 if (!data.isMotion) {
46 if (MotionStart != 0) MotionStart = 0;
47 return;
48 }
49
50 // Set timer if new motion
51 if ((MotionStart == 0) && data.isMotion) {
52 if (debug_mouse) dprintf("Starting motion.\n");
53 MotionStart = timer_read();
54 }
55
56 if (debug_mouse) {
57 dprintf("Delt] d: %d t: %u\n", abs(data.dx) + abs(data.dy), MotionStart);
58 }
59 if (debug_mouse) {
60 dprintf("Pre ] X: %d, Y: %d\n", data.dx, data.dy);
61 }
62#if defined(PROFILE_LINEAR)
63 float scale = float(timer_elaspsed(MotionStart)) / 1000.0;
64 data.dx *= scale;
65 data.dy *= scale;
66#elif defined(PROFILE_INVERSE)
67 // TODO
68#else
69 // no post processing
70#endif
71
72 // Wrap to HID size
73 data.dx = constrain(data.dx, -127, 127);
74 data.dy = constrain(data.dy, -127, 127);
75 if (debug_mouse) dprintf("Cons] X: %d, Y: %d\n", data.dx, data.dy);
76 // dprintf("Elapsed:%u, X: %f Y: %\n", i, pgm_read_byte(firmware_data+i));
77
78 mouse_report->x = -data.dx;
79 mouse_report->y = data.dy;
80 }
81}
82
83bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
84 if (!process_record_user(keycode, record)) { return false; }
85
86#ifdef POINTING_DEVICE_ENABLE
87 if (keycode == DPI_CONFIG && record->event.pressed) {
88 keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
89 eeconfig_update_kb(keyboard_config.raw);
90 trackball_set_cpi(dpi_array[keyboard_config.dpi_config]);
91 }
92#endif
93
94/* If Mousekeys is disabled, then use handle the mouse button
95 * keycodes. This makes things simpler, and allows usage of
96 * the keycodes in a consistent manner. But only do this if
97 * Mousekeys is not enable, so it's not handled twice.
98 */
99#ifndef MOUSEKEY_ENABLE
100 if (IS_MOUSEKEY_BUTTON(keycode)) {
101 report_mouse_t currentReport = pointing_device_get_report();
102 if (record->event.pressed) {
103 currentReport.buttons |= 1 << (keycode - KC_MS_BTN1);
104 } else {
105 currentReport.buttons &= ~(1 << (keycode - KC_MS_BTN1));
106 }
107 pointing_device_set_report(currentReport);
108 pointing_device_send();
109 }
110#endif
111
112 return true;
113}
114
115// Hardware Setup
116void keyboard_pre_init_kb(void) {
117 // debug_enable = true;
118 // debug_matrix = true;
119 // debug_mouse = true;
120 // debug_encoder = true;
121
122 /* Ground all output pins connected to ground. This provides additional
123 * pathways to ground. If you're messing with this, know this: driving ANY
124 * of these pins high will cause a short. On the MCU. Ka-blooey.
125 */
126
127 // This is the debug LED.
128#if defined(DEBUG_LED_PIN)
129 setPinOutput(DEBUG_LED_PIN);
130 writePin(DEBUG_LED_PIN, debug_enable);
131#endif
132
133 keyboard_pre_init_user();
134}
135
136#ifdef POINTING_DEVICE_ENABLE
137void pointing_device_init(void) {
138 if (!is_keyboard_left()) {
139 // initialize ball sensor
140 pmw_spi_init();
141 }
142 trackball_set_cpi(dpi_array[keyboard_config.dpi_config]);
143}
144
145static bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) {
146 return (new.buttons != old.buttons) ||
147 (new.x && new.x != old.x) ||
148 (new.y && new.y != old.y) ||
149 (new.h && new.h != old.h) ||
150 (new.v && new.v != old.v);
151}
152
153void pointing_device_task(void) {
154 report_mouse_t mouse_report = pointing_device_get_report();
155 if (!is_keyboard_left()) {
156 process_mouse(&mouse_report);
157 }
158
159 pointing_device_set_report(mouse_report);
160 pointing_device_send();
161}
162#endif
163
164void eeconfig_init_kb(void) {
165 keyboard_config.dpi_config = TRACKBALL_DPI_DEFAULT;
166 trackball_set_cpi(dpi_array[keyboard_config.dpi_config]);
167 eeconfig_update_kb(keyboard_config.raw);
168}
169
170void matrix_init_kb(void) {
171 // is safe to just read DPI setting since matrix init
172 // comes before pointing device init.
173 keyboard_config.raw = eeconfig_read_kb();
174 if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
175 eeconfig_init_kb();
176 }
177 matrix_init_user();
178}
179
180#ifdef POINTING_DEVICE_ENABLE
181void pointing_device_send(void) {
182 static report_mouse_t old_report = {};
183 report_mouse_t mouseReport = pointing_device_get_report();
184 if (is_keyboard_master()) {
185 int8_t x = mouseReport.x, y = mouseReport.y;
186 mouseReport.x = 0;
187 mouseReport.y = 0;
188 process_mouse_user(&mouseReport, x, y);
189 if (has_mouse_report_changed(mouseReport, old_report)) {
190 host_mouse_send(&mouseReport);
191 }
192 } else {
193 master_mouse_send(mouseReport.x, mouseReport.y);
194 }
195 mouseReport.x = 0;
196 mouseReport.y = 0;
197 mouseReport.v = 0;
198 mouseReport.h = 0;
199 old_report = mouseReport;
200 pointing_device_set_report(mouseReport);
201}
202#endif
203
204#ifdef SWAP_HANDS_ENABLE
205const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
206 /* Left hand, matrix positions */
207 {{5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}},
208 {{5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7}, {0, 7}},
209 {{5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8}},
210 {{5, 9}, {4, 9}, {3, 9}, {2, 9}, {1, 9}, {0, 9}},
211 {{5, 10}, {4, 10}, {3, 10}, {2, 10}, {1, 10}, {0, 10}},
212 {{5, 11}, {4, 11}, {3, 11}, {2, 11}, {1, 11}, {0, 11}},
213 /* Right hand, matrix positions */
214 {{5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
215 {{5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
216 {{5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
217 {{5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
218 {{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}},
219 {{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}
220};
221#endif
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h
new file mode 100644
index 000000000..c8650f73d
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h
@@ -0,0 +1,73 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include "dactyl_manuform.h"
20#include "quantum.h"
21#include "spi_master.h"
22#include "pmw3360.h"
23#include "pointing_device.h"
24
25
26#define ___ KC_NO
27
28#define LAYOUT_5x6_right_trackball(\
29 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
30 L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
31 L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
32 L30, L31, L32, L33, L34, L35, R30, R31, R32, R33, R34, R35, \
33 L42, L43, R42, R43, \
34 L44, L45, R41, \
35 L54, L55, R51, \
36 L52, L53, R52, R53 \
37 ) \
38 { \
39 { L00, L01, L02, L03, L04, L05 }, \
40 { L10, L11, L12, L13, L14, L15 }, \
41 { L20, L21, L22, L23, L24, L25 }, \
42 { L30, L31, L32, L33, L34, L35 }, \
43 { ___, ___, L42, L43, L44, L45 }, \
44 { ___, ___, L52, L53, L54, L55 }, \
45 \
46 { R00, R01, R02, R03, R04, R05 }, \
47 { R10, R11, R12, R13, R14, R15 }, \
48 { R20, R21, R22, R23, R24, R25 }, \
49 { R30, R31, R32, R33, R34, R35 }, \
50 { ___, R41, R42, R43, ___, ___ }, \
51 { ___, R51, R52, R53, ___, ___ } \
52}
53
54
55void process_wheel(report_mouse_t* mouse_report);
56void process_wheel_user(report_mouse_t* mouse_report, int16_t h, int16_t v);
57
58typedef union {
59 uint32_t raw;
60 struct {
61 uint8_t dpi_config;
62 };
63} keyboard_config_t;
64
65extern keyboard_config_t keyboard_config;
66
67enum ploopy_keycodes {
68 DPI_CONFIG = SAFE_RANGE,
69 KEYMAP_SAFE_RANGE,
70};
71
72void master_mouse_send(int8_t x, int8_t y);
73void trackball_set_cpi(uint16_t cpi);
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/config.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/config.h
new file mode 100644
index 000000000..147f12600
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/config.h
@@ -0,0 +1,67 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2015 Jack Humbert
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#pragma once
20
21#include "config_common.h"
22
23#define PRODUCT_ID 0x3536
24#define DEVICE_VER 0x0001
25#define PRODUCT Tractyl-Manuform (5x6 with right side Trackball)
26
27/* key matrix size */
28// Rows are doubled-up
29#define MATRIX_ROWS 12
30#define MATRIX_COLS 6
31
32// wiring of each half
33#define MATRIX_COL_PINS { C0, C1, C2, C3, C4, C5 }
34#define MATRIX_ROW_PINS { F7, F6, F5, F4, F3, F2 }
35
36#define DIODE_DIRECTION COL2ROW
37
38// WS2812 RGB LED strip input and number of LEDs
39#define RGB_DI_PIN D3
40#define RGBLED_NUM 8
41#define RGBLIGHT_SPLIT
42#define RGBLED_SPLIT { 0 , 8 }
43#define RGBLIGHT_SLEEP
44#define RGBW
45#define RGBLIGHT_LIMIT_VAL 150
46/* define if matrix has ghost */
47//#define MATRIX_HAS_GHOST
48
49/* number of backlight levels */
50// #define BACKLIGHT_LEVELS 3
51
52#define DEBUG_LED_PIN D6
53
54#define USB_POLLING_INTERVAL_MS 1
55
56#define ROTATIONAL_TRANSFORM_ANGLE -25
57
58/* Bootmagic Lite key configuration */
59#define BOOTMAGIC_LITE_ROW 0
60#define BOOTMAGIC_LITE_COLUMN 0
61#define BOOTMAGIC_LITE_ROW_RIGHT 6
62#define BOOTMAGIC_LITE_COLUMN_RIGHT 5
63
64#define C6_AUDIO
65
66#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095
67#define DYNAMIC_KEYMAP_LAYER_COUNT 16
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/info.json b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/info.json
new file mode 100644
index 000000000..89f99dc23
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/info.json
@@ -0,0 +1,75 @@
1{
2 "keyboard_name": "Dactyl Manuform 5x6",
3 "url": "",
4 "maintainer": "qmk",
5 "width": 17,
6 "height": 8,
7 "layouts": {
8 "LAYOUT_5x6": {
9 "layout": [
10 {"label":"L00", "x":0, "y":0},
11 {"label":"L01", "x":1, "y":0},
12 {"label":"L02", "x":2, "y":0},
13 {"label":"L03", "x":3, "y":0},
14 {"label":"L04", "x":4, "y":0},
15 {"label":"L05", "x":5, "y":0},
16 {"label":"R00", "x":11, "y":0},
17 {"label":"R01", "x":12, "y":0},
18 {"label":"R02", "x":13, "y":0},
19 {"label":"R03", "x":14, "y":0},
20 {"label":"R04", "x":15, "y":0},
21 {"label":"R05", "x":16, "y":0},
22 {"label":"L10", "x":0, "y":1},
23 {"label":"L11", "x":1, "y":1},
24 {"label":"L12", "x":2, "y":1},
25 {"label":"L13", "x":3, "y":1},
26 {"label":"L14", "x":4, "y":1},
27 {"label":"L15", "x":5, "y":1},
28 {"label":"R10", "x":11, "y":1},
29 {"label":"R11", "x":12, "y":1},
30 {"label":"R12", "x":13, "y":1},
31 {"label":"R13", "x":14, "y":1},
32 {"label":"R14", "x":15, "y":1},
33 {"label":"R15", "x":16, "y":1},
34 {"label":"L20", "x":0, "y":2},
35 {"label":"L21", "x":1, "y":2},
36 {"label":"L22", "x":2, "y":2},
37 {"label":"L23", "x":3, "y":2},
38 {"label":"L24", "x":4, "y":2},
39 {"label":"L25", "x":5, "y":2},
40 {"label":"R20", "x":11, "y":2},
41 {"label":"R21", "x":12, "y":2},
42 {"label":"R22", "x":13, "y":2},
43 {"label":"R23", "x":14, "y":2},
44 {"label":"R24", "x":15, "y":2},
45 {"label":"R25", "x":16, "y":2},
46 {"label":"L30", "x":0, "y":3},
47 {"label":"L31", "x":1, "y":3},
48 {"label":"L32", "x":2, "y":3},
49 {"label":"L33", "x":3, "y":3},
50 {"label":"L34", "x":4, "y":3},
51 {"label":"L35", "x":5, "y":3},
52 {"label":"R30", "x":11, "y":3},
53 {"label":"R31", "x":12, "y":3},
54 {"label":"R32", "x":13, "y":3},
55 {"label":"R33", "x":14, "y":3},
56 {"label":"R34", "x":15, "y":3},
57 {"label":"R35", "x":16, "y":3},
58 {"label":"L42", "x":2, "y":4},
59 {"label":"L43", "x":3, "y":4},
60 {"label":"R42", "x":13, "y":4},
61 {"label":"R43", "x":14, "y":4},
62 {"label":"L44", "x":4, "y":5},
63 {"label":"L45", "x":5, "y":5},
64 {"label":"R41", "x":12, "y":5},
65 {"label":"L54", "x":6, "y":6},
66 {"label":"L55", "x":7, "y":6},
67 {"label":"R51", "x":10, "y":6},
68 {"label":"L52", "x":6, "y":7},
69 {"label":"L53", "x":7, "y":7},
70 {"label":"R52", "x":9, "y":7},
71 {"label":"R53", "x":10, "y":7}
72 ]
73 }
74 }
75}
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/config.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/config.h
new file mode 100644
index 000000000..4e35d4c4f
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/config.h
@@ -0,0 +1,27 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17
18
19#pragma once
20
21
22#define USE_SERIAL
23
24#define MASTER_LEFT
25// #define MASTER_RIGHT
26//#define EE_HANDS
27// Rows are doubled-up
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/keymap.c b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/keymap.c
new file mode 100644
index 000000000..7550b1fd8
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/default/keymap.c
@@ -0,0 +1,63 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include QMK_KEYBOARD_H
18
19
20#define _QWERTY 0
21#define _LOWER 1
22#define _RAISE 2
23
24#define RAISE MO(_RAISE)
25#define LOWER MO(_LOWER)
26
27const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
28
29 [_QWERTY] = LAYOUT_5x6_right_trackball(
30 KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 ,KC_BSPC,
31 KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P ,KC_MINS,
32 KC_LSFT, KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L ,KC_SCLN,KC_QUOT,
33 KC_LCTL, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M ,KC_COMM,KC_DOT ,KC_SLSH,KC_BSLASH,
34 KC_LBRC,KC_RBRC, KC_EQL,
35 RAISE,KC_SPC, LOWER,
36 KC_TAB,KC_HOME, KC_END, KC_DEL,
37 KC_BSPC, KC_GRV, KC_LGUI, KC_LALT
38 ),
39
40 [_LOWER] = LAYOUT_5x6_right_trackball(
41
42 KC_TILD,KC_EXLM, KC_AT ,KC_HASH,KC_DLR ,KC_PERC, KC_CIRC,KC_AMPR,KC_ASTR,KC_LPRN,KC_RPRN,KC_DEL,
43 _______,_______,_______,_______,_______,KC_LBRC, KC_RBRC, KC_P7 , KC_P8 , KC_P9 ,_______,KC_PLUS,
44 _______,KC_HOME,KC_PGUP,KC_PGDN,KC_END ,KC_LPRN, KC_RPRN, KC_P4 , KC_P5 , KC_P6 ,KC_MINS,KC_PIPE,
45 _______,_______,_______,_______,_______,_______, _______, KC_P1 , KC_P2 , KC_P3 ,KC_EQL ,KC_UNDS,
46 _______,KC_PSCR, KC_P0,
47 _______,_______, _______,
48 _______,_______, _______,_______,
49 _______,_______, _______,_______
50
51 ),
52
53 [_RAISE] = LAYOUT_5x6_right_trackball(
54 KC_F12 , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 ,KC_F10 ,KC_F11 ,
55 _______,_______,_______,_______,_______,KC_LBRC, KC_RBRC,_______,KC_NLCK,KC_INS ,KC_SLCK,KC_MUTE,
56 _______,KC_LEFT,KC_UP ,KC_DOWN,KC_RGHT,KC_LPRN, KC_RPRN,KC_MPRV,KC_MPLY,KC_MNXT,_______,KC_VOLU,
57 _______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,KC_VOLD,
58 _______,_______, _______,
59 _______,_______, _______,
60 _______,_______, _______,_______,
61 _______,_______, _______,_______
62 ),
63};
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/config.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/config.h
new file mode 100644
index 000000000..78dff3896
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/config.h
@@ -0,0 +1,28 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19// #define USE_I2C
20
21#define EE_HANDS
22#define TRACKBALL_DPI_OPTIONS \
23 { 1200, 1800, 2600, 3400 }
24
25#define RGBLIGHT_EFFECT_TWINKLE_LIFE 50
26#define RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 1/63
27
28#define SOLENOID_PIN F1
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/keymap.c b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/keymap.c
new file mode 100644
index 000000000..ca9733b6e
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/keymap.c
@@ -0,0 +1,197 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "drashna.h"
18
19#define TG_DBLO TG(_DIABLO)
20#define _MOUSE _MEDIA
21
22
23// clang-format off
24#define LAYOUT_5x6_right_trackball_wrapper(...) LAYOUT_5x6_right_trackball(__VA_ARGS__)
25#define LAYOUT_5x6_right_trackball_base( \
26 K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, \
27 K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, \
28 K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A \
29 ) \
30 LAYOUT_5x6_right_trackball_wrapper( \
31 KC_GRV, ________________NUMBER_LEFT________________, ________________NUMBER_RIGHT_______________, KC_MINS, \
32 KC_ESC, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, KC_BSLS, \
33 LALT_T(KC_TAB), K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, RALT_T(KC_QUOT), \
34 OS_LSFT, CTL_T(K21), K22, K23, K24, K25, K26, K27, K28, K29, RCTL_T(K2A), OS_RSFT, \
35 OS_LALT, OS_LGUI, TG_GAME, TG_DBLO, \
36 OS_LGUI, KC_GRV, OS_RGUI, \
37 KC_SPC, _______, KC_ENT, \
38 BK_LWER, MO(_MOUSE), MO(_MOUSE), DL_RAIS \
39 )
40#define LAYOUT_5x6_right_trackball_base_wrapper(...) LAYOUT_5x6_right_trackball_base(__VA_ARGS__)
41
42
43const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
44 [_QWERTY] = LAYOUT_5x6_right_trackball_base_wrapper(
45 _________________QWERTY_L1_________________, _________________QWERTY_R1_________________,
46 _________________QWERTY_L2_________________, _________________QWERTY_R2_________________,
47 _________________QWERTY_L3_________________, _________________QWERTY_R3_________________
48 ),
49
50 [_COLEMAK] = LAYOUT_5x6_right_trackball_base_wrapper(
51 _________________COLEMAK_L1________________, _________________COLEMAK_R1________________,
52 _________________COLEMAK_L2________________, _________________COLEMAK_R2________________,
53 _________________COLEMAK_L3________________, _________________COLEMAK_R3________________
54 ),
55
56 [_DVORAK] = LAYOUT_5x6_right_trackball_base_wrapper(
57 _________________DVORAK_L1_________________, _________________DVORAK_R1_________________,
58 _________________DVORAK_L2_________________, _________________DVORAK_R2_________________,
59 _________________DVORAK_L3_________________, _________________DVORAK_R3_________________
60 ),
61
62 [_WORKMAN] = LAYOUT_5x6_right_trackball_base_wrapper(
63 _________________WORKMAN_L1________________, _________________WORKMAN_R1________________,
64 _________________WORKMAN_L2________________, _________________WORKMAN_R2________________,
65 _________________WORKMAN_L3________________, _________________WORKMAN_R3________________
66 ),
67
68 [_NORMAN] = LAYOUT_5x6_right_trackball_base_wrapper(
69 _________________NORMAN_L1_________________, _________________NORMAN_L1_________________,
70 _________________NORMAN_L2_________________, _________________NORMAN_R2_________________,
71 _________________NORMAN_L3_________________, _________________NORMAN_R3_________________
72 ),
73
74 [_MALTRON] = LAYOUT_5x6_right_trackball_base_wrapper(
75 _________________MALTRON_L1________________, _________________MALTRON_R1________________,
76 _________________MALTRON_L2________________, _________________MALTRON_R2________________,
77 _________________MALTRON_L3________________, _________________MALTRON_R3________________
78 ),
79
80 [_EUCALYN] = LAYOUT_5x6_right_trackball_base_wrapper(
81 _________________EUCALYN_L1________________, _________________EUCALYN_R1________________,
82 _________________EUCALYN_L2________________, _________________EUCALYN_R2________________,
83 _________________EUCALYN_L3________________, _________________EUCALYN_R3________________
84 ),
85
86 [_CARPLAX] = LAYOUT_5x6_right_trackball_base_wrapper(
87 _____________CARPLAX_QFMLWY_L1_____________, _____________CARPLAX_QFMLWY_R1_____________,
88 _____________CARPLAX_QFMLWY_L2_____________, _____________CARPLAX_QFMLWY_R2_____________,
89 _____________CARPLAX_QFMLWY_L3_____________, _____________CARPLAX_QFMLWY_R3_____________
90 ),
91
92 [_MOUSE] = LAYOUT_5x6_right_trackball(
93 _______, _______, _______, _______, _______, _______, DPI_CONFIG, _______, _______, _______, _______, _______,
94 _______, _______, _______, _______, _______, _______, KC_WH_U, _______, _______, _______, _______, _______,
95 _______, _______, _______, _______, _______, _______, KC_WH_D, KC_BTN1, KC_BTN3, KC_BTN2, _______, _______,
96 _______, _______, _______, _______, _______, _______, _______, KC_BTN4, KC_BTN5, _______, _______, _______,
97 _______, _______, _______, _______,
98 _______, _______, _______,
99 _______, _______, _______,
100 _______, _______, _______, _______
101 ),
102 [_GAMEPAD] = LAYOUT_5x6_right_trackball(
103 KC_ESC, KC_NO, KC_1, KC_2, KC_3, KC_4, DPI_CONFIG, _______, _______, _______, _______, _______,
104 KC_F1, KC_K, KC_Q, KC_W, KC_E, KC_R, KC_WH_U, _______, _______, _______, _______, _______,
105 KC_TAB, KC_G, KC_A, KC_S, KC_D, KC_F, KC_WH_D, KC_BTN1, KC_BTN3, KC_BTN2, _______, _______,
106 KC_LCTL, KC_LSFT, KC_Z, KC_X, KC_C, KC_H, _______, KC_BTN4, KC_BTN5, _______, _______, _______,
107 KC_I, KC_T, TG_GAME, KC_NO,
108 KC_V, KC_O, _______,
109 KC_SPC, KC_P, _______,
110 KC_H, KC_LGUI, _______, _______
111 ),
112 [_DIABLO] = LAYOUT_5x6_right_trackball(
113 KC_ESC, KC_V, KC_D, KC_LALT, KC_NO, KC_NO, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO,
114 KC_TAB, KC_S, KC_I, KC_F, KC_M, KC_T, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
115 KC_Q, KC_1, KC_2, KC_3, KC_4, KC_G, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
116 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,
117 KC_F, KC_L, KC_NO, TG_DBLO,
118 SFT_T(KC_SPC), KC_F, _______,
119 ALT_T(KC_Q), KC_J, _______,
120 KC_DIABLO_CLEAR, KC_LGUI, _______, _______
121 ),
122 [_LOWER] = LAYOUT_5x6_right_trackball_wrapper(
123 KC_F12, _________________FUNC_LEFT_________________, _________________FUNC_RIGHT________________, KC_F11,
124 _______, _________________LOWER_L1__________________, _________________LOWER_R1__________________, _______,
125 _______, _________________LOWER_L2__________________, _________________LOWER_R2__________________, KC_PIPE,
126 _______, _________________LOWER_L3__________________, _________________LOWER_R3__________________, _______,
127 _______, _______, _______, _______,
128 _______, _______, _______,
129 _______, _______, _______,
130 _______, _______, _______, _______
131 ),
132 [_RAISE] = LAYOUT_5x6_right_trackball_wrapper(
133 KC_F12, _________________FUNC_LEFT_________________, _________________FUNC_RIGHT________________, KC_F11,
134 KC_GRV, _________________RAISE_L1__________________, _________________RAISE_R1__________________, _______,
135 _______, _________________RAISE_L2__________________, _________________RAISE_R2__________________, KC_BSLS,
136 _______, _________________RAISE_L3__________________, _________________RAISE_R3__________________, _______,
137 _______, _______, _______, _______,
138 _______, _______, _______,
139 _______, _______, _______,
140 _______, _______, _______, _______
141 ),
142 [_ADJUST] = LAYOUT_5x6_right_trackball_wrapper(
143 KC_MAKE, ___________________BLANK___________________, _________________ADJUST_R1_________________, KC_RST,
144 VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EEP_RST,
145 _______, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
146 _______, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
147 HPT_DWLI, HPT_DWLD, _______, _______,
148 HPT_TOG, HPT_BUZ, KC_NUKE,
149 _______, _______, _______,
150 _______, _______, KC_NUKE, _______
151 ),
152};
153// clang-format off
154
155
156#ifdef POINTING_DEVICE_ENABLE
157static uint16_t mouse_timer = 0;
158static uint16_t mouse_debounce_timer = 0;
159static uint8_t mouse_keycode_tracker = 0;
160
161void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) {
162 if ((x || y) && timer_elapsed(mouse_timer) > 125) {
163 mouse_timer = timer_read();
164 if (!layer_state_is(_MOUSE) && !layer_state_is(_GAMEPAD) && timer_elapsed(mouse_debounce_timer) > 125) {
165 layer_on(_MOUSE);
166 }
167 }
168 if (timer_elapsed(mouse_debounce_timer) > 125 || layer_state_is(_GAMEPAD) ) {
169 mouse_report->x = x;
170 mouse_report->y = y;
171 }
172}
173
174void matrix_scan_keymap(void) {
175 if (timer_elapsed(mouse_timer) > 750 && layer_state_is(_MOUSE) && !mouse_keycode_tracker) {
176 layer_off(_MOUSE);
177 }
178}
179
180bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
181 switch(keycode){
182 case MO(_MOUSE):
183 case DPI_CONFIG:
184 case KC_MS_UP...KC_MS_WH_RIGHT:
185 record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
186 mouse_timer = timer_read();
187 break;
188 default:
189 if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) {
190 layer_off(_MOUSE);
191 }
192 mouse_debounce_timer = timer_read();
193 break;
194 }
195 return true;
196}
197#endif
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/rules.mk b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/rules.mk
new file mode 100644
index 000000000..2e3e9607c
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/keymaps/drashna/rules.mk
@@ -0,0 +1,2 @@
1RGBLIGHT_STARTUP_ANIMATION = yes
2HAPTIC_ENABLE = SOLENOID
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.c b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.c
new file mode 100644
index 000000000..8007fecef
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.c
@@ -0,0 +1,225 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20#include "pmw3360.h"
21#include "pmw3360_firmware.h"
22
23#ifdef CONSOLE_ENABLE
24# include "print.h"
25#endif
26bool _inBurst = false;
27
28#ifndef PMW_CPI
29# define PMW_CPI 1600
30#endif
31#ifndef SPI_DIVISOR
32# define SPI_DIVISOR 2
33#endif
34#ifndef ROTATIONAL_TRANSFORM_ANGLE
35# define ROTATIONAL_TRANSFORM_ANGLE 0x00
36#endif
37
38#ifdef CONSOLE_ENABLE
39void 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')); }
40#endif
41
42
43bool spi_start_adv(void) {
44 bool status = spi_start(SPI_SS_PIN, false, 3, SPI_DIVISOR);
45 wait_us(1);
46 return status;
47}
48
49void spi_stop_adv(void) {
50 wait_us(1);
51 spi_stop();
52}
53
54spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) {
55 if (reg_addr != REG_Motion_Burst) {
56 _inBurst = false;
57 }
58
59 spi_start_adv();
60 // send address of the register, with MSBit = 1 to indicate it's a write
61 spi_status_t status = spi_write(reg_addr | 0x80);
62 status = spi_write(data);
63
64 // tSCLK-NCS for write operation
65 wait_us(20);
66
67 // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
68 wait_us(100);
69 spi_stop();
70 return status;
71}
72
73uint8_t spi_read_adv(uint8_t reg_addr) {
74 spi_start_adv();
75 // send adress of the register, with MSBit = 0 to indicate it's a read
76 spi_write(reg_addr & 0x7f);
77
78 uint8_t data = spi_read();
79
80 // tSCLK-NCS for read operation is 120ns
81 wait_us(1);
82
83 // tSRW/tSRR (=20us) minus tSCLK-NCS
84 wait_us(19);
85
86 spi_stop();
87 return data;
88}
89
90void pmw_set_cpi(uint16_t cpi) {
91 int cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119
92
93 spi_start_adv();
94 spi_write_adv(REG_Config1, cpival);
95 spi_stop();
96}
97
98bool pmw_spi_init(void) {
99 spi_init();
100 _inBurst = false;
101
102 spi_stop();
103 spi_start_adv();
104 spi_stop();
105
106 spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first
107 wait_ms(300);
108
109 spi_start_adv();
110 wait_us(40);
111 spi_stop_adv();
112 wait_us(40);
113
114 spi_write_adv(REG_Power_Up_Reset, 0x5a);
115 wait_ms(50);
116
117 spi_read_adv(REG_Motion);
118 spi_read_adv(REG_Delta_X_L);
119 spi_read_adv(REG_Delta_X_H);
120 spi_read_adv(REG_Delta_Y_L);
121 spi_read_adv(REG_Delta_Y_H);
122
123 pmw_upload_firmware();
124
125 spi_stop_adv();
126
127 wait_ms(10);
128 pmw_set_cpi(PMW_CPI);
129
130 wait_ms(1);
131
132 return pmw_check_signature();
133}
134
135void pmw_upload_firmware(void) {
136 spi_write_adv(REG_Config2, 0x00);
137
138 spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
139
140 spi_write_adv(REG_SROM_Enable, 0x1d);
141
142 wait_ms(10);
143
144 spi_write_adv(REG_SROM_Enable, 0x18);
145
146 spi_start_adv();
147 spi_write(REG_SROM_Load_Burst | 0x80);
148 wait_us(15);
149
150 unsigned char c;
151 for (int i = 0; i < firmware_length; i++) {
152 c = (unsigned char)pgm_read_byte(firmware_data + i);
153 spi_write(c);
154 wait_us(15);
155 }
156 wait_us(200);
157
158 spi_read_adv(REG_SROM_ID);
159
160 spi_write_adv(REG_Config2, 0x00);
161
162 spi_stop();
163 wait_ms(10);
164}
165
166bool pmw_check_signature(void) {
167 uint8_t pid = spi_read_adv(REG_Product_ID);
168 uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID);
169 uint8_t SROM_ver = spi_read_adv(REG_SROM_ID);
170 return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04
171}
172
173report_pmw_t pmw_read_burst(void) {
174 if (!_inBurst) {
175#ifdef CONSOLE_ENABLE
176 dprintf("burst on");
177#endif
178 spi_write_adv(REG_Motion_Burst, 0x00);
179 _inBurst = true;
180 }
181
182 spi_start_adv();
183 spi_write(REG_Motion_Burst);
184 wait_us(35); // waits for tSRAD
185
186 report_pmw_t data;
187 data.motion = 0;
188 data.dx = 0;
189 data.mdx = 0;
190 data.dy = 0;
191 data.mdx = 0;
192
193 data.motion = spi_read();
194 spi_write(0x00); // skip Observation
195 data.dx = spi_read();
196 data.mdx = spi_read();
197 data.dy = spi_read();
198 data.mdy = spi_read();
199
200 spi_stop();
201
202#ifdef CONSOLE_ENABLE
203 print_byte(data.motion);
204 print_byte(data.dx);
205 print_byte(data.mdx);
206 print_byte(data.dy);
207 print_byte(data.mdy);
208 dprintf("\n");
209#endif
210
211 data.isMotion = (data.motion & 0x80) != 0;
212 data.isOnSurface = (data.motion & 0x08) == 0;
213 data.dx |= (data.mdx << 8);
214 data.dx = data.dx * -1;
215 data.dy |= (data.mdy << 8);
216 data.dy = data.dy * -1;
217
218 spi_stop();
219
220 if (data.motion & 0b111) { // panic recovery, sometimes burst mode works weird.
221 _inBurst = false;
222 }
223
224 return data;
225}
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.h
new file mode 100644
index 000000000..c1d5e3bad
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.h
@@ -0,0 +1,103 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include "spi_master.h"
22
23// Registers
24#define REG_Product_ID 0x00
25#define REG_Revision_ID 0x01
26#define REG_Motion 0x02
27#define REG_Delta_X_L 0x03
28#define REG_Delta_X_H 0x04
29#define REG_Delta_Y_L 0x05
30#define REG_Delta_Y_H 0x06
31#define REG_SQUAL 0x07
32#define REG_Raw_Data_Sum 0x08
33#define REG_Maximum_Raw_data 0x09
34#define REG_Minimum_Raw_data 0x0A
35#define REG_Shutter_Lower 0x0B
36#define REG_Shutter_Upper 0x0C
37#define REG_Control 0x0D
38#define REG_Config1 0x0F
39#define REG_Config2 0x10
40#define REG_Angle_Tune 0x11
41#define REG_Frame_Capture 0x12
42#define REG_SROM_Enable 0x13
43#define REG_Run_Downshift 0x14
44#define REG_Rest1_Rate_Lower 0x15
45#define REG_Rest1_Rate_Upper 0x16
46#define REG_Rest1_Downshift 0x17
47#define REG_Rest2_Rate_Lower 0x18
48#define REG_Rest2_Rate_Upper 0x19
49#define REG_Rest2_Downshift 0x1A
50#define REG_Rest3_Rate_Lower 0x1B
51#define REG_Rest3_Rate_Upper 0x1C
52#define REG_Observation 0x24
53#define REG_Data_Out_Lower 0x25
54#define REG_Data_Out_Upper 0x26
55#define REG_Raw_Data_Dump 0x29
56#define REG_SROM_ID 0x2A
57#define REG_Min_SQ_Run 0x2B
58#define REG_Raw_Data_Threshold 0x2C
59#define REG_Config5 0x2F
60#define REG_Power_Up_Reset 0x3A
61#define REG_Shutdown 0x3B
62#define REG_Inverse_Product_ID 0x3F
63#define REG_LiftCutoff_Tune3 0x41
64#define REG_Angle_Snap 0x42
65#define REG_LiftCutoff_Tune1 0x4A
66#define REG_Motion_Burst 0x50
67#define REG_LiftCutoff_Tune_Timeout 0x58
68#define REG_LiftCutoff_Tune_Min_Length 0x5A
69#define REG_SROM_Load_Burst 0x62
70#define REG_Lift_Config 0x63
71#define REG_Raw_Data_Burst 0x64
72#define REG_LiftCutoff_Tune2 0x65
73
74#ifdef CONSOLE_ENABLE
75void print_byte(uint8_t byte);
76#endif
77
78typedef struct {
79 int8_t motion;
80 bool isMotion; // True if a motion is detected.
81 bool isOnSurface; // True when a chip is on a surface
82 int16_t dx; // displacement on x directions. Unit: Count. (CPI * Count = Inch value)
83 int8_t mdx;
84 int16_t dy; // displacement on y directions.
85 int8_t mdy;
86} report_pmw_t;
87
88
89
90bool spi_start_adv(void);
91void spi_stop_adv(void);
92spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
93uint8_t spi_read_adv(uint8_t reg_addr);
94bool pmw_spi_init(void);
95void pmw_set_cpi(uint16_t cpi);
96void pmw_upload_firmware(void);
97bool pmw_check_signature(void);
98report_pmw_t pmw_read_burst(void);
99
100
101#define degToRad(angleInDegrees) ((angleInDegrees)*M_PI / 180.0)
102#define radToDeg(angleInRadians) ((angleInRadians)*180.0 / M_PI)
103#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360_firmware.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360_firmware.h
new file mode 100644
index 000000000..cca5a6a4d
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360_firmware.h
@@ -0,0 +1,300 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21// clang-format off
22// Firmware Blob foor PMW3360
23const uint16_t firmware_length = 4094;
24// clang-format off
25const uint8_t firmware_data[] PROGMEM = { // SROM 0x04
260x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
270xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
280xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
290x97, 0x8d, 0x79, 0x51, 0x20, 0xc7, 0x06, 0x8e, 0x7c, 0x7c, 0x7a, 0x76, 0x4f, 0xfd, 0x59,
300x30, 0xe2, 0x46, 0x0e, 0x9e, 0xbe, 0xdf, 0x1d, 0x99, 0x91, 0xa0, 0xa5, 0xa1, 0xa9, 0xd0,
310x22, 0xc6, 0xef, 0x5c, 0x1b, 0x95, 0x89, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x55, 0x28, 0xb3,
320xe4, 0x4a, 0xf7, 0x6c, 0x3b, 0xf4, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x05,
330x88, 0x92, 0xa6, 0xce, 0x1e, 0xbe, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x07,
340x11, 0x5d, 0x98, 0x0b, 0x9d, 0x94, 0x97, 0xee, 0x4e, 0x45, 0x33, 0x6b, 0x44, 0xc7, 0x29,
350x56, 0x27, 0x30, 0xc6, 0xa7, 0xd5, 0xf2, 0x56, 0xdf, 0xb4, 0x38, 0x62, 0xcb, 0xa0, 0xb6,
360xe3, 0x0f, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6f, 0x76, 0x89, 0xb5, 0x77, 0x41, 0x27, 0x82,
370x66, 0x65, 0x82, 0xcc, 0xd5, 0xe6, 0x20, 0xd5, 0x27, 0x17, 0xc5, 0xf8, 0x03, 0x23, 0x7c,
380x5f, 0x64, 0xa5, 0x1d, 0xc1, 0xd6, 0x36, 0xcb, 0x4c, 0xd4, 0xdb, 0x66, 0xd7, 0x8b, 0xb1,
390x99, 0x7e, 0x6f, 0x4c, 0x36, 0x40, 0x06, 0xd6, 0xeb, 0xd7, 0xa2, 0xe4, 0xf4, 0x95, 0x51,
400x5a, 0x54, 0x96, 0xd5, 0x53, 0x44, 0xd7, 0x8c, 0xe0, 0xb9, 0x40, 0x68, 0xd2, 0x18, 0xe9,
410xdd, 0x9a, 0x23, 0x92, 0x48, 0xee, 0x7f, 0x43, 0xaf, 0xea, 0x77, 0x38, 0x84, 0x8c, 0x0a,
420x72, 0xaf, 0x69, 0xf8, 0xdd, 0xf1, 0x24, 0x83, 0xa3, 0xf8, 0x4a, 0xbf, 0xf5, 0x94, 0x13,
430xdb, 0xbb, 0xd8, 0xb4, 0xb3, 0xa0, 0xfb, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71,
440xa2, 0xd3, 0x13, 0xe7, 0xfa, 0xe7, 0xce, 0x0f, 0x63, 0x15, 0x0b, 0x6b, 0x94, 0xbb, 0x37,
450x83, 0x26, 0x05, 0x9d, 0xfb, 0x46, 0x92, 0xfc, 0x0a, 0x15, 0xd1, 0x0d, 0x73, 0x92, 0xd6,
460x8c, 0x1b, 0x8c, 0xb8, 0x55, 0x8a, 0xce, 0xbd, 0xfe, 0x8e, 0xfc, 0xed, 0x09, 0x12, 0x83,
470x91, 0x82, 0x51, 0x31, 0x23, 0xfb, 0xb4, 0x0c, 0x76, 0xad, 0x7c, 0xd9, 0xb4, 0x4b, 0xb2,
480x67, 0x14, 0x09, 0x9c, 0x7f, 0x0c, 0x18, 0xba, 0x3b, 0xd6, 0x8e, 0x14, 0x2a, 0xe4, 0x1b,
490x52, 0x9f, 0x2b, 0x7d, 0xe1, 0xfb, 0x6a, 0x33, 0x02, 0xfa, 0xac, 0x5a, 0xf2, 0x3e, 0x88,
500x7e, 0xae, 0xd1, 0xf3, 0x78, 0xe8, 0x05, 0xd1, 0xe3, 0xdc, 0x21, 0xf6, 0xe1, 0x9a, 0xbd,
510x17, 0x0e, 0xd9, 0x46, 0x9b, 0x88, 0x03, 0xea, 0xf6, 0x66, 0xbe, 0x0e, 0x1b, 0x50, 0x49,
520x96, 0x40, 0x97, 0xf1, 0xf1, 0xe4, 0x80, 0xa6, 0x6e, 0xe8, 0x77, 0x34, 0xbf, 0x29, 0x40,
530x44, 0xc2, 0xff, 0x4e, 0x98, 0xd3, 0x9c, 0xa3, 0x32, 0x2b, 0x76, 0x51, 0x04, 0x09, 0xe7,
540xa9, 0xd1, 0xa6, 0x32, 0xb1, 0x23, 0x53, 0xe2, 0x47, 0xab, 0xd6, 0xf5, 0x69, 0x5c, 0x3e,
550x5f, 0xfa, 0xae, 0x45, 0x20, 0xe5, 0xd2, 0x44, 0xff, 0x39, 0x32, 0x6d, 0xfd, 0x27, 0x57,
560x5c, 0xfd, 0xf0, 0xde, 0xc1, 0xb5, 0x99, 0xe5, 0xf5, 0x1c, 0x77, 0x01, 0x75, 0xc5, 0x6d,
570x58, 0x92, 0xf2, 0xb2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7a, 0x30, 0xff, 0xb7, 0xf0, 0xef,
580x77, 0xc1, 0x8a, 0x5d, 0xdc, 0xc0, 0xd1, 0x29, 0x30, 0x1e, 0x77, 0x38, 0x7a, 0x94, 0xf1,
590xb8, 0x7a, 0x7e, 0xef, 0xa4, 0xd1, 0xac, 0x31, 0x4a, 0xf2, 0x5d, 0x64, 0x3d, 0xb2, 0xe2,
600xf0, 0x08, 0x99, 0xfc, 0x70, 0xee, 0x24, 0xa7, 0x7e, 0xee, 0x1e, 0x20, 0x69, 0x7d, 0x44,
610xbf, 0x87, 0x42, 0xdf, 0x88, 0x3b, 0x0c, 0xda, 0x42, 0xc9, 0x04, 0xf9, 0x45, 0x50, 0xfc,
620x83, 0x8f, 0x11, 0x6a, 0x72, 0xbc, 0x99, 0x95, 0xf0, 0xac, 0x3d, 0xa7, 0x3b, 0xcd, 0x1c,
630xe2, 0x88, 0x79, 0x37, 0x11, 0x5f, 0x39, 0x89, 0x95, 0x0a, 0x16, 0x84, 0x7a, 0xf6, 0x8a,
640xa4, 0x28, 0xe4, 0xed, 0x83, 0x80, 0x3b, 0xb1, 0x23, 0xa5, 0x03, 0x10, 0xf4, 0x66, 0xea,
650xbb, 0x0c, 0x0f, 0xc5, 0xec, 0x6c, 0x69, 0xc5, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0x99,
660x88, 0x76, 0x08, 0xa0, 0xa8, 0x95, 0x7c, 0xd8, 0x38, 0x6d, 0xcd, 0x59, 0x02, 0x51, 0x4b,
670xf1, 0xb5, 0x2b, 0x50, 0xe3, 0xb6, 0xbd, 0xd0, 0x72, 0xcf, 0x9e, 0xfd, 0x6e, 0xbb, 0x44,
680xc8, 0x24, 0x8a, 0x77, 0x18, 0x8a, 0x13, 0x06, 0xef, 0x97, 0x7d, 0xfa, 0x81, 0xf0, 0x31,
690xe6, 0xfa, 0x77, 0xed, 0x31, 0x06, 0x31, 0x5b, 0x54, 0x8a, 0x9f, 0x30, 0x68, 0xdb, 0xe2,
700x40, 0xf8, 0x4e, 0x73, 0xfa, 0xab, 0x74, 0x8b, 0x10, 0x58, 0x13, 0xdc, 0xd2, 0xe6, 0x78,
710xd1, 0x32, 0x2e, 0x8a, 0x9f, 0x2c, 0x58, 0x06, 0x48, 0x27, 0xc5, 0xa9, 0x5e, 0x81, 0x47,
720x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xa4, 0x3e, 0x88, 0x9c, 0xda, 0x33, 0x0a, 0xce, 0xbc,
730x8b, 0x8e, 0xcf, 0x9f, 0xd3, 0x71, 0x80, 0x43, 0xcf, 0x6b, 0xa9, 0x51, 0x83, 0x76, 0x30,
740x82, 0xc5, 0x6a, 0x85, 0x39, 0x11, 0x50, 0x1a, 0x82, 0xdc, 0x1e, 0x1c, 0xd5, 0x7d, 0xa9,
750x71, 0x99, 0x33, 0x47, 0x19, 0x97, 0xb3, 0x5a, 0xb1, 0xdf, 0xed, 0xa4, 0xf2, 0xe6, 0x26,
760x84, 0xa2, 0x28, 0x9a, 0x9e, 0xdf, 0xa6, 0x6a, 0xf4, 0xd6, 0xfc, 0x2e, 0x5b, 0x9d, 0x1a,
770x2a, 0x27, 0x68, 0xfb, 0xc1, 0x83, 0x21, 0x4b, 0x90, 0xe0, 0x36, 0xdd, 0x5b, 0x31, 0x42,
780x55, 0xa0, 0x13, 0xf7, 0xd0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xc5, 0xf3, 0x21,
790xf8, 0x37, 0x2f, 0x40, 0xf3, 0xd4, 0xaf, 0x16, 0x08, 0x36, 0x02, 0xfc, 0x77, 0xc5, 0x8b,
800x04, 0x90, 0x56, 0xb9, 0xc9, 0x67, 0x9a, 0x99, 0xe8, 0x00, 0xd3, 0x86, 0xff, 0x97, 0x2d,
810x08, 0xe9, 0xb7, 0xb3, 0x91, 0xbc, 0xdf, 0x45, 0xc6, 0xed, 0x0f, 0x8c, 0x4c, 0x1e, 0xe6,
820x5b, 0x6e, 0x38, 0x30, 0xe4, 0xaa, 0xe3, 0x95, 0xde, 0xb9, 0xe4, 0x9a, 0xf5, 0xb2, 0x55,
830x9a, 0x87, 0x9b, 0xf6, 0x6a, 0xb2, 0xf2, 0x77, 0x9a, 0x31, 0xf4, 0x7a, 0x31, 0xd1, 0x1d,
840x04, 0xc0, 0x7c, 0x32, 0xa2, 0x9e, 0x9a, 0xf5, 0x62, 0xf8, 0x27, 0x8d, 0xbf, 0x51, 0xff,
850xd3, 0xdf, 0x64, 0x37, 0x3f, 0x2a, 0x6f, 0x76, 0x3a, 0x7d, 0x77, 0x06, 0x9e, 0x77, 0x7f,
860x5e, 0xeb, 0x32, 0x51, 0xf9, 0x16, 0x66, 0x9a, 0x09, 0xf3, 0xb0, 0x08, 0xa4, 0x70, 0x96,
870x46, 0x30, 0xff, 0xda, 0x4f, 0xe9, 0x1b, 0xed, 0x8d, 0xf8, 0x74, 0x1f, 0x31, 0x92, 0xb3,
880x73, 0x17, 0x36, 0xdb, 0x91, 0x30, 0xd6, 0x88, 0x55, 0x6b, 0x34, 0x77, 0x87, 0x7a, 0xe7,
890xee, 0x06, 0xc6, 0x1c, 0x8c, 0x19, 0x0c, 0x48, 0x46, 0x23, 0x5e, 0x9c, 0x07, 0x5c, 0xbf,
900xb4, 0x7e, 0xd6, 0x4f, 0x74, 0x9c, 0xe2, 0xc5, 0x50, 0x8b, 0xc5, 0x8b, 0x15, 0x90, 0x60,
910x62, 0x57, 0x29, 0xd0, 0x13, 0x43, 0xa1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xc7, 0x4d, 0x19,
920x86, 0xcc, 0x2f, 0x2a, 0x75, 0x5a, 0xfc, 0xeb, 0x97, 0x2a, 0x70, 0xe3, 0x78, 0xd8, 0x91,
930xb0, 0x4f, 0x99, 0x07, 0xa3, 0x95, 0xea, 0x24, 0x21, 0xd5, 0xde, 0x51, 0x20, 0x93, 0x27,
940x0a, 0x30, 0x73, 0xa8, 0xff, 0x8a, 0x97, 0xe9, 0xa7, 0x6a, 0x8e, 0x0d, 0xe8, 0xf0, 0xdf,
950xec, 0xea, 0xb4, 0x6c, 0x1d, 0x39, 0x2a, 0x62, 0x2d, 0x3d, 0x5a, 0x8b, 0x65, 0xf8, 0x90,
960x05, 0x2e, 0x7e, 0x91, 0x2c, 0x78, 0xef, 0x8e, 0x7a, 0xc1, 0x2f, 0xac, 0x78, 0xee, 0xaf,
970x28, 0x45, 0x06, 0x4c, 0x26, 0xaf, 0x3b, 0xa2, 0xdb, 0xa3, 0x93, 0x06, 0xb5, 0x3c, 0xa5,
980xd8, 0xee, 0x8f, 0xaf, 0x25, 0xcc, 0x3f, 0x85, 0x68, 0x48, 0xa9, 0x62, 0xcc, 0x97, 0x8f,
990x7f, 0x2a, 0xea, 0xe0, 0x15, 0x0a, 0xad, 0x62, 0x07, 0xbd, 0x45, 0xf8, 0x41, 0xd8, 0x36,
1000xcb, 0x4c, 0xdb, 0x6e, 0xe6, 0x3a, 0xe7, 0xda, 0x15, 0xe9, 0x29, 0x1e, 0x12, 0x10, 0xa0,
1010x14, 0x2c, 0x0e, 0x3d, 0xf4, 0xbf, 0x39, 0x41, 0x92, 0x75, 0x0b, 0x25, 0x7b, 0xa3, 0xce,
1020x39, 0x9c, 0x15, 0x64, 0xc8, 0xfa, 0x3d, 0xef, 0x73, 0x27, 0xfe, 0x26, 0x2e, 0xce, 0xda,
1030x6e, 0xfd, 0x71, 0x8e, 0xdd, 0xfe, 0x76, 0xee, 0xdc, 0x12, 0x5c, 0x02, 0xc5, 0x3a, 0x4e,
1040x4e, 0x4f, 0xbf, 0xca, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x41, 0xf1, 0x10, 0xe0, 0x4f, 0x7e,
1050x97, 0x7f, 0x1c, 0xae, 0x47, 0x8e, 0x6b, 0xb1, 0x25, 0x31, 0xb0, 0x73, 0xc7, 0x1b, 0x97,
1060x79, 0xf9, 0x80, 0xd3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1e, 0xe4, 0xd0, 0x80, 0x21, 0xd6,
1070xee, 0x6b, 0x6c, 0x4f, 0xbf, 0xf5, 0xb7, 0xd9, 0x09, 0x87, 0x2f, 0xa9, 0x14, 0xbe, 0x27,
1080xd9, 0x72, 0x50, 0x01, 0xd4, 0x13, 0x73, 0xa6, 0xa7, 0x51, 0x02, 0x75, 0x25, 0xe1, 0xb3,
1090x45, 0x34, 0x7d, 0xa8, 0x8e, 0xeb, 0xf3, 0x16, 0x49, 0xcb, 0x4f, 0x8c, 0xa1, 0xb9, 0x36,
1100x85, 0x39, 0x75, 0x5d, 0x08, 0x00, 0xae, 0xeb, 0xf6, 0xea, 0xd7, 0x13, 0x3a, 0x21, 0x5a,
1110x5f, 0x30, 0x84, 0x52, 0x26, 0x95, 0xc9, 0x14, 0xf2, 0x57, 0x55, 0x6b, 0xb1, 0x10, 0xc2,
1120xe1, 0xbd, 0x3b, 0x51, 0xc0, 0xb7, 0x55, 0x4c, 0x71, 0x12, 0x26, 0xc7, 0x0d, 0xf9, 0x51,
1130xa4, 0x38, 0x02, 0x05, 0x7f, 0xb8, 0xf1, 0x72, 0x4b, 0xbf, 0x71, 0x89, 0x14, 0xf3, 0x77,
1140x38, 0xd9, 0x71, 0x24, 0xf3, 0x00, 0x11, 0xa1, 0xd8, 0xd4, 0x69, 0x27, 0x08, 0x37, 0x35,
1150xc9, 0x11, 0x9d, 0x90, 0x1c, 0x0e, 0xe7, 0x1c, 0xff, 0x2d, 0x1e, 0xe8, 0x92, 0xe1, 0x18,
1160x10, 0x95, 0x7c, 0xe0, 0x80, 0xf4, 0x96, 0x43, 0x21, 0xf9, 0x75, 0x21, 0x64, 0x38, 0xdd,
1170x9f, 0x1e, 0x95, 0x16, 0xda, 0x56, 0x1d, 0x4f, 0x9a, 0x53, 0xb2, 0xe2, 0xe4, 0x18, 0xcb,
1180x6b, 0x1a, 0x65, 0xeb, 0x56, 0xc6, 0x3b, 0xe5, 0xfe, 0xd8, 0x26, 0x3f, 0x3a, 0x84, 0x59,
1190x72, 0x66, 0xa2, 0xf3, 0x75, 0xff, 0xfb, 0x60, 0xb3, 0x22, 0xad, 0x3f, 0x2d, 0x6b, 0xf9,
1200xeb, 0xea, 0x05, 0x7c, 0xd8, 0x8f, 0x6d, 0x2c, 0x98, 0x9e, 0x2b, 0x93, 0xf1, 0x5e, 0x46,
1210xf0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xd7, 0x7f, 0xf9, 0xf0, 0xe5, 0x7d, 0xdb, 0x1d, 0x75,
1220x19, 0xf3, 0xc4, 0x58, 0x9b, 0x17, 0x88, 0xa8, 0x92, 0xe0, 0xbe, 0xbd, 0x8b, 0x1d, 0x8d,
1230x9f, 0x56, 0x76, 0xad, 0xaf, 0x29, 0xe2, 0xd9, 0xd5, 0x52, 0xf6, 0xb5, 0x56, 0x35, 0x57,
1240x3a, 0xc8, 0xe1, 0x56, 0x43, 0x19, 0x94, 0xd3, 0x04, 0x9b, 0x6d, 0x35, 0xd8, 0x0b, 0x5f,
1250x4d, 0x19, 0x8e, 0xec, 0xfa, 0x64, 0x91, 0x0a, 0x72, 0x20, 0x2b, 0xbc, 0x1a, 0x4a, 0xfe,
1260x8b, 0xfd, 0xbb, 0xed, 0x1b, 0x23, 0xea, 0xad, 0x72, 0x82, 0xa1, 0x29, 0x99, 0x71, 0xbd,
1270xf0, 0x95, 0xc1, 0x03, 0xdd, 0x7b, 0xc2, 0xb2, 0x3c, 0x28, 0x54, 0xd3, 0x68, 0xa4, 0x72,
1280xc8, 0x66, 0x96, 0xe0, 0xd1, 0xd8, 0x7f, 0xf8, 0xd1, 0x26, 0x2b, 0xf7, 0xad, 0xba, 0x55,
1290xca, 0x15, 0xb9, 0x32, 0xc3, 0xe5, 0x88, 0x97, 0x8e, 0x5c, 0xfb, 0x92, 0x25, 0x8b, 0xbf,
1300xa2, 0x45, 0x55, 0x7a, 0xa7, 0x6f, 0x8b, 0x57, 0x5b, 0xcf, 0x0e, 0xcb, 0x1d, 0xfb, 0x20,
1310x82, 0x77, 0xa8, 0x8c, 0xcc, 0x16, 0xce, 0x1d, 0xfa, 0xde, 0xcc, 0x0b, 0x62, 0xfe, 0xcc,
1320xe1, 0xb7, 0xf0, 0xc3, 0x81, 0x64, 0x73, 0x40, 0xa0, 0xc2, 0x4d, 0x89, 0x11, 0x75, 0x33,
1330x55, 0x33, 0x8d, 0xe8, 0x4a, 0xfd, 0xea, 0x6e, 0x30, 0x0b, 0xd7, 0x31, 0x2c, 0xde, 0x47,
1340xe3, 0xbf, 0xf8, 0x55, 0x42, 0xe2, 0x7f, 0x59, 0xe5, 0x17, 0xef, 0x99, 0x34, 0x69, 0x91,
1350xb1, 0x23, 0x8e, 0x20, 0x87, 0x2d, 0xa8, 0xfe, 0xd5, 0x8a, 0xf3, 0x84, 0x3a, 0xf0, 0x37,
1360xe4, 0x09, 0x00, 0x54, 0xee, 0x67, 0x49, 0x93, 0xe4, 0x81, 0x70, 0xe3, 0x90, 0x4d, 0xef,
1370xfe, 0x41, 0xb7, 0x99, 0x7b, 0xc1, 0x83, 0xba, 0x62, 0x12, 0x6f, 0x7d, 0xde, 0x6b, 0xaf,
1380xda, 0x16, 0xf9, 0x55, 0x51, 0xee, 0xa6, 0x0c, 0x2b, 0x02, 0xa3, 0xfd, 0x8d, 0xfb, 0x30,
1390x17, 0xe4, 0x6f, 0xdf, 0x36, 0x71, 0xc4, 0xca, 0x87, 0x25, 0x48, 0xb0, 0x47, 0xec, 0xea,
1400xb4, 0xbf, 0xa5, 0x4d, 0x9b, 0x9f, 0x02, 0x93, 0xc4, 0xe3, 0xe4, 0xe8, 0x42, 0x2d, 0x68,
1410x81, 0x15, 0x0a, 0xeb, 0x84, 0x5b, 0xd6, 0xa8, 0x74, 0xfb, 0x7d, 0x1d, 0xcb, 0x2c, 0xda,
1420x46, 0x2a, 0x76, 0x62, 0xce, 0xbc, 0x5c, 0x9e, 0x8b, 0xe7, 0xcf, 0xbe, 0x78, 0xf5, 0x7c,
1430xeb, 0xb3, 0x3a, 0x9c, 0xaa, 0x6f, 0xcc, 0x72, 0xd1, 0x59, 0xf2, 0x11, 0x23, 0xd6, 0x3f,
1440x48, 0xd1, 0xb7, 0xce, 0xb0, 0xbf, 0xcb, 0xea, 0x80, 0xde, 0x57, 0xd4, 0x5e, 0x97, 0x2f,
1450x75, 0xd1, 0x50, 0x8e, 0x80, 0x2c, 0x66, 0x79, 0xbf, 0x72, 0x4b, 0xbd, 0x8a, 0x81, 0x6c,
1460xd3, 0xe1, 0x01, 0xdc, 0xd2, 0x15, 0x26, 0xc5, 0x36, 0xda, 0x2c, 0x1a, 0xc0, 0x27, 0x94,
1470xed, 0xb7, 0x9b, 0x85, 0x0b, 0x5e, 0x80, 0x97, 0xc5, 0xec, 0x4f, 0xec, 0x88, 0x5d, 0x50,
1480x07, 0x35, 0x47, 0xdc, 0x0b, 0x3b, 0x3d, 0xdd, 0x60, 0xaf, 0xa8, 0x5d, 0x81, 0x38, 0x24,
1490x25, 0x5d, 0x5c, 0x15, 0xd1, 0xde, 0xb3, 0xab, 0xec, 0x05, 0x69, 0xef, 0x83, 0xed, 0x57,
1500x54, 0xb8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xda, 0x9f, 0x2d, 0x7f, 0x36, 0xbb, 0x44,
1510x5a, 0x34, 0xe8, 0x7f, 0xbf, 0x03, 0xeb, 0x00, 0x7f, 0x59, 0x68, 0x22, 0x79, 0xcf, 0x73,
1520x6c, 0x2c, 0x29, 0xa7, 0xa1, 0x5f, 0x38, 0xa1, 0x1d, 0xf0, 0x20, 0x53, 0xe0, 0x1a, 0x63,
1530x14, 0x58, 0x71, 0x10, 0xaa, 0x08, 0x0c, 0x3e, 0x16, 0x1a, 0x60, 0x22, 0x82, 0x7f, 0xba,
1540xa4, 0x43, 0xa0, 0xd0, 0xac, 0x1b, 0xd5, 0x6b, 0x64, 0xb5, 0x14, 0x93, 0x31, 0x9e, 0x53,
1550x50, 0xd0, 0x57, 0x66, 0xee, 0x5a, 0x4f, 0xfb, 0x03, 0x2a, 0x69, 0x58, 0x76, 0xf1, 0x83,
1560xf7, 0x4e, 0xba, 0x8c, 0x42, 0x06, 0x60, 0x5d, 0x6d, 0xce, 0x60, 0x88, 0xae, 0xa4, 0xc3,
1570xf1, 0x03, 0xa5, 0x4b, 0x98, 0xa1, 0xff, 0x67, 0xe1, 0xac, 0xa2, 0xb8, 0x62, 0xd7, 0x6f,
1580xa0, 0x31, 0xb4, 0xd2, 0x77, 0xaf, 0x21, 0x10, 0x06, 0xc6, 0x9a, 0xff, 0x1d, 0x09, 0x17,
1590x0e, 0x5f, 0xf1, 0xaa, 0x54, 0x34, 0x4b, 0x45, 0x8a, 0x87, 0x63, 0xa6, 0xdc, 0xf9, 0x24,
1600x30, 0x67, 0xc6, 0xb2, 0xd6, 0x61, 0x33, 0x69, 0xee, 0x50, 0x61, 0x57, 0x28, 0xe7, 0x7e,
1610xee, 0xec, 0x3a, 0x5a, 0x73, 0x4e, 0xa8, 0x8d, 0xe4, 0x18, 0xea, 0xec, 0x41, 0x64, 0xc8,
1620xe2, 0xe8, 0x66, 0xb6, 0x2d, 0xb6, 0xfb, 0x6a, 0x6c, 0x16, 0xb3, 0xdd, 0x46, 0x43, 0xb9,
1630x73, 0x00, 0x6a, 0x71, 0xed, 0x4e, 0x9d, 0x25, 0x1a, 0xc3, 0x3c, 0x4a, 0x95, 0x15, 0x99,
1640x35, 0x81, 0x14, 0x02, 0xd6, 0x98, 0x9b, 0xec, 0xd8, 0x23, 0x3b, 0x84, 0x29, 0xaf, 0x0c,
1650x99, 0x83, 0xa6, 0x9a, 0x34, 0x4f, 0xfa, 0xe8, 0xd0, 0x3c, 0x4b, 0xd0, 0xfb, 0xb6, 0x68,
1660xb8, 0x9e, 0x8f, 0xcd, 0xf7, 0x60, 0x2d, 0x7a, 0x22, 0xe5, 0x7d, 0xab, 0x65, 0x1b, 0x95,
1670xa7, 0xa8, 0x7f, 0xb6, 0x77, 0x47, 0x7b, 0x5f, 0x8b, 0x12, 0x72, 0xd0, 0xd4, 0x91, 0xef,
1680xde, 0x19, 0x50, 0x3c, 0xa7, 0x8b, 0xc4, 0xa9, 0xb3, 0x23, 0xcb, 0x76, 0xe6, 0x81, 0xf0,
1690xc1, 0x04, 0x8f, 0xa3, 0xb8, 0x54, 0x5b, 0x97, 0xac, 0x19, 0xff, 0x3f, 0x55, 0x27, 0x2f,
1700xe0, 0x1d, 0x42, 0x9b, 0x57, 0xfc, 0x4b, 0x4e, 0x0f, 0xce, 0x98, 0xa9, 0x43, 0x57, 0x03,
1710xbd, 0xe7, 0xc8, 0x94, 0xdf, 0x6e, 0x36, 0x73, 0x32, 0xb4, 0xef, 0x2e, 0x85, 0x7a, 0x6e,
1720xfc, 0x6c, 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xf3, 0xe4, 0x9f, 0x3e, 0xdc, 0x68, 0xf3,
1730xb5, 0xf3, 0x19, 0x80, 0x92, 0x06, 0x99, 0xa2, 0xe8, 0x6f, 0xff, 0x2e, 0x7f, 0xae, 0x42,
1740xa4, 0x5f, 0xfb, 0xd4, 0x0e, 0x81, 0x2b, 0xc3, 0x04, 0xff, 0x2b, 0xb3, 0x74, 0x4e, 0x36,
1750x5b, 0x9c, 0x15, 0x00, 0xc6, 0x47, 0x2b, 0xe8, 0x8b, 0x3d, 0xf1, 0x9c, 0x03, 0x9a, 0x58,
1760x7f, 0x9b, 0x9c, 0xbf, 0x85, 0x49, 0x79, 0x35, 0x2e, 0x56, 0x7b, 0x41, 0x14, 0x39, 0x47,
1770x83, 0x26, 0xaa, 0x07, 0x89, 0x98, 0x11, 0x1b, 0x86, 0xe7, 0x73, 0x7a, 0xd8, 0x7d, 0x78,
1780x61, 0x53, 0xe9, 0x79, 0xf5, 0x36, 0x8d, 0x44, 0x92, 0x84, 0xf9, 0x13, 0x50, 0x58, 0x3b,
1790xa4, 0x6a, 0x36, 0x65, 0x49, 0x8e, 0x3c, 0x0e, 0xf1, 0x6f, 0xd2, 0x84, 0xc4, 0x7e, 0x8e,
1800x3f, 0x39, 0xae, 0x7c, 0x84, 0xf1, 0x63, 0x37, 0x8e, 0x3c, 0xcc, 0x3e, 0x44, 0x81, 0x45,
1810xf1, 0x4b, 0xb9, 0xed, 0x6b, 0x36, 0x5d, 0xbb, 0x20, 0x60, 0x1a, 0x0f, 0xa3, 0xaa, 0x55,
1820x77, 0x3a, 0xa9, 0xae, 0x37, 0x4d, 0xba, 0xb8, 0x86, 0x6b, 0xbc, 0x08, 0x50, 0xf6, 0xcc,
1830xa4, 0xbd, 0x1d, 0x40, 0x72, 0xa5, 0x86, 0xfa, 0xe2, 0x10, 0xae, 0x3d, 0x58, 0x4b, 0x97,
1840xf3, 0x43, 0x74, 0xa9, 0x9e, 0xeb, 0x21, 0xb7, 0x01, 0xa4, 0x86, 0x93, 0x97, 0xee, 0x2f,
1850x4f, 0x3b, 0x86, 0xa1, 0x41, 0x6f, 0x41, 0x26, 0x90, 0x78, 0x5c, 0x7f, 0x30, 0x38, 0x4b,
1860x3f, 0xaa, 0xec, 0xed, 0x5c, 0x6f, 0x0e, 0xad, 0x43, 0x87, 0xfd, 0x93, 0x35, 0xe6, 0x01,
1870xef, 0x41, 0x26, 0x90, 0x99, 0x9e, 0xfb, 0x19, 0x5b, 0xad, 0xd2, 0x91, 0x8a, 0xe0, 0x46,
1880xaf, 0x65, 0xfa, 0x4f, 0x84, 0xc1, 0xa1, 0x2d, 0xcf, 0x45, 0x8b, 0xd3, 0x85, 0x50, 0x55,
1890x7c, 0xf9, 0x67, 0x88, 0xd4, 0x4e, 0xe9, 0xd7, 0x6b, 0x61, 0x54, 0xa1, 0xa4, 0xa6, 0xa2,
1900xc2, 0xbf, 0x30, 0x9c, 0x40, 0x9f, 0x5f, 0xd7, 0x69, 0x2b, 0x24, 0x82, 0x5e, 0xd9, 0xd6,
1910xa7, 0x12, 0x54, 0x1a, 0xf7, 0x55, 0x9f, 0x76, 0x50, 0xa9, 0x95, 0x84, 0xe6, 0x6b, 0x6d,
1920xb5, 0x96, 0x54, 0xd6, 0xcd, 0xb3, 0xa1, 0x9b, 0x46, 0xa7, 0x94, 0x4d, 0xc4, 0x94, 0xb4,
1930x98, 0xe3, 0xe1, 0xe2, 0x34, 0xd5, 0x33, 0x16, 0x07, 0x54, 0xcd, 0xb7, 0x77, 0x53, 0xdb,
1940x4f, 0x4d, 0x46, 0x9d, 0xe9, 0xd4, 0x9c, 0x8a, 0x36, 0xb6, 0xb8, 0x38, 0x26, 0x6c, 0x0e,
1950xff, 0x9c, 0x1b, 0x43, 0x8b, 0x80, 0xcc, 0xb9, 0x3d, 0xda, 0xc7, 0xf1, 0x8a, 0xf2, 0x6d,
1960xb8, 0xd7, 0x74, 0x2f, 0x7e, 0x1e, 0xb7, 0xd3, 0x4a, 0xb4, 0xac, 0xfc, 0x79, 0x48, 0x6c,
1970xbc, 0x96, 0xb6, 0x94, 0x46, 0x57, 0x2d, 0xb0, 0xa3, 0xfc, 0x1e, 0xb9, 0x52, 0x60, 0x85,
1980x2d, 0x41, 0xd0, 0x43, 0x01, 0x1e, 0x1c, 0xd5, 0x7d, 0xfc, 0xf3, 0x96, 0x0d, 0xc7, 0xcb,
1990x2a, 0x29, 0x9a, 0x93, 0xdd, 0x88, 0x2d, 0x37, 0x5d, 0xaa, 0xfb, 0x49, 0x68, 0xa0, 0x9c,
2000x50, 0x86, 0x7f, 0x68, 0x56, 0x57, 0xf9, 0x79, 0x18, 0x39, 0xd4, 0xe0, 0x01, 0x84, 0x33,
2010x61, 0xca, 0xa5, 0xd2, 0xd6, 0xe4, 0xc9, 0x8a, 0x4a, 0x23, 0x44, 0x4e, 0xbc, 0xf0, 0xdc,
2020x24, 0xa1, 0xa0, 0xc4, 0xe2, 0x07, 0x3c, 0x10, 0xc4, 0xb5, 0x25, 0x4b, 0x65, 0x63, 0xf4,
2030x80, 0xe7, 0xcf, 0x61, 0xb1, 0x71, 0x82, 0x21, 0x87, 0x2c, 0xf5, 0x91, 0x00, 0x32, 0x0c,
2040xec, 0xa9, 0xb5, 0x9a, 0x74, 0x85, 0xe3, 0x36, 0x8f, 0x76, 0x4f, 0x9c, 0x6d, 0xce, 0xbc,
2050xad, 0x0a, 0x4b, 0xed, 0x76, 0x04, 0xcb, 0xc3, 0xb9, 0x33, 0x9e, 0x01, 0x93, 0x96, 0x69,
2060x7d, 0xc5, 0xa2, 0x45, 0x79, 0x9b, 0x04, 0x5c, 0x84, 0x09, 0xed, 0x88, 0x43, 0xc7, 0xab,
2070x93, 0x14, 0x26, 0xa1, 0x40, 0xb5, 0xce, 0x4e, 0xbf, 0x2a, 0x42, 0x85, 0x3e, 0x2c, 0x3b,
2080x54, 0xe8, 0x12, 0x1f, 0x0e, 0x97, 0x59, 0xb2, 0x27, 0x89, 0xfa, 0xf2, 0xdf, 0x8e, 0x68,
2090x59, 0xdc, 0x06, 0xbc, 0xb6, 0x85, 0x0d, 0x06, 0x22, 0xec, 0xb1, 0xcb, 0xe5, 0x04, 0xe6,
2100x3d, 0xb3, 0xb0, 0x41, 0x73, 0x08, 0x3f, 0x3c, 0x58, 0x86, 0x63, 0xeb, 0x50, 0xee, 0x1d,
2110x2c, 0x37, 0x74, 0xa9, 0xd3, 0x18, 0xa3, 0x47, 0x6e, 0x93, 0x54, 0xad, 0x0a, 0x5d, 0xb8,
2120x2a, 0x55, 0x5d, 0x78, 0xf6, 0xee, 0xbe, 0x8e, 0x3c, 0x76, 0x69, 0xb9, 0x40, 0xc2, 0x34,
2130xec, 0x2a, 0xb9, 0xed, 0x7e, 0x20, 0xe4, 0x8d, 0x00, 0x38, 0xc7, 0xe6, 0x8f, 0x44, 0xa8,
2140x86, 0xce, 0xeb, 0x2a, 0xe9, 0x90, 0xf1, 0x4c, 0xdf, 0x32, 0xfb, 0x73, 0x1b, 0x6d, 0x92,
2150x1e, 0x95, 0xfe, 0xb4, 0xdb, 0x65, 0xdf, 0x4d, 0x23, 0x54, 0x89, 0x48, 0xbf, 0x4a, 0x2e,
2160x70, 0xd6, 0xd7, 0x62, 0xb4, 0x33, 0x29, 0xb1, 0x3a, 0x33, 0x4c, 0x23, 0x6d, 0xa6, 0x76,
2170xa5, 0x21, 0x63, 0x48, 0xe6, 0x90, 0x5d, 0xed, 0x90, 0x95, 0x0b, 0x7a, 0x84, 0xbe, 0xb8,
2180x0d, 0x5e, 0x63, 0x0c, 0x62, 0x26, 0x4c, 0x14, 0x5a, 0xb3, 0xac, 0x23, 0xa4, 0x74, 0xa7,
2190x6f, 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xa0, 0x28, 0xb7, 0xee, 0x19, 0x38, 0xf1, 0x64,
2200x80, 0x82, 0x43, 0xe1, 0x41, 0x27, 0x1f, 0x1f, 0x90, 0x54, 0x7a, 0xd5, 0x23, 0x2e, 0xd1,
2210x3d, 0xcb, 0x28, 0xba, 0x58, 0x7f, 0xdc, 0x7c, 0x91, 0x24, 0xe9, 0x28, 0x51, 0x83, 0x6e,
2220xc5, 0x56, 0x21, 0x42, 0xed, 0xa0, 0x56, 0x22, 0xa1, 0x40, 0x80, 0x6b, 0xa8, 0xf7, 0x94,
2230xca, 0x13, 0x6b, 0x0c, 0x39, 0xd9, 0xfd, 0xe9, 0xf3, 0x6f, 0xa6, 0x9e, 0xfc, 0x70, 0x8a,
2240xb3, 0xbc, 0x59, 0x3c, 0x1e, 0x1d, 0x6c, 0xf9, 0x7c, 0xaf, 0xf9, 0x88, 0x71, 0x95, 0xeb,
2250x57, 0x00, 0xbd, 0x9f, 0x8c, 0x4f, 0xe1, 0x24, 0x83, 0xc5, 0x22, 0xea, 0xfd, 0xd3, 0x0c,
2260xe2, 0x17, 0x18, 0x7c, 0x6a, 0x4c, 0xde, 0x77, 0xb4, 0x53, 0x9b, 0x4c, 0x81, 0xcd, 0x23,
2270x60, 0xaa, 0x0e, 0x25, 0x73, 0x9c, 0x02, 0x79, 0x32, 0x30, 0xdf, 0x74, 0xdf, 0x75, 0x19,
2280xf4, 0xa5, 0x14, 0x5c, 0xf7, 0x7a, 0xa8, 0xa5, 0x91, 0x84, 0x7c, 0x60, 0x03, 0x06, 0x3b,
2290xcd, 0x50, 0xb6, 0x27, 0x9c, 0xfe, 0xb1, 0xdd, 0xcc, 0xd3, 0xb0, 0x59, 0x24, 0xb2, 0xca,
2300xe2, 0x1c, 0x81, 0x22, 0x9d, 0x07, 0x8f, 0x8e, 0xb9, 0xbe, 0x4e, 0xfa, 0xfc, 0x39, 0x65,
2310xba, 0xbf, 0x9d, 0x12, 0x37, 0x5e, 0x97, 0x7e, 0xf3, 0x89, 0xf5, 0x5d, 0xf5, 0xe3, 0x09,
2320x8c, 0x62, 0xb5, 0x20, 0x9d, 0x0c, 0x53, 0x8a, 0x68, 0x1b, 0xd2, 0x8f, 0x75, 0x17, 0x5d,
2330xd4, 0xe5, 0xda, 0x75, 0x62, 0x19, 0x14, 0x6a, 0x26, 0x2d, 0xeb, 0xf8, 0xaf, 0x37, 0xf0,
2340x6c, 0xa4, 0x55, 0xb1, 0xbc, 0xe2, 0x33, 0xc0, 0x9a, 0xca, 0xb0, 0x11, 0x49, 0x4f, 0x68,
2350x9b, 0x3b, 0x6b, 0x3c, 0xcc, 0x13, 0xf6, 0xc7, 0x85, 0x61, 0x68, 0x42, 0xae, 0xbb, 0xdd,
2360xcd, 0x45, 0x16, 0x29, 0x1d, 0xea, 0xdb, 0xc8, 0x03, 0x94, 0x3c, 0xee, 0x4f, 0x82, 0x11,
2370xc3, 0xec, 0x28, 0xbd, 0x97, 0x05, 0x99, 0xde, 0xd7, 0xbb, 0x5e, 0x22, 0x1f, 0xd4, 0xeb,
2380x64, 0xd9, 0x92, 0xd9, 0x85, 0xb7, 0x6a, 0x05, 0x6a, 0xe4, 0x24, 0x41, 0xf1, 0xcd, 0xf0,
2390xd8, 0x3f, 0xf8, 0x9e, 0x0e, 0xcd, 0x0b, 0x7a, 0x70, 0x6b, 0x5a, 0x75, 0x0a, 0x6a, 0x33,
2400x88, 0xec, 0x17, 0x75, 0x08, 0x70, 0x10, 0x2f, 0x24, 0xcf, 0xc4, 0xe9, 0x42, 0x00, 0x61,
2410x94, 0xca, 0x1f, 0x3a, 0x76, 0x06, 0xfa, 0xd2, 0x48, 0x81, 0xf0, 0x77, 0x60, 0x03, 0x45,
2420xd9, 0x61, 0xf4, 0xa4, 0x6f, 0x3d, 0xd9, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec,
2430x3b, 0xf4, 0x4b, 0xf5, 0x68, 0x52, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5,
2440xa9, 0xb1, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xa5, 0xa9, 0xb1,
2450xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0xeb, 0x54, 0x0b,
2460x75, 0x68, 0x52, 0x07, 0x8c, 0x9a, 0x97, 0x8d, 0x79, 0x70, 0x62, 0x46, 0xef, 0x5c, 0x1b,
2470x95, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x67, 0x4c, 0x1a, 0xb6,
2480xcf, 0xfd, 0x78, 0x53, 0x24, 0xab, 0xb5, 0xc9, 0xf1, 0x60, 0x23, 0xa5, 0xc8, 0x12, 0x87,
2490x6d, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xc7, 0x0c, 0x9a, 0x97, 0xac,
2500xda, 0x36, 0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x47,
2510xed, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8c, 0x7b, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef,
2520x3d, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xdf,
2530x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x53, 0x05, 0x69,
2540x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x27, 0xcc, 0xfb, 0x74,
2550x4b, 0x14, 0x8b, 0x94, 0x8b, 0x75, 0x68, 0x33, 0xc5, 0x08, 0x92, 0x87, 0x8c, 0x9a, 0xb6,
2560xcf, 0x1c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0x89, 0x71, 0x60,
2570x23, 0xc4, 0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xf6, 0x6e, 0x3f, 0xfc, 0x5b, 0x15, 0xa8, 0xd2,
2580x26, 0xaf, 0xbd, 0xf8, 0x72, 0x66, 0x2f, 0xdc, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa,
2590xb7, 0xcd, 0xf9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6f, 0x3d, 0xd9, 0x30, 0xe2, 0x27, 0xcc,
2600xfb, 0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x70, 0x43, 0x04, 0x6b, 0x35, 0xc9, 0xf1,
2610x60, 0x23, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xe6, 0x2f, 0xbd,
2620xf8, 0x72, 0x66, 0x4e, 0x1e, 0xbe, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x1d, 0x99, 0x91, 0xa0,
2630xa3, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93, 0xa4, 0xab, 0xd4, 0x0b, 0x75, 0x49, 0x10, 0xa2,
2640xc6, 0xef, 0x3d, 0xf8, 0x53, 0x24, 0xab, 0xb5, 0xe8, 0x33, 0xe4, 0x4a, 0x16, 0xae, 0xde,
2650x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xb3, 0xc5, 0x08, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0xe1, 0x21,
2660xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x5c, 0x3a, 0xd7, 0x0d, 0x98, 0x93, 0xa4, 0xca,
2670x16, 0xae, 0xde, 0x1f, 0x9d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x72, 0x47, 0x0c,
2680x9a, 0xb6, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87,
2690x6d, 0x39, 0xf0, 0x43, 0x04, 0x8a, 0x96, 0xae, 0xde, 0x3e, 0xdf, 0x1d, 0x99, 0x91, 0xa0,
2700xc2, 0x06, 0x6f, 0x3d, 0xf8, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0x8d, 0x98, 0x93, 0x85, 0x88,
2710x73, 0x45, 0xe9, 0x31, 0xe0, 0x23, 0xa5, 0xa9, 0xd0, 0x03, 0x84, 0x8a, 0x96, 0xae, 0xde,
2720x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xd2, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x82,
2730x67, 0x2d, 0xd8, 0x13, 0xa4, 0xab, 0xd4, 0x0b, 0x94, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20,
2740xa3, 0xa5, 0xc8, 0xf3, 0x45, 0xe9, 0x50, 0x22, 0xc6, 0xef, 0x5c, 0x3a, 0xd7, 0x0d, 0x98,
2750x93, 0x85, 0x88, 0x73, 0x64, 0x4a, 0xf7, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0x0a, 0x96,
2760xae, 0xde, 0x3e, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x78, 0x72,
2770x66, 0x2f, 0xbd, 0xd9, 0x30, 0xc3, 0xe5, 0x48, 0x12, 0x87, 0x8c, 0x7b, 0x55, 0x28, 0xd2,
2780x07, 0x8c, 0x9a, 0x97, 0xac, 0xda, 0x17, 0x8d, 0x79, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x54,
2790x0b, 0x94, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xfc, 0x5b, 0x15, 0xa8, 0xd2, 0x26, 0xaf,
2800xdc, 0x1b, 0xb4, 0xea, 0x37, 0xec, 0x3b, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0x93, 0x85, 0x69,
2810x31, 0xc1, 0xe1, 0x40, 0xe3, 0x25, 0xc8, 0x12, 0x87, 0x8c, 0x9a, 0xb6, 0xcf, 0xfd, 0x59,
2820x11, 0xa0, 0xc2, 0x06, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x37,
2830xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0x95, 0x89, 0x71, 0x41,
2840x00, 0x63, 0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x0f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0x93, 0x85,
2850x69, 0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x9e, 0xbe, 0xdf, 0x3c, 0xfa, 0x57, 0x2c, 0xda,
2860x36, 0xee, 0x3f, 0xfc, 0x5b, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d,
2870x38, 0xf2, 0x47, 0xed, 0x58, 0x13, 0xa4, 0xca, 0xf7, 0x4d, 0xf9, 0x51, 0x01, 0x80, 0x63,
2880x44, 0xeb, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xa9, 0xb1,
2890xe0, 0x42, 0x06, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0x0a, 0x96, 0x8f, 0x7d,
2900x78, 0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0xbc, 0xfa, 0x57, 0x0d,
2910x79, 0x51, 0x01, 0x61, 0x21, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xc1, 0xe1, 0x40, 0x02,
2920x67, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xd6, 0x0f, 0x9c, 0x9b,
2930xb4, 0xcb, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x35, 0xc9, 0xf1,
2940x60, 0x42, 0x06, 0x8e, 0x7f, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xfc, 0x7a, 0x76, 0x6e, 0x5e,
2950x3e, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xc0, 0xe3, 0x44,
2960xeb, 0x54, 0x2a, 0xb7, 0xcd, 0xf9, 0x70, 0x62, 0x27, 0xad, 0xd8, 0x32, 0xc7, 0x0c, 0x7b,
2970x74, 0x4b, 0x14, 0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x39, 0xd1, 0x20,
2980xc2, 0xe7, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0xb2, 0xc7, 0x0c, 0x59, 0x28, 0xf3, 0x9b };
299
300// clang-format off
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pointer_transport.c b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pointer_transport.c
new file mode 100644
index 000000000..003468c82
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pointer_transport.c
@@ -0,0 +1,375 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <string.h>
18#include <stddef.h>
19
20#include "matrix.h"
21#include QMK_KEYBOARD_H
22
23#define ROWS_PER_HAND (MATRIX_ROWS / 2)
24
25#ifdef RGBLIGHT_ENABLE
26# include "rgblight.h"
27#endif
28
29#ifdef BACKLIGHT_ENABLE
30# include "backlight.h"
31#endif
32
33#ifdef ENCODER_ENABLE
34# include "encoder.h"
35static pin_t encoders_pad[] = ENCODERS_PAD_A;
36# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))
37#endif
38
39#ifdef POINTING_DEVICE_ENABLE
40static uint16_t device_cpi = 0;
41static int8_t split_mouse_x = 0, split_mouse_y = 0;
42#endif
43
44#if defined(USE_I2C)
45
46# include "i2c_master.h"
47# include "i2c_slave.h"
48
49typedef struct _I2C_slave_buffer_t {
50 matrix_row_t smatrix[ROWS_PER_HAND];
51 uint8_t backlight_level;
52# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
53 rgblight_syncinfo_t rgblight_sync;
54# endif
55# ifdef ENCODER_ENABLE
56 uint8_t encoder_state[NUMBER_OF_ENCODERS];
57# endif
58# ifdef WPM_ENABLE
59 uint8_t current_wpm;
60# endif
61 int8_t mouse_x;
62 int8_t mouse_y;
63 uint16_t device_cpi;
64} I2C_slave_buffer_t;
65
66static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg;
67
68# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)
69# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
70# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, mmatrix)
71# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
72# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm)
73# define I2C_MOUSE_X_START offsetof(I2C_slave_buffer_t, mouse_x)
74# define I2C_MOUSE_Y_START offsetof(I2C_slave_buffer_t, mouse_y)
75# define I2C_MOUSE_DPI_START offsetof(I2C_slave_buffer_t, device_cpi)
76# define TIMEOUT 100
77
78# ifndef SLAVE_I2C_ADDRESS
79# define SLAVE_I2C_ADDRESS 0x32
80# endif
81
82// Get rows from other half over i2c
83bool transport_master(matrix_row_t matrix[]) {
84 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, sizeof(i2c_buffer->smatrix), TIMEOUT);
85
86 // write backlight info
87# ifdef BACKLIGHT_ENABLE
88 uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0;
89 if (level != i2c_buffer->backlight_level) {
90 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
91 i2c_buffer->backlight_level = level;
92 }
93 }
94# endif
95
96# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
97 if (rgblight_get_change_flags()) {
98 rgblight_syncinfo_t rgblight_sync;
99 rgblight_get_syncinfo(&rgblight_sync);
100 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) {
101 rgblight_clear_change_flags();
102 }
103 }
104# endif
105
106# ifdef ENCODER_ENABLE
107 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT);
108 encoder_update_raw(i2c_buffer->encoder_state);
109# endif
110
111# ifdef WPM_ENABLE
112 uint8_t current_wpm = get_current_wpm();
113 if (current_wpm != i2c_buffer->current_wpm) {
114 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)&current_wpm, sizeof(current_wpm), TIMEOUT) >= 0) {
115 i2c_buffer->current_wpm = current_wpm;
116 }
117 }
118# endif
119
120# ifdef POINTING_DEVICE_ENABLE
121 if (is_keyboard_left()) {
122 report_mouse_t temp_report = pointing_device_get_report();
123 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT);
124 temp_report.x = i2c_buffer->mouse_x;
125 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT);
126 temp_report.y = i2c_buffer->mouse_y;
127 pointing_device_set_report(temp_report);
128
129 if (device_cpi != i2c_buffer->device_cpi) {
130 if(i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_DPI_START, (void *)&device_cpi, sizeof(device_cpi), TIMEOUT) >= 0) {
131 i2c_buffer->device_cpi = device_cpi
132 }
133 }
134 }
135# endif
136
137 return true;
138}
139
140void transport_slave(matrix_row_t matrix[]) {
141 // Copy matrix to I2C buffer
142 memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix));
143
144// Read Backlight Info
145# ifdef BACKLIGHT_ENABLE
146 backlight_set(i2c_buffer->backlight_level);
147# endif
148
149# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
150 // Update the RGB with the new data
151 if (i2c_buffer->rgblight_sync.status.change_flags != 0) {
152 rgblight_update_sync(&i2c_buffer->rgblight_sync, false);
153 i2c_buffer->rgblight_sync.status.change_flags = 0;
154 }
155# endif
156
157# ifdef ENCODER_ENABLE
158 encoder_state_raw(i2c_buffer->encoder_state);
159# endif
160
161# ifdef WPM_ENABLE
162 set_current_wpm(i2c_buffer->current_wpm);
163# endif
164
165# ifdef POINTING_DEVICE_ENABLE
166 if (!is_keyboard_left()) {
167 static uint16_t cpi;
168 if (cpi != i2c_buffer->device_cpi) {
169 cpi = i2c_buffer->device_cpi;
170 pmw_set_cpi(cpi);
171 }
172 i2c_buffer->mouse_x = split_mouse_x;
173 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT);
174 i2c_buffer->mouse_y = split_mouse_y;
175 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT);
176 }
177
178# endif
179}
180
181void transport_master_init(void) { i2c_init(); }
182
183void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
184
185#else // USE_SERIAL
186
187# include "serial.h"
188
189typedef struct _Serial_s2m_buffer_t {
190 // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
191 matrix_row_t smatrix[ROWS_PER_HAND];
192# ifdef ENCODER_ENABLE
193 uint8_t encoder_state[NUMBER_OF_ENCODERS];
194# endif
195 int8_t mouse_x;
196 int8_t mouse_y;
197} Serial_s2m_buffer_t;
198
199typedef struct _Serial_m2s_buffer_t {
200# ifdef BACKLIGHT_ENABLE
201 uint8_t backlight_level;
202# endif
203# ifdef WPM_ENABLE
204 uint8_t current_wpm;
205# endif
206 uint16_t device_cpi;
207} Serial_m2s_buffer_t;
208
209# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
210// When MCUs on both sides drive their respective RGB LED chains,
211// it is necessary to synchronize, so it is necessary to communicate RGB
212// information. In that case, define RGBLIGHT_SPLIT with info on the number
213// of LEDs on each half.
214//
215// Otherwise, if the master side MCU drives both sides RGB LED chains,
216// there is no need to communicate.
217
218typedef struct _Serial_rgblight_t {
219 rgblight_syncinfo_t rgblight_sync;
220} Serial_rgblight_t;
221
222volatile Serial_rgblight_t serial_rgblight = {};
223uint8_t volatile status_rgblight = 0;
224# endif
225
226volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
227volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
228uint8_t volatile status0 = 0;
229
230enum serial_transaction_id {
231 GET_SLAVE_MATRIX = 0,
232# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
233 PUT_RGBLIGHT,
234# endif
235};
236
237SSTD_t transactions[] = {
238 [GET_SLAVE_MATRIX] =
239 {
240 (uint8_t *)&status0,
241 sizeof(serial_m2s_buffer),
242 (uint8_t *)&serial_m2s_buffer,
243 sizeof(serial_s2m_buffer),
244 (uint8_t *)&serial_s2m_buffer,
245 },
246# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
247 [PUT_RGBLIGHT] =
248 {
249 (uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer
250 },
251# endif
252};
253
254void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
255
256void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
257
258# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
259
260// rgblight synchronization information communication.
261
262void transport_rgblight_master(void) {
263 if (rgblight_get_change_flags()) {
264 rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync);
265 if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) {
266 rgblight_clear_change_flags();
267 }
268 }
269}
270
271void transport_rgblight_slave(void) {
272 if (status_rgblight == TRANSACTION_ACCEPTED) {
273 rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false);
274 status_rgblight = TRANSACTION_END;
275 }
276}
277
278# else
279# define transport_rgblight_master()
280# define transport_rgblight_slave()
281# endif
282
283bool transport_master(matrix_row_t matrix[]) {
284# ifndef SERIAL_USE_MULTI_TRANSACTION
285 if (soft_serial_transaction() != TRANSACTION_END) {
286 return false;
287 }
288# else
289 transport_rgblight_master();
290 if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) {
291 return false;
292 }
293# endif
294
295 // TODO: if MATRIX_COLS > 8 change to unpack()
296 for (int i = 0; i < ROWS_PER_HAND; ++i) {
297 matrix[i] = serial_s2m_buffer.smatrix[i];
298 }
299
300# ifdef BACKLIGHT_ENABLE
301 // Write backlight level for slave to read
302 serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0;
303# endif
304
305# ifdef ENCODER_ENABLE
306 encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state);
307# endif
308
309# ifdef WPM_ENABLE
310 // Write wpm to slave
311 serial_m2s_buffer.current_wpm = get_current_wpm();
312# endif
313
314# ifdef POINTING_DEVICE_ENABLE
315 if (is_keyboard_left()) {
316 report_mouse_t temp_report = pointing_device_get_report();
317 temp_report.x = serial_s2m_buffer.mouse_x;
318 temp_report.y = serial_s2m_buffer.mouse_y;
319 pointing_device_set_report(temp_report);
320 serial_m2s_buffer.device_cpi = device_cpi;
321 }
322# endif
323
324 return true;
325}
326
327void transport_slave(matrix_row_t matrix[]) {
328 transport_rgblight_slave();
329
330 // TODO: if MATRIX_COLS > 8 change to pack()
331 for (int i = 0; i < ROWS_PER_HAND; ++i) {
332 serial_s2m_buffer.smatrix[i] = matrix[i];
333 }
334
335# ifdef BACKLIGHT_ENABLE
336 backlight_set(serial_m2s_buffer.backlight_level);
337# endif
338
339# ifdef ENCODER_ENABLE
340 encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state);
341# endif
342
343# ifdef WPM_ENABLE
344 set_current_wpm(serial_m2s_buffer.current_wpm);
345# endif
346
347# ifdef POINTING_DEVICE_ENABLE
348 if (!is_keyboard_left()) {
349 static uint16_t cpi;
350 if (cpi != serial_m2s_buffer.device_cpi) {
351 cpi = serial_m2s_buffer.device_cpi;
352 pmw_set_cpi(cpi);
353 }
354 serial_s2m_buffer.mouse_x = split_mouse_x;
355 serial_s2m_buffer.mouse_y = split_mouse_y;
356 }
357
358# endif
359}
360
361#endif
362
363#ifdef POINTING_DEVICE_ENABLE
364void master_mouse_send(int8_t x, int8_t y) {
365 split_mouse_x = x;
366 split_mouse_y = y;
367}
368void trackball_set_cpi(uint16_t cpi) {
369 if (!is_keyboard_left()) {
370 pmw_set_cpi(cpi);
371 } else {
372 device_cpi = cpi * 1.5;
373 }
374}
375#endif
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/post_config.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/post_config.h
new file mode 100644
index 000000000..40f1029b5
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/post_config.h
@@ -0,0 +1,33 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#ifndef MOUSEKEY_WHEEL_DELTA
20# define MOUSEKEY_WHEEL_DELTA 1
21#endif
22#ifndef MOUSEKEY_WHEEL_DELAY
23# define MOUSEKEY_WHEEL_DELAY 200
24#endif
25#ifndef MOUSEKEY_WHEEL_INTERVAL
26# define MOUSEKEY_WHEEL_INTERVAL 50
27#endif
28#ifndef MOUSEKEY_WHEEL_MAX_SPEED
29# define MOUSEKEY_WHEEL_MAX_SPEED 8
30#endif
31#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
32# define MOUSEKEY_WHEEL_TIME_TO_MAX 80
33#endif
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/readme.md b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/readme.md
new file mode 100644
index 000000000..b6e38dc84
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/readme.md
@@ -0,0 +1,21 @@
1# Drashna's Dactyl Manuform (5x6) with a right side trackball
2
3![](https://preview.redd.it/zwt91036m3y51.jpg?width=960&crop=smart&auto=webp&s=e030deb7d8285c95a1a30c69a7e7a71f750e87bb)
4
5It's a Dactyl Manuform with an integrated thumb based trackball, using the pmw3360 optical sensor.
6
7It'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.
8
9
10* Keyboard Maintainer: [Drashna Jael're](https://github.com/drashna)
11* 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/)
12
13Make example for this keyboard (after setting up your build environment):
14
15 make handwired/dactyl_manuform/5x6_right_trackball:default
16
17Flashing example for this keyboard:
18
19 make handwired/dactyl_manuform/5x6_right_trackball:default:flash
20
21See 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).
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk
new file mode 100644
index 000000000..19b330cdc
--- /dev/null
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk
@@ -0,0 +1,30 @@
1# MCU name
2MCU = at90usb1286
3
4# Bootloader selection
5BOOTLOADER = halfkay
6
7# Build Options
8# change yes to no to disable
9#
10BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration
11MOUSEKEY_ENABLE = yes # Mouse keys
12EXTRAKEY_ENABLE = yes # Audio control and System control
13CONSOLE_ENABLE = no # Console for debug
14COMMAND_ENABLE = yes # Commands for debug and configuration
15# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
16SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
17# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
18NKRO_ENABLE = no # USB Nkey Rollover
19BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
20RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
21BLUETOOTH_ENABLE = no # Enable Bluetooth
22AUDIO_ENABLE = no # Audio output
23SWAP_HANDS_ENABLE = yes
24POINTING_DEVICE_ENABLE = yes
25
26SPLIT_KEYBOARD = yes
27SPLIT_TRANSPORT = custom
28
29SRC += pointer_transport.c pmw3360.c
30QUANTUM_LIB_SRC += serial.c i2c_master.c i2c_slave.c spi_master.c
diff --git a/keyboards/handwired/dactyl_manuform/dactyl_manuform.h b/keyboards/handwired/dactyl_manuform/dactyl_manuform.h
index c91b247f1..7352b5e83 100644
--- a/keyboards/handwired/dactyl_manuform/dactyl_manuform.h
+++ b/keyboards/handwired/dactyl_manuform/dactyl_manuform.h
@@ -14,6 +14,8 @@
14 #include "6x6.h" 14 #include "6x6.h"
15#elif KEYBOARD_handwired_dactyl_manuform_dmote_62key 15#elif KEYBOARD_handwired_dactyl_manuform_dmote_62key
16 #include "62key.h" 16 #include "62key.h"
17#elif KEYBOARD_handwired_dactyl_manuform_5x6_right_trackball
18# include "5x6_right_trackball.h"
17#endif 19#endif
18 20
19#include "quantum.h" 21#include "quantum.h"