Compare commits

..

11 Commits

Author SHA1 Message Date
Ryan
e3211e307e Fix small typo in V-USB configuration descriptor (#11253) 2020-12-21 13:12:07 +11:00
Ryan
0239ce025a Doctor: add check for .git folder (#11208)
Co-authored-by: Erovia <Erovia@users.noreply.github.com>
2020-12-20 15:46:01 +01:00
Nick Brassel
13bbeefc5a Follow symlinks when listing keyboards. (#11250) 2020-12-20 19:08:39 +11:00
Takeshi ISHII
63362a9c5e [Keymap] fix keyboards/helix/rev2/keymaps/default/oled_display.c (#11228)
Fixed the OLED display on the right side as it was showing some garbage.
右側のOLEDディスプレイにゴミが表示されていたのを修正しました。
2020-12-20 13:27:54 +11:00
MechMerlin
25b1367806 VIA Support: MF68 (#11030)
* add via support to mf68 pcb

* add license header
2020-12-19 13:14:41 -08:00
Zach White
624cafbfd2 Change keyboard json format to bring it inline with the current api (#11231) 2020-12-19 19:46:30 +01:00
Drashna Jaelre
5619b1d3db [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>
2020-12-19 19:43:00 +01:00
Zach White
bded5f473c simplify qmk doctor to make room for #11208 (#11242) 2020-12-18 16:42:30 -08:00
precondition
6890090fbb Updated usage of qmk c2json (#11148) 2020-12-18 21:56:23 +01:00
Zach White
03cbee8637 Add the ability to exclude keyboards from travis builds (#11178)
* add the ability to exclude keyboards from travis builds

* add filtering to make all:

* only skip keyboards during make all:

* working implementation

* forego a CI_KEYBOARDS variable

* optimize the startup by only listing keyboards once

* add sort -u to all list_keyboard invocations

* move the if else if tree back to 1 level
2020-12-18 12:17:53 -08:00
Joel Challis
a9f7d4dccc Various compilation fixes for avr-gcc 10 (#9269) 2020-12-18 17:28:29 +00:00
46 changed files with 1991 additions and 99 deletions

View File

@@ -99,40 +99,13 @@ $(eval $(call NEXT_PATH_ELEMENT))
# endif
# endif
define GET_KEYBOARDS
ifndef ALT_GET_KEYBOARDS
All_RULES_MK := $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/rules.mk))
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/rules.mk))
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/rules.mk))
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/*/rules.mk))
KEYMAPS_MK := $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/keymaps/*/rules.mk))
KEYMAPS_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/keymaps/*/rules.mk))
KEYMAPS_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/keymaps/*/rules.mk))
KEYMAPS_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/*/keymaps/*/rules.mk))
KEYBOARDS := $$(sort $$(filter-out $$(KEYMAPS_MK), $$(All_RULES_MK)))
else
KEYBOARDS := $(shell find keyboards/ -type f -iname "rules.mk" | grep -v keymaps | sed 's!keyboards/\(.*\)/rules.mk!\1!' | sort | uniq)
endif
endef
$(eval $(call GET_KEYBOARDS))
# Only consider folders with makefiles, to prevent errors in case there are extra folders
#KEYBOARDS += $(patsubst $(ROOD_DIR)/keyboards/%/rules.mk,%,$(wildcard $(ROOT_DIR)/keyboards/*/*/rules.mk))
.PHONY: list-keyboards
list-keyboards:
echo $(KEYBOARDS)
define PRINT_KEYBOARD
$(info $(PRINTING_KEYBOARD))
endef
util/list_keyboards.sh | sort -u | tr '\n' ' '
.PHONY: generate-keyboards-file
generate-keyboards-file:
$(foreach PRINTING_KEYBOARD,$(KEYBOARDS),$(eval $(call PRINT_KEYBOARD)))
util/list_keyboards.sh | sort -u
.PHONY: clean
clean:
@@ -159,7 +132,6 @@ endif
# $(info Keyboard: $(KEYBOARD))
# $(info Keymap: $(KEYMAP))
# $(info Subproject: $(SUBPROJECT))
# $(info Keyboards: $(KEYBOARDS))
# Set the default goal depending on where we are running make from
@@ -294,7 +266,7 @@ define PARSE_RULE
$$(eval $$(call PARSE_TEST))
# If the rule starts with the name of a known keyboard, then continue
# the parsing from PARSE_KEYBOARD
else ifeq ($$(call TRY_TO_MATCH_RULE_FROM_LIST,$$(KEYBOARDS)),true)
else ifeq ($$(call TRY_TO_MATCH_RULE_FROM_LIST,$$(shell util/list_keyboards.sh | sort -u)),true)
KEYBOARD_RULE=$$(MATCHED_ITEM)
$$(eval $$(call PARSE_KEYBOARD,$$(MATCHED_ITEM)))
# Otherwise use the KEYBOARD variable, which is determined either by
@@ -411,7 +383,7 @@ endef
# if we are going to compile all keyboards, match the rest of the rule
# for each of them
define PARSE_ALL_KEYBOARDS
$$(eval $$(call PARSE_ALL_IN_LIST,PARSE_KEYBOARD,$(KEYBOARDS)))
$$(eval $$(call PARSE_ALL_IN_LIST,PARSE_KEYBOARD,$(shell util/list_keyboards.sh noci | sort -u)))
endef
# $1 Subproject

