(Development branch) Added in code to implement fuction hooks

This commit is contained in:
Dave 2020-05-01 16:39:21 -05:00
parent 3d8438bede
commit 4d8bc2a9be
25 changed files with 815 additions and 126 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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) */
//-------|---------|---------+---------+---------+---------+---------+---------+

View File

@ -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) */
//-------|---------|---------+---------+---------+---------+---------+---------+

View File

@ -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) */
//-------|---------|---------+---------+---------+---------+---------+---------+

View File

@ -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) */
//-------|---------|---------+---------+---------+---------+---------+---------+

View File

@ -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) */
//-------|---------|---------+---------+---------+---------+---------+---------+

View File

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

View File

@ -1,6 +1,6 @@
# -*- makefile -*-
ARCH ?= atmega2560
ARCH ?= atmega328p
TARGET_KEYMAP ?= production
TARGET_MAKEFILE ?= Makefile.$(ARCH)

View File

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

View File

@ -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 += ~* *\#

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,111 @@
#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"
#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();
}

View File

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

View File

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

View File

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

View File

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