From 1b388bc5918e189de2e771de5fb7381e5ac19658 Mon Sep 17 00:00:00 2001 From: David Fenyes Date: Sun, 8 Mar 2020 14:45:40 -0500 Subject: [PATCH] Add virtual output device module (compiles without warning) * Created test fixture for virtual outputs * Added virtual output configuration to keymap definitions removed special actions_send_reset() and actions_send_screenclear() functions, and replaced with virtual output definitions. * asdf_actions.c is removed from build. * asdf_arch_atmega328p.c: added functions to set/clear each real output * asdf_arch_atmega328p.c: added pulse_delay() function * asdf_arch_test.c: added mock machinery to emulate outputs, test output settings, and detect properly and improperly-formed pulses on the outputs. * asdf_keymaps.c: allocate initialzer array. asdf_keymaps_select_keymap() calls asdf_virtual_init() with initializer list for the keymap to set up the LEDS and outputs every time a new keymap is selected. --- firmware/asdf/src/Arch/asdf_arch_atmega328p.c | 153 +++++++++---- firmware/asdf/src/Arch/asdf_arch_atmega328p.h | 22 ++ firmware/asdf/src/Arch/asdf_arch_test.c | 208 +++++++++++++++++- firmware/asdf/src/Arch/asdf_arch_test.h | 138 ++++++++++-- .../Keymaps/asdf_all_keymap_defs_production.h | 2 + .../src/Keymaps/asdf_all_keymap_defs_test.h | 2 +- .../src/Keymaps/asdf_keymap_defs_apple2.h | 54 ++++- .../asdf/src/Keymaps/asdf_keymap_defs_ascii.h | 52 ++++- .../asdf/src/Keymaps/asdf_keymap_defs_test.h | 25 ++- .../asdf/src/Keymaps/asdf_keymap_defs_test2.h | 14 +- firmware/asdf/src/Makefile.app | 4 +- firmware/asdf/src/Makefile.test | 31 ++- firmware/asdf/src/asdf.c | 46 +++- firmware/asdf/src/asdf.h | 11 +- firmware/asdf/src/asdf_config.h | 6 + firmware/asdf/src/asdf_keymaps.c | 4 +- firmware/asdf/src/asdf_keymaps.h | 4 +- firmware/asdf/src/asdf_modifiers.c | 20 +- firmware/asdf/src/asdf_virtual.c | 64 ++++-- firmware/asdf/src/asdf_virtual.h | 22 +- firmware/asdf/test/test_asdf_keymaps.c | 28 --- firmware/asdf/test/test_asdf_modifiers.c | 83 ------- 22 files changed, 723 insertions(+), 270 deletions(-) diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega328p.c b/firmware/asdf/src/Arch/asdf_arch_atmega328p.c index 6434c63..9b87545 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega328p.c +++ b/firmware/asdf/src/Arch/asdf_arch_atmega328p.c @@ -243,7 +243,8 @@ void asdf_arch_led1_set(uint8_t value) { if (value) { clear_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT); - } else { + } + else { set_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT); } } @@ -267,7 +268,8 @@ void asdf_arch_led2_set(uint8_t value) { if (value) { set_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT); - } else { + } + else { clear_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT); } } @@ -291,7 +293,8 @@ void asdf_arch_led3_set(uint8_t value) { if (value) { set_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT); - } else { + } + else { clear_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT); } } @@ -314,7 +317,8 @@ void asdf_arch_out1_set(uint8_t value) { if (value) { set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT); - } else { + } + else { clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT); } set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT); @@ -339,7 +343,8 @@ 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 { + } + else { clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT); set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT); } @@ -353,7 +358,8 @@ void asdf_arch_out1_hi_z_set(uint8_t value) // // 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. +// NOTES: OUT2 is inverted by the 7404 buffer, so clearing the bit sets the output high. OUT2 +// cannot be high impedance. // // SCOPE: public // @@ -363,12 +369,51 @@ void asdf_arch_out2_set(uint8_t value) { if (value) { clear_bit(&ASDF_OUT2_PORT, ASDF_OUT1_BIT); - } else { + } + else { set_bit(&ASDF_OUT2_PORT, ASDF_OUT1_BIT); } set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT); } +// PROCEDURE: asdf_arch_null_output +// INPUTS: (uint8_t) value - ignored +// OUTPUTS: none +// +// DESCRIPTION: Does nothing. +// +// SIDE EFFECTS: See above. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_null_output(uint8_t value) +{ + (void) value; +} + +// PROCEDURE: asdf_arch_out2_hi_z_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// +// DESCRIPTION: Sets the OUT2 bit to hi-z if value is true, and low if value is false. +// +// SIDE EFFECTS: See above. +// +// NOTES: Not supported for the ATMega-328 ASCII interface. +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_out2_hi_z_set(uint8_t value) +{ + asdf_arch_null_output(value); +} + // PROCEDURE: asdf_arch_out3_set // INPUTS: (uint8_t) value // OUTPUTS: none @@ -387,7 +432,8 @@ void asdf_arch_out3_set(uint8_t value) { if (value) { set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT); - } else { + } + else { clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT); } set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT); @@ -412,7 +458,8 @@ 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 { + } + else { clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT); set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT); } @@ -508,50 +555,68 @@ static void asdf_arch_init_row_outputs(void) ASDF_ROW_DDR |= ASDF_ROW_MASK; } +// PROCEDURE: asdf_arch_pulse_delay +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses. +// +// SIDE EFFECTS: see above. +// +// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_arch_pulse_delay(void) +{ + _delay_us(ASDF_PULSE_DELAY_US); +} - // 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(); +// 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; + // 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 timers for 1 msec intervals + asdf_arch_init_clock(); + asdf_arch_tick_timer_init(); - // set up ASCII output port - asdf_arch_init_ascii_output(); + // 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; + // 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(); + asdf_arch_init_strobe(); + asdf_arch_init_leds(); - // set up row output port - asdf_arch_init_row_outputs(); + // set up row output port + asdf_arch_init_row_outputs(); - // set up column control lines - asdf_arch_init_column_control(); + // set up column control lines + asdf_arch_init_column_control(); - // enable interrupts: - sei(); - } + // enable interrupts: + sei(); +} // PROCEDURE: asdf_arch_read_row diff --git a/firmware/asdf/src/Arch/asdf_arch_atmega328p.h b/firmware/asdf/src/Arch/asdf_arch_atmega328p.h index f3448b7..756f45e 100644 --- a/firmware/asdf/src/Arch/asdf_arch_atmega328p.h +++ b/firmware/asdf/src/Arch/asdf_arch_atmega328p.h @@ -248,6 +248,13 @@ // For 1 ms tick, (8000000 / 64(prescale)) / 1000(usec) - 1 = 124 #define TICK_COUNT 124 +// PROCEDURE: asdf_arch_null_output +// INPUTS: (uint8_t) value - ignored +// OUTPUTS: none +// DESCRIPTION: null/dummy output function +// NOTES: Not supported for the ATMega-328 ASCII interface. +void asdf_arch_null_output(uint8_t value); + // PROCEDURE: asdf_arch_led1_set // INPUTS: (uint8_t) value // OUTPUTS: none @@ -290,6 +297,14 @@ void asdf_arch_out2_set(uint8_t value); // 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_out2_hi_z_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// DESCRIPTION: Sets the OUT2 bit to hi-z if value is true, and low if value is false. +// NOTES: Not supported for the ATMega-328 ASCII interface. +void asdf_arch_out2_hi_z_set(uint8_t value); + + // PROCEDURE: asdf_arch_out3_hi_z_set // INPUTS: (uint8_t) value // OUTPUTS: none @@ -304,6 +319,13 @@ void asdf_arch_out3_hi_z_set(uint8_t value); // pressed within the row, with 1=pressed, 0=released. asdf_cols_t asdf_arch_read_row(uint8_t row); +// PROCEDURE: asdf_arch_pulse_delay +// INPUTS: none +// OUTPUTS: none +// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses. +// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h +void asdf_arch_pulse_delay(void); + // PROCEDURE: asdf_arch_tick // INPUTS: none // OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise diff --git a/firmware/asdf/src/Arch/asdf_arch_test.c b/firmware/asdf/src/Arch/asdf_arch_test.c index 27ddb5d..f2474b9 100644 --- a/firmware/asdf/src/Arch/asdf_arch_test.c +++ b/firmware/asdf/src/Arch/asdf_arch_test.c @@ -39,10 +39,154 @@ #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; +typedef enum { + INITIAL_STATE, + STABLE_LOW, + STABLE_HIGH, + TRANSITION_LOW, + TRANSITION_HIGH, + PULSE_DELAY_LOW, + PULSE_DELAY_HIGH, + PULSE_HIGH_DETECTED, + PULSE_LOW_DETECTED, + NUM_VALID_PULSE_STATES, // error states below this + ERROR_DOUBLE_DELAY, + ERROR_DOUBLE_SET, + ERROR_NO_TRANSITION_BEFORE_DELAY, + ERROR_NO_TRANSITION_AFTER_DELAY, + ERROR_DOUBLE_TRANSITION, // fast pulse without delay + ERROR_DOUBLE_PULSE, +} pulse_state_t; + +typedef enum { SET_HIGH, SET_LOW, PULSE_DELAY, NUM_PULSE_STATE_INPUTS } pulse_state_event_t; + +static pulse_state_t pulse_transition_table[NUM_VALID_PULSE_STATES][NUM_PULSE_STATE_INPUTS] = + { + [STABLE_LOW] = + { + [SET_HIGH] = TRANSITION_HIGH, + [SET_LOW] = ERROR_DOUBLE_SET, + [PULSE_DELAY] = ERROR_NO_TRANSITION_BEFORE_DELAY, + }, + [STABLE_HIGH] = + { + [SET_HIGH] = ERROR_DOUBLE_SET, + [SET_LOW] = TRANSITION_LOW, + [PULSE_DELAY] = ERROR_NO_TRANSITION_BEFORE_DELAY, + }, + [TRANSITION_LOW] = + { + [SET_HIGH] = ERROR_DOUBLE_TRANSITION, + [SET_LOW] = ERROR_DOUBLE_SET, + [PULSE_DELAY] = PULSE_DELAY_LOW, + }, + [TRANSITION_HIGH] = + { + [SET_HIGH] = ERROR_DOUBLE_SET, + [SET_LOW] = ERROR_DOUBLE_TRANSITION, + [PULSE_DELAY] = PULSE_DELAY_HIGH, + }, + [PULSE_DELAY_LOW] = + { + [SET_HIGH] = PULSE_LOW_DETECTED, + [SET_LOW] = ERROR_NO_TRANSITION_AFTER_DELAY, + [PULSE_DELAY] = ERROR_DOUBLE_PULSE, + }, + [PULSE_DELAY_HIGH] = + { + [SET_HIGH] = ERROR_NO_TRANSITION_AFTER_DELAY, + [SET_LOW] = PULSE_HIGH_DETECTED, + [PULSE_DELAY] = ERROR_DOUBLE_PULSE, + }, + [PULSE_HIGH_DETECTED] = + { + [SET_HIGH] = STABLE_HIGH, + [SET_LOW] = STABLE_LOW, + [PULSE_DELAY] = ERROR_NO_TRANSITION_BEFORE_DELAY + }, + [PULSE_LOW_DETECTED] = + { + [SET_HIGH] = STABLE_HIGH, + [SET_LOW] = STABLE_LOW, + [PULSE_DELAY] = ERROR_NO_TRANSITION_BEFORE_DELAY + }, + }; + static uint8_t outputs[NUM_REAL_OUTPUTS]; +static pulse_state_t pulses[NUM_REAL_OUTPUTS]; + +// PROCEDURE: asdf_arch_null_output +// INPUTS: (uint8_t) value - ignored +// OUTPUTS: none +// +// DESCRIPTION: Does nothing. +// +// SIDE EFFECTS: See above. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_null_output(uint8_t value) +{ + (void) value; +} + +// PROCEDURE: pulse_detect +// INPUTS: (pulse_state_t) current_state +// (pulse_event_t) event - current input to the state machine +// OUTPUTS: returns new pulse detector state for the output. +// +// DESCRIPTION: Given an output and a new value for the output, calculate the +// next state of the pulse detector for the output. +// +// SIDE EFFECTS: none. +// +// NOTES: +// +// SCOPE: private +// +// COMPLEXITY: 2 +// +static pulse_state_t pulse_detect(pulse_state_t current_state, pulse_state_event_t event) +{ + pulse_state_t next_state = current_state; + + // advance state if current state is valid (not an error state) + if (current_state < NUM_VALID_PULSE_STATES) { + next_state = pulse_transition_table[current_state][event]; + } + return next_state; +} + + +// PROCEDURE: set_output +// INPUTS: (asdf_virtual_real_dev_t) output_dev - the output to set +// (uint8_t) value - value to assert on the output +// OUTPUTS: none +// +// DESCRIPTION: Given an output and a new value for the output, set the output +// and advance the pulse detector state for the output. +// +// SIDE EFFECTS: see above. +// +// NOTES: +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void set_output(asdf_virtual_real_dev_t output_dev, uint8_t value) +{ + pulse_state_event_t pulse_event = value ? SET_HIGH : SET_LOW; + + outputs[output_dev] = value; + pulses[output_dev] = pulse_detect(pulses[output_dev], pulse_event); +} + // PROCEDURE: asdf_arch_led1_set // INPUTS: (uint8_t) value @@ -58,7 +202,7 @@ static uint8_t outputs[NUM_REAL_OUTPUTS]; // void asdf_arch_led1_set(uint8_t value) { - outputs[VMAP_LED1] = value; + set_output(VMAP_LED1, value); } // PROCEDURE: asdf_arch_led2_set @@ -75,7 +219,7 @@ void asdf_arch_led1_set(uint8_t value) // void asdf_arch_led2_set(uint8_t value) { - outputs[VMAP_LED2] = value; + set_output(VMAP_LED2, value); } // PROCEDURE: asdf_arch_led3_set @@ -92,7 +236,7 @@ void asdf_arch_led2_set(uint8_t value) // void asdf_arch_led3_set(uint8_t value) { - outputs[VMAP_LED3] = value; + set_output(VMAP_LED3, value); } // PROCEDURE: asdf_arch_out1_set @@ -111,7 +255,7 @@ void asdf_arch_led3_set(uint8_t value) // void asdf_arch_out1_set(uint8_t value) { - outputs[VMAP_OUT1] = value; + set_output(VMAP_OUT1, value); } // PROCEDURE: asdf_arch_out1_hi_z_set @@ -130,7 +274,7 @@ void asdf_arch_out1_set(uint8_t value) // void asdf_arch_out1_hi_z_set(uint8_t value) { - outputs[VMAP_OUT1_OC] = value; + set_output(VMAP_OUT1_OC, value); } // PROCEDURE: asdf_arch_out2_set @@ -147,7 +291,27 @@ void asdf_arch_out1_hi_z_set(uint8_t value) // void asdf_arch_out2_set(uint8_t value) { - outputs[VMAP_OUT2] = value; + set_output(VMAP_OUT2, value); +} + + +// PROCEDURE: asdf_arch_out2_hi_z_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// +// DESCRIPTION: Sets the OUT2 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_out2_hi_z_set(uint8_t value) +{ + set_output(VMAP_OUT2_OC, value); } // PROCEDURE: asdf_arch_out3_set @@ -166,9 +330,10 @@ void asdf_arch_out2_set(uint8_t value) // void asdf_arch_out3_set(uint8_t value) { - outputs[VMAP_OUT3] = value; + set_output(VMAP_OUT3, value); } + // PROCEDURE: asdf_arch_out3_hi_z_set // INPUTS: (uint8_t) value // OUTPUTS: none @@ -185,7 +350,7 @@ void asdf_arch_out3_set(uint8_t value) // void asdf_arch_out3_hi_z_set(uint8_t value) { - outputs[VMAP_OUT3_OC] = value; + set_output(VMAP_OUT3_OC, value); } // PROCEDURE: asdf_arch_check_output @@ -207,6 +372,28 @@ uint8_t asdf_arch_check_output(asdf_virtual_real_dev_t device) return outputs[device]; } +// PROCEDURE: asdf_arch_pulse_delay +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Emulates a delay by advancing the pulse detector state machine +// for each output. +// +// SIDE EFFECTS: see above. +// +// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_arch_pulse_delay(void) +{ + for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) { + pulses[i] = pulse_detect(pulses[i], PULSE_DELAY); + } +} + // PROCEDURE: asdf_arch_init // INPUTS: none // OUTPUTS: none @@ -223,6 +410,7 @@ void asdf_arch_init(void) { for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) { outputs[i] = 0; + pulses[i] = INITIAL_STATE; } } diff --git a/firmware/asdf/src/Arch/asdf_arch_test.h b/firmware/asdf/src/Arch/asdf_arch_test.h index 0571559..5a25cc8 100644 --- a/firmware/asdf/src/Arch/asdf_arch_test.h +++ b/firmware/asdf/src/Arch/asdf_arch_test.h @@ -32,25 +32,123 @@ #define FLASH_READ (a) (*(a)) #define FLASH_READ_MATRIX_ELEMENT(mat,row,col) (mat)[(row)][(col)] -// PROCEDURE: asdf_arch_read_row -// INPUTS: (uint8_t) row: the row number to be scanned -// OUTPUTS: returns a word containing the active (pressed) columns -// DESCRIPTION: Outputs the argument to the ROW port, then reads the column port -// and returns the value. The value is a binary representation of the keys -// pressed within the row, with 1=pressed, 0=released. -asdf_cols_t asdf_arch_read_row(uint8_t row); +// -*- 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 . -// PROCEDURE: asdf_arch_send_screen_clear + +// Wiring Information: +// Chip: {Microcontroller type and version} +// +// Example: +// PIN NAME FUNCTION +// 14-19,9,10 PORTB COLUMN inputs (1 bit per column) +// 23-25 PORTC0-2 ROW outputs (row number) +// 27 PORTC4 + + +#include +#include "asdf_keymap_defs.h" +#include "asdf_config.h" +#include "asdf_virtual.h" +#include "asdf_arch.h" + +static uint8_t outputs[NUM_REAL_OUTPUTS]; + +// PROCEDURE: asdf_arch_null_output +// INPUTS: (uint8_t) value - ignored +// OUTPUTS: none +// DESCRIPTION: Does nothing. +void asdf_arch_null_output(uint8_t value); + +// 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_out2_hi_z_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// DESCRIPTION: Sets the OUT2 bit to hi-z if value is true, and low if value is false. +void asdf_arch_out2_hi_z_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_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) +uint8_t asdf_arch_check_output(asdf_virtual_real_dev_t device); + +// PROCEDURE: asdf_arch_pulse_delay // INPUTS: none // OUTPUTS: none -// DESCRIPTION: Toggles the SCREEN_CLEAR output. -void asdf_arch_send_screen_clear(void); +// DESCRIPTION: Emulates a delay by advancing the pulse detector state machine +// for each output. +void asdf_arch_pulse_delay(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_init // INPUTS: none @@ -58,11 +156,11 @@ void asdf_arch_send_reset(void); // DESCRIPTION: sets up all the hardware for the keyboard void asdf_arch_init(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. -void asdf_arch_caps_led(uint8_t led_status); + + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. +// #endif // !defined (ASDF_ARCH_H) diff --git a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h index 57977f7..703082b 100644 --- a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h +++ b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_production.h @@ -40,6 +40,8 @@ #define ASDF_KEYMAP_DEFS { ASDF_ASCII_ALL_MAPS , ASDF_APPLE2_ALL_MAPS } #define ASDF_KEYMAP_DECLARATIONS ASDF_ASCII_MAP_DECLARATIONS ASDF_APPLE2_MAP_DECLARATIONS +#define ASDF_KEYMAP_INITIALIZERS { ASDF_ASCII_KEYMAP_INITIALIZER , ASDF_APPLE2_KEYMAP_INITIALIZER } + typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; diff --git a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h index dab40b0..fa6fe74 100644 --- a/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h +++ b/firmware/asdf/src/Keymaps/asdf_all_keymap_defs_test.h @@ -45,7 +45,7 @@ #define ASDF_KEYMAP_DECLARATIONS ASDF_TEST_DECLARATIONS ASDF_TEST2_DECLARATIONS -#define ASDF_KEYMAP_INITIALIZERS { ASDF_TEST_KEYMAP_INITIALIZER , ASDF_TEST2_KEYMAP_INTIALIZER } +#define ASDF_KEYMAP_INITIALIZERS { ASDF_TEST_KEYMAP_INITIALIZER , ASDF_TEST2_KEYMAP_INITIALIZER } typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h index 868a606..b091694 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_apple2.h @@ -47,15 +47,38 @@ #define ASDF_APPLE2_NUM_ROWS 16 // DIP switches are row 15. #define ASDF_APPLE2_NUM_COLS 8 -#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_APPLE2_NUM_ROWS) -#undef ASDF_NUM_ROWS -#define ASDF_NUM_ROWS ASDF_APPLE2_NUM_ROWS -#endif +#define ASDF_ASCII_NUM_ROWS 16 // DIP switches are row 15. +#define ASDF_ASCII_NUM_COLS 8 -#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_APPLE2_NUM_COLS) -#undef ASDF_NUM_COLS -#define ASDF_NUM_COLS ASDF_APPLE2_NUM_COLS -#endif +#define VIRTUAL_RESET VOUT1 +#define RESET_OUTPUT VMAP_OUT3_OC +#define RESET_ACTIVE_VALUE 0 + +#define VIRTUAL_CLR_SCR VOUT2 +#define CLR_SCR_OUT VMAP_OUT1 +#define CLR_SCR_ACTIVE_VALUE 1 + +#define VIRTUAL_POWER_LED VLED1 +#define POWER_LED VMAP_LED1 +#define POWER_LED_INIT_VALUE 1 + +#define ASDF_APPLE2_KEYMAP_INITIALIZER_LENGTH 4 +#define ASDF_APPLE2_KEYMAP_INITIALIZER \ + { \ + { .virtual_device = VIRTUAL_POWER_LED, \ + .real_device = POWER_LED, \ + .initial_value = POWER_LED_INIT_VALUE }, \ + { .virtual_device = VCAPS_LED, \ + .real_device = VMAP_LED3 }, \ + { .virtual_device = RESET_OUTPUT, \ + .real_device = VMAP_OUT1, \ + .function = V_PULSE, \ + .initial_value = !CLR_SCR_ACTIVE_VALUE }, \ + { .virtual_device = CLR_SCR_OUT, \ + .real_device = VMAP_OUT3, \ + .function = V_PULSE, \ + .initial_value = !RESET_ACTIVE_VALUE } \ + } // TO ensure consistent DIP switch operation within the keymap, a // ASDF_APPLE2_DIP_SWITCHES macro is defined. Keeping the ACTION_MAPSEL0-3 @@ -187,6 +210,21 @@ #define ASDF_APPLE2_ALL_MAPS_COUNT 2 +#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_APPLE2_NUM_ROWS) +#undef ASDF_NUM_ROWS +#define ASDF_NUM_ROWS ASDF_APPLE2_NUM_ROWS +#endif + +#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_APPLE2_NUM_COLS) +#undef ASDF_NUM_COLS +#define ASDF_NUM_COLS ASDF_APPLE2_NUM_COLS +#endif + +#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) || (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_APPLE2_KEYMAP_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_INITIALIZER_LENGTH +#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_APPLE2_KEYMAP_INITIALIZER_LENGTH +#endif + #endif /* !defined (ASDF_KEYMAP_DEFS_APPLE2_H) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h index 46147e9..b8436ad 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_ascii.h @@ -39,15 +39,36 @@ #define ASDF_ASCII_NUM_ROWS 16 // DIP switches are row 15. #define ASDF_ASCII_NUM_COLS 8 -#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_ASCII_NUM_ROWS) -#undef ASDF_NUM_ROWS -#define ASDF_NUM_ROWS ASDF_ASCII_NUM_ROWS -#endif +#define VIRTUAL_RESET VOUT1 +#define RESET_OUTPUT VMAP_OUT3_OC +#define RESET_ACTIVE_VALUE 0 + +#define VIRTUAL_CLR_SCR VOUT2 +#define CLR_SCR_OUT VMAP_OUT1 +#define CLR_SCR_ACTIVE_VALUE 1 + +#define VIRTUAL_POWER_LED VLED1 +#define POWER_LED VMAP_LED1 +#define POWER_LED_INIT_VALUE 1 + +#define ASDF_ASCII_KEYMAP_INITIALIZER_LENGTH 4 +#define ASDF_ASCII_KEYMAP_INITIALIZER \ + { \ + { .virtual_device = VIRTUAL_POWER_LED, \ + .real_device = POWER_LED, \ + .initial_value = POWER_LED_INIT_VALUE }, \ + { .virtual_device = VCAPS_LED, \ + .real_device = VMAP_LED3 }, \ + { .virtual_device = RESET_OUTPUT, \ + .real_device = VMAP_OUT1, \ + .function = V_PULSE, \ + .initial_value = !CLR_SCR_ACTIVE_VALUE }, \ + { .virtual_device = CLR_SCR_OUT, \ + .real_device = VMAP_OUT3, \ + .function = V_PULSE, \ + .initial_value = !RESET_ACTIVE_VALUE } \ + } -#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_ASCII_NUM_COLS) -#undef ASDF_NUM_COLS -#define ASDF_NUM_COLS ASDF_ASCII_NUM_COLS -#endif // TO ensure consistent DIP switch operation within the keymap, a // ASDF_ASCII_DIP_SWITCHES macro is defined. Keeping the ACTION_MAPSEL0-3 @@ -159,6 +180,21 @@ #define ASDF_ASCII_ALL_MAPS_COUNT 2 +#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_ASCII_NUM_ROWS) +#undef ASDF_NUM_ROWS +#define ASDF_NUM_ROWS ASDF_ASCII_NUM_ROWS +#endif + +#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_ASCII_NUM_COLS) +#undef ASDF_NUM_COLS +#define ASDF_NUM_COLS ASDF_ASCII_NUM_COLS +#endif + +#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) || (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_ASCII_KEYMAP_INITIALIZER_LENGTH) +#undef ASDF_KEYMAP_INITIALIZER_LENGTH +#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_ASCII_KEYMAP_INITIALIZER_LENGTH +#endif + #endif /* !defined (ASDF_KEYMAP_DEFS_ASCII_H) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h index 04dca7c..0c7d142 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test.h @@ -148,11 +148,23 @@ #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 } \ +#define ASDF_TEST_KEYMAP_INITIALIZER \ + { \ + { \ + .virtual_device = VCAPS_LED, \ + .real_device = VMAP_LED1, \ + .function = V_NOFUNC, \ + .initial_value = 1, \ + }, \ + { \ + .virtual_device = VOUT1, \ + .real_device = VMAP_OUT1, \ + .function = V_TOGGLE, \ + .initial_value = 1, \ + }, \ + { \ + .virtual_device = VOUT2, .real_device = VMAP_OUT3, .function = V_PULSE, .initial_value = 1, \ + } \ } @@ -174,7 +186,8 @@ #define ASDF_NUM_COLS ASDF_TEST_NUM_COLS #endif -#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) || (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST_KEYMAP_INITIALIZER_LENGTH) +#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 diff --git a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h index 155a576..653a4e3 100644 --- a/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h +++ b/firmware/asdf/src/Keymaps/asdf_keymap_defs_test2.h @@ -149,12 +149,14 @@ #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 } \ +#define ASDF_TEST2_KEYMAP_INITIALIZER \ + { \ + { .virtual_device = VCAPS_LED, .real_device = VMAP_LED2, .initial_value = 1 }, \ + { .virtual_device = VOUT1, .real_device = VMAP_OUT2, .initial_value = 1 }, \ + { .virtual_device = VOUT2, .real_device = VMAP_OUT3, .initial_value = 0 }, \ + { \ + .virtual_device = VOUT2, .real_device = NUM_REAL_OUTPUTS, .initial_value = 0 \ + } \ } diff --git a/firmware/asdf/src/Makefile.app b/firmware/asdf/src/Makefile.app index 83a7aa0..a6aba56 100644 --- a/firmware/asdf/src/Makefile.app +++ b/firmware/asdf/src/Makefile.app @@ -68,7 +68,7 @@ MAKEDEPEND = $(CPP) $(DEPFLAGS) $(CPPFLAGS) $< \ | sort -u > $*.d SRC_FILES = main.c asdf.c asdf_modifiers.c asdf_repeat.c asdf_keymaps.c -SRC_FILES += asdf_buffer.c asdf_arch.c asdf_actions.c +SRC_FILES += asdf_buffer.c asdf_arch.c asdf_virtual.c OBJ_FILES := $(SRC_FILES:.c=.o) DEP_FILES := $(SRC_FILES:%.c=$(DEP_DIR)/%.d) @@ -141,7 +141,7 @@ 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_actions.o: asdf_actions.h asdf.h asdf_arch.h +asdf_virtual.o: asdf_virtual.c asdf_virtual.h asdf_arch.h tags: $(SRC_FILES) etags $(SRC_FILES) diff --git a/firmware/asdf/src/Makefile.test b/firmware/asdf/src/Makefile.test index cdbe4f9..0acc034 100644 --- a/firmware/asdf/src/Makefile.test +++ b/firmware/asdf/src/Makefile.test @@ -41,7 +41,7 @@ OBJ_FILES = $(SRC_FILES:.c=.o) ARCH_FILES = asdf_arch.c asdf_arch.h CLEAN_FILES += ARCH_FILES -TESTS = repeat modifiers keymaps interface keyscan +TESTS = repeat modifiers keymaps interface keyscan virtual TEST1 = asdf_repeat TEST1_SRC = $(TEST_DIR)/test_$(TEST1).c @@ -49,13 +49,13 @@ TEST1_DEPS = ./$(TEST1).c $(UNITY_DIR)/unity.c TEST1_BUILD = $(BUILD_DIR)/test_$(TEST1) TEST2 = asdf_modifiers -TEST2_SRC = $(TEST_DIR)/test_$(TEST2).c ./asdf_arch.c +TEST2_SRC = $(TEST_DIR)/test_$(TEST2).c ./asdf_arch.c ./asdf_virtual.c TEST2_DEPS = ./$(TEST2).c $(UNITY_DIR)/unity.c TEST2_BUILD = $(BUILD_DIR)/test_$(TEST2) TEST3 = asdf_keymaps TEST3_SRC = $(TEST_DIR)/test_$(TEST3).c -TEST3_DEPS = ./$(TEST3).c $(UNITY_DIR)/unity.c +TEST3_DEPS = ./$(TEST3).c $(UNITY_DIR)/unity.c ./asdf_virtual.c ./asdf_arch.c TEST3_BUILD = $(BUILD_DIR)/test_$(TEST3) TEST4 = asdf_buffer @@ -63,10 +63,15 @@ TEST4_SRC = $(TEST_DIR)/test_$(TEST4).c TEST4_DEPS = ./$(TEST4).c $(UNITY_DIR)/unity.c TEST4_BUILD = $(BUILD_DIR)/test_$(TEST4) -TEST5 = asdf -TEST5_SRC = $(TEST_DIR)/test_$(TEST5).c -TEST5_DEPS = ./$(TEST5).c $(UNITY_DIR)/unity.c ./asdf_actions.c ./asdf_arch.c ./$(TEST1).c $(TEST2).c $(TEST3).c $(TEST4).c -TEST5_BUILD = $(BUILD_DIR)/test_$(TEST5) +TEST5 = asdf_virtual +TEST5_SRC = $(TEST_DIR)/test_$(TEST4).c +TEST5_DEPS = ./$(TEST4).c $(UNITY_DIR)/unity.c +TEST5_BUILD = $(BUILD_DIR)/test_$(TEST4) + +TEST6 = asdf +TEST6_SRC = $(TEST_DIR)/test_$(TEST5).c +TEST6_DEPS = ./$(TEST5).c $(UNITY_DIR)/unity.c ./asdf_arch.c ./$(TEST1).c $(TEST2).c $(TEST3).c $(TEST4).c +TEST6_BUILD = $(BUILD_DIR)/test_$(TEST5) .SUFFIXES: .SUFFIXES: .c .o .bin .hex @@ -96,12 +101,13 @@ $(ARCH_TOKEN): asdf_keymaps.c: asdf.h asdf_ascii.h asdf_modifiers.h asdf_arch.h asdf_keymaps.h asdf_keymap_defs.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 tags: $(SRC_FILES) etags $(SRC_FILES) .PHONY: test -test: test1 test2 test3 test4 test5 +test: test1 test2 test3 test4 test6 test5 .PHONY: test1 test1: $(TEST1_BUILD) @@ -123,6 +129,10 @@ test4: $(TEST4_BUILD) test5: $(TEST5_BUILD) $(TEST5_BUILD) +.PHONY: test6 +test5: $(TEST6_BUILD) + $(TEST6_BUILD) + $(TEST1_BUILD): $(TEST1_SRC) $(TEST1_DEPS) $(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST1_SRC) $(TEST1_DEPS) @@ -139,7 +149,10 @@ $(TEST4_BUILD): $(TEST4_SRC) $(TEST4_DEPS) $(TEST5_BUILD): $(TEST5_SRC) $(TEST5_DEPS) $(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST5_SRC) $(TEST5_DEPS) -TEST_BUILD_FILES += $(TEST1_BUILD) $(TEST2_BUILD) $(TEST3_BUILD) $(TEST4_BUILD) $(TEST5_BUILD) +$(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) CLEAN_FILES += $(TEST_BUILD_FILES) _Arch_* *.o CLEAN_FILES += ~* *\# diff --git a/firmware/asdf/src/asdf.c b/firmware/asdf/src/asdf.c index 04b8969..a7a6071 100644 --- a/firmware/asdf/src/asdf.c +++ b/firmware/asdf/src/asdf.c @@ -33,6 +33,7 @@ #include #include "asdf.h" #include "asdf_ascii.h" +#include "asdf_virtual.h" #include "asdf_keymaps.h" #include "asdf_keymap_defs.h" #include "asdf_repeat.h" @@ -136,6 +137,7 @@ asdf_keycode_t asdf_lookup_keycode(uint8_t row, uint8_t col) static void asdf_activate_action(action_t keycode) { switch (keycode) { + case ACTION_SHIFT: { asdf_modifier_shift_activate(); break; @@ -156,14 +158,6 @@ static void asdf_activate_action(action_t keycode) asdf_repeat_activate(); break; } - case ACTION_CLEAR: { - asdf_send_screen_clear(); - break; - } - case ACTION_RESET: { - asdf_send_reset(); - break; - } case ACTION_MAPSEL_0: { asdf_keymaps_map_select_0_set(); break; @@ -180,6 +174,42 @@ static void asdf_activate_action(action_t keycode) asdf_keymaps_map_select_3_set(); break; } + case ACTION_VLED1: { + asdf_virtual_activate(VLED1); + break; + } + case ACTION_VLED2: { + asdf_virtual_activate(VLED2); + break; + } + case ACTION_VLED3: { + asdf_virtual_activate(VLED3); + break; + } + case ACTION_VOUT1: { + asdf_virtual_activate(VOUT1); + break; + } + case ACTION_VOUT2: { + asdf_virtual_activate(VOUT2); + break; + } + case ACTION_VOUT3: { + asdf_virtual_activate(VOUT3); + break; + } + case ACTION_VOUT4: { + asdf_virtual_activate(VOUT4); + break; + } + case ACTION_VOUT5: { + asdf_virtual_activate(VOUT5); + break; + } + case ACTION_VOUT6: { + asdf_virtual_activate(VOUT6); + break; + } case ACTION_NOTHING: case ACTION_LOCAL: case ACTION_BREAK: diff --git a/firmware/asdf/src/asdf.h b/firmware/asdf/src/asdf.h index 4a7d193..b6250b4 100644 --- a/firmware/asdf/src/asdf.h +++ b/firmware/asdf/src/asdf.h @@ -54,6 +54,15 @@ typedef enum { ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3, + ACTION_VLED1, + ACTION_VLED2, + ACTION_VLED3, + ACTION_VOUT1, + ACTION_VOUT2, + ACTION_VOUT3, + ACTION_VOUT4, + ACTION_VOUT5, + ACTION_VOUT6, ACTION_FN_1, ACTION_FN_2, ACTION_FN_3, @@ -79,7 +88,7 @@ typedef enum { RESERVED_13, RESERVED_14, RESERVED_15, - RESERVED_16 + RESERVED_16, } action_t; diff --git a/firmware/asdf/src/asdf_config.h b/firmware/asdf/src/asdf_config.h index bd2739a..c4331c1 100644 --- a/firmware/asdf/src/asdf_config.h +++ b/firmware/asdf/src/asdf_config.h @@ -63,6 +63,12 @@ // time between repeats of a character with repeat key held, or in autorepeat (milliseconds) #define ASDF_REPEAT_TIME_MS (1000 / 15) // l5 characters per sec. +// duration of keyboard output pulses (RESET, SCREEN CLEAR, BREAK, etc.) +#define ASDF_PULSE_DELAY_US 100 + +// DEFAULT value of keyboard outputs +#define ASDF_VIRTUAL_OUT_DEFAULT_VALUE 1 // High if not used. + #endif /* !defined (CONFIG_H) */ //-------|---------|---------+---------+---------+---------+---------+---------+ diff --git a/firmware/asdf/src/asdf_keymaps.c b/firmware/asdf/src/asdf_keymaps.c index 97c612e..a082ce8 100644 --- a/firmware/asdf/src/asdf_keymaps.c +++ b/firmware/asdf/src/asdf_keymaps.c @@ -43,7 +43,7 @@ static keycode_matrix_t const *keymap_matrix[ASDF_NUM_KEYMAPS][ASDF_MOD_NUM_MODI ASDF_KEYMAP_DEFS; -static const FLASH virtual_initializer_t keymap_initializer_list[ASDF_NUM_KEYMAPS][ASDF_INITIALIZER_LENGTH] = +static const asdf_virtual_initializer_t keymap_initializer_list[ASDF_NUM_KEYMAPS][ASDF_KEYMAP_INITIALIZER_LENGTH] = ASDF_KEYMAP_INITIALIZERS; static uint8_t keymap_index; @@ -68,7 +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]); + asdf_virtual_init((asdf_virtual_initializer_t *const) keymap_initializer_list[keymap_index]); } } diff --git a/firmware/asdf/src/asdf_keymaps.h b/firmware/asdf/src/asdf_keymaps.h index d681830..21e195d 100644 --- a/firmware/asdf/src/asdf_keymaps.h +++ b/firmware/asdf/src/asdf_keymaps.h @@ -34,7 +34,7 @@ #define ASDF_KEYMAP_BIT_2 4 #define ASDF_KEYMAP_BIT_3 8 -typdef enum { +typedef enum { CLEAR_OUT1, SET_OUT1, CLEAR_OUT2, @@ -73,7 +73,7 @@ typdef enum { SET_VLED2_LED3, SET_VLED3_LED3, -} keymap_init_t +} keymap_init_t; diff --git a/firmware/asdf/src/asdf_modifiers.c b/firmware/asdf/src/asdf_modifiers.c index 4dcb963..b21a3f0 100644 --- a/firmware/asdf/src/asdf_modifiers.c +++ b/firmware/asdf/src/asdf_modifiers.c @@ -26,6 +26,7 @@ #include #include "asdf_modifiers.h" +#include "asdf_virtual.h" #include "asdf_arch.h" static shift_state_t shift_state; @@ -45,7 +46,7 @@ static const modifier_index_t modifier_indices[] = { }; -// PROCEDURE: set_shiftlock_state +// PROCEDURE: set_shift_state // INPUTS: (uint8_t) state: the new shift state // OUTPUTS: none // @@ -55,10 +56,13 @@ static const modifier_index_t modifier_indices[] = { // // COMPLEXITY: 1 // -void asdf_modifier_set_shiftlock_state(uint8_t new_state) +void asdf_modifier_set_shift_state(uint8_t new_state) { + uint8_t shiftlock_status = new_state & SHIFT_LOCKED_ST; + shift_state = new_state; - asdf_virtual_action(VSHIFT_LED, (shift_state ? V_SET_HI : V_SET_LO)); + + asdf_virtual_action(VSHIFT_LED, (shiftlock_status ? V_SET_HI : V_SET_LO)); } // PROCEDURE: asdf_modifier_shift_activate @@ -100,7 +104,7 @@ void asdf_modifier_shift_activate(void) // // COMPLEXITY: 2 // -void asdf_modifier_shiftlock_activate(); +void asdf_modifier_shiftlock_activate(void) { if (asdf_toggle_shiftlock) { asdf_modifier_set_shift_state(shift_state ^ SHIFT_LOCKED_ST); @@ -120,17 +124,17 @@ void asdf_modifier_shiftlock_activate(); // // COMPLEXITY: 1 // -static void asdf_modifier_set_caps_state(uint8_t new_state); +static void asdf_modifier_set_caps_state(uint8_t new_state) { - uint8_t caps_state = new_state; - asdf_virtual_action(VCAPS_LED, (caps_state ? V_SET_HI : V_SET_LO ); + caps_state = new_state; + asdf_virtual_action(VCAPS_LED, (caps_state ? V_SET_HI : V_SET_LO )); } // PROCEDURE: asdf_modifier_capslock_activate // INPUTS: none // OUTPUTS: none // -// DESCRIPTION: Turns on Capslock state +// DESCRIPTION: Toggles Capslock state // // SIDE EFFECTS: see DESCRIPTION // diff --git a/firmware/asdf/src/asdf_virtual.c b/firmware/asdf/src/asdf_virtual.c index 04ad71a..0aac4de 100644 --- a/firmware/asdf/src/asdf_virtual.c +++ b/firmware/asdf/src/asdf_virtual.c @@ -27,8 +27,10 @@ // this program. If not, see . // - +#include #include "asdf_virtual.h" +#include "asdf_keymap_defs.h" +#include "asdf_config.h" #include "asdf_arch.h" // For each virtual out, maintain a "shadow" register for the output value. This @@ -55,17 +57,17 @@ 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, // +static void (*const vout_set[])(uint8_t) = { + [VMAP_NO_OUT] = &asdf_arch_null_output, // [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 // + [VMAP_LED1] = &asdf_arch_led1_set, // + [VMAP_LED2] = &asdf_arch_led2_set, // + [VMAP_LED3] = &asdf_arch_led3_set // }; // virtual_out[] contains all the virtual outputs. An asdf_virtual_output_t @@ -94,7 +96,7 @@ static virtual_dev_t virtual_device_table[NUM_VIRTUAL_OUTPUTS]; 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; + real_device_table[real_out].shadow = value; } @@ -113,7 +115,7 @@ static void asdf_virtual_real_set(asdf_virtual_real_dev_t real_out, uint8_t valu // // COMPLEXITY: 1 // -static void asdf_virtual_real_assert(asdf_virtual_real_dev_t real_out); +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); @@ -134,7 +136,7 @@ static void asdf_virtual_real_assert(asdf_virtual_real_dev_t real_out); // // COMPLEXITY: 1 // -static void asdf_virtual_real_toggle(asdf_virtual_real_dev_t real_out); +static void asdf_virtual_real_toggle(asdf_virtual_real_dev_t real_out) { uint8_t value = real_device_table[real_out].shadow; @@ -160,7 +162,7 @@ static void asdf_virtual_real_toggle(asdf_virtual_real_dev_t real_out); // 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; + asdf_virtual_real_dev_t device = virtual_device_table[virtual_out].real_device; while (VMAP_NO_OUT != device) { switch (function) { @@ -192,6 +194,26 @@ void asdf_virtual_action(asdf_virtual_output_t virtual_out, asdf_virtual_functio } } +// PROCEDURE: asdf_virtual_activate +// INPUTS: asdf_virtual_output_t: The virtual device to be activated +// OUTPUTS: none +// +// DESCRIPTION: for each real output mapped to the virtual output, apply the +// function assigned to the virtual output at initialization. +// +// SIDE EFFECTS: see above +// +// NOTES: The virtual output points to a linked list of real devices. +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_virtual_activate(asdf_virtual_output_t virtual_out) +{ + asdf_virtual_action(virtual_out, virtual_device_table[virtual_out].function); +} + // PROCEDURE: asdf_virtual_assign // INPUTS: (asdf_vout_t) virtual_out // (uint8_t) real_out @@ -209,9 +231,9 @@ void asdf_virtual_action(asdf_virtual_output_t virtual_out, asdf_virtual_functio // 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) + asdf_virtual_function_t function, uint8_t initial_value) { - virtual_device_table[virtual_device].function = function; + virtual_device_table[virtual_out].function = function; // add real device to the list associated with the virtual device: @@ -220,25 +242,25 @@ static void asdf_virtual_assign(asdf_virtual_output_t virtual_out, asdf_virtual_ // 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; + real_device_table[real_out].shadow = initial_value; } // PROCEDURE: asdf_virtual_init -// INPUTS: initializers +// INPUTS: (asdf_virtual_initializer_t *) initializer_list - contains the +// initializer list for the selected keymap. // 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. +// NOTES: 1) // 2) ASDF_VIRTUAL_OUT_DEFAULT_VALUE is defined in asdf_config.h // // SCOPE: public // // COMPLEXITY: 2 // -void asdf_virtual_init(virtual_initializer_t *initializer_list) +void asdf_virtual_init(asdf_virtual_initializer_t *const initializer_list) { // initialize list of virtual outputs @@ -250,19 +272,19 @@ void asdf_virtual_init(virtual_initializer_t *initializer_list) // 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 + 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. + // V_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++) { + i < ASDF_KEYMAP_INITIALIZER_LENGTH && initializer_list[i].virtual_device != V_NULL; i++) { - asdf_virtual_assign(intializer_list[i].virtual_device, intializer_list[i].real_device, + asdf_virtual_assign(initializer_list[i].virtual_device, initializer_list[i].real_device, initializer_list[i].function, initializer_list[i].initial_value); } diff --git a/firmware/asdf/src/asdf_virtual.h b/firmware/asdf/src/asdf_virtual.h index 448d817..6c9b0af 100644 --- a/firmware/asdf/src/asdf_virtual.h +++ b/firmware/asdf/src/asdf_virtual.h @@ -54,6 +54,7 @@ typedef enum { VMAP_OUT1, VMAP_OUT1_OC, VMAP_OUT2, + VMAP_OUT2_OC, VMAP_OUT3, VMAP_OUT3_OC, VMAP_LED1, @@ -62,7 +63,14 @@ typedef enum { 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; +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. @@ -71,7 +79,7 @@ typedef struct { asdf_virtual_real_dev_t real_device; asdf_virtual_function_t function; uint8_t initial_value; -} virtual_initializer_t; +} asdf_virtual_initializer_t; // PROCEDURE: asdf_virtual_action // INPUTS: (asdf_virtual_output_t) virtual_out: which virtual output to modify @@ -81,11 +89,19 @@ typedef struct { // specified function. void asdf_virtual_action(asdf_virtual_output_t virtual_out, asdf_virtual_function_t function); +// PROCEDURE: asdf_virtual_activate +// INPUTS: asdf_virtual_output_t: The virtual device to be activated +// OUTPUTS: none +// DESCRIPTION: for each real output mapped to the virtual output, apply the +// function assigned to the virtual output at initialization. +void asdf_virtual_activate(asdf_virtual_output_t virtual_out); + // PROCEDURE: asdf_virtual_init // INPUTS: initializers // OUTPUTS: none // DESCRIPTION: Initializes the LED and output mapping -void asdf_virtual_init(virtual_initializer_t *initializer_list); +void asdf_virtual_init(asdf_virtual_initializer_t *const initializer_list); + #endif /* !defined (ASDF_VIRTUAL_H) */ diff --git a/firmware/asdf/test/test_asdf_keymaps.c b/firmware/asdf/test/test_asdf_keymaps.c index 243ebe9..6c21371 100644 --- a/firmware/asdf/test/test_asdf_keymaps.c +++ b/firmware/asdf/test/test_asdf_keymaps.c @@ -82,24 +82,6 @@ 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; @@ -131,8 +113,6 @@ void setUp(void) { coord_t *temp; - reset_testvals(); - asdf_keymaps_init(); temp = find_code(TESTALPHA); @@ -348,14 +328,6 @@ 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) { UNITY_BEGIN(); diff --git a/firmware/asdf/test/test_asdf_modifiers.c b/firmware/asdf/test/test_asdf_modifiers.c index ad0c63a..e244212 100644 --- a/firmware/asdf/test/test_asdf_modifiers.c +++ b/firmware/asdf/test/test_asdf_modifiers.c @@ -279,82 +279,6 @@ void ctrl_double_shiftlock_returns_to_ctrl_map(void) TESTMAP(MOD_CTRL_MAP); } -// CAPS give caps -void caps_gives_caps(void) -{ - asdf_modifier_caps_activate(); - TESTMAP(MOD_CAPS_MAP); -} - -// CAPS and release gives plain -void caps_and_release_gives_plain(void) -{ - asdf_modifier_caps_activate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_caps_deactivate(); - TESTMAP(MOD_PLAIN_MAP); -} - - -// CAPSLOCK and CAPS gives caps -void capslock_and_caps_gives_caps(void) -{ - asdf_modifier_capslock_activate(); - asdf_modifier_capslock_deactivate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_caps_activate(); - TESTMAP(MOD_CAPS_MAP); -} - -// CAPSLOCK and CAPS and release CAPS gives caps -void capslock_and_caps_and_release_gives_caps(void) -{ - asdf_modifier_capslock_activate(); - asdf_modifier_capslock_deactivate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_caps_activate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_caps_deactivate(); - TESTMAP(MOD_CAPS_MAP); -} - -// CAPS and CAPSLOCK gives caps -void caps_and_capslock_gives_caps(void) -{ - asdf_modifier_caps_activate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_capslock_activate(); - asdf_modifier_capslock_deactivate(); - TESTMAP(MOD_CAPS_MAP); -} - -// CAPS and CAPSLOCK and release CAPS gives caps -void caps_and_capslock_and_release_gives_caps(void) -{ - asdf_modifier_caps_activate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_capslock_activate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_caps_deactivate(); - TESTMAP(MOD_CAPS_MAP); -} - -// CAPS and CAPSLOCK and release CAPS then CAPSLOCK gives plain -void caps_and_capslock_and_release_and_capslock_gives_plain(void) -{ - asdf_modifier_caps_activate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_capslock_activate(); - asdf_modifier_capslock_deactivate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_caps_deactivate(); - TESTMAP(MOD_CAPS_MAP); - asdf_modifier_capslock_activate(); - asdf_modifier_capslock_deactivate(); - TESTMAP(MOD_PLAIN_MAP); -} - - int main(void) { UNITY_BEGIN(); @@ -381,13 +305,6 @@ int main(void) RUN_TEST(ctrl_shiftlock_gives_ctrl_map); RUN_TEST(ctrl_double_caps_returns_to_ctrl_map); RUN_TEST(ctrl_double_shiftlock_returns_to_ctrl_map); - RUN_TEST(caps_gives_caps); - RUN_TEST(caps_and_release_gives_plain); - RUN_TEST(capslock_and_caps_gives_caps); - RUN_TEST(capslock_and_caps_and_release_gives_caps); - RUN_TEST(caps_and_capslock_gives_caps); - RUN_TEST(caps_and_capslock_and_release_gives_caps); - RUN_TEST(caps_and_capslock_and_release_and_capslock_gives_plain); // toggle shiftlock_mode switches the shiftlock behavior to toggle_mode // calling toggle_shiftlock_mode twice leaves shiftlock behavior in hold mode // calling toggle_shiftlock_mode three times leaves shiftlock behavior in toggle mode