Compare commits

..

2 Commits

Author SHA1 Message Date
Mark e0d54f8e79
Minor cleanup 2023-12-31 10:29:30 -08:00
Mark 0856908bec
Added voyager code 2023-12-31 10:28:51 -08:00
33 changed files with 2160 additions and 42 deletions

View File

@ -14,7 +14,12 @@
"xstddef": "c",
"type_traits": "c",
"utility": "c",
"ranges": "c"
"ranges": "c",
"compare": "c",
"cstdint": "c",
"chrono": "c",
"typeindex": "c",
"typeinfo": "c"
},
"C_Cpp.errorSquiggles": "disabled",
}

View File

@ -1,4 +1,13 @@
default:
voyager:
@mkdir -p "$$(pwd)/output"
docker run -it --rm \
--user $$(id -u):$$(id -g) \
-v "$$(pwd)/output:/build_output" \
-v "$$(pwd)/keyboards:/qmk_firmware/keyboards:ro" \
-e QMK_TARGET="betalupi_voyager:default" \
git.betalupi.com/mark/qmk
ergodox:
@mkdir -p "$$(pwd)/output"
docker run -it --rm \
--user $$(id -u):$$(id -g) \
@ -7,11 +16,11 @@ default:
-e QMK_TARGET="betalupi_ergodox:default" \
git.betalupi.com/mark/qmk
upload:
ergodox_upload:
wally-cli output/betalupi_ergodox_default.hex
docker:
docker build docker -t git.betalupi.com/mark/qmk
.PHONY: docker upload default
.PHONY: voyager ergodox ergodox_upload docker

View File

@ -1,9 +1,3 @@
// ORDER MATTERS!
// Don't forget how QMK layers work...
//
// Learned that the hard way.
// First layer will be "default" layer in QMK.
// Second will have index 1, etc. See layers.h

View File

@ -1,38 +1,25 @@
# MCU name
MCU = atmega32u4
BOOTLOADER = halfkay
# Enable raw HID for bi-directional communication
RAW_ENABLE = yes
# Bootloader selection
# Teensy halfkay
# Pro Micro caterina
# Atmel DFU atmel-dfu
# LUFA DFU lufa-dfu
# QMK DFU qmk-dfu
# ATmega32A bootloadHID
# ATmega328P USBasp
BOOTLOADER = halfkay
# Build Options
# comment out to disable the options.
#
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
MOUSEKEY_ENABLE = no # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
CUSTOM_MATRIX = lite # Custom matrix file for the ErgoDox EZ
NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
UNICODE_ENABLE = no # Unicode
SWAP_HANDS_ENABLE= no # Allow swapping hands of keyboard
SLEEP_LED_ENABLE = no
API_SYSEX_ENABLE = no
MOUSE_SHARED_EP = no
MAGIC_ENABLE = no
LEADER_ENABLE = no
TAP_DANCE_ENABLE = yes
AUDIO_SUPPORTED = no
BOOTMAGIC_ENABLE = no
MOUSEKEY_ENABLE = no
EXTRAKEY_ENABLE = yes
CONSOLE_ENABLE = no
COMMAND_ENABLE = no
CUSTOM_MATRIX = lite
NKRO_ENABLE = yes
UNICODE_ENABLE = no
SWAP_HANDS_ENABLE = no
SLEEP_LED_ENABLE = no
API_SYSEX_ENABLE = no
MOUSE_SHARED_EP = no
MAGIC_ENABLE = no
LEADER_ENABLE = no
TAP_DANCE_ENABLE = yes
AUDIO_SUPPORTED = no
BACKLIGHT_SUPPORTED = no
DEBOUNCE_TYPE = sym_eager_pr
@ -59,8 +46,7 @@ LTO_ENABLE = yes
# Enable keyboard-specific effects
RGB_MATRIX_CUSTOM_KB = yes
# FROM glow dir
# From glow dir
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = is31fl3731
RGBLIGHT_ENABLE = yes

View File

@ -0,0 +1,221 @@
#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();
}

View File

@ -0,0 +1,87 @@
#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);

View File

@ -0,0 +1,63 @@
#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

View File

