Changes for virtual LED and output mapping.

Rough first cut, have not yet tried to compile or test.
This commit is contained in:
David Fenyes 2020-03-06 13:24:03 -06:00
parent 63e733c18d
commit cff7f6052a
12 changed files with 957 additions and 273 deletions

View File

@ -203,11 +203,12 @@ static void asdf_arch_init_clock(void)
CLKPR = (CLKPCE | SYSCLK_DIV1);
}
// PROCEDURE: asdf_arch_screen_clear(void)
// PROCEDURE: asdf_arch_init_outputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize Screen Clear to LOW
// DESCRIPTION: Initialize all LED ports as outputs. Values are not set here.
// They are set by the keymap code
//
// SIDE EFFECTS: See DESCRIPTION
//
@ -215,38 +216,206 @@ static void asdf_arch_init_clock(void)
//
// COMPLEXITY: 1
//
static void asdf_arch_init_screen_clear(void)
static void asdf_arch_init_leds(void)
{
if (ASDF_DEFAULT_SCREEN_CLEAR_POLARITY == ASDF_POSITIVE_POLARITY) {
clear_bit(&ASDF_SCREEN_CLEAR_PORT, ASDF_SCREEN_CLEAR_BIT);
} else {
set_bit(&ASDF_SCREEN_CLEAR_PORT, ASDF_SCREEN_CLEAR_BIT);
}
set_bit(&ASDF_SCREEN_CLEAR_DDR, ASDF_SCREEN_CLEAR_BIT);
set_bit(&ASDF_LED1_DDR, ASDF_LED1_BIT);
set_bit(&ASDF_LED2_DDR, ASDF_LED2_BIT);
set_bit(&ASDF_LED3_DDR, ASDF_LED3_BIT);
}
// PROCEDURE: asdf_arch_init_sys_reset
// INPUTS: none
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Initialize system reset to INACTIVE. Sys Reset emulates an open
// collector output, so the inactive state is high impedance. Configure as an
// input. Set the pin up as an input, and enable the weak pullup. Normally the
// host system should pull the line high. The weak pullup is ~200-300k, at least
// an order of magnitude greater than the typical host pullup value, so should
// not have significant impact on the current, but will ensure the line is high
// if the host omits a pullup.
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
//
// SIDE EFFECTS: See DESCRIPTION
// SIDE EFFECTS: See above.
//
// SCOPE: private
// NOTES: The LED1 port drives the LED directly by pulling the cathode low, so
// clearing the bit turns the LED on.
//
// COMPLEXITY: 1
// SCOPE: public
//
static void asdf_arch_init_sys_reset(void)
// COMPLEXITY: 2
//
void asdf_arch_led1_set(uint8_t value)
{
clear_bit(&ASDF_SYS_RESET_DDR, ASDF_SYS_RESET_BIT); // set as input
set_bit(&ASDF_SYS_RESET_PORT, ASDF_SYS_RESET_BIT); // enable weak pullup
if (value) {
clear_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
} else {
set_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
}
}
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED2 output drives the LED via an inverter buffer, so a high
// output pulls the LED cathode low, lighting the LED.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led2_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
} else {
clear_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
}
}
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED3 output drives the LED via an inverter buffer, so a high
// output pulls the LED cathode low, lighting the LED.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led3_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
} else {
clear_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
}
}
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
} else {
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
// PROCEDURE: asdf_arch_out1_hi_z_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_hi_z_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
} else {
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
}
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES: OUT2 is inverted by the 7404 buffer, so clearing the bit sets the output high. OUT2 cannot be high impedance.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT2_PORT, ASDF_OUT1_BIT);
} else {
set_bit(&ASDF_OUT2_PORT, ASDF_OUT1_BIT);
}
set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
}
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
} else {
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
// PROCEDURE: asdf_arch_out3_hi_z_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_hi_z_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
} else {
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
}
// PROCEDURE: asdf_arch_init_strobe
@ -340,159 +509,50 @@ static void asdf_arch_init_row_outputs(void)
}
// PROCEDURE: asdf_arch_caps_led
// INPUTS: (uint8_t) led_state: nonzero value turns on LED, zero turns off LED
// OUTPUTS: none
//
// DESCRIPTION: Controls the CAPSLOCK LED.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_caps_led(uint8_t led_status)
{
if (led_status) {
set_bit(&ASDF_CAPS_LED_PORT, ASDF_CAPS_LED_BIT);
} else {
clear_bit(&ASDF_CAPS_LED_PORT, ASDF_CAPS_LED_BIT);
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: sets up all the hardware for the keyboard
//
// SIDE EFFECTS: see DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_init(void)
{
// disable interrupts:
cli();
// clear the 1ms timer flag;
tick = 0;
// set up timers for 1 msec intervals
asdf_arch_init_clock();
asdf_arch_tick_timer_init();
// set up ASCII output port
asdf_arch_init_ascii_output();
// initialize keyboard data and strobe to positive polairy
data_polarity = ASDF_DEFAULT_DATA_POLARITY;
strobe_polarity = ASDF_DEFAULT_STROBE_POLARITY;
asdf_arch_init_strobe();
asdf_arch_init_leds();
// set up row output port
asdf_arch_init_row_outputs();
// set up column control lines
asdf_arch_init_column_control();
// enable interrupts:
sei();
}
}
// PROCEDURE: asdf_arch_init_caps_led
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize CAPSLOCK LED to off.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_caps_led(void)
{
asdf_arch_caps_led(0);
set_bit(&ASDF_CAPS_LED_DDR, ASDF_CAPS_LED_BIT);
}
// PROCEDURE: asdf_arch_init_power_led
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize CAPSLOCK LED to off.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_power_led(void)
{
clear_bit(&ASDF_POWER_LED_PORT, ASDF_POWER_LED_BIT);
set_bit(&ASDF_POWER_LED_DDR, ASDF_POWER_LED_BIT);
}
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: sets up all the hardware for the keyboard
//
// SIDE EFFECTS: see DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_init(void)
{
// disable interrupts:
cli();
// clear the 1ms timer flag;
tick = 0;
// set up timers for 1 msec intervals
asdf_arch_init_clock();
asdf_arch_tick_timer_init();
// set up ASCII output port
asdf_arch_init_ascii_output();
// initialize keyboard data and strobe to positive polairy
data_polarity = ASDF_DEFAULT_DATA_POLARITY;
strobe_polarity = ASDF_DEFAULT_STROBE_POLARITY;
asdf_arch_init_strobe();
asdf_arch_init_screen_clear();
asdf_arch_init_sys_reset();
asdf_arch_init_caps_led();
asdf_arch_init_power_led();
// set up row output port
asdf_arch_init_row_outputs();
// set up column control lines
asdf_arch_init_column_control();
// enable interrupts:
sei();
}
// PROCEDURE: asdf_arch_send_screen_clear
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
//
// SIDE EFFECTS: see DESCRIPTION
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_send_screen_clear(void)
{
set_bit(&ASDF_SCREEN_CLEAR_PIN, ASDF_SCREEN_CLEAR_BIT);
_delay_us(ASDF_STROBE_LENGTH_US);
set_bit(&ASDF_SCREEN_CLEAR_PIN, ASDF_SCREEN_CLEAR_BIT);
}
// PROCEDURE: asdf_arch_send_reset
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Pulses the SYS_RESET output. This emulates open collector, so
// PORT is set to LOW also briefly disabling the weak pullup but also preventing
// even a brief conflict on the output, in case the line is pulled low
// elsewhere. Then, DDR is set to output. After the pulse duration, the DDR is
// set back to input, and PORT is set to HIGH to activate the weak pullup.
//
// SIDE EFFECTS: see DESCRIPTION
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_send_reset(void)
{
clear_bit(&ASDF_SYS_RESET_PORT, ASDF_SYS_RESET_BIT);
set_bit(&ASDF_SYS_RESET_DDR, ASDF_SYS_RESET_BIT);
_delay_us(ASDF_STROBE_LENGTH_US);
clear_bit(&ASDF_SYS_RESET_DDR, ASDF_SYS_RESET_BIT);
set_bit(&ASDF_SYS_RESET_PORT, ASDF_SYS_RESET_BIT);
}
// PROCEDURE: asdf_arch_read_row
// INPUTS: (uint8_t) row: the row number to be scanned

View File

@ -213,23 +213,20 @@
#define ASDF_LED3_DDR DDRB
#define ASDF_LED3_BIT 4
#define ASDF_POWER_LED_PORT ASDF_LED1_PORT
#define ASDF_POWER_LED_DDR ASDF_LED1_DDR
#define ASDF_POWER_LED_BIT ASDF_LED1_BIT
#define ASDF_OUT1_PORT PORTC
#define ASDF_OUT1_PIN PINC
#define ASDF_OUT1_DDR DDRC
#define ASDF_OUT1_BIT 5
#define ASDF_CAPS_LED_PORT ASDF_LED3_PORT
#define ASDF_CAPS_LED_DDR ASDF_LED3_DDR
#define ASDF_CAPS_LED_BIT ASDF_LED3_BIT
#define ASDF_OUT2_PORT PORTB
#define ASDF_OUT2_PIN PINB
#define ASDF_OUT2_DDR DDRB
#define ASDF_OUT2_BIT 3
#define ASDF_SCREEN_CLEAR_PORT PORTC
#define ASDF_SCREEN_CLEAR_PIN PINC
#define ASDF_SCREEN_CLEAR_DDR DDRC
#define ASDF_SCREEN_CLEAR_BIT 5
#define ASDF_SYS_RESET_PORT PORTB
#define ASDF_SYS_RESET_PIN PINB
#define ASDF_SYS_RESET_DDR DDRB
#define ASDF_SYS_RESET_BIT 7
#define ASDF_OUT3_PORT PORTB
#define ASDF_OUT3_PIN PINB
#define ASDF_OUT3_DDR DDRB
#define ASDF_OUT3_BIT 7
#define ASDF_STROBE_PORT PORTB
#define ASDF_STROBE_PIN PINB
@ -251,6 +248,53 @@
// For 1 ms tick, (8000000 / 64(prescale)) / 1000(usec) - 1 = 124
#define TICK_COUNT 124
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
void asdf_arch_led1_set(uint8_t value);
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
void asdf_arch_led2_set(uint8_t value);
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
void asdf_arch_led3_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
void asdf_arch_out1_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_hi_z_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out1_hi_z_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
void asdf_arch_out2_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
void asdf_arch_out3_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_hi_z_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out3_hi_z_set(uint8_t value);
// PROCEDURE: asdf_arch_read_row
// INPUTS: (uint8_t) row: the row number to be scanned
@ -265,24 +309,6 @@ asdf_cols_t asdf_arch_read_row(uint8_t row);
// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise
uint8_t asdf_arch_tick(void);
// PROCEDURE: asdf_arch_caps_led
// INPUTS: (uint8_t) led_state: nonzero value turns on LED, zero turns off LED
// OUTPUTS: none
// DESCRIPTION: Controls the CAPSLOCK LED.
void asdf_arch_caps_led(uint8_t led_status);
// PROCEDURE: asdf_arch_send_screen_clear
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
void asdf_arch_send_screen_clear(void);
// PROCEDURE: asdf_arch_send_reset
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
void asdf_arch_send_reset(void);
// PROCEDURE: asdf_arch_send_code
// INPUTS: (keycode_t) code - the code to be output by the keyboard
// OUTPUTS: none

View File

@ -37,11 +37,176 @@
#include <stdint.h>
#include "asdf_keymap_defs.h"
#include "asdf_config.h"
#include "asdf_virtual.h"
#include "asdf_arch.h"
// this is to get rid of "unused variable" warnings.
volatile static uint32_t junk_variable;
static uint8_t outputs[NUM_REAL_OUTPUTS];
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_led1_set(uint8_t value)
{
outputs[VMAP_LED1] = value;
}
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_led2_set(uint8_t value)
{
outputs[VMAP_LED2] = value;
}
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_led3_set(uint8_t value)
{
outputs[VMAP_LED3] = value;
}
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out1_set(uint8_t value)
{
outputs[VMAP_OUT1] = value;
}
// PROCEDURE: asdf_arch_out1_hi_z_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out1_hi_z_set(uint8_t value)
{
outputs[VMAP_OUT1_OC] = value;
}
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_set(uint8_t value)
{
outputs[VMAP_OUT2] = value;
}
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out3_set(uint8_t value)
{
outputs[VMAP_OUT3] = value;
}
// PROCEDURE: asdf_arch_out3_hi_z_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out3_hi_z_set(uint8_t value)
{
outputs[VMAP_OUT3_OC] = value;
}
// PROCEDURE: asdf_arch_check_output
// INPUTS:(asdf_virtual_real_dev_t) device - which device to check
// OUTPUTS: the value of the device setting.
//
// DESCRIPTION: For a given real device, return the current setting (true or false)
//
// SIDE EFFECTS: none
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
uint8_t asdf_arch_check_output(asdf_virtual_real_dev_t device)
{
return outputs[device];
}
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
@ -54,54 +219,11 @@ volatile static uint32_t junk_variable;
//
// COMPLEXITY: 1
//
void asdf_arch_init(void) {}
// PROCEDURE: asdf_arch_send_screen_clear
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
//
// SIDE EFFECTS: see DESCRIPTION
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_send_screen_clear(void) {}
// PROCEDURE: asdf_arch_send_reset
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
//
// SIDE EFFECTS: see DESCRIPTION
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_send_reset(void) {}
// PROCEDURE: asdf_arch_caps_led
// INPUTS: (uint8_t) led_state: nonzero value turns on LED, zero turns off LED
// OUTPUTS: none
//
// DESCRIPTION: Controls the CAPSLOCK LED. Test version is empty.
//
// SIDE EFFECTS: None for test version
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_caps_led(uint8_t led_status) {
junk_variable = led_status;
void asdf_arch_init(void)
{
for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) {
outputs[i] = 0;
}
}

View File

@ -45,6 +45,7 @@
#define ASDF_KEYMAP_DECLARATIONS ASDF_TEST_DECLARATIONS ASDF_TEST2_DECLARATIONS
#define ASDF_KEYMAP_INITIALIZERS { ASDF_TEST_KEYMAP_INITIALIZER , ASDF_TEST2_KEYMAP_INTIALIZER }
typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS];

