Update qmk, navigator
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,3 +4,6 @@
|
||||
[submodule "docker/qmk_firmware"]
|
||||
path = docker/qmk_firmware
|
||||
url = ssh://git@git.betalupi.com:33/QMK/qmk_firmware.git
|
||||
[submodule "docker/zsa_firmware"]
|
||||
path = docker/zsa_firmware
|
||||
url = ssh://git@git.betalupi.com:33/QMK/zsa_firmware.git
|
||||
|
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ voyager:
|
||||
--user $$(id -u):$$(id -g) \
|
||||
-v "$$(pwd)/output:/build_output" \
|
||||
-v "$$(pwd)/keyboards:/qmk_firmware/keyboards:ro" \
|
||||
-e QMK_TARGET="betalupi_voyager:default" \
|
||||
-e QMK_TARGET="zsa/voyager:betalupi" \
|
||||
git.betalupi.com/mark/qmk
|
||||
|
||||
ergodox:
|
||||
|
@ -48,30 +48,28 @@ RUN python3 -m pip install --upgrade \
|
||||
nose2 \
|
||||
yapf
|
||||
|
||||
# upgrade avr-gcc... for reasons?
|
||||
# upgrade avr-gcc, ergodox patch
|
||||
RUN /bin/bash -c "set -o pipefail && \
|
||||
wget -q https://github.com/ZakKemble/avr-gcc-build/releases/download/v8.3.0-1/avr-gcc-8.3.0-x64-linux.tar.bz2 -O - | tee /tmp/asdf.tar.bz2 | md5sum -c <(echo '588D0BEA4C5D21A1A06AA17625684417 -') && \
|
||||
tar xfj /tmp/asdf.tar.bz2 --strip-components=1 -C / && \
|
||||
wget -q https://github.com/ZakKemble/avr-gcc-build/releases/download/v8.3.0-1/avr-gcc-8.3.0-x64-linux.tar.bz2 -O - | tee /tmp/avr-gcc.tar.bz2 | md5sum -c <(echo '588D0BEA4C5D21A1A06AA17625684417 -') && \
|
||||
tar xfj /tmp/avr-gcc.tar.bz2 --strip-components=1 -C / && \
|
||||
rm -rf /share/ /tmp/*"
|
||||
|
||||
|
||||
|
||||
|
||||
# Install qmk-cli
|
||||
COPY --from=qmk_cli_builder /app/dist /tmp/dist
|
||||
RUN python3 -m pip install /tmp/dist/qmk-*.whl && \
|
||||
rm -rf /tmp/dist
|
||||
|
||||
# Copy qmk repo.
|
||||
# Make sure you've pulled submodules first!
|
||||
COPY qmk_firmware /qmk_firmware
|
||||
# Don't forget to sync submodules
|
||||
# Temporarily use ZSA, qmk doesn't support navigator yet
|
||||
COPY zsa_firmware /qmk_firmware
|
||||
RUN chmod -R 777 /qmk_firmware
|
||||
|
||||
RUN /usr/bin/python3 -m pip install -r /qmk_firmware/requirements.txt
|
||||
|
||||
VOLUME /qmk_firmware/keyboards
|
||||
VOLUME /build_output
|
||||
WORKDIR /qmk_firmware
|
||||
|
||||
ENV SKIP_GIT true
|
||||
ENV SKIP_GIT=true
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
CMD ["/bin/bash", "/entrypoint.sh"]
|
Submodule docker/qmk_cli updated: aecd02e850...7be310f364
Submodule docker/qmk_firmware updated: 0f341dfdd3...8f728aa731
1
docker/zsa_firmware
Submodule
1
docker/zsa_firmware
Submodule
Submodule docker/zsa_firmware added at e87a3e6949
@ -1,221 +0,0 @@
|
||||
#include "betalupi_voyager.h"
|
||||
#include "raw_hid.h"
|
||||
|
||||
keyboard_config_t keyboard_config;
|
||||
|
||||
bool mcp23018_leds[2] = {0, 0};
|
||||
bool is_launching = false;
|
||||
|
||||
void voyager_led_task(void) {
|
||||
if (is_launching) {
|
||||
STATUS_LED_1(false);
|
||||
STATUS_LED_2(false);
|
||||
STATUS_LED_3(false);
|
||||
STATUS_LED_4(false);
|
||||
wait_ms(250);
|
||||
|
||||
STATUS_LED_1(true);
|
||||
STATUS_LED_2(true);
|
||||
wait_ms(250);
|
||||
STATUS_LED_3(true);
|
||||
STATUS_LED_4(true);
|
||||
wait_ms(250);
|
||||
STATUS_LED_1(false);
|
||||
STATUS_LED_2(false);
|
||||
wait_ms(250);
|
||||
STATUS_LED_3(false);
|
||||
STATUS_LED_4(false);
|
||||
wait_ms(250);
|
||||
is_launching = false;
|
||||
layer_state_set_kb(layer_state);
|
||||
}
|
||||
}
|
||||
|
||||
static THD_WORKING_AREA(waLEDThread, 128);
|
||||
static THD_FUNCTION(LEDThread, arg) {
|
||||
(void)arg;
|
||||
chRegSetThreadName("LEDThread");
|
||||
while (true) {
|
||||
voyager_led_task();
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_pre_init_kb(void) {
|
||||
// Initialize Reset pins
|
||||
setPinInput(A8);
|
||||
setPinOutput(A9);
|
||||
writePinLow(A9);
|
||||
|
||||
setPinOutput(B5);
|
||||
setPinOutput(B4);
|
||||
setPinOutput(B3);
|
||||
|
||||
writePinLow(B5);
|
||||
writePinLow(B4);
|
||||
writePinLow(B3);
|
||||
|
||||
chThdCreateStatic(waLEDThread, sizeof(waLEDThread), NORMALPRIO - 16, LEDThread, NULL);
|
||||
keyboard_pre_init_user();
|
||||
|
||||
rgb_matrix_set_flags(LED_FLAG_NONE);
|
||||
rgb_matrix_set_color_all(0, 0, 0);
|
||||
}
|
||||
|
||||
layer_state_t layer_state_set_kb(layer_state_t state) {
|
||||
state = layer_state_set_user(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
// clang-format off
|
||||
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
|
||||
/* Refer to IS31 manual for these locations
|
||||
* driver
|
||||
* | R location
|
||||
* | | G location
|
||||
* | | | B location
|
||||
* | | | | */
|
||||
{0, C2_2, C1_2, C4_3},
|
||||
{0, C2_3, C1_3, C3_3},
|
||||
{0, C2_4, C1_4, C3_4},
|
||||
{0, C2_5, C1_5, C3_5},
|
||||
{0, C2_6, C1_6, C3_6},
|
||||
{0, C2_7, C1_7, C3_7},
|
||||
{0, C2_8, C1_8, C3_8},
|
||||
{0, C8_1, C7_1, C9_1},
|
||||
{0, C8_2, C7_2, C9_2},
|
||||
{0, C8_3, C7_3, C9_3},
|
||||
{0, C8_4, C7_4, C9_4},
|
||||
{0, C8_5, C7_5, C9_5},
|
||||
{0, C8_6, C7_6, C9_6},
|
||||
{0, C2_10, C1_10, C4_11},
|
||||
{0, C2_11, C1_11, C3_11},
|
||||
{0, C2_12, C1_12, C3_12},
|
||||
{0, C2_13, C1_13, C3_13},
|
||||
{0, C2_14, C1_14, C3_14},
|
||||
{0, C2_15, C1_15, C3_15},
|
||||
{0, C2_16, C1_16, C3_16},
|
||||
{0, C8_9, C7_9, C9_9},
|
||||
{0, C8_10, C7_10, C9_10},
|
||||
{0, C8_11, C7_11, C9_11},
|
||||
{0, C8_12, C7_12, C9_12},
|
||||
{0, C8_13, C7_13, C9_13},
|
||||
{0, C8_14, C7_14, C9_14},
|
||||
|
||||
{1, C2_7, C1_7, C3_7},
|
||||
{1, C2_6, C1_6, C3_6},
|
||||
{1, C2_5, C1_5, C3_5},
|
||||
{1, C2_4, C1_4, C3_4},
|
||||
{1, C2_3, C1_3, C3_3},
|
||||
{1, C2_2, C1_2, C4_3},
|
||||
|
||||
{1, C8_5, C7_5, C9_5},
|
||||
{1, C8_4, C7_4, C9_4},
|
||||
{1, C8_3, C7_3, C9_3},
|
||||
{1, C8_2, C7_2, C9_2},
|
||||
{1, C8_1, C7_1, C9_1},
|
||||
{1, C2_8, C1_8, C3_8},
|
||||
|
||||
{1, C2_14, C1_14, C3_14},
|
||||
{1, C2_13, C1_13, C3_13},
|
||||
{1, C2_12, C1_12, C3_12},
|
||||
{1, C2_11, C1_11, C3_11},
|
||||
{1, C2_10, C1_10, C4_11},
|
||||
{1, C8_6, C7_6, C9_6},
|
||||
|
||||
{1, C8_12, C7_12, C9_12},
|
||||
{1, C8_11, C7_11, C9_11},
|
||||
{1, C8_10, C7_10, C9_10},
|
||||
{1, C8_9, C7_9, C9_9},
|
||||
{1, C2_16, C1_16, C3_16},
|
||||
{1, C2_15, C1_15, C3_15},
|
||||
|
||||
{1, C8_14, C7_14, C9_14},
|
||||
{1, C8_13, C7_13, C9_13},
|
||||
};
|
||||
|
||||
led_config_t g_led_config = { {
|
||||
{ NO_LED, 0, 1, 2, 3, 4, 5 },
|
||||
{ NO_LED, 6, 7, 8, 9, 10, 11 },
|
||||
{ NO_LED, 12, 13, 14, 15, 16, 17 },
|
||||
{ NO_LED, 18, 19, 20, 21, 22, NO_LED },
|
||||
{ NO_LED, NO_LED, NO_LED, NO_LED, 23, NO_LED, NO_LED },
|
||||
{ 24, 25, NO_LED, NO_LED, NO_LED, NO_LED, NO_LED },
|
||||
|
||||
{ 26, 27, 28, 29, 30, 31, NO_LED },
|
||||
{ 32, 33, 34, 35, 36, 37, NO_LED },
|
||||
{ 38, 39, 40, 41, 42, 43, NO_LED },
|
||||
{ NO_LED, 45, 46, 47, 48, 49, NO_LED },
|
||||
{ NO_LED, NO_LED, 44, NO_LED, NO_LED, NO_LED, NO_LED },
|
||||
{ NO_LED, NO_LED, NO_LED, NO_LED, NO_LED, 50, 51 },
|
||||
}, {
|
||||
{0, 10}, {17, 10}, {34,8}, {52, 5}, {69, 8}, {86, 10},
|
||||
{0, 21}, {17, 21}, {34, 19}, {52, 17}, {69, 19}, {86, 21},
|
||||
{0, 32}, {17, 32}, {34, 30}, {52, 28}, {69, 30}, {86, 32},
|
||||
{0, 43}, {17, 43}, {34, 41}, {52, 39}, {69, 41}, {86, 43},
|
||||
{86, 53}, {96, 58},
|
||||
|
||||
{138, 10}, {155, 10}, {172, 8}, {190, 5}, {207, 8}, {224, 10},
|
||||
{138, 21}, {155, 21}, {172, 19}, {190, 17}, {207, 19}, {224, 21},
|
||||
{138, 32}, {155, 32}, {172, 30}, {190, 28}, {207, 30}, {224, 32},
|
||||
{138, 43}, {155,43}, {172, 41}, {190, 39}, {207, 41}, {224, 43},
|
||||
{128, 58}, {138, 53}
|
||||
}, {
|
||||
1, 4, 4, 4, 4, 4,
|
||||
1, 4, 4, 4, 4, 4,
|
||||
1, 4, 4, 4, 4, 4,
|
||||
1, 4, 4, 4, 4, 4,
|
||||
1, 1, 4, 4, 4, 4,
|
||||
4, 1, 4, 4, 4, 4,
|
||||
4, 1, 4, 4, 4, 4,
|
||||
4, 1, 4, 4, 4, 4,
|
||||
4, 1, 1, 1
|
||||
} };
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
|
||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
if (!process_record_user(keycode, record)) {
|
||||
return false;
|
||||
}
|
||||
switch (keycode) {
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
case RGB_TOG:
|
||||
if (record->event.pressed) {
|
||||
switch (rgb_matrix_get_flags()) {
|
||||
case LED_FLAG_ALL: {
|
||||
rgb_matrix_set_flags(LED_FLAG_NONE);
|
||||
rgb_matrix_set_color_all(0, 0, 0);
|
||||
} break;
|
||||
default: {
|
||||
rgb_matrix_set_flags(LED_FLAG_ALL);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void matrix_init_kb(void) {
|
||||
keyboard_config.raw = eeconfig_read_kb();
|
||||
|
||||
if (!keyboard_config.led_level && !keyboard_config.led_level_res) {
|
||||
keyboard_config.led_level = true;
|
||||
keyboard_config.led_level_res = 0b11;
|
||||
eeconfig_update_kb(keyboard_config.raw);
|
||||
}
|
||||
matrix_init_user();
|
||||
}
|
||||
|
||||
void eeconfig_init_kb(void) { // EEPROM is getting reset!
|
||||
keyboard_config.raw = 0;
|
||||
keyboard_config.led_level = true;
|
||||
keyboard_config.led_level_res = 0b11;
|
||||
keyboard_config.disable_layer_led = false;
|
||||
|
||||
eeconfig_update_kb(keyboard_config.raw);
|
||||
eeconfig_init_user();
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
#pragma once
|
||||
#include "quantum.h"
|
||||
|
||||
extern bool mcp23018_leds[];
|
||||
|
||||
#define MCP23018_DEFAULT_ADDRESS 0b0100000
|
||||
#define STATUS_LED_1(status) writePin(B5, (bool)status)
|
||||
#define STATUS_LED_2(status) writePin(B4, (bool)status)
|
||||
#define STATUS_LED_3(status) mcp23018_leds[0] = (bool)status
|
||||
#define STATUS_LED_4(status) mcp23018_leds[1] = (bool)status
|
||||
|
||||
/*
|
||||
// clang-format off
|
||||
#define LAYOUT( \
|
||||
k00, k01, k02, k03, k04, k05, k26, k27, k28, k29, k30, k31, \
|
||||
k06, k07, k08, k09, k10, k11, k32, k33, k34, k35, k36, k37, \
|
||||
k12, k13, k14, k15, k16, k17, k38, k39, k40, k41, k42, k43, \
|
||||
k18, k19, k20, k21, k22, k23, k44, k45, k46, k47, k48, k49, \
|
||||
k24, k25, k50, k51 \
|
||||
)\
|
||||
{ \
|
||||
{ KC_NO, k00, k01, k02, k03, k04, k05 }, \
|
||||
{ KC_NO, k06, k07, k08, k09, k10, k11 }, \
|
||||
{ KC_NO, k12, k13, k14, k15, k16, k17 }, \
|
||||
{ KC_NO, k18, k19, k20, k21, k22, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, k23, KC_NO, KC_NO }, \
|
||||
{ k24, k25, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
\
|
||||
{ k26, k27, k28, k29, k30, k31, KC_NO }, \
|
||||
{ k32, k33, k34, k35, k36, k37, KC_NO }, \
|
||||
{ k38, k39, k40, k41, k42, k43, KC_NO }, \
|
||||
{ KC_NO, k45, k46, k47, k48, k49, KC_NO }, \
|
||||
{ KC_NO, KC_NO, k44, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, k50, k51 }, \
|
||||
}
|
||||
// clang-format on
|
||||
*/
|
||||
|
||||
|
||||
// clang-format off
|
||||
#define LAYOUT( \
|
||||
k00, k01, k02, k03, k04, k05, \
|
||||
k06, k07, k08, k09, k10, k11, \
|
||||
k12, k13, k14, k15, k16, k17, \
|
||||
k18, k19, k20, k21, k22, k23, \
|
||||
k24, k25, \
|
||||
k26, k27, k28, k29, k30, k31, \
|
||||
k32, k33, k34, k35, k36, k37, \
|
||||
k38, k39, k40, k41, k42, k43, \
|
||||
k44, k45, k46, k47, k48, k49, \
|
||||
k50, k51 \
|
||||
)\
|
||||
{ \
|
||||
{ KC_NO, k00, k01, k02, k03, k04, k05 }, \
|
||||
{ KC_NO, k06, k07, k08, k09, k10, k11 }, \
|
||||
{ KC_NO, k12, k13, k14, k15, k16, k17 }, \
|
||||
{ KC_NO, k18, k19, k20, k21, k22, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, k23, KC_NO, KC_NO }, \
|
||||
{ k24, k25, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
\
|
||||
{ k26, k27, k28, k29, k30, k31, KC_NO }, \
|
||||
{ k32, k33, k34, k35, k36, k37, KC_NO }, \
|
||||
{ k38, k39, k40, k41, k42, k43, KC_NO }, \
|
||||
{ KC_NO, k45, k46, k47, k48, k49, KC_NO }, \
|
||||
{ KC_NO, KC_NO, k44, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, k50, k51 }, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
enum voyager_keycodes {
|
||||
LED_LEVEL = SAFE_RANGE,
|
||||
BETA_SAFE_RANGE,
|
||||
};
|
||||
|
||||
typedef union {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
bool disable_layer_led : 1;
|
||||
bool placeholder : 1;
|
||||
bool led_level : 1;
|
||||
uint8_t led_level_res : 2; // DO NOT REMOVE
|
||||
};
|
||||
} keyboard_config_t;
|
||||
|
||||
extern keyboard_config_t keyboard_config;
|
||||
|
||||
bool is_transport_connected(void);
|
@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
/* key matrix size */
|
||||
#define MATRIX_ROWS 12
|
||||
#define MATRIX_COLS 7
|
||||
|
||||
/* PCB default pin-out */
|
||||
// #define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 }
|
||||
// #define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 }
|
||||
|
||||
// #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 }
|
||||
// #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 }
|
||||
|
||||
// #define MCP23_LED_R GPB7
|
||||
// #define MCP23_LED_G GPB6
|
||||
// #define MCP23_LED_B GPA7
|
||||
|
||||
// Not needed, is default address:
|
||||
// #define EXTERNAL_EEPROM_I2C_BASE_ADDRESS 0b10100000
|
||||
|
||||
/* COL2ROW or ROW2COL */
|
||||
#define DIODE_DIRECTION ROW2COL
|
||||
|
||||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
|
||||
#define LOCKING_SUPPORT_ENABLE
|
||||
/* Locking resynchronize hack */
|
||||
#define LOCKING_RESYNC_ENABLE
|
||||
|
||||
#define LED_BRIGHTNESS_LO 5
|
||||
#define LED_BRIGHTNESS_HI 100
|
||||
#define LED_BRIGHTNESS_DEFAULT (LED_BRIGHTNESS_LO)
|
||||
|
||||
#define DRIVER_ADDR_1 0b1110100
|
||||
#define DRIVER_ADDR_2 0b1110111
|
||||
|
||||
#define DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 36
|
||||
#define DRIVER_2_LED_TOTAL 36
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
#define RGB_MATRIX_CENTER { 125, 26 }
|
||||
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 175
|
||||
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
|
||||
#define RGB_MATRIX_KEYPRESSES
|
||||
#define RGB_DISABLE_WHEN_USB_SUSPENDED
|
||||
|
||||
#ifndef ISSI_TIMEOUT
|
||||
#define ISSI_TIMEOUT 5
|
||||
#endif
|
||||
|
||||
#define MOUSEKEY_INTERVAL 20
|
||||
#define MOUSEKEY_DELAY 0
|
||||
#define MOUSEKEY_TIME_TO_MAX 60
|
||||
#define MOUSEKEY_MAX_SPEED 7
|
||||
#define MOUSEKEY_WHEEL_DELAY 400
|
||||
#define MOUSEKEY_WHEEL_INTERVAL MOUSEKEY_INTERVAL
|
||||
#define MOUSEKEY_WHEEL_MAX_SPEED MOUSEKEY_MAX_SPEED
|
||||
#define MOUSEKEY_WHEEL_TIME_TO_MAX MOUSEKEY_TIME_TO_MAX
|
||||
|
||||
#define TAPPING_TOGGLE 1
|
||||
|
||||
// Delay between each i2c io expander ops (in MCU cycles)
|
||||
#define IO_EXPANDER_OP_DELAY 500
|
@ -1,230 +0,0 @@
|
||||
{
|
||||
"keyboard_name": "Betalupi Voyager",
|
||||
"manufacturer": "ZSA Technology Labs",
|
||||
"url": "zsa.io/voyager",
|
||||
"maintainer": "ZSA Technology Labs",
|
||||
"usb": {
|
||||
"vid": "0x3297",
|
||||
"pid": "0x1977",
|
||||
"device_version": "0.0.1"
|
||||
},
|
||||
"layout_aliases": {
|
||||
"LAYOUT_voyager": "LAYOUT"
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"layout": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 0.25
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 0.25
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 0.25
|
||||
},
|
||||
{
|
||||
"x": 13,
|
||||
"y": 0.25
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0.5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0.5
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 0.5
|
||||
},
|
||||
{
|
||||
"x": 10,
|
||||
"y": 0.5
|
||||
},
|
||||
{
|
||||
"x": 14,
|
||||
"y": 0.5
|
||||
},
|
||||
{
|
||||
"x": 15,
|
||||
"y": 0.5
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 12,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1.25
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 1.25
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 1.25
|
||||
},
|
||||
{
|
||||
"x": 13,
|
||||
"y": 1.25
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 1.5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1.5
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 1.5
|
||||
},
|
||||
{
|
||||
"x": 10,
|
||||
"y": 1.5
|
||||
},
|
||||
{
|
||||
"x": 14,
|
||||
"y": 1.5
|
||||
},
|
||||
{
|
||||
"x": 15,
|
||||
"y": 1.5
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 12,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2.25
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2.25
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 2.25
|
||||
},
|
||||
{
|
||||
"x": 13,
|
||||
"y": 2.25
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2.5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 2.5
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 2.5
|
||||
},
|
||||
{
|
||||
"x": 10,
|
||||
"y": 2.5
|
||||
},
|
||||
{
|
||||
"x": 14,
|
||||
"y": 2.5
|
||||
},
|
||||
{
|
||||
"x": 15,
|
||||
"y": 2.5
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 12,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 3.25
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3.25
|
||||
},
|
||||
{
|
||||
"x": 11,
|
||||
"y": 3.25
|
||||
},
|
||||
{
|
||||
"x": 13,
|
||||
"y": 3.25
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 3.5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3.5
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 3.5
|
||||
},
|
||||
{
|
||||
"x": 10,
|
||||
"y": 3.5
|
||||
},
|
||||
{
|
||||
"x": 14,
|
||||
"y": 3.5
|
||||
},
|
||||
{
|
||||
"x": 15,
|
||||
"y": 3.5
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 4.5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 4.5,
|
||||
"h": 1.75
|
||||
},
|
||||
{
|
||||
"x": -0.75,
|
||||
"y": 4.75,
|
||||
"h": 1.75
|
||||
},
|
||||
{
|
||||
"x": 0.25,
|
||||
"y": 4.75
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
BIN
keyboards/betalupi_voyager/keymaps/.DS_Store
vendored
BIN
keyboards/betalupi_voyager/keymaps/.DS_Store
vendored
Binary file not shown.
@ -1,40 +0,0 @@
|
||||
#define ENABLE_BETA_LEADER
|
||||
|
||||
// No timeout after initial leader key press
|
||||
#define LEADER_NO_TIMEOUT
|
||||
|
||||
#define COMBO_SHOULD_TRIGGER
|
||||
|
||||
// Timeout resets after each keypress
|
||||
#define LEADER_PER_KEY_TIMING
|
||||
#define LEADER_TIMEOUT 500
|
||||
|
||||
// Enable spellcheck over HID
|
||||
//#define ENABLE_HID_SPELLCHECK
|
||||
|
||||
//#define ENABLE_AUTOCORRECT
|
||||
|
||||
// RGBLight effects
|
||||
// Static color is always enabled.
|
||||
//#define RGBLIGHT_EFFECT_ALTERNATING
|
||||
//#define RGBLIGHT_EFFECT_BREATHING
|
||||
//#define RGBLIGHT_EFFECT_CHRISTMAS
|
||||
//#define RGBLIGHT_EFFECT_KNIGHT
|
||||
//#define RGBLIGHT_EFFECT_RAINBOW_MOOD
|
||||
//#define RGBLIGHT_EFFECT_RAINBOW_SWIRL
|
||||
//#define RGBLIGHT_EFFECT_RGB_TEST
|
||||
//#define RGBLIGHT_EFFECT_SNAKE
|
||||
//#define RGBLIGHT_EFFECT_STATIC_GRADIENT
|
||||
//#define RGBLIGHT_EFFECT_TWINKLE
|
||||
|
||||
// Custom effects
|
||||
// #define RGB_MATRIX_FRAMEBUFFER_EFFECTS
|
||||
// #define ENABLE_RGB_MATRIX_FFT_ANIM // Requires framebuffer
|
||||
|
||||
|
||||
#define USB_SUSPEND_WAKEUP_DELAY 200
|
||||
#define RAW_USAGE_PAGE 0xFF60
|
||||
#define RAW_USAGE_ID 0x61
|
||||
#define LAYER_STATE_32BIT
|
||||
|
||||
#define RGB_MATRIX_STARTUP_SPD 60
|
@ -1,49 +0,0 @@
|
||||
// See symbols.h for docs
|
||||
|
||||
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(CTRL)
|
||||
|
||||
#ifdef BETA_LAYER_LAYOUTS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_EN
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#ifdef BETA_LAYER_KEYS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_voyager(\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
|
||||
KC_TRNS, LGUI(KC_A), LGUI(KC_S), LGUI(KC_D), KC_TRNS, KC_TRNS,\
|
||||
KC_NO, LGUI(KC_Z), LGUI(KC_X), LGUI(KC_C), LGUI(KC_V), KC_TRNS,\
|
||||
KC_TRNS, KC_TRNS, \
|
||||
\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
|
||||
KC_TRNS, KC_TRNS \
|
||||
)
|
||||
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BETA_LAYER_LEDS
|
||||
#define BETA_LAYER_CONTEXT_DATA {\
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_RED, LC_ORN, LC_GRN, LC_GRN, LC_CYN, LC_OFF, \
|
||||
LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF \
|
||||
}
|
||||
|
||||
// This is important.
|
||||
// The magic macro MUST be here, AFTER the RGBMatrix data.
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#undef BETA_LAYER_CONTEXT_DATA
|
||||
#undef BETA_LAYER_MAGIC_MACRO
|
@ -1,37 +0,0 @@
|
||||
// See symbols.h for docs
|
||||
|
||||
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(MAIN)
|
||||
|
||||
#ifdef BETA_LAYER_LAYOUTS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_EN
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
// TODO:
|
||||
// russian
|
||||
// spellcheck
|
||||
// shared features
|
||||
|
||||
#ifdef BETA_LAYER_KEYS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_voyager(\
|
||||
KC_ESCAPE, KC_1, KC_2, KC_3, KC_4, KC_5, \
|
||||
OSL(LAYER_MACROS), KC_Q, KC_W, KC_E, KC_R, KC_T, \
|
||||
KC_DELETE, MT(MOD_LALT, KC_A), KC_S, KC_D, KC_F, KC_G, \
|
||||
MO(LAYER_CTRL), KC_Z, MT(MOD_LSFT, KC_X), KC_C, MO(LAYER_ARROWS), KC_B, \
|
||||
\
|
||||
KC_SPACE, KC_BSPC, \
|
||||
\
|
||||
\
|
||||
KC_6, KC_7, KC_8, KC_9, KC_0, LGUI(KC_SPACE), \
|
||||
KC_Y, KC_U, KC_I, KC_O, KC_NO, KC_NO, \
|
||||
KC_H, KC_J, KC_K, MO(LAYER_SYMBOLS), KC_L, QK_LEAD, \
|
||||
KC_N, KC_M, KC_P, KC_V, KC_NO, KC_NO, \
|
||||
\
|
||||
KC_RSFT, KC_ENTER \
|
||||
)
|
||||
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#undef BETA_LAYER_CONTEXT_DATA
|
||||
#undef BETA_LAYER_MAGIC_MACRO
|
@ -1,3 +0,0 @@
|
||||
# rules.mk overrides
|
||||
|
||||
TAP_DANCE_ENABLE = yes
|
@ -1,241 +0,0 @@
|
||||
/* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
|
||||
* Copyright 2020 Jack Humbert <jack.humb@gmail.com>
|
||||
* 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 "betalupi_voyager.h"
|
||||
#include "is31fl3731.h"
|
||||
#include "i2c_master.h"
|
||||
|
||||
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
|
||||
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
|
||||
static matrix_row_t raw_matrix_right[MATRIX_COLS];
|
||||
|
||||
#define ROWS_PER_HAND (MATRIX_ROWS / 2)
|
||||
#ifndef VOYAGER_I2C_TIMEOUT
|
||||
# define VOYAGER_I2C_TIMEOUT 100
|
||||
#endif
|
||||
|
||||
extern bool mcp23018_leds[2];
|
||||
extern bool is_launching;
|
||||
|
||||
bool mcp23018_initd = false;
|
||||
// extern bool IS31FL3731_initd;
|
||||
static uint8_t mcp23018_reset_loop;
|
||||
// static uint8_t is31fl3731_reset_loop;
|
||||
|
||||
uint8_t mcp23018_tx[3];
|
||||
uint8_t mcp23018_rx[1];
|
||||
|
||||
void mcp23018_init(void) {
|
||||
i2c_init();
|
||||
|
||||
mcp23018_tx[0] = 0x00; // IODIRA
|
||||
mcp23018_tx[1] = 0b00000000; // A is output
|
||||
mcp23018_tx[2] = 0b00111111; // B is inputs
|
||||
|
||||
if (MSG_OK == i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, VOYAGER_I2C_TIMEOUT)) {
|
||||
mcp23018_tx[0] = 0x0C; // GPPUA
|
||||
mcp23018_tx[1] = 0b10000000; // A is not pulled-up
|
||||
mcp23018_tx[2] = 0b11111111; // B is pulled-up
|
||||
wait_ms(5);
|
||||
|
||||
if (MSG_OK == i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, VOYAGER_I2C_TIMEOUT)) {
|
||||
wait_ms(5);
|
||||
mcp23018_initd = is_launching = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool io_expander_ready(void) {
|
||||
uint8_t tx[1] = {0x13};
|
||||
if (MSG_OK == i2c_readReg(MCP23018_DEFAULT_ADDRESS << 1, tx[0], &tx[0], 1, VOYAGER_I2C_TIMEOUT)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void matrix_init_custom(void) {
|
||||
// outputs
|
||||
setPinOutput(B10);
|
||||
setPinOutput(B11);
|
||||
setPinOutput(B12);
|
||||
setPinOutput(B13);
|
||||
setPinOutput(B14);
|
||||
setPinOutput(B15);
|
||||
|
||||
// inputs
|
||||
setPinInputLow(A0);
|
||||
setPinInputLow(A1);
|
||||
setPinInputLow(A2);
|
||||
setPinInputLow(A3);
|
||||
setPinInputLow(A6);
|
||||
setPinInputLow(A7);
|
||||
setPinInputLow(B0);
|
||||
|
||||
mcp23018_init();
|
||||
}
|
||||
|
||||
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
|
||||
bool changed = false;
|
||||
// Attempt to reset the mcp23018 if it's not initialized
|
||||
if (!mcp23018_initd) {
|
||||
if (++mcp23018_reset_loop == 0) {
|
||||
// Since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans. This will be approx bit more frequent than once per second.
|
||||
if (io_expander_ready()) {
|
||||
// If we managed to initialize the mcp23018 - we need to reinitialize the matrix / layer state. During an electric discharge the i2c peripherals might be in a weird state. Giving a delay and resetting the MCU allows to recover from this.
|
||||
wait_ms(200);
|
||||
mcu_reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scanning left and right side of the keyboard for key presses.
|
||||
// Left side is scanned by reading the gpio pins directly, right side is scanned by reading the mcp23018 registers.
|
||||
|
||||
matrix_row_t data = 0;
|
||||
for (uint8_t row = 0; row <= ROWS_PER_HAND; row++) {
|
||||
// strobe row
|
||||
switch (row) {
|
||||
case 0:
|
||||
writePinHigh(B10);
|
||||
break;
|
||||
case 1:
|
||||
writePinHigh(B11);
|
||||
break;
|
||||
case 2:
|
||||
writePinHigh(B12);
|
||||
break;
|
||||
case 3:
|
||||
writePinHigh(B13);
|
||||
break;
|
||||
case 4:
|
||||
writePinHigh(B14);
|
||||
break;
|
||||
case 5:
|
||||
writePinHigh(B15);
|
||||
break;
|
||||
case 6:
|
||||
break; // Left hand has 6 rows
|
||||
}
|
||||
|
||||
// Selecting the row on the right side of the keyboard.
|
||||
if (mcp23018_initd) {
|
||||
// select row
|
||||
mcp23018_tx[0] = 0x12; // GPIOA
|
||||
mcp23018_tx[1] = (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7); // activate row
|
||||
mcp23018_tx[2] = ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7); // activate row
|
||||
|
||||
if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, VOYAGER_I2C_TIMEOUT)) {
|
||||
mcp23018_initd = false;
|
||||
}
|
||||
}
|
||||
// Reading the left side of the keyboard.
|
||||
if (row < ROWS_PER_HAND) {
|
||||
// i2c comm incur enough wait time
|
||||
if (!mcp23018_initd) {
|
||||
// need wait to settle pin state
|
||||
matrix_io_delay();
|
||||
}
|
||||
// read col data
|
||||
data = ((readPin(A0) << 0) | (readPin(A1) << 1) | (readPin(A2) << 2) | (readPin(A3) << 3) | (readPin(A6) << 4) | (readPin(A7) << 5) | (readPin(B0) << 6));
|
||||
// unstrobe row
|
||||
switch (row) {
|
||||
case 0:
|
||||
writePinLow(B10);
|
||||
break;
|
||||
case 1:
|
||||
writePinLow(B11);
|
||||
break;
|
||||
case 2:
|
||||
writePinLow(B12);
|
||||
break;
|
||||
case 3:
|
||||
writePinLow(B13);
|
||||
break;
|
||||
case 4:
|
||||
writePinLow(B14);
|
||||
break;
|
||||
case 5:
|
||||
writePinLow(B15);
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
}
|
||||
|
||||
if (current_matrix[row] != data) {
|
||||
current_matrix[row] = data;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reading the right side of the keyboard.
|
||||
if (mcp23018_initd) {
|
||||
for (uint16_t i = 0; i < IO_EXPANDER_OP_DELAY; i++) {
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
mcp23018_tx[0] = 0x13; // GPIOB
|
||||
if (MSG_OK != i2c_readReg(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx[0], &mcp23018_rx[0], 1, VOYAGER_I2C_TIMEOUT)) {
|
||||
mcp23018_initd = false;
|
||||
}
|
||||
data = ~(mcp23018_rx[0] & 0b00111111);
|
||||
for (uint16_t i = 0; i < IO_EXPANDER_OP_DELAY; i++) {
|
||||
__asm__("nop");
|
||||
}
|
||||
} else {
|
||||
data = 0;
|
||||
}
|
||||
|
||||
if (raw_matrix_right[row] != data) {
|
||||
raw_matrix_right[row] = data;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t row = 0; row < ROWS_PER_HAND; row++) {
|
||||
current_matrix[11 - row] = 0;
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||
current_matrix[11 - row] |= ((raw_matrix_right[6 - col] & (1 << row) ? 1 : 0) << col);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
// DO NOT REMOVE
|
||||
// Needed for proper wake/sleep
|
||||
void matrix_power_up(void) {
|
||||
bool temp_launching = is_launching;
|
||||
|
||||
matrix_init_custom();
|
||||
|
||||
is_launching = temp_launching;
|
||||
if (!temp_launching) {
|
||||
STATUS_LED_1(false);
|
||||
STATUS_LED_2(false);
|
||||
STATUS_LED_3(false);
|
||||
STATUS_LED_4(false);
|
||||
}
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_transport_connected(void) {
|
||||
return mcp23018_initd;
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
# Voyager
|
||||
|
||||

|
||||
|
||||
A next-gen split, ergonomic keyboard with an active left side, USB type C, integrated wrist rest, and a thumb cluster that can move.
|
||||
|
||||
|
||||
* Keyboard Maintainer: [drashna](https://github.com/drashna), [ZSA](https://github.com/zsa/)
|
||||
* Hardware Supported: Voyager (STM32F303xC)
|
||||
* Hardware Availability: [ZSA Store](https://zsa.io/voyager/)
|
||||
|
||||
Make example for this keyboard (after setting up your build environment):
|
||||
|
||||
make voyager:default
|
||||
|
||||
Flashing example for this keyboard:
|
||||
|
||||
make voyager: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).
|
||||
|
||||
|
||||
## Voyager Customization
|
||||
|
||||
### Indicator LEDs
|
||||
|
||||
There are 6 functions for enabling and disabling the LEDs on the top of the boards. The functions are `ML_LED_1(bool)` through `ML_LED_6(bool)`, with the first LED being the left most LED on the left hand, and the sixth LED being the right most LED on the right side.
|
||||
|
||||
By default, the Indicator LEDs are used to indicate the layer state for the keyboard. If you wish to change this (and indicate caps/num/scroll lock status instead), then define `VOYAGER_USER_LEDS` in your `config.h` file.
|
||||
|
||||
|
||||
### Oryx Configuration
|
||||
|
||||
To enable the features from Oryx (ZSA's Configurator), either compile the `default` keymap, or add `#define ORYX_CONFIGURATOR` to your `config.h` file.
|
||||
|
||||
This enables the front Indicator LEDs, and the `TOGGLE_LAYER_COLOR` keycode. The `TOGGLE_LAYER_COLOR` keycode toggles the customized LED map configured on Oryx.
|
||||
|
||||
### RGB Matrix Features
|
||||
|
||||
If you're using the Smart LED (layer indication) feature from the Oryx Configurator, you want to make sure that you enable these options by adding `#define ORYX_CONFIGURATOR` to your keymap's `config.h`.
|
||||
|
||||
This changes the `RGB_TOG` keycode so that it will toggle the lights on and off, in a way that will allow the Smart LEDs to continue to work, even with the rest of the LEDs turned off.
|
||||
|
||||
Additionally, a new keycode has been added to toggle the Smart LEDs. Use `TOGGLE_LAYER_COLOR`, if you aren't already.
|
||||
|
||||
### Detecting split / Gaming mode
|
||||
|
||||
To make it extra gaming friendly, you can configure what happens when you disconnect the right half. This is especially useful when using gaming unfriendly layers or layouts (e.g. home row mods, dvorak, colemak).
|
||||
|
||||
Example for enabling a specific layer while right side is disconnected:
|
||||
|
||||
```
|
||||
void housekeeping_task_user(void) {
|
||||
if (!is_transport_connected()) {
|
||||
// set layer
|
||||
}
|
||||
}
|
||||
```
|
@ -1,29 +0,0 @@
|
||||
MCU = STM32F303
|
||||
BOOTLOADER = ignition
|
||||
DFU_SUFFIX_ARGS = -v 3297 -p 0791
|
||||
|
||||
BOOTMAGIC_ENABLE = yes
|
||||
MOUSEKEY_ENABLE = no
|
||||
EXTRAKEY_ENABLE = yes
|
||||
CONSOLE_ENABLE = no
|
||||
COMMAND_ENABLE = no
|
||||
NKRO_ENABLE = yes
|
||||
BACKLIGHT_ENABLE = no
|
||||
RGBLIGHT_ENABLE = no
|
||||
AUDIO_ENABLE = no
|
||||
CUSTOM_MATRIX = lite
|
||||
SWAP_HANDS_ENABLE = no
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = is31fl3731
|
||||
EEPROM_DRIVER = vendor
|
||||
MOUSE_SHARED_EP = no
|
||||
LTO_ENABLE = yes
|
||||
DEBUG_ENABLE = no
|
||||
MOUSE_SHARED_EP = no
|
||||
COMBO_ENABLE = yes
|
||||
|
||||
SRC += matrix.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
|
||||
SRC += \
|
||||
features/leader/leader.c
|
1
keyboards/zsa/common/features.mk
Normal file
1
keyboards/zsa/common/features.mk
Normal file
@ -0,0 +1 @@
|
||||
VPATH += keyboards/zsa/common
|
19
keyboards/zsa/voyager/config.h
Normal file
19
keyboards/zsa/voyager/config.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2023 ZSA Technology Labs, Inc <@zsa>
|
||||
// Copyright 2023 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MATRIX_COLS 7
|
||||
#define MATRIX_ROWS 12
|
||||
|
||||
#define MCP23018_TIMEOUT 10
|
||||
|
||||
#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
|
||||
#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_VCC
|
||||
|
||||
#define IS31FL3731_I2C_TIMEOUT 5
|
||||
|
||||
#define MOUSEKEY_WHEEL_INTERVAL MOUSEKEY_INTERVAL
|
||||
#define MOUSEKEY_WHEEL_MAX_SPEED MOUSEKEY_MAX_SPEED
|
||||
#define MOUSEKEY_WHEEL_TIME_TO_MAX MOUSEKEY_TIME_TO_MAX
|
184
keyboards/zsa/voyager/features/autocorrect/autocorrect.c
Normal file
184
keyboards/zsa/voyager/features/autocorrect/autocorrect.c
Normal file
@ -0,0 +1,184 @@
|
||||
#include "autocorrect.h"
|
||||
#include <string.h>
|
||||
#include "autocorrect_data.h"
|
||||
|
||||
#if AUTOCORRECTION_MIN_LENGTH < 4
|
||||
// Odd output or hard locks on the board have been observed when the min typo
|
||||
// length is 3 or lower (https://github.com/getreuer/qmk-keymap/issues/2).
|
||||
// Additionally, autocorrection entries for short typos are more likely to false
|
||||
// trigger, so it is suggested that typos be at least 5 characters.
|
||||
#error "Min typo length is less than 4. Autocorrection may behave poorly."
|
||||
#endif
|
||||
|
||||
bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
|
||||
static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {0};
|
||||
static uint8_t typo_buffer_size = 0;
|
||||
|
||||
// Ignore key release; we only process key presses.
|
||||
if (!record->event.pressed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
const uint8_t mods = get_mods() | get_oneshot_mods();
|
||||
#else
|
||||
const uint8_t mods = get_mods();
|
||||
#endif
|
||||
|
||||
// Disable autocorrection while a mod other than shift is active.
|
||||
if ((mods & ~MOD_MASK_SHIFT) != 0) {
|
||||
typo_buffer_size = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The following switch cases address various kinds of keycodes. This logic is
|
||||
// split over two switches rather than merged into one. The first switch may
|
||||
// extract a basic keycode which is then further handled by the second switch,
|
||||
// e.g. a layer-tap key with Caps Lock `LT(layer, KC_CAPS)`.
|
||||
switch (keycode) {
|
||||
#ifndef NO_ACTION_TAPPING
|
||||
case QK_MOD_TAP ... QK_MOD_TAP_MAX: // Tap-hold keys.
|
||||
#ifndef NO_ACTION_LAYER
|
||||
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
|
||||
#endif
|
||||
|
||||
if (record->tap.count == 0) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise when tapped, get the basic keycode.
|
||||
// Fallthrough intended.
|
||||
#endif
|
||||
|
||||
// Handle shifted keys, e.g. symbols like KC_EXLM = S(KC_1).
|
||||
case QK_LSFT ... QK_LSFT + 255:
|
||||
case QK_RSFT ... QK_RSFT + 255:
|
||||
keycode &= 0xff; // Get the basic keycode.
|
||||
break;
|
||||
|
||||
// NOTE: Space Cadet keys expose no info to check whether they are being
|
||||
// tapped vs. held. This makes autocorrection ambiguous, e.g. KC_LCPO
|
||||
// might be '(', which we would treat as a word break, or it might be
|
||||
// shift, which we would treat as having no effect. To behave cautiously,
|
||||
// we allow Space Cadet keycodes to fall to the logic below and clear
|
||||
// autocorrection state.
|
||||
}
|
||||
|
||||
switch (keycode) {
|
||||
// Ignore shifts, Caps Lock, one-shot mods, and layer switch keys.
|
||||
case KC_NO:
|
||||
case KC_LSFT:
|
||||
case KC_RSFT:
|
||||
case KC_CAPS:
|
||||
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
|
||||
case QK_TO ... QK_TO_MAX:
|
||||
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
|
||||
case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:
|
||||
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
|
||||
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
|
||||
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
|
||||
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
|
||||
return true; // Ignore these keys.
|
||||
}
|
||||
|
||||
if (keycode == KC_QUOT) {
|
||||
// Treat " (shifted ') as a word boundary.
|
||||
if ((mods & MOD_MASK_SHIFT) != 0) {
|
||||
keycode = KC_SPC;
|
||||
}
|
||||
} else if (!(KC_A <= keycode && keycode <= KC_Z)) {
|
||||
if (keycode == KC_BSPC) {
|
||||
// Remove last character from the buffer.
|
||||
if (typo_buffer_size > 0) {
|
||||
--typo_buffer_size;
|
||||
}
|
||||
return true;
|
||||
} else if (KC_1 <= keycode && keycode <= KC_SLSH && keycode != KC_ESC) {
|
||||
// Set a word boundary if space, period, digit, etc. is pressed.
|
||||
// Behave more conservatively for the enter key. Reset, so that enter
|
||||
// can't be used on a word ending.
|
||||
if (keycode == KC_ENT) {
|
||||
typo_buffer_size = 0;
|
||||
}
|
||||
keycode = KC_SPC;
|
||||
} else {
|
||||
// Clear state if some other non-alpha key is pressed.
|
||||
typo_buffer_size = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the buffer is full, rotate it to discard the oldest character.
|
||||
if (typo_buffer_size >= AUTOCORRECTION_MAX_LENGTH) {
|
||||
memmove(typo_buffer, typo_buffer + 1, AUTOCORRECTION_MAX_LENGTH - 1);
|
||||
typo_buffer_size = AUTOCORRECTION_MAX_LENGTH - 1;
|
||||
}
|
||||
|
||||
// Append `keycode` to the buffer.
|
||||
// NOTE: `keycode` must be a basic keycode (0-255) by this point.
|
||||
typo_buffer[typo_buffer_size++] = (uint8_t)keycode;
|
||||
// Early return if not many characters have been buffered so far.
|
||||
if (typo_buffer_size < AUTOCORRECTION_MIN_LENGTH) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check whether the buffer ends in a typo. This is done using a trie
|
||||
// stored in `autocorrection_data`.
|
||||
uint16_t state = 0;
|
||||
uint8_t code = pgm_read_byte(autocorrection_data + state);
|
||||
for (int i = typo_buffer_size - 1; i >= 0; --i) {
|
||||
const uint8_t key_i = typo_buffer[i];
|
||||
|
||||
if (code & 64) { // Check for match in node with multiple children.
|
||||
code &= 63;
|
||||
for (; code != key_i; code = pgm_read_byte(autocorrection_data + (state += 3))) {
|
||||
if (!code) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Follow link to child node.
|
||||
state = (uint16_t)(
|
||||
(uint_fast16_t) pgm_read_byte(
|
||||
autocorrection_data + state + 1
|
||||
) |
|
||||
(uint_fast16_t) pgm_read_byte(
|
||||
autocorrection_data + state + 2
|
||||
) << 8
|
||||
);
|
||||
|
||||
// Otherwise check for match in node with a single child.
|
||||
} else if (code != key_i) {
|
||||
return true;
|
||||
} else if (!(code = pgm_read_byte(autocorrection_data + (++state)))) {
|
||||
++state;
|
||||
}
|
||||
|
||||
// Stop if `state` becomes an invalid index. This should not normally
|
||||
// happen, it is a safeguard in case of a bug, data corruption, etc.
|
||||
if (state >= sizeof(autocorrection_data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read first byte of the next node.
|
||||
code = pgm_read_byte(autocorrection_data + state);
|
||||
|
||||
if (code & 128) { // A typo was found! Apply autocorrection.
|
||||
const int backspaces = code & 63;
|
||||
for (int i = 0; i < backspaces; ++i) {
|
||||
tap_code(KC_BSPC);
|
||||
}
|
||||
send_string_P((char const*)(autocorrection_data + state + 1));
|
||||
|
||||
if (keycode == KC_SPC) {
|
||||
typo_buffer[0] = KC_SPC;
|
||||
typo_buffer_size = 1;
|
||||
return true;
|
||||
} else {
|
||||
typo_buffer_size = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
111
keyboards/zsa/voyager/features/autocorrect/autocorrect.h
Normal file
111
keyboards/zsa/voyager/features/autocorrect/autocorrect.h
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright 2021-2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @file autocorrection.h
|
||||
* @brief Autocorrection on your keyboard.
|
||||
*
|
||||
* Overview
|
||||
* --------
|
||||
*
|
||||
* Some words are more prone to typos than others. This userspace QMK library
|
||||
* implements rudimentary autocorrection, automatically detecting and fixing
|
||||
* some misspellings.
|
||||
*
|
||||
* Features:
|
||||
*
|
||||
* * It runs on your keyboard, so it is always active no matter what software.
|
||||
* * Low resource cost.
|
||||
* * It is case insensitive.
|
||||
* * It works within words, useful for programming to catch typos within longer
|
||||
* identifiers.
|
||||
*
|
||||
* Limitations:
|
||||
*
|
||||
* * It is limited to alphabet characters a–z, apostrophes ', and word breaks.
|
||||
* I'm sorry this probably isn't useful for languages besides English.
|
||||
* * It does not follow mouse or hotkey driven cursor movement.
|
||||
*
|
||||
* Changing the autocorrection dictionary
|
||||
* --------------------------------------
|
||||
*
|
||||
* The file autocorrection_data.h encodes the typos to correct. While you could
|
||||
* simply use the version of this file provided above for a practical
|
||||
* configuration, you can make your own to personalize the autocorrection to
|
||||
* your most troublesome typos:
|
||||
*
|
||||
* Step 1: First, create an autocorrection dictionary autocorrection_dict.txt,
|
||||
* in a form like
|
||||
*
|
||||
* :thier -> their
|
||||
* dosen't -> doesn't
|
||||
* fitler -> filter
|
||||
* ouput -> output
|
||||
* widht -> width
|
||||
*
|
||||
* For a practical 71-entry example, see autocorrection_dict.txt. And for a yet
|
||||
* larger 400-entry example, see autocorrection_dict_extra.txt.
|
||||
*
|
||||
* The syntax is `typo -> correction`. Typos and corrections are case
|
||||
* insensitive, and any whitespace before or after the typo and correction is
|
||||
* ignored. The typo must be only the characters a-z, ', or the special
|
||||
* character : representing a word break. The correction may have just about any
|
||||
* printable ASCII characters.
|
||||
*
|
||||
* Step 2: Use the make_autocorrection_data.py Python script to process the
|
||||
* dictionary. Put autocorrection_dict.txt in the same directory as the Python
|
||||
* script and run
|
||||
*
|
||||
* $ python3 make_autocorrection_data.py
|
||||
* Processed 71 autocorrection entries to table with 1120 bytes.
|
||||
*
|
||||
* The script arranges the entries in autocorrection_dict.txt into a trie and
|
||||
* generates autocorrection_data.h with the serialized trie embedded as an
|
||||
* array. The .h file will be written in the same directory.
|
||||
*
|
||||
* Step 3: Finally, recompile and flash your keymap.
|
||||
*
|
||||
* For full documentation, see
|
||||
* <https://getreuer.info/posts/keyboards/autocorrection>
|
||||
*
|
||||
* @author Pascal Getreuer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Handler function for autocorrection.
|
||||
*
|
||||
* Call this function in keymap.c from `process_record_user()` like
|
||||
*
|
||||
* #include "features/autocorrection.h"
|
||||
*
|
||||
* bool process_record_user(uint16_t keycode, keyrecord_t* record) {
|
||||
* if (!process_autocorrection(keycode, record)) { return false; }
|
||||
* // Your macros...
|
||||
*
|
||||
* return true;
|
||||
* }
|
||||
*/
|
||||
bool process_autocorrection(uint16_t keycode, keyrecord_t* record);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
238
keyboards/zsa/voyager/features/autocorrect/autocorrect_data.h
Normal file
238
keyboards/zsa/voyager/features/autocorrect/autocorrect_data.h
Normal file
@ -0,0 +1,238 @@
|
||||
// Generated code.
|
||||
|
||||
// Autocorrection dictionary (132 entries):
|
||||
// :agian -> again
|
||||
// :agred -> agreed
|
||||
// :ajust -> adjust
|
||||
// :alot: -> a lot
|
||||
// :andteh -> and the
|
||||
// :andthe -> and the
|
||||
// :anual -> annual
|
||||
// :asign -> assign
|
||||
// :asthe -> as the
|
||||
// :atthe -> at the
|
||||
// :casue -> cause
|
||||
// :eveyr -> every
|
||||
// :foudn -> found
|
||||
// :gaurd -> guard
|
||||
// :goign -> going
|
||||
// :gonig -> going
|
||||
// :graet -> great
|
||||
// :haev -> have
|
||||
// :htere -> there
|
||||
// :htikn -> think
|
||||
// :htink -> think
|
||||
// :hwihc -> which
|
||||
// :hwile -> while
|
||||
// :idaes -> ideas
|
||||
// :jstu: -> just
|
||||
// :jsut: -> just
|
||||
// :knwo -> know
|
||||
// :konw -> know
|
||||
// :kwno -> know
|
||||
// :moeny -> money
|
||||
// :olther -> other
|
||||
// :otehr -> other
|
||||
// :owudl -> would
|
||||
// :sicne -> since
|
||||
// :the:the: -> the
|
||||
// :theri -> their
|
||||
// :thier -> their
|
||||
// :thsoe -> those
|
||||
// :tothe -> to the
|
||||
// :yaers -> years
|
||||
// :yeasr -> years
|
||||
// abbout -> about
|
||||
// abotu -> about
|
||||
// abouta -> about a
|
||||
// aboutit -> about it
|
||||
// aboutthe -> about the
|
||||
// almsot -> almost
|
||||
// alomst -> almost
|
||||
// alwasy -> always
|
||||
// alwyas -> always
|
||||
// anohter -> another
|
||||
// aroud -> around
|
||||
// arround -> around
|
||||
// arund -> around
|
||||
// baceause -> because
|
||||
// baout -> about
|
||||
// beacuse -> because
|
||||
// becasue -> because
|
||||
// beccause -> because
|
||||
// becouse -> because
|
||||
// becuase -> because
|
||||
// bedore -> before
|
||||
// beeing -> being
|
||||
// befoer -> before
|
||||
// beteen -> between
|
||||
// beween -> between
|
||||
// bewteen -> between
|
||||
// chekc -> check
|
||||
// childen -> children
|
||||
// chnage -> change
|
||||
// claer -> clear
|
||||
// comapny -> company
|
||||
// contian -> contain
|
||||
// coudl -> could
|
||||
// didnot -> did not
|
||||
// elasped -> elapsed
|
||||
// firend -> friend
|
||||
// firts -> first
|
||||
// fitler -> filter
|
||||
// follwo -> follow
|
||||
// freind -> friend
|
||||
// frequecy -> frequency
|
||||
// fromthe -> from the
|
||||
// heigth -> height
|
||||
// iamge -> image
|
||||
// inital -> initial
|
||||
// intput -> input
|
||||
// laguage -> language
|
||||
// lenght -> length
|
||||
// levle -> level
|
||||
// libary -> library
|
||||
// littel -> little
|
||||
// mysefl -> myself
|
||||
// ouptut -> output
|
||||
// ouput -> output
|
||||
// peaple -> people
|
||||
// peolpe -> people
|
||||
// peopel -> people
|
||||
// poeople -> people
|
||||
// poeple -> people
|
||||
// probaly -> probably
|
||||
// probelm -> problem
|
||||
// raelly -> really
|
||||
// realy -> really
|
||||
// recrod -> record
|
||||
// relaly -> really
|
||||
// reponse -> response
|
||||
// reprot -> report
|
||||
// shoudl -> should
|
||||
// singel -> single
|
||||
// stregth -> strength
|
||||
// strengh -> strength
|
||||
// theese -> these
|
||||
// therfore -> therefore
|
||||
// thign -> thing
|
||||
// thigsn -> things
|
||||
// thikn -> think
|
||||
// thiunk -> think
|
||||
// thnigs -> things
|
||||
// throught -> thought
|
||||
// tihkn -> think
|
||||
// tkaes -> takes
|
||||
// todya -> today
|
||||
// toghether -> together
|
||||
// unkown -> unknown
|
||||
// unqiue -> unique
|
||||
// whcih -> which
|
||||
// whihc -> which
|
||||
// whlch -> which
|
||||
// widht -> width
|
||||
// wihch -> which
|
||||
// woudl -> would
|
||||
|
||||
#define AUTOCORRECTION_MIN_LENGTH 5 // "abotu"
|
||||
#define AUTOCORRECTION_MAX_LENGTH 9 // "toghether"
|
||||
|
||||
static const uint8_t autocorrection_data[1881] PROGMEM = {108, 61, 0, 4, 117, 0,
|
||||
6, 141, 0, 7, 181, 0, 8, 52, 1, 10, 237, 2, 11, 8, 3, 12, 105, 3, 14, 115, 3,
|
||||
15, 143, 3, 16, 12, 4, 17, 24, 4, 18, 234, 4, 21, 16, 5, 22, 152, 5, 23, 233,
|
||||
5, 24, 190, 6, 25, 199, 6, 26, 208, 6, 28, 218, 6, 0, 72, 71, 0, 23, 81, 0,
|
||||
24, 107, 0, 0, 11, 23, 44, 8, 11, 23, 44, 0, 132, 0, 82, 88, 0, 24, 98, 0, 0,
|
||||
15, 4, 44, 0, 131, 32, 108, 111, 116, 0, 22, 13, 44, 0, 131, 117, 115, 116, 0,
|
||||
23, 22, 13, 44, 0, 131, 117, 115, 116, 0, 87, 124, 0, 28, 133, 0, 0, 24, 18,
|
||||
5, 4, 0, 128, 32, 97, 0, 7, 18, 23, 0, 129, 97, 121, 0, 75, 148, 0, 14, 173,
|
||||
0, 0, 12, 0, 75, 157, 0, 26, 163, 0, 0, 26, 0, 129, 99, 104, 0, 11, 44, 0,
|
||||
132, 119, 104, 105, 99, 104, 0, 8, 11, 6, 0, 129, 99, 107, 0, 72, 197, 0, 17,
|
||||
223, 0, 18, 23, 1, 21, 33, 1, 24, 44, 1, 0, 83, 204, 0, 21, 215, 0, 0, 22, 4,
|
||||
15, 8, 0, 131, 112, 115, 101, 100, 0, 10, 4, 44, 0, 128, 101, 100, 0, 72, 233,
|
||||
0, 12, 244, 0, 24, 254, 0, 0, 21, 12, 9, 0, 132, 114, 105, 101, 110, 100, 0,
|
||||
8, 21, 9, 0, 131, 105, 101, 110, 100, 0, 82, 5, 1, 21, 15, 1, 0, 21, 21, 4, 0,
|
||||
132, 111, 117, 110, 100, 0, 4, 0, 130, 111, 117, 110, 100, 0, 21, 6, 8, 21, 0,
|
||||
130, 111, 114, 100, 0, 24, 4, 10, 44, 0, 131, 117, 97, 114, 100, 0, 18, 21, 4,
|
||||
0, 128, 110, 100, 0, 74, 80, 1, 11, 124, 1, 15, 205, 1, 17, 17, 2, 18, 27, 2,
|
||||
19, 37, 2, 21, 47, 2, 22, 93, 2, 24, 198, 2, 0, 68, 87, 1, 16, 115, 1, 0, 81,
|
||||
94, 1, 24, 103, 1, 0, 11, 6, 0, 131, 97, 110, 103, 101, 0, 10, 4, 15, 0, 132,
|
||||
110, 103, 117, 97, 103, 101, 0, 4, 12, 0, 131, 109, 97, 103, 101, 0, 23, 0,
|
||||
71, 142, 1, 16, 152, 1, 18, 162, 1, 22, 171, 1, 23, 180, 1, 0, 17, 4, 44, 0,
|
||||
130, 32, 116, 104, 101, 0, 18, 21, 9, 0, 130, 32, 116, 104, 101, 0, 23, 44, 0,
|
||||
130, 32, 116, 104, 101, 0, 4, 44, 0, 130, 32, 116, 104, 101, 0, 68, 187, 1,
|
||||
24, 195, 1, 0, 44, 0, 130, 32, 116, 104, 101, 0, 18, 5, 4, 0, 130, 32, 116,
|
||||
104, 101, 0, 76, 215, 1, 19, 226, 1, 25, 10, 2, 0, 26, 11, 44, 0, 132, 119,
|
||||
104, 105, 108, 101, 0, 68, 236, 1, 8, 245, 1, 18, 255, 1, 0, 8, 19, 0, 131,
|
||||
111, 112, 108, 101, 0, 18, 19, 0, 132, 101, 111, 112, 108, 101, 0, 8, 18, 19,
|
||||
0, 133, 101, 111, 112, 108, 101, 0, 8, 15, 0, 129, 101, 108, 0, 6, 12, 22, 44,
|
||||
0, 130, 110, 99, 101, 0, 22, 11, 23, 44, 0, 130, 111, 115, 101, 0, 15, 18, 8,
|
||||
19, 0, 130, 112, 108, 101, 0, 72, 54, 2, 18, 65, 2, 0, 23, 11, 44, 0, 132,
|
||||
116, 104, 101, 114, 101, 0, 71, 72, 2, 9, 81, 2, 0, 8, 5, 0, 131, 102, 111,
|
||||
114, 101, 0, 21, 8, 11, 23, 0, 131, 101, 102, 111, 114, 101, 0, 68, 106, 2, 8,
|
||||
117, 2, 17, 125, 2, 24, 138, 2, 0, 24, 6, 8, 5, 0, 131, 97, 117, 115, 101, 0,
|
||||
8, 11, 23, 0, 130, 115, 101, 0, 18, 19, 8, 21, 0, 132, 115, 112, 111, 110,
|
||||
115, 101, 0, 68, 148, 2, 6, 177, 2, 18, 188, 2, 0, 70, 155, 2, 8, 165, 2, 0,
|
||||
6, 8, 5, 0, 132, 97, 117, 115, 101, 0, 6, 4, 5, 0, 134, 101, 99, 97, 117, 115,
|
||||
101, 0, 4, 8, 5, 0, 132, 99, 97, 117, 115, 101, 0, 6, 8, 5, 0, 131, 97, 117,
|
||||
115, 101, 0, 76, 205, 2, 22, 215, 2, 0, 20, 17, 24, 0, 131, 105, 113, 117,
|
||||
101, 0, 4, 6, 0, 108, 225, 2, 8, 230, 2, 0, 130, 117, 115, 101, 0, 5, 0, 130,
|
||||
117, 115, 101, 0, 76, 244, 2, 17, 254, 2, 0, 17, 18, 10, 44, 0, 130, 105, 110,
|
||||
103, 0, 12, 8, 8, 5, 0, 131, 105, 110, 103, 0, 70, 24, 3, 8, 48, 3, 10, 60, 3,
|
||||
12, 70, 3, 23, 79, 3, 0, 75, 31, 3, 15, 40, 3, 0, 12, 26, 0, 131, 104, 105,
|
||||
99, 104, 0, 11, 26, 0, 130, 105, 99, 104, 0, 23, 7, 17, 4, 44, 0, 130, 32,
|
||||
116, 104, 101, 0, 17, 8, 21, 23, 22, 0, 128, 116, 104, 0, 6, 11, 26, 0, 130,
|
||||
105, 99, 104, 0, 10, 0, 72, 88, 3, 12, 98, 3, 0, 21, 23, 22, 0, 130, 110, 103,
|
||||
116, 104, 0, 8, 11, 0, 129, 104, 116, 0, 21, 8, 11, 23, 44, 0, 129, 105, 114,
|
||||
0, 17, 0, 76, 124, 3, 24, 135, 3, 0, 23, 11, 44, 0, 132, 116, 104, 105, 110,
|
||||
107, 0, 12, 11, 23, 0, 130, 110, 107, 0, 68, 156, 3, 7, 182, 3, 8, 225, 3, 9,
|
||||
3, 4, 0, 87, 163, 3, 24, 172, 3, 0, 12, 17, 12, 0, 129, 105, 97, 108, 0, 17,
|
||||
4, 44, 0, 130, 110, 117, 97, 108, 0, 24, 0, 82, 191, 3, 26, 215, 3, 0, 70,
|
||||
201, 3, 11, 205, 3, 26, 211, 3, 0, 129, 108, 100, 0, 22, 0, 129, 108, 100, 0,
|
||||
129, 108, 100, 0, 18, 44, 0, 132, 119, 111, 117, 108, 100, 0, 74, 235, 3, 19,
|
||||
243, 3, 23, 251, 3, 0, 17, 12, 22, 0, 129, 108, 101, 0, 18, 8, 19, 0, 129,
|
||||
108, 101, 0, 23, 12, 15, 0, 129, 108, 101, 0, 8, 22, 28, 16, 0, 129, 108, 102,
|
||||
0, 15, 8, 5, 18, 21, 19, 0, 130, 108, 101, 109, 0, 68, 46, 4, 7, 72, 4, 8, 81,
|
||||
4, 10, 140, 4, 14, 174, 4, 22, 213, 4, 26, 223, 4, 0, 12, 0, 74, 55, 4, 23,
|
||||
63, 4, 0, 4, 44, 0, 130, 97, 105, 110, 0, 17, 18, 6, 0, 130, 97, 105, 110, 0,
|
||||
24, 18, 9, 44, 0, 129, 110, 100, 0, 71, 88, 4, 8, 98, 4, 0, 15, 12, 11, 6, 0,
|
||||
129, 114, 101, 110, 0, 87, 105, 4, 26, 130, 4, 0, 72, 112, 4, 26, 120, 4, 0,
|
||||
5, 0, 130, 119, 101, 101, 110, 0, 8, 5, 0, 132, 116, 119, 101, 101, 110, 0, 8,
|
||||
5, 0, 131, 116, 119, 101, 101, 110, 0, 12, 0, 75, 152, 4, 18, 158, 4, 22, 165,
|
||||
4, 0, 23, 0, 129, 110, 103, 0, 10, 44, 0, 129, 110, 103, 0, 4, 44, 0, 130,
|
||||
115, 105, 103, 110, 0, 75, 181, 4, 12, 190, 4, 0, 12, 23, 0, 131, 104, 105,
|
||||
110, 107, 0, 75, 197, 4, 23, 203, 4, 0, 23, 0, 129, 110, 107, 0, 11, 44, 0,
|
||||
132, 116, 104, 105, 110, 107, 0, 10, 12, 11, 23, 0, 130, 110, 103, 115, 0, 18,
|
||||
14, 17, 24, 0, 130, 110, 111, 119, 110, 0, 81, 241, 4, 26, 250, 4, 0, 26, 14,
|
||||
44, 0, 130, 110, 111, 119, 0, 79, 1, 5, 17, 9, 5, 0, 15, 18, 9, 0, 129, 111,
|
||||
119, 0, 14, 44, 0, 129, 111, 119, 0, 72, 29, 5, 11, 124, 5, 22, 134, 5, 28,
|
||||
143, 5, 0, 68, 48, 5, 11, 56, 5, 12, 86, 5, 15, 95, 5, 18, 105, 5, 23, 113, 5,
|
||||
0, 15, 6, 0, 130, 101, 97, 114, 0, 23, 0, 72, 65, 5, 15, 77, 5, 0, 11, 10, 18,
|
||||
23, 0, 133, 101, 116, 104, 101, 114, 0, 18, 44, 0, 132, 116, 104, 101, 114, 0,
|
||||
11, 23, 44, 0, 130, 101, 105, 114, 0, 23, 12, 9, 0, 131, 108, 116, 101, 114,
|
||||
0, 9, 8, 5, 0, 129, 114, 101, 0, 11, 18, 17, 4, 0, 131, 116, 104, 101, 114, 0,
|
||||
8, 23, 18, 44, 0, 130, 104, 101, 114, 0, 4, 8, 28, 44, 0, 129, 114, 115, 0, 8,
|
||||
25, 8, 44, 0, 129, 114, 121, 0, 68, 168, 5, 8, 178, 5, 10, 203, 5, 21, 214, 5,
|
||||
23, 225, 5, 0, 28, 26, 15, 4, 0, 130, 97, 121, 115, 0, 4, 0, 71, 187, 5, 14,
|
||||
195, 5, 0, 12, 44, 0, 130, 101, 97, 115, 0, 23, 0, 131, 97, 107, 101, 115, 0,
|
||||
12, 17, 11, 23, 0, 131, 105, 110, 103, 115, 0, 8, 4, 28, 44, 0, 131, 101, 97,
|
||||
114, 115, 0, 21, 12, 9, 0, 129, 115, 116, 0, 72, 252, 5, 11, 6, 6, 12, 46, 6,
|
||||
18, 57, 6, 22, 95, 6, 24, 123, 6, 0, 4, 21, 10, 44, 0, 130, 101, 97, 116, 0,
|
||||
71, 13, 6, 10, 20, 6, 0, 12, 26, 0, 129, 116, 104, 0, 81, 27, 6, 24, 34, 6, 0,
|
||||
8, 15, 0, 129, 116, 104, 0, 18, 21, 11, 23, 0, 133, 111, 117, 103, 104, 116,
|
||||
0, 23, 24, 18, 5, 4, 0, 129, 32, 105, 116, 0, 81, 67, 6, 21, 77, 6, 22, 86, 6,
|
||||
0, 7, 12, 7, 0, 130, 32, 110, 111, 116, 0, 19, 8, 21, 0, 130, 111, 114, 116,
|
||||
0, 16, 15, 4, 0, 130, 111, 115, 116, 0, 80, 102, 6, 24, 112, 6, 0, 18, 15, 4,
|
||||
0, 131, 109, 111, 115, 116, 0, 13, 4, 44, 0, 131, 100, 106, 117, 115, 116, 0,
|
||||
82, 133, 6, 19, 157, 6, 23, 180, 6, 0, 68, 140, 6, 5, 149, 6, 0, 5, 0, 132,
|
||||
97, 98, 111, 117, 116, 0, 5, 4, 0, 131, 111, 117, 116, 0, 87, 164, 6, 24, 172,
|
||||
6, 0, 17, 12, 0, 131, 112, 117, 116, 0, 18, 0, 130, 116, 112, 117, 116, 0, 19,
|
||||
24, 18, 0, 131, 116, 112, 117, 116, 0, 23, 18, 5, 4, 0, 129, 117, 116, 0, 8,
|
||||
4, 11, 44, 0, 129, 118, 101, 0, 17, 18, 14, 44, 0, 130, 110, 111, 119, 0, 70,
|
||||
234, 6, 15, 246, 6, 17, 42, 7, 21, 69, 7, 22, 80, 7, 0, 8, 24, 20, 8, 21, 9,
|
||||
0, 129, 110, 99, 121, 0, 68, 253, 6, 15, 31, 7, 0, 69, 7, 7, 8, 16, 7, 15, 22,
|
||||
7, 0, 18, 21, 19, 0, 129, 98, 108, 121, 0, 21, 0, 128, 108, 121, 0, 8, 21, 0,
|
||||
131, 97, 108, 108, 121, 0, 8, 4, 21, 0, 132, 101, 97, 108, 108, 121, 0, 72,
|
||||
49, 7, 19, 58, 7, 0, 18, 16, 44, 0, 130, 110, 101, 121, 0, 4, 16, 18, 6, 0,
|
||||
131, 112, 97, 110, 121, 0, 4, 5, 12, 15, 0, 130, 114, 97, 114, 121, 0, 4, 26,
|
||||
15, 4, 0, 129, 121, 115, 0};
|
||||
|
148
keyboards/zsa/voyager/features/autocorrect/dict.txt
Normal file
148
keyboards/zsa/voyager/features/autocorrect/dict.txt
Normal file
@ -0,0 +1,148 @@
|
||||
# Dictionary syntax:
|
||||
# Each line of this file defines one typo correction entry with the syntax
|
||||
# "typo -> correction". Typos and corrections are case insensitive, and any
|
||||
# whitespace before or after the typo and correction is ignored. The typo must be
|
||||
# only the letters a-z, or the special character : representing a word break.
|
||||
|
||||
:htere -> there
|
||||
abbout -> about
|
||||
abotu -> about
|
||||
baout -> about
|
||||
:theri -> their
|
||||
:thier -> their
|
||||
:owudl -> would
|
||||
woudl -> would
|
||||
peaple -> people
|
||||
peolpe -> people
|
||||
peopel -> people
|
||||
poeple -> people
|
||||
poeople -> people
|
||||
:hwihc -> which
|
||||
whcih -> which
|
||||
whihc -> which
|
||||
whlch -> which
|
||||
wihch -> which
|
||||
coudl -> could
|
||||
:htikn -> think
|
||||
:htink -> think
|
||||
thikn -> think
|
||||
thiunk -> think
|
||||
tihkn -> think
|
||||
:olther -> other
|
||||
:otehr -> other
|
||||
baceause -> because
|
||||
beacuse -> because
|
||||
becasue -> because
|
||||
beccause -> because
|
||||
becouse -> because
|
||||
becuase -> because
|
||||
|
||||
theese -> these
|
||||
:goign -> going
|
||||
:gonig -> going
|
||||
:yaers -> years
|
||||
:yeasr -> years
|
||||
:thsoe -> those
|
||||
shoudl -> should
|
||||
raelly -> really
|
||||
realy -> really
|
||||
relaly -> really
|
||||
bedore -> before
|
||||
befoer -> before
|
||||
littel -> little
|
||||
beeing -> being
|
||||
:hwile -> while
|
||||
|
||||
aroud -> around
|
||||
arround -> around
|
||||
arund -> around
|
||||
thign -> thing
|
||||
thigsn -> things
|
||||
thnigs -> things
|
||||
anohter -> another
|
||||
beteen -> between
|
||||
beween -> between
|
||||
bewteen -> between
|
||||
:eveyr -> every
|
||||
:graet -> great
|
||||
:agian -> again
|
||||
:sicne -> since
|
||||
alwasy -> always
|
||||
alwyas -> always
|
||||
throught -> thought
|
||||
|
||||
|
||||
almsot -> almost
|
||||
alomst -> almost
|
||||
chnage -> change
|
||||
chekc -> check
|
||||
childen -> children
|
||||
claer -> clear
|
||||
comapny -> company
|
||||
contian -> contain
|
||||
elasped -> elapsed
|
||||
fitler -> filter
|
||||
firts -> first
|
||||
follwo -> follow
|
||||
:foudn -> found
|
||||
frequecy -> frequency
|
||||
firend -> friend
|
||||
freind -> friend
|
||||
heigth -> height
|
||||
iamge -> image
|
||||
inital -> initial
|
||||
intput -> input
|
||||
laguage -> language
|
||||
lenght -> length
|
||||
levle -> level
|
||||
libary -> library
|
||||
:moeny -> money
|
||||
mysefl -> myself
|
||||
ouptut -> output
|
||||
ouput -> output
|
||||
probaly -> probably
|
||||
probelm -> problem
|
||||
recrod -> record
|
||||
reponse -> response
|
||||
reprot -> report
|
||||
singel -> single
|
||||
stregth -> strength
|
||||
strengh -> strength
|
||||
tkaes -> takes
|
||||
therfore -> therefore
|
||||
todya -> today
|
||||
toghether -> together
|
||||
unkown -> unknown
|
||||
unqiue -> unique
|
||||
widht -> width
|
||||
|
||||
|
||||
## Catch skipped spaces between common words.
|
||||
:alot: -> a lot
|
||||
:andteh -> and the
|
||||
:andthe -> and the
|
||||
:asthe -> as the
|
||||
:atthe -> at the
|
||||
abouta -> about a
|
||||
aboutit -> about it
|
||||
aboutthe -> about the
|
||||
:tothe -> to the
|
||||
didnot -> did not
|
||||
fromthe -> from the
|
||||
:the:the: -> the
|
||||
|
||||
|
||||
## Various additional entries.
|
||||
:agred -> agreed
|
||||
:ajust -> adjust
|
||||
:anual -> annual
|
||||
:asign -> assign
|
||||
:casue -> cause
|
||||
:gaurd -> guard
|
||||
:haev -> have
|
||||
:idaes -> ideas
|
||||
:jsut: -> just
|
||||
:jstu: -> just
|
||||
:knwo -> know
|
||||
:konw -> know
|
||||
:kwno -> know
|
352
keyboards/zsa/voyager/features/autocorrect/gen_autocorrect.py
Normal file
352
keyboards/zsa/voyager/features/autocorrect/gen_autocorrect.py
Normal file
@ -0,0 +1,352 @@
|
||||
"""Python program to make autocorrection_data.h.
|
||||
|
||||
This program reads "autocorrection_dict.txt" from the current directory and
|
||||
generates a C source file "autocorrection_data.h" with a serialized trie
|
||||
embedded as an array. Run this program without arguments like
|
||||
|
||||
$ python3 make_autocorrection_data.py
|
||||
|
||||
Or specify a dict file as the first argument like
|
||||
|
||||
$ python3 make_autocorrection_data.py mykeymap/dict.txt
|
||||
|
||||
The output is written to "autocorrection_data.h" in the same directory as the
|
||||
dictionary. Or optionally specify the output .h file as well like
|
||||
|
||||
$ python3 make_autocorrection_data.py dict.txt somewhere/out.h
|
||||
|
||||
Each line of the dict file defines one typo and its correction with the syntax
|
||||
"typo -> correction". Blank lines or lines starting with '#' are ignored.
|
||||
Example:
|
||||
|
||||
:thier -> their
|
||||
dosen't -> doesn't
|
||||
fitler -> filter
|
||||
lenght -> length
|
||||
ouput -> output
|
||||
widht -> width
|
||||
|
||||
See autocorrection_dict_extra.txt for a larger example.
|
||||
|
||||
For full documentation, see
|
||||
https://getreuer.info/posts/keyboards/autocorrection
|
||||
"""
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
import textwrap
|
||||
from typing import Any, Dict, Iterator, List, Tuple
|
||||
|
||||
try:
|
||||
from english_words import english_words_lower_alpha_set as CORRECT_WORDS
|
||||
except ImportError:
|
||||
print(
|
||||
"Autocorrection will falsely trigger when a typo is a substring of a "
|
||||
"correctly spelled word. To check for this, install the english_words "
|
||||
"package and rerun this script:\n\n pip install english_words\n"
|
||||
)
|
||||
# Use a minimal word list as a fallback.
|
||||
CORRECT_WORDS = (
|
||||
"apparent",
|
||||
"association",
|
||||
"available",
|
||||
"classification",
|
||||
"effect",
|
||||
"entertainment",
|
||||
"fantastic",
|
||||
"information",
|
||||
"integrate",
|
||||
"international",
|
||||
"language",
|
||||
"loosest",
|
||||
"manual",
|
||||
"nothing",
|
||||
"provides",
|
||||
"reference",
|
||||
"statehood",
|
||||
"technology",
|
||||
"virtually",
|
||||
"wealthier",
|
||||
"wonderful",
|
||||
)
|
||||
|
||||
KC_A = 4
|
||||
KC_SPC = 0x2C
|
||||
KC_QUOT = 0x34
|
||||
|
||||
TYPO_CHARS = dict(
|
||||
[
|
||||
("'", KC_QUOT),
|
||||
(":", KC_SPC), # "Word break" character.
|
||||
]
|
||||
+
|
||||
# Characters a-z.
|
||||
[(chr(c), c + KC_A - ord("a")) for c in range(ord("a"), ord("z") + 1)]
|
||||
)
|
||||
|
||||
|
||||
def parse_file(file_name: str) -> List[Tuple[str, str]]:
|
||||
"""Parses autocorrections dictionary file.
|
||||
|
||||
Each line of the file defines one typo and its correction with the syntax
|
||||
"typo -> correction". Blank lines or lines starting with '#' are ignored. The
|
||||
function validates that typos only have characters in TYPO_CHARS, that
|
||||
typos are not substrings of other typos, and checking that typos don't trigger
|
||||
on CORRECT_WORDS.
|
||||
|
||||
Args:
|
||||
file_name: String, path of the autocorrections dictionary.
|
||||
Returns:
|
||||
List of (typo, correction) tuples.
|
||||
"""
|
||||
|
||||
autocorrections = []
|
||||
typos = set()
|
||||
for line_number, typo, correction in parse_file_lines(file_name):
|
||||
if typo in typos:
|
||||
print(f'Warning:{line_number}: Ignoring duplicate typo: "{typo}"')
|
||||
continue
|
||||
|
||||
# Check that `typo` is valid.
|
||||
if not (all([c in TYPO_CHARS for c in typo])):
|
||||
print(
|
||||
f'Error:{line_number}: Typo "{typo}" has '
|
||||
"characters other than " + "".join(TYPO_CHARS.keys())
|
||||
)
|
||||
sys.exit(1)
|
||||
for other_typo in typos:
|
||||
if typo in other_typo or other_typo in typo:
|
||||
print(
|
||||
f"Error:{line_number}: Typos may not be substrings of one "
|
||||
f"another, otherwise the longer typo would never trigger: "
|
||||
f'"{typo}" vs. "{other_typo}".'
|
||||
)
|
||||
sys.exit(1)
|
||||
if len(typo) < 5:
|
||||
print(
|
||||
f"Warning:{line_number}: It is suggested that typos are at "
|
||||
f'least 5 characters long to avoid false triggers: "{typo}"'
|
||||
)
|
||||
|
||||
check_typo_against_dictionary(line_number, typo)
|
||||
|
||||
autocorrections.append((typo, correction))
|
||||
typos.add(typo)
|
||||
|
||||
return autocorrections
|
||||
|
||||
|
||||
def make_trie(autocorrections: List[Tuple[str, str]]) -> Dict[str, Any]:
|
||||
"""Makes a trie from the the typos, writing in reverse.
|
||||
|
||||
Args:
|
||||
autocorrections: List of (typo, correction) tuples.
|
||||
Returns:
|
||||
Dict of dict, representing the trie.
|
||||
"""
|
||||
trie = {}
|
||||
for typo, correction in autocorrections:
|
||||
node = trie
|
||||
for letter in typo[::-1]:
|
||||
node = node.setdefault(letter, {})
|
||||
node["LEAF"] = (typo, correction)
|
||||
|
||||
return trie
|
||||
|
||||
|
||||
def parse_file_lines(file_name: str) -> Iterator[Tuple[int, str, str]]:
|
||||
"""Parses lines read from `file_name` into typo-correction pairs."""
|
||||
|
||||
line_number = 0
|
||||
for line in open(file_name, "rt"):
|
||||
line_number += 1
|
||||
line = line.strip()
|
||||
if line and line[0] != "#":
|
||||
# Parse syntax "typo -> correction", using strip to ignore indenting.
|
||||
tokens = [token.strip() for token in line.split("->", 1)]
|
||||
if len(tokens) != 2 or not tokens[0]:
|
||||
print(f'Error:{line_number}: Invalid syntax: "{line}"')
|
||||
sys.exit(1)
|
||||
|
||||
typo, correction = tokens
|
||||
typo = typo.lower() # Force typos to lowercase.
|
||||
typo = typo.replace(" ", ":")
|
||||
|
||||
yield line_number, typo, correction
|
||||
|
||||
|
||||
def check_typo_against_dictionary(line_number: int, typo: str) -> None:
|
||||
"""Checks `typo` against English dictionary words."""
|
||||
|
||||
if typo.startswith(":") and typo.endswith(":"):
|
||||
if typo[1:-1] in CORRECT_WORDS:
|
||||
print(
|
||||
f'Warning:{line_number}: Typo "{typo}" is a correctly spelled '
|
||||
"dictionary word."
|
||||
)
|
||||
elif typo.startswith(":") and not typo.endswith(":"):
|
||||
for word in CORRECT_WORDS:
|
||||
if word.startswith(typo[1:]):
|
||||
print(
|
||||
f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
|
||||
f'on correctly spelled word "{word}".'
|
||||
)
|
||||
elif not typo.startswith(":") and typo.endswith(":"):
|
||||
for word in CORRECT_WORDS:
|
||||
if word.endswith(typo[:-1]):
|
||||
print(
|
||||
f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
|
||||
f'on correctly spelled word "{word}".'
|
||||
)
|
||||
elif not typo.startswith(":") and not typo.endswith(":"):
|
||||
for word in CORRECT_WORDS:
|
||||
if typo in word:
|
||||
print(
|
||||
f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
|
||||
f'on correctly spelled word "{word}".'
|
||||
)
|
||||
|
||||
|
||||
def serialize_trie(
|
||||
autocorrections: List[Tuple[str, str]], trie: Dict[str, Any]
|
||||
) -> List[int]:
|
||||
"""Serializes trie and correction data in a form readable by the C code.
|
||||
|
||||
Args:
|
||||
autocorrections: List of (typo, correction) tuples.
|
||||
trie: Dict of dicts.
|
||||
Returns:
|
||||
List of ints in the range 0-255.
|
||||
"""
|
||||
table = []
|
||||
|
||||
# Traverse trie in depth first order.
|
||||
def traverse(trie_node: Dict[str, Any]) -> Dict[str, Any]:
|
||||
if "LEAF" in trie_node: # Handle a leaf trie node.
|
||||
typo, correction = trie_node["LEAF"]
|
||||
word_boundary_ending = typo[-1] == ":"
|
||||
typo = typo.strip(":")
|
||||
i = 0 # Make the autocorrection data for this entry and serialize it.
|
||||
while i < min(len(typo), len(correction)) and typo[i] == correction[i]:
|
||||
i += 1
|
||||
backspaces = len(typo) - i - 1 + word_boundary_ending
|
||||
assert 0 <= backspaces <= 63
|
||||
correction = correction[i:]
|
||||
data = [backspaces + 128] + list(bytes(correction, "ascii")) + [0]
|
||||
|
||||
entry = {"data": data, "links": [], "byte_offset": 0}
|
||||
table.append(entry)
|
||||
elif len(trie_node) == 1: # Handle trie node with a single child.
|
||||
c, trie_node = next(iter(trie_node.items()))
|
||||
entry = {"chars": c, "byte_offset": 0}
|
||||
|
||||
# It's common for a trie to have long chains of single-child nodes. We
|
||||
# find the whole chain so that we can serialize it more efficiently.
|
||||
while len(trie_node) == 1 and "LEAF" not in trie_node:
|
||||
c, trie_node = next(iter(trie_node.items()))
|
||||
entry["chars"] += c
|
||||
|
||||
table.append(entry)
|
||||
entry["links"] = [traverse(trie_node)]
|
||||
else: # Handle trie node with multiple children.
|
||||
entry = {"chars": "".join(sorted(trie_node.keys())), "byte_offset": 0}
|
||||
table.append(entry)
|
||||
entry["links"] = [traverse(trie_node[c]) for c in entry["chars"]]
|
||||
return entry
|
||||
|
||||
traverse(trie)
|
||||
|
||||
def serialize(e: Dict[str, Any]) -> List[int]:
|
||||
if not e["links"]: # Handle a leaf table entry.
|
||||
return e["data"]
|
||||
elif len(e["links"]) == 1: # Handle a chain table entry.
|
||||
return [TYPO_CHARS[c] for c in e["chars"]] + [0]
|
||||
else: # Handle a branch table entry.
|
||||
data = []
|
||||
for c, link in zip(e["chars"], e["links"]):
|
||||
data += [TYPO_CHARS[c] | (0 if data else 64)] + encode_link(link)
|
||||
return data + [0]
|
||||
|
||||
byte_offset = 0
|
||||
for e in table: # To encode links, first compute byte offset of each entry.
|
||||
e["byte_offset"] = byte_offset
|
||||
byte_offset += len(serialize(e))
|
||||
|
||||
return [b for e in table for b in serialize(e)] # Serialize final table.
|
||||
|
||||
|
||||
def encode_link(link: Dict[str, Any]) -> List[int]:
|
||||
"""Encodes a node link as two bytes."""
|
||||
byte_offset = link["byte_offset"]
|
||||
if not (0 <= byte_offset <= 0xFFFF):
|
||||
print(
|
||||
"Error: The autocorrection table is too large, a node link exceeds "
|
||||
"64KB limit. Try reducing the autocorrection dict to fewer entries."
|
||||
)
|
||||
sys.exit(1)
|
||||
return [byte_offset & 255, byte_offset >> 8]
|
||||
|
||||
|
||||
def write_generated_code(
|
||||
autocorrections: List[Tuple[str, str]], data: List[int], file_name: str
|
||||
) -> None:
|
||||
"""Writes autocorrection data as generated C code to `file_name`.
|
||||
|
||||
Args:
|
||||
autocorrections: List of (typo, correction) tuples.
|
||||
data: List of ints in 0-255, the serialized trie.
|
||||
file_name: String, path of the output C file.
|
||||
"""
|
||||
assert all(0 <= b <= 255 for b in data)
|
||||
|
||||
def typo_len(e: Tuple[str, str]) -> int:
|
||||
return len(e[0])
|
||||
|
||||
min_typo = min(autocorrections, key=typo_len)[0]
|
||||
max_typo = max(autocorrections, key=typo_len)[0]
|
||||
generated_code = "".join(
|
||||
[
|
||||
"// Generated code.\n\n",
|
||||
f"// Autocorrection dictionary ({len(autocorrections)} entries):\n",
|
||||
"".join(
|
||||
sorted(
|
||||
f"// {typo:<{len(max_typo)}} -> {correction}\n"
|
||||
for typo, correction in autocorrections
|
||||
)
|
||||
),
|
||||
f'\n#define AUTOCORRECTION_MIN_LENGTH {len(min_typo)} // "{min_typo}"\n',
|
||||
f'#define AUTOCORRECTION_MAX_LENGTH {len(max_typo)} // "{max_typo}"\n\n',
|
||||
textwrap.fill(
|
||||
"static const uint8_t autocorrection_data[%d] PROGMEM = {%s};"
|
||||
% (len(data), ", ".join(map(str, data))),
|
||||
width=80,
|
||||
subsequent_indent=" ",
|
||||
),
|
||||
"\n\n",
|
||||
]
|
||||
)
|
||||
|
||||
with open(file_name, "wt") as f:
|
||||
f.write(generated_code)
|
||||
|
||||
|
||||
def get_default_h_file(dict_file: str) -> str:
|
||||
return os.path.join(os.path.dirname(dict_file), "autocorrect_data.h")
|
||||
|
||||
|
||||
def main(argv):
|
||||
dict_file = argv[1] if len(argv) > 1 else "dict.txt"
|
||||
h_file = argv[2] if len(argv) > 2 else get_default_h_file(dict_file)
|
||||
|
||||
autocorrections = parse_file(dict_file)
|
||||
trie = make_trie(autocorrections)
|
||||
data = serialize_trie(autocorrections, trie)
|
||||
print(
|
||||
f"Processed %d autocorrection entries to table with %d bytes."
|
||||
% (len(autocorrections), len(data))
|
||||
)
|
||||
write_generated_code(autocorrections, data, h_file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
@ -16,7 +16,5 @@
|
||||
#pragma once
|
||||
|
||||
#define HAL_USE_I2C TRUE
|
||||
#define HAL_USE_GPT TRUE
|
||||
#define HAL_USE_DAC TRUE
|
||||
|
||||
#include_next <halconf.h>
|
221
keyboards/zsa/voyager/keyboard.json
Normal file
221
keyboards/zsa/voyager/keyboard.json
Normal file
@ -0,0 +1,221 @@
|
||||
{
|
||||
"manufacturer": "ZSA Technology Labs",
|
||||
"keyboard_name": "Voyager",
|
||||
"maintainer": "ZSA Technology Labs",
|
||||
"url": "zsa.io/voyager",
|
||||
"processor": "STM32F303",
|
||||
"bootloader": "custom",
|
||||
"usb": {
|
||||
"vid": "0x3297",
|
||||
"pid": "0x1977",
|
||||
"device_version": "0.0.1",
|
||||
"shared_endpoint": {
|
||||
"mouse": false
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"caps_word": true,
|
||||
"deferred_exec": true,
|
||||
"mousekey": true,
|
||||
"extrakey": true,
|
||||
"nkro": true,
|
||||
"swap_hands": true,
|
||||
"rgb_matrix": true
|
||||
},
|
||||
"bootmagic": {
|
||||
"matrix": [0, 1]
|
||||
},
|
||||
"diode_direction": "ROW2COL",
|
||||
"mousekey": {
|
||||
"delay": 0,
|
||||
"interval": 20,
|
||||
"max_speed": 7,
|
||||
"time_to_max": 60,
|
||||
"wheel_delay": 400
|
||||
},
|
||||
"qmk": {
|
||||
"locking": {
|
||||
"enabled": true,
|
||||
"resync": true
|
||||
}
|
||||
},
|
||||
"tapping": {
|
||||
"toggle": 1
|
||||
},
|
||||
"rgb_matrix": {
|
||||
"driver": "is31fl3731",
|
||||
"led_flush_limit": 26,
|
||||
"led_process_limit": 5,
|
||||
"max_brightness": 175,
|
||||
"sleep": true,
|
||||
"animations": {
|
||||
"alphas_mods": true,
|
||||
"gradient_up_down": true,
|
||||
"gradient_left_right": true,
|
||||
"breathing": true,
|
||||
"band_sat": true,
|
||||
"band_val": true,
|
||||
"band_pinwheel_sat": true,
|
||||
"band_pinwheel_val": true,
|
||||
"band_spiral_sat": true,
|
||||
"band_spiral_val": true,
|
||||
"cycle_all": true,
|
||||
"cycle_left_right": true,
|
||||
"cycle_up_down": true,
|
||||
"rainbow_moving_chevron": true,
|
||||
"cycle_out_in": true,
|
||||
"cycle_out_in_dual": true,
|
||||
"cycle_pinwheel": true,
|
||||
"cycle_spiral": true,
|
||||
"dual_beacon": true,
|
||||
"rainbow_beacon": true,
|
||||
"rainbow_pinwheels": true,
|
||||
"flower_blooming": true,
|
||||
"raindrops": true,
|
||||
"jellybean_raindrops": true,
|
||||
"hue_breathing": true,
|
||||
"hue_pendulum": true,
|
||||
"hue_wave": true,
|
||||
"pixel_rain": true,
|
||||
"pixel_flow": true,
|
||||
"pixel_fractal": true,
|
||||
"typing_heatmap": true,
|
||||
"digital_rain": true,
|
||||
"solid_reactive_simple": true,
|
||||
"solid_reactive": true,
|
||||
"solid_reactive_wide": true,
|
||||
"solid_reactive_multiwide": true,
|
||||
"solid_reactive_cross": true,
|
||||
"solid_reactive_multicross": true,
|
||||
"solid_reactive_nexus": true,
|
||||
"solid_reactive_multinexus": true,
|
||||
"splash": true,
|
||||
"multisplash": true,
|
||||
"solid_splash": true,
|
||||
"solid_multisplash": true,
|
||||
"starlight": true,
|
||||
"starlight_dual_hue": true,
|
||||
"starlight_dual_sat": true,
|
||||
"riverflow": true
|
||||
},
|
||||
"layout": [
|
||||
{"matrix": [0, 1], "x": 0, "y": 10, "flags": 1},
|
||||
{"matrix": [0, 2], "x": 17, "y": 10, "flags": 4},
|
||||
{"matrix": [0, 3], "x": 34, "y": 8, "flags": 4},
|
||||
{"matrix": [0, 4], "x": 52, "y": 5, "flags": 4},
|
||||
{"matrix": [0, 5], "x": 69, "y": 8, "flags": 4},
|
||||
{"matrix": [0, 6], "x": 86, "y": 10, "flags": 4},
|
||||
{"matrix": [1, 1], "x": 0, "y": 21, "flags": 1},
|
||||
{"matrix": [1, 2], "x": 17, "y": 21, "flags": 4},
|
||||
{"matrix": [1, 3], "x": 34, "y": 19, "flags": 4},
|
||||
{"matrix": [1, 4], "x": 52, "y": 17, "flags": 4},
|
||||
{"matrix": [1, 5], "x": 69, "y": 19, "flags": 4},
|
||||
{"matrix": [1, 6], "x": 86, "y": 21, "flags": 4},
|
||||
{"matrix": [2, 1], "x": 0, "y": 32, "flags": 1},
|
||||
{"matrix": [2, 2], "x": 17, "y": 32, "flags": 4},
|
||||
{"matrix": [2, 3], "x": 34, "y": 30, "flags": 4},
|
||||
{"matrix": [2, 4], "x": 52, "y": 28, "flags": 4},
|
||||
{"matrix": [2, 5], "x": 69, "y": 30, "flags": 4},
|
||||
{"matrix": [2, 6], "x": 86, "y": 32, "flags": 4},
|
||||
{"matrix": [3, 1], "x": 0, "y": 43, "flags": 1},
|
||||
{"matrix": [3, 2], "x": 17, "y": 43, "flags": 4},
|
||||
{"matrix": [3, 3], "x": 34, "y": 41, "flags": 4},
|
||||
{"matrix": [3, 4], "x": 52, "y": 39, "flags": 4},
|
||||
{"matrix": [3, 5], "x": 69, "y": 41, "flags": 4},
|
||||
{"matrix": [4, 4], "x": 86, "y": 43, "flags": 4},
|
||||
{"matrix": [5, 0], "x": 86, "y": 53, "flags": 1},
|
||||
{"matrix": [5, 1], "x": 96, "y": 58, "flags": 1},
|
||||
{"matrix": [6, 0], "x": 138, "y": 10, "flags": 4},
|
||||
{"matrix": [6, 1], "x": 155, "y": 10, "flags": 4},
|
||||
{"matrix": [6, 2], "x": 172, "y": 8, "flags": 4},
|
||||
{"matrix": [6, 3], "x": 190, "y": 5, "flags": 4},
|
||||
{"matrix": [6, 4], "x": 207, "y": 8, "flags": 4},
|
||||
{"matrix": [6, 5], "x": 224, "y": 10, "flags": 1},
|
||||
{"matrix": [7, 0], "x": 138, "y": 21, "flags": 4},
|
||||
{"matrix": [7, 1], "x": 155, "y": 21, "flags": 4},
|
||||
{"matrix": [7, 2], "x": 172, "y": 19, "flags": 4},
|
||||
{"matrix": [7, 3], "x": 190, "y": 17, "flags": 4},
|
||||
{"matrix": [7, 4], "x": 207, "y": 19, "flags": 4},
|
||||
{"matrix": [7, 5], "x": 224, "y": 21, "flags": 1},
|
||||
{"matrix": [8, 0], "x": 138, "y": 32, "flags": 4},
|
||||
{"matrix": [8, 1], "x": 155, "y": 32, "flags": 4},
|
||||
{"matrix": [8, 2], "x": 172, "y": 30, "flags": 4},
|
||||
{"matrix": [8, 3], "x": 190, "y": 28, "flags": 4},
|
||||
{"matrix": [8, 4], "x": 207, "y": 30, "flags": 4},
|
||||
{"matrix": [8, 5], "x": 224, "y": 32, "flags": 1},
|
||||
{"matrix": [10, 2], "x": 138, "y": 43, "flags": 4},
|
||||
{"matrix": [9, 1], "x": 155, "y": 43, "flags": 4},
|
||||
{"matrix": [9, 2], "x": 172, "y": 41, "flags": 4},
|
||||
{"matrix": [9, 3], "x": 190, "y": 39, "flags": 4},
|
||||
{"matrix": [9, 4], "x": 207, "y": 41, "flags": 4},
|
||||
{"matrix": [9, 5], "x": 224, "y": 43, "flags": 1},
|
||||
{"matrix": [11, 5], "x": 128, "y": 58, "flags": 1},
|
||||
{"matrix": [11, 6], "x": 138, "y": 53, "flags": 1}
|
||||
]
|
||||
},
|
||||
"layout_aliases": {
|
||||
"LAYOUT_voyager": "LAYOUT"
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"layout": [
|
||||
{"label": "k00", "matrix": [0, 1], "x": 0, "y": 0.5},
|
||||
{"label": "k01", "matrix": [0, 2], "x": 1, "y": 0.5},
|
||||
{"label": "k02", "matrix": [0, 3], "x": 2, "y": 0.25},
|
||||
{"label": "k03", "matrix": [0, 4], "x": 3, "y": 0},
|
||||
{"label": "k04", "matrix": [0, 5], "x": 4, "y": 0.25},
|
||||
{"label": "k05", "matrix": [0, 6], "x": 5, "y": 0.5},
|
||||
{"label": "k06", "matrix": [1, 1], "x": 0, "y": 1.5},
|
||||
{"label": "k07", "matrix": [1, 2], "x": 1, "y": 1.5},
|
||||
{"label": "k08", "matrix": [1, 3], "x": 2, "y": 1.25},
|
||||
{"label": "k09", "matrix": [1, 4], "x": 3, "y": 1},
|
||||
{"label": "k10", "matrix": [1, 5], "x": 4, "y": 1.25},
|
||||
{"label": "k11", "matrix": [1, 6], "x": 5, "y": 1.5},
|
||||
{"label": "k12", "matrix": [2, 1], "x": 0, "y": 2.5},
|
||||
{"label": "k13", "matrix": [2, 2], "x": 1, "y": 2.5},
|
||||
{"label": "k14", "matrix": [2, 3], "x": 2, "y": 2.25},
|
||||
{"label": "k15", "matrix": [2, 4], "x": 3, "y": 2},
|
||||
{"label": "k16", "matrix": [2, 5], "x": 4, "y": 2.25},
|
||||
{"label": "k17", "matrix": [2, 6], "x": 5, "y": 2.5},
|
||||
{"label": "k18", "matrix": [3, 1], "x": 0, "y": 3.5},
|
||||
{"label": "k19", "matrix": [3, 2], "x": 1, "y": 3.5},
|
||||
{"label": "k20", "matrix": [3, 3], "x": 2, "y": 3.25},
|
||||
{"label": "k21", "matrix": [3, 4], "x": 3, "y": 3},
|
||||
{"label": "k22", "matrix": [3, 5], "x": 4, "y": 3.25},
|
||||
{"label": "k23", "matrix": [4, 4], "x": 5, "y": 3.5},
|
||||
{"label": "k24", "matrix": [5, 0], "x": 5, "y": 4.5},
|
||||
{"label": "k25", "matrix": [5, 1], "x": 6, "y": 4.75},
|
||||
{"label": "k26", "matrix": [6, 0], "x": 10, "y": 0.5},
|
||||
{"label": "k27", "matrix": [6, 1], "x": 11, "y": 0.25},
|
||||
{"label": "k28", "matrix": [6, 2], "x": 12, "y": 0},
|
||||
{"label": "k29", "matrix": [6, 3], "x": 13, "y": 0.25},
|
||||
{"label": "k30", "matrix": [6, 4], "x": 14, "y": 0.5},
|
||||
{"label": "k31", "matrix": [6, 5], "x": 15, "y": 0.5},
|
||||
{"label": "k32", "matrix": [7, 0], "x": 10, "y": 1.5},
|
||||
{"label": "k33", "matrix": [7, 1], "x": 11, "y": 1.25},
|
||||
{"label": "k34", "matrix": [7, 2], "x": 12, "y": 1},
|
||||
{"label": "k35", "matrix": [7, 3], "x": 13, "y": 1.25},
|
||||
{"label": "k36", "matrix": [7, 4], "x": 14, "y": 1.5},
|
||||
{"label": "k37", "matrix": [7, 5], "x": 15, "y": 1.5},
|
||||
{"label": "k38", "matrix": [8, 0], "x": 10, "y": 2.5},
|
||||
{"label": "k39", "matrix": [8, 1], "x": 11, "y": 2.25},
|
||||
{"label": "k40", "matrix": [8, 2], "x": 12, "y": 2},
|
||||
{"label": "k41", "matrix": [8, 3], "x": 13, "y": 2.25},
|
||||
{"label": "k42", "matrix": [8, 4], "x": 14, "y": 2.5},
|
||||
{"label": "k43", "matrix": [8, 5], "x": 15, "y": 2.5},
|
||||
{"label": "k44", "matrix": [10, 2], "x": 10, "y": 3.5},
|
||||
{"label": "k45", "matrix": [9, 1], "x": 11, "y": 3.25},
|
||||
{"label": "k46", "matrix": [9, 2], "x": 12, "y": 3},
|
||||
{"label": "k47", "matrix": [9, 3], "x": 13, "y": 3.25},
|
||||
{"label": "k48", "matrix": [9, 4], "x": 14, "y": 3.5},
|
||||
{"label": "k49", "matrix": [9, 5], "x": 15, "y": 3.5},
|
||||
|
||||
|
||||
|
||||
{"label": "k50", "matrix": [11, 5], "x": 9, "y": 4.75},
|
||||
{"label": "k51", "matrix": [11, 6], "x": 10, "y": 4.5}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
220
keyboards/zsa/voyager/keyboard.json.original
Normal file
220
keyboards/zsa/voyager/keyboard.json.original
Normal file
@ -0,0 +1,220 @@
|
||||
{
|
||||
"README": "This is the stock ZSA keyboard json. The one we use has a modified layout, because changing that is easier than changing my keymaps".
|
||||
|
||||
"manufacturer": "ZSA Technology Labs",
|
||||
"keyboard_name": "Voyager",
|
||||
"maintainer": "ZSA Technology Labs",
|
||||
"url": "zsa.io/voyager",
|
||||
"processor": "STM32F303",
|
||||
"bootloader": "custom",
|
||||
"usb": {
|
||||
"vid": "0x3297",
|
||||
"pid": "0x1977",
|
||||
"device_version": "0.0.1",
|
||||
"shared_endpoint": {
|
||||
"mouse": false
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"caps_word": true,
|
||||
"deferred_exec": true,
|
||||
"mousekey": true,
|
||||
"extrakey": true,
|
||||
"nkro": true,
|
||||
"swap_hands": true,
|
||||
"rgb_matrix": true
|
||||
},
|
||||
"bootmagic": {
|
||||
"matrix": [0, 1]
|
||||
},
|
||||
"diode_direction": "ROW2COL",
|
||||
"mousekey": {
|
||||
"delay": 0,
|
||||
"interval": 20,
|
||||
"max_speed": 7,
|
||||
"time_to_max": 60,
|
||||
"wheel_delay": 400
|
||||
},
|
||||
"qmk": {
|
||||
"locking": {
|
||||
"enabled": true,
|
||||
"resync": true
|
||||
}
|
||||
},
|
||||
"tapping": {
|
||||
"toggle": 1
|
||||
},
|
||||
"rgb_matrix": {
|
||||
"driver": "is31fl3731",
|
||||
"led_flush_limit": 26,
|
||||
"led_process_limit": 5,
|
||||
"max_brightness": 175,
|
||||
"sleep": true,
|
||||
"animations": {
|
||||
"alphas_mods": true,
|
||||
"gradient_up_down": true,
|
||||
"gradient_left_right": true,
|
||||
"breathing": true,
|
||||
"band_sat": true,
|
||||
"band_val": true,
|
||||
"band_pinwheel_sat": true,
|
||||
"band_pinwheel_val": true,
|
||||
"band_spiral_sat": true,
|
||||
"band_spiral_val": true,
|
||||
"cycle_all": true,
|
||||
"cycle_left_right": true,
|
||||
"cycle_up_down": true,
|
||||
"rainbow_moving_chevron": true,
|
||||
"cycle_out_in": true,
|
||||
"cycle_out_in_dual": true,
|
||||
"cycle_pinwheel": true,
|
||||
"cycle_spiral": true,
|
||||
"dual_beacon": true,
|
||||
"rainbow_beacon": true,
|
||||
"rainbow_pinwheels": true,
|
||||
"flower_blooming": true,
|
||||
"raindrops": true,
|
||||
"jellybean_raindrops": true,
|
||||
"hue_breathing": true,
|
||||
"hue_pendulum": true,
|
||||
"hue_wave": true,
|
||||
"pixel_rain": true,
|
||||
"pixel_flow": true,
|
||||
"pixel_fractal": true,
|
||||
"typing_heatmap": true,
|
||||
"digital_rain": true,
|
||||
"solid_reactive_simple": true,
|
||||
"solid_reactive": true,
|
||||
"solid_reactive_wide": true,
|
||||
"solid_reactive_multiwide": true,
|
||||
"solid_reactive_cross": true,
|
||||
"solid_reactive_multicross": true,
|
||||
"solid_reactive_nexus": true,
|
||||
"solid_reactive_multinexus": true,
|
||||
"splash": true,
|
||||
"multisplash": true,
|
||||
"solid_splash": true,
|
||||
"solid_multisplash": true,
|
||||
"starlight": true,
|
||||
"starlight_dual_hue": true,
|
||||
"starlight_dual_sat": true,
|
||||
"riverflow": true
|
||||
},
|
||||
"layout": [
|
||||
{"matrix": [0, 1], "x": 0, "y": 10, "flags": 1},
|
||||
{"matrix": [0, 2], "x": 17, "y": 10, "flags": 4},
|
||||
{"matrix": [0, 3], "x": 34, "y": 8, "flags": 4},
|
||||
{"matrix": [0, 4], "x": 52, "y": 5, "flags": 4},
|
||||
{"matrix": [0, 5], "x": 69, "y": 8, "flags": 4},
|
||||
{"matrix": [0, 6], "x": 86, "y": 10, "flags": 4},
|
||||
{"matrix": [1, 1], "x": 0, "y": 21, "flags": 1},
|
||||
{"matrix": [1, 2], "x": 17, "y": 21, "flags": 4},
|
||||
{"matrix": [1, 3], "x": 34, "y": 19, "flags": 4},
|
||||
{"matrix": [1, 4], "x": 52, "y": 17, "flags": 4},
|
||||
{"matrix": [1, 5], "x": 69, "y": 19, "flags": 4},
|
||||
{"matrix": [1, 6], "x": 86, "y": 21, "flags": 4},
|
||||
{"matrix": [2, 1], "x": 0, "y": 32, "flags": 1},
|
||||
{"matrix": [2, 2], "x": 17, "y": 32, "flags": 4},
|
||||
{"matrix": [2, 3], "x": 34, "y": 30, "flags": 4},
|
||||
{"matrix": [2, 4], "x": 52, "y": 28, "flags": 4},
|
||||
{"matrix": [2, 5], "x": 69, "y": 30, "flags": 4},
|
||||
{"matrix": [2, 6], "x": 86, "y": 32, "flags": 4},
|
||||
{"matrix": [3, 1], "x": 0, "y": 43, "flags": 1},
|
||||
{"matrix": [3, 2], "x": 17, "y": 43, "flags": 4},
|
||||
{"matrix": [3, 3], "x": 34, "y": 41, "flags": 4},
|
||||
{"matrix": [3, 4], "x": 52, "y": 39, "flags": 4},
|
||||
{"matrix": [3, 5], "x": 69, "y": 41, "flags": 4},
|
||||
{"matrix": [4, 4], "x": 86, "y": 43, "flags": 4},
|
||||
{"matrix": [5, 0], "x": 86, "y": 53, "flags": 1},
|
||||
{"matrix": [5, 1], "x": 96, "y": 58, "flags": 1},
|
||||
{"matrix": [6, 0], "x": 138, "y": 10, "flags": 4},
|
||||
{"matrix": [6, 1], "x": 155, "y": 10, "flags": 4},
|
||||
{"matrix": [6, 2], "x": 172, "y": 8, "flags": 4},
|
||||
{"matrix": [6, 3], "x": 190, "y": 5, "flags": 4},
|
||||
{"matrix": [6, 4], "x": 207, "y": 8, "flags": 4},
|
||||
{"matrix": [6, 5], "x": 224, "y": 10, "flags": 1},
|
||||
{"matrix": [7, 0], "x": 138, "y": 21, "flags": 4},
|
||||
{"matrix": [7, 1], "x": 155, "y": 21, "flags": 4},
|
||||
{"matrix": [7, 2], "x": 172, "y": 19, "flags": 4},
|
||||
{"matrix": [7, 3], "x": 190, "y": 17, "flags": 4},
|
||||
{"matrix": [7, 4], "x": 207, "y": 19, "flags": 4},
|
||||
{"matrix": [7, 5], "x": 224, "y": 21, "flags": 1},
|
||||
{"matrix": [8, 0], "x": 138, "y": 32, "flags": 4},
|
||||
{"matrix": [8, 1], "x": 155, "y": 32, "flags": 4},
|
||||
{"matrix": [8, 2], "x": 172, "y": 30, "flags": 4},
|
||||
{"matrix": [8, 3], "x": 190, "y": 28, "flags": 4},
|
||||
{"matrix": [8, 4], "x": 207, "y": 30, "flags": 4},
|
||||
{"matrix": [8, 5], "x": 224, "y": 32, "flags": 1},
|
||||
{"matrix": [10, 2], "x": 138, "y": 43, "flags": 4},
|
||||
{"matrix": [9, 1], "x": 155, "y": 43, "flags": 4},
|
||||
{"matrix": [9, 2], "x": 172, "y": 41, "flags": 4},
|
||||
{"matrix": [9, 3], "x": 190, "y": 39, "flags": 4},
|
||||
{"matrix": [9, 4], "x": 207, "y": 41, "flags": 4},
|
||||
{"matrix": [9, 5], "x": 224, "y": 43, "flags": 1},
|
||||
{"matrix": [11, 5], "x": 128, "y": 58, "flags": 1},
|
||||
{"matrix": [11, 6], "x": 138, "y": 53, "flags": 1}
|
||||
]
|
||||
},
|
||||
"layout_aliases": {
|
||||
"LAYOUT_voyager": "LAYOUT"
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"layout": [
|
||||
{"label": "k00", "matrix": [0, 1], "x": 0, "y": 0.5},
|
||||
{"label": "k01", "matrix": [0, 2], "x": 1, "y": 0.5},
|
||||
{"label": "k02", "matrix": [0, 3], "x": 2, "y": 0.25},
|
||||
{"label": "k03", "matrix": [0, 4], "x": 3, "y": 0},
|
||||
{"label": "k04", "matrix": [0, 5], "x": 4, "y": 0.25},
|
||||
{"label": "k05", "matrix": [0, 6], "x": 5, "y": 0.5},
|
||||
{"label": "k26", "matrix": [6, 0], "x": 10, "y": 0.5},
|
||||
{"label": "k27", "matrix": [6, 1], "x": 11, "y": 0.25},
|
||||
{"label": "k28", "matrix": [6, 2], "x": 12, "y": 0},
|
||||
{"label": "k29", "matrix": [6, 3], "x": 13, "y": 0.25},
|
||||
{"label": "k30", "matrix": [6, 4], "x": 14, "y": 0.5},
|
||||
{"label": "k31", "matrix": [6, 5], "x": 15, "y": 0.5},
|
||||
{"label": "k06", "matrix": [1, 1], "x": 0, "y": 1.5},
|
||||
{"label": "k07", "matrix": [1, 2], "x": 1, "y": 1.5},
|
||||
{"label": "k08", "matrix": [1, 3], "x": 2, "y": 1.25},
|
||||
{"label": "k09", "matrix": [1, 4], "x": 3, "y": 1},
|
||||
{"label": "k10", "matrix": [1, 5], "x": 4, "y": 1.25},
|
||||
{"label": "k11", "matrix": [1, 6], "x": 5, "y": 1.5},
|
||||
{"label": "k32", "matrix": [7, 0], "x": 10, "y": 1.5},
|
||||
{"label": "k33", "matrix": [7, 1], "x": 11, "y": 1.25},
|
||||
{"label": "k34", "matrix": [7, 2], "x": 12, "y": 1},
|
||||
{"label": "k35", "matrix": [7, 3], "x": 13, "y": 1.25},
|
||||
{"label": "k36", "matrix": [7, 4], "x": 14, "y": 1.5},
|
||||
{"label": "k37", "matrix": [7, 5], "x": 15, "y": 1.5},
|
||||
{"label": "k12", "matrix": [2, 1], "x": 0, "y": 2.5},
|
||||
{"label": "k13", "matrix": [2, 2], "x": 1, "y": 2.5},
|
||||
{"label": "k14", "matrix": [2, 3], "x": 2, "y": 2.25},
|
||||
{"label": "k15", "matrix": [2, 4], "x": 3, "y": 2},
|
||||
{"label": "k16", "matrix": [2, 5], "x": 4, "y": 2.25},
|
||||
{"label": "k17", "matrix": [2, 6], "x": 5, "y": 2.5},
|
||||
{"label": "k38", "matrix": [8, 0], "x": 10, "y": 2.5},
|
||||
{"label": "k39", "matrix": [8, 1], "x": 11, "y": 2.25},
|
||||
{"label": "k40", "matrix": [8, 2], "x": 12, "y": 2},
|
||||
{"label": "k41", "matrix": [8, 3], "x": 13, "y": 2.25},
|
||||
{"label": "k42", "matrix": [8, 4], "x": 14, "y": 2.5},
|
||||
{"label": "k43", "matrix": [8, 5], "x": 15, "y": 2.5},
|
||||
{"label": "k18", "matrix": [3, 1], "x": 0, "y": 3.5},
|
||||
{"label": "k19", "matrix": [3, 2], "x": 1, "y": 3.5},
|
||||
{"label": "k20", "matrix": [3, 3], "x": 2, "y": 3.25},
|
||||
{"label": "k21", "matrix": [3, 4], "x": 3, "y": 3},
|
||||
{"label": "k22", "matrix": [3, 5], "x": 4, "y": 3.25},
|
||||
{"label": "k23", "matrix": [4, 4], "x": 5, "y": 3.5},
|
||||
{"label": "k44", "matrix": [10, 2], "x": 10, "y": 3.5},
|
||||
{"label": "k45", "matrix": [9, 1], "x": 11, "y": 3.25},
|
||||
{"label": "k46", "matrix": [9, 2], "x": 12, "y": 3},
|
||||
{"label": "k47", "matrix": [9, 3], "x": 13, "y": 3.25},
|
||||
{"label": "k48", "matrix": [9, 4], "x": 14, "y": 3.5},
|
||||
{"label": "k49", "matrix": [9, 5], "x": 15, "y": 3.5},
|
||||
{"label": "k24", "matrix": [5, 0], "x": 5, "y": 4.5},
|
||||
{"label": "k25", "matrix": [5, 1], "x": 6, "y": 4.75},
|
||||
{"label": "k50", "matrix": [11, 5], "x": 9, "y": 4.75},
|
||||
{"label": "k51", "matrix": [11, 6], "x": 10, "y": 4.5}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
48
keyboards/zsa/voyager/keymaps/betalupi/config.h
Normal file
48
keyboards/zsa/voyager/keymaps/betalupi/config.h
Normal file
@ -0,0 +1,48 @@
|
||||
#define ENABLE_BETA_LEADER
|
||||
|
||||
// No timeout after initial leader key press
|
||||
#define LEADER_NO_TIMEOUT
|
||||
|
||||
#define COMBO_SHOULD_TRIGGER
|
||||
|
||||
// Timeout resets after each keypress
|
||||
#define LEADER_PER_KEY_TIMING
|
||||
#define LEADER_TIMEOUT 500
|
||||
|
||||
#define NAVIGATOR_TRACKBALL_CPI 30
|
||||
#define NAVIGATOR_SCROLL_DIVIDER 70
|
||||
|
||||
#define POINTING_DEVICE_AUTO_MOUSE_ENABLE
|
||||
#define AUTO_MOUSE_DEFAULT_LAYER 3
|
||||
#define AUTO_MOUSE_THRESHOLD 10
|
||||
#define AUTO_MOUSE_SCROLL_THRESHOLD AUTO_MOUSE_THRESHOLD / NAVIGATOR_SCROLL_DIVIDER
|
||||
#define RGB_MATRIX_STARTUP_SPD 60
|
||||
|
||||
// Enable spellcheck over HID
|
||||
// #define ENABLE_HID_SPELLCHECK
|
||||
|
||||
#define ENABLE_AUTOCORRECT
|
||||
|
||||
// RGBLight effects
|
||||
// Static color is always enabled.
|
||||
// #define RGBLIGHT_EFFECT_ALTERNATING
|
||||
// #define RGBLIGHT_EFFECT_BREATHING
|
||||
// #define RGBLIGHT_EFFECT_CHRISTMAS
|
||||
// #define RGBLIGHT_EFFECT_KNIGHT
|
||||
// #define RGBLIGHT_EFFECT_RAINBOW_MOOD
|
||||
// #define RGBLIGHT_EFFECT_RAINBOW_SWIRL
|
||||
// #define RGBLIGHT_EFFECT_RGB_TEST
|
||||
// #define RGBLIGHT_EFFECT_SNAKE
|
||||
// #define RGBLIGHT_EFFECT_STATIC_GRADIENT
|
||||
// #define RGBLIGHT_EFFECT_TWINKLE
|
||||
|
||||
// Custom effects
|
||||
// #define RGB_MATRIX_FRAMEBUFFER_EFFECTS
|
||||
// #define ENABLE_RGB_MATRIX_FFT_ANIM // Requires framebuffer
|
||||
|
||||
#define USB_SUSPEND_WAKEUP_DELAY 200
|
||||
#define RAW_USAGE_PAGE 0xFF60
|
||||
#define RAW_USAGE_ID 0x61
|
||||
#define LAYER_STATE_32BIT
|
||||
|
||||
#define RGB_MATRIX_STARTUP_SPD 60
|
@ -15,7 +15,7 @@
|
||||
// Macro keycodes
|
||||
enum custom_keycodes
|
||||
{
|
||||
M_SHUTDOWN = BETA_SAFE_RANGE,
|
||||
M_SHUTDOWN = ZSA_SAFE_RANGE,
|
||||
|
||||
// Macros
|
||||
M_RESETWM,
|
||||
@ -40,7 +40,11 @@ enum custom_keycodes
|
||||
M_SC_RCBR,
|
||||
M_SC_LKVCH,
|
||||
M_SC_RKVCH,
|
||||
M_SPECIAL_BOTTOM
|
||||
M_SPECIAL_BOTTOM,
|
||||
|
||||
DRAG_SCROLL,
|
||||
NAVIGATOR_TURBO,
|
||||
NAVIGATOR_AIM
|
||||
};
|
||||
|
||||
// LED colors
|
||||
@ -83,6 +87,10 @@ bool send_special_character(uint16_t keycode) {
|
||||
return true;
|
||||
}*/
|
||||
|
||||
extern bool set_scrolling;
|
||||
extern bool navigator_turbo;
|
||||
extern bool navigator_aim;
|
||||
|
||||
const uint16_t PROGMEM combo2[] = {KC_D, KC_F, COMBO_END};
|
||||
const uint16_t PROGMEM combo3[] = {KC_M, KC_P, COMBO_END};
|
||||
const uint16_t PROGMEM combo4[] = {RU_ER, RU_TE, COMBO_END};
|
||||
@ -112,6 +120,12 @@ enum tap_dance_codes
|
||||
TD_NOGAME
|
||||
};
|
||||
|
||||
void pointing_device_init_user(void)
|
||||
{
|
||||
// set_auto_mouse_layer(<mouse_layer>); // only required if AUTO_MOUSE_DEFAULT_LAYER is not set to index of <mouse_layer>
|
||||
set_auto_mouse_enable(true); // always required before the auto mouse feature will work
|
||||
}
|
||||
|
||||
// Include all other parts of configuration
|
||||
#include "layers/layers.c"
|
||||
#include "parts/leader.c"
|
||||
@ -212,26 +226,56 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record)
|
||||
SEND_STRING(SS_LGUI(SS_TAP(X_P)) SS_DELAY(100) SS_TAP(X_Y) SS_DELAY(100) SS_TAP(X_ENTER));
|
||||
}
|
||||
return false;
|
||||
/*
|
||||
case M_RU_CTRL:
|
||||
if (record->event.pressed) {
|
||||
layer_move(LAYER_MAIN);
|
||||
register_code16(KC_LCTL);
|
||||
} else {
|
||||
unregister_code16(KC_LCTL);
|
||||
layer_move(LAYER_RUSSIAN);
|
||||
}
|
||||
return false;
|
||||
/*
|
||||
case M_RU_CTRL:
|
||||
if (record->event.pressed) {
|
||||
layer_move(LAYER_MAIN);
|
||||
register_code16(KC_LCTL);
|
||||
} else {
|
||||
unregister_code16(KC_LCTL);
|
||||
layer_move(LAYER_RUSSIAN);
|
||||
}
|
||||
return false;
|
||||
|
||||
case M_RU_ALT:
|
||||
if (record->event.pressed) {
|
||||
layer_move(LAYER_MAIN);
|
||||
register_code16(KC_LALT);
|
||||
} else {
|
||||
unregister_code16(KC_LALT);
|
||||
layer_move(LAYER_RUSSIAN);
|
||||
}
|
||||
return false;*/
|
||||
case M_RU_ALT:
|
||||
if (record->event.pressed) {
|
||||
layer_move(LAYER_MAIN);
|
||||
register_code16(KC_LALT);
|
||||
} else {
|
||||
unregister_code16(KC_LALT);
|
||||
layer_move(LAYER_RUSSIAN);
|
||||
}
|
||||
return false;*/
|
||||
case DRAG_SCROLL:
|
||||
if (record->event.pressed)
|
||||
{
|
||||
set_scrolling = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
set_scrolling = false;
|
||||
}
|
||||
return false;
|
||||
case NAVIGATOR_TURBO:
|
||||
if (record->event.pressed)
|
||||
{
|
||||
navigator_turbo = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
navigator_turbo = false;
|
||||
}
|
||||
return false;
|
||||
case NAVIGATOR_AIM:
|
||||
if (record->event.pressed)
|
||||
{
|
||||
navigator_aim = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
navigator_aim = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
6
keyboards/zsa/voyager/keymaps/betalupi/keymap.json
Normal file
6
keyboards/zsa/voyager/keymaps/betalupi/keymap.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"modules": [
|
||||
"zsa/oryx",
|
||||
"zsa/defaults"
|
||||
]
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
// See symbols.h for docs
|
||||
|
||||
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(CTRL)
|
||||
|
||||
#ifdef BETA_LAYER_LAYOUTS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_EN
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#ifdef BETA_LAYER_KEYS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_voyager( \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, LGUI(KC_A), LGUI(KC_S), LGUI(KC_D), KC_TRNS, KC_TRNS, \
|
||||
KC_NO, LGUI(KC_Z), LGUI(KC_X), LGUI(KC_C), LGUI(KC_V), KC_TRNS, \
|
||||
KC_LALT, KC_LSFT, \
|
||||
\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS)
|
||||
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#ifdef BETA_LAYER_LEDS
|
||||
#define BETA_LAYER_CONTEXT_DATA { \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_RED, LC_ORN, LC_GRN, LC_GRN, LC_CYN, LC_OFF, \
|
||||
LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF}
|
||||
|
||||
// This is important.
|
||||
// The magic macro MUST be here, AFTER the RGBMatrix data.
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#undef BETA_LAYER_CONTEXT_DATA
|
||||
#undef BETA_LAYER_MAGIC_MACRO
|
@ -11,6 +11,7 @@
|
||||
#include "main.h"
|
||||
#include "game.h"
|
||||
#include "ctrl.h"
|
||||
#include "mouse.h"
|
||||
|
||||
#include "russian.h"
|
||||
|
@ -0,0 +1,35 @@
|
||||
// See symbols.h for docs
|
||||
|
||||
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(MAIN)
|
||||
|
||||
#ifdef BETA_LAYER_LAYOUTS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_EN
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
// TODO:
|
||||
// russian
|
||||
// spellcheck
|
||||
// shared features
|
||||
|
||||
#ifdef BETA_LAYER_KEYS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_voyager( \
|
||||
KC_ESCAPE, KC_1, KC_2, KC_3, KC_4, KC_5, \
|
||||
OSL(LAYER_MACROS), KC_Q, KC_W, KC_E, KC_R, KC_T, \
|
||||
KC_DELETE, MT(MOD_LALT, KC_A), KC_S, KC_D, KC_F, KC_G, \
|
||||
MO(LAYER_CTRL), KC_Z, MT(MOD_LSFT, KC_X), KC_C, MO(LAYER_ARROWS), KC_B, \
|
||||
\
|
||||
KC_SPACE, KC_BSPC, \
|
||||
\
|
||||
KC_6, KC_7, KC_8, KC_9, KC_0, LGUI(KC_SPACE), \
|
||||
KC_Y, KC_U, KC_I, KC_O, KC_NO, KC_NO, \
|
||||
KC_H, KC_J, KC_K, MO(LAYER_SYMBOLS), KC_L, QK_LEAD, \
|
||||
KC_N, KC_M, KC_P, KC_V, KC_NO, KC_NO, \
|
||||
\
|
||||
KC_RSFT, KC_ENTER)
|
||||
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#undef BETA_LAYER_CONTEXT_DATA
|
||||
#undef BETA_LAYER_MAGIC_MACRO
|
@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(MOUSE)
|
||||
|
||||
#ifdef BETA_LAYER_LAYOUTS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_NULL
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#ifdef BETA_LAYER_KEYS
|
||||
#define BETA_LAYER_CONTEXT_DATA LAYOUT_voyager( \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_BTN1, NAVIGATOR_AIM, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, DRAG_SCROLL, KC_MS_BTN2, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, \
|
||||
\
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
|
||||
KC_TRNS, KC_TRNS)
|
||||
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#ifdef BETA_LAYER_LEDS
|
||||
#define BETA_LAYER_CONTEXT_DATA { \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_GRN, LC_ORN, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_ORN, LC_GRN, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
|
||||
LC_OFF, LC_OFF}
|
||||
|
||||
BETA_LAYER_MAGIC_MACRO
|
||||
#endif
|
||||
|
||||
#undef BETA_LAYER_CONTEXT_DATA
|
||||
#undef BETA_LAYER_MAGIC_MACRO
|
@ -1,61 +1,56 @@
|
||||
//#include "extra_mappings.h"
|
||||
// #include "extra_mappings.h"
|
||||
#define LAYER_INCLUDE_FILE "definitions/include.c"
|
||||
|
||||
|
||||
/*
|
||||
Setup
|
||||
*/
|
||||
|
||||
|
||||
// Generate layer ids
|
||||
#define BETA_LAYER_KEYS
|
||||
#define BETA_LAYER(name) LAYER_##name,
|
||||
enum layer_indices {
|
||||
#include LAYER_INCLUDE_FILE
|
||||
enum layer_indices
|
||||
{
|
||||
#include LAYER_INCLUDE_FILE
|
||||
X_LAYER_MAX
|
||||
};
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_KEYS
|
||||
|
||||
|
||||
// Generate RGBMatrix ids
|
||||
// We don't use the same id for layers and layer colors
|
||||
// to save memory. Not every layer has colors!
|
||||
#define BETA_LAYER_LEDS
|
||||
#define BETA_LAYER(name) LAYER_##name##_LEDS,
|
||||
enum led_indices {
|
||||
#include LAYER_INCLUDE_FILE
|
||||
enum led_indices
|
||||
{
|
||||
#include LAYER_INCLUDE_FILE
|
||||
X_LAYER_LEDS_MAX
|
||||
};
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_LEDS
|
||||
|
||||
|
||||
/*
|
||||
Load layers
|
||||
*/
|
||||
|
||||
|
||||
// Create keymap array
|
||||
#define BETA_LAYER_KEYS
|
||||
#define BETA_LAYER(name) [LAYER_##name] = BETA_LAYER_CONTEXT_DATA,
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
#include LAYER_INCLUDE_FILE
|
||||
#include LAYER_INCLUDE_FILE
|
||||
};
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_KEYS
|
||||
|
||||
|
||||
// Create led map array
|
||||
#define BETA_LAYER_LEDS
|
||||
#define BETA_LAYER(name) [LAYER_##name##_LEDS] = BETA_LAYER_CONTEXT_DATA,
|
||||
const uint8_t PROGMEM ledmaps[][RGB_MATRIX_LED_COUNT][3] = {
|
||||
#include LAYER_INCLUDE_FILE
|
||||
#include LAYER_INCLUDE_FILE
|
||||
};
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_LEDS
|
||||
|
||||
|
||||
/*
|
||||
// Create os layout array
|
||||
#define BETA_LAYER_LAYOUTS
|
||||
@ -67,74 +62,84 @@ uint8_t layer_layouts[] = {
|
||||
#undef BETA_LAYER_LAYOUTS
|
||||
*/
|
||||
|
||||
void set_layer_color(int layer) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
void set_layer_color(int layer)
|
||||
{
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++)
|
||||
{
|
||||
HSV hsv = {
|
||||
.h = pgm_read_byte(&ledmaps[layer][i][0]),
|
||||
.s = pgm_read_byte(&ledmaps[layer][i][1]),
|
||||
.v = pgm_read_byte(&ledmaps[layer][i][2]),
|
||||
};
|
||||
if (!hsv.h && !hsv.s && !hsv.v) {
|
||||
rgb_matrix_set_color( i, 0, 0, 0 );
|
||||
} else {
|
||||
RGB rgb = hsv_to_rgb( hsv );
|
||||
if (!hsv.h && !hsv.s && !hsv.v)
|
||||
{
|
||||
rgb_matrix_set_color(i, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RGB rgb = hsv_to_rgb(hsv);
|
||||
float f = (float)rgb_matrix_config.hsv.v / UINT8_MAX;
|
||||
rgb_matrix_set_color( i, f * rgb.r, f * rgb.g, f * rgb.b );
|
||||
rgb_matrix_set_color(i, f * rgb.r, f * rgb.g, f * rgb.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern bool beta_leading;
|
||||
|
||||
bool rgb_matrix_indicators_user(void) {
|
||||
if (keyboard_config.disable_layer_led) {
|
||||
bool rgb_matrix_indicators_user(void)
|
||||
{
|
||||
if (keyboard_config.disable_layer_led)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (biton32(layer_state)) {
|
||||
switch (biton32(layer_state))
|
||||
{
|
||||
|
||||
// Load layer RGBMatrix colors
|
||||
#define BETA_LAYER_LEDS
|
||||
#define BETA_LAYER(name)\
|
||||
case LAYER_##name:\
|
||||
set_layer_color(LAYER_##name##_LEDS);\
|
||||
break;
|
||||
// Load layer RGBMatrix colors
|
||||
#define BETA_LAYER_LEDS
|
||||
#define BETA_LAYER(name) \
|
||||
case LAYER_##name: \
|
||||
set_layer_color(LAYER_##name##_LEDS); \
|
||||
break;
|
||||
|
||||
#include LAYER_INCLUDE_FILE
|
||||
#include LAYER_INCLUDE_FILE
|
||||
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_LEDS
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_LEDS
|
||||
|
||||
default:
|
||||
if (rgb_matrix_get_flags() == LED_FLAG_NONE) {
|
||||
rgb_matrix_set_color_all(0, 0, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (rgb_matrix_get_flags() == LED_FLAG_NONE)
|
||||
{
|
||||
rgb_matrix_set_color_all(0, 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (beta_leading) {
|
||||
if (beta_leading)
|
||||
{
|
||||
rgb_matrix_set_color(43, 0x00, 0x00, 0xFF);
|
||||
}
|
||||
|
||||
if (biton32(layer_state) == LAYER_KEYBOARD) {
|
||||
rgb_matrix_set_color(0, 0xFF, 0x00, 0x00);
|
||||
if (biton32(layer_state) == LAYER_KEYBOARD)
|
||||
{
|
||||
rgb_matrix_set_color(0, 0xFF, 0x00, 0x00);
|
||||
rgb_matrix_set_color(18, 0x95, 0xFF, 0x00);
|
||||
rgb_matrix_set_color(19, 0x95, 0xFF, 0x00);
|
||||
|
||||
rgb_matrix_set_color(14, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(13, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(8, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(7, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(2, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(1, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(8, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(7, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(2, 0x00, 0xFF, 0x8C);
|
||||
rgb_matrix_set_color(1, 0x00, 0xFF, 0x8C);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
layer_state_t layer_state_set_user(layer_state_t state)
|
||||
{
|
||||
uint8_t layer = biton32(state);
|
||||
|
||||
STATUS_LED_1(false);
|
||||
@ -142,19 +147,19 @@ layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
STATUS_LED_3(false);
|
||||
STATUS_LED_4(false);
|
||||
|
||||
switch (layer) {
|
||||
switch (layer)
|
||||
{
|
||||
|
||||
// Load indicator LED cases
|
||||
#define BETA_LAYER_INDICATORS
|
||||
#define BETA_LAYER(name) LAYER_##name
|
||||
#include LAYER_INCLUDE_FILE
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_INDICATORS
|
||||
// Load indicator LED cases
|
||||
#define BETA_LAYER_INDICATORS
|
||||
#define BETA_LAYER(name) LAYER_##name
|
||||
#include LAYER_INCLUDE_FILE
|
||||
#undef BETA_LAYER
|
||||
#undef BETA_LAYER_INDICATORS
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
12
keyboards/zsa/voyager/keymaps/betalupi/rules.mk
Normal file
12
keyboards/zsa/voyager/keymaps/betalupi/rules.mk
Normal file
@ -0,0 +1,12 @@
|
||||
# rules.mk overrides
|
||||
|
||||
TAP_DANCE_ENABLE = yes
|
||||
|
||||
CONSOLE_ENABLE = no
|
||||
COMMAND_ENABLE = no
|
||||
ORYX_ENABLE = no
|
||||
RGB_MATRIX_CUSTOM_KB = no
|
||||
SPACE_CADET_ENABLE = no
|
||||
COMBO_ENABLE = yes
|
||||
POINTING_DEVICE_ENABLE = yes
|
||||
POINTING_DEVICE_DRIVER = navigator_trackball
|
@ -1,40 +1,40 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32F303xC memory setup.
|
||||
* STM32F303xB memory setup.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash0 (rx) : org = 0x08002000, len = 256k - 0x2000
|
||||
flash1 (rx) : org = 0x00000000, len = 0
|
||||
flash2 (rx) : org = 0x00000000, len = 0
|
||||
flash3 (rx) : org = 0x00000000, len = 0
|
||||
flash4 (rx) : org = 0x00000000, len = 0
|
||||
flash5 (rx) : org = 0x00000000, len = 0
|
||||
flash6 (rx) : org = 0x00000000, len = 0
|
||||
flash7 (rx) : org = 0x00000000, len = 0
|
||||
ram0 (wx) : org = 0x20000000, len = 40k
|
||||
ram1 (wx) : org = 0x00000000, len = 0
|
||||
ram2 (wx) : org = 0x00000000, len = 0
|
||||
ram3 (wx) : org = 0x00000000, len = 0
|
||||
ram4 (wx) : org = 0x10000000, len = 8k
|
||||
ram5 (wx) : org = 0x00000000, len = 0
|
||||
ram6 (wx) : org = 0x00000000, len = 0
|
||||
ram7 (wx) : org = 0x00000000, len = 0
|
||||
flash0 (rx) : org = 0x08002000, len = 128k - 0x2000
|
||||
flash1 (rx) : org = 0x00000000, len = 0
|
||||
flash2 (rx) : org = 0x00000000, len = 0
|
||||
flash3 (rx) : org = 0x00000000, len = 0
|
||||
flash4 (rx) : org = 0x00000000, len = 0
|
||||
flash5 (rx) : org = 0x00000000, len = 0
|
||||
flash6 (rx) : org = 0x00000000, len = 0
|
||||
flash7 (rx) : org = 0x00000000, len = 0
|
||||
ram0 (wx) : org = 0x20000000, len = 32k
|
||||
ram1 (wx) : org = 0x00000000, len = 0
|
||||
ram2 (wx) : org = 0x00000000, len = 0
|
||||
ram3 (wx) : org = 0x00000000, len = 0
|
||||
ram4 (wx) : org = 0x10000000, len = 8k
|
||||
ram5 (wx) : org = 0x00000000, len = 0
|
||||
ram6 (wx) : org = 0x00000000, len = 0
|
||||
ram7 (wx) : org = 0x00000000, len = 0
|
||||
}
|
||||
|
||||
/* For each data/text section two region are defined, a virtual region
|
256
keyboards/zsa/voyager/matrix.c
Normal file
256
keyboards/zsa/voyager/matrix.c
Normal file
@ -0,0 +1,256 @@
|
||||
// Copyright 2023 ZSA Technology Labs, Inc <@zsa>
|
||||
// Copyright 2023 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "voyager.h"
|
||||
#include "mcp23018.h"
|
||||
#include "i2c_master.h"
|
||||
#include <hal.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("-O3")
|
||||
|
||||
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
|
||||
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
|
||||
static matrix_row_t raw_matrix_right[MATRIX_COLS];
|
||||
|
||||
#define MCP_ROWS_PER_HAND (MATRIX_ROWS / 2)
|
||||
#ifndef I2C_DRIVER
|
||||
#define I2C_DRIVER I2CD1
|
||||
#endif
|
||||
#ifndef VOYAGER_I2C_TIMEOUT
|
||||
#define VOYAGER_I2C_TIMEOUT 100
|
||||
#endif
|
||||
// Delay between each i2c io expander ops (in MCU cycles)
|
||||
#ifndef IO_EXPANDER_OP_DELAY
|
||||
#define IO_EXPANDER_OP_DELAY 500
|
||||
#endif
|
||||
|
||||
extern bool mcp23018_leds[2];
|
||||
extern bool is_launching;
|
||||
|
||||
static uint16_t mcp23018_reset_loop;
|
||||
uint8_t mcp23018_errors;
|
||||
|
||||
bool io_expander_ready(void)
|
||||
{
|
||||
uint8_t tx;
|
||||
return mcp23018_readPins(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTA, &tx);
|
||||
}
|
||||
|
||||
uint8_t mcp23018_init_local(bool first_run)
|
||||
{
|
||||
if (!first_run)
|
||||
{
|
||||
i2cStop(&I2C_DRIVER);
|
||||
}
|
||||
wait_ms(10);
|
||||
// Try releasing special pins for a short time
|
||||
palSetLineMode(B6, PAL_MODE_INPUT);
|
||||
palSetLineMode(B7, PAL_MODE_INPUT);
|
||||
wait_ms(10);
|
||||
palSetLineMode(B6, PAL_MODE_ALTERNATE(4) | PAL_OUTPUT_TYPE_OPENDRAIN);
|
||||
palSetLineMode(B7, PAL_MODE_ALTERNATE(4) | PAL_OUTPUT_TYPE_OPENDRAIN);
|
||||
|
||||
uint8_t errors = 0;
|
||||
errors += !mcp23018_set_config(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTA, 0b00000000);
|
||||
errors += !mcp23018_set_config(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTB, 0b00111111);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
void matrix_init_custom(void)
|
||||
{
|
||||
// outputs
|
||||
gpio_set_pin_output(B10);
|
||||
gpio_set_pin_output(B11);
|
||||
gpio_set_pin_output(B12);
|
||||
gpio_set_pin_output(B13);
|
||||
gpio_set_pin_output(B14);
|
||||
gpio_set_pin_output(B15);
|
||||
|
||||
// inputs
|
||||
gpio_set_pin_input_low(A0);
|
||||
gpio_set_pin_input_low(A1);
|
||||
gpio_set_pin_input_low(A2);
|
||||
gpio_set_pin_input_low(A3);
|
||||
gpio_set_pin_input_low(A6);
|
||||
gpio_set_pin_input_low(A7);
|
||||
gpio_set_pin_input_low(B0);
|
||||
|
||||
mcp23018_errors = mcp23018_init_local(true);
|
||||
|
||||
if (!mcp23018_errors)
|
||||
{
|
||||
is_launching = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool matrix_scan_custom(matrix_row_t current_matrix[])
|
||||
{
|
||||
bool changed = false;
|
||||
// Attempt to reset the mcp23018 if it's not initialized
|
||||
if (mcp23018_errors)
|
||||
{
|
||||
if (++mcp23018_reset_loop > 0x1FFF)
|
||||
{
|
||||
if (io_expander_ready())
|
||||
{
|
||||
// If we managed to initialize the mcp23018 - we need to reinitialize the matrix / layer state. During an electric discharge the i2c peripherals might be in a weird state. Giving a delay and resetting the MCU allows to recover from this.
|
||||
mcp23018_reset_loop = 0;
|
||||
mcp23018_errors = mcp23018_init_local(false);
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
rgb_matrix_init();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scanning left and right side of the keyboard for key presses.
|
||||
// Left side is scanned by reading the gpio pins directly, right side is scanned by reading the mcp23018 registers.
|
||||
|
||||
matrix_row_t data = 0;
|
||||
for (uint8_t row = 0; row <= MCP_ROWS_PER_HAND; row++)
|
||||
{
|
||||
// strobe row
|
||||
switch (row)
|
||||
{
|
||||
case 0:
|
||||
gpio_write_pin_high(B10);
|
||||
break;
|
||||
case 1:
|
||||
gpio_write_pin_high(B11);
|
||||
break;
|
||||
case 2:
|
||||
gpio_write_pin_high(B12);
|
||||
break;
|
||||
case 3:
|
||||
gpio_write_pin_high(B13);
|
||||
break;
|
||||
case 4:
|
||||
gpio_write_pin_high(B14);
|
||||
break;
|
||||
case 5:
|
||||
gpio_write_pin_high(B15);
|
||||
break;
|
||||
case 6:
|
||||
break; // Left hand has 6 rows
|
||||
}
|
||||
|
||||
// Selecting the row on the right side of the keyboard.
|
||||
if (!mcp23018_errors)
|
||||
{
|
||||
// select row
|
||||
mcp23018_errors += !mcp23018_set_output(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTA, 0b01111111 & ~(1 << (row)));
|
||||
mcp23018_errors += !mcp23018_set_output(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTB, ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7));
|
||||
}
|
||||
// Reading the left side of the keyboard.
|
||||
if (row < MCP_ROWS_PER_HAND)
|
||||
{
|
||||
// i2c comm incur enough wait time
|
||||
if (mcp23018_errors)
|
||||
{
|
||||
// need wait to settle pin state
|
||||
matrix_io_delay();
|
||||
}
|
||||
// read col data
|
||||
data = ((gpio_read_pin(A0) << 0) | (gpio_read_pin(A1) << 1) | (gpio_read_pin(A2) << 2) | (gpio_read_pin(A3) << 3) | (gpio_read_pin(A6) << 4) | (gpio_read_pin(A7) << 5) | (gpio_read_pin(B0) << 6));
|
||||
// unstrobe row
|
||||
switch (row)
|
||||
{
|
||||
case 0:
|
||||
gpio_write_pin_low(B10);
|
||||
break;
|
||||
case 1:
|
||||
gpio_write_pin_low(B11);
|
||||
break;
|
||||
case 2:
|
||||
gpio_write_pin_low(B12);
|
||||
break;
|
||||
case 3:
|
||||
gpio_write_pin_low(B13);
|
||||
break;
|
||||
case 4:
|
||||
gpio_write_pin_low(B14);
|
||||
break;
|
||||
case 5:
|
||||
gpio_write_pin_low(B15);
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
}
|
||||
|
||||
if (current_matrix[row] != data)
|
||||
{
|
||||
current_matrix[row] = data;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reading the right side of the keyboard.
|
||||
if (!mcp23018_errors)
|
||||
{
|
||||
for (uint16_t i = 0; i < IO_EXPANDER_OP_DELAY; i++)
|
||||
{
|
||||
__asm__("nop");
|
||||
}
|
||||
uint8_t rx;
|
||||
mcp23018_errors += !mcp23018_readPins(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTB, &rx);
|
||||
data = ~(rx & 0b00111111);
|
||||
for (uint16_t i = 0; i < IO_EXPANDER_OP_DELAY; i++)
|
||||
{
|
||||
__asm__("nop");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = 0;
|
||||
}
|
||||
|
||||
if (raw_matrix_right[row] != data)
|
||||
{
|
||||
raw_matrix_right[row] = data;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t row = 0; row < MCP_ROWS_PER_HAND; row++)
|
||||
{
|
||||
current_matrix[11 - row] = 0;
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++)
|
||||
{
|
||||
current_matrix[11 - row] |= ((raw_matrix_right[6 - col] & (1 << row) ? 1 : 0) << col);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
// DO NOT REMOVE
|
||||
// Needed for proper wake/sleep
|
||||
void matrix_power_up(void)
|
||||
{
|
||||
bool temp_launching = is_launching;
|
||||
|
||||
matrix_init_custom();
|
||||
|
||||
is_launching = temp_launching;
|
||||
if (!temp_launching)
|
||||
{
|
||||
STATUS_LED_1(false);
|
||||
STATUS_LED_2(false);
|
||||
STATUS_LED_3(false);
|
||||
STATUS_LED_4(false);
|
||||
}
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++)
|
||||
{
|
||||
matrix[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_transport_connected(void)
|
||||
{
|
||||
return (bool)(mcp23018_errors == 0);
|
||||
}
|
||||
#pragma GCC pop_options
|
@ -21,19 +21,3 @@
|
||||
// for i2c expander, and ISSI
|
||||
#undef STM32_I2C_USE_I2C1
|
||||
#define STM32_I2C_USE_I2C1 TRUE
|
||||
|
||||
// for future hardware
|
||||
#undef STM32_I2C_USE_I2C2
|
||||
#define STM32_I2C_USE_I2C2 TRUE
|
||||
|
||||
// for audio
|
||||
#undef STM32_DAC_USE_DAC1_CH1
|
||||
#define STM32_DAC_USE_DAC1_CH1 TRUE
|
||||
#undef STM32_DAC_USE_DAC1_CH2
|
||||
#define STM32_DAC_USE_DAC1_CH2 TRUE
|
||||
#undef STM32_GPT_USE_TIM6
|
||||
#define STM32_GPT_USE_TIM6 TRUE
|
||||
#undef STM32_GPT_USE_TIM7
|
||||
#define STM32_GPT_USE_TIM7 TRUE
|
||||
#undef STM32_GPT_USE_TIM8
|
||||
#define STM32_GPT_USE_TIM8 TRUE
|
1
keyboards/zsa/voyager/post_rules.mk
Normal file
1
keyboards/zsa/voyager/post_rules.mk
Normal file
@ -0,0 +1 @@
|
||||
include keyboards/zsa/common/features.mk
|
40
keyboards/zsa/voyager/readme.md
Normal file
40
keyboards/zsa/voyager/readme.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Voyager
|
||||
|
||||
A next-gen split, ergonomic keyboard with an active left side, USB type C, and low profile switches.
|
||||
|
||||
* Keyboard Maintainer: [drashna](https://github.com/drashna), [ZSA](https://github.com/zsa/)
|
||||
* Hardware Supported: Voyager (STM32F303xC)
|
||||
* Hardware Availability: [ZSA Store](https://zsa.io/voyager/)
|
||||
|
||||
Make example for this keyboard (after setting up your build environment):
|
||||
|
||||
make zsa/voyager:default
|
||||
|
||||
Flashing example for this keyboard:
|
||||
|
||||
make zsa/voyager: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).
|
||||
|
||||
|
||||
## Voyager Customization
|
||||
|
||||
### Indicator LEDs
|
||||
|
||||
There are 4 functions for enabling and disabling the LEDs on the top of the boards. The functions are `STATUS_LED_1(bool)` through `STATUS_LED_4(bool)`, with the first LED being the top most LED on the left hand, and the fourth LED being the bottom most LED on the right side.
|
||||
|
||||
By default, the Indicator LEDs are used to indicate the layer state for the keyboard. If you wish to change this (and indicate caps/num/scroll lock status instead), then define `VOYAGER_USER_LEDS` in your `config.h` file.
|
||||
|
||||
### Detecting split / Gaming mode
|
||||
|
||||
To make it extra gaming friendly, you can configure what happens when you disconnect the right half. This is especially useful when using gaming unfriendly layers or layouts (e.g. home row mods, dvorak, colemak).
|
||||
|
||||
Example for enabling a specific layer while right side is disconnected:
|
||||
|
||||
```c
|
||||
void housekeeping_task_user(void) {
|
||||
if (!is_transport_connected()) {
|
||||
// set layer
|
||||
}
|
||||
}
|
||||
```
|
14
keyboards/zsa/voyager/rules.mk
Normal file
14
keyboards/zsa/voyager/rules.mk
Normal file
@ -0,0 +1,14 @@
|
||||
MCU_LDSCRIPT = voyager
|
||||
|
||||
CUSTOM_MATRIX = lite
|
||||
PROGRAM_CMD = $(call EXEC_DFU)
|
||||
DFU_ARGS = -d 3297:0791 -a 0 -s 0x08002000:leave
|
||||
DFU_SUFFIX_ARGS = -v 3297 -p 0791
|
||||
|
||||
VPATH += drivers/gpio
|
||||
SRC += matrix.c mcp23018.c
|
||||
I2C_DRIVER_REQUIRED = yes
|
||||
|
||||
SRC += \
|
||||
features/leader/leader.c \
|
||||
features/autocorrect/autocorrect.c
|
330
keyboards/zsa/voyager/voyager.c
Normal file
330
keyboards/zsa/voyager/voyager.c
Normal file
@ -0,0 +1,330 @@
|
||||
// Copyright 2023 ZSA Technology Labs, Inc <@zsa>
|
||||
// Copyright 2023 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
#ifdef COMMUNITY_MODULE_ORYX_ENABLE
|
||||
# include "oryx.h"
|
||||
#endif // COMMUNITY_MODULE_ORYX_ENABLE
|
||||
#ifdef COMMUNITY_MODULE_DEFAULTS_ENABLE
|
||||
# include "defaults.h"
|
||||
#endif
|
||||
|
||||
keyboard_config_t keyboard_config;
|
||||
|
||||
bool mcp23018_leds[2] = {0, 0};
|
||||
bool is_launching = false;
|
||||
|
||||
#if defined(DEFERRED_EXEC_ENABLE)
|
||||
# if defined(DYNAMIC_MACRO_ENABLE)
|
||||
deferred_token dynamic_macro_token = INVALID_DEFERRED_TOKEN;
|
||||
static uint32_t dynamic_macro_led(uint32_t trigger_time, void *cb_arg) {
|
||||
static bool led_state = true;
|
||||
if (!is_launching) {
|
||||
led_state = !led_state;
|
||||
STATUS_LED_3(led_state);
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
bool dynamic_macro_record_start_kb(int8_t direction) {
|
||||
if (!dynamic_macro_record_start_user(direction)) {
|
||||
return false;
|
||||
}
|
||||
if (dynamic_macro_token == INVALID_DEFERRED_TOKEN) {
|
||||
STATUS_LED_3(true);
|
||||
dynamic_macro_token = defer_exec(100, dynamic_macro_led, NULL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dynamic_macro_record_end_kb(int8_t direction) {
|
||||
if (!dynamic_macro_record_end_user(direction)) {
|
||||
return false;
|
||||
}
|
||||
if (cancel_deferred_exec(dynamic_macro_token)) {
|
||||
dynamic_macro_token = INVALID_DEFERRED_TOKEN;
|
||||
STATUS_LED_3(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
# endif
|
||||
|
||||
static uint32_t startup_exec(uint32_t trigger_time, void *cb_arg) {
|
||||
static uint8_t startup_loop = 0;
|
||||
|
||||
switch (startup_loop++) {
|
||||
case 0:
|
||||
STATUS_LED_1(true);
|
||||
STATUS_LED_2(false);
|
||||
STATUS_LED_3(false);
|
||||
STATUS_LED_4(false);
|
||||
break;
|
||||
case 1:
|
||||
STATUS_LED_2(true);
|
||||
break;
|
||||
case 2:
|
||||
STATUS_LED_3(true);
|
||||
break;
|
||||
case 3:
|
||||
STATUS_LED_4(true);
|
||||
break;
|
||||
case 4:
|
||||
STATUS_LED_1(false);
|
||||
break;
|
||||
case 5:
|
||||
STATUS_LED_2(false);
|
||||
break;
|
||||
case 6:
|
||||
STATUS_LED_3(false);
|
||||
break;
|
||||
case 7:
|
||||
STATUS_LED_4(false);
|
||||
break;
|
||||
case 8:
|
||||
is_launching = false;
|
||||
layer_state_set_kb(layer_state);
|
||||
return 0;
|
||||
}
|
||||
return 250;
|
||||
}
|
||||
#endif
|
||||
|
||||
void keyboard_pre_init_kb(void) {
|
||||
// Initialize Reset pins
|
||||
gpio_set_pin_input(A8);
|
||||
gpio_set_pin_output(A9);
|
||||
gpio_write_pin_low(A9);
|
||||
|
||||
gpio_set_pin_output(B5);
|
||||
gpio_set_pin_output(B4);
|
||||
gpio_set_pin_output(B3);
|
||||
|
||||
gpio_write_pin_low(B5);
|
||||
gpio_write_pin_low(B4);
|
||||
gpio_write_pin_low(B3);
|
||||
|
||||
keyboard_pre_init_user();
|
||||
}
|
||||
|
||||
layer_state_t layer_state_set_kb(layer_state_t state) {
|
||||
state = layer_state_set_user(state);
|
||||
#if !defined(VOYAGER_USER_LEDS)
|
||||
# ifdef COMMUNITY_MODULE_ORYX_ENABLE
|
||||
if (rawhid_state.status_led_control) {
|
||||
return state;
|
||||
}
|
||||
# endif
|
||||
if (is_launching || !keyboard_config.led_level) return state;
|
||||
uint8_t layer = get_highest_layer(state);
|
||||
STATUS_LED_1(layer & (1 << 0));
|
||||
STATUS_LED_2(layer & (1 << 1));
|
||||
STATUS_LED_3(layer & (1 << 2));
|
||||
# if !defined(CAPS_LOCK_STATUS)
|
||||
STATUS_LED_4(layer & (1 << 3));
|
||||
# endif
|
||||
#endif
|
||||
return state;
|
||||
}
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
// clang-format off
|
||||
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[RGB_MATRIX_LED_COUNT] = {
|
||||
/* Refer to IS31 manual for these locations
|
||||
* driver
|
||||
* | R location
|
||||
* | | G location
|
||||
* | | | B location
|
||||
* | | | | */
|
||||
{0, C2_2, C1_2, C4_3},
|
||||
{0, C2_3, C1_3, C3_3},
|
||||
{0, C2_4, C1_4, C3_4},
|
||||
{0, C2_5, C1_5, C3_5},
|
||||
{0, C2_6, C1_6, C3_6},
|
||||
{0, C2_7, C1_7, C3_7},
|
||||
{0, C2_8, C1_8, C3_8},
|
||||
{0, C8_1, C7_1, C9_1},
|
||||
{0, C8_2, C7_2, C9_2},
|
||||
{0, C8_3, C7_3, C9_3},
|
||||
{0, C8_4, C7_4, C9_4},
|
||||
{0, C8_5, C7_5, C9_5},
|
||||
{0, C8_6, C7_6, C9_6},
|
||||
{0, C2_10, C1_10, C4_11},
|
||||
{0, C2_11, C1_11, C3_11},
|
||||
{0, C2_12, C1_12, C3_12},
|
||||
{0, C2_13, C1_13, C3_13},
|
||||
{0, C2_14, C1_14, C3_14},
|
||||
{0, C2_15, C1_15, C3_15},
|
||||
{0, C2_16, C1_16, C3_16},
|
||||
{0, C8_9, C7_9, C9_9},
|
||||
{0, C8_10, C7_10, C9_10},
|
||||
{0, C8_11, C7_11, C9_11},
|
||||
{0, C8_12, C7_12, C9_12},
|
||||
{0, C8_13, C7_13, C9_13},
|
||||
{0, C8_14, C7_14, C9_14},
|
||||
|
||||
{1, C2_7, C1_7, C3_7},
|
||||
{1, C2_6, C1_6, C3_6},
|
||||
{1, C2_5, C1_5, C3_5},
|
||||
{1, C2_4, C1_4, C3_4},
|
||||
{1, C2_3, C1_3, C3_3},
|
||||
{1, C2_2, C1_2, C4_3},
|
||||
|
||||
{1, C8_5, C7_5, C9_5},
|
||||
{1, C8_4, C7_4, C9_4},
|
||||
{1, C8_3, C7_3, C9_3},
|
||||
{1, C8_2, C7_2, C9_2},
|
||||
{1, C8_1, C7_1, C9_1},
|
||||
{1, C2_8, C1_8, C3_8},
|
||||
|
||||
{1, C2_14, C1_14, C3_14},
|
||||
{1, C2_13, C1_13, C3_13},
|
||||
{1, C2_12, C1_12, C3_12},
|
||||
{1, C2_11, C1_11, C3_11},
|
||||
{1, C2_10, C1_10, C4_11},
|
||||
{1, C8_6, C7_6, C9_6},
|
||||
|
||||
{1, C8_12, C7_12, C9_12},
|
||||
{1, C8_11, C7_11, C9_11},
|
||||
{1, C8_10, C7_10, C9_10},
|
||||
{1, C8_9, C7_9, C9_9},
|
||||
{1, C2_16, C1_16, C3_16},
|
||||
{1, C2_15, C1_15, C3_15},
|
||||
|
||||
{1, C8_14, C7_14, C9_14},
|
||||
{1, C8_13, C7_13, C9_13},
|
||||
};
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#ifdef SWAP_HANDS_ENABLE
|
||||
// swap-hands action needs a matrix to define the swap
|
||||
// clang-format off
|
||||
const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Left hand, matrix positions */
|
||||
{{6,6}, {5,6}, {4,6}, {3,6}, {2,6}, {1,6},{0,6}},
|
||||
{{6,7}, {5,7}, {4,7}, {3,7}, {2,7}, {1,7},{0,7}},
|
||||
{{6,8}, {5,8}, {4,8}, {3,8}, {2,8}, {1,8},{0,8}},
|
||||
{{6,9}, {5,9}, {4,9}, {3,9}, {2,9}, {1,9},{0,9}},
|
||||
{{6,10},{5,10},{4,10},{3,10},{2,10},{1,10},{0,10}},
|
||||
{{6,11},{5,11},{4,11},{3,11},{2,11},{1,11},{0,11}},
|
||||
/* Right hand, matrix positions */
|
||||
{{6,0}, {5,0}, {4,0}, {3,0}, {2,0}, {1,0},{0,0}},
|
||||
{{6,1}, {5,1}, {4,1}, {3,1}, {2,1}, {1,1},{0,1}},
|
||||
{{6,2}, {5,2}, {4,2}, {3,2}, {2,2}, {1,2},{0,2}},
|
||||
{{6,3}, {5,3}, {4,3}, {3,3}, {2,3}, {1,3},{0,3}},
|
||||
{{6,4}, {5,4}, {4,4}, {3,4}, {2,4}, {1,4},{0,4}},
|
||||
{{6,5}, {5,5}, {4,5}, {3,5}, {2,5}, {1,5},{0,5}},
|
||||
};
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#ifdef CAPS_LOCK_STATUS
|
||||
bool led_update_kb(led_t led_state) {
|
||||
bool res = led_update_user(led_state);
|
||||
if (res) {
|
||||
STATUS_LED_4(led_state.caps_lock);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
if (!process_record_user(keycode, record)) {
|
||||
return false;
|
||||
}
|
||||
switch (keycode) {
|
||||
#if !defined(VOYAGER_USER_LEDS)
|
||||
case LED_LEVEL:
|
||||
if (record->event.pressed) {
|
||||
keyboard_config.led_level ^= 1;
|
||||
eeconfig_update_kb(keyboard_config.raw);
|
||||
if (keyboard_config.led_level) {
|
||||
layer_state_set_kb(layer_state);
|
||||
} else {
|
||||
STATUS_LED_1(false);
|
||||
STATUS_LED_2(false);
|
||||
STATUS_LED_3(false);
|
||||
STATUS_LED_4(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
case TOGGLE_LAYER_COLOR:
|
||||
if (record->event.pressed) {
|
||||
keyboard_config.disable_layer_led ^= 1;
|
||||
if (keyboard_config.disable_layer_led) rgb_matrix_set_color_all(0, 0, 0);
|
||||
eeconfig_update_kb(keyboard_config.raw);
|
||||
}
|
||||
break;
|
||||
case RGB_TOG:
|
||||
case QK_RGB_MATRIX_TOGGLE:
|
||||
if (record->event.pressed) {
|
||||
switch (rgb_matrix_get_flags()) {
|
||||
case LED_FLAG_ALL: {
|
||||
rgb_matrix_set_flags(LED_FLAG_NONE);
|
||||
rgb_matrix_set_color_all(0, 0, 0);
|
||||
} break;
|
||||
default: {
|
||||
rgb_matrix_set_flags(LED_FLAG_ALL);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void keyboard_post_init_kb(void) {
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
rgb_matrix_enable_noeeprom();
|
||||
#endif
|
||||
|
||||
keyboard_config.raw = eeconfig_read_kb();
|
||||
|
||||
if (!keyboard_config.led_level && !keyboard_config.led_level_res) {
|
||||
keyboard_config.led_level = true;
|
||||
keyboard_config.led_level_res = 0b11;
|
||||
eeconfig_update_kb(keyboard_config.raw);
|
||||
}
|
||||
#if defined(DEFERRED_EXEC_ENABLE)
|
||||
is_launching = true;
|
||||
defer_exec(500, startup_exec, NULL);
|
||||
#endif
|
||||
keyboard_post_init_user();
|
||||
}
|
||||
|
||||
void eeconfig_init_kb(void) { // EEPROM is getting reset!
|
||||
keyboard_config.raw = 0;
|
||||
keyboard_config.led_level = true;
|
||||
keyboard_config.led_level_res = 0b11;
|
||||
eeconfig_update_kb(keyboard_config.raw);
|
||||
eeconfig_init_user();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
// The ignition bootloader is checking for a high signal on A8 for 100ms when powering on the board.
|
||||
// Setting both A8 and A9 high will charge the capacitor quickly.
|
||||
// Setting A9 low before reset will cause the capacitor to discharge
|
||||
// thus making the bootloder unlikely to trigger twice between power cycles.
|
||||
gpio_set_pin_output_push_pull(A9);
|
||||
gpio_set_pin_output_push_pull(A8);
|
||||
gpio_write_pin_high(A9);
|
||||
gpio_write_pin_high(A8);
|
||||
wait_ms(500);
|
||||
gpio_write_pin_low(A9);
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void mcu_reset(void) {
|
||||
gpio_set_pin_output_push_pull(A9);
|
||||
gpio_set_pin_output_push_pull(A8);
|
||||
gpio_write_pin_low(A8);
|
||||
gpio_write_pin_low(A9);
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
31
keyboards/zsa/voyager/voyager.h
Normal file
31
keyboards/zsa/voyager/voyager.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2023 ZSA Technology Labs, Inc <@zsa>
|
||||
// Copyright 2023 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "quantum.h"
|
||||
|
||||
extern bool mcp23018_leds[];
|
||||
|
||||
#define MCP23018_DEFAULT_ADDRESS 0b0100000
|
||||
|
||||
#define STATUS_LED_1(status) gpio_write_pin(B5, (bool)(status))
|
||||
#define STATUS_LED_2(status) gpio_write_pin(B4, (bool)(status))
|
||||
#define STATUS_LED_3(status) mcp23018_leds[0] = (bool)(status)
|
||||
#define STATUS_LED_4(status) mcp23018_leds[1] = (bool)(status)
|
||||
|
||||
typedef union {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
bool disable_layer_led : 1;
|
||||
bool led_level : 1;
|
||||
uint8_t led_level_res : 2; // DO NOT REMOVE
|
||||
uint8_t navigator_cpi : 3;
|
||||
};
|
||||
} keyboard_config_t;
|
||||
|
||||
extern keyboard_config_t keyboard_config;
|
||||
|
||||
bool is_transport_connected(void);
|
Reference in New Issue
Block a user