@ -0,0 +1,39 @@
#pragma once
#ifdef ENABLE_BETA_LEADER
#include "quantum.h"
bool beta_process_leader(uint16_t keycode, keyrecord_t *record);
void beta_leader_start(void);
void beta_leader_end(void);
bool beta_leader_check(void);
void beta_qk_leader_check(void);
void beta_qk_leader_start(void);
#define BETA_LEADER_EXTERNS() \
extern bool beta_leading; \
extern uint16_t beta_leader_time; \
extern uint16_t beta_leader_sequence[5]; \
extern uint8_t beta_leader_sequence_size
// Normal sequence
// These do the same thing as SEQ_X_KEYS from qmk.
#define BETA_SEQ_1_LONG(key) if (beta_leader_sequence[0] == (key) && beta_leader_sequence[1] == 0 && beta_leader_sequence[2] == 0 && beta_leader_sequence[3] == 0 && beta_leader_sequence[4] == 0 && timer_elapsed(beta_leader_time) > LEADER_TIMEOUT)
#define BETA_SEQ_2_LONG(key1, key2) if (beta_leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2) && beta_leader_sequence[2] == 0 && beta_leader_sequence[3] == 0 && beta_leader_sequence[4] == 0 && timer_elapsed(beta_leader_time) > LEADER_TIMEOUT)
#define BETA_SEQ_3_LONG(key1, key2, key3) if (beta_leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2) && beta_leader_sequence[2] == (key3) && beta_leader_sequence[3] == 0 && beta_leader_sequence[4] == 0 && timer_elapsed(beta_leader_time) > LEADER_TIMEOUT)
#define BETA_SEQ_4_LONG(key1, key2, key3, key4) if (beta_leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2) && beta_leader_sequence[2] == (key3) && beta_leader_sequence[3] == (key4) && beta_leader_sequence[4] == 0 && timer_elapsed(beta_leader_time) > LEADER_TIMEOUT)
#define BETA_SEQ_5_LONG(key1, key2, key3, key4, key5) if (leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2) && beta_leader_sequence[2] == (key3) && beta_leader_sequence[3] == (key4) && beta_leader_sequence[4] == (key5) && timer_elapsed(beta_leader_time) > LEADER_TIMEOUT)
// Short-circuit sequence
// These match as soon as a matching sequence is seen,
// not waiting for the leader timeout. They thus register
// immediately, but cannot be used in longer sequences.
#define BETA_SEQ_1_SHORT(key) if (beta_leader_sequence[0] == (key))
#define BETA_SEQ_2_SHORT(key1, key2) if (beta_leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2))
#define BETA_SEQ_3_SHORT(key1, key2, key3) if (beta_leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2))
#define BETA_SEQ_4_SHORT(key1, key2, key3, key4) if (beta_leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2))
#define BETA_SEQ_5_SHORT(key1, key2, key3, key4, key5) if (beta_leader_sequence[0] == (key1) && beta_leader_sequence[1] == (key2))
#endif

View File

@ -0,0 +1,103 @@
#ifdef ENABLE_BETA_LEADER
#include "beta_leader.h"
#include <string.h>
#ifndef LEADER_TIMEOUT
#define LEADER_TIMEOUT 300
#endif
__attribute__((weak)) void beta_leader_start(void) {}
__attribute__((weak)) void beta_leader_end(void) {}
__attribute__((weak)) bool beta_leader_check(void) { return true; }
// Leader key stuff
bool beta_leading = false;
uint16_t beta_leader_time = 0;
bool beta_leader_change = false;
uint16_t beta_leader_sequence[5] = {0, 0, 0, 0, 0};
uint8_t beta_leader_sequence_size = 0;
void beta_qk_leader_start(void) {
if (beta_leading) {
return;
}
beta_leader_start();
beta_leading = true;
beta_leader_time = timer_read();
beta_leader_sequence_size = 0;
beta_leader_change = false; // If true, run
memset(beta_leader_sequence, 0, sizeof(beta_leader_sequence));
}
void beta_qk_leader_check() {
#ifdef LEADER_NO_TIMEOUT
bool timeout = (beta_leading && beta_leader_sequence_size > 0 && timer_elapsed(beta_leader_time) > LEADER_TIMEOUT);
#else
bool timeout = (beta_leading && timer_elapsed(beta_leader_time) > LEADER_TIMEOUT);
#endif
if (beta_leader_change || timeout) {
beta_leader_change = false;
if (
beta_leader_sequence[beta_leader_sequence_size - 1] == (QK_LEAD)
) {
beta_leading = false;
beta_leader_end();
return;
}
if (timeout) {
beta_leading = false;
beta_leader_end();
}
if (!beta_leader_check()) {
beta_leading = false;
beta_leader_end();
};
}
}
bool beta_process_leader(uint16_t keycode, keyrecord_t *record) {
// Leader key set-up
if (record->event.pressed) {
if (beta_leading) {
# ifndef LEADER_NO_TIMEOUT
if (timer_elapsed(beta_leader_time) < LEADER_TIMEOUT)
# endif // LEADER_NO_TIMEOUT
{
# ifndef LEADER_KEY_STRICT_KEY_PROCESSING
if (IS_QK_MOD_TAP(keycode)) {
keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
} else if (IS_QK_LAYER_TAP(keycode)) {
keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
}
# endif // LEADER_KEY_STRICT_KEY_PROCESSING
if (beta_leader_sequence_size < ARRAY_SIZE(beta_leader_sequence)) {
beta_leader_sequence[beta_leader_sequence_size] = keycode;
beta_leader_sequence_size++;
beta_leader_change = true;
} else {
beta_leading = false;
beta_leader_end();
return true;
}
# ifdef LEADER_PER_KEY_TIMING
beta_leader_time = timer_read();
# endif
return false;
}
} else {
if (keycode == QK_LEADER) {
beta_qk_leader_start();
}
}
}
return true;
}
#endif

