From 3775c92ff88cbd72f53ed97709932a5352495092 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 23 Jun 2018 00:14:22 +0300 Subject: [PATCH 1/7] Fix missing brackets warning --- drivers/qwiic/qwiic_keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 52c7d87935..8542a9f2b9 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -43,7 +43,7 @@ uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; -uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {0}; +uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}}; uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; uint8_t qwiic_keyboard_processing_slave = false; From c11c7948e6c6814aa9df509c2d718b200820da60 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 17:10:03 +0300 Subject: [PATCH 2/7] Make the layer cache more efficient Also change the internal representation to a one dimensional array --- tests/layer_cache/config.h | 21 ++++ tests/layer_cache/keymap.c | 24 +++++ tests/layer_cache/rules.mk | 16 +++ tests/layer_cache/test_layer_cache.cpp | 140 +++++++++++++++++++++++++ tmk_core/common/action_layer.c | 75 +++++++++---- 5 files changed, 256 insertions(+), 20 deletions(-) create mode 100644 tests/layer_cache/config.h create mode 100644 tests/layer_cache/keymap.c create mode 100644 tests/layer_cache/rules.mk create mode 100644 tests/layer_cache/test_layer_cache.cpp diff --git a/tests/layer_cache/config.h b/tests/layer_cache/config.h new file mode 100644 index 0000000000..656cedb338 --- /dev/null +++ b/tests/layer_cache/config.h @@ -0,0 +1,21 @@ +/* Copyright 2018 Fred Sundvik + * + * 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 . + */ + +#pragma once + +#define MATRIX_ROWS 2 +#define MATRIX_COLS 2 +#define PREVENT_STUCK_MODIFIERS diff --git a/tests/layer_cache/keymap.c b/tests/layer_cache/keymap.c new file mode 100644 index 0000000000..d310bff8b9 --- /dev/null +++ b/tests/layer_cache/keymap.c @@ -0,0 +1,24 @@ +/* Copyright 2018 Fred Sundvik + * + * 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 . + */ + +#include "quantum.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = { + {KC_A, KC_B}, + {KC_C, KC_D}, + } +}; diff --git a/tests/layer_cache/rules.mk b/tests/layer_cache/rules.mk new file mode 100644 index 0000000000..9b8615f954 --- /dev/null +++ b/tests/layer_cache/rules.mk @@ -0,0 +1,16 @@ +# Copyright 2018 Fred Sundvik +# +# 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 . + +CUSTOM_MATRIX=yes diff --git a/tests/layer_cache/test_layer_cache.cpp b/tests/layer_cache/test_layer_cache.cpp new file mode 100644 index 0000000000..4aebe24b74 --- /dev/null +++ b/tests/layer_cache/test_layer_cache.cpp @@ -0,0 +1,140 @@ +/* Copyright 2018 Fred Sundvik + * + * 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 . + */ + +#include "test_common.hpp" + +#if MAX_LAYER_BITS != 5 +#error "Tese tests assume that the MAX_LAYER_BITS is equal to 5" +// If this is changed, change the constants below +#endif + +#if MATRIX_COLS != 2 || MATRIX_ROWS !=2 +#error "These tests assume that the second row starts after the second column" +#endif + +namespace +{ + constexpr uint8_t max_layer_value = 0b11111; + constexpr uint8_t min_layer_value = 0; + constexpr uint8_t alternating_starting_with_1 = 0b10101; + constexpr uint8_t alternating_starting_with_0 = 0b01010; + + + uint8_t read_cache(uint8_t col, uint8_t row) { + keypos_t key; + key.col = col; + key.row = row; + return read_source_layers_cache(key); + } + + void write_cache(uint8_t col, uint8_t row, uint8_t value) { + keypos_t key; + key.col = col; + key.row = row; + return update_source_layers_cache(key, value); + } + + void fill_cache() { + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + write_cache(j, i, max_layer_value); + } + } + } + + void clear_cache() { + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + write_cache(j, i, min_layer_value); + } + } + } +} + +class LayerCache : public testing::Test +{ +public: + LayerCache() + { + clear_cache(); + } +}; + +TEST_F(LayerCache, LayerCacheIsInitializedToZero) { + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + EXPECT_EQ(read_cache(j, i), min_layer_value); + } + } +} + +TEST_F(LayerCache, FillAndClearCache) { + fill_cache(); + clear_cache(); + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + EXPECT_EQ(read_cache(j, i), min_layer_value); + } + } +} + +TEST_F(LayerCache, WriteAndReadFirstPosMaximumValue) { + write_cache(0, 0, max_layer_value); + EXPECT_EQ(read_cache(0, 0), max_layer_value); + // The second position should not be updated + EXPECT_EQ(read_cache(1, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadSecondPosMaximumValue) { + write_cache(1, 0, max_layer_value); + EXPECT_EQ(read_cache(1, 0), max_layer_value); + // The surrounding positions should not be updated + EXPECT_EQ(read_cache(0, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadFirstPosAlternatingBitsStartingWith1) { + write_cache(0, 0, alternating_starting_with_1); + EXPECT_EQ(read_cache(0, 0), alternating_starting_with_1); + // The second position should not be updated + EXPECT_EQ(read_cache(1, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadSecondPosAlternatingBitsStartingWith1) { + write_cache(1, 0, alternating_starting_with_1); + EXPECT_EQ(read_cache(1, 0), alternating_starting_with_1); + // The surrounding positions should not be updated + EXPECT_EQ(read_cache(0, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadFirstPosAlternatingBitsStartingWith0) { + write_cache(0, 0, alternating_starting_with_0); + EXPECT_EQ(read_cache(0, 0), alternating_starting_with_0); + // The second position should not be updated + EXPECT_EQ(read_cache(1, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadSecondPosAlternatingBitsStartingWith0) { + write_cache(1, 0, alternating_starting_with_0); + EXPECT_EQ(read_cache(1, 0), alternating_starting_with_0); + // The surrounding positions should not be updated + EXPECT_EQ(read_cache(0, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index f3cd381ab0..a1ead402c8 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -220,37 +220,72 @@ void layer_debug(void) #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) -uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}}; +uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; +static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; void update_source_layers_cache(keypos_t key, uint8_t layer) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; + const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint32_t bit_number = key_number * MAX_LAYER_BITS; + const uint16_t byte_number = bit_number / 8; + if (byte_number >= sizeof(source_layers_cache)) { + return; + } + const uint8_t bit_position = bit_number % 8; + int8_t shift = 16 - MAX_LAYER_BITS - bit_position; - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - source_layers_cache[storage_row][bit_number] ^= - (-((layer & (1U << bit_number)) != 0) - ^ source_layers_cache[storage_row][bit_number]) - & (1U << storage_bit); + if (shift > 8 ) { + // We need to write only one byte + shift -= 8; + const uint8_t mask = layer_cache_mask << shift; + const uint8_t shifted_layer = layer << shift; + source_layers_cache[byte_number] = (shifted_layer & mask) | (source_layers_cache[byte_number] & (~mask)); + } else { + if (byte_number + 1 >= sizeof(source_layers_cache)) { + return; } + // We need to write two bytes + uint16_t value = layer; + uint16_t mask = layer_cache_mask; + value <<= shift; + mask <<= shift; + + uint16_t masked_value = value & mask; + uint16_t inverse_mask = ~mask; + + // This could potentially be done with a single write, but then we have to assume the endian + source_layers_cache[byte_number + 1] = masked_value | (source_layers_cache[byte_number + 1] & (inverse_mask)); + masked_value >>= 8; + inverse_mask >>= 8; + source_layers_cache[byte_number] = masked_value | (source_layers_cache[byte_number] & (inverse_mask)); + } } uint8_t read_source_layers_cache(keypos_t key) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; - uint8_t layer = 0; + const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint32_t bit_number = key_number * MAX_LAYER_BITS; + const uint16_t byte_number = bit_number / 8; + if (byte_number >= sizeof(source_layers_cache)) { + return 0; + } + const uint8_t bit_position = bit_number % 8; - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - layer |= - ((source_layers_cache[storage_row][bit_number] - & (1U << storage_bit)) != 0) - << bit_number; + int8_t shift = 16 - MAX_LAYER_BITS - bit_position; + + if (shift > 8 ) { + // We need to read only one byte + shift -= 8; + return (source_layers_cache[byte_number] >> shift) & layer_cache_mask; + } else { + if (byte_number + 1 >= sizeof(source_layers_cache)) { + return 0; } - - return layer; + // Otherwise read two bytes + // This could potentially be done with a single read, but then we have to assume the endian + uint16_t value = source_layers_cache[byte_number] << 8 | source_layers_cache[byte_number + 1]; + return (value >> shift) & layer_cache_mask; + } } #endif From f9c61b1bbe14ffb9d00107fcb68e86dcba6eb22a Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 17:21:00 +0300 Subject: [PATCH 3/7] Add a keymatrix_t type This contains both the matrix number and key position, in preparation for multi-matrix support --- drivers/qwiic/qwiic_keyboard.c | 16 +++++++--------- .../planck/old_keymap_files/keymap_common.c | 2 +- quantum/keymap.h | 2 +- quantum/keymap_common.c | 8 +++++--- quantum/process_keycode/process_music.c | 13 +++++++------ quantum/quantum.c | 2 +- tests/layer_cache/test_layer_cache.cpp | 14 ++++++++------ tmk_core/common/action.c | 2 +- tmk_core/common/action.h | 4 ++-- tmk_core/common/action_layer.c | 14 +++++++------- tmk_core/common/action_layer.h | 10 +++++----- tmk_core/common/bootmagic.c | 2 +- tmk_core/common/keyboard.c | 3 ++- tmk_core/common/keyboard.h | 16 +++++++++++----- 14 files changed, 59 insertions(+), 49 deletions(-) diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 8542a9f2b9..8e3591fd9d 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -80,7 +80,6 @@ void qwiic_keyboard_task(void) { #ifdef QMK_KEYS_PER_SCAN uint8_t keys_processed = 0; #endif - qwiic_keyboard_processing_slave = true; for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) { matrix_row = qwiic_keyboard_matrix_message[r]; matrix_change = matrix_row ^ matrix_prev[r]; @@ -88,7 +87,8 @@ void qwiic_keyboard_task(void) { for (uint8_t c = 0; c < QWIIC_KEYBOARD_COLS; c++) { if (matrix_change & ((qwiic_matrix_t)1<. /* translates key to keycode */ -uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key) +uint8_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key) { return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); } diff --git a/quantum/keymap.h b/quantum/keymap.h index bfcb2f7cd5..734d128573 100644 --- a/quantum/keymap.h +++ b/quantum/keymap.h @@ -44,7 +44,7 @@ along with this program. If not, see . #include "quantum_keycodes.h" // translates key to keycode -uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key); +uint16_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key); // translates function id to action uint16_t keymap_function_id_to_action( uint16_t function_id ); diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 9a412b66ad..d68001bb65 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -38,7 +38,7 @@ extern keymap_config_t keymap_config; #include /* converts key to action */ -action_t action_for_key(uint8_t layer, keypos_t key) +action_t action_for_key(uint8_t layer, keymatrix_t key) { // 16bit keycodes - important uint16_t keycode = keymap_key_to_keycode(layer, key); @@ -184,10 +184,12 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) // translates key to keycode __attribute__ ((weak)) -uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) +uint16_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key) { // Read entire word (16bits) - return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]); + // The default implmention does not have multiple matrix support + // and therfore it ignores the matrix field of the key + return pgm_read_word(&keymaps[(layer)][(key.pos.row)][(key.pos.col)]); } // translates function id to action diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 697aa237fa..fc6de4350a 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -198,22 +198,23 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } uint8_t note = 36; + // Note: Multimatrix support is missing from this (it's probablly better to define it using keycodes) #ifdef MUSIC_MAP if (music_mode == MUSIC_MODE_CHROMATIC) { - note = music_starting_note + music_offset + 36 + music_map[record->event.key.row][record->event.key.col]; + note = music_starting_note + music_offset + 36 + music_map[record->event.key.pos.row][record->event.key.pos.col]; } else { - uint8_t position = music_map[record->event.key.row][record->event.key.col]; + uint8_t position = music_map[record->event.key.pos.row][record->event.key.pos.col]; note = music_starting_note + music_offset + 36 + SCALE[position % 12] + (position / 12)*12; } #else if (music_mode == MUSIC_MODE_CHROMATIC) - note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + record->event.key.pos.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.pos.row); else if (music_mode == MUSIC_MODE_GUITAR) - note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + record->event.key.pos.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.pos.row); else if (music_mode == MUSIC_MODE_VIOLIN) - note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + record->event.key.pos.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.pos.row); else if (music_mode == MUSIC_MODE_MAJOR) - note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + SCALE[record->event.key.pos.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.pos.row); else note = music_starting_note; #endif diff --git a/quantum/quantum.c b/quantum/quantum.c index 331ed5634c..086c1160b4 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -190,7 +190,7 @@ static bool grave_esc_was_shifted = false; bool process_record_quantum(keyrecord_t *record) { /* This gets the keycode from the key pressed */ - keypos_t key = record->event.key; + keymatrix_t key = record->event.key; uint16_t keycode; #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) diff --git a/tests/layer_cache/test_layer_cache.cpp b/tests/layer_cache/test_layer_cache.cpp index 4aebe24b74..cc58cbbdba 100644 --- a/tests/layer_cache/test_layer_cache.cpp +++ b/tests/layer_cache/test_layer_cache.cpp @@ -34,16 +34,18 @@ namespace uint8_t read_cache(uint8_t col, uint8_t row) { - keypos_t key; - key.col = col; - key.row = row; + keymatrix_t key; + key.pos.col = col; + key.pos.row = row; + key.matrix = 0; return read_source_layers_cache(key); } void write_cache(uint8_t col, uint8_t row, uint8_t value) { - keypos_t key; - key.col = col; - key.row = row; + keymatrix_t key; + key.pos.col = col; + key.pos.row = row; + key.matrix = 0; return update_source_layers_cache(key, value); } diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index f7c039f457..cfc933fb28 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -892,7 +892,7 @@ void clear_keyboard_but_mods(void) * * FIXME: Needs documentation. */ -bool is_tap_key(keypos_t key) +bool is_tap_key(keymatrix_t key) { action_t action = layer_switch_get_action(key); diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index acc55c7d38..7b69c6c282 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -50,7 +50,7 @@ typedef struct { void action_exec(keyevent_t event); /* action for key */ -action_t action_for_key(uint8_t layer, keypos_t key); +action_t action_for_key(uint8_t layer, keymatrix_t key); /* macro */ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); @@ -94,7 +94,7 @@ void unregister_mods(uint8_t mods); void clear_keyboard(void); void clear_keyboard_but_mods(void); void layer_switch(uint8_t new_layer); -bool is_tap_key(keypos_t key); +bool is_tap_key(keymatrix_t key); #ifndef NO_ACTION_TAPPING void process_record_tap_hint(keyrecord_t *record); diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index a1ead402c8..6bcf3d935d 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -223,9 +223,9 @@ void layer_debug(void) uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; -void update_source_layers_cache(keypos_t key, uint8_t layer) +void update_source_layers_cache(keymatrix_t key, uint8_t layer) { - const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; if (byte_number >= sizeof(source_layers_cache)) { @@ -261,9 +261,9 @@ void update_source_layers_cache(keypos_t key, uint8_t layer) } } -uint8_t read_source_layers_cache(keypos_t key) +uint8_t read_source_layers_cache(keymatrix_t key) { - const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; if (byte_number >= sizeof(source_layers_cache)) { @@ -296,7 +296,7 @@ uint8_t read_source_layers_cache(keypos_t key) * when the layer is switched after the down event but before the up * event as they may get stuck otherwise. */ -action_t store_or_get_action(bool pressed, keypos_t key) +action_t store_or_get_action(bool pressed, keymatrix_t key) { #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) if (disable_action_cache) { @@ -323,7 +323,7 @@ action_t store_or_get_action(bool pressed, keypos_t key) * * FIXME: Needs docs */ -int8_t layer_switch_get_layer(keypos_t key) +int8_t layer_switch_get_layer(keymatrix_t key) { #ifndef NO_ACTION_LAYER action_t action; @@ -350,7 +350,7 @@ int8_t layer_switch_get_layer(keypos_t key) * * FIXME: Needs docs */ -action_t layer_switch_get_action(keypos_t key) +action_t layer_switch_get_action(keymatrix_t key) { return action_for_key(layer_switch_get_layer(key), key); } diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h index 72a6bd8f68..8f47fb0c96 100644 --- a/tmk_core/common/action_layer.h +++ b/tmk_core/common/action_layer.h @@ -91,15 +91,15 @@ uint32_t layer_state_set_kb(uint32_t state); #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) /* The number of bits needed to represent the layer number: log2(32). */ #define MAX_LAYER_BITS 5 -void update_source_layers_cache(keypos_t key, uint8_t layer); -uint8_t read_source_layers_cache(keypos_t key); +void update_source_layers_cache(keymatrix_t key, uint8_t layer); +uint8_t read_source_layers_cache(keymatrix_t key); #endif -action_t store_or_get_action(bool pressed, keypos_t key); +action_t store_or_get_action(bool pressed, keymatrix_t key); /* return the topmost non-transparent layer currently associated with key */ -int8_t layer_switch_get_layer(keypos_t key); +int8_t layer_switch_get_layer(keymatrix_t key); /* return action depending on current layer status */ -action_t layer_switch_get_action(keypos_t key); +action_t layer_switch_get_action(keymatrix_t key); #endif diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c index 9f79fb8eed..828769c322 100644 --- a/tmk_core/common/bootmagic.c +++ b/tmk_core/common/bootmagic.c @@ -116,7 +116,7 @@ static bool scan_keycode(uint8_t keycode) matrix_row_t matrix_row = matrix_get_row(r); for (uint8_t c = 0; c < MATRIX_COLS; c++) { if (matrix_row & ((matrix_row_t)1< Date: Fri, 29 Jun 2018 20:48:08 +0300 Subject: [PATCH 4/7] Add proper multimatrix support --- drivers/qwiic/qwiic_keyboard.c | 87 +++++++++---------- tmk_core/common/action_layer.c | 49 ++++++++--- tmk_core/common/action_layer.h | 2 + tmk_core/common/keyboard.c | 151 +++++++++++++++++++++++++-------- tmk_core/common/keyboard.h | 3 + 5 files changed, 195 insertions(+), 97 deletions(-) diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 8e3591fd9d..4c7e22fdee 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -37,15 +37,15 @@ void qwiic_keyboard_write_keymap(uint8_t * pointer); void qwiic_keyboard_read_keymap(uint8_t * pointer); -bool qwiic_keyboard_master = false; -bool qwiic_keyboard_connected = false; -uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] = {0}; -uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; -twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; +static bool qwiic_keyboard_master = false; +static bool qwiic_keyboard_connected = false; +static uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] = {0}; +static uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; +static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS] = {0}; +static twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; -uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}}; -uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; -uint8_t qwiic_keyboard_processing_slave = false; +static uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}}; +static uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; void qwiic_keyboard_init(void) { twi2c_init(); @@ -69,50 +69,10 @@ void qwiic_keyboard_task(void) { if (qwiic_keyboard_master) { if (qwiic_keyboard_connected) { // send empty message, expecting matrix info - if (MSG_OK == twi2c_transmit_receive(qwiic_keyboard_listening_address, + if (MSG_OK != twi2c_transmit_receive(qwiic_keyboard_listening_address, command, 1, qwiic_keyboard_matrix_message, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE )) { - // majority of this is pulled from keyboard.c:keyboard_task() - static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS]; - qwiic_matrix_t matrix_row = 0; - qwiic_matrix_t matrix_change = 0; - #ifdef QMK_KEYS_PER_SCAN - uint8_t keys_processed = 0; - #endif - for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) { - matrix_row = qwiic_keyboard_matrix_message[r]; - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { - for (uint8_t c = 0; c < QWIIC_KEYBOARD_COLS; c++) { - if (matrix_change & ((qwiic_matrix_t)1<= QMK_KEYS_PER_SCAN) - #endif - // process a key per task call - goto QWIIC_MATRIX_LOOP_END; - } - } - } - } - // call with pseudo tick event when no real key event. - #ifdef QMK_KEYS_PER_SCAN - // we can get here with some keys processed now. - if (!keys_processed) - #endif - action_exec(TICK); - QWIIC_MATRIX_LOOP_END: - qwiic_keyboard_processing_slave = false; - } else { // disconnect // qwiic_keyboard_connected = false; } @@ -198,3 +158,32 @@ uint16_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key) { return qwiic_keyboard_keymap[(layer)][(key.pos.row)][(key.pos.col)]; } } + +uint8_t multimatrix_get_num_matrices(void) { + return qwiic_keyboard_connected ? 1 : 0; +} + +uint8_t multimatrix_get_num_cols(uint8_t matrix) { + return QWIIC_KEYBOARD_COLS; +} + +uint8_t multimatrix_get_num_rows(uint8_t matrix) { + return QWIIC_KEYBOARD_ROWS; +} + +uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) { +return qwiic_keyboard_matrix_message[row]; +} + +uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) { + return matrix_prev[row]; +} + +void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { + matrix_prev[row] = value; +} + +uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) { + static uint8_t source_layers_cache[(QWIIC_KEYBOARD_ROWS * QWIIC_KEYBOARD_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; + return source_layers_cache; +} diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index 6bcf3d935d..f01a3d99d8 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -220,15 +220,32 @@ void layer_debug(void) #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) -uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; +__attribute__((weak)) +uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) { + return 0; +} + +static uint8_t* get_source_layers_cache(keymatrix_t key) { + if (key.matrix == 0) { + static uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; + return source_layers_cache; + } else { + return multimatrix_get_source_layers_cache(key.matrix - 1); + } +} + void update_source_layers_cache(keymatrix_t key, uint8_t layer) { - const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); + const uint8_t num_cols = keyboard_get_num_cols(key.matrix); + const uint8_t num_rows = keyboard_get_num_rows(key.matrix); + const uint16_t num_cache_bytes = get_source_layers_cache_size(num_cols, num_rows); + uint8_t* cache = get_source_layers_cache(key); + const uint16_t key_number = key.pos.col + (key.pos.row * num_cols); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; - if (byte_number >= sizeof(source_layers_cache)) { + if (byte_number >= num_cache_bytes) { return; } const uint8_t bit_position = bit_number % 8; @@ -239,9 +256,9 @@ void update_source_layers_cache(keymatrix_t key, uint8_t layer) shift -= 8; const uint8_t mask = layer_cache_mask << shift; const uint8_t shifted_layer = layer << shift; - source_layers_cache[byte_number] = (shifted_layer & mask) | (source_layers_cache[byte_number] & (~mask)); + cache[byte_number] = (shifted_layer & mask) | (cache[byte_number] & (~mask)); } else { - if (byte_number + 1 >= sizeof(source_layers_cache)) { + if (byte_number + 1 >= num_cache_bytes) { return; } // We need to write two bytes @@ -254,19 +271,23 @@ void update_source_layers_cache(keymatrix_t key, uint8_t layer) uint16_t inverse_mask = ~mask; // This could potentially be done with a single write, but then we have to assume the endian - source_layers_cache[byte_number + 1] = masked_value | (source_layers_cache[byte_number + 1] & (inverse_mask)); + cache[byte_number + 1] = masked_value | (cache[byte_number + 1] & (inverse_mask)); masked_value >>= 8; inverse_mask >>= 8; - source_layers_cache[byte_number] = masked_value | (source_layers_cache[byte_number] & (inverse_mask)); + cache[byte_number] = masked_value | (cache[byte_number] & (inverse_mask)); } } uint8_t read_source_layers_cache(keymatrix_t key) { - const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); + const uint8_t num_cols = keyboard_get_num_cols(key.matrix); + const uint8_t num_rows = keyboard_get_num_rows(key.matrix); + const uint16_t num_cache_bytes = get_source_layers_cache_size(num_cols, num_rows); + uint8_t* cache = get_source_layers_cache(key); + const uint16_t key_number = key.pos.col + (key.pos.row * num_cols); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; - if (byte_number >= sizeof(source_layers_cache)) { + if (byte_number >= num_cache_bytes) { return 0; } const uint8_t bit_position = bit_number % 8; @@ -276,17 +297,21 @@ uint8_t read_source_layers_cache(keymatrix_t key) if (shift > 8 ) { // We need to read only one byte shift -= 8; - return (source_layers_cache[byte_number] >> shift) & layer_cache_mask; + return (cache[byte_number] >> shift) & layer_cache_mask; } else { - if (byte_number + 1 >= sizeof(source_layers_cache)) { + if (byte_number + 1 >= num_cache_bytes) { return 0; } // Otherwise read two bytes // This could potentially be done with a single read, but then we have to assume the endian - uint16_t value = source_layers_cache[byte_number] << 8 | source_layers_cache[byte_number + 1]; + uint16_t value = cache[byte_number] << 8 | cache[byte_number + 1]; return (value >> shift) & layer_cache_mask; } } + +uint8_t get_source_layers_cache_size(uint8_t num_cols, uint8_t num_rows) { + return (num_rows * num_cols * MAX_LAYER_BITS + 7) / 8; +} #endif /** \brief Store or get action (FIXME: Needs better summary) diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h index 8f47fb0c96..c64d0df9df 100644 --- a/tmk_core/common/action_layer.h +++ b/tmk_core/common/action_layer.h @@ -93,6 +93,8 @@ uint32_t layer_state_set_kb(uint32_t state); #define MAX_LAYER_BITS 5 void update_source_layers_cache(keymatrix_t key, uint8_t layer); uint8_t read_source_layers_cache(keymatrix_t key); + +uint8_t get_source_layers_cache_size(uint8_t num_cols, uint8_t num_rows); #endif action_t store_or_get_action(bool pressed, keymatrix_t key); diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index c19661147b..36f7f76705 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -145,6 +145,82 @@ bool is_keyboard_master(void) { return true; } +__attribute__((weak)) +uint8_t multimatrix_get_num_matrices(void) { + return 0; +} + +__attribute__((weak)) +uint8_t multimatrix_get_num_cols(uint8_t matrix) { + return 0; +} + +__attribute__((weak)) +uint8_t multimatrix_get_num_rows(uint8_t matrix) { + return 0; +} + +__attribute__((weak)) +uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) { + return 0; +} + +__attribute__((weak)) +uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) { + return 0; +} + +__attribute__((weak)) +void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { +} + +static uint8_t get_num_matrices(void) { + return 1 + multimatrix_get_num_matrices(); +} + +uint8_t keyboard_get_num_cols(uint8_t matrix) { + if (matrix == 0) { + return MATRIX_COLS; + } else { + return multimatrix_get_num_cols(matrix - 1); + } +} + +uint8_t keyboard_get_num_rows(uint8_t matrix) { + if (matrix == 0) { + return MATRIX_ROWS; + } else { + return multimatrix_get_num_rows(matrix - 1); + } +} + +static uint32_t get_row(uint8_t matrix, uint8_t row) { + if (matrix == 0) { + return matrix_get_row(row); + } else { + return multimatrix_get_row(matrix - 1, row); + } +} + +static matrix_row_t matrix_prev[MATRIX_ROWS]; + +static uint32_t get_row_cache(uint8_t matrix, uint8_t row) { + if (matrix == 0) { + return matrix_prev[row]; + } else { + return multimatrix_get_row_cache(matrix - 1, row); + } +} + +static void set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { + if (matrix == 0) { + matrix_prev[row] = value; + } else { + return multimatrix_set_row_cache(matrix - 1, row, value); + } +} + + /** \brief keyboard_init * * FIXME: needs doc @@ -203,54 +279,57 @@ void keyboard_init(void) { */ void keyboard_task(void) { - static matrix_row_t matrix_prev[MATRIX_ROWS]; -#ifdef MATRIX_HAS_GHOST - // static matrix_row_t matrix_ghost[MATRIX_ROWS]; -#endif static uint8_t led_status = 0; - matrix_row_t matrix_row = 0; - matrix_row_t matrix_change = 0; + uint32_t matrix_row = 0; + uint32_t matrix_change = 0; #ifdef QMK_KEYS_PER_SCAN uint8_t keys_processed = 0; #endif matrix_scan(); if (is_keyboard_master()) { - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row = matrix_get_row(r); - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { + for (uint8_t m = 0; m < get_num_matrices(); m++) { + uint8_t num_cols = keyboard_get_num_cols(m); + uint8_t num_rows = keyboard_get_num_rows(m); + for (uint8_t r = 0; r < num_rows; r++) { + matrix_row = get_row(m, r); + uint32_t row_cache = get_row_cache(m, r); + matrix_change = matrix_row ^ row_cache; + if (matrix_change) { #ifdef MATRIX_HAS_GHOST - if (has_ghost_in_row(r, matrix_row)) { - /* Keep track of whether ghosted status has changed for - * debugging. But don't update matrix_prev until un-ghosted, or - * the last key would be lost. - */ - //if (debug_matrix && matrix_ghost[r] != matrix_row) { - // matrix_print(); - //} + //NOTE: The we support ghosting only for the main matrix, since it's only useful for old keyboards without diodes + if (has_ghost_in_row(r, matrix_row)) { + /* Keep track of whether ghosted status has changed for + * debugging. But don't update matrix_prev until un-ghosted, or + * the last key would be lost. + */ + //if (debug_matrix && matrix_ghost[r] != matrix_row) { + // matrix_print(); + //} + //matrix_ghost[r] = matrix_row; + continue; + } //matrix_ghost[r] = matrix_row; - continue; - } - //matrix_ghost[r] = matrix_row; #endif - if (debug_matrix) matrix_print(); - for (uint8_t c = 0; c < MATRIX_COLS; c++) { - if (matrix_change & ((matrix_row_t)1<= QMK_KEYS_PER_SCAN) + // only jump out if we have processed "enough" keys. + if (++keys_processed >= QMK_KEYS_PER_SCAN) #endif - // process a key per task call - goto MATRIX_LOOP_END; + // process a key per task call + goto MATRIX_LOOP_END; + } } } } diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index 08f9979817..f3bbb1739d 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -72,6 +72,9 @@ void keyboard_task(void); /* it runs when host LED status is updated */ void keyboard_set_leds(uint8_t leds); +uint8_t keyboard_get_num_cols(uint8_t matrix); +uint8_t keyboard_get_num_rows(uint8_t matrix); + #ifdef __cplusplus } #endif From 9ddb678fd0af3276755a62e871a99263eb9d87ba Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 21:05:15 +0300 Subject: [PATCH 5/7] Document some functions --- tmk_core/common/action_layer.c | 5 +++ tmk_core/common/keyboard.c | 58 +++++++++++++++++++++++++++++++--- tmk_core/common/keyboard.h | 2 ++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index f01a3d99d8..7c7cec7071 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -222,6 +222,11 @@ void layer_debug(void) #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; +/** \brief Get the pointer to the source layer cache for a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) { return 0; diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 36f7f76705..076f11686c 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -145,39 +145,79 @@ bool is_keyboard_master(void) { return true; } +/** \brief Get the number of currently connected matrices + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: It should return the number of additional matrices, the master is always implied. + */ __attribute__((weak)) uint8_t multimatrix_get_num_matrices(void) { return 0; } +/** \brief Get the number of columns of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint8_t multimatrix_get_num_cols(uint8_t matrix) { return 0; } +/** \brief Get the number of rows of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint8_t multimatrix_get_num_rows(uint8_t matrix) { return 0; } +/** \brief Get the row status of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) { return 0; } +/** \brief Get the row cache of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) { return 0; } +/** \brief Set the row cache of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { } -static uint8_t get_num_matrices(void) { +/** \brief Get the number of currently connected matrices + * + * For normal keyboards this usually returns 1, but for multi-matrix keyboards this will + * return the total number of connected keyboards/modules including the master + */ +uint8_t keyboard_get_num_matrices(void) { return 1 + multimatrix_get_num_matrices(); } +/** \brief Get the number of columns of a connected matrix + * + * Specify the matrix index to query connected multi-matrix keyboards/modules + * 0 is always the master + */ uint8_t keyboard_get_num_cols(uint8_t matrix) { if (matrix == 0) { return MATRIX_COLS; @@ -186,6 +226,11 @@ uint8_t keyboard_get_num_cols(uint8_t matrix) { } } +/** \brief Get the number of rows of a connected matrix + * + * Specify the matrix index to query connected multi-matrix keyboards/modules + * 0 is always the master + */ uint8_t keyboard_get_num_rows(uint8_t matrix) { if (matrix == 0) { return MATRIX_ROWS; @@ -194,7 +239,12 @@ uint8_t keyboard_get_num_rows(uint8_t matrix) { } } -static uint32_t get_row(uint8_t matrix, uint8_t row) { +/** \brief Get the row status of a connected matrix + * + * Specify the matrix index to query connected multi-matrix keyboards/modules + * 0 is always the master + */ +uint32_t keyboard_get_row(uint8_t matrix, uint8_t row) { if (matrix == 0) { return matrix_get_row(row); } else { @@ -288,11 +338,11 @@ void keyboard_task(void) matrix_scan(); if (is_keyboard_master()) { - for (uint8_t m = 0; m < get_num_matrices(); m++) { + for (uint8_t m = 0; m < keyboard_get_num_matrices(); m++) { uint8_t num_cols = keyboard_get_num_cols(m); uint8_t num_rows = keyboard_get_num_rows(m); for (uint8_t r = 0; r < num_rows; r++) { - matrix_row = get_row(m, r); + matrix_row = keyboard_get_row(m, r); uint32_t row_cache = get_row_cache(m, r); matrix_change = matrix_row ^ row_cache; if (matrix_change) { diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index f3bbb1739d..6424e2fd2d 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -72,8 +72,10 @@ void keyboard_task(void); /* it runs when host LED status is updated */ void keyboard_set_leds(uint8_t leds); +uint8_t keyboard_get_num_matrices(void); uint8_t keyboard_get_num_cols(uint8_t matrix); uint8_t keyboard_get_num_rows(uint8_t matrix); +uint32_t keyboard_get_row(uint8_t matrix, uint8_t row); #ifdef __cplusplus } From 32028cfc43fd7a26bde5eb507fc2aa330e75a36e Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 22:57:05 +0300 Subject: [PATCH 6/7] Fix SWAP_HANDS for multimatrix --- tmk_core/common/action.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index cfc933fb28..f85a695b85 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -106,13 +106,14 @@ bool swap_held = false; void process_hand_swap(keyevent_t *event) { static swap_state_row_t swap_state[MATRIX_ROWS]; - keypos_t pos = event->key; + // TODO: Properly support multimatrices, currenty this only works for single-matrix keyboards + keypos_t pos = event->key.pos; swap_state_row_t col_bit = (swap_state_row_t)1<pressed ? swap_hands : swap_state[pos.row] & (col_bit); if (do_swap) { - event->key = hand_swap_config[pos.row][pos.col]; + event->key.pos = hand_swap_config[pos.row][pos.col]; swap_state[pos.row] |= col_bit; } else { swap_state[pos.row] &= ~(col_bit); From 19e0bc852f1b42d0a97b916d2c703d54a570090b Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 22:59:23 +0300 Subject: [PATCH 7/7] Fix rgb matrix compilation --- quantum/rgb_matrix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index d29a65b907..f72acca670 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -119,7 +119,8 @@ void rgb_matrix_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) { bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) { if ( record->event.pressed ) { uint8_t led[8], led_count; - map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count); + // TODO: Support multi-matrix keyboards + map_row_column_to_led(record->event.key.pos.row, record->event.key.pos.col, led, &led_count); if (led_count > 0) { for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { g_last_led_hit[i - 1] = g_last_led_hit[i - 2];