View File

@@ -175,7 +175,7 @@ Creates a keymap.json from a keymap.c.
**Usage**:
```
qmk c2json [--no-cpp] [-o OUTPUT] filename
qmk c2json -km KEYMAP -kb KEYBOARD [-q] [--no-cpp] [-o OUTPUT] filename
```
## `qmk lint`

View File

@@ -21,8 +21,6 @@
#include <math.h>
uint8_t DRV2605L_transfer_buffer[2];
uint8_t DRV2605L_tx_register[0];
uint8_t DRV2605L_read_buffer[0];
uint8_t DRV2605L_read_register;
void DRV_write(uint8_t drv_register, uint8_t settings) {
@@ -32,8 +30,7 @@ void DRV_write(uint8_t drv_register, uint8_t settings) {
}
uint8_t DRV_read(uint8_t regaddress) {
i2c_readReg(DRV2605L_BASE_ADDRESS << 1, regaddress, DRV2605L_read_buffer, 1, 100);
DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];
i2c_readReg(DRV2605L_BASE_ADDRESS << 1, regaddress, &DRV2605L_read_register, 1, 100);
return DRV2605L_read_register;
}

View File

@@ -20,8 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "config_common.h"
/* USB Device descriptor parameter */
#define VENDOR_ID 0xCEEB
#define PRODUCT_ID 0x0510
#define VENDOR_ID 0x3430 // "40"
#define PRODUCT_ID 0x4D68 // "M68"
#define DEVICE_VER 0x0101
#define MANUFACTURER di0ib
#define PRODUCT MF68

View File