View File

@ -0,0 +1,22 @@
/* Copyright 2021 QMK
*
* 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 3 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#define HAL_USE_I2C TRUE
#define HAL_USE_GPT TRUE
#define HAL_USE_DAC TRUE
#include_next <halconf.h>

View File

@ -0,0 +1,230 @@
{
"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
}
]
}
}
}

Binary file not shown.

View File

@ -0,0 +1,38 @@
#define ENABLE_BETA_LEADER
// No timeout after initial leader key press
#define LEADER_NO_TIMEOUT
// 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_8BIT
#define RGB_MATRIX_STARTUP_SPD 60

View File

@ -0,0 +1,183 @@
#include QMK_KEYBOARD_H
#include "version.h"
#include "keymap_russian.h"
#include "keymap_us_international.h"
// Values that should not be saved to git.
// There should be a`secrets.h` in this directory
// with the following contents:
//
// #define SECRET_EMAIL "value"
// #define SECRET_GMAIL "value"
// #define SECRET_SCHOOL_EMAIL "value"
#include "secrets.h"
// Macro keycodes
enum custom_keycodes {
M_SHUTDOWN = BETA_SAFE_RANGE,
// Macros
M_RESETWM,
M_RU_CTRL,
M_RU_ALT,
M_GUI,
// Special characters.
// M_SPECIAL_TOP and M_SPECIAL_BOTTOM are
// bounds used to parse these. Only special
// characters should be between them.
//
// Сharacters here should be in the same
// order as they are in the host inteface.
M_SPECIAL_TOP,
M_SC_GRAVE,
M_SC_TILD,
M_SC_QUOT,
M_SC_LBR,
M_SC_RBR,
M_SC_LCBR,
M_SC_RCBR,
M_SC_LKVCH,
M_SC_RKVCH,
M_SPECIAL_BOTTOM
};
// Tapdance keycodes
enum tap_dance_codes {
TD_WMLAYOUT,
TD_SCREENSHOT,
TD_OCR
};
// LED colors
#define LC_OFF { 0, 0, 0}
#define LC_GRN { 85, 203, 158}
#define LC_YLW { 32, 176, 255}
#define LC_PNK {243, 222, 234}
#define LC_CYN {134, 255, 213}
#define LC_ORN { 14, 255, 255}
#define LC_WHT { 0, 0, 150}
#define LC_RED { 0, 255, 145}
#define LC_BLU {153, 255, 153}
#define LC_RU_B LC_HSV( 0, 0, 165)
#define LC_RU_G LC_HSV(153, 255, 153)
#define LC_RU_K LC_HSV( 0, 255, 145)
#ifdef ENABLE_HID_SPELLCHECK
#include "features/hid_spellcheck.h"
#endif
#ifdef ENABLE_AUTOCORRECT
#include "features/autocorrect/autocorrect.h"
#endif
#ifdef ENABLE_BETA_LEADER
#include "features/leader/beta_leader.h"
#endif
//#include "features/beta_rawhid.h"
/*
// Send a special character.
// Returns false if character was caught, true otherwise.
bool send_special_character(uint16_t keycode) {
if ( (keycode > M_SPECIAL_TOP) && (keycode < M_SPECIAL_BOTTOM) ) {
hid_send_special_char(keycode - M_SPECIAL_TOP - 1);
return false;
}
return true;
}*/
const uint16_t PROGMEM test_combo2[] = {KC_D, KC_F, COMBO_END};
const uint16_t PROGMEM test_combo3[] = {KC_M, KC_P, COMBO_END};
combo_t key_combos[] = {
COMBO(test_combo2, KC_TAB),
COMBO(test_combo3, KC_RIGHT),
};
void matrix_scan_user(void) {
#ifdef ENABLE_BETA_LEADER
beta_qk_leader_check();
#endif
}
// Include all other parts of configuration
#include "layers/layers.c"
#include "parts/leader.c"
//#include "parts/tapdance.c"
// Process macros.
// Return FALSE to halt key processing,
// Return TRUE to allow QMK to handle keypress.
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#ifdef ENABLE_BETA_LEADER
if (!beta_process_leader(keycode, record)) { return false; }
#endif
#ifdef ENABLE_HID_SPELLCHECK
if (!process_spellcheck(keycode, record)) { return false; }
#endif
#ifdef ENABLE_AUTOCORRECT
if (!process_autocorrection(keycode, record)) { return false; }
#endif
// Handle special chars
//if (record->event.pressed) {
// if (!send_special_character(keycode)) { return false; }
//}
// Handle macros
switch (keycode) {
case M_RESETWM:
if (record->event.pressed) {
SEND_STRING(SS_LCTL(SS_LGUI(SS_LSFT(SS_TAP(X_R)))));
}
return false;
// Workaround for one-shot LGUI key.
// Using just LGUI with LAYER_DESKTOP as OSL
// does not allow you to hold lgui. This does.
case M_GUI:
if (record->event.pressed) {
register_code16(KC_LGUI);
} else {
unregister_code16(KC_LGUI);
}
return false;
case M_SHUTDOWN:
if (record->event.pressed) {
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_ALT:
if (record->event.pressed) {
layer_move(LAYER_MAIN);
register_code16(KC_LALT);
} else {
unregister_code16(KC_LALT);
layer_move(LAYER_RUSSIAN);
}
return false;*/
}
return true;
}