View File

@ -147,6 +147,15 @@
#define ASDF_TEST_PLAIN_MAP_INDEX ASDF_TEST_BASE + 0
#define ASDF_TEST_CAPS_MAP_INDEX ASDF_TEST_BASE + 1
#define ASDF_TEST_KEYMAP_INITIALIZER_LENGTH 3
#define ASDF_TEST_KEYMAP_INITIALIZER \
{ \
{ .virtual_device = VCAPS_LED, .device = VMAP_LED1, .initial_value = 1 }, \
{ .virtual_device = VOUT1, .device = VMAP_OUT1, .initial_value = 1 }, \
{ .virtual_device = VOUT2, .device = VMAP_OUT3, .initial_value = 1 } \
}
// 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
@ -165,6 +174,10 @@
#define ASDF_NUM_COLS ASDF_TEST_NUM_COLS
#endif
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) || (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST_KEYMAP_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST_KEYMAP_INITIALIZER_LENGTH
#endif
#endif /* !defined (ASDF_KEYMAP_DEFS_TEST_H) */

View File

@ -56,10 +56,10 @@
#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1)
#define ASDF_TEST_MAP_DIP_SWITCHES \
#define ASDF_TEST_MAP_DIP_SWITCHES \
[ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 }
#define ASDF_TEST2_PLAIN_MAP \
#define ASDF_TEST2_PLAIN_MAP \
{ \
{ PLAIN_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
@ -73,7 +73,7 @@
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST2_CAPS_MAP \
#define ASDF_TEST2_CAPS_MAP \
{ \
{ CAPS_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
@ -87,7 +87,7 @@
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST2_SHIFT_MAP \
#define ASDF_TEST2_SHIFT_MAP \
{ \
\
{ SHIFT_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
@ -104,7 +104,7 @@
}
#define ASDF_TEST2_CTRL_MAP \
#define ASDF_TEST2_CTRL_MAP \
{ \
{ CTRL_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \
@ -126,28 +126,38 @@
}
#define ASDF_TEST2_DECLARATIONS \
static const FLASH keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; \
static const FLASH keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; \
static const FLASH keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; \
#define ASDF_TEST2_DECLARATIONS \
static const FLASH keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; \
static const FLASH keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; \
static const FLASH keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; \
static const FLASH keycode_matrix_t test2_CTRL_matrix = ASDF_TEST2_CTRL_MAP;
#define ASDF_TEST2_MAP_DEFS \
#define ASDF_TEST2_MAP_DEFS \
{ \
&test2_PLAIN_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
&test2_PLAIN_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
}
#define ASDF_TEST2_CAPS_MAP_DEFS \
#define ASDF_TEST2_CAPS_MAP_DEFS \
{ \
&test2_CAPS_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
&test2_CAPS_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
}
#define ASDF_TEST2_KEYMAPS ASDF_TEST2_MAP_DEFS, ASDF_TEST2_CAPS_MAP_DEFS
#define ASDF_TEST2_KEYMAPS ASDF_TEST2_MAP_DEFS, ASDF_TEST2_CAPS_MAP_DEFS
#define ASDF_TEST2_KEYMAPS_COUNT 2
#define ASDF_TEST2_PLAIN_MAP_INDEX (ASDF_TEST2_BASE + 0)
#define ASDF_TEST2_CAPS_MAP_INDEX (ASDF_TEST2_BASE + 1)
#define ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH 4
#define ASDF_TEST2_KEYMAP_INITIALIZER \
{ \
{ .virtual_device = VCAPS_LED, .device = VMAP_LED2, .initial_value = 1 }, \
{ .virtual_device = VOUT1, .device = VMAP_OUT2, .initial_value = 1 }, \
{ .virtual_device = VOUT2, .device = VMAP_OUT3, .initial_value = 0 }, \
{ .virtual_device = VOUT2, .device = NUM_VIRTUAL_OUTPUTS, .initial_value = 0 } \
}
// 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
@ -166,6 +176,12 @@
#define ASDF_NUM_COLS ASDF_TEST2_NUM_COLS
#endif
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH
#endif
#endif /* !defined (ASDF_KEYMAP_DEFS_TEST2_H) */

View File

@ -75,7 +75,7 @@ typedef enum {
ASCII_TILDE = 0x7e,
ASCII_VERT_BAR = 0x7c,
ASCII_DEL = 0x7f
} ascii;
} ascii_defs_t;
#define ASCII_LF ASCII_CTRL_J
#define ASCII_CR ASCII_CTRL_M

View File

@ -23,6 +23,7 @@
#include <stdint.h>
#include "asdf.h"
#include "asdf_arch.h"
#include "asdf_virtual.h"
#include "asdf_keymaps.h"
#include "asdf_keymap_defs.h"
@ -41,8 +42,13 @@ ASDF_KEYMAP_DECLARATIONS;
static keycode_matrix_t const *keymap_matrix[ASDF_NUM_KEYMAPS][ASDF_MOD_NUM_MODIFIERS] =
ASDF_KEYMAP_DEFS;
static const FLASH virtual_initializer_t keymap_initializer_list[ASDF_NUM_KEYMAPS][ASDF_INITIALIZER_LENGTH] =
ASDF_KEYMAP_INITIALIZERS;
static uint8_t keymap_index;
// PROCEDURE: asdf_keymaps_select_keymap
// INPUTS: (uint8_t) index - index of the keymap number to select
// OUTPUTS: none
@ -62,6 +68,7 @@ void asdf_keymaps_select_keymap(uint8_t index)
{
if (index < ASDF_NUM_KEYMAPS) {
keymap_index = index;
asdf_virtual_init(keymap_initializer_list[keymap_index]);
}
}

View File

@ -34,6 +34,49 @@
#define ASDF_KEYMAP_BIT_2 4
#define ASDF_KEYMAP_BIT_3 8
typdef enum {
CLEAR_OUT1,
SET_OUT1,
CLEAR_OUT2,
SET_OUT2,
CLEAR_OUT3,
SET_OUT3,
CLEAR_OC1,
SET_OC1,
CLEAR_OC3,
SET_OC3,
PULSE_OUT1,
PULSE_OUT2,
PULSE_OUT3,
TOGGLE_OUT1,
TOGGLE_OUT2,
TOGGLE_OUT3,
ON_VLED1,
OFF_VLED1,
ON_VLED2,
OFF_VLED2,
ON_VLED3,
OFF_VLED3,
SET_CAPS_LED1,
SET_CAPS_LED2,
SET_CAPS_LED3,
SET_SHIFTLOCK_LED1,
SET_SHIFTLOCK_LED2,
SET_SHIFTLOCK_LED3,
SET_VLED1_LED1,
SET_VLED2_LED1,
SET_VLED3_LED1,
SET_VLED1_LED2,
SET_VLED2_LED2,
SET_VLED3_LED2,
SET_VLED1_LED3,
SET_VLED2_LED3,
SET_VLED3_LED3,
} keymap_init_t
// PROCEDURE: asdf_keymaps_select_keymap
// INPUTS: (uint8_t) index - index of the keymap number to select
// OUTPUTS: none

View File

@ -0,0 +1,276 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_virtual_outputs.c
//
// This file contains code that maps "virtual" LEDs and outputs referenced by
// the code to actual LEDs and outputs in hardware. This keeps keymap-specific
// details out of the architecture-dependent files, and provides a flexible way
// for the keymap definitions to specify the LED and output functions for
// different keymaps or keyboard layouts.
//
// 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 "asdf_virtual.h"
#include "asdf_arch.h"
// For each virtual out, maintain a "shadow" register for the output value. This
// permits machine independent implementations of the toggle and pulse functions
// to be implemented in this module, requiring only a "set" function for each
// virtual output in the architecture-dependent layer. This implementation is
// not as efficient, but the timing is not critical, and the events are so
// infrequent that the benefits of the refactoring far outweigh any performance
// penalty.
typedef struct {
uint8_t shadow;
asdf_virtual_real_dev_t next;
} real_dev_t;
typedef struct {
asdf_virtual_real_dev_t real_device; // Each virtual device points to a linked
// list of any number of real devices.
asdf_virtual_function_t function;
} virtual_dev_t;
static real_dev_t real_device_table[NUM_REAL_OUTPUTS];
// vout_set[] contains the set() function for each real output device.
static const void (*vout_set[])(uint8_t) = {
[VMAP_NO_OUT] = NULL, //
[VMAP_OUT1] = &asdf_arch_out1_set, //
[VMAP_OUT2] = &asdf_arch_out2_set, //
[VMAP_OUT3] = &asdf_arch_out3_set, //
[VMAP_OUT1_OC] = &asdf_arch_out1_hi_z_set, //
[VMAP_OUT2_OC] = &asdf_arch_out2_hi_z_set, //
[VMAP_OUT3_OC] = &asdf_arch_out3_hi_z_set, //
[VMAP_VLED1] = &asdf_arch_led1_set, //
[VMAP_VLED2] = &asdf_arch_led2_set, //
[VMAP_VLED3] = &asdf_arch_led3_set //
};
// virtual_out[] contains all the virtual outputs. An asdf_virtual_output_t
// value is used to identify each element. Each element is a virtual device,
// containing an asdf_virtual_real_dev_t value indicating the real device (if
// any) assigned to the virtual device.
static virtual_dev_t virtual_device_table[NUM_VIRTUAL_OUTPUTS];
// PROCEDURE: asdf_virtual_real_set
// INPUTS: (asdf_virtual_real_dev_t) real_out: which real output to set or clear
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If the real output is valid, set to high if value is true, low
// if false.
//
// SIDE EFFECTS: see above
//
// NOTES: No bounds checking. The caller must ensure a valid device
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_virtual_real_set(asdf_virtual_real_dev_t real_out, uint8_t value)
{
vout_set[real_out](value);
shadow_out[real_out] = value;
}
// PROCEDURE: asdf_virtual_real_assert
// INPUTS: (asdf_virtual_real_dev_t) real_out: which real output to set or clear
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Assert the value of the real output shadow register on the output.
//
// SIDE EFFECTS: see above
//
// NOTES: No bounds checking. Only called from initialization code.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_virtual_real_assert(asdf_virtual_real_dev_t real_out);
{
uint8_t value = real_device_table[real_out].shadow;
vout_set[real_out](value);
}
// PROCEDURE: asdf_virtual_real_toggle
// INPUTS: (asdf_virtual_real_dev_t) real_out: which real output to toggle
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Toggle the value of the real output.
//
// SIDE EFFECTS: see above
//
// NOTES: No bounds checking. Only called from initialization code.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_virtual_real_toggle(asdf_virtual_real_dev_t real_out);
{
uint8_t value = real_device_table[real_out].shadow;
real_device_table[real_out].shadow = !value;
vout_set[real_out](value);
}
// PROCEDURE: asdf_virtual_action
// INPUTS: (asdf_virtual_output_t) virtual_out: which virtual output to modify
// INPUTS: (asdf_virtual_function_t) function: what function to apply to the virtual output
// OUTPUTS: none
//
// DESCRIPTION: for each real output mapped to the virtual output, apply the
// specified function.
//
// SIDE EFFECTS: see above
//
// NOTES: The virtual output points to a linked list of real devices.
//
// SCOPE: public
//
// COMPLEXITY: 7
//
void asdf_virtual_action(asdf_virtual_output_t virtual_out, asdf_virtual_function_t function)
{
real_dev_t device = virtual_device_table[virtual_out].real_device;
while (VMAP_NO_OUT != device) {
switch (function) {
case V_PULSE: {
asdf_virtual_real_toggle(device);
asdf_arch_pulse_delay();
// yes we could omit the next two lines and fall through, but we will
// spend a few bytes of redundant code for the sake of consistency and
// readability.
asdf_virtual_real_toggle(device);
break;
}
case V_TOGGLE: {
asdf_virtual_real_toggle(device);
break;
}
case V_SET_HI: {
asdf_virtual_real_set(device, 1);
break;
}
case V_SET_LO: {
asdf_virtual_real_set(device, 0);
}
case V_NOFUNC:
default: break;
}
device = real_device_table[device].next;
}
}
// PROCEDURE: asdf_virtual_assign
// INPUTS: (asdf_vout_t) virtual_out
// (uint8_t) real_out
// OUTPUTS: none
//
// DESCRIPTION: map the virtual output specified by new_vout to real_out, if
// both arguments are valid. Ignore if not valid.
//
// SIDE EFFECTS: see above.
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 2
//
static void asdf_virtual_assign(asdf_virtual_output_t virtual_out, asdf_virtual_real_dev_t real_out,
asdf_virtual_function_t function, uint8_t initial_value)
{
virtual_device_table[virtual_device].function = function;
// add real device to the list associated with the virtual device:
real_device_table[real_out].next = virtual_device_table[virtual_out].real_device;
virtual_device_table[virtual_out].real_device = real_out;
// The real device shadow value is set here. The shadow values are asserted to
// the outputs only after all the assignments have been performed.
real_device_table[real_out].shadow = value;
}
// PROCEDURE: asdf_virtual_init
// INPUTS: initializers
// OUTPUTS: none
//
// DESCRIPTION: Initializes the LED and output mapping
//
// SIDE EFFECTS: see above
//
// NOTES: The table of real devices is initialized as a linked list of available
// devices.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_virtual_init(virtual_initializer_t *initializer_list)
{
// initialize list of virtual outputs
for (uint8_t i = 0; i < NUM_VIRTUAL_OUTPUTS; i++) {
virtual_device_table[i].function = V_NOFUNC;
virtual_device_table[i].real_device = VMAP_NO_OUT;
}
// initialize the linked list of free devices
for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) {
real_device_table[i].shadow = ASDF_VIRTUAL_OUT_DEFAULT_VALUE;
real_device_table[i].next = i + 1 // initialize pointer to next in table
}
// The last item in the table is left with a bogus next pointer (beyond the
// end of the array) after the above loop. Make the last element point to
// NULL.
real_device_table[NUM_REAL_OUTPUTS - 1].next = VMAP_NO_OUT; // end of list.
// run through the keymap specific setup
for (uint8_t i = 0; //
i < NUM_INITIALIZERS && initializers[i].virtual_device != V_NULL; i++) {
asdf_virtual_assign(intializer_list[i].virtual_device, intializer_list[i].real_device,
initializer_list[i].function, initializer_list[i].initial_value);
}
// Now set all the initial LED and output values
for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) {
asdf_virtual_real_assert((asdf_virtual_real_dev_t) i);
}
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,93 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_virtual.h
//
// Definitions and prototypes for virtual LED and virtual output management.
//
// 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_VIRTUAL_H)
#define ASDF_VIRTUAL_H
// These are "virtual" output identifiers that can be mapped to the real outputs using
// keymap initializer commands.
typedef enum {
V_NULL,
VOUT1,
VOUT2,
VOUT3,
VOUT4,
VOUT5,
VOUT6,
VLED1,
VLED2,
VLED3,
VCAPS_LED,
VSHIFT_LED,
NUM_VIRTUAL_OUTPUTS
} asdf_virtual_output_t;
// The asdf_virtual_real_dev_t enumerates real outputs that can be assigned to
// virtual outputs via the asdf_virtual_assign() function. The name is a bit
// confusing, containing virtual and real. The "virtual" part refers to the
// module and the "real_dev" part attempts to clarify that these are the
// hardware outputs implemented by the architecture-specific module.
typedef enum {
VMAP_NO_OUT = 0,
VMAP_OUT1,
VMAP_OUT1_OC,
VMAP_OUT2,
VMAP_OUT3,
VMAP_OUT3_OC,
VMAP_LED1,
VMAP_LED2,
VMAP_LED3,
NUM_REAL_OUTPUTS
} asdf_virtual_real_dev_t;
typedef enum { V_NOFUNC, V_SET_HI, V_SET_LO, V_PULSE, V_TOGGLE, NUM_VIRTUAL_FUNCTIONS } asdf_virtual_function_t;
// Each keymap specifies an array of initializer structs to configure virtual
// devices, specifying the mapped real device and initial value.
typedef struct {
asdf_virtual_output_t virtual_device;
asdf_virtual_real_dev_t real_device;
asdf_virtual_function_t function;
uint8_t initial_value;
} virtual_initializer_t;
// PROCEDURE: asdf_virtual_action
// INPUTS: (asdf_virtual_output_t) virtual_out: which virtual output to modify
// INPUTS: (asdf_virtual_function_t) function: what function to apply to the virtual output
// OUTPUTS: none
// DESCRIPTION: for each real output mapped to the virtual output, apply the
// specified function.
void asdf_virtual_action(asdf_virtual_output_t virtual_out, asdf_virtual_function_t function);
// PROCEDURE: asdf_virtual_init
// INPUTS: initializers
// OUTPUTS: none
// DESCRIPTION: Initializes the LED and output mapping
void asdf_virtual_init(virtual_initializer_t *initializer_list);
#endif /* !defined (ASDF_VIRTUAL_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -77,11 +77,29 @@ typedef struct {
ASDF_KEYMAP_DECLARATIONS;
// keymap coordinates for special functions
static coord_t alpha_sample;
static coord_t num_sample;
static coord_t keymap_tag;
// Array of zeros which will be initialized to specific values on keymap changes.
static keycode_t init_testvals[ASDF_NUM_INITIALIZERS] = {};
static keycode_t initializers[ASDF_NUM_KEYMAPS][ASDF_NUM_INITIALIZERS] = ASDF_KEYMAP_INITIALIZERS;
void reset_testvals(void)
{
for(int i = 0; i < ASDF_NUM_INITIALIZERS; i++) {
init_testvals[i] = 0;
}
}
uint32_t max(uint8_t first, uint8_t second)
{
uint32_t max = first;
@ -113,6 +131,8 @@ void setUp(void)
{
coord_t *temp;
reset_testvals();
asdf_keymaps_init();
temp = find_code(TESTALPHA);
@ -328,6 +348,13 @@ void dip_switch_invalid_keymap_has_no_effect(void)
}
void keymap_initializers_run_on_startup(void)
{
for (int i = 0; i < NUM_INITIALIZERS; i++)
{
TEST_ASSERT_EQUAL_INT32((int32_t) )
}
}
int main(void)
{