summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio/musical_notes.h4
-rw-r--r--quantum/config_common.h43
-rw-r--r--quantum/debounce.c52
-rw-r--r--quantum/debounce.h11
-rw-r--r--quantum/keymap_common.c2
-rw-r--r--quantum/matrix.c32
-rw-r--r--quantum/mcu_selection.mk70
-rw-r--r--quantum/process_keycode/process_combo.c18
-rw-r--r--quantum/process_keycode/process_combo.h1
-rw-r--r--quantum/process_keycode/process_terminal.c6
-rw-r--r--quantum/process_keycode/process_unicode_common.c2
-rw-r--r--quantum/process_keycode/process_unicodemap.c33
-rw-r--r--quantum/process_keycode/process_unicodemap.h4
-rw-r--r--quantum/quantum.c5
-rw-r--r--quantum/quantum.h3
-rw-r--r--quantum/quantum_keycodes.h72
-rw-r--r--quantum/split_common/i2c.h5
-rw-r--r--quantum/split_common/matrix.c639
-rw-r--r--quantum/split_common/matrix.h30
-rw-r--r--quantum/split_common/serial.h5
-rw-r--r--quantum/split_common/split_flags.h9
-rw-r--r--quantum/split_common/split_util.c152
-rw-r--r--quantum/split_common/split_util.h15
-rw-r--r--quantum/split_common/transport.c224
-rw-r--r--quantum/split_common/transport.h10
-rw-r--r--quantum/stm32/chconf.h520
-rw-r--r--quantum/stm32/halconf.h388
-rw-r--r--quantum/stm32/mcuconf.h257
-rw-r--r--quantum/stm32/proton_c.mk44
-rw-r--r--quantum/template/avr/config.h2
-rw-r--r--quantum/template/avr/template.c2
-rw-r--r--quantum/template/avr/template.h38
-rw-r--r--quantum/template/base/keymaps/default/config.h2
-rw-r--r--quantum/template/base/keymaps/default/keymap.c2
-rw-r--r--quantum/template/base/template.h (renamed from quantum/template/ps2avrgb/template.h)7
-rw-r--r--quantum/template/ps2avrgb/rules.mk2
-rw-r--r--quantum/template/ps2avrgb/template.c2
37 files changed, 1987 insertions, 726 deletions
diff --git a/quantum/audio/musical_notes.h b/quantum/audio/musical_notes.h
index 065608ccce..ce8d47d1c1 100644
--- a/quantum/audio/musical_notes.h
+++ b/quantum/audio/musical_notes.h
@@ -61,7 +61,11 @@
// Notes - # = Octave
+#ifdef __arm__
+#define NOTE_REST 1.00f
+#else
#define NOTE_REST 0.00f
+#endif
/* These notes are currently bugged
#define NOTE_C0 16.35f
diff --git a/quantum/config_common.h b/quantum/config_common.h
index cbff372eaf..0b2e408a43 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -21,6 +21,9 @@
#define ROW2COL 1
#define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */
+// useful for direct pin mapping
+#define NO_PIN (~0)
+
#ifdef __AVR__
#ifndef __ASSEMBLER__
#include <avr/io.h>
@@ -125,6 +128,45 @@
#endif
#elif defined(PROTOCOL_CHIBIOS)
+ // Defines mapping for Proton C replacement
+ #ifdef CONVERT_TO_PROTON_C
+ // Left side (front)
+ #define D3 PAL_LINE(GPIOA, 9)
+ #define D2 PAL_LINE(GPIOA, 10)
+ // GND
+ // GND
+ #define D1 PAL_LINE(GPIOB, 7)
+ #define D0 PAL_LINE(GPIOB, 6)
+ #define D4 PAL_LINE(GPIOB, 5)
+ #define C6 PAL_LINE(GPIOB, 4)
+ #define D7 PAL_LINE(GPIOB, 3)
+ #define E6 PAL_LINE(GPIOB, 2)
+ #define B4 PAL_LINE(GPIOB, 1)
+ #define B5 PAL_LINE(GPIOB, 0)
+
+ // Right side (front)
+ // RAW
+ // GND
+ // RESET
+ // VCC
+ #define F4 PAL_LINE(GPIOA, 2)
+ #define F5 PAL_LINE(GPIOA, 1)
+ #define F6 PAL_LINE(GPIOA, 0)
+ #define F7 PAL_LINE(GPIOB, 8)
+ #define B1 PAL_LINE(GPIOB, 13)
+ #define B3 PAL_LINE(GPIOB, 14)
+ #define B2 PAL_LINE(GPIOB, 15)
+ #define B6 PAL_LINE(GPIOB, 9)
+
+ // LEDs (only D5/C13 uses an actual LED)
+ #ifdef CONVERT_TO_PROTON_C_RXLED
+ #define D5 PAL_LINE(GPIOC, 13)
+ #define B0 PAL_LINE(GPIOC, 13)
+ #else
+ #define D5 PAL_LINE(GPIOC, 13)
+ #define B0 PAL_LINE(GPIOC, 14)
+ #endif
+ #else
#define A0 PAL_LINE(GPIOA, 0)
#define A1 PAL_LINE(GPIOA, 1)
#define A2 PAL_LINE(GPIOA, 2)
@@ -221,6 +263,7 @@
#define F13 PAL_LINE(GPIOF, 13)
#define F14 PAL_LINE(GPIOF, 14)
#define F15 PAL_LINE(GPIOF, 15)
+ #endif
#endif
/* USART configuration */
diff --git a/quantum/debounce.c b/quantum/debounce.c
new file mode 100644
index 0000000000..929023ab2d
--- /dev/null
+++ b/quantum/debounce.c
@@ -0,0 +1,52 @@
+
+#include "matrix.h"
+#include "timer.h"
+#include "quantum.h"
+
+#ifndef DEBOUNCING_DELAY
+# define DEBOUNCING_DELAY 5
+#endif
+
+void debounce_init(uint8_t num_rows) {
+}
+
+#if DEBOUNCING_DELAY > 0
+
+static bool debouncing = false;
+
+void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
+ static uint16_t debouncing_time;
+
+ if (changed) {
+ debouncing = true;
+ debouncing_time = timer_read();
+ }
+
+ if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
+ for (uint8_t i = 0; i < num_rows; i++) {
+ cooked[i] = raw[i];
+ }
+ debouncing = false;
+ }
+}
+
+bool debounce_active(void) {
+ return debouncing;
+}
+
+#else
+
+// no debounce
+void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
+ if (changed)
+ {
+ for (uint8_t i = 0; i < num_rows; i++) {
+ cooked[i] = raw[i];
+ }
+ }
+}
+
+bool debounce_active(void) {
+ return false;
+}
+#endif
diff --git a/quantum/debounce.h b/quantum/debounce.h
new file mode 100644
index 0000000000..360af77e78
--- /dev/null
+++ b/quantum/debounce.h
@@ -0,0 +1,11 @@
+#pragma once
+
+// raw is the current key state
+// on entry cooked is the previous debounced state
+// on exit cooked is the current debounced state
+// changed is true if raw has changed since the last call
+void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed);
+
+bool debounce_active(void);
+
+void debounce_init(uint8_t num_rows); \ No newline at end of file
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index f6c8b70d28..1a6af9e08f 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -120,7 +120,7 @@ action_t action_for_key(uint8_t layer, keypos_t key)
break;
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: ;
// OSM(mod) - One-shot mod
- mod = keycode & 0xFF;
+ mod = mod_config(keycode & 0xFF);
action.code = ACTION_MODS_ONESHOT(mod);
break;
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 292171490c..71292db511 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -21,10 +21,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "debug.h"
#include "util.h"
#include "matrix.h"
-#include "timer.h"
+#include "debounce.h"
#include "quantum.h"
-
#if (MATRIX_COLS <= 8)
# define print_matrix_header() print("\nr/c 01234567\n")
# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
@@ -52,8 +51,9 @@ static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
#endif
/* matrix state(1:on, 0:off) */
-static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t raw_matrix[MATRIX_ROWS];
+static matrix_row_t matrix[MATRIX_ROWS];
#if (DIODE_DIRECTION == COL2ROW)
static void init_cols(void);
@@ -120,34 +120,40 @@ void matrix_init(void) {
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ raw_matrix[i] = 0;
matrix[i] = 0;
}
+ debounce_init(MATRIX_ROWS);
matrix_init_quantum();
}
uint8_t matrix_scan(void)
{
+ bool changed = false;
#if (DIODE_DIRECTION == COL2ROW)
- // Set row, read cols
- for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
- read_cols_on_row(matrix, current_row);
- }
+ // Set row, read cols
+ for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
+ changed |= read_cols_on_row(raw_matrix, current_row);
+ }
#elif (DIODE_DIRECTION == ROW2COL)
- // Set col, read rows
- for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
- read_rows_on_col(matrix, current_col);
- }
+ // Set col, read rows
+ for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
+ changed |= read_rows_on_col(raw_matrix, current_col);
+ }
#endif
- matrix_scan_quantum();
- return 1;
+ debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
+
+ matrix_scan_quantum();
+ return 1;
}
//Deprecated.
bool matrix_is_modified(void)
{
+ if (debounce_active()) return false;
return true;
}
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk
new file mode 100644
index 0000000000..209b578ea5
--- /dev/null
+++ b/quantum/mcu_selection.mk
@@ -0,0 +1,70 @@
+
+ifneq ($(findstring STM32F303, $(MCU)),)
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY ?= STM32
+ MCU_SERIES ?= STM32F3xx
+
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <this_dir>/ld/
+ MCU_LDSCRIPT ?= STM32F303xC
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP ?= stm32f3xx
+
+ # Board: it should exist either in <chibios>/os/hal/boards/
+ # or <this_dir>/boards
+ BOARD ?= GENERIC_STM32_F303XC
+
+ # Cortex version
+ MCU = cortex-m4
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV ?= 7
+
+ USE_FPU = yes
+
+ # Vector table for application
+ # 0x00000000-0x00001000 area is occupied by bootlaoder.*/
+ # The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
+ # OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000
+
+ # Options to pass to dfu-util when flashing
+ DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave
+endif
+
+ifneq (,$(filter $(MCU),atmega32u4 at90usb1286))
+ # Processor frequency.
+ # This will define a symbol, F_CPU, in all source code files equal to the
+ # processor frequency in Hz. You can then use this symbol in your source code to
+ # calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+ # automatically to create a 32-bit value in your source code.
+ #
+ # This will be an integer division of F_USB below, as it is sourced by
+ # F_USB after it has run through any CPU prescalers. Note that this value
+ # does not *change* the processor frequency - it should merely be updated to
+ # reflect the processor speed set externally so that the code can use accurate
+ # software delays.
+ F_CPU ?= 16000000
+
+ # LUFA specific
+ #
+ # Target architecture (see library "Board Types" documentation).
+ ARCH ?= AVR8
+
+ # Input clock frequency.
+ # This will define a symbol, F_USB, in all source code files equal to the
+ # input clock frequency (before any prescaling is performed) in Hz. This value may
+ # differ from F_CPU if prescaling is used on the latter, and is required as the
+ # raw input clock is fed directly to the PLL sections of the AVR for high speed
+ # clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+ # at the end, this will be done automatically to create a 32-bit value in your
+ # source code.
+ #
+ # If no clock division is performed on the input clock inside the AVR (via the
+ # CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+ F_USB ?= $(F_CPU)
+endif
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
index 6e9c28e4fc..13f8bbb331 100644
--- a/quantum/process_keycode/process_combo.c
+++ b/quantum/process_keycode/process_combo.c
@@ -18,9 +18,6 @@
#include "print.h"
-#define COMBO_TIMER_ELAPSED -1
-
-
__attribute__ ((weak))
combo_t key_combos[COMBO_COUNT] = {
@@ -65,7 +62,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
if (-1 == (int8_t)index) return false;
/* The combos timer is used to signal whether the combo is active */
- bool is_combo_active = COMBO_TIMER_ELAPSED == combo->timer ? false : true;
+ bool is_combo_active = combo->is_active;
if (record->event.pressed) {
KEY_STATE_DOWN(index);
@@ -73,9 +70,10 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
if (is_combo_active) {
if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */
send_combo(combo->keycode, true);
- combo->timer = COMBO_TIMER_ELAPSED;
+ combo->is_active = false;
} else { /* Combo key was pressed */
combo->timer = timer_read();
+ combo->is_active = true;
#ifdef COMBO_ALLOW_ACTION_KEYS
combo->prev_record = *record;
#else
@@ -99,6 +97,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
send_keyboard_report();
unregister_code16(keycode);
#endif
+ combo->is_active = false;
combo->timer = 0;
}
@@ -106,6 +105,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
}
if (NO_COMBO_KEYS_ARE_DOWN) {
+ combo->is_active = true;
combo->timer = 0;
}
@@ -132,14 +132,14 @@ void matrix_scan_combo(void)
#pragma GCC diagnostic ignored "-Warray-bounds"
combo_t *combo = &key_combos[i];
#pragma GCC diagnostic pop
- if (combo->timer &&
- combo->timer != COMBO_TIMER_ELAPSED &&
+ if (combo->is_active &&
+ combo->timer &&
timer_elapsed(combo->timer) > COMBO_TERM) {
-
+
/* This disables the combo, meaning key events for this
* combo will be handled by the next processors in the chain
*/
- combo->timer = COMBO_TIMER_ELAPSED;
+ combo->is_active = false;
#ifdef COMBO_ALLOW_ACTION_KEYS
process_action(&combo->prev_record,
diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h
index a5dbd788a4..a5787c9ed3 100644
--- a/quantum/process_keycode/process_combo.h
+++ b/quantum/process_keycode/process_combo.h
@@ -33,6 +33,7 @@ typedef struct
uint8_t state;
#endif
uint16_t timer;
+ bool is_active;
#ifdef COMBO_ALLOW_ACTION_KEYS
keyrecord_t prev_record;
#else
diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c
index 6998639f20..e791deffc1 100644
--- a/quantum/process_keycode/process_terminal.c
+++ b/quantum/process_keycode/process_terminal.c
@@ -273,11 +273,17 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
disable_terminal();
return false;
}
+
+ if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
+ keycode = keycode & 0xFF;
+ }
+
if (keycode < 256) {
uint8_t str_len;
char char_to_add;
switch (keycode) {
case KC_ENTER:
+ case KC_KP_ENTER:
push_to_cmd_buffer();
current_cmd_buffer_pos = 0;
process_terminal_command();
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index 3286f45b5d..b64feb7003 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -216,7 +216,7 @@ bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
#if defined(UNICODE_ENABLE)
return process_unicode(keycode, record);
#elif defined(UNICODEMAP_ENABLE)
- return process_unicode_map(keycode, record);
+ return process_unicodemap(keycode, record);
#elif defined(UCIS_ENABLE)
return process_ucis(keycode, record);
#else
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
index 75f35112b1..cee9acb5fc 100644
--- a/quantum/process_keycode/process_unicodemap.c
+++ b/quantum/process_keycode/process_unicodemap.c
@@ -18,8 +18,7 @@
#include "process_unicode_common.h"
__attribute__((weak))
-const uint32_t PROGMEM unicode_map[] = {
-};
+const uint32_t PROGMEM unicode_map[] = {};
void register_hex32(uint32_t hex) {
bool onzerostart = true;
@@ -42,26 +41,26 @@ void register_hex32(uint32_t hex) {
}
__attribute__((weak))
-void unicode_map_input_error() {}
+void unicodemap_input_error() {}
-bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
- uint8_t input_mode = get_unicode_input_mode();
- if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
- const uint32_t* map = unicode_map;
- uint16_t index = keycode - QK_UNICODE_MAP;
- uint32_t code = pgm_read_dword(&map[index]);
- if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) {
+bool process_unicodemap(uint16_t keycode, keyrecord_t *record) {
+ if ((keycode & QK_UNICODEMAP) == QK_UNICODEMAP && record->event.pressed) {
+ uint16_t index = keycode - QK_UNICODEMAP;
+ uint32_t code = pgm_read_dword(unicode_map + index);
+ uint8_t input_mode = get_unicode_input_mode();
+
+ if (code > 0xFFFF && code <= 0x10FFFF && input_mode == UC_OSX) {
// Convert to UTF-16 surrogate pair
code -= 0x10000;
- uint32_t lo = code & 0x3ff;
- uint32_t hi = (code & 0xffc00) >> 10;
+ uint32_t lo = code & 0x3FF, hi = (code & 0xFFC00) >> 10;
+
unicode_input_start();
- register_hex32(hi + 0xd800);
- register_hex32(lo + 0xdc00);
+ register_hex32(hi + 0xD800);
+ register_hex32(lo + 0xDC00);
unicode_input_finish();
- } else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
- // when character is out of range supported by the OS
- unicode_map_input_error();
+ } else if ((code > 0x10FFFF && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
+ // Character is out of range supported by the OS
+ unicodemap_input_error();
} else {
unicode_input_start();
register_hex32(code);
diff --git a/quantum/process_keycode/process_unicodemap.h b/quantum/process_keycode/process_unicodemap.h
index f6d64bb86b..5764697f84 100644
--- a/quantum/process_keycode/process_unicodemap.h
+++ b/quantum/process_keycode/process_unicodemap.h
@@ -19,5 +19,5 @@
#include "quantum.h"
#include "process_unicode_common.h"
-void unicode_map_input_error(void);
-bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
+void unicodemap_input_error(void);
+bool process_unicodemap(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 85db100ab4..5d8ffe34eb 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -15,6 +15,11 @@
*/
#include "quantum.h"
+
+#if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE)
+ #include "rgb.h"
+#endif
+
#ifdef PROTOCOL_LUFA
#include "outputselect.h"
#endif
diff --git a/quantum/quantum.h b/quantum/quantum.h
index f78915fdfb..56a6a1a991 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -30,9 +30,6 @@
#ifdef BACKLIGHT_ENABLE
#include "backlight.h"
#endif
-#if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE)
- #include "rgb.h"
-#endif
#ifdef RGBLIGHT_ENABLE
#include "rgblight.h"
#else
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 2b309f4d52..0462291c2b 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -86,8 +86,8 @@ enum quantum_keycodes {
QK_UNICODE_MAX = 0xFFFF,
#endif
#ifdef UNICODEMAP_ENABLE
- QK_UNICODE_MAP = 0x8000,
- QK_UNICODE_MAP_MAX = 0x83FF,
+ QK_UNICODEMAP = 0x8000,
+ QK_UNICODEMAP_MAX = 0x83FF,
#endif
// Loose keycodes - to be used directly
@@ -489,9 +489,8 @@ enum quantum_keycodes {
#define SWIN(kc) SGUI(kc)
#define LCA(kc) (QK_LCTL | QK_LALT | (kc))
-#define MOD_HYPR 0xf
-#define MOD_MEH 0x7
-
+#define MOD_HYPR 0xF
+#define MOD_MEH 0x7
// Aliases for shifted symbols
// Each key has a 4-letter code, and some have longer aliases too.
@@ -568,9 +567,12 @@ enum quantum_keycodes {
#define FUNC(kc) (QK_FUNCTION | (kc))
// Aliases
+#define C(kc) LCTL(kc)
#define S(kc) LSFT(kc)
-#define F(kc) FUNC(kc)
+#define A(kc) LALT(kc)
+#define G(kc) LGUI(kc)
+#define F(kc) FUNC(kc)
#define M(kc) (QK_MACRO | (kc))
#define MACROTAP(kc) (QK_MACRO | (FUNC_TAP << 8) | (kc))
@@ -601,7 +603,7 @@ enum quantum_keycodes {
#define RGB_M_T RGB_MODE_RGBTEST
// L-ayer, T-ap - 256 keycode max, 16 layer max
-#define LT(layer, kc) (QK_LAYER_TAP | ((layer & 0xF) << 8) | ((kc) & 0xFF))
+#define LT(layer, kc) (QK_LAYER_TAP | (((layer) & 0xF) << 8) | ((kc) & 0xFF))
#define AG_SWAP MAGIC_SWAP_ALT_GUI
#define AG_NORM MAGIC_UNSWAP_ALT_GUI
@@ -615,79 +617,77 @@ enum quantum_keycodes {
// In fact, we changed it to assume ON_PRESS for sanity/simplicity. If needed, you can add your own
// keycode modeled after the old version, kept below for this.
/* #define TO(layer, when) (QK_TO | (when << 0x4) | (layer & 0xFF)) */
-#define TO(layer) (QK_TO | (ON_PRESS << 0x4) | (layer & 0xFF))
+#define TO(layer) (QK_TO | (ON_PRESS << 0x4) | ((layer) & 0xFF))
// Momentary switch layer - 256 layer max
-#define MO(layer) (QK_MOMENTARY | (layer & 0xFF))
+#define MO(layer) (QK_MOMENTARY | ((layer) & 0xFF))
// Set default layer - 256 layer max
-#define DF(layer) (QK_DEF_LAYER | (layer & 0xFF))
+#define DF(layer) (QK_DEF_LAYER | ((layer) & 0xFF))
// Toggle to layer - 256 layer max
-#define TG(layer) (QK_TOGGLE_LAYER | (layer & 0xFF))
+#define TG(layer) (QK_TOGGLE_LAYER | ((layer) & 0xFF))
// One-shot layer - 256 layer max
-#define OSL(layer) (QK_ONE_SHOT_LAYER | (layer & 0xFF))
+#define OSL(layer) (QK_ONE_SHOT_LAYER | ((layer) & 0xFF))
// L-ayer M-od: Momentary switch layer with modifiers active - 16 layer max, left mods only
-#define LM(layer, mod) (QK_LAYER_MOD | ((layer & 0xF) << 4) | ((mod) & 0xF))
+#define LM(layer, mod) (QK_LAYER_MOD | (((layer) & 0xF) << 4) | ((mod) & 0xF))
// One-shot mod
#define OSM(mod) (QK_ONE_SHOT_MOD | ((mod) & 0xFF))
// Layer tap-toggle
-#define TT(layer) (QK_LAYER_TAP_TOGGLE | (layer & 0xFF))
+#define TT(layer) (QK_LAYER_TAP_TOGGLE | ((layer) & 0xFF))
// M-od, T-ap - 256 keycode max
#define MT(mod, kc) (QK_MOD_TAP | (((mod) & 0x1F) << 8) | ((kc) & 0xFF))
-#define CTL_T(kc) MT(MOD_LCTL, kc)
#define LCTL_T(kc) MT(MOD_LCTL, kc)
#define RCTL_T(kc) MT(MOD_RCTL, kc)
+#define CTL_T(kc) LCTL_T(kc)
-#define SFT_T(kc) MT(MOD_LSFT, kc)
#define LSFT_T(kc) MT(MOD_LSFT, kc)
#define RSFT_T(kc) MT(MOD_RSFT, kc)
+#define SFT_T(kc) LSFT_T(kc)
-#define ALT_T(kc) MT(MOD_LALT, kc)
#define LALT_T(kc) MT(MOD_LALT, kc)
#define RALT_T(kc) MT(MOD_RALT, kc)
+#define ALT_T(kc) LALT_T(kc)
#define ALGR_T(kc) RALT_T(kc)
-#define GUI_T(kc) MT(MOD_LGUI, kc)
-#define CMD_T(kc) GUI_T(kc)
-#define WIN_T(kc) GUI_T(kc)
#define LGUI_T(kc) MT(MOD_LGUI, kc)
+#define RGUI_T(kc) MT(MOD_RGUI, kc)
#define LCMD_T(kc) LGUI_T(kc)
#define LWIN_T(kc) LGUI_T(kc)
-#define RGUI_T(kc) MT(MOD_RGUI, kc)
#define RCMD_T(kc) RGUI_T(kc)
#define RWIN_T(kc) RGUI_T(kc)
-
-#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Control + Shift e.g. for gnome-terminal
-#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
-#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left control alt and gui
-#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right control alt and gui
-#define ALL_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
-#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc)
+#define GUI_T(kc) LGUI_T(kc)
+#define CMD_T(kc) LCMD_T(kc)
+#define WIN_T(kc) LWIN_T(kc)
+
+#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal
+#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
+#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI
+#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI
+#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
+#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc) // Left Shift + GUI
#define SCMD_T(kc) SGUI_T(kc)
#define SWIN_T(kc) SGUI_T(kc)
-#define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left control and left alt
+#define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left Control + Alt
+#define ALL_T(kc) HYPR_T(kc)
// Dedicated keycode versions for Hyper and Meh, if you want to use them as standalone keys rather than mod-tap
#define KC_HYPR HYPR(KC_NO)
#define KC_MEH MEH(KC_NO)
#ifdef UNICODE_ENABLE
- // For sending unicode codes.
- // You may not send codes over 7FFF -- this supports most of UTF8.
- // To have a key that sends out Œ, go UC(0x0152)
- #define UNICODE(n) (QK_UNICODE | (n))
- #define UC(n) UNICODE(n)
+ // Allows Unicode input up to 0x7FFF
+ #define UC(c) (QK_UNICODE | (c))
#endif
-
#ifdef UNICODEMAP_ENABLE
- #define X(n) (QK_UNICODE_MAP | (n))
+ // Allows Unicode input up to 0x10FFFF, requires unicode_map
+ #define X(i) (QK_UNICODEMAP | (i))
#endif
#define UC_MOD UNICODE_MODE_FORWARD
diff --git a/quantum/split_common/i2c.h b/quantum/split_common/i2c.h
index b3cbe8c826..91e8e96f47 100644
--- a/quantum/split_common/i2c.h
+++ b/quantum/split_common/i2c.h
@@ -1,5 +1,4 @@
-#ifndef I2C_H
-#define I2C_H
+#pragma once
#include <stdint.h>
@@ -58,5 +57,3 @@ extern unsigned char i2c_readNak(void);
extern unsigned char i2c_read(unsigned char ack);
#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
-
-#endif
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index 2c37053f88..c3d2857ed5 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -25,529 +25,304 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "matrix.h"
#include "split_util.h"
#include "config.h"
-#include "timer.h"
#include "split_flags.h"
#include "quantum.h"
-
-#ifdef BACKLIGHT_ENABLE
-# include "backlight.h"
- extern backlight_config_t backlight_config;
-#endif
-
-#if defined(USE_I2C) || defined(EH)
-# include "i2c.h"
-#else // USE_SERIAL
-# include "serial.h"
-#endif
-
-#ifndef DEBOUNCING_DELAY
-# define DEBOUNCING_DELAY 5
-#endif
-
-#if (DEBOUNCING_DELAY > 0)
- static uint16_t debouncing_time;
- static bool debouncing = false;
-#endif
-
-#if defined(USE_I2C) || defined(EH)
-
-#if (MATRIX_COLS <= 8)
-# define print_matrix_header() print("\nr/c 01234567\n")
-# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop(matrix[i])
-# define ROW_SHIFTER ((uint8_t)1)
-#else
-# error "Currently only supports 8 COLS"
-#endif
-
-#else // USE_SERIAL
+#include "debounce.h"
+#include "transport.h"
#if (MATRIX_COLS <= 8)
-# define print_matrix_header() print("\nr/c 01234567\n")
-# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop(matrix[i])
-# define ROW_SHIFTER ((uint8_t)1)
+# define print_matrix_header() print("\nr/c 01234567\n")
+# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop(matrix[i])
+# define ROW_SHIFTER ((uint8_t)1)
#elif (MATRIX_COLS <= 16)
-# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
-# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop16(matrix[i])
-# define ROW_SHIFTER ((uint16_t)1)
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop16(matrix[i])
+# define ROW_SHIFTER ((uint16_t)1)
#elif (MATRIX_COLS <= 32)
-# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
-# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop32(matrix[i])
-# define ROW_SHIFTER ((uint32_t)1)
-#endif
-
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop32(matrix[i])
+# define ROW_SHIFTER ((uint32_t)1)
#endif
-static matrix_row_t matrix_debouncing[MATRIX_ROWS];
#define ERROR_DISCONNECT_COUNT 5
-#define ROWS_PER_HAND (MATRIX_ROWS/2)
-
-static uint8_t error_count = 0;
+#define ROWS_PER_HAND (MATRIX_ROWS / 2)
+#ifdef DIRECT_PINS
+static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
+#else
static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
+#endif
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
-static matrix_row_t matrix_debouncing[MATRIX_ROWS];
-
-#if (DIODE_DIRECTION == COL2ROW)
- static void init_cols(void);
- static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
- static void unselect_rows(void);
- static void select_row(uint8_t row);
- static void unselect_row(uint8_t row);
-#elif (DIODE_DIRECTION == ROW2COL)
- static void init_rows(void);
- static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
- static void unselect_cols(void);
- static void unselect_col(uint8_t col);
- static void select_col(uint8_t col);
-#endif
+static matrix_row_t raw_matrix[ROWS_PER_HAND];
-__attribute__ ((weak))
-void matrix_init_kb(void) {
- matrix_init_user();
-}
+// row offsets for each hand
+uint8_t thisHand, thatHand;
-__attribute__ ((weak))
-void matrix_scan_kb(void) {
- matrix_scan_user();
-}
+// user-defined overridable functions
-__attribute__ ((weak))
-void matrix_init_user(void) {
-}
+__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
-__attribute__ ((weak))
-void matrix_scan_user(void) {
-}
+__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
-__attribute__ ((weak))
-void matrix_slave_scan_user(void) {
-}
+__attribute__((weak)) void matrix_init_user(void) {}
-inline
-uint8_t matrix_rows(void)
-{
- return MATRIX_ROWS;
-}
+__attribute__((weak)) void matrix_scan_user(void) {}
-inline
-uint8_t matrix_cols(void)
-{
- return MATRIX_COLS;
-}
+__attribute__((weak)) void matrix_slave_scan_user(void) {}
-void matrix_init(void)
-{
- debug_enable = true;
- debug_matrix = true;
- debug_mouse = true;
+// helper functions
- // Set pinout for right half if pinout for that half is defined
- if (!isLeftHand) {
-#ifdef MATRIX_ROW_PINS_RIGHT
- const uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
- for (uint8_t i = 0; i < MATRIX_ROWS; i++)
- row_pins[i] = row_pins_right[i];
-#endif
-#ifdef MATRIX_COL_PINS_RIGHT
- const uint8_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
- for (uint8_t i = 0; i < MATRIX_COLS; i++)
- col_pins[i] = col_pins_right[i];
-#endif
- }
+inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
- // initialize row and col
-#if (DIODE_DIRECTION == COL2ROW)
- unselect_rows();
- init_cols();
-#elif (DIODE_DIRECTION == ROW2COL)
- unselect_cols();
- init_rows();
-#endif
+inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
- // initialize matrix state: all keys off
- for (uint8_t i=0; i < MATRIX_ROWS; i++) {
- matrix[i] = 0;
- matrix_debouncing[i] = 0;
- }
-
- matrix_init_quantum();
-
+bool matrix_is_modified(void) {
+ if (debounce_active()) return false;
+ return true;
}
-uint8_t _matrix_scan(void)
-{
- int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
-#if (DIODE_DIRECTION == COL2ROW)
- // Set row, read cols
- for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
-# if (DEBOUNCING_DELAY > 0)
- bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row);
-
- if (matrix_changed) {
- debouncing = true;
- debouncing_time = timer_read();
- }
-
-# else
- read_cols_on_row(matrix+offset, current_row);
-# endif
-
- }
+inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
-#elif (DIODE_DIRECTION == ROW2COL)
- // Set col, read rows
- for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
-# if (DEBOUNCING_DELAY > 0)
- bool matrix_changed = read_rows_on_col(matrix_debouncing+offset, current_col);
- if (matrix_changed) {
- debouncing = true;
- debouncing_time = timer_read();
- }
-# else
- read_rows_on_col(matrix+offset, current_col);
-# endif
+inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
- }
-#endif
+void matrix_print(void) {
+ print_matrix_header();
-# if (DEBOUNCING_DELAY > 0)
- if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
- for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
- matrix[i+offset] = matrix_debouncing[i+offset];
- }
- debouncing = false;
- }
-# endif
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row);
+ print(": ");
+ print_matrix_row(row);
+ print("\n");
+ }
+}
- return 1;
+uint8_t matrix_key_count(void) {
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ count += matrix_bitpop(i);
+ }
+ return count;
}
-#if defined(USE_I2C) || defined(EH)
-
-// Get rows from other half over i2c
-int i2c_transaction(void) {
- int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
- int err = 0;
-
- // write backlight info
- #ifdef BACKLIGHT_ENABLE
- if (BACKLIT_DIRTY) {
- err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
- if (err) goto i2c_error;
-
- // Backlight location
- err = i2c_master_write(I2C_BACKLIT_START);
- if (err) goto i2c_error;
-
- // Write backlight
- i2c_master_write(get_backlight_level());
-
- BACKLIT_DIRTY = false;
- }
- #endif
+// matrix code
- err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
- if (err) goto i2c_error;
+#ifdef DIRECT_PINS
- // start of matrix stored at I2C_KEYMAP_START
- err = i2c_master_write(I2C_KEYMAP_START);
- if (err) goto i2c_error;
+static void init_pins(void) {
+ for (int row = 0; row < MATRIX_ROWS; row++) {
+ for (int col = 0; col < MATRIX_COLS; col++) {
+ pin_t pin = direct_pins[row][col];
+ if (pin != NO_PIN) {
+ setPinInputHigh(pin);
+ }
+ }
+ }
+}
- // Start read
- err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
- if (err) goto i2c_error;
+static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
+ matrix_row_t last_row_value = current_matrix[current_row];
+ current_matrix[current_row] = 0;
- if (!err) {
- int i;
- for (i = 0; i < ROWS_PER_HAND-1; ++i) {
- matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
- }
- matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
- i2c_master_stop();
- } else {
-i2c_error: // the cable is disconnceted, or something else went wrong
- i2c_reset_state();
- return err;
+ for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
+ pin_t pin = direct_pins[current_row][col_index];
+ if (pin != NO_PIN) {
+ current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index);
}
-
- #ifdef RGBLIGHT_ENABLE
- if (RGB_DIRTY) {
- err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
- if (err) goto i2c_error;
-
- // RGB Location
- err = i2c_master_write(I2C_RGB_START);
- if (err) goto i2c_error;
-
- uint32_t dword = eeconfig_read_rgblight();
-
- // Write RGB
- err = i2c_master_write_data(&dword, 4);
- if (err) goto i2c_error;
-
- RGB_DIRTY = false;
- i2c_master_stop();
- }
- #endif
+ }
- return 0;
+ return (last_row_value != current_matrix[current_row]);
}
-#else // USE_SERIAL
-
+#elif (DIODE_DIRECTION == COL2ROW)
-typedef struct _Serial_s2m_buffer_t {
- // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
- matrix_row_t smatrix[ROWS_PER_HAND];
-} Serial_s2m_buffer_t;
+static void select_row(uint8_t row) {
+ writePinLow(row_pins[row]);
+ setPinOutput(row_pins[row]);
+}
-volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
-volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
-uint8_t volatile status0 = 0;
+static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
-SSTD_t transactions[] = {
- { (uint8_t *)&status0,
- sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
- sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
+static void unselect_rows(void) {
+ for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
+ setPinInputHigh(row_pins[x]);
}
-};
+}
-void serial_master_init(void)
-{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
+static void init_pins(void) {
+ unselect_rows();
+ for (uint8_t x = 0; x < MATRIX_COLS; x++) {
+ setPinInputHigh(col_pins[x]);
+ }
+}
-void serial_slave_init(void)
-{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
+static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
+ // Store last value of row prior to reading
+ matrix_row_t last_row_value = current_matrix[current_row];
-int serial_transaction(void) {
- int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
+ // Clear data in matrix row
+ current_matrix[current_row] = 0;
- if (soft_serial_transaction()) {
- return 1;
- }
+ // Select row and wait for row selecton to stabilize
+ select_row(current_row);
+ wait_us(30);
- // TODO: if MATRIX_COLS > 8 change to unpack()
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- matrix[slaveOffset+i] = serial_s2m_buffer.smatrix[i];
- }
-
- #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
- // Code to send RGB over serial goes here (not implemented yet)
- #endif
-
- #ifdef BACKLIGHT_ENABLE
- // Write backlight level for slave to read
- serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
- #endif
-
- return 0;
-}
-#endif
+ // For each col...
+ for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
+ // Populate the matrix row with the state of the col pin
+ current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index);
+ }
-uint8_t matrix_scan(void)
-{
- uint8_t ret = _matrix_scan();
+ // Unselect row
+ unselect_row(current_row);
-#if defined(USE_I2C) || defined(EH)
- if( i2c_transaction() ) {
-#else // USE_SERIAL
- if( serial_transaction() ) {
-#endif
+ return (last_row_value != current_matrix[current_row]);
+}
- error_count++;
+#elif (DIODE_DIRECTION == ROW2COL)
- if (error_count > ERROR_DISCONNECT_COUNT) {
- // reset other half if disconnected
- int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- matrix[slaveOffset+i] = 0;
- }
- }
- } else {
- error_count = 0;
- }
- matrix_scan_quantum();
- return ret;
+static void select_col(uint8_t col) {
+ writePinLow(col_pins[col]);
+ setPinOutput(col_pins[col]);
}
-void matrix_slave_scan(void) {
- _matrix_scan();
-
- int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
+static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); }
-#if defined(USE_I2C) || defined(EH)
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i];
- }
-#else // USE_SERIAL
- // TODO: if MATRIX_COLS > 8 change to pack()
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- serial_s2m_buffer.smatrix[i] = matrix[offset+i];
- }
-#endif
- matrix_slave_scan_user();
+static void unselect_cols(void) {
+ for (uint8_t x = 0; x < MATRIX_COLS; x++) {
+ setPinInputHigh(col_pins[x]);
+ }
}
-bool matrix_is_modified(void)
-{
- if (debouncing) return false;
- return true;
+static void init_pins(void) {
+ unselect_cols();
+ for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
+ setPinInputHigh(row_pins[x]);
+ }
}
-inline
-bool matrix_is_on(uint8_t row, uint8_t col)
-{
- return (matrix[row] & ((matrix_row_t)1<<col));
-}
+static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
+ bool matrix_changed = false;
-inline
-matrix_row_t matrix_get_row(uint8_t row)
-{
- return matrix[row];
-}
+ // Select col and wait for col selecton to stabilize
+ select_col(current_col);
+ wait_us(30);
+
+ // For each row...
+ for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
+ // Store last value of row prior to reading
+ matrix_row_t last_row_value = current_matrix[row_index];
-void matrix_print(void)
-{
- print("\nr/c 0123456789ABCDEF\n");
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- phex(row); print(": ");
- pbin_reverse16(matrix_get_row(row));
- print("\n");
+ // Check row pin state
+ if (readPin(row_pins[row_index])) {
+ // Pin HI, clear col bit
+ current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
+ } else {
+ // Pin LO, set col bit
+ current_matrix[row_index] |= (ROW_SHIFTER << current_col);
}
-}
-uint8_t matrix_key_count(void)
-{
- uint8_t count = 0;
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- count += bitpop16(matrix[i]);
+ // Determine if the matrix changed state
+ if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
+ matrix_changed = true;
}
- return count;
-}
+ }
-#if (DIODE_DIRECTION == COL2ROW)
+ // Unselect col
+ unselect_col(current_col);
-static void init_cols(void)
-{
- for(uint8_t x = 0; x < MATRIX_COLS; x++) {
- setPinInputHigh(col_pins[x]);
- }
+ return matrix_changed;
}
-static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
-{
- // Store last value of row prior to reading
- matrix_row_t last_row_value = current_matrix[current_row];
-
- // Clear data in matrix row
- current_matrix[current_row] = 0;
+#endif
- // Select row and wait for row selecton to stabilize
- select_row(current_row);
- wait_us(30);
+void matrix_init(void) {
+ debug_enable = true;
+ debug_matrix = true;
+ debug_mouse = true;
- // For each col...
- for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
- // Populate the matrix row with the state of the col pin
- current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index);
+ // Set pinout for right half if pinout for that half is defined
+ if (!isLeftHand) {
+#ifdef MATRIX_ROW_PINS_RIGHT
+ const uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ row_pins[i] = row_pins_right[i];
}
+#endif
+#ifdef MATRIX_COL_PINS_RIGHT
+ const uint8_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
+ for (uint8_t i = 0; i < MATRIX_COLS; i++) {
+ col_pins[i] = col_pins_right[i];
+ }
+#endif
+ }
- // Unselect row
- unselect_row(current_row);
+ thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
+ thatHand = ROWS_PER_HAND - thisHand;
- return (last_row_value != current_matrix[current_row]);
-}
+ // initialize key pins
+ init_pins();
-static void select_row(uint8_t row)
-{
- writePinLow(row_pins[row]);
- setPinOutput(row_pins[row]);
-}
+ // initialize matrix state: all keys off
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ }
-static void unselect_row(uint8_t row)
-{
- setPinInputHigh(row_pins[row]);
-}
+ debounce_init(ROWS_PER_HAND);
-static void unselect_rows(void)
-{
- for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
- setPinInputHigh(row_pins[x]);
- }
+ matrix_init_quantum();
}
+uint8_t _matrix_scan(void) {
+ bool changed = false;
+
+#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
+ // Set row, read cols
+ for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
+ changed |= read_cols_on_row(raw_matrix, current_row);
+ }
#elif (DIODE_DIRECTION == ROW2COL)
+ // Set col, read rows
+ for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
+ changed |= read_rows_on_col(raw_matrix, current_col);
+ }
+#endif
-static void init_rows(void)
-{
- for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
- setPinInputHigh(row_pins[x]);
- }
-}
+ debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
-static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
-{
- bool matrix_changed = false;
+ return 1;
+}
- // Select col and wait for col selecton to stabilize
- select_col(current_col);
- wait_us(30);
+uint8_t matrix_scan(void) {
+ uint8_t ret = _matrix_scan();
- // For each row...
- for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++)
- {
+ if (is_keyboard_master()) {
+ static uint8_t error_count;
- // Store last value of row prior to reading
- matrix_row_t last_row_value = current_matrix[row_index];
+ if (!transport_master(matrix + thatHand)) {
+ error_count++;
- // Check row pin state
- if (readPin(row_pins[row_index]))
- {
- // Pin HI, clear col bit
- current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
- }
- else
- {
- // Pin LO, set col bit
- current_matrix[row_index] |= (ROW_SHIFTER << current_col);
- }
-
- // Determine if the matrix changed state
- if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
- {
- matrix_changed = true;
+ if (error_count > ERROR_DISCONNECT_COUNT) {
+ // reset other half if disconnected
+ for (int i = 0; i < ROWS_PER_HAND; ++i) {
+ matrix[thatHand + i] = 0;
}
+ }
+ } else {
+ error_count = 0;
}
- // Unselect col
- unselect_col(current_col);
-
- return matrix_changed;
-}
-
-static void select_col(uint8_t col)
-{
- writePinLow(col_pins[col]);
- setPinOutput(col_pins[col]);
-}
-
-static void unselect_col(uint8_t col)
-{
- setPinInputHigh(col_pins[col]);
-}
+ matrix_scan_quantum();
+ } else {
+ transport_slave(matrix + thisHand);
+ matrix_slave_scan_user();
+ }
-static void unselect_cols(void)
-{
- for(uint8_t x = 0; x < MATRIX_COLS; x++) {
- setPinInputHigh(col_pins[x]);
- }
+ return ret;
}
-
-#endif
diff --git a/quantum/split_common/matrix.h b/quantum/split_common/matrix.h
index b5cb45baed..c2bdd3098c 100644
--- a/quantum/split_common/matrix.h
+++ b/quantum/split_common/matrix.h
@@ -1,31 +1,3 @@
-#ifndef SPLIT_COMMON_MATRIX_H
-#define SPLIT_COMMON_MATRIX_H
+#pragma once
#include <common/matrix.h>
-
-#ifdef RGBLIGHT_ENABLE
-# include "rgblight.h"
-#endif
-
-typedef struct _Serial_m2s_buffer_t {
-#ifdef BACKLIGHT_ENABLE
- uint8_t backlight_level;
-#endif
-#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
- rgblight_config_t rgblight_config; //not yet use
- //
- // When MCUs on both sides drive their respective RGB LED chains,
- // it is necessary to synchronize, so it is necessary to communicate RGB information.
- // In that case, define the RGBLIGHT_SPLIT macro.
- //
- // Otherwise, if the master side MCU drives both sides RGB LED chains,
- // there is no need to communicate.
-#endif
-} Serial_m2s_buffer_t;
-
-extern volatile Serial_m2s_buffer_t serial_m2s_buffer;
-
-void serial_master_init(void);
-void serial_slave_init(void);
-
-#endif
diff --git a/quantum/split_common/serial.h b/quantum/split_common/serial.h
index b6638b3bde..1c1e640069 100644
--- a/quantum/split_common/serial.h
+++ b/quantum/split_common/serial.h
@@ -1,5 +1,4 @@
-#ifndef SOFT_SERIAL_H
-#define SOFT_SERIAL_H
+#pragma once
#include <stdbool.h>
@@ -61,5 +60,3 @@ int soft_serial_transaction(int sstd_index);
#ifdef SERIAL_USE_MULTI_TRANSACTION
int soft_serial_get_and_clean_status(int sstd_index);
#endif
-
-#endif /* SOFT_SERIAL_H */
diff --git a/quantum/split_common/split_flags.h b/quantum/split_common/split_flags.h
index f101fff5b5..aaac474a7d 100644
--- a/quantum/split_common/split_flags.h
+++ b/quantum/split_common/split_flags.h
@@ -1,10 +1,9 @@
-#ifndef SPLIT_FLAGS_H
-#define SPLIT_FLAGS_H
+#pragma once
#include <stdbool.h>
#include <stdint.h>
-/**
+/**
* Global Flags
**/
@@ -14,7 +13,3 @@ extern volatile bool RGB_DIRTY;
//Backlight Stuff
extern volatile bool BACKLIT_DIRTY;
-
-
-
-#endif \ No newline at end of file
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index e41b6f6386..5095cb8fdc 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -4,142 +4,84 @@
#include "config.h"
#include "timer.h"
#include "split_flags.h"
+#include "transport.h"
#include "quantum.h"
#ifdef EE_HANDS
# include "tmk_core/common/eeprom.h"
-#endif
-
-#ifdef BACKLIGHT_ENABLE
-# include "backlight.h"
-#endif
-
-#if defined(USE_I2C) || defined(EH)
-# include "i2c.h"
+# include "eeconfig.h"
#endif
volatile bool isLeftHand = true;
-volatile uint8_t setTries = 0;
-
-static void setup_handedness(void) {
+__attribute__((weak))
+bool is_keyboard_left(void) {
#ifdef SPLIT_HAND_PIN
// Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
setPinInput(SPLIT_HAND_PIN);
- isLeftHand = readPin(SPLIT_HAND_PIN);
+ return readPin(SPLIT_HAND_PIN);
#else
#ifdef EE_HANDS
- isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
+ return eeprom_read_byte(EECONFIG_HANDEDNESS);
#else
#ifdef MASTER_RIGHT
- isLeftHand = !has_usb();
+ return !is_keyboard_master();
#else
- isLeftHand = has_usb();
+ return is_keyboard_master();
#endif
#endif
#endif
}
-static void keyboard_master_setup(void) {
-#if defined(USE_I2C) || defined(EH)
- i2c_master_init();
- #ifdef SSD1306OLED
- matrix_master_OLED_init ();
- #endif
-#else
- serial_master_init();
-#endif
+bool is_keyboard_master(void)
+{
+#ifdef __AVR__
+ static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN;
- // For master the Backlight info needs to be sent on startup
- // Otherwise the salve won't start with the proper info until an update
- BACKLIT_DIRTY = true;
-}
+ // only check once, as this is called often
+ if (usbstate == UNKNOWN)
+ {
+ USBCON |= (1 << OTGPADE); // enables VBUS pad
+ wait_us(5);
-static void keyboard_slave_setup(void) {
- timer_init();
-#if defined(USE_I2C) || defined(EH)
- i2c_slave_init(SLAVE_I2C_ADDRESS);
+ usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE; // checks state of VBUS
+ }
+
+ return (usbstate == MASTER);
#else
- serial_slave_init();
+ return true;
#endif
}
-bool has_usb(void) {
- USBCON |= (1 << OTGPADE); //enables VBUS pad
- _delay_us(5);
- return (USBSTA & (1<<VBUS)); //checks state of VBUS
-}
-
-void split_keyboard_setup(void) {
- setup_handedness();
+static void keyboard_master_setup(void) {
+#if defined(USE_I2C) || defined(EH)
+ #ifdef SSD1306OLED
+ matrix_master_OLED_init ();
+ #endif
+#endif
+ transport_master_init();
- if (has_usb()) {
- keyboard_master_setup();
- } else {
- keyboard_slave_setup();
- }
- sei();
+ // For master the Backlight info needs to be sent on startup
+ // Otherwise the salve won't start with the proper info until an update
+ BACKLIT_DIRTY = true;
}
-void keyboard_slave_loop(void) {
- matrix_init();
-
- //Init RGB
- #ifdef RGBLIGHT_ENABLE
- rgblight_init();
- #endif
-
- while (1) {
- // Matrix Slave Scan
- matrix_slave_scan();
-
- // Read Backlight Info
- #ifdef BACKLIGHT_ENABLE
- #ifdef USE_I2C
- if (BACKLIT_DIRTY) {
- backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]);
- BACKLIT_DIRTY = false;
- }
- #else // USE_SERIAL
- backlight_set(serial_m2s_buffer.backlight_level);
- #endif
- #endif
- // Read RGB Info
- #ifdef RGBLIGHT_ENABLE
- #ifdef USE_I2C
- if (RGB_DIRTY) {
- // Disable interupts (RGB data is big)
- cli();
- // Create new DWORD for RGB data
- uint32_t dword;
-
- // Fill the new DWORD with the data that was sent over
- uint8_t *dword_dat = (uint8_t *)(&dword);
- for (int i = 0; i < 4; i++) {
- dword_dat[i] = i2c_slave_buffer[I2C_RGB_START+i];
- }
-
- // Update the RGB now with the new data and set RGB_DIRTY to false
- rgblight_update_dword(dword);
- RGB_DIRTY = false;
- // Re-enable interupts now that RGB is set
- sei();
- }
- #else // USE_SERIAL
- #ifdef RGBLIGHT_SPLIT
- // Add serial implementation for RGB here
- #endif
- #endif
- #endif
- }
+static void keyboard_slave_setup(void)
+{
+ transport_slave_init();
}
// this code runs before the usb and keyboard is initialized
-void matrix_setup(void) {
- split_keyboard_setup();
-
- if (!has_usb()) {
- //rgblight_init();
- keyboard_slave_loop();
- }
+void matrix_setup(void)
+{
+ isLeftHand = is_keyboard_left();
+
+ if (is_keyboard_master())
+ {
+ keyboard_master_setup();
+ }
+ else
+ {
+ keyboard_slave_setup();
+ }
}
diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h
index d6cf3e72a9..20f7535bf4 100644
--- a/quantum/split_common/split_util.h
+++ b/quantum/split_common/split_util.h
@@ -1,23 +1,10 @@
-#ifndef SPLIT_KEYBOARD_UTIL_H
-#define SPLIT_KEYBOARD_UTIL_H
+#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include "eeconfig.h"
-
-#define SLAVE_I2C_ADDRESS 0x32
extern volatile bool isLeftHand;
-// slave version of matix scan, defined in matrix.c
-void matrix_slave_scan(void);
-
-void split_keyboard_setup(void);
-bool has_usb(void);
-void keyboard_slave_loop(void);
-
void matrix_master_OLED_init (void);
-
-#endif
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
new file mode 100644
index 0000000000..95738530ec
--- /dev/null
+++ b/quantum/split_common/transport.c
@@ -0,0 +1,224 @@
+
+#include "config.h"
+#include "matrix.h"
+#include "quantum.h"
+
+#define ROWS_PER_HAND (MATRIX_ROWS/2)
+
+#ifdef RGBLIGHT_ENABLE
+# include "rgblight.h"
+#endif
+
+#ifdef BACKLIGHT_ENABLE
+# include "backlight.h"
+ extern backlight_config_t backlight_config;
+#endif
+
+#if defined(USE_I2C) || defined(EH)
+
+#include "i2c.h"
+
+#ifndef SLAVE_I2C_ADDRESS
+# define SLAVE_I2C_ADDRESS 0x32
+#endif
+
+#if (MATRIX_COLS > 8)
+# error "Currently only supports 8 COLS"
+#endif
+
+// Get rows from other half over i2c
+bool transport_master(matrix_row_t matrix[]) {
+ int err = 0;
+
+ // write backlight info
+#ifdef BACKLIGHT_ENABLE
+ if (BACKLIT_DIRTY) {
+ err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
+ if (err) { goto i2c_error; }
+
+ // Backlight location
+ err = i2c_master_write(I2C_BACKLIT_START);
+ if (err) { goto i2c_error; }
+
+ // Write backlight
+ i2c_master_write(get_backlight_level());
+
+ BACKLIT_DIRTY = false;
+ }
+#endif
+
+ err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
+ if (err) { goto i2c_error; }
+
+ // start of matrix stored at I2C_KEYMAP_START
+ err = i2c_master_write(I2C_KEYMAP_START);
+ if (err) { goto i2c_error; }
+
+ // Start read
+ err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
+ if (err) { goto i2c_error; }
+
+ if (!err) {
+ int i;
+ for (i = 0; i < ROWS_PER_HAND-1; ++i) {
+ matrix[i] = i2c_master_read(I2C_ACK);
+ }
+ matrix[i] = i2c_master_read(I2C_NACK);
+ i2c_master_stop();
+ } else {
+i2c_error: // the cable is disconnceted, or something else went wrong
+ i2c_reset_state();
+ return false;
+ }
+
+#ifdef RGBLIGHT_ENABLE
+ if (RGB_DIRTY) {
+ err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
+ if (err) { goto i2c_error; }
+
+ // RGB Location
+ err = i2c_master_write(I2C_RGB_START);
+ if (err) { goto i2c_error; }
+
+ uint32_t dword = eeconfig_read_rgblight();
+
+ // Write RGB
+ err = i2c_master_write_data(&dword, 4);
+ if (err) { goto i2c_error; }
+
+ RGB_DIRTY = false;
+ i2c_master_stop();
+ }
+#endif
+
+ return true;
+}
+
+void transport_slave(matrix_row_t matrix[]) {
+
+ for (int i = 0; i < ROWS_PER_HAND; ++i)
+ {
+ i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[i];
+ }
+ // Read Backlight Info
+ #ifdef BACKLIGHT_ENABLE
+ if (BACKLIT_DIRTY)
+ {
+ backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]);
+ BACKLIT_DIRTY = false;
+ }
+ #endif
+ #ifdef RGBLIGHT_ENABLE
+ if (RGB_DIRTY)
+ {
+ // Disable interupts (RGB data is big)
+ cli();
+ // Create new DWORD for RGB data
+ uint32_t dword;
+
+ // Fill the new DWORD with the data that was sent over
+ uint8_t * dword_dat = (uint8_t *)(&dword);
+ for (int i = 0; i < 4; i++)
+ {
+ dword_dat[i] = i2c_slave_buffer[I2C_RGB_START + i];
+ }
+
+ // Update the RGB now with the new data and set RGB_DIRTY to false
+ rgblight_update_dword(dword);
+ RGB_DIRTY = false;
+ // Re-enable interupts now that RGB is set
+ sei();
+ }
+ #endif
+}
+
+void transport_master_init(void) {
+ i2c_master_init();
+}
+
+void transport_slave_init(void) {
+ i2c_slave_init(SLAVE_I2C_ADDRESS);
+}
+
+#else // USE_SERIAL
+
+#include "serial.h"
+
+typedef struct _Serial_s2m_buffer_t {
+ // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
+ matrix_row_t smatrix[ROWS_PER_HAND];
+} Serial_s2m_buffer_t;
+
+typedef struct _Serial_m2s_buffer_t {
+#ifdef BACKLIGHT_ENABLE
+ uint8_t backlight_level;
+#endif
+#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
+ rgblight_config_t rgblight_config; //not yet use
+ //
+ // When MCUs on both sides drive their respective RGB LED chains,
+ // it is necessary to synchronize, so it is necessary to communicate RGB information.
+ // In that case, define the RGBLIGHT_SPLIT macro.
+ //
+ // Otherwise, if the master side MCU drives both sides RGB LED chains,
+ // there is no need to communicate.
+#endif
+} Serial_m2s_buffer_t;
+
+volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
+volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
+uint8_t volatile status0 = 0;
+
+SSTD_t transactions[] = {
+ { (uint8_t *)&status0,
+ sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
+ sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
+ }
+};
+
+void transport_master_init(void)
+{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
+
+void transport_slave_init(void)
+{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
+
+bool transport_master(matrix_row_t matrix[]) {
+
+ if (soft_serial_transaction()) {
+ return false;
+ }
+
+ // TODO: if MATRIX_COLS > 8 change to unpack()
+ for (int i = 0; i < ROWS_PER_HAND; ++i) {
+ matrix[i] = serial_s2m_buffer.smatrix[i];
+ }
+
+ #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
+ // Code to send RGB over serial goes here (not implemented yet)
+ #endif
+
+ #ifdef BACKLIGHT_ENABLE
+ // Write backlight level for slave to read
+ serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
+ #endif
+
+ return true;
+}
+
+void transport_slave(matrix_row_t matrix[]) {
+
+ // TODO: if MATRIX_COLS > 8 change to pack()
+ for (int i = 0; i < ROWS_PER_HAND; ++i)
+ {
+ serial_s2m_buffer.smatrix[i] = matrix[i];
+ }
+ #ifdef BACKLIGHT_ENABLE
+ backlight_set(serial_m2s_buffer.backlight_level);
+ #endif
+ #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
+ // Add serial implementation for RGB here
+ #endif
+
+}
+
+#endif
diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h
new file mode 100644
index 0000000000..ccce57e444
--- /dev/null
+++ b/quantum/split_common/transport.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <common/matrix.h>
+
+void transport_master_init(void);
+void transport_slave_init(void);
+
+// returns false if valid data not received from slave
+bool transport_master(matrix_row_t matrix[]);
+void transport_slave(matrix_row_t matrix[]);
diff --git a/quantum/stm32/chconf.h b/quantum/stm32/chconf.h
new file mode 100644
index 0000000000..1d9f12ff1f
--- /dev/null
+++ b/quantum/stm32/chconf.h
@@ -0,0 +1,520 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 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.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 100000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 2
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 0
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM TRUE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY TRUE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/quantum/stm32/halconf.h b/quantum/stm32/halconf.h
new file mode 100644
index 0000000000..8fe8e0c6f5
--- /dev/null
+++ b/quantum/stm32/halconf.h
@@ -0,0 +1,388 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 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.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef HALCONF_H
+#define HALCONF_H
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC TRUE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT TRUE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the QSPI subsystem.
+ */
+#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__)
+#define HAL_USE_QSPI FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB TRUE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 16 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 1
+#endif
+
+/**
+ * @brief Serial over USB number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_NUMBER 2
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* UART driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
+#define UART_USE_WAIT FALSE
+#endif
+
+/**
+ * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define UART_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* HALCONF_H */
+
+/** @} */
diff --git a/quantum/stm32/mcuconf.h b/quantum/stm32/mcuconf.h
new file mode 100644
index 0000000000..7c3c6e570c
--- /dev/null
+++ b/quantum/stm32/mcuconf.h
@@ -0,0 +1,257 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 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.
+*/
+
+#ifndef MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * STM32F3xx drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 15...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+#define STM32F3xx_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#define STM32_NO_INIT FALSE
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+#define STM32_HSI_ENABLED TRUE
+#define STM32_LSI_ENABLED TRUE
+#define STM32_HSE_ENABLED TRUE
+#define STM32_LSE_ENABLED FALSE
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#define STM32_PREDIV_VALUE 1
+#define STM32_PLLMUL_VALUE 9
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE1 STM32_PPRE1_DIV2
+#define STM32_PPRE2 STM32_PPRE2_DIV2
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#define STM32_ADC12PRES STM32_ADC12PRES_DIV1
+#define STM32_ADC34PRES STM32_ADC34PRES_DIV1
+#define STM32_USART1SW STM32_USART1SW_PCLK
+#define STM32_USART2SW STM32_USART2SW_PCLK
+#define STM32_USART3SW STM32_USART3SW_PCLK
+#define STM32_UART4SW STM32_UART4SW_PCLK
+#define STM32_UART5SW STM32_UART5SW_PCLK
+#define STM32_I2C1SW STM32_I2C1SW_SYSCLK
+#define STM32_I2C2SW STM32_I2C2SW_SYSCLK
+#define STM32_TIM1SW STM32_TIM1SW_PCLK2
+#define STM32_TIM8SW STM32_TIM8SW_PCLK2
+#define STM32_RTCSEL STM32_RTCSEL_LSI
+#define STM32_USB_CLOCK_REQUIRED TRUE
+#define STM32_USBPRE STM32_USBPRE_DIV1P5
+
+#undef STM32_HSE_BYPASS
+// #error "oh no"
+// #endif
+
+/*
+ * ADC driver system settings.
+ */
+#define STM32_ADC_DUAL_MODE FALSE
+#define STM32_ADC_COMPACT_SAMPLES FALSE
+#define STM32_ADC_USE_ADC1 FALSE
+#define STM32_ADC_USE_ADC2 FALSE
+#define STM32_ADC_USE_ADC3 FALSE
+#define STM32_ADC_USE_ADC4 FALSE
+#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
+#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
+#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
+#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#define STM32_ADC_ADC2_DMA_PRIORITY 2
+#define STM32_ADC_ADC3_DMA_PRIORITY 2
+#define STM32_ADC_ADC4_DMA_PRIORITY 2
+#define STM32_ADC_ADC12_IRQ_PRIORITY 5
+#define STM32_ADC_ADC3_IRQ_PRIORITY 5
+#define STM32_ADC_ADC4_IRQ_PRIORITY 5
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
+#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
+#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
+#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5
+#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
+
+/*
+ * CAN driver system settings.
+ */
+#define STM32_CAN_USE_CAN1 FALSE
+#define STM32_CAN_CAN1_IRQ_PRIORITY 11
+
+/*
+ * DAC driver system settings.
+ */
+#define STM32_DAC_DUAL_MODE FALSE
+#define STM32_DAC_USE_DAC1_CH1 TRUE
+#define STM32_DAC_USE_DAC1_CH2 TRUE
+#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
+#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
+#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
+#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
+
+/*
+ * EXT driver system settings.
+ */
+#define STM32_EXT_EXTI0_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI1_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI2_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI3_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI4_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI16_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI17_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI18_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI19_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI20_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI30_32_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI33_IRQ_PRIORITY 6
+
+/*
+ * GPT driver system settings.
+ */
+#define STM32_GPT_USE_TIM1 FALSE
+#define STM32_GPT_USE_TIM2 FALSE
+#define STM32_GPT_USE_TIM3 FALSE
+#define STM32_GPT_USE_TIM4 FALSE
+#define STM32_GPT_USE_TIM6 TRUE
+#define STM32_GPT_USE_TIM7 TRUE
+#define STM32_GPT_USE_TIM8 TRUE
+#define STM32_GPT_TIM1_IRQ_PRIORITY 7
+#define STM32_GPT_TIM2_IRQ_PRIORITY 7
+#define STM32_GPT_TIM3_IRQ_PRIORITY 7
+#define STM32_GPT_TIM4_IRQ_PRIORITY 7
+#define STM32_GPT_TIM6_IRQ_PRIORITY 7
+#define STM32_GPT_TIM7_IRQ_PRIORITY 7
+#define STM32_GPT_TIM8_IRQ_PRIORITY 7
+
+/*
+ * I2C driver system settings.
+ */
+#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_BUSY_TIMEOUT 50
+#define STM32_I2C_I2C1_IRQ_PRIORITY 10
+#define STM32_I2C_I2C2_IRQ_PRIORITY 10
+#define STM32_I2C_USE_DMA TRUE
+#define STM32_I2C_I2C1_DMA_PRIORITY 1
+#define STM32_I2C_I2C2_DMA_PRIORITY 1
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define STM32_ICU_USE_TIM1 FALSE
+#define STM32_ICU_USE_TIM2 FALSE
+#define STM32_ICU_USE_TIM3 FALSE
+#define STM32_ICU_USE_TIM4 FALSE
+#define STM32_ICU_USE_TIM8 FALSE
+#define STM32_ICU_TIM1_IRQ_PRIORITY 7
+#define STM32_ICU_TIM2_IRQ_PRIORITY 7
+#define STM32_ICU_TIM3_IRQ_PRIORITY 7
+#define STM32_ICU_TIM4_IRQ_PRIORITY 7
+#define STM32_ICU_TIM8_IRQ_PRIORITY 7
+
+/*
+ * PWM driver system settings.
+ */
+#define STM32_PWM_USE_ADVANCED FALSE
+#define STM32_PWM_USE_TIM1 FALSE
+#define STM32_PWM_USE_TIM2 TRUE
+#define STM32_PWM_USE_TIM3 TRUE
+#define STM32_PWM_USE_TIM4 FALSE
+#define STM32_PWM_USE_TIM8 FALSE
+#define STM32_PWM_TIM1_IRQ_PRIORITY 7
+#define STM32_PWM_TIM2_IRQ_PRIORITY 7
+#define STM32_PWM_TIM3_IRQ_PRIORITY 7
+#define STM32_PWM_TIM4_IRQ_PRIORITY 7
+#define STM32_PWM_TIM8_IRQ_PRIORITY 7
+
+/*
+ * SERIAL driver system settings.
+ */
+#define STM32_SERIAL_USE_USART1 FALSE
+#define STM32_SERIAL_USE_USART2 TRUE
+#define STM32_SERIAL_USE_USART3 FALSE
+#define STM32_SERIAL_USE_UART4 FALSE
+#define STM32_SERIAL_USE_UART5 FALSE
+#define STM32_SERIAL_USART1_PRIORITY 12
+#define STM32_SERIAL_USART2_PRIORITY 12
+#define STM32_SERIAL_USART3_PRIORITY 12
+#define STM32_SERIAL_UART4_PRIORITY 12
+#define STM32_SERIAL_UART5_PRIORITY 12
+
+/*
+ * SPI driver system settings.
+ */
+#define STM32_SPI_USE_SPI1 FALSE
+#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_USE_SPI3 FALSE
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#define STM32_SPI_SPI3_DMA_PRIORITY 1
+#define STM32_SPI_SPI1_IRQ_PRIORITY 10
+#define STM32_SPI_SPI2_IRQ_PRIORITY 10
+#define STM32_SPI_SPI3_IRQ_PRIORITY 10
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+/*
+ * ST driver system settings.
+ */
+#define STM32_ST_IRQ_PRIORITY 8
+#define STM32_ST_USE_TIMER 2
+
+/*
+ * UART driver system settings.
+ */
+#define STM32_UART_USE_USART1 FALSE
+#define STM32_UART_USE_USART2 FALSE
+#define STM32_UART_USE_USART3 FALSE
+#define STM32_UART_USART1_IRQ_PRIORITY 12
+#define STM32_UART_USART2_IRQ_PRIORITY 12
+#define STM32_UART_USART3_IRQ_PRIORITY 12
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#define STM32_UART_USART3_DMA_PRIORITY 0
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define STM32_USB_USE_USB1 TRUE
+#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
+#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
+#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
+
+/*
+ * WDG driver system settings.
+ */
+#define STM32_WDG_USE_IWDG FALSE
+
+#endif /* MCUCONF_H */
diff --git a/quantum/stm32/proton_c.mk b/quantum/stm32/proton_c.mk
new file mode 100644
index 0000000000..a0fa013736
--- /dev/null
+++ b/quantum/stm32/proton_c.mk
@@ -0,0 +1,44 @@
+# Proton C MCU settings for converting AVR projects
+
+# These are defaults based on what has been implemented for ARM boards
+AUDIO_ENABLE = yes
+RGBLIGHT_ENABLE = no
+BACKLIGHT_ENABLE = no
+
+# The rest of these settings shouldn't change
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+MCU_FAMILY = STM32
+MCU_SERIES = STM32F3xx
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+MCU_LDSCRIPT = STM32F303xC
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+MCU_STARTUP = stm32f3xx
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+BOARD = GENERIC_STM32_F303XC
+
+# Cortex version
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ARMV = 7
+
+USE_FPU = yes
+
+# Vector table for application
+# 0x00000000-0x00001000 area is occupied by bootlaoder.*/
+# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
+# OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000
+OPT_DEFS =
+
+# Options to pass to dfu-util when flashing
+DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave
diff --git a/quantum/template/avr/config.h b/quantum/template/avr/config.h
index eed50e5c04..d05b2cb98d 100644
--- a/quantum/template/avr/config.h
+++ b/quantum/template/avr/config.h
@@ -1,5 +1,5 @@
/*
-Copyright 2018 REPLACE_WITH_YOUR_NAME
+Copyright 2019 REPLACE_WITH_YOUR_NAME
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
diff --git a/quantum/template/avr/template.c b/quantum/template/avr/template.c
index b6366fd9a3..3deeae88ba 100644
--- a/quantum/template/avr/template.c
+++ b/quantum/template/avr/template.c
@@ -1,4 +1,4 @@
-/* Copyright 2018 REPLACE_WITH_YOUR_NAME
+/* Copyright 2019 REPLACE_WITH_YOUR_NAME
*
* 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
diff --git a/quantum/template/avr/template.h b/quantum/template/avr/template.h
deleted file mode 100644
index 0d626ed50b..0000000000
--- a/quantum/template/avr/template.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright 2018 REPLACE_WITH_YOUR_NAME
- *
- * 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/>.
- */
-#ifndef %KEYBOARD_UPPERCASE%_H
-#define %KEYBOARD_UPPERCASE%_H
-
-#include "quantum.h"
-
-/* This a shortcut to help you visually see your layout.
- *
- * The first section contains all of the arguments representing the physical
- * layout of the board and position of the keys.
- *
- * The second converts the arguments into a two-dimensional array which
- * represents the switch matrix.
- */
-#define LAYOUT( \
- K00, K01, K02, \
- K10, K11 \
-) \
-{ \
- { K00, K01, K02 }, \
- { K10, KC_NO, K11 }, \
-}
-
-#endif
diff --git a/quantum/template/base/keymaps/default/config.h b/quantum/template/base/keymaps/default/config.h
index 4496c59100..c8e4334124 100644
--- a/quantum/template/base/keymaps/default/config.h
+++ b/quantum/template/base/keymaps/default/config.h
@@ -1,4 +1,4 @@
-/* Copyright 2018 REPLACE_WITH_YOUR_NAME
+/* Copyright 2019 REPLACE_WITH_YOUR_NAME
*
* 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
diff --git a/quantum/template/base/keymaps/default/keymap.c b/quantum/template/base/keymaps/default/keymap.c
index 5f0730c8a9..11cd134a06 100644
--- a/quantum/template/base/keymaps/default/keymap.c
+++ b/quantum/template/base/keymaps/default/keymap.c
@@ -1,4 +1,4 @@
-/* Copyright 2018 REPLACE_WITH_YOUR_NAME
+/* Copyright 2019 REPLACE_WITH_YOUR_NAME
*
* 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
diff --git a/quantum/template/ps2avrgb/template.h b/quantum/template/base/template.h
index b4d6f46624..caf2abb4c6 100644
--- a/quantum/template/ps2avrgb/template.h
+++ b/quantum/template/base/template.h
@@ -1,4 +1,4 @@
-/* Copyright 2018 REPLACE_WITH_YOUR_NAME
+/* Copyright 2019 REPLACE_WITH_YOUR_NAME
*
* 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
@@ -13,8 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef %KEYBOARD_UPPERCASE%_H
-#define %KEYBOARD_UPPERCASE%_H
+#pragma once
#include "quantum.h"
@@ -34,5 +33,3 @@
{ k00, k01, k02 }, \
{ k10, KC_NO, k11 }, \
}
-
-#endif
diff --git a/quantum/template/ps2avrgb/rules.mk b/quantum/template/ps2avrgb/rules.mk
index 85603f955c..bcd7dff999 100644
--- a/quantum/template/ps2avrgb/rules.mk
+++ b/quantum/template/ps2avrgb/rules.mk
@@ -1,4 +1,4 @@
-# Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>
+# Copyright 2019 Luiz Ribeiro <luizribeiro@gmail.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
diff --git a/quantum/template/ps2avrgb/template.c b/quantum/template/ps2avrgb/template.c
index 8bbf9ebda5..4e35a2c129 100644
--- a/quantum/template/ps2avrgb/template.c
+++ b/quantum/template/ps2avrgb/template.c
@@ -1,4 +1,4 @@
-/* Copyright 2018 REPLACE_WITH_YOUR_NAME
+/* Copyright 2019 REPLACE_WITH_YOUR_NAME
*
* 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