Rebase newmaps branch to master

(WARNING: WIP) Gathered Work-in-progress on alternate keymap defs

Exploratory branch.  Code is messy and untested.
Examining creating a module for each keymap rather than header file.
This commit is contained in:
Dave 2021-01-29 14:30:19 -06:00 committed by Dave
parent 859a5e03d1
commit d6edb15734
28 changed files with 2062 additions and 81 deletions

View File

@ -41,7 +41,6 @@
#include <stdint.h>
#include "asdf_config.h"
#include "asdf_keymap_defs.h"
// Tick is true every 1 ms.
static volatile uint8_t tick = 0;

View File

@ -40,7 +40,6 @@
#include <util/delay.h>
#include <stdint.h>
#include "asdf_config.h"
#include "asdf_keymap_defs.h"
static volatile uint8_t tick = 0;

View File

@ -35,7 +35,6 @@
#include <stdio.h>
#include <stdint.h>
#include "asdf_keymap_defs.h"
#include "asdf_config.h"
#include "asdf_physical.h"
#include "asdf_virtual.h"

View File

@ -28,7 +28,6 @@
#include <stdint.h>
#include "asdf.h"
#include "asdf_keymap_defs.h"
#include "asdf_config.h"
#include "asdf_physical.h"
#include "asdf_virtual.h"

View File

@ -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"

View File

@ -24,6 +24,8 @@
#if !defined(ASDF_H)
#define ASDF_H
#include <stdint.h>
// 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.

View File

@ -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

View File

@ -33,7 +33,6 @@
#include <stddef.h>
#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

View File

@ -21,55 +21,167 @@
// this program. If not, see <https://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stddef.h>
#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);
}

View File

@ -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.

View File

@ -26,7 +26,6 @@
#include <stdint.h>
#include "asdf_physical.h"
#include "asdf_keymap_defs.h"
#include "asdf_config.h"
#include "asdf_arch.h"

View File

@ -25,6 +25,7 @@
#if !defined(ASDF_PHYSICAL_H)
#define ASDF_PHYSICAL_H
#include <stdint.h>
// 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

View File

@ -30,7 +30,6 @@
#include <stdint.h>
#include "asdf_physical.h"
#include "asdf_virtual.h"
#include "asdf_keymap_defs.h"
#include "asdf_config.h"
#include "asdf_arch.h"

View File

@ -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 {

View File

@ -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 <https://www.gnu.org/licenses/>.
// 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.

View File

@ -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 <https://www.gnu.org/licenses/>.
// 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.

View File

@ -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 <https://www.gnu.org/licenses/>.
// 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.

View File

@ -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"

View File

@ -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 <https://www.gnu.org/licenses/>.
//
#include <test_asdf_keymap_defs.h>
#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.

View File

@ -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 <https://www.gnu.org/licenses/>.
// 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.

View File

@ -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);

View File

@ -0,0 +1,68 @@
#include<stdint.h>
#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];
}

View File

@ -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)

View File

@ -1,7 +1,8 @@
#include<stdint.h>
#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"

View File

@ -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"

View File

@ -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 <https://www.gnu.org/licenses/>.
// 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.

View File

@ -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 <https://www.gnu.org/licenses/>.
// 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.

View File

@ -0,0 +1,505 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#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();
}