mirror of
https://github.com/osiweb/unified_retro_keyboard.git
synced 2024-12-30 10:30:38 +00:00
Changes for virtual LED and output mapping.
Rough first cut, have not yet tried to compile or test.
This commit is contained in:
parent
63e733c18d
commit
cff7f6052a
@ -203,11 +203,12 @@ static void asdf_arch_init_clock(void)
|
||||
CLKPR = (CLKPCE | SYSCLK_DIV1);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_screen_clear(void)
|
||||
// PROCEDURE: asdf_arch_init_outputs
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Initialize Screen Clear to LOW
|
||||
// DESCRIPTION: Initialize all LED ports as outputs. Values are not set here.
|
||||
// They are set by the keymap code
|
||||
//
|
||||
// SIDE EFFECTS: See DESCRIPTION
|
||||
//
|
||||
@ -215,38 +216,206 @@ static void asdf_arch_init_clock(void)
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
static void asdf_arch_init_screen_clear(void)
|
||||
static void asdf_arch_init_leds(void)
|
||||
{
|
||||
if (ASDF_DEFAULT_SCREEN_CLEAR_POLARITY == ASDF_POSITIVE_POLARITY) {
|
||||
clear_bit(&ASDF_SCREEN_CLEAR_PORT, ASDF_SCREEN_CLEAR_BIT);
|
||||
} else {
|
||||
set_bit(&ASDF_SCREEN_CLEAR_PORT, ASDF_SCREEN_CLEAR_BIT);
|
||||
}
|
||||
set_bit(&ASDF_SCREEN_CLEAR_DDR, ASDF_SCREEN_CLEAR_BIT);
|
||||
set_bit(&ASDF_LED1_DDR, ASDF_LED1_BIT);
|
||||
set_bit(&ASDF_LED2_DDR, ASDF_LED2_BIT);
|
||||
set_bit(&ASDF_LED3_DDR, ASDF_LED3_BIT);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_init_sys_reset
|
||||
// INPUTS: none
|
||||
|
||||
// PROCEDURE: asdf_arch_led1_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Initialize system reset to INACTIVE. Sys Reset emulates an open
|
||||
// collector output, so the inactive state is high impedance. Configure as an
|
||||
// input. Set the pin up as an input, and enable the weak pullup. Normally the
|
||||
// host system should pull the line high. The weak pullup is ~200-300k, at least
|
||||
// an order of magnitude greater than the typical host pullup value, so should
|
||||
// not have significant impact on the current, but will ensure the line is high
|
||||
// if the host omits a pullup.
|
||||
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
|
||||
//
|
||||
// SIDE EFFECTS: See DESCRIPTION
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// SCOPE: private
|
||||
// NOTES: The LED1 port drives the LED directly by pulling the cathode low, so
|
||||
// clearing the bit turns the LED on.
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
// SCOPE: public
|
||||
//
|
||||
static void asdf_arch_init_sys_reset(void)
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_led1_set(uint8_t value)
|
||||
{
|
||||
clear_bit(&ASDF_SYS_RESET_DDR, ASDF_SYS_RESET_BIT); // set as input
|
||||
set_bit(&ASDF_SYS_RESET_PORT, ASDF_SYS_RESET_BIT); // enable weak pullup
|
||||
if (value) {
|
||||
clear_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
|
||||
} else {
|
||||
set_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_led2_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES: The LED2 output drives the LED via an inverter buffer, so a high
|
||||
// output pulls the LED cathode low, lighting the LED.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_led2_set(uint8_t value)
|
||||
{
|
||||
if (value) {
|
||||
set_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
|
||||
} else {
|
||||
clear_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_led3_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES: The LED3 output drives the LED via an inverter buffer, so a high
|
||||
// output pulls the LED cathode low, lighting the LED.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_led3_set(uint8_t value)
|
||||
{
|
||||
if (value) {
|
||||
set_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
|
||||
} else {
|
||||
clear_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out1_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_out1_set(uint8_t value)
|
||||
{
|
||||
if (value) {
|
||||
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
|
||||
} else {
|
||||
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
|
||||
}
|
||||
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out1_hi_z_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_out1_hi_z_set(uint8_t value)
|
||||
{
|
||||
if (value) {
|
||||
clear_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
|
||||
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
|
||||
} else {
|
||||
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
|
||||
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out2_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES: OUT2 is inverted by the 7404 buffer, so clearing the bit sets the output high. OUT2 cannot be high impedance.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_out2_set(uint8_t value)
|
||||
{
|
||||
if (value) {
|
||||
clear_bit(&ASDF_OUT2_PORT, ASDF_OUT1_BIT);
|
||||
} else {
|
||||
set_bit(&ASDF_OUT2_PORT, ASDF_OUT1_BIT);
|
||||
}
|
||||
set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out3_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_out3_set(uint8_t value)
|
||||
{
|
||||
if (value) {
|
||||
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
|
||||
} else {
|
||||
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
|
||||
}
|
||||
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out3_hi_z_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_out3_hi_z_set(uint8_t value)
|
||||
{
|
||||
if (value) {
|
||||
clear_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
|
||||
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
|
||||
} else {
|
||||
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
|
||||
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_init_strobe
|
||||
@ -340,159 +509,50 @@ static void asdf_arch_init_row_outputs(void)
|
||||
}
|
||||
|
||||
|
||||
// PROCEDURE: asdf_arch_caps_led
|
||||
// INPUTS: (uint8_t) led_state: nonzero value turns on LED, zero turns off LED
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Controls the CAPSLOCK LED.
|
||||
//
|
||||
// SIDE EFFECTS: See DESCRIPTION
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_caps_led(uint8_t led_status)
|
||||
{
|
||||
if (led_status) {
|
||||
set_bit(&ASDF_CAPS_LED_PORT, ASDF_CAPS_LED_BIT);
|
||||
} else {
|
||||
clear_bit(&ASDF_CAPS_LED_PORT, ASDF_CAPS_LED_BIT);
|
||||
// PROCEDURE: asdf_arch_init
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: sets up all the hardware for the keyboard
|
||||
//
|
||||
// SIDE EFFECTS: see DESCRIPTION
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_init(void)
|
||||
{
|
||||
// disable interrupts:
|
||||
cli();
|
||||
|
||||
// clear the 1ms timer flag;
|
||||
tick = 0;
|
||||
|
||||
// set up timers for 1 msec intervals
|
||||
asdf_arch_init_clock();
|
||||
asdf_arch_tick_timer_init();
|
||||
|
||||
// set up ASCII output port
|
||||
asdf_arch_init_ascii_output();
|
||||
|
||||
// initialize keyboard data and strobe to positive polairy
|
||||
data_polarity = ASDF_DEFAULT_DATA_POLARITY;
|
||||
strobe_polarity = ASDF_DEFAULT_STROBE_POLARITY;
|
||||
|
||||
asdf_arch_init_strobe();
|
||||
asdf_arch_init_leds();
|
||||
|
||||
// set up row output port
|
||||
asdf_arch_init_row_outputs();
|
||||
|
||||
// set up column control lines
|
||||
asdf_arch_init_column_control();
|
||||
|
||||
// enable interrupts:
|
||||
sei();
|
||||
}
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_init_caps_led
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Initialize CAPSLOCK LED to off.
|
||||
//
|
||||
// SIDE EFFECTS: See DESCRIPTION
|
||||
//
|
||||
// SCOPE: private
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
static void asdf_arch_init_caps_led(void)
|
||||
{
|
||||
asdf_arch_caps_led(0);
|
||||
set_bit(&ASDF_CAPS_LED_DDR, ASDF_CAPS_LED_BIT);
|
||||
}
|
||||
|
||||
|
||||
// PROCEDURE: asdf_arch_init_power_led
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Initialize CAPSLOCK LED to off.
|
||||
//
|
||||
// SIDE EFFECTS: See DESCRIPTION
|
||||
//
|
||||
// SCOPE: private
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
static void asdf_arch_init_power_led(void)
|
||||
{
|
||||
clear_bit(&ASDF_POWER_LED_PORT, ASDF_POWER_LED_BIT);
|
||||
set_bit(&ASDF_POWER_LED_DDR, ASDF_POWER_LED_BIT);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_init
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: sets up all the hardware for the keyboard
|
||||
//
|
||||
// SIDE EFFECTS: see DESCRIPTION
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_init(void)
|
||||
{
|
||||
// disable interrupts:
|
||||
cli();
|
||||
|
||||
// clear the 1ms timer flag;
|
||||
tick = 0;
|
||||
|
||||
// set up timers for 1 msec intervals
|
||||
asdf_arch_init_clock();
|
||||
asdf_arch_tick_timer_init();
|
||||
|
||||
// set up ASCII output port
|
||||
asdf_arch_init_ascii_output();
|
||||
|
||||
// initialize keyboard data and strobe to positive polairy
|
||||
data_polarity = ASDF_DEFAULT_DATA_POLARITY;
|
||||
strobe_polarity = ASDF_DEFAULT_STROBE_POLARITY;
|
||||
|
||||
asdf_arch_init_strobe();
|
||||
asdf_arch_init_screen_clear();
|
||||
asdf_arch_init_sys_reset();
|
||||
asdf_arch_init_caps_led();
|
||||
asdf_arch_init_power_led();
|
||||
|
||||
// set up row output port
|
||||
asdf_arch_init_row_outputs();
|
||||
|
||||
// set up column control lines
|
||||
asdf_arch_init_column_control();
|
||||
|
||||
// enable interrupts:
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
// PROCEDURE: asdf_arch_send_screen_clear
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
|
||||
//
|
||||
// SIDE EFFECTS: see DESCRIPTION
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_send_screen_clear(void)
|
||||
{
|
||||
set_bit(&ASDF_SCREEN_CLEAR_PIN, ASDF_SCREEN_CLEAR_BIT);
|
||||
_delay_us(ASDF_STROBE_LENGTH_US);
|
||||
set_bit(&ASDF_SCREEN_CLEAR_PIN, ASDF_SCREEN_CLEAR_BIT);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_send_reset
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Pulses the SYS_RESET output. This emulates open collector, so
|
||||
// PORT is set to LOW also briefly disabling the weak pullup but also preventing
|
||||
// even a brief conflict on the output, in case the line is pulled low
|
||||
// elsewhere. Then, DDR is set to output. After the pulse duration, the DDR is
|
||||
// set back to input, and PORT is set to HIGH to activate the weak pullup.
|
||||
//
|
||||
// SIDE EFFECTS: see DESCRIPTION
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_send_reset(void)
|
||||
{
|
||||
clear_bit(&ASDF_SYS_RESET_PORT, ASDF_SYS_RESET_BIT);
|
||||
set_bit(&ASDF_SYS_RESET_DDR, ASDF_SYS_RESET_BIT);
|
||||
_delay_us(ASDF_STROBE_LENGTH_US);
|
||||
clear_bit(&ASDF_SYS_RESET_DDR, ASDF_SYS_RESET_BIT);
|
||||
set_bit(&ASDF_SYS_RESET_PORT, ASDF_SYS_RESET_BIT);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_read_row
|
||||
// INPUTS: (uint8_t) row: the row number to be scanned
|
||||
|
@ -213,23 +213,20 @@
|
||||
#define ASDF_LED3_DDR DDRB
|
||||
#define ASDF_LED3_BIT 4
|
||||
|
||||
#define ASDF_POWER_LED_PORT ASDF_LED1_PORT
|
||||
#define ASDF_POWER_LED_DDR ASDF_LED1_DDR
|
||||
#define ASDF_POWER_LED_BIT ASDF_LED1_BIT
|
||||
#define ASDF_OUT1_PORT PORTC
|
||||
#define ASDF_OUT1_PIN PINC
|
||||
#define ASDF_OUT1_DDR DDRC
|
||||
#define ASDF_OUT1_BIT 5
|
||||
|
||||
#define ASDF_CAPS_LED_PORT ASDF_LED3_PORT
|
||||
#define ASDF_CAPS_LED_DDR ASDF_LED3_DDR
|
||||
#define ASDF_CAPS_LED_BIT ASDF_LED3_BIT
|
||||
#define ASDF_OUT2_PORT PORTB
|
||||
#define ASDF_OUT2_PIN PINB
|
||||
#define ASDF_OUT2_DDR DDRB
|
||||
#define ASDF_OUT2_BIT 3
|
||||
|
||||
#define ASDF_SCREEN_CLEAR_PORT PORTC
|
||||
#define ASDF_SCREEN_CLEAR_PIN PINC
|
||||
#define ASDF_SCREEN_CLEAR_DDR DDRC
|
||||
#define ASDF_SCREEN_CLEAR_BIT 5
|
||||
|
||||
#define ASDF_SYS_RESET_PORT PORTB
|
||||
#define ASDF_SYS_RESET_PIN PINB
|
||||
#define ASDF_SYS_RESET_DDR DDRB
|
||||
#define ASDF_SYS_RESET_BIT 7
|
||||
#define ASDF_OUT3_PORT PORTB
|
||||
#define ASDF_OUT3_PIN PINB
|
||||
#define ASDF_OUT3_DDR DDRB
|
||||
#define ASDF_OUT3_BIT 7
|
||||
|
||||
#define ASDF_STROBE_PORT PORTB
|
||||
#define ASDF_STROBE_PIN PINB
|
||||
@ -251,6 +248,53 @@
|
||||
// For 1 ms tick, (8000000 / 64(prescale)) / 1000(usec) - 1 = 124
|
||||
#define TICK_COUNT 124
|
||||
|
||||
// PROCEDURE: asdf_arch_led1_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
|
||||
void asdf_arch_led1_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_led2_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
|
||||
void asdf_arch_led2_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_led3_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
|
||||
void asdf_arch_led3_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_out1_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
|
||||
void asdf_arch_out1_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_out1_hi_z_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
|
||||
void asdf_arch_out1_hi_z_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_out2_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
|
||||
void asdf_arch_out2_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_out3_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
|
||||
void asdf_arch_out3_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_out3_hi_z_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
|
||||
void asdf_arch_out3_hi_z_set(uint8_t value);
|
||||
|
||||
// PROCEDURE: asdf_arch_read_row
|
||||
// INPUTS: (uint8_t) row: the row number to be scanned
|
||||
@ -265,24 +309,6 @@ asdf_cols_t asdf_arch_read_row(uint8_t row);
|
||||
// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise
|
||||
uint8_t asdf_arch_tick(void);
|
||||
|
||||
// PROCEDURE: asdf_arch_caps_led
|
||||
// INPUTS: (uint8_t) led_state: nonzero value turns on LED, zero turns off LED
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Controls the CAPSLOCK LED.
|
||||
void asdf_arch_caps_led(uint8_t led_status);
|
||||
|
||||
// PROCEDURE: asdf_arch_send_screen_clear
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
|
||||
void asdf_arch_send_screen_clear(void);
|
||||
|
||||
// PROCEDURE: asdf_arch_send_reset
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
|
||||
void asdf_arch_send_reset(void);
|
||||
|
||||
// PROCEDURE: asdf_arch_send_code
|
||||
// INPUTS: (keycode_t) code - the code to be output by the keyboard
|
||||
// OUTPUTS: none
|
||||
|
@ -37,11 +37,176 @@
|
||||
#include <stdint.h>
|
||||
#include "asdf_keymap_defs.h"
|
||||
#include "asdf_config.h"
|
||||
#include "asdf_virtual.h"
|
||||
#include "asdf_arch.h"
|
||||
|
||||
// this is to get rid of "unused variable" warnings.
|
||||
volatile static uint32_t junk_variable;
|
||||
|
||||
static uint8_t outputs[NUM_REAL_OUTPUTS];
|
||||
|
||||
// PROCEDURE: asdf_arch_led1_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_led1_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_LED1] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_led2_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_led2_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_LED2] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_led3_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_led3_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_LED3] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out1_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_out1_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_OUT1] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out1_hi_z_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_out1_hi_z_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_OUT1_OC] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out2_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_arch_out2_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_OUT2] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out3_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_out3_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_OUT3] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_out3_hi_z_set
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
|
||||
//
|
||||
// SIDE EFFECTS: See above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_out3_hi_z_set(uint8_t value)
|
||||
{
|
||||
outputs[VMAP_OUT3_OC] = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_check_output
|
||||
// INPUTS:(asdf_virtual_real_dev_t) device - which device to check
|
||||
// OUTPUTS: the value of the device setting.
|
||||
//
|
||||
// DESCRIPTION: For a given real device, return the current setting (true or false)
|
||||
//
|
||||
// SIDE EFFECTS: none
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
uint8_t asdf_arch_check_output(asdf_virtual_real_dev_t device)
|
||||
{
|
||||
return outputs[device];
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_arch_init
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
@ -54,54 +219,11 @@ volatile static uint32_t junk_variable;
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_init(void) {}
|
||||
|
||||
// PROCEDURE: asdf_arch_send_screen_clear
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
|
||||
//
|
||||
// SIDE EFFECTS: see DESCRIPTION
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_send_screen_clear(void) {}
|
||||
|
||||
// PROCEDURE: asdf_arch_send_reset
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Toggles the SCREEN_CLEAR output.
|
||||
//
|
||||
// SIDE EFFECTS: see DESCRIPTION
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_send_reset(void) {}
|
||||
|
||||
// PROCEDURE: asdf_arch_caps_led
|
||||
// INPUTS: (uint8_t) led_state: nonzero value turns on LED, zero turns off LED
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Controls the CAPSLOCK LED. Test version is empty.
|
||||
//
|
||||
// SIDE EFFECTS: None for test version
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
void asdf_arch_caps_led(uint8_t led_status) {
|
||||
junk_variable = led_status;
|
||||
void asdf_arch_init(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) {
|
||||
outputs[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#define ASDF_KEYMAP_DECLARATIONS ASDF_TEST_DECLARATIONS ASDF_TEST2_DECLARATIONS
|
||||
|
||||
#define ASDF_KEYMAP_INITIALIZERS { ASDF_TEST_KEYMAP_INITIALIZER , ASDF_TEST2_KEYMAP_INTIALIZER }
|
||||
|
||||
typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS];
|
||||
|
||||
|
@ -147,6 +147,15 @@
|
||||
#define ASDF_TEST_PLAIN_MAP_INDEX ASDF_TEST_BASE + 0
|
||||
#define ASDF_TEST_CAPS_MAP_INDEX ASDF_TEST_BASE + 1
|
||||
|
||||
#define ASDF_TEST_KEYMAP_INITIALIZER_LENGTH 3
|
||||
#define ASDF_TEST_KEYMAP_INITIALIZER \
|
||||
{ \
|
||||
{ .virtual_device = VCAPS_LED, .device = VMAP_LED1, .initial_value = 1 }, \
|
||||
{ .virtual_device = VOUT1, .device = VMAP_OUT1, .initial_value = 1 }, \
|
||||
{ .virtual_device = VOUT2, .device = VMAP_OUT3, .initial_value = 1 } \
|
||||
}
|
||||
|
||||
|
||||
// The following preprocessor "code" permits various keymaps to be created and
|
||||
// included without generating a lot of complicating code dependencies. The use
|
||||
// of macros in this way is a bit ugly, I realize, and stretches the intention
|
||||
@ -165,6 +174,10 @@
|
||||
#define ASDF_NUM_COLS ASDF_TEST_NUM_COLS
|
||||
#endif
|
||||
|
||||
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) || (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST_KEYMAP_INITIALIZER_LENGTH)
|
||||
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
|
||||
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST_KEYMAP_INITIALIZER_LENGTH
|
||||
#endif
|
||||
|
||||
#endif /* !defined (ASDF_KEYMAP_DEFS_TEST_H) */
|
||||
|
||||
|
@ -56,10 +56,10 @@
|
||||
|
||||
#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1)
|
||||
|
||||
#define ASDF_TEST_MAP_DIP_SWITCHES \
|
||||
#define ASDF_TEST_MAP_DIP_SWITCHES \
|
||||
[ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 }
|
||||
|
||||
#define ASDF_TEST2_PLAIN_MAP \
|
||||
#define ASDF_TEST2_PLAIN_MAP \
|
||||
{ \
|
||||
{ PLAIN_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
|
||||
ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
|
||||
@ -73,7 +73,7 @@
|
||||
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
|
||||
}
|
||||
|
||||
#define ASDF_TEST2_CAPS_MAP \
|
||||
#define ASDF_TEST2_CAPS_MAP \
|
||||
{ \
|
||||
{ CAPS_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
|
||||
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
|
||||
@ -87,7 +87,7 @@
|
||||
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
|
||||
}
|
||||
|
||||
#define ASDF_TEST2_SHIFT_MAP \
|
||||
#define ASDF_TEST2_SHIFT_MAP \
|
||||
{ \
|
||||
\
|
||||
{ SHIFT_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
|
||||
@ -104,7 +104,7 @@
|
||||
}
|
||||
|
||||
|
||||
#define ASDF_TEST2_CTRL_MAP \
|
||||
#define ASDF_TEST2_CTRL_MAP \
|
||||
{ \
|
||||
{ CTRL_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
|
||||
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \
|
||||
@ -126,28 +126,38 @@
|
||||
}
|
||||
|
||||
|
||||
#define ASDF_TEST2_DECLARATIONS \
|
||||
static const FLASH keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; \
|
||||
static const FLASH keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; \
|
||||
static const FLASH keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; \
|
||||
#define ASDF_TEST2_DECLARATIONS \
|
||||
static const FLASH keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; \
|
||||
static const FLASH keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; \
|
||||
static const FLASH keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; \
|
||||
static const FLASH keycode_matrix_t test2_CTRL_matrix = ASDF_TEST2_CTRL_MAP;
|
||||
|
||||
#define ASDF_TEST2_MAP_DEFS \
|
||||
#define ASDF_TEST2_MAP_DEFS \
|
||||
{ \
|
||||
&test2_PLAIN_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
|
||||
&test2_PLAIN_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
|
||||
}
|
||||
|
||||
#define ASDF_TEST2_CAPS_MAP_DEFS \
|
||||
#define ASDF_TEST2_CAPS_MAP_DEFS \
|
||||
{ \
|
||||
&test2_CAPS_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
|
||||
&test2_CAPS_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
|
||||
}
|
||||
|
||||
#define ASDF_TEST2_KEYMAPS ASDF_TEST2_MAP_DEFS, ASDF_TEST2_CAPS_MAP_DEFS
|
||||
#define ASDF_TEST2_KEYMAPS ASDF_TEST2_MAP_DEFS, ASDF_TEST2_CAPS_MAP_DEFS
|
||||
|
||||
#define ASDF_TEST2_KEYMAPS_COUNT 2
|
||||
#define ASDF_TEST2_PLAIN_MAP_INDEX (ASDF_TEST2_BASE + 0)
|
||||
#define ASDF_TEST2_CAPS_MAP_INDEX (ASDF_TEST2_BASE + 1)
|
||||
|
||||
#define ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH 4
|
||||
#define ASDF_TEST2_KEYMAP_INITIALIZER \
|
||||
{ \
|
||||
{ .virtual_device = VCAPS_LED, .device = VMAP_LED2, .initial_value = 1 }, \
|
||||
{ .virtual_device = VOUT1, .device = VMAP_OUT2, .initial_value = 1 }, \
|
||||
{ .virtual_device = VOUT2, .device = VMAP_OUT3, .initial_value = 0 }, \
|
||||
{ .virtual_device = VOUT2, .device = NUM_VIRTUAL_OUTPUTS, .initial_value = 0 } \
|
||||
}
|
||||
|
||||
|
||||
// The following preprocessor "code" permits various keymaps to be created and
|
||||
// included without generating a lot of complicating code dependencies. The use
|
||||
// of macros in this way is a bit ugly, I realize, and stretches the intention
|
||||
@ -166,6 +176,12 @@
|
||||
#define ASDF_NUM_COLS ASDF_TEST2_NUM_COLS
|
||||
#endif
|
||||
|
||||
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \
|
||||
|| (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH)
|
||||
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
|
||||
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* !defined (ASDF_KEYMAP_DEFS_TEST2_H) */
|
||||
|
||||
|
@ -75,7 +75,7 @@ typedef enum {
|
||||
ASCII_TILDE = 0x7e,
|
||||
ASCII_VERT_BAR = 0x7c,
|
||||
ASCII_DEL = 0x7f
|
||||
} ascii;
|
||||
} ascii_defs_t;
|
||||
|
||||
#define ASCII_LF ASCII_CTRL_J
|
||||
#define ASCII_CR ASCII_CTRL_M
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <stdint.h>
|
||||
#include "asdf.h"
|
||||
#include "asdf_arch.h"
|
||||
#include "asdf_virtual.h"
|
||||
#include "asdf_keymaps.h"
|
||||
#include "asdf_keymap_defs.h"
|
||||
|
||||
@ -41,8 +42,13 @@ ASDF_KEYMAP_DECLARATIONS;
|
||||
static keycode_matrix_t const *keymap_matrix[ASDF_NUM_KEYMAPS][ASDF_MOD_NUM_MODIFIERS] =
|
||||
ASDF_KEYMAP_DEFS;
|
||||
|
||||
|
||||
static const FLASH virtual_initializer_t keymap_initializer_list[ASDF_NUM_KEYMAPS][ASDF_INITIALIZER_LENGTH] =
|
||||
ASDF_KEYMAP_INITIALIZERS;
|
||||
|
||||
static uint8_t keymap_index;
|
||||
|
||||
|
||||
// PROCEDURE: asdf_keymaps_select_keymap
|
||||
// INPUTS: (uint8_t) index - index of the keymap number to select
|
||||
// OUTPUTS: none
|
||||
@ -62,6 +68,7 @@ void asdf_keymaps_select_keymap(uint8_t index)
|
||||
{
|
||||
if (index < ASDF_NUM_KEYMAPS) {
|
||||
keymap_index = index;
|
||||
asdf_virtual_init(keymap_initializer_list[keymap_index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,49 @@
|
||||
#define ASDF_KEYMAP_BIT_2 4
|
||||
#define ASDF_KEYMAP_BIT_3 8
|
||||
|
||||
typdef enum {
|
||||
CLEAR_OUT1,
|
||||
SET_OUT1,
|
||||
CLEAR_OUT2,
|
||||
SET_OUT2,
|
||||
CLEAR_OUT3,
|
||||
SET_OUT3,
|
||||
CLEAR_OC1,
|
||||
SET_OC1,
|
||||
CLEAR_OC3,
|
||||
SET_OC3,
|
||||
PULSE_OUT1,
|
||||
PULSE_OUT2,
|
||||
PULSE_OUT3,
|
||||
TOGGLE_OUT1,
|
||||
TOGGLE_OUT2,
|
||||
TOGGLE_OUT3,
|
||||
ON_VLED1,
|
||||
OFF_VLED1,
|
||||
ON_VLED2,
|
||||
OFF_VLED2,
|
||||
ON_VLED3,
|
||||
OFF_VLED3,
|
||||
SET_CAPS_LED1,
|
||||
SET_CAPS_LED2,
|
||||
SET_CAPS_LED3,
|
||||
SET_SHIFTLOCK_LED1,
|
||||
SET_SHIFTLOCK_LED2,
|
||||
SET_SHIFTLOCK_LED3,
|
||||
SET_VLED1_LED1,
|
||||
SET_VLED2_LED1,
|
||||
SET_VLED3_LED1,
|
||||
SET_VLED1_LED2,
|
||||
SET_VLED2_LED2,
|
||||
SET_VLED3_LED2,
|
||||
SET_VLED1_LED3,
|
||||
SET_VLED2_LED3,
|
||||
SET_VLED3_LED3,
|
||||
|
||||
} keymap_init_t
|
||||
|
||||
|
||||
|
||||
// PROCEDURE: asdf_keymaps_select_keymap
|
||||
// INPUTS: (uint8_t) index - index of the keymap number to select
|
||||
// OUTPUTS: none
|
||||
|
276
firmware/asdf/src/asdf_virtual.c
Normal file
276
firmware/asdf/src/asdf_virtual.c
Normal file
@ -0,0 +1,276 @@
|
||||
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
|
||||
//
|
||||
// Unified Keyboard Project
|
||||
// ASDF keyboard firmware
|
||||
//
|
||||
// asdf_virtual_outputs.c
|
||||
//
|
||||
// This file contains code that maps "virtual" LEDs and outputs referenced by
|
||||
// the code to actual LEDs and outputs in hardware. This keeps keymap-specific
|
||||
// details out of the architecture-dependent files, and provides a flexible way
|
||||
// for the keymap definitions to specify the LED and output functions for
|
||||
// different keymaps or keyboard layouts.
|
||||
//
|
||||
// Copyright 2019 David Fenyes
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation, either version 3 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
|
||||
#include "asdf_virtual.h"
|
||||
#include "asdf_arch.h"
|
||||
|
||||
// For each virtual out, maintain a "shadow" register for the output value. This
|
||||
// permits machine independent implementations of the toggle and pulse functions
|
||||
// to be implemented in this module, requiring only a "set" function for each
|
||||
// virtual output in the architecture-dependent layer. This implementation is
|
||||
// not as efficient, but the timing is not critical, and the events are so
|
||||
// infrequent that the benefits of the refactoring far outweigh any performance
|
||||
// penalty.
|
||||
|
||||
typedef struct {
|
||||
uint8_t shadow;
|
||||
asdf_virtual_real_dev_t next;
|
||||
} real_dev_t;
|
||||
|
||||
typedef struct {
|
||||
asdf_virtual_real_dev_t real_device; // Each virtual device points to a linked
|
||||
// list of any number of real devices.
|
||||
asdf_virtual_function_t function;
|
||||
} virtual_dev_t;
|
||||
|
||||
|
||||
static real_dev_t real_device_table[NUM_REAL_OUTPUTS];
|
||||
|
||||
|
||||
// vout_set[] contains the set() function for each real output device.
|
||||
static const void (*vout_set[])(uint8_t) = {
|
||||
[VMAP_NO_OUT] = NULL, //
|
||||
[VMAP_OUT1] = &asdf_arch_out1_set, //
|
||||
[VMAP_OUT2] = &asdf_arch_out2_set, //
|
||||
[VMAP_OUT3] = &asdf_arch_out3_set, //
|
||||
[VMAP_OUT1_OC] = &asdf_arch_out1_hi_z_set, //
|
||||
[VMAP_OUT2_OC] = &asdf_arch_out2_hi_z_set, //
|
||||
[VMAP_OUT3_OC] = &asdf_arch_out3_hi_z_set, //
|
||||
[VMAP_VLED1] = &asdf_arch_led1_set, //
|
||||
[VMAP_VLED2] = &asdf_arch_led2_set, //
|
||||
[VMAP_VLED3] = &asdf_arch_led3_set //
|
||||
};
|
||||
|
||||
// virtual_out[] contains all the virtual outputs. An asdf_virtual_output_t
|
||||
// value is used to identify each element. Each element is a virtual device,
|
||||
// containing an asdf_virtual_real_dev_t value indicating the real device (if
|
||||
// any) assigned to the virtual device.
|
||||
static virtual_dev_t virtual_device_table[NUM_VIRTUAL_OUTPUTS];
|
||||
|
||||
|
||||
// PROCEDURE: asdf_virtual_real_set
|
||||
// INPUTS: (asdf_virtual_real_dev_t) real_out: which real output to set or clear
|
||||
// INPUTS: (uint8_t) value
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: If the real output is valid, set to high if value is true, low
|
||||
// if false.
|
||||
//
|
||||
// SIDE EFFECTS: see above
|
||||
//
|
||||
// NOTES: No bounds checking. The caller must ensure a valid device
|
||||
//
|
||||
// SCOPE: private
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
static void asdf_virtual_real_set(asdf_virtual_real_dev_t real_out, uint8_t value)
|
||||
{
|
||||
vout_set[real_out](value);
|
||||
shadow_out[real_out] = value;
|
||||
}
|
||||
|
||||
|
||||
// PROCEDURE: asdf_virtual_real_assert
|
||||
// INPUTS: (asdf_virtual_real_dev_t) real_out: which real output to set or clear
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Assert the value of the real output shadow register on the output.
|
||||
//
|
||||
// SIDE EFFECTS: see above
|
||||
//
|
||||
// NOTES: No bounds checking. Only called from initialization code.
|
||||
//
|
||||
// SCOPE: private
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
static void asdf_virtual_real_assert(asdf_virtual_real_dev_t real_out);
|
||||
{
|
||||
uint8_t value = real_device_table[real_out].shadow;
|
||||
vout_set[real_out](value);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_virtual_real_toggle
|
||||
// INPUTS: (asdf_virtual_real_dev_t) real_out: which real output to toggle
|
||||
// INPUTS: none
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Toggle the value of the real output.
|
||||
//
|
||||
// SIDE EFFECTS: see above
|
||||
//
|
||||
// NOTES: No bounds checking. Only called from initialization code.
|
||||
//
|
||||
// SCOPE: private
|
||||
//
|
||||
// COMPLEXITY: 1
|
||||
//
|
||||
static void asdf_virtual_real_toggle(asdf_virtual_real_dev_t real_out);
|
||||
{
|
||||
uint8_t value = real_device_table[real_out].shadow;
|
||||
|
||||
real_device_table[real_out].shadow = !value;
|
||||
vout_set[real_out](value);
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_virtual_action
|
||||
// INPUTS: (asdf_virtual_output_t) virtual_out: which virtual output to modify
|
||||
// INPUTS: (asdf_virtual_function_t) function: what function to apply to the virtual output
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: for each real output mapped to the virtual output, apply the
|
||||
// specified function.
|
||||
//
|
||||
// SIDE EFFECTS: see above
|
||||
//
|
||||
// NOTES: The virtual output points to a linked list of real devices.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 7
|
||||
//
|
||||
void asdf_virtual_action(asdf_virtual_output_t virtual_out, asdf_virtual_function_t function)
|
||||
{
|
||||
real_dev_t device = virtual_device_table[virtual_out].real_device;
|
||||
|
||||
while (VMAP_NO_OUT != device) {
|
||||
switch (function) {
|
||||
|
||||
case V_PULSE: {
|
||||
asdf_virtual_real_toggle(device);
|
||||
asdf_arch_pulse_delay();
|
||||
// yes we could omit the next two lines and fall through, but we will
|
||||
// spend a few bytes of redundant code for the sake of consistency and
|
||||
// readability.
|
||||
asdf_virtual_real_toggle(device);
|
||||
break;
|
||||
}
|
||||
case V_TOGGLE: {
|
||||
asdf_virtual_real_toggle(device);
|
||||
break;
|
||||
}
|
||||
case V_SET_HI: {
|
||||
asdf_virtual_real_set(device, 1);
|
||||
break;
|
||||
}
|
||||
case V_SET_LO: {
|
||||
asdf_virtual_real_set(device, 0);
|
||||
}
|
||||
case V_NOFUNC:
|
||||
default: break;
|
||||
}
|
||||
device = real_device_table[device].next;
|
||||
}
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_virtual_assign
|
||||
// INPUTS: (asdf_vout_t) virtual_out
|
||||
// (uint8_t) real_out
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: map the virtual output specified by new_vout to real_out, if
|
||||
// both arguments are valid. Ignore if not valid.
|
||||
//
|
||||
// SIDE EFFECTS: see above.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// SCOPE: private
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
static void asdf_virtual_assign(asdf_virtual_output_t virtual_out, asdf_virtual_real_dev_t real_out,
|
||||
asdf_virtual_function_t function, uint8_t initial_value)
|
||||
{
|
||||
virtual_device_table[virtual_device].function = function;
|
||||
|
||||
// add real device to the list associated with the virtual device:
|
||||
|
||||
real_device_table[real_out].next = virtual_device_table[virtual_out].real_device;
|
||||
virtual_device_table[virtual_out].real_device = real_out;
|
||||
|
||||
// The real device shadow value is set here. The shadow values are asserted to
|
||||
// the outputs only after all the assignments have been performed.
|
||||
real_device_table[real_out].shadow = value;
|
||||
}
|
||||
|
||||
// PROCEDURE: asdf_virtual_init
|
||||
// INPUTS: initializers
|
||||
// OUTPUTS: none
|
||||
//
|
||||
// DESCRIPTION: Initializes the LED and output mapping
|
||||
//
|
||||
// SIDE EFFECTS: see above
|
||||
//
|
||||
// NOTES: The table of real devices is initialized as a linked list of available
|
||||
// devices.
|
||||
//
|
||||
// SCOPE: public
|
||||
//
|
||||
// COMPLEXITY: 2
|
||||
//
|
||||
void asdf_virtual_init(virtual_initializer_t *initializer_list)
|
||||
{
|
||||
|
||||
// initialize list of virtual outputs
|
||||
for (uint8_t i = 0; i < NUM_VIRTUAL_OUTPUTS; i++) {
|
||||
virtual_device_table[i].function = V_NOFUNC;
|
||||
virtual_device_table[i].real_device = VMAP_NO_OUT;
|
||||
}
|
||||
|
||||
// initialize the linked list of free devices
|
||||
for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) {
|
||||
real_device_table[i].shadow = ASDF_VIRTUAL_OUT_DEFAULT_VALUE;
|
||||
real_device_table[i].next = i + 1 // initialize pointer to next in table
|
||||
}
|
||||
// The last item in the table is left with a bogus next pointer (beyond the
|
||||
// end of the array) after the above loop. Make the last element point to
|
||||
// NULL.
|
||||
real_device_table[NUM_REAL_OUTPUTS - 1].next = VMAP_NO_OUT; // end of list.
|
||||
|
||||
|
||||
// run through the keymap specific setup
|
||||
for (uint8_t i = 0; //
|
||||
i < NUM_INITIALIZERS && initializers[i].virtual_device != V_NULL; i++) {
|
||||
|
||||
asdf_virtual_assign(intializer_list[i].virtual_device, intializer_list[i].real_device,
|
||||
initializer_list[i].function, initializer_list[i].initial_value);
|
||||
}
|
||||
|
||||
// Now set all the initial LED and output values
|
||||
for (uint8_t i = 0; i < NUM_REAL_OUTPUTS; i++) {
|
||||
asdf_virtual_real_assert((asdf_virtual_real_dev_t) i);
|
||||
}
|
||||
}
|
||||
|
||||
//-------|---------|---------+---------+---------+---------+---------+---------+
|
||||
// Above line is 80 columns, and should display completely in the editor.
|
93
firmware/asdf/src/asdf_virtual.h
Normal file
93
firmware/asdf/src/asdf_virtual.h
Normal file
@ -0,0 +1,93 @@
|
||||
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
|
||||
//
|
||||
// Unfified Keyboard Project
|
||||
// ASDF keyboard firmware
|
||||
//
|
||||
// asdf_virtual.h
|
||||
//
|
||||
// Definitions and prototypes for virtual LED and virtual output management.
|
||||
//
|
||||
// Copyright 2019 David Fenyes
|
||||
// This program is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation, either version 3 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#if !defined(ASDF_VIRTUAL_H)
|
||||
#define ASDF_VIRTUAL_H
|
||||
|
||||
|
||||
// These are "virtual" output identifiers that can be mapped to the real outputs using
|
||||
// keymap initializer commands.
|
||||
typedef enum {
|
||||
V_NULL,
|
||||
VOUT1,
|
||||
VOUT2,
|
||||
VOUT3,
|
||||
VOUT4,
|
||||
VOUT5,
|
||||
VOUT6,
|
||||
VLED1,
|
||||
VLED2,
|
||||
VLED3,
|
||||
VCAPS_LED,
|
||||
VSHIFT_LED,
|
||||
NUM_VIRTUAL_OUTPUTS
|
||||
} asdf_virtual_output_t;
|
||||
|
||||
// The asdf_virtual_real_dev_t enumerates real outputs that can be assigned to
|
||||
// virtual outputs via the asdf_virtual_assign() function. The name is a bit
|
||||
// confusing, containing virtual and real. The "virtual" part refers to the
|
||||
// module and the "real_dev" part attempts to clarify that these are the
|
||||
// hardware outputs implemented by the architecture-specific module.
|
||||
typedef enum {
|
||||
VMAP_NO_OUT = 0,
|
||||
VMAP_OUT1,
|
||||
VMAP_OUT1_OC,
|
||||
VMAP_OUT2,
|
||||
VMAP_OUT3,
|
||||
VMAP_OUT3_OC,
|
||||
VMAP_LED1,
|
||||
VMAP_LED2,
|
||||
VMAP_LED3,
|
||||
NUM_REAL_OUTPUTS
|
||||
} asdf_virtual_real_dev_t;
|
||||
|
||||
typedef enum { V_NOFUNC, V_SET_HI, V_SET_LO, V_PULSE, V_TOGGLE, NUM_VIRTUAL_FUNCTIONS } asdf_virtual_function_t;
|
||||
|
||||
// Each keymap specifies an array of initializer structs to configure virtual
|
||||
// devices, specifying the mapped real device and initial value.
|
||||
typedef struct {
|
||||
asdf_virtual_output_t virtual_device;
|
||||
asdf_virtual_real_dev_t real_device;
|
||||
asdf_virtual_function_t function;
|
||||
uint8_t initial_value;
|
||||
} virtual_initializer_t;
|
||||
|
||||
// PROCEDURE: asdf_virtual_action
|
||||
// INPUTS: (asdf_virtual_output_t) virtual_out: which virtual output to modify
|
||||
// INPUTS: (asdf_virtual_function_t) function: what function to apply to the virtual output
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: for each real output mapped to the virtual output, apply the
|
||||
// specified function.
|
||||
void asdf_virtual_action(asdf_virtual_output_t virtual_out, asdf_virtual_function_t function);
|
||||
|
||||
// PROCEDURE: asdf_virtual_init
|
||||
// INPUTS: initializers
|
||||
// OUTPUTS: none
|
||||
// DESCRIPTION: Initializes the LED and output mapping
|
||||
void asdf_virtual_init(virtual_initializer_t *initializer_list);
|
||||
|
||||
#endif /* !defined (ASDF_VIRTUAL_H) */
|
||||
|
||||
//-------|---------|---------+---------+---------+---------+---------+---------+
|
||||
// Above line is 80 columns, and should display completely in the editor.
|
@ -77,11 +77,29 @@ typedef struct {
|
||||
|
||||
ASDF_KEYMAP_DECLARATIONS;
|
||||
|
||||
|
||||
// keymap coordinates for special functions
|
||||
static coord_t alpha_sample;
|
||||
static coord_t num_sample;
|
||||
static coord_t keymap_tag;
|
||||
|
||||
// Array of zeros which will be initialized to specific values on keymap changes.
|
||||
static keycode_t init_testvals[ASDF_NUM_INITIALIZERS] = {};
|
||||
static keycode_t initializers[ASDF_NUM_KEYMAPS][ASDF_NUM_INITIALIZERS] = ASDF_KEYMAP_INITIALIZERS;
|
||||
|
||||
void reset_testvals(void)
|
||||
{
|
||||
for(int i = 0; i < ASDF_NUM_INITIALIZERS; i++) {
|
||||
init_testvals[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint32_t max(uint8_t first, uint8_t second)
|
||||
{
|
||||
uint32_t max = first;
|
||||
@ -113,6 +131,8 @@ void setUp(void)
|
||||
{
|
||||
coord_t *temp;
|
||||
|
||||
reset_testvals();
|
||||
|
||||
asdf_keymaps_init();
|
||||
|
||||
temp = find_code(TESTALPHA);
|
||||
@ -328,6 +348,13 @@ void dip_switch_invalid_keymap_has_no_effect(void)
|
||||
|
||||
}
|
||||
|
||||
void keymap_initializers_run_on_startup(void)
|
||||
{
|
||||
for (int i = 0; i < NUM_INITIALIZERS; i++)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT32((int32_t) )
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user