View File

@ -0,0 +1,10 @@
# EditorConfig is awesome: https://EditorConfig.org
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false

View File

@ -0,0 +1,45 @@
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(ARROWS)
#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_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_TRNS, KC_NO, KC_NO, KC_UP, KC_NO, KC_PGUP, \
KC_TRNS, LALT(KC_LCTL), KC_LEFT, KC_DOWN, KC_RIGHT, KC_PGDN, \
KC_LCTL, LGUI(KC_LCTL), KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, \
\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
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_OFF, LC_ORN, \
LC_OFF, LC_ORN, LC_GRN, LC_GRN, LC_GRN, LC_ORN, \
LC_OFF, LC_ORN, LC_OFF, LC_OFF, LC_RED, 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

View File

@ -0,0 +1,49 @@
// 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, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, 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

View File

@ -0,0 +1,48 @@
// See symbols.h for docs
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(FKEYS)
#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(\
TO(LAYER_MAIN), KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, \
KC_NO, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, \
\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
\
KC_NO, KC_NO \
)
BETA_LAYER_MAGIC_MACRO
#endif
#ifdef BETA_LAYER_LEDS
#define BETA_LAYER_CONTEXT_DATA {\
LC_RED, LC_BLU, LC_BLU, LC_BLU, LC_BLU, LC_BLU, \
LC_OFF, LC_BLU, LC_BLU, LC_BLU, LC_BLU, LC_BLU, \
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, 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

View File

@ -0,0 +1,29 @@
// See symbols.h for docs
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(KEYBOARD)
#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(\
TO(LAYER_MAIN), KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
RGB_MOD, RGB_TOG, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, \
\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO \
)
BETA_LAYER_MAGIC_MACRO
#endif
#undef BETA_LAYER_CONTEXT_DATA
#undef BETA_LAYER_MAGIC_MACRO

View File

