diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega2560.h b/firmware/asdf/src/Arch/asdf_arch_atmega2560.h index 78859d9..19ce63d 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega2560.h +++ b/firmware/asdf/src/Arch/asdf_arch_atmega2560.h @@ -342,6 +342,13 @@ // For 1 ms tick, (16000000 / 64(prescale)) / 1000(usec) - 1 = 249 #define TICK_COUNT 249 +// Default key matrix row scanner +#define ASDF_ARCH_DEFAULT_SCANNER asdf_arch_read_row + +// Default keyboard output +#define ASDF_ARCH_DEFAULT_OUTPUT asdf_arch_send_code + + // PROCEDURE: asdf_arch_null_output // INPUTS: (uint8_t) value - ignored // OUTPUTS: none diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega328p.h b/firmware/asdf/src/Arch/asdf_arch_atmega328p.h index d38ba48..fe61051 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega328p.h +++ b/firmware/asdf/src/Arch/asdf_arch_atmega328p.h @@ -248,6 +248,13 @@ // For 1 ms tick, (8000000 / 64(prescale)) / 1000(usec) - 1 = 124 #define TICK_COUNT 124 + +// Default key matrix row scanner +#define ASDF_ARCH_DEFAULT_SCANNER asdf_arch_read_row + +// Default keyboard output +#define ASDF_ARCH_DEFAULT_OUTPUT asdf_arch_send_code + // PROCEDURE: asdf_arch_null_output // INPUTS: (uint8_t) value - ignored // OUTPUTS: none diff --git a/firmware/asdf/src/Arch/asdf_arch_test.c b/firmware/asdf/src/Arch/asdf_arch_test.c index 0ac6489..b697d7e 100644 --- a/firmware/asdf/src/Arch/asdf_arch_test.c +++ b/firmware/asdf/src/Arch/asdf_arch_test.c @@ -110,6 +110,68 @@ static uint8_t outputs[ASDF_PHYSICAL_NUM_RESOURCES]; static pulse_state_t pulses[ASDF_PHYSICAL_NUM_RESOURCES]; + +static asdf_keycode_t code_register; +static uint8_t code_sent; + +// PROCEDURE: asdf_arch_send_code +// INPUTS: asdf_keycode_t code +// OUTPUTS: none +// DESCRIPTION: emulates sending a code, by copying code to a register that can +// be tested. +// +// SIDE_EFFECTS: sets code_sent variable and alters code_register +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_arch_send_code(asdf_keycode_t code) +{ + code_register = code; + code_sent = 1; +} + +// PROCEDURE: asdf_arch_get_sent_code +// INPUTS: none +// OUTPUTS: returns type (asdf_keycode_t) in register and zeros the register. +// DESCRIPTION: faciliates test of sending a code, by reporting contents of the +// "sent register". Resets code_sent variable. +// +// SIDE_EFFECTS: alters code_sent variable +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +asdf_keycode_t asdf_arch_get_sent_code(void) +{ + code_sent = 0; + return code_register; +} + +// PROCEDURE: asdf_arch_was_code_sent +// INPUTS: none +// OUTPUTS: returns TRUE if a code was sent, FALSE otherwise. +// DESCRIPTION: returns status of code_sent variable. +// +// SIDE_EFFECTS: sets code_sent variable and alters code_register +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +uint8_t asdf_arch_was_code_sent(void){ + return code_sent; +} + + // PROCEDURE: pulse_detect // INPUTS: (pulse_state_t) current_state // (pulse_event_t) event - current input to the state machine @@ -521,6 +583,9 @@ void asdf_arch_init(void) outputs[i] = 0; pulses[i] = PD_ST_INITIAL_STATE; } + + // initially, no keycodes have been sent via asdf_arch_send_code: + code_sent = 0; } diff --git a/firmware/asdf/src/Arch/asdf_arch_test.h b/firmware/asdf/src/Arch/asdf_arch_test.h index 6f1eaab..5f4d824 100644 --- a/firmware/asdf/src/Arch/asdf_arch_test.h +++ b/firmware/asdf/src/Arch/asdf_arch_test.h @@ -26,49 +26,8 @@ #if !defined (ASDF_ARCH_H) #define ASDF_ARCH_H -#include "asdf.h" - -#define FLASH -#define FLASH_READ (a) (*(a)) -#define FLASH_READ_MATRIX_ELEMENT(mat,row,col) (mat)[(row)][(col)] - -// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*- -// -// Unfified Keyboard Project -// ASDF keyboard firmware -// -// asdf_arch.c -// -// This file contains all the architecture dependent code, including register -// setup, I/O, timers, etc. -// -// 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 . - - -// Wiring Information: -// Chip: {Microcontroller type and version} -// -// Example: -// PIN NAME FUNCTION -// 14-19,9,10 PORTB COLUMN inputs (1 bit per column) -// 23-25 PORTC0-2 ROW outputs (row number) -// 27 PORTC4 - - #include +#include "asdf.h" #include "asdf_keymap_defs.h" #include "asdf_config.h" #include "asdf_physical.h" @@ -76,6 +35,7 @@ #include "asdf_arch.h" + typedef enum { PD_ST_INITIAL_STATE = 0, PD_ST_STABLE_LOW = 1, @@ -95,6 +55,12 @@ typedef enum { PD_ST_ERROR_PULSE_FROM_INITIAL_STATE = 15, } pulse_state_t; +#define FLASH +#define FLASH_READ (a) (*(a)) +#define FLASH_READ_MATRIX_ELEMENT(mat,row,col) (mat)[(row)][(col)] +#define ASDF_ARCH_DEFAULT_SCANNER asdf_arch_read_row +#define ASDF_ARCH_DEFAULT_OUTPUT asdf_arch_send_code + // PROCEDURE: asdf_arch_null_output // INPUTS: (uint8_t) value - ignored // OUTPUTS: none @@ -213,6 +179,24 @@ void asdf_arch_pulse_delay_long(void); // the row, with 1=pressed, 0=released. asdf_cols_t asdf_arch_read_row(uint8_t row); +// PROCEDURE: asdf_arch_send_code +// INPUTS: asdf_keycode_t code +// OUTPUTS: none +// DESCRIPTION: emulates sending a code, by copying code to a register that can +// be tested. +void asdf_arch_send_code(asdf_keycode_t); + +// PROCEDURE: asdf_arch_get_sent_code +// INPUTS: none +// OUTPUTS: returns type (asdf_keycode_t) in register and zeros the register. +// DESCRIPTION: faciliates test of sending a code, by reporting contents of the +// "sent register" +asdf_keycode_t asdf_arch_get_sent_code(void); + +// PROCEDURE: asdf_arch_was_code_sent +// INPUTS: none +// OUTPUTS: returns TRUE if a code was sent, FALSE otherwise. +uint8_t asdf_arch_was_code_sent(void); // PROCEDURE: asdf_arch_init // INPUTS: none diff --git a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h index dcd0497..f0c8e0c 100644 --- a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h +++ b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h @@ -42,12 +42,12 @@ #define ASDF_NUM_KEYMAPS \ (ASDF_ASCII_ALL_MAPS_COUNT + ASDF_APPLE2_ALL_MAPS_COUNT + ASDF_SOL_ALL_MAPS_COUNT) -#define ASDF_KEYMAP_DEFS \ +#define ASDF_KEYMAP_DEFS \ { \ ASDF_ASCII_ALL_MAPS, ASDF_APPLE2_ALL_MAPS, ASDF_SOL_ALL_MAPS \ } -#define ASDF_KEYMAP_DECLARATIONS \ +#define ASDF_KEYMAP_DECLARATIONS \ ASDF_ASCII_MAP_DECLARATIONS ASDF_APPLE2_MAP_DECLARATIONS ASDF_SOL_MAP_DECLARATIONS #define ASDF_KEYMAP_INITIALIZERS \ @@ -55,6 +55,14 @@ ASDF_ASCII_KEYMAP_INITIALIZER, ASDF_APPLE2_KEYMAP_INITIALIZER, ASDF_SOL_KEYMAP_INITIALIZER \ } +#define ASDF_KEYMAP_HOOK_INITIALIZERS \ + { \ + ASDF_ASCII_KEYMAP_HOOK_INITIALIZER, ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER, \ + ASDF_SOL_KEYMAP_HOOK_INITIALIZER \ + } + +typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; + typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; diff --git a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h index fa6fe74..1ee4747 100644 --- a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h +++ b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h @@ -30,6 +30,7 @@ #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" @@ -41,16 +42,26 @@ #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_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_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) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h index d6d4c07..b2695ea 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h @@ -109,7 +109,15 @@ #define ASDF_APPLE2_KEYMAP_INITIALIZER ASDF_APPLE2_PLAIN_KEYMAP_INITIALIZER, ASDF_APPLE2_CAPS_KEYMAP_INITIALIZER -// Key Matrix for combination of ASCII controller (ATMega328P version) and Classic ASCII matrix +// Structure to initialize hooks. No hook functions are needed for APPLE2 keyboard. +#define ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER_LENGTH 0 +#define ASDF_APPLE2_PLAIN_KEYMAP_HOOK_INITIALIZER {} +#define ASDF_APPLE2_CAPS_KEYMAP_HOOK_INITIALIZER {} +#define ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER ASDF_APPLE2_PLAIN_KEYMAP_HOOK_INITIALIZER, ASDF_APPLE2_CAPS_KEYMAP_HOOK_INITIALIZER + + + +// Key Matrix for combination of ASCII controller and Classic ASCII matrix // // Col-> 0 1 2 3 4 5 6 7 // Row 0 POWER R-Shift L-Shift (no key) ESC TAB CTRL \(backslash) @@ -279,6 +287,11 @@ #define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_APPLE2_KEYMAP_INITIALIZER_LENGTH #endif +#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) || (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH +#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER_LENGTH +#endif + #endif /* !defined (ASDF_KEYMAP_DEFS_APPLE2_H) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h index cc8af28..f1c172e 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h @@ -103,7 +103,13 @@ #define ASDF_ASCII_KEYMAP_INITIALIZER ASDF_ASCII_PLAIN_KEYMAP_INITIALIZER, ASDF_ASCII_CAPS_KEYMAP_INITIALIZER -// Key Matrix for combination of ASCII controller (ATMega328P version) and Classic ASCII matrix +// Structure to initialize hooks. No hook functions are needed for ASCII keyboard. +#define ASDF_ASCII_KEYMAP_HOOK_INITIALIZER_LENGTH 0 +#define ASDF_ASCII_PLAIN_KEYMAP_HOOK_INITIALIZER {} +#define ASDF_ASCII_CAPS_KEYMAP_HOOK_INITIALIZER {} +#define ASDF_ASCII_KEYMAP_HOOK_INITIALIZER ASDF_ASCII_PLAIN_KEYMAP_HOOK_INITIALIZER, ASDF_ASCII_CAPS_KEYMAP_HOOK_INITIALIZER + +// Key Matrix for combination of ASCII controller and Classic ASCII matrix // // Col-> 0 1 2 3 4 5 6 7 // Row 0 POWER R-Shift L-Shift (no key) ESC TAB CTRL \(backslash) @@ -254,6 +260,11 @@ #define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_ASCII_KEYMAP_INITIALIZER_LENGTH #endif +#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) || (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_ASCII_KEYMAP_HOOK_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH +#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_ASCII_KEYMAP_HOOK_INITIALIZER_LENGTH +#endif + #endif /* !defined (ASDF_KEYMAP_DEFS_ASCII_H) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_sol.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_sol.h index 6309a8a..57a01c5 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_sol.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_sol.h @@ -84,7 +84,7 @@ // The weird C preprocessor expansion behavior requires one dereference for each // expansion. -#define SOL_KBD_VIRTUAL_SUB1(SOL_VDEVICE) ACTION_ ## SOL_VDEVICE +#define SOL_KBD_VIRTUAL_SUB1(SOL_VDEVICE) ACTION_##SOL_VDEVICE #define SOL_KBD_VIRTUAL_SUB(SOL_VDEVICE) SOL_KBD_VIRTUAL_SUB1(SOL_VDEVICE) #define SOL_KBD_LOCAL_ACTION SOL_KBD_VIRTUAL_SUB(SOL_KBD_VLOCAL) @@ -137,6 +137,18 @@ .initial_value = SOL_KBD_TTL_HIGH }, \ } +// function hooks for the SOL keyboard. At Setup, activate CAPSLOCK to emulate +// original keyboard. +#define ASDF_SOL_KEYMAP_HOOK_INITIALIZER_LENGTH 1 +#define ASDF_SOL_KEYMAP_HOOK_INITIALIZER \ + { \ + { \ + .hook_id = ASDF_HOOK_KEYMAP_SETUP, \ + .hook_func = asdf_modifier_capslock_activate, \ + }, \ + } + + #define DIP_SWITCH_ROW 15 #define ASDF_SOL_DIP_SWITCHES \ @@ -283,6 +295,12 @@ #define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_SOL_KEYMAP_INITIALIZER_LENGTH #endif +#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) \ + || (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_SOL_KEYMAP_HOOK_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH +#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_SOL_KEYMAP_HOOK_INITIALIZER_LENGTH +#endif + #endif /* !defined (ASDF_KEYMAP_DEFS_SOL20_H) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h index 4f88072..35598dd 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h @@ -63,10 +63,10 @@ { 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, 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', \ + /**/ { 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 \ @@ -77,10 +77,10 @@ { 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, 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', \ + /**/ { 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 \ @@ -92,10 +92,10 @@ { 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, '>', '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', '<' }, \ + { 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, '!' }, \ @@ -109,14 +109,14 @@ 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_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_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, \ @@ -158,31 +158,31 @@ { \ /* Single assignment */ \ .virtual_device = VOUT1, \ - .physical_device = PHYSICAL_OUT1, \ + .physical_device = PHYSICAL_OUT1, \ .function = V_NOFUNC, \ .initial_value = 0, \ }, \ { \ /* single toggle */ \ .virtual_device = VOUT2, \ - .physical_device = PHYSICAL_OUT2, \ + .physical_device = PHYSICAL_OUT2, \ .function = V_TOGGLE, \ .initial_value = 0, \ }, \ { \ /* single pulse */ \ .virtual_device = VOUT3, \ - .physical_device = PHYSICAL_OUT3, \ - .function = V_PULSE_SHORT, \ + .physical_device = PHYSICAL_OUT3, \ + .function = V_PULSE_SHORT, \ .initial_value = 0, \ }, \ { /* first of double assignment attempt */ \ .virtual_device = VOUT4, \ - .physical_device = PHYSICAL_LED1, \ + .physical_device = PHYSICAL_LED1, \ .initial_value = 0 \ }, \ { /* second of double assignment attempt */ \ - .virtual_device = VOUT5, .physical_device = PHYSICAL_LED1, .initial_value = 1 \ + .virtual_device = VOUT5, .physical_device = PHYSICAL_LED1, .initial_value = 1 \ } \ } @@ -191,23 +191,54 @@ { \ /* Triple assignment */ \ .virtual_device = VOUT1, \ - .physical_device = PHYSICAL_OUT1, \ + .physical_device = PHYSICAL_OUT1, \ .function = V_TOGGLE, \ .initial_value = 0, \ }, \ { \ .virtual_device = VOUT1, \ - .physical_device = PHYSICAL_OUT2, \ + .physical_device = PHYSICAL_OUT2, \ .function = V_TOGGLE, \ .initial_value = 1, \ }, \ { \ - .virtual_device = VOUT1, .physical_device = PHYSICAL_OUT3, .function = V_TOGGLE, .initial_value = 0, \ + .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 @@ -232,6 +263,12 @@ #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) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h index 2e142d2..a26512d 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h @@ -64,10 +64,10 @@ { 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, 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', \ + /**/ { 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 \ @@ -78,10 +78,10 @@ { 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, 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', \ + /**/ { 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 \ @@ -93,10 +93,10 @@ { 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, '>', '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', '<' }, \ + { 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, '!' }, \ @@ -110,14 +110,14 @@ 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_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_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, \ @@ -147,34 +147,62 @@ #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 = 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 \ + .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 = 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 \ + .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 @@ -199,6 +227,11 @@ #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) */ diff --git a/firmware/asdf/src/Makefile b/firmware/asdf/src/Makefile index 5140620..f53b351 100644 --- a/firmware/asdf/src/Makefile +++ b/firmware/asdf/src/Makefile @@ -1,6 +1,6 @@ # -*- makefile -*- -ARCH ?= atmega2560 +ARCH ?= atmega328p TARGET_KEYMAP ?= production TARGET_MAKEFILE ?= Makefile.$(ARCH) diff --git a/firmware/asdf/src/Makefile.atmega328p b/firmware/asdf/src/Makefile.atmega328p index 048d0d0..9fcbe44 100644 --- a/firmware/asdf/src/Makefile.atmega328p +++ b/firmware/asdf/src/Makefile.atmega328p @@ -69,6 +69,7 @@ MAKEDEPEND = $(CPP) $(DEPFLAGS) $(CPPFLAGS) $< \ SRC_FILES = main.c asdf.c asdf_modifiers.c asdf_repeat.c asdf_keymaps.c SRC_FILES += asdf_buffer.c asdf_arch.c asdf_virtual.c asdf_physical.c +SRC_FILES += asdf_hook.c OBJ_FILES := $(SRC_FILES:.c=.o) DEP_FILES := $(SRC_FILES:%.c=$(DEP_DIR)/%.d) @@ -141,8 +142,9 @@ asdf.o: asdf.c asdf.h asdf_arch.h asdf_keymaps.h asdf_config.h asdf_keymap_defs. asdf_repeat.o: asdf_repeat.c asdf_repeat.h asdf_config.h asdf_buffer.o: asdf_buffer.c asdf.h asdf_config.h asdf_modifiers.o: asdf_modifiers.c asdf_modifiers.h -asdf_virtual.o: asdf_virtual.c asdf_virtual.h asdf_arch.h asdf_physical.h +asdf_virtual.o: asdf_virtual.c asdf_virtual.h asdf_arch.h asdf_physical.h asdf_keymap_defs.h asdf_physical.o: asdf_physical.c asdf_virtual.h asdf_arch.h +asdf_hook.o: asdf_hook.c asdf_hook.h asdf_arch.h asdf_keymap_defs.h tags: $(SRC_FILES) etags $(SRC_FILES) diff --git a/firmware/asdf/src/Makefile.test b/firmware/asdf/src/Makefile.test index dd56cdd..146c66e 100644 --- a/firmware/asdf/src/Makefile.test +++ b/firmware/asdf/src/Makefile.test @@ -55,7 +55,9 @@ TEST2_BUILD = $(BUILD_DIR)/test_$(TEST2) TEST3 = asdf_keymaps TEST3_SRC = $(TEST_DIR)/test_$(TEST3).c -TEST3_DEPS = ./$(TEST3).c $(UNITY_DIR)/unity.c ./asdf_physical.c ./asdf_virtual.c ./asdf_modifiers.c ./asdf_arch.c +TEST3_DEPS = ./$(TEST3).c $(UNITY_DIR)/unity.c ./asdf_physical.c \ + $(TEST_DIR)/test_asdf_lib.c ./asdf_virtual.c \ + ./asdf_hook.c ./asdf_modifiers.c ./asdf_arch.c TEST3_BUILD = $(BUILD_DIR)/test_$(TEST3) TEST4 = asdf_buffer @@ -65,13 +67,16 @@ TEST4_BUILD = $(BUILD_DIR)/test_$(TEST4) TEST5 = asdf_virtual TEST5_SRC = $(TEST_DIR)/test_$(TEST5).c -TEST5_DEPS = ./$(TEST5).c $(UNITY_DIR)/unity.c ./asdf_physical.c ./asdf_modifiers.c ./asdf_arch.c ./asdf_keymaps.c +TEST5_DEPS = ./$(TEST5).c $(UNITY_DIR)/unity.c ./asdf_physical.c ./asdf_modifiers.c \ + ./asdf_hook.c ./asdf_arch.c ./asdf_keymaps.c $(TEST_DIR)/test_asdf_lib.c TEST5_BUILD = $(BUILD_DIR)/test_$(TEST5) -TEST6 = asdf -TEST6_SRC = $(TEST_DIR)/test_$(TEST6).c ./asdf_arch.c ./$(TEST1).c $(TEST2).c $(TEST3).c $(TEST4).c $(TEST5).c ./asdf_physical.c -TEST6_DEPS = ./$(TEST6).c $(UNITY_DIR)/unity.c -TEST6_BUILD = $(BUILD_DIR)/test_$(TEST6) +TEST7 = asdf_hook +TEST7_SRC = $(TEST_DIR)/test_$(TEST7).c ./asdf_arch.c $(TEST_DIR)/test_asdf_lib.c +TEST7_DEPS = ./$(TEST7).c $(UNITY_DIR)/unity.c ./asdf_keymaps.c ./asdf.c \ + ./asdf_modifiers.c ./asdf_buffer.c \ + ./asdf_virtual.c ./asdf_physical.c ./asdf_repeat.c +TEST7_BUILD = $(BUILD_DIR)/test_$(TEST7) .SUFFIXES: .SUFFIXES: .c .o .bin .hex @@ -102,12 +107,13 @@ asdf_keymaps.c: asdf.h asdf_ascii.h asdf_modifiers.h asdf_arch.h asdf_keymaps.h asdf_modifiers.c: asdf_modifiers.h asdf_arch.h asdf_keymap_defs.h asdf_arch.h: asdf_arch.h asdf_virtual.c: asdf_virtual.h asdf_arch.h asdf_keymap_defs.h +asdf_hook.c: asdf_hook.h asdf_keymap_defs.h asdf_arch.h tags: $(SRC_FILES) etags $(SRC_FILES) .PHONY: test -test: test1 test2 test3 test4 test6 test5 +test: test1 test2 test3 test4 test6 test5 test7 .PHONY: test1 test1: $(TEST1_BUILD) @@ -133,6 +139,10 @@ test5: $(TEST5_BUILD) test6: $(TEST6_BUILD) $(TEST6_BUILD) +.PHONY: test7 +test7: $(TEST7_BUILD) + $(TEST7_BUILD) + $(TEST1_BUILD): $(TEST1_SRC) $(TEST1_DEPS) $(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST1_SRC) $(TEST1_DEPS) @@ -152,7 +162,10 @@ $(TEST5_BUILD): $(TEST5_SRC) $(TEST5_DEPS) $(TEST6_BUILD): $(TEST6_SRC) $(TEST6_DEPS) $(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST6_SRC) $(TEST6_DEPS) -TEST_BUILD_FILES += $(TEST1_BUILD) $(TEST2_BUILD) $(TEST3_BUILD) $(TEST4_BUILD) $(TEST5_BUILD) $(TEST6_BUILD) +$(TEST7_BUILD): $(TEST7_SRC) $(TEST7_DEPS) + $(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST7_SRC) $(TEST7_DEPS) + +TEST_BUILD_FILES += $(TEST1_BUILD) $(TEST2_BUILD) $(TEST3_BUILD) $(TEST4_BUILD) $(TEST5_BUILD) $(TEST6_BUILD) $(TEST7_BUILD) CLEAN_FILES += $(TEST_BUILD_FILES) _Arch_* *.o CLEAN_FILES += ~* *\# diff --git a/firmware/asdf/src/asdf.c b/firmware/asdf/src/asdf.c index f81b10f..560f9cd 100644 --- a/firmware/asdf/src/asdf.c +++ b/firmware/asdf/src/asdf.c @@ -41,7 +41,7 @@ #include "asdf_modifiers.h" #include "asdf_buffer.h" #include "asdf_arch.h" - +#include "asdf_hook.h" // The key scanner keeps track of the last stable (debounced) state of each key // in the matrix, one bit per key, 8 bits per row. @@ -380,13 +380,13 @@ void asdf_init(void) asdf_repeat_init(); // initialize the repeat counters asdf_keymaps_init(); // initialize keymaps. This also initializes the modifier // key states. - asdf_buffer_init(); // initialize the buffers + asdf_buffer_init(); // initialize the buffers // reserve a buffer for the ASCII output: asdf_keycode_buffer = asdf_buffer_new(ASDF_KEYCODE_BUFFER_SIZE); // Initialize all the keys to the unpressed state, and initialze the debounce - // counters. + // counters. for (uint8_t row = 0; row < ASDF_NUM_ROWS; row++) { last_stable_key_state[row] = 0; for (uint8_t col = 0; col < ASDF_NUM_COLS; col++) { @@ -496,8 +496,12 @@ static void asdf_handle_key_held_pressed(uint8_t row, uint8_t col) // void asdf_keyscan(void) { + //asdf_hook_get(ASDF_HOOK_EACH_SCAN)(); for (uint8_t row = 0; row < ASDF_NUM_ROWS; row++) { - asdf_cols_t row_key_state = asdf_arch_read_row(row); + //asdf_cols_t (*row_reader)(uint8_t) = + //(asdf_cols_t (*) (uint8_t)) asdf_hook_get(ASDF_HOOK_SCANNER); + //asdf_cols_t row_key_state = (*row_reader)(row); + asdf_cols_t changed = row_key_state ^ last_stable_key_state[row]; // loop over the bits until all changed or pressed keys in the row are handled. diff --git a/firmware/asdf/src/asdf_hook.c b/firmware/asdf/src/asdf_hook.c new file mode 100644 index 0000000..1b4bc59 --- /dev/null +++ b/firmware/asdf/src/asdf_hook.c @@ -0,0 +1,192 @@ +// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*- +// +// Unified Keyboard Project +// ASDF keyboard firmware +// +// asdf_hook.c +// +// This file contains code to allow function "hooks" to be specified in the +// keymap files, so that the keymap can determine the handline of certain +// functions, such as keyboard scanner, output (parallel, serial, USB, etc.), +// keyboard setup (e.g., set capslock or emulate other keypresses), or specify +// functions to be run at every keyscan. The keyboard logic code access the +// functionality via the hooks module rather than directly calling scanning +// functions, etc. +// +// 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 +#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 +// a pointer to the first in the list of functions (if any) assigned to the hook +// ID. +asdf_hook_function_t hook_map[ASDF_NUM_HOOKS]; + +// PROCEDURE: asdf_hook_null_func +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: dummy function, default hook for all but output and scanner. +// +// SIDE EFFECTS: none +// +// NOTES: +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +void asdf_hook_null_func(void) {} + + +// PROCEDURE: asdf_hook_valid_id +// INPUTS: (asdf_hook_id_t) hook_it: ID of the hook to be tested +// OUTPUTS: returns true (1) if the hook ID is valid, false (0) if not valid. +// +// DESCRIPTION: test to see if hooks ID is valid (i.e., within the valid range) +// +// SIDE EFFECTS: none +// +// NOTES: +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static uint8_t asdf_hook_valid_id(asdf_hook_id_t id) +{ + return (id < ASDF_NUM_HOOKS); +} + +// PROCEDURE: asdf_hook_do +// INPUTS: (asdf_hook_id_t) hook_id: The hook for which to execute the attached +// function. +// +// OUTPUTS: none + +// DESCRIPTION: if the hook ID is valid, then execute the function attached to the hook. +// +// SIDE EFFECTS: variable depending on the hooks. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_hook_do(asdf_hook_id_t hook_id) +{ + if (asdf_hook_valid_id(hook_id)) { + hook_map[hook_id](); + } +} + +// PROCEDURE: asdf_hook_get +// INPUTS: (asdf_hook_id_t) hook_id: The hook for which to retrieve the attached +// function. +// OUTPUTS: none + +// DESCRIPTION: if the hook ID is valid, then retrieve the function attached to the hook. +// +// SIDE EFFECTS: variable depending on the hooks. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +asdf_hook_function_t asdf_hook_get(asdf_hook_id_t hook_id) +{ + return asdf_hook_valid_id(hook_id) ? hook_map[hook_id] : asdf_hook_null_func; +} + +// PROCEDURE: asdf_hook_assign +// INPUTS: (asdf_hook_id_t) hook_id: The hook for which to execute attache functions. +// (asdf_hook_function_t) func: function to be attached to the hook. +// +// OUTPUTS: none +// +// DESCRIPTION: If the hook ID is valid, map the function to the hook ID. +// Ignore if not valid. +// +// SIDE EFFECTS: see above. +// +// NOTES: +// +// SCOPE: private +// +// COMPLEXITY: 2 +// +static void asdf_hook_assign(asdf_hook_id_t hook_id, asdf_hook_function_t func) +{ + if (asdf_hook_valid_id(hook_id)) { + hook_map[hook_id] = func; + } +} + +// PROCEDURE: asdf_hook_init +// INPUTS: (asdf_hook_initializer_t *) initializer_list - contains the hook +// initializer list for the selected keymap. +// +// OUTPUTS: none +// +// DESCRIPTION: Initializes function hooks for the selected keymap. If a +// function is assigned to the "KEYMAP_SETUP" hook, then execute the function. +// There is no actual slot where KEYMAP_SETUP functions are stored. +// +// SIDE EFFECTS: see above +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 4 +// +void asdf_hook_init(asdf_hook_initializer_t *const initializer_list) +{ + + // initialize hooks to NULL + for (uint8_t i = 0; i < ASDF_NUM_HOOKS; i++) { + hook_map[i] = asdf_hook_null_func; + } + + hook_map[ASDF_HOOK_SCANNER] = (asdf_hook_function_t) ASDF_ARCH_DEFAULT_SCANNER; + hook_map[ASDF_HOOK_OUTPUT] = (asdf_hook_function_t) ASDF_ARCH_DEFAULT_OUTPUT; + + // run through the keymap specific setup + for (uint8_t i = 0; i < ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH; i++) { + asdf_hook_id_t id = initializer_list[i].hook_id; + + if (ASDF_HOOK_KEYMAP_SETUP == id) { + initializer_list[i].hook_func(); + } + else { + asdf_hook_assign(initializer_list[i].hook_id, initializer_list[i].hook_func); + } + } +} + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/src/asdf_hook.h b/firmware/asdf/src/asdf_hook.h new file mode 100644 index 0000000..da92b93 --- /dev/null +++ b/firmware/asdf/src/asdf_hook.h @@ -0,0 +1,77 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// asdf_hook.h +// +// Definitions and prototypes for configurable function hooks +// +// 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 . +// + +#if !defined(ASDF_HOOKS_H) +#define ASDF_HOOKS_H + +// These are "hooks" output identifiers that can be mapped to the real outputs using +// keymap initializer commands. +typedef enum { + ASDF_HOOK_SCANNER, + ASDF_HOOK_OUTPUT, + ASDF_HOOK_EACH_SCAN, + ASDF_NUM_HOOKS, +} asdf_hook_id_t; + +#define ASDF_HOOK_KEYMAP_SETUP ASDF_NUM_HOOKS + +// Each keymap specifies an array of initializer structs to configure function hooks, +// specifying the hook ID and mapped function. + +typedef void (*asdf_hook_function_t)(void); + +typedef struct { + asdf_hook_id_t hook_id; + asdf_hook_function_t hook_func; +} asdf_hook_initializer_t; + + +// PROCEDURE: asdf_hook_do +// INPUTS: (asdf_hook_id_t) hook_id: The hook for which to execute attache functions. +// OUTPUTS: none +// DESCRIPTION: if the hook ID is valid, then execute the function attached to the hook. +// SIDE EFFECTS: variable depending on the hooks. +void asdf_hook_do(asdf_hook_id_t hook_id); + +// PROCEDURE: asdf_hook_get +// INPUTS: (asdf_hook_id_t) hook_id: The hook for which to retrieve the attached +// function. +// OUTPUTS: none +// DESCRIPTION: if the hook ID is valid, then retrieve the function attached to the hook. +// SIDE EFFECTS: none +asdf_hook_function_t asdf_hook_get(asdf_hook_id_t hook_id); + +// PROCEDURE: asdf_hook_init +// INPUTS: (asdf_hook_initializer_t *) initializer_list - contains the hook +// initializer list for the selected keymap. +// OUTPUTS: none +// DESCRIPTION: Initializes function hooks for the selected keymap. If a +// function is assigned to the "KEYMAP_SETUP" hook, then execute the function. +// There is no actual slot where KEYMAP_SETUP functions are stored. +void asdf_hook_init(asdf_hook_initializer_t *const initializer_list); + +#endif /* !defined (ASDF_HOOKS_H) */ + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/src/asdf_keymaps.c b/firmware/asdf/src/asdf_keymaps.c index d6368b3..a6b1f5e 100644 --- a/firmware/asdf/src/asdf_keymaps.c +++ b/firmware/asdf/src/asdf_keymaps.c @@ -25,6 +25,7 @@ #include "asdf_arch.h" #include "asdf_physical.h" #include "asdf_virtual.h" +#include "asdf_hook.h" #include "asdf_keymaps.h" #include "asdf_keymap_defs.h" @@ -50,14 +51,20 @@ static keycode_matrix_t const *keymap_matrix[ASDF_NUM_KEYMAPS][ASDF_MOD_NUM_MODI // Each keymap (representing a keyboard configuration) has an associated set of -// keyboard initializers that set up the I/O and LED lines for the keyboard, and -// other configuration unique to the keyboard defined by the map. This builds -// the keymap initializer array from the initializer definitions in the keymap -// definitino files. +// 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; +// 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; + // Index of the currently active keymap, initialized to zero in the init // routine. static uint8_t keymap_index; @@ -86,6 +93,7 @@ void asdf_keymaps_select_keymap(uint8_t index) if (index < ASDF_NUM_KEYMAPS) { keymap_index = index; asdf_virtual_init((asdf_virtual_initializer_t *const) keymap_initializer_list[keymap_index]); + asdf_hook_init((asdf_hook_initializer_t *const) keymap_hook_initializer_list[keymap_index]); asdf_modifiers_init(); } } diff --git a/firmware/asdf/src/asdf_physical.c b/firmware/asdf/src/asdf_physical.c index ec557b1..52c7d1e 100644 --- a/firmware/asdf/src/asdf_physical.c +++ b/firmware/asdf/src/asdf_physical.c @@ -204,7 +204,7 @@ asdf_physical_dev_t asdf_physical_next_device(asdf_physical_dev_t device) } // PROCEDURE: asdf_physical_allocate - +// // INPUTS: (asdf_physical_out_t) physical_out - the desired physical resource to allocate. // (asdf_physical_out_t) tail - the list of physical resources to tack on // to the requested resource, if available. diff --git a/firmware/asdf/src/main.c b/firmware/asdf/src/main.c index da28aa4..4369e9e 100644 --- a/firmware/asdf/src/main.c +++ b/firmware/asdf/src/main.c @@ -26,6 +26,7 @@ #include "asdf.h" #include "asdf_arch.h" #include "asdf_buffer.h" +#include "asdf_hook.h" // PROCEDURE: main // INPUTS: none @@ -72,8 +73,10 @@ int main(void) if (code != ASDF_INVALID_CODE) { asdf_arch_send_code(code); + // void (*output_function)(asdf_keycode_t) = + // (void (*)(asdf_keycode_t)) asdf_hook_get(ASDF_HOOK_OUTPUT); + //(*output_function)(code); } - asdf_keyscan(); } } diff --git a/firmware/asdf/test/test_asdf_hook.c b/firmware/asdf/test/test_asdf_hook.c new file mode 100644 index 0000000..56b822c --- /dev/null +++ b/firmware/asdf/test/test_asdf_hook.c @@ -0,0 +1,111 @@ +#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" +#include "asdf_hook.h" +#include "test_asdf_lib.h" + +//ASDF_TEST_DECLARATIONS; + +// emulates arch_read_row function, used mainly to see that the read_row hook is +// getting called. +asdf_cols_t asdf_arch_read_row(uint8_t row) +{ + return (asdf_keycode_t) (row + 1); +} + + +void setUp(void) +{ + test_hook_clear(); + asdf_keymaps_init(); + asdf_init(); +} + +void tearDown(void) {} + + +typedef asdf_cols_t (*scanner_func_t)(uint8_t); + +void test_default_scan_hook_is_default_scanner(void) +{ + scanner_func_t testfunc = (scanner_func_t) asdf_hook_get(ASDF_HOOK_SCANNER); + asdf_cols_t testval = 0; + + // make sure the pointer points to the correct function + TEST_ASSERT_EQUAL_PTR(testfunc, &asdf_arch_read_row); + + // Now try calling the function + testval = (*testfunc)(100); + TEST_ASSERT_EQUAL_INT((int) asdf_arch_read_row(100), (int) testval); +} + +// test_alternate_scan_hook +void test_alternate_scan_hook(void) +{ + asdf_keymaps_select_keymap(ASDF_TEST_ALTERNATE_SCANNER_MAP); + scanner_func_t testfunc = (scanner_func_t) asdf_hook_get(ASDF_HOOK_SCANNER); + asdf_cols_t testval = 0; + + // make sure the pointer points to the correct function + TEST_ASSERT_EQUAL_PTR(testfunc, &test_hook_read_row); + + // Now try calling the function + testval = (*testfunc)(100); + TEST_ASSERT_EQUAL_INT((int) test_hook_read_row(100), (int) testval); +} + +#define NUM_SCAN_TEST_REPS 101 + +void test_each_scan_hook_is_executed_each_scan(void) +{ + + test_hook_clear(); + asdf_keymaps_select_keymap(ASDF_TEST_EACH_SCAN_MAP); + TEST_ASSERT_EQUAL_INT(0, test_hook_readback()); + for (int i = 0; i < NUM_SCAN_TEST_REPS; i++) { + asdf_keyscan(); + } + TEST_ASSERT_EQUAL_INT(NUM_SCAN_TEST_REPS, test_hook_readback()); +} + +// Check that setup hooks are executed immediately +void test_setup_hook_is_executed_immediately(void) +{ + test_hook_clear(); + asdf_keymaps_select_keymap(0); + uint32_t expected = TEST_HOOK_VAL1 | TEST_HOOK_VAL2; + TEST_ASSERT_EQUAL_INT(expected, test_hook_readback()); +} + +// Check that setup hooks are executed properly after selecting nonzero map +void test_setup_hook_is_executed_immediately_when_selecting_nonzero_map(void) +{ + test_hook_clear(); + asdf_keymaps_select_keymap(1); + uint32_t expected = TEST_HOOK_VAL3 | TEST_HOOK_VAL4; + TEST_ASSERT_EQUAL_INT(expected, test_hook_readback()); +} + + + + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_default_scan_hook_is_default_scanner); + RUN_TEST(test_alternate_scan_hook); + RUN_TEST(test_setup_hook_is_executed_immediately); + RUN_TEST(test_setup_hook_is_executed_immediately_when_selecting_nonzero_map); + RUN_TEST(test_each_scan_hook_is_executed_each_scan); + return UNITY_END(); +} diff --git a/firmware/asdf/test/test_asdf_keymaps.c b/firmware/asdf/test/test_asdf_keymaps.c index 6c21371..a6623e2 100644 --- a/firmware/asdf/test/test_asdf_keymaps.c +++ b/firmware/asdf/test/test_asdf_keymaps.c @@ -82,15 +82,6 @@ static coord_t alpha_sample; static coord_t num_sample; static coord_t keymap_tag; -uint32_t max(uint8_t first, uint8_t second) -{ - uint32_t max = first; - if (second > max) { - max = second; - } - return max; -} - coord_t *find_code(asdf_keycode_t code) { uint32_t done = 0; @@ -148,6 +139,12 @@ void complicated_set_keymap(uint8_t mapnum) } } +// dummy function, to resolve reference in keymap hook initialization. +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 diff --git a/firmware/asdf/test/test_asdf_lib.c b/firmware/asdf/test/test_asdf_lib.c new file mode 100644 index 0000000..80d9612 --- /dev/null +++ b/firmware/asdf/test/test_asdf_lib.c @@ -0,0 +1,68 @@ +#include +#include "asdf.h" +#include "asdf_keymaps.h" +#include "asdf_keymap_defs.h" +#include "asdf_arch.h" +#include "asdf_hook.h" +#include "test_asdf_lib.h" + +uint32_t hook_register; + +uint32_t max(uint8_t first, uint8_t second) +{ + uint32_t max = first; + if (second > max) { + max = second; + } + return max; +} + +void test_hook_clear(void) +{ + hook_register = 0; +} + +uint32_t test_hook_readback(void) +{ + return hook_register; +} + +void test_hook_1(void) +{ + hook_register |= TEST_HOOK_VAL1; +} + +void test_hook_2(void) +{ + hook_register |= TEST_HOOK_VAL2; +} + +void test_hook_3(void) +{ + hook_register |= TEST_HOOK_VAL3; +} + +void test_hook_4(void) +{ + hook_register |= TEST_HOOK_VAL4; +} + +void test_hook_5(void) +{ + hook_register |= TEST_HOOK_VAL5; +} + +uint8_t test_hook_read_row(uint8_t val) +{ + return (uint8_t) val+2; +} + +void test_hook_output(uint8_t val) +{ + hook_register = val; +} + +void test_hook_each_scan(void) +{ + hook_register++; +} diff --git a/firmware/asdf/test/test_asdf_lib.h b/firmware/asdf/test/test_asdf_lib.h new file mode 100644 index 0000000..45fb05f --- /dev/null +++ b/firmware/asdf/test/test_asdf_lib.h @@ -0,0 +1,23 @@ +#if !defined(TEST_ASDF_LIB_H) + +#define TEST_HOOK_VAL1 1 +#define TEST_HOOK_VAL2 2 +#define TEST_HOOK_VAL3 4 +#define TEST_HOOK_VAL4 8 +#define TEST_HOOK_VAL5 16 + +uint32_t max(uint8_t first, uint8_t second); +void test_hook_clear(void); +uint32_t test_hook_readback(void); +void test_hook_1(void); +void test_hook_2(void); +void test_hook_3(void); +void test_hook_4(void); +void test_hook_5(void); +void test_hook_each_scan(void); +uint8_t test_hook_read_row(uint8_t val); +void test_hook_output(uint8_t val); + + +#define TEST_ASDF_LIB_H +#endif // if !defined(TEST_ASDF_LIB_H) diff --git a/firmware/asdf/test/test_asdf_virtual.c b/firmware/asdf/test/test_asdf_virtual.c index 58eefd8..d281dc9 100644 --- a/firmware/asdf/test/test_asdf_virtual.c +++ b/firmware/asdf/test/test_asdf_virtual.c @@ -8,18 +8,10 @@ #include "asdf_keymaps.h" #include "asdf_keymap_defs.h" #include "asdf_config.h" +#include "test_asdf_lib.h" -uint32_t max(uint8_t first, uint8_t second) -{ - uint32_t max = first; - if (second > max) { - max = second; - } - return max; -} - void setUp(void) { asdf_arch_init(); @@ -28,6 +20,11 @@ void setUp(void) void tearDown(void) {} +// needed for keymap. +asdf_cols_t asdf_arch_read_row(uint8_t row) +{ + return (asdf_cols_t) row; +} // check to see that the longest keymap initializer sequence initia is detected. void test_inizializer_length_is_max_length(void)