From 27b151964a583b7b2cf2bd43f2d0bcad6c3b7b5f Mon Sep 17 00:00:00 2001 From: Dave Date: Wed, 13 May 2020 11:14:43 -0500 Subject: [PATCH] More gitignore updates --- .gitignore | 8 + firmware/asdf/src/asdf_arch.c | 834 +++++++++++++++++++++++++++ firmware/asdf/src/asdf_arch.h | 486 ++++++++++++++++ firmware/asdf/src/asdf_keymap_defs.h | 72 +++ 4 files changed, 1400 insertions(+) create mode 100644 firmware/asdf/src/asdf_arch.c create mode 100644 firmware/asdf/src/asdf_arch.h create mode 100644 firmware/asdf/src/asdf_keymap_defs.h diff --git a/.gitignore b/.gitignore index 9ef8702..82387af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ .DS_Store *scratch* +*.bak +*.sch-bak +*-cache.lib +*.kicad_pcb-bak +fp-lib-table +fp-info-cache +*.o +*-rescue.lib diff --git a/firmware/asdf/src/asdf_arch.c b/firmware/asdf/src/asdf_arch.c new file mode 100644 index 0000000..117e17a --- /dev/null +++ b/firmware/asdf/src/asdf_arch.c @@ -0,0 +1,834 @@ +// -*- 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 . + + +// 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 "asdf_arch.h" + +#include +#include +#include +#include + +#include "asdf_config.h" +#include "asdf_keymap_defs.h" + +// Tick is true every 1 ms. +static volatile uint8_t tick = 0; + +// data polarity may be changed with a DIP switch, so we use a static instead of a constant +static uint8_t data_polarity = ASDF_DEFAULT_DATA_POLARITY; + +// strobe polarity may be changed with a DIP switch, so we use a static instead of a constant +static uint8_t strobe_polarity = ASDF_DEFAULT_STROBE_POLARITY; + + +// PROCEDURE: ISR for Timer 0 overflow +// INPUTS: none +// OUTPUTS:none +// +// DESCRIPTION: Occurs every 1 ms. Set tick flag, kick watchdog. +// +// SIDE EFFECTS: +// +// NOTES: +// +// SCOPE: +// +// COMPLEXITY: +// +ISR(TIMER0_COMPA_vect) +{ + tick = 1; +} + +// PROCEDURE: set_bit +// INPUTS: port: pointer to a (uint8) port +// bit: bit position to be set +// OUTPUTS: none +// +// DESCRIPTION: Give a port address and bit position, set the bit position. +// +// SIDE EFFECTS: See DESCRIPTION +// +// NOTES: Declared inline. Will only be inlined for functions in this module, so +// also declared static. +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static inline void set_bit(volatile uint8_t *port, uint8_t bit) +{ + *port |= (1 << bit); +} + +// PROCEDURE: clear_bit +// INPUTS: port: pointer to a (uint8) port +// bit: bit position to be cleared +// OUTPUTS: none +// +// DESCRIPTION: Give a port address and bit position, clear the bit position. +// +// SIDE EFFECTS: See DESCRIPTION +// +// NOTES: Declared inline. Will only be inlined for functions in this module, so +// also declared static. +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static inline void clear_bit(volatile uint8_t *port, uint8_t bit) +{ + *port &= ~(1 << bit); +} + +// PROCEDURE: arch_timer0_config +// +// INPUTS: bits: a 4 byte field containing the configuration values for the +// 8-bit timer0 A and B control registers, and the interrupt mask register. +// +// OUTPUTS: none +// +// DESCRIPTION: Takes a 4 byte value with settings for all the control +// registers for the 8-bit counter/timer (timer 0), and writes them all +// to the respective registers. +// +// SIDE EFFECTS: see above +// +// NOTES: Setting all the bits together, and writing all the registers from a +// single word permits more clear initialization of control fields that are +// spread across more than one word. +// +// COMPLEXITY: 1 +// +// SCOPE: private +// +static void arch_timer0_config(uint32_t bits) +{ + TCCR0B = 0; // first turn off timer. + TCCR0A = (bits >> TMR0A_POS) & 0xff; + TIMSK0 = (bits >> TMR0IMSK_POS) & 0xff; + TCCR0B = (bits >> TMR0B_POS) & 0xff; // Set the mode (and turn on timer) last +} + +// PROCEDURE: arch_tick_timer_init +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Sets up 1ms tick timer. +// +// SIDE EFFECTS: +// +// NOTES: Set up Timer 0 in CTC mode for 1 ms overflow. +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void asdf_arch_tick_timer_init(void) +{ + tick = 0; + + // set compare register first, so timer can operate correctly as soon as it is + // enabled. + OCR0A = TICK_COUNT; + + // operate in CTC mode to overflow at exactly 1 ms + // prescaler = 64 and output compare value is 250 + arch_timer0_config(TIMER0_WFM_CTC | TIMER0_DIV64 | TIMER0_INT_ON_COMA); +} + +// PROCEDURE: asdf_arch_tick +// INPUTS: none +// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise +// +// DESCRIPTION: See Outputs. +// +// SIDE EFFECTS: Zeroes out the 1 ms timer flag. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +uint8_t asdf_arch_tick(void) +{ + uint8_t retval = tick; + tick = 0; + return retval; +} + +// PROCEDURE: asdf_arch_init_timers +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Sets up timer for 1 ms intervals +// +// SIDE EFFECTS: See DESCRIPTION +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void asdf_arch_init_clock(void) +{ + CLKPR = (CLKPCE | SYSCLK_DIV1); +} + +// PROCEDURE: asdf_arch_init_outputs +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Initialize all LED ports as outputs. Values are not set here. +// They are set by the keymap code +// +// SIDE EFFECTS: See DESCRIPTION +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void asdf_arch_init_leds(void) +{ + 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_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. +// +// NOTES: The LED1 port drives the LED directly by pulling the cathode low, so +// clearing the bit turns the LED on. +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_led1_set(uint8_t value) +{ + 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) { + clear_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT); + } + else { + set_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) { + clear_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT); + } + else { + set_bit(&ASDF_LED3_PORT, ASDF_LED3_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_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_open_hi_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_open_hi_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_out1_open_lo_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// +// DESCRIPTION: Sets the OUT1 bit to high if value is true, and hi-z if value is false. +// +// SIDE EFFECTS: See above. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_out1_open_lo_set(uint8_t value) +{ + if (value) { + set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT); + set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT); + } + else { + clear_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT); + clear_bit(&ASDF_OUT1_PORT, 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: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_out2_set(uint8_t value) +{ + if (value) { + set_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT); + } + else { + clear_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT); + } + set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT); +} + +// PROCEDURE: asdf_arch_out2_open_hi_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: 2 +// +void asdf_arch_out2_open_hi_set(uint8_t value) +{ + if (value) { + clear_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT); + set_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT); + } + else { + clear_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT); + set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT); + } +} + +// PROCEDURE: asdf_arch_out2_open_lo_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// +// DESCRIPTION: Sets the OUT2 bit to high if value is true, and hi-z if value is false. +// +// SIDE EFFECTS: See above. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_out2_open_lo_set(uint8_t value) +{ + if (value) { + set_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT); + set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT); + } + else { + clear_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT); + clear_bit(&ASDF_OUT2_PORT, 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_open_hi_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_open_hi_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_out3_open_lo_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// +// DESCRIPTION: Sets the OUT3 bit to high if value is true, and hi-z if value is false. +// +// SIDE EFFECTS: See above. +// +// NOTES: +// +// SCOPE: public +// +// COMPLEXITY: 2 +// +void asdf_arch_out3_open_lo_set(uint8_t value) +{ + if (value) { + set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT); + set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT); + } + else { + clear_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT); + clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT); + } +} + +// PROCEDURE: asdf_arch_init_strobe +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Initialize strobe output +// +// SIDE EFFECTS: See DESCRIPTION +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void asdf_arch_init_strobe(void) +{ + if (strobe_polarity == ASDF_POSITIVE_POLARITY) { + clear_bit(&ASDF_STROBE_PORT, ASDF_STROBE_BIT); + } + else { + set_bit(&ASDF_STROBE_PORT, ASDF_STROBE_BIT); + } + set_bit(&ASDF_STROBE_DDR, ASDF_STROBE_BIT); +} + +// PROCEDURE: asdf_arch_init_ascii_output +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Sets up output port for ASCII output +// +// SIDE EFFECTS: See DESCRIPTION +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void asdf_arch_init_ascii_output(void) +{ + // set all outputs + ASDF_ASCII_PORT = data_polarity; + ASDF_ASCII_DDR = ALL_OUTPUTS; +} + +// PROCEDURE: asdf_arch_init_columns +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Sets up columns port as input and enable weak pullups. +// +// SIDE EFFECTS: See DESCRIPTION +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void asdf_arch_init_columns(void) +{ + ASDF_COLUMNS_DDR = ALL_INPUTS; + ASDF_COLUMNS_PORT = ALL_PULLUPS; +} + +// PROCEDURE: asdf_arch_init_row_outputs +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Sets up output port to latch keyboard matrix row for scanning. +// +// SIDE EFFECTS: See DESCRIPTION +// +// SCOPE: private +// +// COMPLEXITY: 1 +// +static void asdf_arch_init_row_outputs(void) +{ + ASDF_HIROW_DDR = ALL_OUTPUTS; + ASDF_LOROW_DDR = ALL_OUTPUTS; +} + +// PROCEDURE: asdf_arch_pulse_delay_short +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by ASDF_PULSE_DELAY_SHORT_US +// +// SIDE EFFECTS: see above. +// +// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_arch_pulse_delay_short(void) +{ + _delay_us(ASDF_PULSE_DELAY_SHORT_US); +} + +// PROCEDURE: asdf_arch_pulse_delay_long +// INPUTS: none +// OUTPUTS: none +// +// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by ASDF_PULSE_DELAY_LONG_MS +// +// SIDE EFFECTS: see above. +// +// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +void asdf_arch_pulse_delay_long(void) +{ + _delay_us(ASDF_PULSE_DELAY_LONG_MS); +} + +// 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 and column ports + asdf_arch_init_row_outputs(); + asdf_arch_init_columns(); + + // enable interrupts: + sei(); +} + +// 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 ports, 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. +// +// SIDE EFFECTS: Sets ROW output port. +// +// NOTES: +// +// 1) The keymap represents an unpressed key as a "0" and a pressed key as a +// "1". So, if a keypress pulls the column line low, then the reading of the +// physical bits must be inverted. +// +// 2) A small delay (2usec) is required between setting the keyboard row outputs +// and reading the columns, which I think is due to capacitance across the +// reverse-biased diodes. +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +asdf_cols_t asdf_arch_read_row(uint8_t row) +{ + uint32_t rows = ~(1L << row); + + ASDF_LOROW_PORT = (uint8_t)(rows & 0xff); + ASDF_HIROW_PORT = (uint8_t)((rows >> 8) & 0xff); + + _delay_us(ASDF_KEYBOARD_ROW_SETTLING_TIME_US); + + return ~(asdf_cols_t) ASDF_COLUMNS_PIN; +} + +// PROCEDURE: asdf_arch_osi_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 ports, 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. +// +// SIDE EFFECTS: Sets ROW output port. +// +// NOTES: +// +// 1) The keymap represents an unpressed key as a "0" and a pressed key as a +// "1". So, if a keypress pulls the column line low, then the reading of the +// physical bits must be inverted. +// +// SCOPE: public +// +// COMPLEXITY: 1 +// +asdf_cols_t asdf_arch_osi_read_row(uint8_t row) +{ + asdf_cols_t cols; + + if (row > 7) { + cols = asdf_arch_read_row(row); + } else { + // enable the OSI keyboard + clear_bit(&ASDF_OSI_KBE_PORT, ASDF_OSI_KBE_BIT); + + // register the row to be read + ASDF_COLUMNS_DDR = ALL_OUTPUTS; + + ASDF_COLUMNS_PORT = (1 << row); + clear_bit(&ASDF_OSI_RW_PORT, ASDF_OSI_RW_BIT); + set_bit(&ASDF_OSI_RW_PORT, ASDF_OSI_RW_BIT); + + // Read in the columns + ASDF_COLUMNS_DDR = ALL_INPUTS; + return ASDF_COLUMNS_PIN; + + ASDF_LOROW_PORT = row & 0xff; + + cols = (asdf_cols_t) ASDF_COLUMNS_PORT; + } + return cols; +} + + +// PROCEDURE: asdf_arch_send_code +// INPUTS: (keycode_t) code - the 7-bit ASCII code to be output by the keyboard +// OUTPUTS: none +// +// DESCRIPTION: Takes a character code and outputs the code on a parallel ASCII +// port, with a strobe. This routine could be replaced with UART, I2C, USB, or +// other output mechanism, of course. +// +// SIDE EFFECTS: See above. +// +// NOTES: The strobe is set by the ASDF_STROBE_LENGTH definition. The data +// output and strobe polarity are set by the static data_polarity and static +// strobe_polarity variables. +// +// SCOPE: +// +// COMPLEXITY: +// + +void asdf_arch_send_code(asdf_keycode_t code) +{ + ASDF_ASCII_PORT = (code ^ data_polarity); + + + // toggle strobe. Must test before setting to avoid spurious strobe + set_bit(&ASDF_STROBE_PIN, ASDF_STROBE_BIT); + + _delay_us(ASDF_STROBE_LENGTH_US); + + set_bit(&ASDF_STROBE_PIN, ASDF_STROBE_BIT); +} + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. +// diff --git a/firmware/asdf/src/asdf_arch.h b/firmware/asdf/src/asdf_arch.h new file mode 100644 index 0000000..6145470 --- /dev/null +++ b/firmware/asdf/src/asdf_arch.h @@ -0,0 +1,486 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// asdf_arch_atmega2560.h +// +// Contains architecture-specific definitions for the atmega 2560 +// +// +// Copyright 2019 David Fenyes +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +#if !defined(ASDF_ARCH_H) +#define ASDF_ARCH_H + +#include +#include + +#include "asdf.h" + +// ASDF keyboard definitions: + +#define F_CPU 16000000L + +#define ASDF_STROBE_LENGTH_US 10 // strobe length in microseconds +#define ASDF_KEYBOARD_ROW_SETTLING_TIME_US 2 // time for keyboard capacitance to + // settle before sampling + +// Clock definitions: +#define SYSCLK_DIV1 0 +#define SYSCLK_DIV2 (CLKPS0) +#define SYCCLK_DIV4 (CLKPS1) +#define SYSCLK_DIV8 (CLKPS1 | CLKPS0) +#define SYSCLK_DIV16 (CLKPS2) +#define SYSCLK_DIV32 (CLKPS2 | CLKPS0) +#define SYSCLK_DIV64 (CLKPS2 | CLKPS1) +#define SYSCLK_DIV128 (CLKPS2 | CLKPS1 | CLKPS0) +#define SYSCLK_DIV256 (CLKPS3) + +// Timer 0 definitions +// Define fields for register A, B, interrupt mask as 8-bit masks, and +// as masks offset into a combined config word +#define TMR0A_POS 0 +#define TMR0B_POS 8 +#define TMR0IMSK_POS 16 +#define TMR0A (1L << TMR0A_POS) +#define TMR0B (1L << TMR0B_POS) +#define TMR0IMSK (1L << TMR0IMSK_POS) + +#define TIMER0_COM_A_DISCONNECTED 0 +#define TIMER0_COM_B_DISCONNECTED 0 +#define TIMER0_WFM_CTC (TMR0A << WGM01) +#define TIMER0_DIV64 ((TMR0B << CS01) | (TMR0B << CS00)) +#define TIMER0_INT_ON_COMA (TMR0IMSK << OCIE0A) +#define TIMER0_INT_ON_COMB (TMR0IMSK << OCIE0B) +#define TIMER0_INT_OV_ENABLE (TMR0IMSK << TOIE0) + +// Macros for 16-bit timers 1, 3, 4, 5. Datasheet section 17, p. 133 +// +// Define fields for Registers A, B, C, INT Mask registers as 8-bit +// masks, and as masks offset into a 32-bit combined config word. +// +// Macro definitions for individual registers are named TMRXA_*, +// TMRXB_*, and TMRXC_*. +// +// Macros for the one-step combined timer config functions are named +// TMRX_*. +// +// +// Examples: +// // Use TMRXB_* definition to set TCCR4B register +// TCCR4B |= TMRXB_DIV1; +// +// // Use TMRX_* definitions to configure timer with config function +// processor_timer4_config(TMRX_WFM_CTC | TMRX_INT_ON_CMPA); +// +#define TMRXA_POS 0 +#define TMRXB_POS 8 +#define TMRXC_POS 16 +#define TMRXIMSK_POS 24 +#define TMRXA (1L << TMRXA_POS) +#define TMRXB (1L << TMRXB_POS) +#define TMRXC (1L << TMRXC_POS) +#define TMRXIMSK (1L << TMRXIMSK_POS) + +// 16-bit timer reg A - Datasheet 17.11.1, p. 154 +#define TMRXA_CMPA_CLR_MATCH_SET_BOTTOM (1 << COM1A1) +#define TMRXA_CMPB_CLR_MATCH_SET_BOTTOM (1 << COM1B1) +#define TMRXA_CMPC_CLR_MATCH_SET_BOTTOM (1 << COM1C1) +#define TMRX_CMPA_CLR_MATCH_SET_BOTTOM (TMRXA << COM1A1) +#define TMRX_CMPB_CLR_MATCH_SET_BOTTOM (TMRXA << COM1B1) +#define TMRX_CMPC_CLR_MATCH_SET_BOTTOM (TMRXA << COM1C1) + +// 16-bit timer reg B - Datasheet 17.11.6, p. 156 + +#define TMRXB_IN_CAP_POS 0x40L +#define TMRXB_IN_CAP_NEG 0L +#define TMRXB_IN_CAP_NOISE_CANCEL 0x80L + +// 16-bit timer reg C -- see datasheet, 17.11.9, p. 157 +#define TMRXC_FOCA 0x80L +#define TMRXC_FOCB 0x40L +#define TMRXC_FOCC 0x20L + +// 16-bit timer int mask -- see datasheet 17.11.33, p. 161. +#define TMRXIM_INT_CMP_MATCH_A (1L << OCIE1A) +#define TMRXIM_INT_CMP_MATCH_B (1L << OCIE1B) +#define TMRXIM_INT_CMP_MATCH_C (1L << OCIE1C) + +// 16-bit timer all registers: +#define TMRX_CMPA_DISCONNECTED 0L +#define TMRX_CMPB_DISCONNECTED 0L +#define TMRX_CMPC_DISCONNECTED 0L +#define TMRX_INT_ON_CMPA (TMRXIM_INT_CMP_MATCH_A << TMRXIMSK_POS) + +// 16-bit timer clock modes - see Datasheet table 17-6, p. 157 +#define TMRXB_OFF 0 +#define TMRX_OFF 0 +#define TMRXB_DIV1 (0x01L << CS10) +#define TMRXB_DIV8 (0x02L << CS10) +#define TMRXB_DIV64 (0x03L << CS10) +#define TMRXB_DIV256 (0x04L << CS10) +#define TMRXB_DIV1024 (0x05L << CS10) +#define TMRXB_EXT_FALLING_EDGE (0x06L << CS10) +#define TMRXB_EXT_RISING_EDGE (0x07L << CS10) +#define TMRXB_CLK_MASK 0x07L +#define TMRX_DIV1 (TMRXB_DIV1 << TMRXB_POS) +#define TMRX_DIV8 (TMRXB_DIV8 << TMRXB_POS) +#define TMRX_DIV64 (TMRXB_DIV64 << TMRXB_POS) +#define TMRX_DIV256 (TMRXB_DIV256 << TMRXB_POS) +#define TMRX_DIV1024 (TMRXB_DIV1024 << TMRXB_POS) +#define TMRX_EXT_FALLING_EDGE (TMRXB_EXT_FALLING_EDGE << TMRXB_POS) +#define TMRX_EXT_RISING_EDGE (TMRXB_EXT_RISING_EDGE << TMRXB_POS) + +#define TMRXB_EDGE_SEL_POSITIVE (1 << ICES1) +#define TMRXB_EDGE_SEL_NEGATIVE 0L +#define TMRX_EDGE_SEL_POSITIVE (TMRXB << ICES1) +#define TMRX_EDGE_SEL_NEGATIVE 0L + +// 16-bit waveform modes (across reg A and B) Datasheet Table 17.2, p 145 +#define TMRX_WFM_NORMAL 0L +#define TMRX_WFM_PWM_PC8 (TMRXA << WGM10) // PWM Phase Correct 8-bit +#define TMRX_WFM_PWM_PC9 (TMRXA << WGM11) // PWM Phase COrrect 9-bit +#define TMRX_WFM_PWM_PC10 ((TMRXA << WGM11) | (TMRXA << WGM10)) // PWM Phase Correct 10-bit +#define TMRX_WFM_CTC (TMRXB << WGM12) // CTC +#define TMRX_WFM_PWM_FAST8 ((TMRXB << WGM12) | (TMRXA << WGM10)) // PWM Fast 8-bit +#define TMRX_WFM_PWM_FAST9 ((TMRXB << WGM12) | (TMRXA << WGM11)) // PWM Fast 9-bit +#define TMRX_WFM_PWM_FAST10 \ + ((TMRXB << WGM12) | (TMRXA << WGM11) | (TMRXA << WGM10)) // PWM Fast 10-bit +#define TMRX_WFM_PWM_PFC_ICR (TMRXB << WGM13) // PWM Phase and Freq Correct, TpOP=ICR +#define TMRX_WFM_PWM_PFC_OCRA \ + ((TMRXB << WGM13) | (TMRXA << WGM10)) // PWM Phase and Freq Correct, TOP = OCRA +#define TMRX_WFM_PWM_PC_ICR ((TMRXB << WGM13) | (TMRXA << WGM11)) // PWM PhaseCorrect, TOP = ICR +#define TMRX_WFM_PWM_PC_OCRA \ + ((TMRXB << WGM13) | (TMRXA << WGM11) | (TMRXA << WGM12)) // PWM PhaseCorrect, TOP=OCRA +#define TMRX_WFM_CTC_ICR ((TMRXB << WGM13) | (TMRXB << WGM12)) // CTC, TOP = ICR +#define TMRX_WFM_PWM_FAST_ICR \ + ((TMRXB << WGM13) | (TMRXB << WGM12) | (TMRXA << WGM11)) // PWM Fast, TOP = ICR +#define TMRX_WFM_PWM_FAST_OCRA \ + ((TMRXB << WGM13) | (TMRXB << WGM12) | (TMRXA << WGM11) \ + | (TMRXA << WGM10)) // PWM Fast, TOP = OCRA + +// USART configuration (Datasheet section 22, p. 200) +// +// Macro definitions for individual registers are named USARTA_*, +// USARTB_*, and USARTC_*. +// +// Macros for the one-step combined timer config functions are named +// USART_*. +// +// +// Examples: +// // Use USARTB_* definition to set UCSR1B register +// UCSR1B |= USARTB_DATA_REG_EMPTY_INT_EN; // enable interrupt on tx reg empty +// +// // Use USART_* definitions to configure usart with config function +// processor_usart3_config(USART_SIZE_8 | USART_PARITY_NONE | USART_STOP_1 | USART_DATA_TXEN | +// USART_DATA_RXEN | USART_RX_COMPLETE_INT_EN); +// +#define USARTA_POS 0 +#define USARTB_POS 8 +#define USARTC_POS 16 +#define USARTA (1L << USARTA_POS) +#define USARTB (1L << USARTB_POS) +#define USARTC (1L << USARTC_POS) + +// USART Register A, Datasheet 22.10.2, p. 219 + +#define USARTA_DATA_REG_EMPTY (1 << UDR0) +#define USARTA_FRAME_ERROR (1 << FE0) +#define USARTA_DATA_OVERRUN (1 << DOR0) +#define USARTA_PARITY_ERROR (1 << UPE0) +#define USARTA_DOUBLE_SPEED (1 << U2X0) +#define USARTA_MULTI_PROCESSOR (1 << MPCM0) +#define USART_DATA_REG_EMPTY (USARTA << UDR0) +#define USART_FRAME_ERROR (USARTA << FE0) +#define USART_DATA_OVERRUN (USARTA << DOR0) +#define USART_PARITY_ERROR (USARTA << UPE0) +#define USART_DOUBLE_SPEED (USARTA << U2X0) +#define USART_MULTI_PROCESSOR (USARTA << MPCM0) + +// USART Register B, Datasheet 22.10.3, p. 220 + +#define USARTB_RX_COMPLETE_INT_EN (1 << RXCIE0) +#define USARTB_TX_COMPLETE_INT_EN (1 << TXCIE0) +#define USARTB_DATA_REG_EMPTY_INT_EN (1 << UDRIE0) +#define USARTB_DATA_RXEN (1 << RXEN0) +#define USARTB_DATA_TXEN (1 << TXEN0) +#define USARTB_SIZE_9 (1 << UCSZ02) +#define USARTB_RX_BIT_8 (1 << RXB80) +#define USARTB_TX_BIT_8 (1 << TXB80) +#define USART_RX_COMPLETE_INT_EN (USARTB << RXCIE0) +#define USART_TX_COMPLETE_INT_EN (USARTB << TXCIE0) +#define USART_DATA_REG_EMPTY_INT_EN (USARTB << UDRIE0) +#define USART_DATA_RXEN (USARTB << RXEN0) +#define USART_DATA_TXEN (USARTB << TXEN0) +#define USART_RX_BIT_8 (USARTB << RXB80) +#define USART_TX_BIT_8 (USARTB << TXB80) + +// USART Register C, Datasheet 22.10.4, p.221 +#define USARTC_MODE_ASYNC_USART (0x00L << UMSEL00) +#define USARTC_MODE_SYNC_USART (0x01L << UMSEL00) +#define USARTC_MODE_MSPIM (0x03L << UMSEL00) +#define USART_MODE_ASYNC_USART (USARTC_MODE_ASYNC_USART << USARTC_POS) +#define USART_MODE_SYNC_USART (USARTC_MODE_SYNC_USART << USARTC_POS) +#define USART_MODE_MSPIM (USARTC_MODE_MSPIM << USARTC_POS) + +#define USARTC_PARITY_NONE 0 +#define USARTC_PARITY_EVEN (0x01L << UPM00) +#define USARTC_PARITY_ODD (0x03 << UPM00) +#define USART_PARITY_NONE 0 +#define USART_PARITY_EVEN (USARTC_PARITY_EVEN << USARTC_POS) +#define USART_PARITY_ODD (USARTC_PARITY_ODD << USARTC_POS) + +#define USARTC_STOP_1 0 +#define USARTC_STOP_2 (1 << USBS0) +#define USART_STOP_1 0 +#define USART_STOP_2 (USARTC << USBS0) + +#define USARTC_SIZE_5 0 +#define USARTC_SIZE_6 (0x01L << UCSZ00) +#define USARTC_SIZE_7 (0x02L << UCSZ00) +#define USARTC_SIZE_8 (0x03L << UCSZ00) +#define USARTC_SIZE_9 USARTC_SIZE_8 +#define USART_SIZE_5 0 +#define USART_SIZE_6 (USARTC_SIZE_6 << USARTC_POS) +#define USART_SIZE_7 (USARTC_SIZE_7 << USARTC_POS) +#define USART_SIZE_8 (USARTC_SIZE_8 << USARTC_POS) +#define USART_SIZE_9 ((USARTB_SIZE_9 << USARTB_POS) | (USARTC_SIZE_9 << USARTC_POS)) + +#define USARTC_CLK_TX_RISING 0 +#define USART_CLK_TX_RISING 0 +#define USARTC_CLK_TX_FALLING (1 << UCPOL0) +#define USART_CLK_TX_FALLING (USARTC << UCPOL0) + + + +// I/O port definitions: + +#define PIN_INPUT 0 +#define PIN_OUTPUT 1 +#define ALL_INPUTS 0 +#define ALL_OUTPUTS 0xff +#define ALL_PULLUPS 0xff + +#define ASDF_HIROW_PORT PORTA +#define ASDF_HIROW_DDR DDRA +#define ASDF_HIROW_PIN PINA + +#define ASDF_LOROW_PORT PORTJ +#define ASDF_LOROW_DDR DDRJ +#define ASDF_LOROW_PIN PINJ + +#define ASDF_COLUMNS_PORT PORTC +#define ASDF_COLUMNS_PIN PINC +#define ASDF_COLUMNS_DDR DDRC + +#define ASDF_ASCII_PORT PORTH +#define ASDF_ASCII_DDR DDRH + +#define ASDF_LED1_PORT PORTD +#define ASDF_LED1_DDR DDRD +#define ASDF_LED1_BIT 5 + +#define ASDF_LED2_PORT PORTD +#define ASDF_LED2_DDR DDRD +#define ASDF_LED2_BIT 6 + +#define ASDF_LED3_PORT PORTD +#define ASDF_LED3_DDR DDRD +#define ASDF_LED3_BIT 7 + +#define ASDF_OUT1_PORT PORTB +#define ASDF_OUT1_PIN PINB +#define ASDF_OUT1_DDR DDRB +#define ASDF_OUT1_BIT 5 + +#define ASDF_OUT2_PORT PORTB +#define ASDF_OUT2_PIN PINB +#define ASDF_OUT2_DDR DDRB +#define ASDF_OUT2_BIT 6 + +#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 +#define ASDF_STROBE_DDR DDRB +#define ASDF_STROBE_BIT 4 + +#define ASDF_OSI_KBE_PORT ASDF_HIROW_PORT +#define ASDF_OSI_KBE_DDR ASDF_HIROW_DDR +#define ASDF_OSI_KBE_BIT 1 + +#define ASDF_OSI_RW_PORT ASDF_HIROW_PORT +#define ASDF_OSI_RW_DDR ASDF_HIROW_DDR +#define ASDF_OSI_RW_BIT 2 + +#define ASDF_ARCH_DIP_SWITCH_ROW 8 + +#define FUSE_INTERNAL_8MHZ_OSC_4MS (FUSE_CKSEL1 | FUSE_SUT0) +#define FUSE_INTERNAL_8MHZ_OSC_65MS (FUSE_CKSEL1 | FUSE_SUT1) +#define FUSE_XTAL_16MHZ_4MS (FUSE_CKSEL2 | FUSE_CKSEL1 | CKSEL0 | FUSE_SUT1) +#define FUSE_XTAL_16MHZ_65MS (FUSE_CKSEL2 | FUSE_CKSEL1 | CKSEL0 | FUSE_SUT1 | FUSE_SUT0) +#define FLASH PROGMEM + +// not implemented with do-while(0) because this is a function call that returns +// a value, and parameters are expanded inside the parameter list, so this will +// be valid when substituting for function-like syntax. +#define FLASH_READ (a) pgm_read_byte((a)) +#define FLASH_READ_MATRIX_ELEMENT(matrix, row, col) pgm_read_byte(&((matrix)[(row)][(col)])) + +// For 1 ms tick, (16000000 / 64(prescale)) / 1000(usec) - 1 = 249 +#define TICK_COUNT 249 + +// Default key matrix row scanner +#define ASDF_ARCH_DEFAULT_SCANNER asdf_arch_read_row + +// Default keyboard output +#define ASDF_ARCH_DEFAULT_OUTPUT asdf_arch_send_code + +// DIP switch is on row 8 +#define ASDF_ARCH_DIPSWITCH_ROW 8 + +// 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 +// 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_open_hi_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_open_hi_set(uint8_t value); + +// PROCEDURE: asdf_arch_out1_open_lo_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_open_lo_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_open_hi_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_open_hi_set(uint8_t value); + +// PROCEDURE: asdf_arch_out2_open_lo_set +// INPUTS: (uint8_t) value +// OUTPUTS: none +// DESCRIPTION: Sets the OUT2 bit to high if value is true, and hi-z if value is false. +void asdf_arch_out2_open_lo_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_open_hi_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_open_hi_set(uint8_t value); + +// PROCEDURE: asdf_arch_out3_open_lo_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_open_lo_set(uint8_t value); + +// 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); + +// PROCEDURE: asdf_arch_pulse_delay_short +// INPUTS: none +// OUTPUTS: none +// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by +// ASDF_PULSE_DELAY_SHORT_US +void asdf_arch_pulse_delay_short(void); + + +// PROCEDURE: asdf_arch_pulse_delay_long +// INPUTS: none +// OUTPUTS: none +// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by +// ASDF_PULSE_DELAY_LONG_MS +void asdf_arch_pulse_delay_long(void); + + +// PROCEDURE: asdf_arch_tick +// INPUTS: none +// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise +uint8_t asdf_arch_tick(void); + +// PROCEDURE: asdf_arch_send_code +// INPUTS: (keycode_t) code - the code to be output by the keyboard +// OUTPUTS: none +// DESCRIPTION: Takes a character code and outputs the code on a parallel ASCII +// port, with a strobe. This routine could be replaced with UART, I2C, USB, or +// other output mechanism, of course. +void asdf_arch_send_code(asdf_keycode_t code); + +// PROCEDURE: asdf_arch_init +// INPUTS: none +// OUTPUTS: none +// DESCRIPTION: sets up all the hardware for the keyboard +void asdf_arch_init(void); + +#endif /* !defined (ASDF_ARCH_H) */ + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor. diff --git a/firmware/asdf/src/asdf_keymap_defs.h b/firmware/asdf/src/asdf_keymap_defs.h new file mode 100644 index 0000000..04c40f8 --- /dev/null +++ b/firmware/asdf/src/asdf_keymap_defs.h @@ -0,0 +1,72 @@ +// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*- +// +// Unfified Keyboard Project +// ASDF keyboard firmware +// +// asdf_keymap_defs.h +// +// gathers up all the keymap definitions to be included in the firmware. +// +// 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 . + +// While there is nothing preventing a standard keyboard from having both a +// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For +// testing, both must be present to test their functionality. + +#if !defined(ASDF_KEYMAP_DEFS_H) +#define ASDF_KEYMAP_DEFS_H + +#include "asdf.h" +#include "asdf_arch.h" +#include "asdf_ascii.h" +#include "asdf_physical.h" +#include "asdf_virtual.h" +#include "asdf_modifiers.h" + +#include "Keymaps/asdf_keymap_defs_ascii.h" +#include "Keymaps/asdf_keymap_defs_apple2.h" +#include "Keymaps/asdf_keymap_defs_sol.h" + +#define ASDF_NUM_KEYMAPS \ + (ASDF_SOL_ALL_MAPS_COUNT) + +#define ASDF_KEYMAP_DEFS \ + { \ + ASDF_SOL_ALL_MAPS \ + } + +#define ASDF_KEYMAP_DECLARATIONS \ + ASDF_SOL_MAP_DECLARATIONS + +#define ASDF_KEYMAP_INITIALIZERS \ + { \ + ASDF_SOL_KEYMAP_INITIALIZER \ + } + +#define ASDF_KEYMAP_HOOK_INITIALIZERS \ + { \ + ASDF_SOL_KEYMAP_HOOK_INITIALIZER \ + } + +typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; + +typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS]; + + +#endif /* !defined (ASDF_KEYMAP_DEFS_H) */ + +//-------|---------|---------+---------+---------+---------+---------+---------+ +// Above line is 80 columns, and should display completely in the editor.