@ -0,0 +1,28 @@
// ORDER MATTERS!
// Don't forget how QMK layers work...
//
// Learned that the hard way.
// First layer will be "default" layer in QMK.
// Second will have index 1, etc. See layers.h
// These MUST be first.
// (For example, LAYER_ARROWS overlays on top of LAYER_MAIN)
#include "main.h"
#include "ctrl.h"
#include "numbers.h" // Must be under symbols and arrows
// The order of the layers below doesn't matter,
// since they avoid transparent keys.
#include "symbols.h"
#include "arrows.h"
#include "macros.h"
#include "fkeys.h"
#include "keyboard.h"

View File

@ -0,0 +1,48 @@
// See symbols.h for docs
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(MACROS)
#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(\
TO(LAYER_MAIN), LGUI(KC_1), LGUI(KC_2), LGUI(KC_3), LGUI(KC_4), LGUI(KC_5),\
KC_LGUI, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
KC_MEDIA_PLAY_PAUSE, KC_MEDIA_NEXT_TRACK, KC_NO, KC_NO, OSL(LAYER_FKEYS), KC_NO,\
KC_NO, KC_MEDIA_PREV_TRACK, KC_NO, LGUI(LSFT(KC_C)), KC_NO, KC_NO,\
LGUI(KC_ENTER), LGUI(KC_BSLS), \
\
M_SHUTDOWN, KC_NO, KC_NO, KC_NO, KC_NO, LCTL(LGUI(LSFT(KC_R))), \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
KC_NO, KC_NO \
)
BETA_LAYER_MAGIC_MACRO
#endif
#ifdef BETA_LAYER_LEDS
#define BETA_LAYER_CONTEXT_DATA {\
LC_RED, LC_PNK, LC_PNK, LC_PNK, LC_PNK, LC_PNK, \
LC_CYN, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_GRN, LC_GRN, LC_OFF, LC_OFF, LC_BLU, LC_OFF, \
LC_OFF, LC_GRN, LC_OFF, LC_ORN, LC_OFF, LC_OFF, \
LC_PNK, LC_PNK, \
LC_RED, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_ORN, \
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

View File

@ -0,0 +1,39 @@
// 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:
// screenshot keys
// russian
// keyboard led controls
// 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, \
LM(MOD_LCTL, 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_TAB), \
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

View File

@ -0,0 +1,49 @@
// See symbols.h for docs
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(NUMBERS)
#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(\
TO(LAYER_MAIN), KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
KC_TRNS, KC_1, KC_2, KC_3, KC_4, KC_5, \
KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_0, \
KC_TRNS, KC_NO, KC_NO, KC_DOT, KC_COMMA, KC_NO,\
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_RED, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_GRN, LC_GRN, LC_GRN, LC_GRN, LC_GRN, \
LC_OFF, LC_GRN, LC_GRN, LC_GRN, LC_GRN, LC_GRN, \
LC_OFF, LC_OFF, LC_OFF, LC_PNK, LC_PNK, 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

View File