@@ -0,0 +1,49 @@
/* Copyright 2020 MechMerlin
*
* 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
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_68_ansi(
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_PGUP,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_PGDN,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, MO(1), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
[1] = LAYOUT_68_ansi(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_BSPC, KC_VOLU, KC_HOME,
_______, _______, _______, KC_UP, _______, _______, _______, _______, _______, _______, _______, _______, BL_STEP, _______, KC_VOLD, KC_END,
_______, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, _______, _______, KC_MUTE,
_______, _______, _______, _______, _______, _______, _______, KC_MPRV, KC_MPLY, KC_MNXT
),
[2] = LAYOUT_68_ansi(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
[3] = LAYOUT_68_ansi(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
};

View File

@@ -0,0 +1,2 @@
VIA_ENABLE = yes
LTO_ENABLE = yes

View File

@@ -16,7 +16,7 @@
{ K40, K41, K42, K43, K44, K45, K46, K47, K48 }, \
{ K50, K51, K52, K53, K54, K55, K56, K57, K58 }, \
{ K60, K61, K62, K63, K64, K65, K66, K67, K68 }, \
{ K70, K71, K72, K73, K74 } \
{ K70, K71, K72, K73, K74, KC_NO, KC_NO, KC_NO, KC_NO } \
}
#define LAYOUT_kc( \

View File

@@ -14,7 +14,7 @@ BOOTLOADER = caterina
# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
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
@@ -22,7 +22,7 @@ COMMAND_ENABLE = no # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = no # USB Nkey Rollover
NKRO_ENABLE = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality on B7 by default
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
MIDI_ENABLE = no # MIDI controls

View File

@@ -208,8 +208,6 @@ uint32_t layer_state_set_kb(uint32_t state) {
if (is_keyboard_master())
{
current_layer = biton32(state);
serial_m2s_buffer.current_layer = biton32(state);
// If left half, do the LED toggle thing

View File

@@ -56,8 +56,6 @@
{ R40, R41, R42, R43, R44, R45, KC_NO } \
}
uint8_t current_layer;
extern void led_toggle(int id, bool on);
void set_all_leds(bool leds[6]);
extern void set_layer_indicators(uint8_t layer);

View File

@@ -15,7 +15,6 @@ extern size_t keymapsCount; // Total keymaps
extern uint32_t cChord; // Current Chord
extern uint32_t stenoLayers[]; // Chords that simulate QMK layers
extern size_t stenoLayerCount; // Number of simulated layers
uint32_t refChord; // Reference chord for PC macro
// Function defs
void processChord(bool useFakeSteno);
@@ -35,7 +34,7 @@ void CLICK_MOUSE(uint8_t);
#define P(chord, act) if (cChord == (chord)) { if (!lookup) {act;} return chord;}
#define PC(chord, act) if (cChord == (chord)) { if (!lookup) {act;} return chord;} \
for(int i = 0; i < stenoLayerCount; i++) { \
refChord = stenoLayers[i] | chord; \
uint32_t refChord = stenoLayers[i] | chord; \
if (cChord == (refChord)) { if (!lookup) {act;} return refChord;}; \
}

View File

View File

View File

View File

View File

View File

View File

@@ -15,7 +15,6 @@ extern size_t keymapsCount; // Total keymaps
extern uint32_t cChord; // Current Chord
extern uint32_t stenoLayers[]; // Chords that simulate QMK layers
extern size_t stenoLayerCount; // Number of simulated layers
uint32_t refChord; // Reference chord for PC macro
// Function defs
void processChord(bool useFakeSteno);
@@ -35,7 +34,7 @@ void CLICK_MOUSE(uint8_t);
#define P(chord, act) if (cChord == (chord)) { if (!lookup) {act;} return chord;}
#define PC(chord, act) if (cChord == (chord)) { if (!lookup) {act;} return chord;} \
for(int i = 0; i < stenoLayerCount; i++) { \
refChord = stenoLayers[i] | chord; \
uint32_t refChord = stenoLayers[i] | chord; \
if (cChord == (refChord)) { if (!lookup) {act;} return refChord;}; \
}

View File

@@ -38,37 +38,37 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
// MCP Pin Defs
#define RROW1 (1<<3)
#define RROW2 (1<<2)
#define RROW3 (1<<1)
#define RROW4 (1<<0)
#define COL0 (1<<0)
#define COL1 (1<<1)
#define COL2 (1<<2)
#define COL3 (1<<3)
#define COL4 (1<<4)
#define COL5 (1<<5)
#define COL6 (1<<6)
#define RROW1 (1u<<3)
#define RROW2 (1u<<2)
#define RROW3 (1u<<1)
#define RROW4 (1u<<0)
#define COL0 (1u<<0)
#define COL1 (1u<<1)
#define COL2 (1u<<2)
#define COL3 (1u<<3)
#define COL4 (1u<<4)
#define COL5 (1u<<5)
#define COL6 (1u<<6)
// ATmega pin defs
#define ROW1 (1<<6)
#define ROW2 (1<<5)
#define ROW3 (1<<4)
#define ROW4 (1<<1)
#define COL7 (1<<0)
#define COL8 (1<<1)
#define COL9 (1<<2)
#define COL10 (1<<3)
#define COL11 (1<<2)
#define COL12 (1<<3)
#define COL13 (1<<6)
#define ROW1 (1u<<6)
#define ROW2 (1u<<5)
#define ROW3 (1u<<4)
#define ROW4 (1u<<1)
#define COL7 (1u<<0)
#define COL8 (1u<<1)
#define COL9 (1u<<2)
#define COL10 (1u<<3)
#define COL11 (1u<<2)
#define COL12 (1u<<3)
#define COL13 (1u<<6)
//Trackball pin defs
#define TRKUP (1<<4)
#define TRKDN (1<<5)
#define TRKLT (1<<6)
#define TRKRT (1<<7)
#define TRKBTN (1<<6)
#define TRKUP (1u<<4)
#define TRKDN (1u<<5)
#define TRKLT (1u<<6)
#define TRKRT (1u<<7)
#define TRKBTN (1u<<6)
// Multiple for mouse moves

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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}
]
}
}
}

View File

@@ -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

View File

@@ -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,
_______,_______, _______,
_______,_______, _______,
_______,_______, _______,_______,
_______,_______, _______,_______
),
};

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,2 @@
RGBLIGHT_STARTUP_ANIMATION = yes
HAPTIC_ENABLE = SOLENOID

View File

@@ -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;
}

View File

@@ -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)))

View File

@@ -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

View File

@@ -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 *)&current_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

View File

@@ -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

View File

@@ -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).

View File

@@ -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

View File

@@ -14,6 +14,8 @@
#include "6x6.h"
#elif KEYBOARD_handwired_dactyl_manuform_dmote_62key
#include "62key.h"
#elif KEYBOARD_handwired_dactyl_manuform_5x6_right_trackball
# include "5x6_right_trackball.h"
#endif
#include "quantum.h"

View File

@@ -135,6 +135,7 @@ static void render_layer_status(void) {
snprintf(buf,sizeof(buf), "%ld", layer_state);
oled_write(buf, false);
}
oled_write_P(PSTR("\n"), false);
}
# ifdef SSD1306OLED
@@ -160,7 +161,6 @@ void render_status(void) {
# else
render_layer_status();
# endif
oled_write_P(PSTR("\n"), false);
// Host Keyboard LED Status
led_t led_state = host_keyboard_led_state();

View File

@@ -1,6 +1,8 @@
#include QMK_KEYBOARD_H
#include <string.h>
dynamic_macro_t dynamic_macros[DYNAMIC_MACRO_COUNT];
void dynamic_macro_init(void) {
/* zero out macro blocks */
memset(&dynamic_macros, 0, DYNAMIC_MACRO_COUNT * sizeof(dynamic_macro_t));

