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.
This commit is contained in:
David Fenyes 2020-03-08 14:45:40 -05:00
parent 44a49afdae
commit 1b388bc591
22 changed files with 723 additions and 270 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,6 +33,7 @@
#include <stdint.h>
#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:

View File

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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@
#include <stdint.h>
#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
//

View File

@ -27,8 +27,10 @@
// this program. If not, see <https://www.gnu.org/licenses/>.
//
#include <stdint.h>
#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);
}

View File

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

View File

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

View File

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