@ -0,0 +1,112 @@
// Layers are defined in macros,
// so that all supporting code can be
// auto-generated by the preprocessor.
//
// When making a new layer, make sure you update EVERY
// reference to BETA_LAYER() with your layer's name!
// This macro isn't used anywhere else.
// It's here for convenience, so we only have to write
// the layer name in one place.
#define BETA_LAYER_MAGIC_MACRO BETA_LAYER(SYMBOLS)
// What OS keyboard layout this layer is designed for.
// See extra_mappings.h for possible values.
//
// Every layer must have this section.
#ifdef BETA_LAYER_LAYOUTS
#define BETA_LAYER_CONTEXT_DATA LAYOUT_EN
BETA_LAYER_MAGIC_MACRO
#endif
// If BETA_LAYER_NAME is defined, the preprocessor is making
// enums for this layer. See keymap.h.
//
// IMPORTANT:
// Things will break if BETA_LAYER_MAGIC_MACRO is written outside #ifdef/#endif guards.
// If BETA_LAYER_KEYS is defined, the preprocessor is either...
// - making LAYER_* enums (see keymap.h)
// - filling the keymap array (see keymap.c)
//
// Every layer must have this section.
#ifdef BETA_LAYER_KEYS
#define BETA_LAYER_CONTEXT_DATA LAYOUT_voyager(\
KC_NO, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC,\
KC_NO, KC_GRAVE, KC_LPRN, KC_RPRN, KC_QUES, KC_LCBR,\
KC_NO, KC_TILD, KC_QUOT, KC_COMMA, KC_DOT, KC_DQUO,\
KC_NO, KC_NO, KC_LBRC, KC_RBRC, KC_EXLM, KC_RCBR,\
\
KC_NO, KC_NO,\
\
\
KC_CIRC, KC_AMPR, KC_ASTR, KC_NO, KC_NO, KC_NO,\
KC_LABK, KC_RABK, KC_SLASH, KC_NO, KC_BSLS, KC_NO,\
KC_UNDS, KC_MINUS, KC_COLN, KC_TRANSPARENT, KC_PIPE, KC_NO,\
KC_EQUAL, KC_PLUS, KC_SCLN, KC_NO, KC_NO, KC_NO,\
\
KC_NO, KC_NO\
)
// This is important.d
// The magic macro MUST be here, AFTER the keymap data.
BETA_LAYER_MAGIC_MACRO
#endif
// If BETA_LAYER_KEYS is defined, the preprocessor is either...
// - making LAYER_*_LEDS enums (see keymap.h)
// - filling the ledmap array (see keymap.c)
// - building the layer color switch statement (see keymap.c)
//
// This section is optional. If it is missing, this layer will not have
// an RGBMatrix color.
#ifdef BETA_LAYER_LEDS
#define BETA_LAYER_CONTEXT_DATA {\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_ORN, LC_CYN, LC_CYN, LC_PNK, LC_CYN, \
LC_OFF, LC_ORN, LC_PNK, LC_PNK, LC_PNK, LC_PNK, \
LC_OFF, LC_OFF, LC_CYN, LC_CYN, LC_PNK, LC_CYN, \
LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_GRN, LC_GRN, LC_CYN, LC_OFF, LC_CYN, LC_OFF, \
LC_CYN, LC_GRN, LC_PNK, LC_RED, LC_CYN, LC_OFF, \
LC_GRN, LC_GRN, LC_PNK, 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
// If BETA_LAYER_INDICATORS is defined, the preprocessor is
// building the indicator led switch statement (see keymap.c)
//
// This should be a `case` statement that looks exactly like the following example.
//
// This section is optional. If it is missing, this layer will
// not set indicator leds.
/*
#ifdef BETA_LAYER_INDICATORS
case LAYER_MAGIC_MACRO:
ergodox_right_led_1_on();
//ergodox_right_led_2_on();
//ergodox_right_led_3_on();
break;
#endif
*/
// Cleanup.
// This is not optional,
// we MUST undef these here so the next layer
// we load can re-define them.
#undef BETA_LAYER_CONTEXT_DATA
#undef BETA_LAYER_MAGIC_MACRO

View File

@ -0,0 +1,152 @@
//#include "extra_mappings.h"
#define LAYER_INCLUDE_FILE "definitions/layers.inc"
/*
Setup
*/
// Generate layer ids
#define BETA_LAYER_KEYS
#define BETA_LAYER(name) LAYER_##name,
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
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
};
#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
};
#undef BETA_LAYER
#undef BETA_LAYER_LEDS
/*
// Create os layout array
#define BETA_LAYER_LAYOUTS
#define BETA_LAYER(name) [LAYER_##name] = BETA_LAYER_CONTEXT_DATA,
uint8_t layer_layouts[] = {
#include LAYER_INCLUDE_FILE
};
#undef BETA_LAYER
#undef BETA_LAYER_LAYOUTS
*/
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 );
float f = (float)rgb_matrix_config.hsv.v / UINT8_MAX;
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) {
return true;
}
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;
#include LAYER_INCLUDE_FILE
#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;
}
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);
rgb_matrix_set_color(18, 0x00, 0xFF, 0x00);
rgb_matrix_set_color(19, 0x00, 0xFF, 0x00);
}
return true;
}
layer_state_t layer_state_set_user(layer_state_t state) {
uint8_t layer = biton32(state);
STATUS_LED_1(false);
STATUS_LED_2(false);
STATUS_LED_3(false);
STATUS_LED_4(false);
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
default:
break;
}
return state;
};

View File