View File

@@ -71,8 +71,6 @@ typedef struct {
uint16_t checksum;
} dynamic_macro_t;
dynamic_macro_t dynamic_macros[DYNAMIC_MACRO_COUNT];
void dynamic_macro_init(void);
void dynamic_macro_led_blink(void);
void dynamic_macro_record_start(uint8_t macro_id);

View File

@@ -154,6 +154,17 @@ def check_submodules():
return CheckStatus.OK
def check_git_repo():
"""Checks that the .git directory exists inside QMK_HOME.
This is a decent enough indicator that the qmk_firmware directory is a
proper Git repository, rather than a .zip download from GitHub.
"""
dot_git_dir = QMK_FIRMWARE / '.git'
return CheckStatus.OK if dot_git_dir.is_dir() else CheckStatus.WARNING
def check_udev_rules():
"""Make sure the udev rules look good.
"""
@@ -281,6 +292,22 @@ def is_executable(command):
return False
def os_tests():
"""Determine our OS and run platform specific tests
"""
platform_id = platform.platform().lower()
if 'darwin' in platform_id or 'macos' in platform_id:
return os_test_macos()
elif 'linux' in platform_id:
return os_test_linux()
elif 'windows' in platform_id:
return os_test_windows()
else:
cli.log.warning('Unsupported OS detected: %s', platform_id)
return CheckStatus.WARNING
def os_test_linux():
"""Run the Linux specific tests.
"""
@@ -317,23 +344,18 @@ def doctor(cli):
* [ ] Compile a trivial program with each compiler
"""
cli.log.info('QMK Doctor is checking your environment.')
status = CheckStatus.OK
# Determine our OS and run platform specific tests
platform_id = platform.platform().lower()
if 'darwin' in platform_id or 'macos' in platform_id:
status = os_test_macos()
elif 'linux' in platform_id:
status = os_test_linux()
elif 'windows' in platform_id:
status = os_test_windows()
else:
cli.log.warning('Unsupported OS detected: %s', platform_id)
status = CheckStatus.WARNING
status = os_tests()
cli.log.info('QMK home: {fg_cyan}%s', QMK_FIRMWARE)
# Make sure our QMK home is a Git repo
git_ok = check_git_repo()
if git_ok == CheckStatus.WARNING:
cli.log.warning("QMK home does not appear to be a Git repository! (no .git folder)")
status = CheckStatus.WARNING
# Make sure the basic CLI tools we need are available and can be executed.
bin_ok = check_binaries()

View File

@@ -36,7 +36,7 @@ def generate_api(cli):
keyboard_readme_src = Path('keyboards') / keyboard_name / 'readme.md'
keyboard_dir.mkdir(parents=True, exist_ok=True)
keyboard_info.write_text(json.dumps(kb_all['keyboards'][keyboard_name]))
keyboard_info.write_text(json.dumps({'last_updated': current_datetime(), 'keyboards': {keyboard_name: kb_all['keyboards'][keyboard_name]}}))
if keyboard_readme_src.exists():
copyfile(keyboard_readme_src, keyboard_readme)

View File

@@ -230,11 +230,15 @@ def merge_info_jsons(keyboard, info_data):
"""
for info_file in find_info_json(keyboard):
# Load and validate the JSON data
with info_file.open('r') as info_fd:
new_info_data = json.load(info_fd)
try:
with info_file.open('r') as info_fd:
new_info_data = json.load(info_fd)
except Exception as e:
_log_error(info_data, "Invalid JSON in file %s: %s: %s" % (str(info_file), e.__class__.__name__, e))
continue
if not isinstance(new_info_data, dict):
_log_error(info_data, "Invalid file %s, root object should be a dictionary.", str(info_file))
_log_error(info_data, "Invalid file %s, root object should be a dictionary." % (str(info_file),))
continue
# Copy whitelisted keys into `info_data`

View File

@@ -24,7 +24,7 @@ __attribute__((weak)) float fauxclicky_pressed_note[2] = MUSICAL_NOTE(_D4, 0.25
__attribute__((weak)) float fauxclicky_released_note[2] = MUSICAL_NOTE(_C4, 0.125);
__attribute__((weak)) float fauxclicky_beep_note[2] = MUSICAL_NOTE(_C4, 0.25);
bool fauxclicky_enabled;
extern bool fauxclicky_enabled;
//
// tempo in BPM

View File

@@ -680,7 +680,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
},
.bcdHID = 0x0101,
.bCountryCode = 0x00,
.bNumDescriptors = 2,
.bNumDescriptors = 1,
.bDescriptorType = USBDESCR_HID_REPORT,
.wDescriptorLength = sizeof(raw_hid_report)
},

10
util/list_keyboards.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
# Temporary shell script to find keyboards
#
# This allows us to exclude keyboards by including a .noci file.
find -L keyboards -type f -name rules.mk | grep -v keymaps | while read keyboard; do
keyboard=$(echo $keyboard | sed 's!keyboards/\(.*\)/rules.mk!\1!')
[ "$1" = "noci" -a -e "keyboards/${keyboard}/.noci" ] || echo "$keyboard"
done