diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega328p.c b/firmware/asdf/src/Arch/asdf_arch_atmega328p.c index 28504da..6434c63 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega328p.c +++ b/firmware/asdf/src/Arch/asdf_arch_atmega328p.c @@ -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 diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega328p.h b/firmware/asdf/src/Arch/asdf_arch_atmega328p.h index 7c25146..f3448b7 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega328p.h +++ b/firmware/asdf/src/Arch/asdf_arch_atmega328p.h @@ -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 diff --git a/firmware/asdf/src/Arch/asdf_arch_test.c b/firmware/asdf/src/Arch/asdf_arch_test.c index dda8cbc..27ddb5d 100644 --- a/firmware/asdf/src/Arch/asdf_arch_test.c +++ b/firmware/asdf/src/Arch/asdf_arch_test.c @@ -37,11 +37,176 @@ #include #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; + } } 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 112de82..dab40b0 100644 --- a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h +++ b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h @@ -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]; diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h index 8f8830d..04dca7c 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h @@ -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) */ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h index 2213424..155a576 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h @@ -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) */ diff --git a/firmware/asdf/src/asdf_ascii.h b/firmware/asdf/src/asdf_ascii.h index 5b8ed73..49db3f7 100644 --- a/firmware/asdf/src/asdf_ascii.h +++ b/firmware/asdf/src/asdf_ascii.h @@ -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 diff --git a/firmware/asdf/src/asdf_keymaps.c b/firmware/asdf/src/asdf_keymaps.c index f5e4a4e..97c612e 100644 --- a/firmware/asdf/src/asdf_keymaps.c +++ b/firmware/asdf/src/asdf_keymaps.c @@ -23,6 +23,7 @@ #include #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]); } } diff --git a/firmware/asdf/src/asdf_keymaps.h b/firmware/asdf/src/asdf_keymaps.h index be29dfa..d681830 100644 --- a/firmware/asdf/src/asdf_keymaps.h +++ b/firmware/asdf/src/asdf_keymaps.h @@ -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 diff --git a/firmware/asdf/src/asdf_virtual.c b/firmware/asdf/src/asdf_virtual.c new file mode 100644 index 0000000..04ad71a --- /dev/null +++ b/firmware/asdf/src/asdf_virtual.c @@ -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 . +// + + +#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. diff --git a/firmware/asdf/src/asdf_virtual.h b/firmware/asdf/src/asdf_virtual.h new file mode 100644 index 0000000..448d817 --- /dev/null +++ b/firmware/asdf/src/asdf_virtual.h @@ -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 . +// + +#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. diff --git a/firmware/asdf/test/test_asdf_keymaps.c b/firmware/asdf/test/test_asdf_keymaps.c index b2e6d72..243ebe9 100644 --- a/firmware/asdf/test/test_asdf_keymaps.c +++ b/firmware/asdf/test/test_asdf_keymaps.c @@ -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) {