@ -0,0 +1,37 @@
#include "features/leader/beta_leader.h"
BETA_LEADER_EXTERNS();
void beta_leader_start(void) {}
void beta_leader_end(void) {}
bool beta_leader_check(void) {
BETA_SEQ_2_SHORT(KC_E, KC_M) {
SEND_STRING(SECRET_EMAIL);
return false;
}
BETA_SEQ_2_SHORT(KC_G, KC_M) {
SEND_STRING(SECRET_GMAIL);
return false;
}
BETA_SEQ_2_SHORT(KC_L, KC_I) {
SEND_STRING(SECRET_SCHOOL_EMAIL);
return false;
}
BETA_SEQ_2_SHORT(KC_K, KC_B) {
layer_move(LAYER_KEYBOARD);
return false;
}
BETA_SEQ_1_SHORT(KC_N) {
layer_move(LAYER_NUMBERS);
return false;
}
return true;
}

View File

@ -0,0 +1,37 @@
void td_screenshot(tap_dance_state_t *state, void *user_data) {
if (state->count == 1) {
tap_code16(KC_PSCR);
} else if (state->count == 2) {
tap_code16(LSFT(KC_PSCR));
} else if (state->count == 3) {
tap_code16(LALT(KC_PSCR));
} else {
reset_tap_dance(state);
}
}
void td_ocr(tap_dance_state_t *state, void *user_data) {
if (state->count == 1) {
tap_code16(LCTL(KC_PSCR));
} else if (state->count == 2) {
tap_code16(LCTL(LSFT(KC_PSCR)));
} else {
reset_tap_dance(state);
}
}
void td_wmlayout(tap_dance_state_t *state, void *user_data) {
if (state->count == 1) {
tap_code16(LGUI(KC_COMMA));
} else if (state->count == 2) {
tap_code16(LGUI(KC_DOT));
} else {
reset_tap_dance(state);
}
}
tap_dance_action_t tap_dance_actions[] = {
[TD_WMLAYOUT] = ACTION_TAP_DANCE_FN(td_wmlayout),
[TD_SCREENSHOT] = ACTION_TAP_DANCE_FN(td_screenshot),
[TD_OCR] = ACTION_TAP_DANCE_FN(td_ocr),
};

View File

@ -0,0 +1,3 @@
# rules.mk overrides
TAP_DANCE_ENABLE = no

View File

@ -0,0 +1,85 @@
/*
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
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.
*/
/*
* STM32F303xC 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
}
/* For each data/text section two region are defined, a virtual region
and a load region (_LMA suffix).*/
/* Flash region to be used for exception vectors.*/
REGION_ALIAS("VECTORS_FLASH", flash0);
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
/* Flash region to be used for constructors and destructors.*/
REGION_ALIAS("XTORS_FLASH", flash0);
REGION_ALIAS("XTORS_FLASH_LMA", flash0);
/* Flash region to be used for code text.*/
REGION_ALIAS("TEXT_FLASH", flash0);
REGION_ALIAS("TEXT_FLASH_LMA", flash0);
/* Flash region to be used for read only data.*/
REGION_ALIAS("RODATA_FLASH", flash0);
REGION_ALIAS("RODATA_FLASH_LMA", flash0);
/* Flash region to be used for various.*/
REGION_ALIAS("VARIOUS_FLASH", flash0);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
/* Flash region to be used for RAM(n) initialization data.*/
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
/* RAM region to be used for Main stack. This stack accommodates the processing
of all exceptions and interrupts.*/
REGION_ALIAS("MAIN_STACK_RAM", ram0);
/* RAM region to be used for the process stack. This is the stack used by
the main() function.*/
REGION_ALIAS("PROCESS_STACK_RAM", ram0);
/* RAM region to be used for data segment.*/
REGION_ALIAS("DATA_RAM", ram0);
REGION_ALIAS("DATA_RAM_LMA", flash0);
/* RAM region to be used for BSS segment.*/
REGION_ALIAS("BSS_RAM", ram0);
/* RAM region to be used for the default heap.*/
REGION_ALIAS("HEAP_RAM", ram0);
/* Generic rules inclusion.*/
INCLUDE rules.ld

View File

@ -0,0 +1,241 @@
/* 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;
}

View File

@ -0,0 +1,39 @@
/* Copyright 2021 QMK
*
* 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 3 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include_next <mcuconf.h>
// 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

View File

@ -0,0 +1,58 @@
# Voyager
![Voyager](https://zsa.io/static/gallery-white-case-7a2ef555f8f7f4ce1b9030477b16e517.png)
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
}
}
```

View File

@ -0,0 +1,29 @@
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