mirror of
https://github.com/osiweb/unified_retro_keyboard.git
synced 2024-12-12 15:29:18 +00:00
More gitignore updates
This commit is contained in:
parent
3ddca77b42
commit
27b151964a
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,2 +1,10 @@
|
||||
.DS_Store
|
||||
*scratch*
|
||||
*.bak
|
||||
*.sch-bak
|
||||
*-cache.lib
|
||||
*.kicad_pcb-bak
|
||||
fp-lib-table
|
||||
fp-info-cache
|
||||
*.o
|
||||
*-rescue.lib
|
||||
|
834
firmware/asdf/src/asdf_arch.c
Normal file
834
firmware/asdf/src/asdf_arch.c
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
// 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 <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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.
|
||||
//
|
486
firmware/asdf/src/asdf_arch.h
Normal file
486
firmware/asdf/src/asdf_arch.h
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
#if !defined(ASDF_ARCH_H)
|
||||
#define ASDF_ARCH_H
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#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.
|
72
firmware/asdf/src/asdf_keymap_defs.h
Normal file
72
firmware/asdf/src/asdf_keymap_defs.h
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
// 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.
|
Loading…
Reference in New Issue
Block a user