diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega2560.c b/firmware/asdf/src/Arch/asdf_arch_atmega2560.c index 86b0d5b..7da5014 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega2560.c +++ b/firmware/asdf/src/Arch/asdf_arch_atmega2560.c @@ -41,7 +41,6 @@ #include #include "asdf_config.h" -#include "asdf_keymap_defs.h" // Tick is true every 1 ms. static volatile uint8_t tick = 0; diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega328p.c b/firmware/asdf/src/Arch/asdf_arch_atmega328p.c index 364aaf2..a2f2557 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega328p.c +++ b/firmware/asdf/src/Arch/asdf_arch_atmega328p.c @@ -40,7 +40,6 @@ #include #include #include "asdf_config.h" -#include "asdf_keymap_defs.h" static volatile uint8_t tick = 0; diff --git a/firmware/asdf/src/Arch/asdf_arch_test.c b/firmware/asdf/src/Arch/asdf_arch_test.c index 42e547d..9681889 100644 --- a/firmware/asdf/src/Arch/asdf_arch_test.c +++ b/firmware/asdf/src/Arch/asdf_arch_test.c @@ -35,7 +35,6 @@ #include #include -#include "asdf_keymap_defs.h" #include "asdf_config.h" #include "asdf_physical.h" #include "asdf_virtual.h" diff --git a/firmware/asdf/src/Arch/asdf_arch_test.h b/firmware/asdf/src/Arch/asdf_arch_test.h index 2408920..ae23f13 100644 --- a/firmware/asdf/src/Arch/asdf_arch_test.h +++ b/firmware/asdf/src/Arch/asdf_arch_test.h @@ -28,7 +28,6 @@ #include #include "asdf.h" -#include "asdf_keymap_defs.h" #include "asdf_config.h" #include "asdf_physical.h" #include "asdf_virtual.h" diff --git a/firmware/asdf/src/asdf.c b/firmware/asdf/src/asdf.c index 248efcd..6238b6d 100644 --- a/firmware/asdf/src/asdf.c +++ b/firmware/asdf/src/asdf.c @@ -36,7 +36,6 @@ #include "asdf_physical.h" #include "asdf_virtual.h" #include "asdf_keymaps.h" -#include "asdf_keymap_defs.h" #include "asdf_repeat.h" #include "asdf_modifiers.h" #include "asdf_buffer.h" diff --git a/firmware/asdf/src/asdf.h b/firmware/asdf/src/asdf.h index a5413e6..fdbb145 100644 --- a/firmware/asdf/src/asdf.h +++ b/firmware/asdf/src/asdf.h @@ -24,6 +24,8 @@ #if !defined(ASDF_H) #define ASDF_H +#include + // Define the code at which keyboard actions begin. Codes below this value are // values to be transmitted to the host machine. Codes above this value are // actions to be performed. diff --git a/firmware/asdf/src/asdf_config.h b/firmware/asdf/src/asdf_config.h index aeaf501..7e3b613 100644 --- a/firmware/asdf/src/asdf_config.h +++ b/firmware/asdf/src/asdf_config.h @@ -47,6 +47,18 @@ #define ASDF_DEFAULT_SCREEN_CLEAR_POLARITY ASDF_POSITIVE_POLARITY +// Data structure sizes: + +// Size of keymap initializer sequence. These sequences are defined in the +// keymap modules. This should be large enough to accommodate the largest +// initializer sequence among the included keymaps +#define ASDF_KEYMAP_INITIALIZER_LENGTH 6 + +// Size of keymap hook function initializer list. These lists are defined in the +// keymap modules. This should be large enough to accommodate the largest list +// among the included keymaps +#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH 2 + // size of the keycode output buffer. #define ASDF_KEYCODE_BUFFER_SIZE 16 diff --git a/firmware/asdf/src/asdf_hook.c b/firmware/asdf/src/asdf_hook.c index e323ec2..bf13d1a 100644 --- a/firmware/asdf/src/asdf_hook.c +++ b/firmware/asdf/src/asdf_hook.c @@ -33,7 +33,6 @@ #include #include "asdf_arch.h" #include "asdf_hook.h" -#include "asdf_keymap_defs.h" // hooks_table[] contains all the function hooks. The entry for each ID contains diff --git a/firmware/asdf/src/asdf_keymaps.c b/firmware/asdf/src/asdf_keymaps.c index f72820f..f726207 100644 --- a/firmware/asdf/src/asdf_keymaps.c +++ b/firmware/asdf/src/asdf_keymaps.c @@ -21,55 +21,167 @@ // this program. If not, see . #include +#include #include "asdf.h" #include "asdf_arch.h" #include "asdf_physical.h" #include "asdf_virtual.h" #include "asdf_hook.h" -#include "asdf_repeat.h" #include "asdf_keymaps.h" -#include "asdf_keymap_defs.h" - -// ASDF_KEYMAP_DECLARATIONS is defined in asdf_keymap_defs.h, aggregated from -// all the included keymap definition files. -// -// This is a terrible practice, but defining the declarations as a macro permits -// the keymap definitions to be incorporated in a fairly modular fashion, using -// the limited capabilities of the C preprocessor. One alternative is to use a -// program (in C or at the expense of additional build dependencies, in python -// or bash) to generate the keymap definitions and declarations from a -// definition file. But then the keymap declarations would not be private. -// constexpr in C++ may be an alternative option as well. -ASDF_KEYMAP_DECLARATIONS; +#include "asdf_modifiers.h" // The keymap arrays organized as follows: // * Each keymap matrix is a NUM_ROWS x NUM_COLS mapping of key to code for a given modifier. // * Each keymap contains a set of keymap matrices, one for each unique // combination of modifier keys. // * All the keymaps (NUM_KEYMAPS) are gathered in the keymap_matrixp[] array. -static keycode_matrix_t const *keymap_matrix[ASDF_NUM_KEYMAPS][ASDF_MOD_NUM_MODIFIERS] = - ASDF_KEYMAP_DEFS; - +static asdf_keycode_matrix_t *keymap_matrix[ASDF_NUM_KEYMAPS][ASDF_MOD_NUM_MODIFIERS] = {}; // Each keymap (representing a keyboard configuration) has an associated set of // virtual device initializers that set up the I/O and LED lines for the // keyboard, unique to each keymap. This builds the virtual device initializer // array from the initializer definitions in the keymap definition files. -static const asdf_virtual_initializer_t keymap_initializer_list[ASDF_NUM_KEYMAPS] - [ASDF_KEYMAP_INITIALIZER_LENGTH] = - ASDF_KEYMAP_INITIALIZERS; +static asdf_virtual_initializer_t + keymap_initializer_list[ASDF_NUM_KEYMAPS][ASDF_KEYMAP_INITIALIZER_LENGTH] = {}; // Each keymap (representing a keyboard configuration) has an associated set of // function hooks unique to the keyboard defined by the map. This builds the // function hook initializer array from the definitions in the keymap definition // files. -static const asdf_hook_initializer_t - keymap_hook_initializer_list[ASDF_NUM_KEYMAPS][ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH] = - ASDF_KEYMAP_HOOK_INITIALIZERS; +static asdf_hook_initializer_t + keymap_hook_initializer_list[ASDF_NUM_KEYMAPS][ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH] = {}; // Index of the currently active keymap, initialized to zero in the init // routine. -static uint8_t keymap_index; +static uint8_t current_keymap_index = 0; + +// index of the current virtual device initializer entry while building virtual +// device initializer struct. +static uint8_t vdev_index = 0; + +// index of the current hook entry while building hook initializer table. +static uint8_t hook_index = 0; + +// PROCEDURE: asdf_keymaps_add_keymap +// INPUTS: (asdf_keycode_matrix_t *) matrix - keycode matrix to add in to map +// (uint8_t) keymap_modifier - the modifier value for the keycode matrix +// +// OUTPUTS: none +// +// DESCRIPTION: Called by keymap building modules. This routine is responsible +// for building the keymap matrix for all the supported keymaps, assigning +// keymaps for each modifier code in all the keymaps. + +// The routine takes a pointer to a keycode matrix that maps each key in the +// physical keyboard matrix to a code. A modifier code parameter indicates which +// modifier combination activates the provided matrix. +// +// SIDE EFFECTS: +// +// NOTES: If the keymap modifier index is not a valid keymap index then no +// action is performed. +// +// SCOPE: public +// +// COMPLEXITY: 1 +void asdf_keymaps_add_map(asdf_keycode_matrix_t *matrix, uint8_t modifier_index) +{ + if (modifier_index < ASDF_MOD_NUM_MODIFIERS && current_keymap_index < ASDF_NUM_KEYMAPS) { + keymap_matrix[current_keymap_index][modifier_index] = matrix; + } +} + + +// PROCEDURE: asdf_keymaps_next(); +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Called by keymap building modules to conclude a keymap. This is +// done after all modifier maps, hooks, and virtual devices have been defined. +// +// SIDE EFFECTS: 1) Causes asdf_keymaps_add_keymap() to increment the keymap index +// 2) Resets the virtual device table index for the next keymap +// 3) Resets the hook table index for the next keymap +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_keymaps_start_new(uint8_t new_keymap_index) +{ + current_keymap_index = new_keymap_index; + asdf_keymap_add_virtual_device(V_NULL, PHYSICAL_NO_OUT, V_NOFUNC, 0); + asdf_keymap_add_hook(ASDF_HOOK_NULL, NULL); +} + + +// PROCEDURE: asdf_keymap_add_virtual_device +// INPUTS: (asdf_virtual_dev_t) virtual_dev: The virtual device being assigned +// (asdf_physical_dev_t) physical_dev: The physical device attached to the virtual device +// (asdf_virtual_function_t) function: the function associated with the virtual device +// (uint8_t) initial_value: The initial state of the virtual device +// +// OUTPUTS: none +// +// DESCRIPTION: Builds the virtual device initializer structure. Uses the +// arguments to build an entry in the virtual device initializer structure for +// the current keymap. +// +// SIDE EFFECTS: See above. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_keymap_add_virtual_device(asdf_virtual_dev_t virtual_dev, + asdf_physical_dev_t physical_dev, + asdf_virtual_function_t function, uint8_t initial_value) +{ + static uint8_t vdev_index = 0; + + if (V_NULL == virtual_dev) { + vdev_index = 0; + } + else if (current_keymap_index < ASDF_NUM_KEYMAPS && vdev_index < ASDF_VIRTUAL_NUM_RESOURCES) { + keymap_initializer_list[current_keymap_index][vdev_index++].virtual_device = virtual_dev; + keymap_initializer_list[current_keymap_index][vdev_index++].physical_device = physical_dev; + keymap_initializer_list[current_keymap_index][vdev_index++].function = function; + keymap_initializer_list[current_keymap_index][vdev_index++].initial_value = initial_value; + } +} + +// PROCEDURE: asdf_keymap_add_hook +// INPUTS: (asdf_hook_id_t) hook_id: type ID for the provided hook function +// (asdf_hook_function_t) function: the function associated with the hook. +// +// OUTPUTS: none +// +// DESCRIPTION: Builds the hook initializer table for the current keymap +// +// SIDE EFFECTS: See above. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_keymap_add_hook(asdf_hook_id_t hook_id, asdf_hook_function_t function) +{ + static uint8_t hook_entry_index = 0; + + if (ASDF_HOOK_NULL == hook_id) { + hook_entry_index = 0; + } + else if (current_keymap_index < ASDF_NUM_KEYMAPS && hook_index < ASDF_NUM_HOOKS) { + keymap_hook_initializer_list[current_keymap_index][hook_entry_index].hook_id = hook_id; + keymap_hook_initializer_list[current_keymap_index][hook_entry_index].hook_func = function; + } +} // PROCEDURE: asdf_keymaps_select_keymap @@ -78,21 +190,17 @@ static uint8_t keymap_index; // // DESCRIPTION: accepts a index value. If the requested keymap index is valid, // then: -// 1) assign the value to the global (to the module) keymap_index variable +// 1) assign the value to the global (to the module) current_keymap_index variable // 2) execute the architecture-dependent init routine, to undo any settings // from the previous keymap // 3) initialize the virtual outputs for the selected keymap. // 4) initialize the modifier key states. // // SIDE EFFECTS: -// - May change the module-global keymap_index variable. +// - May change the module-global current_keymap_index variable. // - Architecture is initialized to default configuration. // -// NOTES: 1) If the requested index is not valid, then no action is performed. -// -// 2) Hooks are initialized after repeat apparratus and modifiers states -// are initialized, so that hooks can be used to modify default modifier -// states for a map. +// NOTES: If the requested index is not valid, then no action is performed. // // SCOPE: public // @@ -101,17 +209,11 @@ static uint8_t keymap_index; void asdf_keymaps_select_keymap(uint8_t index) { if (index < ASDF_NUM_KEYMAPS) { - keymap_index = index; - + current_keymap_index = index; asdf_arch_init(); - - asdf_virtual_init((asdf_virtual_initializer_t *const) keymap_initializer_list[keymap_index]); - + asdf_virtual_init((asdf_virtual_initializer_t *const) keymap_initializer_list[current_keymap_index]); asdf_modifiers_init(); - - asdf_repeat_init(); - - asdf_hook_init((asdf_hook_initializer_t *const) keymap_hook_initializer_list[keymap_index]); + asdf_hook_init((asdf_hook_initializer_t *const) keymap_hook_initializer_list[current_keymap_index]); } } @@ -155,7 +257,7 @@ void asdf_keymaps_init(void) // void asdf_keymaps_map_select_0_clear(void) { - asdf_keymaps_select_keymap(keymap_index & (~ASDF_KEYMAP_BIT_0)); + asdf_keymaps_select_keymap(current_keymap_index & (~ASDF_KEYMAP_BIT_0)); } // PROCEDURE: asdf_keymaps_map_select_0_set @@ -175,7 +277,7 @@ void asdf_keymaps_map_select_0_clear(void) // void asdf_keymaps_map_select_0_set(void) { - asdf_keymaps_select_keymap(keymap_index | ASDF_KEYMAP_BIT_0); + asdf_keymaps_select_keymap(current_keymap_index | ASDF_KEYMAP_BIT_0); } // PROCEDURE: asdf_keymaps_map_select_1_clear @@ -195,7 +297,7 @@ void asdf_keymaps_map_select_0_set(void) // void asdf_keymaps_map_select_1_clear(void) { - asdf_keymaps_select_keymap(keymap_index & (~ASDF_KEYMAP_BIT_1)); + asdf_keymaps_select_keymap(current_keymap_index & (~ASDF_KEYMAP_BIT_1)); } // PROCEDURE: asdf_keymaps_map_select_1_set @@ -215,7 +317,7 @@ void asdf_keymaps_map_select_1_clear(void) // void asdf_keymaps_map_select_1_set(void) { - asdf_keymaps_select_keymap(keymap_index | ASDF_KEYMAP_BIT_1); + asdf_keymaps_select_keymap(current_keymap_index | ASDF_KEYMAP_BIT_1); } // PROCEDURE: asdf_keymaps_map_select_2_clear @@ -235,7 +337,7 @@ void asdf_keymaps_map_select_1_set(void) // void asdf_keymaps_map_select_2_clear(void) { - asdf_keymaps_select_keymap(keymap_index & (~ASDF_KEYMAP_BIT_2)); + asdf_keymaps_select_keymap(current_keymap_index & (~ASDF_KEYMAP_BIT_2)); } // PROCEDURE: asdf_keymaps_map_select_2_set @@ -255,7 +357,7 @@ void asdf_keymaps_map_select_2_clear(void) // void asdf_keymaps_map_select_2_set(void) { - asdf_keymaps_select_keymap(keymap_index | ASDF_KEYMAP_BIT_2); + asdf_keymaps_select_keymap(current_keymap_index | ASDF_KEYMAP_BIT_2); } // PROCEDURE: asdf_keymaps_map_select_3_clear @@ -275,7 +377,7 @@ void asdf_keymaps_map_select_2_set(void) // void asdf_keymaps_map_select_3_clear(void) { - asdf_keymaps_select_keymap(keymap_index & (~ASDF_KEYMAP_BIT_3)); + asdf_keymaps_select_keymap(current_keymap_index & (~ASDF_KEYMAP_BIT_3)); } // PROCEDURE: asdf_keymaps_map_select_3_set @@ -295,7 +397,7 @@ void asdf_keymaps_map_select_3_clear(void) // void asdf_keymaps_map_select_3_set(void) { - asdf_keymaps_select_keymap(keymap_index | ASDF_KEYMAP_BIT_3); + asdf_keymaps_select_keymap(current_keymap_index | ASDF_KEYMAP_BIT_3); } // PROCEDURE: asdf_keymaps_get_code @@ -318,7 +420,7 @@ void asdf_keymaps_map_select_3_set(void) asdf_keycode_t asdf_keymaps_get_code(const uint8_t row, const uint8_t col, const uint8_t modifier_index) { - const keycode_matrix_t *matrix = keymap_matrix[keymap_index][modifier_index]; + asdf_keycode_matrix_t *matrix = keymap_matrix[current_keymap_index][modifier_index]; return FLASH_READ_MATRIX_ELEMENT(*matrix, row, col); } diff --git a/firmware/asdf/src/asdf_keymaps.h b/firmware/asdf/src/asdf_keymaps.h index 0672646..a03aa0e 100644 --- a/firmware/asdf/src/asdf_keymaps.h +++ b/firmware/asdf/src/asdf_keymaps.h @@ -27,6 +27,14 @@ #if !defined(ASDF_KEYMAPS_H) #define ASDF_KEYMAPS_H +#include "asdf.h" +#include "asdf_hook.h" +#include "asdf_virtual.h" +#include "asdf_physical.h" + +#define ASDF_NUM_KEYMAPS 6 +#define ASDF_NUM_ROWS 13 +#define ASDF_NUM_COLS 8 // Define the bit position of each keymap DIP switch. The DIP switch values at // each bit position can be used to select the current keymap. This requires the @@ -37,6 +45,11 @@ #define ASDF_KEYMAP_BIT_2 4 #define ASDF_KEYMAP_BIT_3 8 + +// define the keycode matrices to be used by the keymaps. Each matrix is a +// mapping of row,column to keycode. +typedef asdf_keycode_t asdf_keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; + // PROCEDURE: asdf_keymaps_select_keymap // INPUTS: (uint8_t) index - index of the keymap number to select // OUTPUTS: none @@ -109,7 +122,28 @@ void asdf_keymaps_map_select_3_set(void); // index, to avoid hard-coding constant index values. void asdf_keymaps_init(void); -// PROCEDURE: asdf_keymaps_get_`code +// PROCEDURE: asdf_keymap_add_virtual_device +// INPUTS: (asdf_virtual_dev_t) virtual_dev: The virtual device being assigned +// (asdf_physical_dev_t) physical_dev: The physical device attached to the virtual device +// (asdf_virtual_function_t) function: the function associated with the virtual device +// (uint8_t) initial_value: The initial state of the virtual device +// OUTPUTS: none +// DESCRIPTION: Builds the virtual device initializer structure. Uses the +// arguments to build an entry in the virtual device initializer structure for +// the current keymap. +void asdf_keymap_add_virtual_device(asdf_virtual_dev_t virtual_dev, + asdf_physical_dev_t physical_dev, + asdf_virtual_function_t function, uint8_t initial_value); + +// PROCEDURE: asdf_keymap_add_hook +// INPUTS: (asdf_hook_id_t) hook_id: type ID for the provided hook function +// (asdf_hook_function_t) function: the function associated with the hook. +// OUTPUTS: none +// DESCRIPTION: Builds the hook initializer table for the current keymap +void asdf_keymap_add_hook(asdf_hook_id_t hook_id, asdf_hook_function_t function); + + +// PROCEDURE: asdf_keymaps_get_code // INPUTS: row, col: row and column of key that has been pressed // modifiers_index: index into the keymap array, based on modifier state // OUTPUTS: returns a key code. diff --git a/firmware/asdf/src/asdf_physical.c b/firmware/asdf/src/asdf_physical.c index 536e8f2..ab1c9e3 100644 --- a/firmware/asdf/src/asdf_physical.c +++ b/firmware/asdf/src/asdf_physical.c @@ -26,7 +26,6 @@ #include #include "asdf_physical.h" -#include "asdf_keymap_defs.h" #include "asdf_config.h" #include "asdf_arch.h" diff --git a/firmware/asdf/src/asdf_physical.h b/firmware/asdf/src/asdf_physical.h index 1f6452f..3dbfb21 100644 --- a/firmware/asdf/src/asdf_physical.h +++ b/firmware/asdf/src/asdf_physical.h @@ -25,6 +25,7 @@ #if !defined(ASDF_PHYSICAL_H) #define ASDF_PHYSICAL_H +#include // The asdf_virtual_real_dev_t enumerates real outputs that can be assigned to // virtual outputs via the asdf_virtual_assign() function. The name is a bit diff --git a/firmware/asdf/src/asdf_virtual.c b/firmware/asdf/src/asdf_virtual.c index 2a1b50b..e25360f 100644 --- a/firmware/asdf/src/asdf_virtual.c +++ b/firmware/asdf/src/asdf_virtual.c @@ -30,7 +30,6 @@ #include #include "asdf_physical.h" #include "asdf_virtual.h" -#include "asdf_keymap_defs.h" #include "asdf_config.h" #include "asdf_arch.h" diff --git a/firmware/asdf/src/asdf_virtual.h b/firmware/asdf/src/asdf_virtual.h index bdc8b7a..cfc9722 100644 --- a/firmware/asdf/src/asdf_virtual.h +++ b/firmware/asdf/src/asdf_virtual.h @@ -25,6 +25,8 @@ #if !defined(ASDF_VIRTUAL_H) #define ASDF_VIRTUAL_H +#include "asdf_physical.h" + // These are "virtual" output identifiers that can be mapped to the real outputs using // keymap initializer commands. typedef enum { diff --git a/firmware/asdf/test/asdf_all_keymap_defs_test.h b/firmware/asdf/test/asdf_all_keymap_defs_test.h new file mode 100644 index 0000000..1ee4747 --- /dev/null +++ b/firmware/asdf/test/asdf_all_keymap_defs_test.h @@ -0,0 +1,68 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// asdf_keymap_defs.h +// +// gathers up all the keymap definitions to be included in the firmware. +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +// While there is nothing preventing a standard keyboard from having both a +// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For +// testing, both must be present to test their functionality. + +#if !defined(ASDF_KEYMAP_DEFS_H) +#define ASDF_KEYMAP_DEFS_H + +#include "asdf.h" +#include "test_asdf_lib.h" +#include "asdf_ascii.h" +#include "asdf_modifiers.h" +#include "Keymaps/asdf_keymap_defs_test.h" +#include "Keymaps/asdf_keymap_defs_test2.h" + + +#define ASDF_TEST_BASE 0 +#define ASDF_TEST2_BASE (ASDF_TEST_BASE + ASDF_TEST_KEYMAPS_COUNT) + +#define ASDF_NUM_KEYMAPS (ASDF_TEST_BASE + ASDF_TEST_KEYMAPS_COUNT + ASDF_TEST2_KEYMAPS_COUNT) + +#define ASDF_KEYMAP_DEFS \ + { \ + ASDF_TEST_KEYMAPS, ASDF_TEST2_KEYMAPS \ + } + +#define ASDF_KEYMAP_DECLARATIONS ASDF_TEST_DECLARATIONS ASDF_TEST2_DECLARATIONS + +#define ASDF_KEYMAP_INITIALIZERS \ + { \ + ASDF_TEST_KEYMAP_INITIALIZER, ASDF_TEST2_KEYMAP_INITIALIZER \ + } + +#define ASDF_KEYMAP_HOOK_INITIALIZERS \ + { \ + ASDF_TEST_KEYMAP_HOOK_INITIALIZER, ASDF_TEST2_KEYMAP_HOOK_INITIALIZER \ + } + +typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; + + +#endif /* !defined (ASDF_KEYMAP_DEFS_H) */ + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/test/asdf_keymap_defs_test.h b/firmware/asdf/test/asdf_keymap_defs_test.h new file mode 100644 index 0000000..35598dd --- /dev/null +++ b/firmware/asdf/test/asdf_keymap_defs_test.h @@ -0,0 +1,275 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// asdf_keymaps.h +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +// While there is nothing preventing a standard keyboard from having both a +// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For +// testing, both must be present to test their functionality. + +#if !defined(ASDF_KEYMAP_DEFS_TEST_H) +#define ASDF_KEYMAP_DEFS_TEST_H + +#define ASDF_TEST_NUM_ROWS 9 +#define ASDF_TEST_NUM_COLS 8 + +// The first value in each row serves two purposes: +// +// 1) Indicate a valid row of codes if the value is nonzero. +// 2) Indicate the physical row number corresponding to the keymap row. +// +// Multiple keymaps may be combined, some of which use more rows than other +// keymaps. The keymap with the most rows determines how many rows are allocated +// for each keymap. Since each keymap only initializes the rows it uses, then +// the shorter keymaps may have multiple uninitialized rows that should not be +// scanned. The C99 standard guarantees that all elements no explicitly +// initialized shall be initialized to 0 (C99 Standard 6.7.8.21). Therefore, +// keymap rows starting with a 0 are not valid and are not scanned. +// +// Some hardware may contain blank physical rows To avoid having unused empty +// rows, the first column of each row indicates the physical row. For example, 8 +// rows of switches (0-7), and a bank of DIP switches on row 15. In this case, +// only 9 rows need be allocated. + + +#define PLAIN_MATRIX_1 RESERVED_1 +#define CAPS_MATRIX_1 RESERVED_2 +#define SHIFT_MATRIX_1 RESERVED_3 +#define CTRL_MATRIX_1 RESERVED_4 + +#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1) +#define ASDF_TEST_MAP_DIP_SWITCHES \ + [ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 } + +#define ASDF_TEST_PLAIN_MAP \ + { \ + { PLAIN_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \ + { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \ + { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'o', \ + 'l', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST_CAPS_MAP \ + { \ + { CAPS_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', \ + 'L', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST_SHIFT_MAP \ + { \ + \ + { SHIFT_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \ + { ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \ + { ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \ + '0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \ + { ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + +#define ASDF_TEST_CTRL_MAP \ + { \ + { CTRL_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \ + { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \ + ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \ + { ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \ + ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \ + { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, \ + ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S }, \ + { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \ + ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, \ + ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \ + { ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \ + ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \ + { ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, \ + ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_2 }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + +#define ASDF_TEST_DECLARATIONS \ + static const FLASH keycode_matrix_t test_PLAIN_matrix = ASDF_TEST_PLAIN_MAP; \ + static const FLASH keycode_matrix_t test_SHIFT_matrix = ASDF_TEST_SHIFT_MAP; \ + static const FLASH keycode_matrix_t test_CAPS_matrix = ASDF_TEST_CAPS_MAP; \ + static const FLASH keycode_matrix_t test_CTRL_matrix = ASDF_TEST_CTRL_MAP; + +#define ASDF_TEST_MAP_DEFS \ + { \ + &test_PLAIN_matrix, &test_SHIFT_matrix, &test_CAPS_matrix, &test_CTRL_matrix \ + } + +#define ASDF_TEST_CAPS_MAP_DEFS \ + { \ + &test_CAPS_matrix, &test_SHIFT_matrix, &test_CAPS_matrix, &test_CTRL_matrix \ + } + +#define ASDF_TEST_KEYMAPS ASDF_TEST_MAP_DEFS, ASDF_TEST_CAPS_MAP_DEFS + +#define ASDF_TEST_KEYMAPS_COUNT 2 +#define ASDF_TEST_PLAIN_MAP_INDEX ASDF_TEST_BASE + 0 +#define ASDF_TEST_CAPS_MAP_INDEX ASDF_TEST_BASE + 1 + +#define SINGLE_TESTS_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX +#define DOUBLE_ASSIGN_TEST_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX + +#define TRIPLE_TESTS_KEYMAP ASDF_TEST_CAPS_MAP_INDEX + +#define ASDF_TEST_KEYMAP_INITIALIZER_LENGTH 5 +#define ASDF_TEST_KEYMAP_INITIALIZER_1 \ + { \ + { \ + /* Single assignment */ \ + .virtual_device = VOUT1, \ + .physical_device = PHYSICAL_OUT1, \ + .function = V_NOFUNC, \ + .initial_value = 0, \ + }, \ + { \ + /* single toggle */ \ + .virtual_device = VOUT2, \ + .physical_device = PHYSICAL_OUT2, \ + .function = V_TOGGLE, \ + .initial_value = 0, \ + }, \ + { \ + /* single pulse */ \ + .virtual_device = VOUT3, \ + .physical_device = PHYSICAL_OUT3, \ + .function = V_PULSE_SHORT, \ + .initial_value = 0, \ + }, \ + { /* first of double assignment attempt */ \ + .virtual_device = VOUT4, \ + .physical_device = PHYSICAL_LED1, \ + .initial_value = 0 \ + }, \ + { /* second of double assignment attempt */ \ + .virtual_device = VOUT5, .physical_device = PHYSICAL_LED1, .initial_value = 1 \ + } \ + } + +#define ASDF_TEST_KEYMAP_INITIALIZER_2 \ + { \ + { \ + /* Triple assignment */ \ + .virtual_device = VOUT1, \ + .physical_device = PHYSICAL_OUT1, \ + .function = V_TOGGLE, \ + .initial_value = 0, \ + }, \ + { \ + .virtual_device = VOUT1, \ + .physical_device = PHYSICAL_OUT2, \ + .function = V_TOGGLE, \ + .initial_value = 1, \ + }, \ + { \ + .virtual_device = VOUT1, .physical_device = PHYSICAL_OUT3, .function = V_TOGGLE, \ + .initial_value = 0, \ + } \ + } + +#define ASDF_TEST_KEYMAP_INITIALIZER ASDF_TEST_KEYMAP_INITIALIZER_1, ASDF_TEST_KEYMAP_INITIALIZER_2 + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_LENGTH 2 + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_1 \ + { \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_1, \ + }, \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_2, \ + }, \ + } + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_2 \ + { \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_3, \ + }, \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_4, \ + }, \ + } + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER \ + ASDF_TEST_KEYMAP_HOOK_INITIALIZER_1, ASDF_TEST_KEYMAP_HOOK_INITIALIZER_2 + + +// The following preprocessor "code" permits various keymaps to be created and +// included without generating a lot of complicating code dependencies. The use +// of macros in this way is a bit ugly, I realize, and stretches the intention +// of the C preprocessor. The C preprocessor is used to store a bit of state to +// keep track of the number and ordering of the keymaps as they are added, and +// to keep track of the array sizes to be allocated at compile time. + + +#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_TEST_NUM_ROWS) +#undef ASDF_NUM_ROWS +#define ASDF_NUM_ROWS ASDF_TEST_NUM_ROWS +#endif + +#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_TEST_NUM_COLS) +#undef ASDF_NUM_COLS +#define ASDF_NUM_COLS ASDF_TEST_NUM_COLS +#endif + +#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \ + || (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST_KEYMAP_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_INITIALIZER_LENGTH +#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST_KEYMAP_INITIALIZER_LENGTH +#endif + +#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) \ + || (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH +#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_LENGTH +#endif + +#endif /* !defined (ASDF_KEYMAP_DEFS_TEST_H) */ + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/test/asdf_keymap_defs_test2.h b/firmware/asdf/test/asdf_keymap_defs_test2.h new file mode 100644 index 0000000..a26512d --- /dev/null +++ b/firmware/asdf/test/asdf_keymap_defs_test2.h @@ -0,0 +1,239 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// asdf_keymaps.h +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +// While there is nothing preventing a standard keyboard from having both a +// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For +// testing, both must be present to test their functionality. + +#if !defined(ASDF_KEYMAP_DEFS_TEST2_H) +#define ASDF_KEYMAP_DEFS_TEST2_H + +#define ASDF_TEST2_NUM_ROWS 16 +#define ASDF_TEST2_NUM_COLS 8 + +// The first value in each row serves two purposes: +// +// 1) Indicate a valid row of codes if the value is nonzero. +// 2) Indicate the physical row number corresponding to the keymap row. +// +// Multiple keymaps may be combined, some of which use more rows than other +// keymaps. The keymap with the most rows determines how many rows are allocated +// for each keymap. Since each keymap only initializes the rows it uses, then +// the shorter keymaps may have multiple uninitialized rows that should not be +// scanned. The C99 standard guarantees that all elements no explicitly +// initialized shall be initialized to 0 (C99 Standard 6.7.8.21). Therefore, +// keymap rows starting with a 0 are not valid and are not scanned. +// +// Some hardware may contain blank physical rows To avoid having unused empty +// rows, the first column of each row indicates the physical row. For example, 8 +// rows of switches (0-7), and a bank of DIP switches on row 15. In this case, +// only 9 rows need be allocated. + + +#define PLAIN_MATRIX_2 RESERVED_5 +#define CAPS_MATRIX_2 RESERVED_6 +#define SHIFT_MATRIX_2 RESERVED_7 +#define CTRL_MATRIX_2 RESERVED_8 + +#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1) + +#define ASDF_TEST_MAP_DIP_SWITCHES \ + [ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 } + +#define ASDF_TEST2_PLAIN_MAP \ + { \ + { PLAIN_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \ + { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \ + { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'o', \ + 'l', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST2_CAPS_MAP \ + { \ + { CAPS_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', \ + 'L', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST2_SHIFT_MAP \ + { \ + \ + { SHIFT_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \ + { ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \ + { ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \ + '0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \ + { ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + +#define ASDF_TEST2_CTRL_MAP \ + { \ + { CTRL_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \ + { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \ + ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \ + { ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \ + ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \ + { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, \ + ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S }, \ + { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \ + ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, \ + ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \ + { ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \ + ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \ + { ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, \ + ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_2 }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + +#define ASDF_TEST2_DECLARATIONS \ + static const FLASH keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; \ + static const FLASH keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; \ + static const FLASH keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; \ + static const FLASH keycode_matrix_t test2_CTRL_matrix = ASDF_TEST2_CTRL_MAP; + +#define ASDF_TEST2_MAP_DEFS \ + { \ + &test2_PLAIN_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \ + } + +#define ASDF_TEST2_CAPS_MAP_DEFS \ + { \ + &test2_CAPS_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \ + } + +#define ASDF_TEST2_KEYMAPS ASDF_TEST2_MAP_DEFS, ASDF_TEST2_CAPS_MAP_DEFS + +#define ASDF_TEST2_KEYMAPS_COUNT 2 +#define ASDF_TEST2_PLAIN_MAP_INDEX (ASDF_TEST2_BASE + 0) +#define ASDF_TEST2_CAPS_MAP_INDEX (ASDF_TEST2_BASE + 1) +#define VCAPS_TEST_KEYMAP ASDF_TEST2_PLAIN_MAP_INDEX +#define VSHIFT_TEST_KEYMAP ASDF_TEST2_PLAIN_MAP_INDEX + +#define ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH 4 +#define ASDF_TEST2_KEYMAP_INITIALIZER_1 \ + { \ + { .virtual_device = VCAPS_LED, .physical_device = PHYSICAL_LED1, .initial_value = 0 }, \ + { .virtual_device = VSHIFT_LED, .physical_device = PHYSICAL_LED2, .initial_value = 0 }, \ + { .virtual_device = VOUT2, .physical_device = PHYSICAL_OUT3, .initial_value = 0 }, \ + { \ + .virtual_device = VOUT2, .physical_device = ASDF_PHYSICAL_NUM_RESOURCES, .initial_value = 0 \ + } \ + } + +#define ASDF_TEST2_KEYMAP_INITIALIZER_2 \ + { \ + { .virtual_device = VCAPS_LED, .physical_device = PHYSICAL_LED1, .initial_value = 0 }, \ + { .virtual_device = VSHIFT_LED, .physical_device = PHYSICAL_LED2, .initial_value = 0 }, \ + { .virtual_device = VOUT2, .physical_device = PHYSICAL_OUT3, .initial_value = 0 }, \ + { \ + .virtual_device = VOUT2, .physical_device = ASDF_PHYSICAL_NUM_RESOURCES, .initial_value = 0 \ + } \ + } + +#define ASDF_TEST2_KEYMAP_INITIALIZER \ + ASDF_TEST2_KEYMAP_INITIALIZER_1, ASDF_TEST2_KEYMAP_INITIALIZER_2 + + +#define ASDF_TEST_ALTERNATE_SCANNER_MAP (ASDF_TEST2_BASE + 0) +#define ASDF_TEST_ALTERNATE_OUTPUT_MAP (ASDF_TEST2_BASE + 0) +#define ASDF_TEST_EACH_SCAN_MAP (ASDF_TEST2_BASE + 1) +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_LENGTH 2 +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_1 \ + { \ + { \ + .hook_id = ASDF_HOOK_SCANNER, \ + .hook_func = (asdf_hook_function_t) test_hook_read_row, \ + }, \ + { \ + .hook_id = ASDF_HOOK_OUTPUT, \ + .hook_func = (asdf_hook_function_t) test_hook_output, \ + }, \ + } + +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_2 \ + { \ + { \ + .hook_id = ASDF_HOOK_EACH_SCAN, \ + .hook_func = (asdf_hook_function_t) test_hook_each_scan, \ + }, \ + } + +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER \ + ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_1, ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_2 + + +// The following preprocessor "code" permits various keymaps to be created and +// included without generating a lot of complicating code dependencies. The use +// of macros in this way is a bit ugly, I realize, and stretches the intention +// of the C preprocessor. The C preprocessor is used to store a bit of state to +// keep track of the number and ordering of the keymaps as they are added, and +// to keep track of the array sizes to be allocated at compile time. + + +#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_TEST2_NUM_ROWS) +#undef ASDF_NUM_ROWS +#define ASDF_NUM_ROWS ASDF_TEST2_NUM_ROWS +#endif + +#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_TEST2_NUM_COLS) +#undef ASDF_NUM_COLS +#define ASDF_NUM_COLS ASDF_TEST2_NUM_COLS +#endif + +#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \ + || (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_INITIALIZER_LENGTH +#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH +#endif + +#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) \ + || (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_TEST_KEYMAP_HOOK_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH +#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_TEST_KEYMAP_HOOK_INITIALIZER_LENGTH +#endif + +#endif /* !defined (ASDF_KEYMAP_DEFS_TEST2_H) */ + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/test/test_asdf_hook.c b/firmware/asdf/test/test_asdf_hook.c index 56b822c..2caac03 100644 --- a/firmware/asdf/test/test_asdf_hook.c +++ b/firmware/asdf/test/test_asdf_hook.c @@ -8,7 +8,6 @@ #include "asdf_ascii.h" #include "asdf_modifiers.h" #include "asdf_keymaps.h" -#include "asdf_keymap_defs.h" #include "asdf_buffer.h" #include "asdf_repeat.h" #include "asdf_hook.h" diff --git a/firmware/asdf/test/test_asdf_keymap_defs.c b/firmware/asdf/test/test_asdf_keymap_defs.c new file mode 100644 index 0000000..fbfc371 --- /dev/null +++ b/firmware/asdf/test/test_asdf_keymap_defs.c @@ -0,0 +1,63 @@ +// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*- +// +// Unified Keyboard Project +// ASDF keyboard firmware +// +// test_asdf_keymap_defs.c +// +// Contains keymap definitions for unit tests +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +// + +#include +#include "asdf_ascii.h" +#include "asdf_keymaps.h" + +static const asdf_keycode_matrix_t test_PLAIN_matrix = ASDF_TEST_PLAIN_MAP; +static const asdf_keycode_matrix_t test_SHIFT_matrix = ASDF_TEST_SHIFT_MAP; +static const asdf_keycode_matrix_t test_CAPS_matrix = ASDF_TEST_CAPS_MAP; +static const asdf_keycode_matrix_t test_CTRL_matrix = ASDF_TEST_CTRL_MAP; + +static const asdf_keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; +static const asdf_keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; +static const asdf_keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; +static const asdf_keycode_matrix_t test2_CTRL_matrix = ASDF_TEST2_CTRL_MAP; + + +// PROCEDURE: +// INPUTS: +// OUTPUTS: +// +// DESCRIPTION: +// +// SIDE EFFECTS: +// +// NOTES: +// +// SCOPE: +// +// COMPLEXITY: +// + + + + + + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. + diff --git a/firmware/asdf/test/test_asdf_keymap_defs.h b/firmware/asdf/test/test_asdf_keymap_defs.h new file mode 100644 index 0000000..983b638 --- /dev/null +++ b/firmware/asdf/test/test_asdf_keymap_defs.h @@ -0,0 +1,381 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// asdf_keymaps.h +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +// While there is nothing preventing a standard keyboard from having both a +// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For +// testing, both must be present to test their functionality. + +#if !defined(TEST_ASDF_KEYMAP_DEFS_H) +#define TEST_ASDF_KEYMAP_DEFS_H + +#define ASDF_TEST_NUM_COLS 8 +#define ASDF_TEST_NUM_ROWS 9 + +// The first value in each row serves two purposes: +// +// 1) Indicate a valid row of codes if the value is nonzero. +// 2) Indicate the physical row number corresponding to the keymap row. +// +// Multiple keymaps may be combined, some of which use more rows than other +// keymaps. The keymap with the most rows determines how many rows are allocated +// for each keymap. Since each keymap only initializes the rows it uses, then +// the shorter keymaps may have multiple uninitialized rows that should not be +// scanned. The C99 standard guarantees that all elements no explicitly +// initialized shall be initialized to 0 (C99 Standard 6.7.8.21). Therefore, +// keymap rows starting with a 0 are not valid and are not scanned. +// +// Some hardware may contain blank physical rows To avoid having unused empty +// rows, the first column of each row indicates the physical row. For example, 8 +// rows of switches (0-7), and a bank of DIP switches on row 15. In this case, +// only 9 rows need be allocated. + + +#define PLAIN_MATRIX_1 RESERVED_1 +#define CAPS_MATRIX_1 RESERVED_2 +#define SHIFT_MATRIX_1 RESERVED_3 +#define CTRL_MATRIX_1 RESERVED_4 + +#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1) +#define ASDF_TEST_MAP_DIP_SWITCHES \ + [ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 } + +#define ASDF_TEST_PLAIN_MAP \ + { \ + { PLAIN_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \ + { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \ + { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'o', \ + 'l', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST_CAPS_MAP \ + { \ + { CAPS_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', \ + 'L', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST_SHIFT_MAP \ + { \ + \ + { SHIFT_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \ + { ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \ + { ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \ + '0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \ + { ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + +#define ASDF_TEST_CTRL_MAP \ + { \ + { CTRL_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \ + { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \ + ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \ + { ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \ + ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \ + { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, \ + ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S }, \ + { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \ + ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, \ + ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \ + { ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \ + ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \ + { ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, \ + ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_2 }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + + +#define ASDF_TEST_KEYMAPS ASDF_TEST_MAP_DEFS, ASDF_TEST_CAPS_MAP_DEFS + +#define ASDF_TEST_PLAIN_MAP_INDEX 0 +#define ASDF_TEST_CAPS_MAP_INDEX 1 + +#define SINGLE_TESTS_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX +#define DOUBLE_ASSIGN_TEST_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX + +#define TRIPLE_TESTS_KEYMAP ASDF_TEST_CAPS_MAP_INDEX + +#define ASDF_TEST_KEYMAP_INITIALIZER_LENGTH 5 +#define ASDF_TEST_KEYMAP_INITIALIZER_1 \ + { \ + { \ + /* Single assignment */ \ + .virtual_device = VOUT1, \ + .physical_device = PHYSICAL_OUT1, \ + .function = V_NOFUNC, \ + .initial_value = 0, \ + }, \ + { \ + /* single toggle */ \ + .virtual_device = VOUT2, \ + .physical_device = PHYSICAL_OUT2, \ + .function = V_TOGGLE, \ + .initial_value = 0, \ + }, \ + { \ + /* single pulse */ \ + .virtual_device = VOUT3, \ + .physical_device = PHYSICAL_OUT3, \ + .function = V_PULSE_SHORT, \ + .initial_value = 0, \ + }, \ + { /* first of double assignment attempt */ \ + .virtual_device = VOUT4, \ + .physical_device = PHYSICAL_LED1, \ + .initial_value = 0 \ + }, \ + { /* second of double assignment attempt */ \ + .virtual_device = VOUT5, .physical_device = PHYSICAL_LED1, .initial_value = 1 \ + } \ + } + +#define ASDF_TEST_KEYMAP_INITIALIZER_2 \ + { \ + { \ + /* Triple assignment */ \ + .virtual_device = VOUT1, \ + .physical_device = PHYSICAL_OUT1, \ + .function = V_TOGGLE, \ + .initial_value = 0, \ + }, \ + { \ + .virtual_device = VOUT1, \ + .physical_device = PHYSICAL_OUT2, \ + .function = V_TOGGLE, \ + .initial_value = 1, \ + }, \ + { \ + .virtual_device = VOUT1, .physical_device = PHYSICAL_OUT3, .function = V_TOGGLE, \ + .initial_value = 0, \ + } \ + } + +#define ASDF_TEST_KEYMAP_INITIALIZER ASDF_TEST_KEYMAP_INITIALIZER_1, ASDF_TEST_KEYMAP_INITIALIZER_2 + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_LENGTH 2 + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_1 \ + { \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_1, \ + }, \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_2, \ + }, \ + } + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_2 \ + { \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_3, \ + }, \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = &test_hook_4, \ + }, \ + } + +#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER \ + ASDF_TEST_KEYMAP_HOOK_INITIALIZER_1, ASDF_TEST_KEYMAP_HOOK_INITIALIZER_2 + + + + + +#define PLAIN_MATRIX_2 RESERVED_5 +#define CAPS_MATRIX_2 RESERVED_6 +#define SHIFT_MATRIX_2 RESERVED_7 +#define CTRL_MATRIX_2 RESERVED_8 + +#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1) + +#define ASDF_TEST_MAP_DIP_SWITCHES \ + [ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 } + +#define ASDF_TEST2_PLAIN_MAP \ + { \ + { PLAIN_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \ + { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \ + { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'o', \ + 'l', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST2_CAPS_MAP \ + { \ + { CAPS_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \ + { ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + /**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', \ + 'L', ASCII_PERIOD }, \ + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \ + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \ + } + +#define ASDF_TEST2_SHIFT_MAP \ + { \ + \ + { SHIFT_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \ + { ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \ + { ACTION_NOTHING, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \ + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \ + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \ + { ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \ + '0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \ + { ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + +#define ASDF_TEST2_CTRL_MAP \ + { \ + { CTRL_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \ + ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \ + { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \ + ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \ + { ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \ + ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \ + { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, \ + ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S }, \ + { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \ + ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \ + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, \ + ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \ + { ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \ + ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \ + { ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, \ + ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_2 }, \ + ASDF_TEST_MAP_DIP_SWITCHES \ + } + + +#define ASDF_TEST2_DECLARATIONS \ + +#define ASDF_TEST2_MAP_DEFS \ + { \ + &test2_PLAIN_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \ + } + +#define ASDF_TEST2_CAPS_MAP_DEFS \ + { \ + &test2_CAPS_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \ + } + +#define ASDF_TEST2_KEYMAPS ASDF_TEST2_MAP_DEFS, ASDF_TEST2_CAPS_MAP_DEFS + +#define ASDF_TEST2_PLAIN_MAP_INDEX 2 +#define ASDF_TEST2_CAPS_MAP_INDEX 3 + +#define VCAPS_TEST_KEYMAP ASDF_TEST2_PLAIN_MAP_INDEX +#define VSHIFT_TEST_KEYMAP ASDF_TEST2_PLAIN_MAP_INDEX + +#define ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH 4 +#define ASDF_TEST2_KEYMAP_INITIALIZER_1 \ + { \ + { .virtual_device = VCAPS_LED, .physical_device = PHYSICAL_LED1, .initial_value = 0 }, \ + { .virtual_device = VSHIFT_LED, .physical_device = PHYSICAL_LED2, .initial_value = 0 }, \ + { .virtual_device = VOUT2, .physical_device = PHYSICAL_OUT3, .initial_value = 0 }, \ + { \ + .virtual_device = VOUT2, .physical_device = ASDF_PHYSICAL_NUM_RESOURCES, .initial_value = 0 \ + } \ + } + +#define ASDF_TEST2_KEYMAP_INITIALIZER_2 \ + { \ + { .virtual_device = VCAPS_LED, .physical_device = PHYSICAL_LED1, .initial_value = 0 }, \ + { .virtual_device = VSHIFT_LED, .physical_device = PHYSICAL_LED2, .initial_value = 0 }, \ + { .virtual_device = VOUT2, .physical_device = PHYSICAL_OUT3, .initial_value = 0 }, \ + { \ + .virtual_device = VOUT2, .physical_device = ASDF_PHYSICAL_NUM_RESOURCES, .initial_value = 0 \ + } \ + } + +#define ASDF_TEST2_KEYMAP_INITIALIZER \ + ASDF_TEST2_KEYMAP_INITIALIZER_1, ASDF_TEST2_KEYMAP_INITIALIZER_2 + + +#define ASDF_TEST_ALTERNATE_SCANNER_MAP (ASDF_TEST2_BASE + 0) +#define ASDF_TEST_ALTERNATE_OUTPUT_MAP (ASDF_TEST2_BASE + 0) +#define ASDF_TEST_EACH_SCAN_MAP (ASDF_TEST2_BASE + 1) +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_LENGTH 2 +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_1 \ + { \ + { \ + .hook_id = ASDF_HOOK_SCANNER, \ + .hook_func = (asdf_hook_function_t) test_hook_read_row, \ + }, \ + { \ + .hook_id = ASDF_HOOK_OUTPUT, \ + .hook_func = (asdf_hook_function_t) test_hook_output, \ + }, \ + } + +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_2 \ + { \ + { \ + .hook_id = ASDF_HOOK_EACH_SCAN, \ + .hook_func = (asdf_hook_function_t) test_hook_each_scan, \ + }, \ + } + +#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER \ + ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_1, ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_2 + +#endif /* !defined (TEST_ASDF_KEYMAP_DEFS_H) */ + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/test/test_asdf_keymaps.c b/firmware/asdf/test/test_asdf_keymaps.c index a6623e2..36e2e8d 100644 --- a/firmware/asdf/test/test_asdf_keymaps.c +++ b/firmware/asdf/test/test_asdf_keymaps.c @@ -5,14 +5,26 @@ #include "asdf.h" #include "asdf_ascii.h" #include "asdf_modifiers.h" +#include "test_asdf_keymap_defs.h" #include "asdf_keymaps.h" -#include "asdf_keymap_defs.h" +#include "test_asdf_lib.h" #define TESTALPHA 'a' #define TESTNUM '2' #define TESTKEYMAP_TAG PLAIN_MATRIX_1 #define NUM_DIPSWITCHES 4 + +static const FLASH asdf_keycode_matrix_t test_PLAIN_matrix = ASDF_TEST_PLAIN_MAP; +static const FLASH asdf_keycode_matrix_t test_SHIFT_matrix = ASDF_TEST_SHIFT_MAP; +static const FLASH asdf_keycode_matrix_t test_CAPS_matrix = ASDF_TEST_CAPS_MAP; +static const FLASH asdf_keycode_matrix_t test_CTRL_matrix = ASDF_TEST_CTRL_MAP; + +static const FLASH asdf_keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; +static const FLASH asdf_keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; +static const FLASH asdf_keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; +static const FLASH asdf_keycode_matrix_t test2_CTRL_matrix = ASDF_TEST2_CTRL_MAP; + // row: row number // col: column number // keymap_name: id of the file defining the matrix to be used. @@ -75,8 +87,6 @@ typedef struct { // used to place the codes are functioning and are being properly used. -ASDF_KEYMAP_DECLARATIONS; - // keymap coordinates for special functions static coord_t alpha_sample; static coord_t num_sample; @@ -145,21 +155,6 @@ asdf_cols_t asdf_arch_read_row(uint8_t row) return (asdf_cols_t) (row+1); } -// the next two test check the preprocessor mechanism for allocating space for -// the largest defined keymap - -// check to see that the largest number of columns is detected. -void test_num_cols_is_max_cols(void) -{ - TEST_ASSERT_EQUAL_INT32(max(ASDF_TEST_NUM_COLS, ASDF_TEST2_NUM_COLS), ASDF_NUM_COLS); -} - -// check to see that the largest number of rows is detected. -void test_num_rows_is_max_rows(void) -{ - TEST_ASSERT_EQUAL_INT32(max(ASDF_TEST_NUM_ROWS, ASDF_TEST2_NUM_ROWS), ASDF_NUM_ROWS); -} - void test_chars_are_in_map(void) { TEST_VALID_CODE(alpha_sample); @@ -328,8 +323,6 @@ void dip_switch_invalid_keymap_has_no_effect(void) int main(void) { UNITY_BEGIN(); - RUN_TEST(test_num_rows_is_max_rows); - RUN_TEST(test_num_cols_is_max_cols); RUN_TEST(test_chars_are_in_map); RUN_TEST(keymap0_plain_gives_plain_values); RUN_TEST(keymap0_shift_gives_shift_values); diff --git a/firmware/asdf/test/test_asdf_keyslib.c b/firmware/asdf/test/test_asdf_keyslib.c new file mode 100644 index 0000000..37741de --- /dev/null +++ b/firmware/asdf/test/test_asdf_keyslib.c @@ -0,0 +1,68 @@ +#include +#include "asdf.h" +#include "asdf_keymaps.h" +#include "asdf_keymap_defs.h" +#include "test_asdf_lib.h" +#include "asdf_arch.h" + +static uint32_t key_matrix[ASDF_NUM_ROWS] = {}; + +ASDF_KEYMAP_DECLARATIONS; + + +coord_t *find_code(asdf_keycode_t code) +{ + uint32_t done = 0; + static coord_t location = { .row = -1, .col = -1 }; + + for (uint32_t row = 0; !done && (row < ASDF_NUM_ROWS); row++) { + for (uint32_t col = 0; !done && (col < ASDF_NUM_COLS); col++) { + if (test_PLAIN_matrix[row][col] == code) { + done = 1; + location.row = row; + location.col = col; + } + } + } + return &location; +} + + +void keyscan_delay(int32_t ticks) +{ + for (; ticks; ticks--) { + asdf_keyscan(); + } +} + +void press_no_debounce(asdf_keycode_t code) +{ + coord_t *location = find_code(code); + key_matrix[location->row] |= (1 << location->col); +} + +void release_no_debounce(asdf_keycode_t code) +{ + coord_t *location = find_code(code); + key_matrix[location->row] &= ~(1 << location->col); +} + +void press(asdf_keycode_t code) +{ + press_no_debounce(code); + keyscan_delay(ASDF_DEBOUNCE_TIME_MS); +} + +void release(asdf_keycode_t code) +{ + release_no_debounce(code); + keyscan_delay(ASDF_DEBOUNCE_TIME_MS); +} + + +asdf_cols_t asdf_arch_read_row(uint8_t row) +{ + return key_matrix[row]; +} + + diff --git a/firmware/asdf/test/test_asdf_keyslib.h b/firmware/asdf/test/test_asdf_keyslib.h new file mode 100644 index 0000000..7a670b0 --- /dev/null +++ b/firmware/asdf/test/test_asdf_keyslib.h @@ -0,0 +1,23 @@ +#if !defined(TEST_ASDF_LIB_H) + +#include "asdf_keymaps.h" + +// struct to define keymap row,col pairs +typedef struct { + int32_t row; + int32_t col; +} coord_t; + + +void keyscan_delay(int32_t ticks); +void press_no_debounce(asdf_keycode_t code); +void release_no_debounce(asdf_keycode_t code); +void press(asdf_keycode_t code); +void release(asdf_keycode_t code); +asdf_cols_t asdf_arch_read_row(uint8_t row); +coord_t *find_code(asdf_keycode_t code); + + + +#define TEST_ASDF_LIB_H +#endif // if !defined(TEST_ASDF_LIB_H) diff --git a/firmware/asdf/test/test_asdf_lib.c b/firmware/asdf/test/test_asdf_lib.c index 80d9612..e571248 100644 --- a/firmware/asdf/test/test_asdf_lib.c +++ b/firmware/asdf/test/test_asdf_lib.c @@ -1,7 +1,8 @@ #include #include "asdf.h" +#include "asdf_virtual.h" +#include "asdf_physical.h" #include "asdf_keymaps.h" -#include "asdf_keymap_defs.h" #include "asdf_arch.h" #include "asdf_hook.h" #include "test_asdf_lib.h" diff --git a/firmware/asdf/test/test_asdf_virtual.c b/firmware/asdf/test/test_asdf_virtual.c index d281dc9..4391563 100644 --- a/firmware/asdf/test/test_asdf_virtual.c +++ b/firmware/asdf/test/test_asdf_virtual.c @@ -6,7 +6,6 @@ #include "asdf_ascii.h" #include "asdf_modifiers.h" #include "asdf_keymaps.h" -#include "asdf_keymap_defs.h" #include "asdf_config.h" #include "test_asdf_lib.h" diff --git a/firmware/asdf/test/test_keymapdefs.c b/firmware/asdf/test/test_keymapdefs.c new file mode 100644 index 0000000..09eb0c7 --- /dev/null +++ b/firmware/asdf/test/test_keymapdefs.c @@ -0,0 +1,176 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// test_keymapdefs.c +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +// While there is nothing preventing a standard keyboard from having both a +// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For +// testing, both must be present to test their functionality. + + +#include "test_keymapdefs.h" + +#define PLAIN_MATRIX_1 RESERVED_1 +#define CAPS_MATRIX_1 RESERVED_2 +#define SHIFT_MATRIX_1 RESERVED_3 +#define CTRL_MATRIX_1 RESERVED_4 + +#define ASDF_TEST_PLAIN_MAP_INDEX 0 +#define ASDF_TEST_CAPS_MAP_INDEX 1 + +#define SINGLE_TESTS_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX +#define DOUBLE_ASSIGN_TEST_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX +#define TRIPLE_TESTS_KEYMAP ASDF_TEST_CAPS_MAP_INDEX + +#define ASDF_TEST_KEYMAP_INITIALIZER_LENGTH 5 + +#define ASDF_TEST_MAP_DIP_SWITCHES \ + [ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 } + + +static const FLASH keycode_matrix_t test_PLAIN_matrix = { + { PLAIN_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ACTION_CAPS, ASCII_ESC, ACTION_CTRL, + ASCII_BACKSLASH }, + { ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, + { ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, + { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, + { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'o', 'l', + ASCII_PERIOD }, + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, + ASDF_TEST_MAP_DIP_SWITCHES, +}; + +static const FLASH keycode_matrix_t test_CAPS_matrix = { + { CAPS_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ACTION_NOTHING, ASCII_ESC, + ACTION_CTRL, ASCII_BACKSLASH }, + { ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, + { ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', + ASCII_PERIOD }, + { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, + { ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, + ASDF_TEST_MAP_DIP_SWITCHES +}; + + +static const FLASH keycode_matrix_t test_SHIFT_matrix = { + { SHIFT_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ACTION_NOTHING, ASCII_ESC, + ACTION_CTRL, ASCII_VERT_BAR }, + { ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, + { ACTION_NOTHING, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, + { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, + { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, + { ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', '0', ASCII_RT_PAREN, + ASCII_LT_PAREN }, + { ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, + ASDF_TEST_MAP_DIP_SWITCHES +}; + +static const FLASH keycode_matrix_t test_CTRL_matrix = { + { CTRL_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ACTION_NOTHING, ASCII_ESC, + ACTION_CTRL, 0x1c }, + { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, ASCII_SPACE, ASCII_CTRL_Z, + ASCII_CTRL_A, ASCII_CTRL_Q }, + { ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, ASCII_CTRL_B, ASCII_CTRL_V, + ASCII_CTRL_C, ASCII_CTRL_X }, + { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, ASCII_CTRL_G, ASCII_CTRL_F, + ASCII_CTRL_D, ASCII_CTRL_S }, + { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, ASCII_CTRL_T, ASCII_CTRL_R, + ASCII_CTRL_E, ASCII_CTRL_W }, + { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, ASCII_CTRL_O, + ASCII_CTRL_L, ACTION_NOTHING }, + { ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, + ACTION_FN_8 }, + { ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, + ACTION_FN_2 }, + ASDF_TEST_MAP_DIP_SWITCHES +}; + + +static void build_test_map_matrices(void) +{ + asdf_keymap_add_keymap(&test_PLAIN_matrix, MOD_PLAIN_MAP); + asdf_keymap_add_keymap(&test_SHIFT_matrix, MOD_SHIFT_MAP); + asdf_keymap_add_keymap(&test_CAPS_matrix, MOD_CAPS_MAP); + asdf_keymap_add_keymap(&test_CTRL_matrix, MOD_CTRL_MAP); +} + +static void build_test_caps_map_matrices(void) +{ + asdf_keymap_add_keymap(&test_CAPS_matrix, MOD_PLAIN_MAP); + asdf_keymap_add_keymap(&test_SHIFT_matrix, MOD_SHIFT_MAP); + asdf_keymap_add_keymap(&test_CAPS_matrix, MOD_CAPS_MAP); + asdf_keymap_add_keymap(&test_CTRL_matrix, MOD_CTRL_MAP); +} + +static void build_test_map_virtual_init(void) +{ + /* Single assignment */ \ + asdf_keymap_add_virtual_device(VOUT1, PHYSICAL_OUT1, V_NOFUNC, 0); + /* single toggle */ \ + asdf_keymap_add_virtual_device(VOUT2, PHYSICAL_OUT2, V_TOGGLE, 0); + /* single pulse */ + asdf_keymap_add_virtual_device(VOUT3, PHYSICAL_OUT3, V_PULSE_SHORT, 0); + /* first of double assignment attempt */ + asdf_keymap_add_virtual_device(VOUT4, PHYSICAL_LED1, V_NOFUNC, 0); + /* second of double assignment attempt */ + asdf_keymap_add_virtual_device(VOUT5, PHYSICAL_LED1, V_NOFUNC, 1); +} + +static void build_test_caps__map_virtual_init(void) +{ + /* Triple assignment */ + asdf_keymap_add_virtual_device(VOUT1, PHYSICAL_OUT1, V_TOGGLE, 0); + asdf_keymap_add_virtual_device(VOUT1, PHYSICAL_OUT2, V_TOGGLE, 1); + asdf_keymap_add_virtual_device(VOUT1, PHYSICAL_OUT3, V_TOGGLE, 0); +} + +static void build_test_map_hooks(void) +{ + asdf_keymap_add_hook(ASDF_HOOK_KEYMAP_SETUP, &test_hook_1); + asdf_keymap_add_hook(ASDF_HOOK_KEYMAP_SETUP, &test_hook_2); +} + +static void build_test_caps_map_hooks(void) +{ + asdf_keymap_add_hook(ASDF_HOOK_KEYMAP_SETUP, &test_hook_3); + asdf_keymap_add_hook(ASDF_HOOK_KEYMAP_SETUP, &test_hook_4); +} + +void build_test_keymap(void) +{ + asdf_keymaps_build_keymap(ASDF_TEST_PLAIN_MAP_INDEX); + build_test_map_matrices(); + build_test_map1_virtual_init(); + build_test_map1_hooks(); + + asdf_keymaps_build_keymap(ASDF_TEST_CAPS_MAP_INDEX); + build_test_caps_map_matrices(); + build_test_caps__map_virtual_init(); + build_test_caps_map_hooks(); +} + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/test/test_keymapdefs.h b/firmware/asdf/test/test_keymapdefs.h new file mode 100644 index 0000000..f7d50f2 --- /dev/null +++ b/firmware/asdf/test/test_keymapdefs.h @@ -0,0 +1,46 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// test_keymapdefs.h +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +// While there is nothing preventing a standard keyboard from having both a +// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For +// testing, both must be present to test their functionality. + + +#if !(defined) TEST_KEYMAPDEFS_H + + +#define PLAIN_MATRIX_1 RESERVED_1 +#define CAPS_MATRIX_1 RESERVED_2 +#define SHIFT_MATRIX_1 RESERVED_3 +#define CTRL_MATRIX_1 RESERVED_4 + +#define SINGLE_TESTS_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX +#define DOUBLE_ASSIGN_TEST_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX +#define TRIPLE_TESTS_KEYMAP ASDF_TEST_CAPS_MAP_INDEX + +#define ASDF_TEST_MAP_DIP_SWITCHES \ + [ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 } + +#endif // TEST_KEYMAPDEFS_H + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/test/test_keypress_lib.c b/firmware/asdf/test/test_keypress_lib.c new file mode 100644 index 0000000..60f0949 --- /dev/null +++ b/firmware/asdf/test/test_keypress_lib.c @@ -0,0 +1,505 @@ +#include +#include +#include + +#include "unity.h" +#include "asdf.h" +#include "asdf_arch.h" +#include "asdf_ascii.h" +#include "asdf_modifiers.h" +#include "asdf_keymaps.h" +#include "asdf_keymap_defs.h" +#include "asdf_buffer.h" +#include "asdf_repeat.h" + +#define A 'a' +#define B 'b' + +#define TEST_STRING "abcdefghijklmnop" + +#define NUM_REPEATS (ASDF_KEYCODE_BUFFER_SIZE - 2) + +#define TESTMAP(row, col, mapname, mapname2) \ + do { \ + asdf_keycode_t expected = mapname##_matrix[(row)][(col)]; \ + asdf_keycode_t result = asdf_keymaps_get_code((row), (col), MOD_##mapname2##_MAP); \ + TEST_ASSERT_EQUAL_INT(expected, result); \ + } while (0); + +#define TESTPLAIN(row, col, n) TESTMAP((row), (col), PLAIN, n) +#define TESTSHIFT(row, col, n) TESTMAP((row), (col), SHIFT, n) +#define TESTCAPS(row, col, n) TESTMAP((row), (col), CAPS, n) +#define TESTCTRL(row, col, n) TESTMAP((row), (col), CTRL, n) + +const char test_string[] = TEST_STRING; + +const asdf_keycode_t key_a = A; +const asdf_keycode_t key_b = B; + +typedef struct { + int32_t row; + int32_t col; +} coord_t; + + +ASDF_TEST_DECLARATIONS; + +static uint32_t key_matrix[ASDF_NUM_ROWS]; + + +void setUp(void) +{ + asdf_buffer_init(); + asdf_init(); + + // initialize simulated key matrix + for (uint32_t i = 0; i < ASDF_NUM_ROWS; i++) { + key_matrix[i] = 0; + } +} + +void tearDown(void) {} + +coord_t *find_code(asdf_keycode_t code) +{ + uint32_t done = 0; + static coord_t location = { .row = -1, .col = -1 }; + + for (uint32_t row = 0; !done && (row < ASDF_NUM_ROWS); row++) { + for (uint32_t col = 0; !done && (col < ASDF_NUM_COLS); col++) { + if (test_PLAIN_matrix[row][col] == code) { + done = 1; + location.row = row; + location.col = col; + } + } + } + return &location; +} + + +asdf_keycode_t shifted(asdf_keycode_t code) +<{ + coord_t *location = find_code(code); + return test_SHIFT_matrix[location->row][location->col]; +} + +asdf_keycode_t caps(asdf_keycode_t code) +{ + coord_t *xy = find_code(code); + return test_CAPS_matrix[xy->row][xy->col]; +} + +asdf_keycode_t ctrl(asdf_keycode_t code) +{ + coord_t *xy = find_code(code); + return test_CTRL_matrix[xy->row][xy->col]; +} + + +void keyscan_delay(int32_t ticks) +{ + for (; ticks; ticks--) { + asdf_keyscan(); + } +} + + +void press_no_debounce(asdf_keycode_t code) +{ + coord_t *location = find_code(code); + key_matrix[location->row] |= (1 << location->col); +} + +void release_no_debounce(asdf_keycode_t code) +{ + coord_t *location = find_code(code); + key_matrix[location->row] &= ~(1 << location->col); +} + +void press(asdf_keycode_t code) +{ + press_no_debounce(code); + keyscan_delay(ASDF_DEBOUNCE_TIME_MS); +} + +void release(asdf_keycode_t code) +{ + release_no_debounce(code); + keyscan_delay(ASDF_DEBOUNCE_TIME_MS); +} + + +asdf_cols_t asdf_arch_read_row(uint8_t row) +{ + return key_matrix[row]; +} + + + +// No repsonse to a keypress before it is debounced. +void pressing_a_gives_nothing_before_debounce(void) +{ + press_no_debounce(key_a); + + // no keypress after only ASDF_DEBOUNCE_TIME_MS -1 ticks (not yet debounced): + keyscan_delay(ASDF_DEBOUNCE_TIME_MS - 1); + TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + +// pressing 'A' gives 'a' +void pressing_a_gives_a(void) +{ + press_no_debounce(key_a); + + // no keypress after only ASDF_DEBOUNCE_TIME_MS -1 ticks (not yet debounced): + keyscan_delay(ASDF_DEBOUNCE_TIME_MS - 1); + TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_next_code()); + + // allow the key to finish debounce + keyscan_delay(1); + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (int32_t) asdf_next_code()); + + // no more codes in the buffer. + TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + +// pressing SHIFT+A gives 'A' +void pressing_shift_a_gives_shifted_a(void) +{ + press(ACTION_SHIFT); + press(key_a); + TEST_ASSERT_EQUAL_INT32((int32_t) shifted(key_a), (int32_t) asdf_next_code()); +} + +// pressing CAPS+A gives 'A' +void pressing_caps_a_gives_caps_a(void) +{ + press(ACTION_CAPS); + release(ACTION_CAPS); + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) caps(key_a), (int32_t) asdf_next_code()); +} + +// pressing CTRL+A gives 0x01 (Ctrl-A) +void pressing_ctrl_a_gives_ctrl_a(void) +{ + press(ACTION_CTRL); + press(key_a); + TEST_ASSERT_EQUAL_INT32((int32_t) ctrl(key_a), (int32_t) asdf_next_code()); +} + +// pressing REPT+A repeats 'a' +void pressing_rept_a_repeats_a(void) +{ + press(ACTION_REPEAT); + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + } + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// pressing REPT+SHIFT+A repeats 'A' +void pressing_shift_rept_a_repeats_shifted_a(void) +{ + press(ACTION_REPEAT); + press(ACTION_SHIFT); + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) shifted(key_a), (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) shifted(key_a), (uint32_t) asdf_next_code()); + } + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// pressing REPT+CAPS+A repeats 'A' +void pressing_caps_rept_a_repeats_caps_a(void) +{ + press(ACTION_REPEAT); + press(ACTION_CAPS); + + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) caps(key_a), (uint32_t) asdf_next_code()); + + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) caps(key_a), (uint32_t) asdf_next_code()); + } + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + +// pressing REPT+CTRL+A repeats CTRL-A +void pressing_ctrl_rept_a_repeats_ctrl_a(void) +{ + press(ACTION_REPEAT); + press(ACTION_CTRL); + + press(key_a); + TEST_ASSERT_EQUAL_INT32((int32_t) ctrl(key_a), (uint32_t) asdf_next_code()); + + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + for (int i = 0; i < NUM_REPEATS + 1; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) ctrl(key_a), (uint32_t) asdf_next_code()); + } + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + +// pressing and holding 'A' autorepeats 'A' +void holding_a_autorepeats_a(void) +{ + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(ASDF_AUTOREPEAT_TIME_MS); + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// pressing and holding 'A' autorepeats 'A' +void holding_a_autorepeats_slow_then_fast(void) +{ + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(ASDF_AUTOREPEAT_TIME_MS); + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + } + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// pressing and holding 'A' and 'B' within less than debounce interval +// eventually returns 'A' then 'B' +void pressing_a_then_b_before_debounce_gives_a_then_b(void) +{ + press_no_debounce(key_a); + + // press B very quickly after a + keyscan_delay(1); + + press(key_b); + + // first get back A + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // next get back B + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + + // and then verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// pressing and holding a series of keys (up to buffer size) in rapid +// succession, allowing each key to debounce, before sending the next, sends all +// the keys in order. (n-key rollover) +void test_key_sequence_nkro(void) +{ + for (int i = 0; i < (int32_t) strlen(test_string); i++) { + press((asdf_keycode_t) test_string[i]); + } + + for (int i = 0; i < (int32_t) strlen(test_string); i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) test_string[i], (int32_t) asdf_next_code()); + } + + // and then verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// pressing and holding a series of keys (up to buffer size) in rapid succession +// without waiting for prior keys to debounce, eventually debounces and sends +// all the keys in order. (n-key rollover) +void test_key_sequence_nkro_simultaneous_debounce(void) +{ + for (int i = 0; i < (int32_t) strlen(test_string); i++) { + press_no_debounce((asdf_keycode_t) test_string[i]); + keyscan_delay(1); + } + + // several keys are already debounced, but now make sure they all are: + keyscan_delay(ASDF_DEBOUNCE_TIME_MS); + + for (int i = 0; i < (int32_t) strlen(test_string); i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) test_string[i], (int32_t) asdf_next_code()); + } + + // and then verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// holding 'A' then pressing 'B' before autorepeat interval and holding 'B' gives 'A', then repeats +// 'B' +void holding_a_briefly_then_holding_b_gives_a_and_repeats_b(void) +{ + press(key_a); + keyscan_delay(ASDF_AUTOREPEAT_TIME_MS / 2); + press(key_b); + + // hold "a" and "b" for autorepeat delay: + keyscan_delay(ASDF_AUTOREPEAT_TIME_MS); + + // hold "a" and "b" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + // should get "a" back, then "b" + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + + // now get back NUM_REEPEATS repetitions of "b" + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + } + + // and then verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +// holding 'B' while repeating 'A' starts autorepeat delay, then starts repeating 'B' +void holding_a_then_holding_b_autorepeats_a_then_autorepeats_b(void) +{ + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // hold "a" for AUTOREPEAT delay + keyscan_delay(ASDF_AUTOREPEAT_TIME_MS); + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + // empty the buffer to make room for 'B' + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + } + + // now press "b" while "a" is autorepeating: + + press(key_b); + + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + + // hold "a" for autorepeat delay + keyscan_delay(ASDF_AUTOREPEAT_TIME_MS); + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + // empty the buffer to make room for 'B' + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + } + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + +// Pressing and holding 'A' then holding 'B' with repeat key held repeats 'A' then 'B' +void repeating_with_a_then_adding_b_repeats_a_then_repeats_b(void) +{ + press(ACTION_REPEAT); + press(key_a); + + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + // empty the buffer to make room for 'B' + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_next_code()); + } + + // now press "b" while "a" is autorepeating: + + press(key_b); + + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + + // hold "a" for NUM_REPEATS repeat cycles: + keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS); + + // empty the buffer to make room for 'B' + for (int i = 0; i < NUM_REPEATS; i++) { + TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_next_code()); + } + + // and verify there are no more codes in buffer: + TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_next_code()); +} + + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(pressing_a_gives_nothing_before_debounce); + RUN_TEST(pressing_a_gives_a); + RUN_TEST(pressing_shift_a_gives_shifted_a); + RUN_TEST(pressing_caps_a_gives_caps_a); + RUN_TEST(pressing_ctrl_a_gives_ctrl_a); + RUN_TEST(pressing_rept_a_repeats_a); + RUN_TEST(pressing_shift_rept_a_repeats_shifted_a); + RUN_TEST(pressing_caps_rept_a_repeats_caps_a); + RUN_TEST(holding_a_autorepeats_a); + RUN_TEST(holding_a_autorepeats_slow_then_fast); + RUN_TEST(pressing_a_then_b_before_debounce_gives_a_then_b); + RUN_TEST(test_key_sequence_nkro); + RUN_TEST(test_key_sequence_nkro_simultaneous_debounce); + RUN_TEST(holding_a_briefly_then_holding_b_gives_a_and_repeats_b); + RUN_TEST(holding_a_then_holding_b_autorepeats_a_then_autorepeats_b); + RUN_TEST(repeating_with_a_then_adding_b_repeats_a_then_repeats_b); + + + + return UNITY_END(); +}