first commit

This commit is contained in:
Dave 2019-12-12 14:46:29 -06:00
commit 784805adc7
80 changed files with 33351 additions and 0 deletions

26
README.md Normal file
View File

@ -0,0 +1,26 @@
## Universal ASCII Keyboard
This project aims to provide a (near) universal ASCII keyboard for vintage computers. Home computers of the 1970's typically either polled a switch matrix, or interfaced to a parallel ASCII keyboard via a parallel port.
The keyboard will allow use of Cherry MX keys, or Futaba MD-4PCS keys.
The keyboard supports diodes per-switch for true N-key rollover, or
per-row (like the OSI).
The keyboard is designed using KiCad in order to be the most useful for anybody wishing to modify the keyboard for more specific uses, or to add to the project.
Goals for the keyboard:
- Drop in replacement for Ohio Scientific polled keyboards
-- Done: drop in for OSI 542 (untested).
-- Done: keycap set available
-- To do: module for advanced 542B/C features
- Drop in replacement for Apple II keyboard
--To do: Add-in ASCII module required
--To do: Add power light and power light cover
--To do: Special Apple keycaps needed.
- Standard ASCII parallel keyboard
-- Done: Keycap set available
-- To do: Add-in ASCII keyboard

126
firmware/asdf/README.md Normal file
View File

@ -0,0 +1,126 @@
-*- text -*-
- asdf Keyboard scanning firmware
The ASDF (Auto Scan by DF) firmware is a key matrix scanner that can detect and
debounce keypress and release events on a key matrix and either send codes or
perform actions on keypress or release. Keymaps are defined per application and
may, for example, generate ASCII codes, special keyscan codes, etc. The code is
modular and may be integrated into a larger system easily.
By default, the code supports any number of rows by 8 columns, which will give
the bestperformance on an 8-bit microcontroller. For more than 8 columns per
row, the row datatype would need to be changed to uint16_t to support 16
columns, etc.
The first supported application is a parallel ASCII output keyboard. If you want
serial or USB output, you can supply your own routines.
ASDF supports basic keyboard functionality and is configurable via a few
boolean variables, and via the key maps. The key maps are organized in
row,column format, with separate keymaps shift, capslock, and control-key modes.
Features:
* modifiers: A set of modifier keys may be specified. When only a few modifiers
are used, this mechanism is a low-overhead alternative to a keymap overlay for
keyboard states that only change the key value, such as SHIFT, CAPS LOCK, CONTROL,
etc. The state of each modifier key is kept in a state variable. In most
cases, pressing the key will set the value to a "pressed" state, and releasing
will reset the value to an "unpressed" state. However some functions interact.
For example, Shift Lock is sticky, so pressing Shift Lock toggles the Shift
Lock state, and Releasing Shift Lock does nothing; but pressing "Shift" will
reset the "Shift Lock" state.
All modifier state variables are kept in a modifier state variable array. On a
regular keypress, all of the modifier state variables are OR'ed together to
produce an index into a value array for the standard key, to determine the
value sent by the standard keypress.
* DIP switches: DIP switches are implemented by adding them into the key
matrix, and providing activate() and deactivate() functions for the on and off
positions.
* Spinners/rotary encoders: Rotary encoders can be implemented by adding the
encoder switches into the matrix, and driving the encoder state machine via
the activate() and deactivate() functions.
* sticky keys: Stick keys remain active until another key is pressed. This
functionality is supported by the per-key activate() and deactivate() functions.
For example, for sticky "control", replace control_deactivate() with
null_deactivate() as the deactivate function for the control key, and add a
call to "control_deactivate()" in the "standard_keypress_postprocess_hook()" function.
* Indicators: Controlled via activate() and deactivate() functions for the various keys.
* Debounce and Repeat functions: The main keyscan logic implements key
debouncing. Multiple keys may be debounced simultaneously using a separate
debounce counter for each key in the matrix.
* Repeat key and Autorepeat: This is provided by the repeat module. Autorepeat
may be disabled or enabled either by configuration, by activate()/deactivate()
functions, or other keyboard logic. Repeat and autorepeat only apply to the
most recently pressed key.
* (Future feature) NVRAM: For architectures that support EEPROM or other non-volatile storage,
configuration parameters are stored in non-volatile storage to survive a power
cycle.
* ASCII output - supported via output_value function.
* (Future feature) Serial, USB CDC, USB HID interfaces - supportable via output_value function.
* Indicator LEDs and other direct logic-level hardware controls: supported via
per-key activate/deactivate functions, and also via hooks to standard key
functions.
Compiling and configuration
The source files are in the ./src directory. The final build files go in the ./build directory.
To build, enter the ./src directory. You should be able to build a binary and
hex file suitable for programming a microcontroller by typing "Make". You may
edit the Makefile to specify your target platform (default is Atmega328P ASCII
controller). You may also wish to edit your preferences in "asdf_config.h" to
specify repeat timings, optimize the debounce setting (if you have very bounce
keys), and specify the character output buffer size (if you are implementing
macros, etc.)
Porting
This firmware was written in modular, portable C99, to be compiled with GCC
(avr-gcc for the Atmega). The hardware-sepecific files are in Arch/*.[ch]. To
adapt the Atmega port for additional hardware, enter the ./src/Arch directory,
and copy the files asdf_arch_atmega328p.c and asdf_arch_astmega328p.h to new
filenames, and edit them to suit the hardware changes.
The firmware is designed to run from ROM on a slow vintage processor, with a
small RAM footprint, and is not re-entrant. It is designed to compile on small
architectures, or to be hand-translated to assembly on small processors, or to
an HDL for a CPLD or FPGA.
The code was written to favor readability over cleverness. While tempted to
optimize bit testing via bithacks, I opted for code simplicity since the
performance benefit was not there for 8-bit values.
To port to a new processor architecture, you may use the atmega328p files as an
example, and create a pair of architecture-specific .c and .h files for the new
hardware, exporting the following functions:
- asdf_arch_init: initializes the CPU and hardware
- asdf_arch_read_row: given a row number, output the row to the matrix, and read
all the columns on that row asdf_arch_send_code
- asdf_arch_send_code: given a key code, output the code to the computer, via
serial, parallel, I2C, whatever is appropriate.
- asdf_arch_tick: true once every 1ms. This tests a flag set in an interrupt
routine that is triggered every 1ms. The function return value is polled and a
keyscan initiated when true. An alternative, if you have an RTOS, or even just
a scheduler, would be to schedule the keyscan every 1 ms, rather than poll. In
that case, this function is not needed, and the "superloop" in main.c would
contain a call to the scheduler.

View File

@ -0,0 +1 @@
This directory contains the files resulting from the build process

View File

@ -0,0 +1,448 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal 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 <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
#include "asdf_arch.h"
static volatile uint8_t tick = 0;
static uint8_t data_polarity = 0; // normally positive polarity
static uint8_t strobe_polarity = 0; // normally positive 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_special_outputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up special output lines for LED indicator(s), System RESET
// and SCREEN CLEAR, etc.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_special_outputs(void)
{
// initialize CAPS LED to OFF
clear_bit(&ASDF_CAPS_LED_PORT, ASDF_CAPS_LED_BIT);
set_bit(&ASDF_CAPS_LED_DDR, ASDF_CAPS_LED_BIT);
// initialize SCREEN_CLEAR output line to LOW (inactive)
clear_bit(&ASDF_SCREEN_CLEAR_PORT, ASDF_SCREEN_CLEAR_BIT);
set_bit(&ASDF_SCREEN_CLEAR_DDR, ASDF_SCREEN_CLEAR_BIT);
// initialize /SYS_RESET output line to HIGH (inactive)
set_bit(&ASDF_SYS_RESET_PORT, ASDF_SYS_RESET_BIT);
set_bit(&ASDF_SYS_RESET_DDR, ASDF_SYS_RESET_BIT);
// initialize /STROBE output to inactive. Must test before set/clear to avoid spurious strobe
if (strobe_polarity) {
set_bit(&ASDF_STROBE_PORT, ASDF_STROBE_BIT);
}
else {
clear_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 = 0;
ASDF_ASCII_DDR = ALL_OUTPUTS;
}
// PROCEDURE: asdf_arch_init_column_inputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: configure the shift register control lines. The MODE control is
// LOW for shift and HIGH for load. Shift or Load occurs when CLK goes high.
//
// SIDE EFFECTS: Cont
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_column_control(void)
{
// COLCLK is output and initialized LOW
clear_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
set_bit(&ASDF_COLCLK_DDR, ASDF_COLCLK_BIT);
// COLMODE is output and initialized HIGH
set_bit(&ASDF_COLMODE_PORT, ASDF_COLMODE_BIT);
set_bit(&ASDF_COLMODE_DDR, ASDF_COLMODE_BIT);
// COL is input, no weak pullup.
clear_bit(&ASDF_COL_DDR, ASDF_COL_BIT);
clear_bit(&ASDF_COL_PORT, ASDF_COL_BIT);
}
// 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_ROW_PORT &= ~ASDF_ROW_MASK;
ASDF_ROW_DDR |= ASDF_ROW_MASK;
}
// 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 = 0;
strobe_polarity = 0;
// set up strobe output
// set up indicator output
// set up RESET output
// set up CLEAR output
asdf_arch_init_special_outputs();
// 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_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.
//
// 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_read_row(uint8_t row)
{
asdf_cols_t cols = 0;
// first, output the new row value:
ASDF_ROW_PORT = (ASDF_ROW_PORT & ~ASDF_ROW_MASK) | row << ASDF_ROW_OFFSET;
// read in the columns. Set LOAD mode and pulse clock.
clear_bit(&ASDF_COLMODE_PORT, ASDF_COLMODE_BIT);
set_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
clear_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
// set back to SHIFT mode
set_bit(&ASDF_COLMODE_PORT, ASDF_COLMODE_BIT);
// After the load operation, the LSB is already at the output pin, so there
// will be one fewer read than clock pulse. Continue reading the bits until
// the leader bit is in the boundary position.
for (uint8_t i = 0; i < ASDF_NUM_COLS; i++) {
// invert the bits as they are read (see note 1)
cols |= (((~(ASDF_COL_PIN) >> ASDF_COL_BIT) & 1) << i);
set_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
clear_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
}
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_PINS, ASDF_STROBE_BIT);
_delay_us(ASDF_STROBE_LENGTH_US);
set_bit(&ASDF_STROBE_PINS, ASDF_STROBE_BIT);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.
//

View File

@ -0,0 +1,267 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch_atmega328p.h
//
// Contains architecture-specific definitions for the atmega 328p.
//
//
// 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 ASDF_STROBE_LENGTH_US 10 // strobe length in microseconds
// 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)
// 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 timer 1. ATmega328P datasheet section 15, p. 108
//
// 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 TMR1A_*,
// TMR1B_*, and TMR1C_*.
//
// Macros for the one-step combined timer config functions are named
// TMR1_*.
//
//
// Examples:
// // Use TMR1B_* definition to set TCCR1B register
// TCCR1B |= TMR1B_DIV1;
//
// // Use TMR1_* definitions to configure timer with config function
// timer1_config(TMR1_WFM_CTC | TMR1_INT_ON_CMPA);
//
#define TMR1A_POS 0
#define TMR1B_POS 8
#define TMR1C_POS 16
#define TMR1IMSK_POS 24
#define TMR1A (1L << TMR1A_POS)
#define TMR1B (1L << TMR1B_POS)
#define TMR1C (1L << TMR1C_POS)
#define TMR1IMSK (1L << TMR1IMSK_POS)
// 16-bit timer reg A - Datasheet 17.11.1, p. 154
#define TMR1A_CMPA_CLR_MATCH_SET_BOTTOM (1 << COM1A1)
#define TMR1A_CMPB_CLR_MATCH_SET_BOTTOM (1 << COM1B1)
#define TMR1A_CMPC_CLR_MATCH_SET_BOTTOM (1 << COM1C1)
#define TMR1_CMPA_CLR_MATCH_SET_BOTTOM (TMR1A << COM1A1)
#define TMR1_CMPB_CLR_MATCH_SET_BOTTOM (TMR1A << COM1B1)
#define TMR1_CMPC_CLR_MATCH_SET_BOTTOM (TMR1A << COM1C1)
// 16-bit timer reg B - Datasheet 17.11.6, p. 156
#define TMR1B_IN_CAP_POS 0x40L
#define TMR1B_IN_CAP_NEG 0L
#define TMR1B_IN_CAP_NOISE_CANCEL 0x80L
// 16-bit timer reg C -- see datasheet, 17.11.9, p. 157
#define TMR1C_FOCA 0x80L
#define TMR1C_FOCB 0x40L
#define TMR1C_FOCC 0x20L
// 16-bit timer int mask -- see datasheet 17.11.33, p. 161.
#define TMR1IM_INT_CMP_MATCH_A (1L << OCIE1A)
#define TMR1IM_INT_CMP_MATCH_B (1L << OCIE1B)
#define TMR1IM_INT_CMP_MATCH_C (1L << OCIE1C)
// 16-bit timer all registers:
#define TMR1_CMPA_DISCONNECTED 0L
#define TMR1_CMPB_DISCONNECTED 0L
#define TMR1_CMPC_DISCONNECTED 0L
#define TMR1_INT_ON_CMPA (TMR1IM_INT_CMP_MATCH_A << TMR1IMSK_POS)
// 16-bit timer clock modes - see Datasheet table 17-6, p. 157
#define TMR1B_OFF 0
#define TMR1_OFF 0
#define TMR1B_DIV1 (0x01L << CS10)
#define TMR1B_DIV8 (0x02L << CS10)
#define TMR1B_DIV64 (0x03L << CS10)
#define TMR1B_DIV256 (0x04L << CS10)
#define TMR1B_DIV1024 (0x05L << CS10)
#define TMR1B_EXT_FALLING_EDGE (0x06L << CS10)
#define TMR1B_EXT_RISING_EDGE (0x07L << CS10)
#define TMR1B_CLK_MASK 0x07L
#define TMR1_DIV1 (TMR1B_DIV1 << TMR1B_POS)
#define TMR1_DIV8 (TMR1B_DIV8 << TMR1B_POS)
#define TMR1_DIV64 (TMR1B_DIV64 << TMR1B_POS)
#define TMR1_DIV256 (TMR1B_DIV256 << TMR1B_POS)
#define TMR1_DIV1024 (TMR1B_DIV1024 << TMR1B_POS)
#define TMR1_EXT_FALLING_EDGE (TMR1B_EXT_FALLING_EDGE << TMR1B_POS)
#define TMR1_EXT_RISING_EDGE (TMR1B_EXT_RISING_EDGE << TMR1B_POS)
#define TMR1B_EDGE_SEL_POSITIVE (1 << ICES1)
#define TMR1B_EDGE_SEL_NEGATIVE 0L
#define TMR1_EDGE_SEL_POSITIVE (TMR1B << ICES1)
#define TMR1_EDGE_SEL_NEGATIVE 0L
// 16-bit waveform modes (across reg A and B) Datasheet Table 17.2, p 145
#define TMR1_WFM_NORMAL 0L
#define TMR1_WFM_PWM_PC8 (TMR1A << WGM10) // PWM Phase Correct 8-bit
#define TMR1_WFM_PWM_PC9 (TMR1A << WGM11) // PWM Phase COrrect 9-bit
#define TMR1_WFM_PWM_PC10 ((TMR1A << WGM11) | (TMR1A << WGM10)) // PWM Phase Correct 10-bit
#define TMR1_WFM_CTC (TMR1B << WGM12) // CTC
#define TMR1_WFM_PWM_FAST8 ((TMR1B << WGM12) | (TMR1A << WGM10)) // PWM Fast 8-bit
#define TMR1_WFM_PWM_FAST9 ((TMR1B << WGM12) | (TMR1A << WGM11)) // PWM Fast 9-bit
#define TMR1_WFM_PWM_FAST10 \
((TMR1B << WGM12) | (TMR1A << WGM11) | (TMR1A << WGM10)) // PWM Fast 10-bit
#define TMR1_WFM_PWM_PFC_ICR (TMR1B << WGM13) // PWM Phase and Freq Correct, TpOP=ICR
#define TMR1_WFM_PWM_PFC_OCRA \
((TMR1B << WGM13) | (TMR1A << WGM10)) // PWM Phase and Freq Correct, TOP = OCRA
#define TMR1_WFM_PWM_PC_ICR ((TMR1B << WGM13) | (TMR1A << WGM11)) // PWM PhaseCorrect, TOP = ICR
#define TMR1_WFM_PWM_PC_OCRA \
((TMR1B << WGM13) | (TMR1A << WGM11) | (TMR1A << WGM12)) // PWM PhaseCorrect, TOP=OCRA
#define TMR1_WFM_CTC_ICR ((TMR1B << WGM13) | (TMR1B << WGM12)) // CTC, TOP = ICR
#define TMR1_WFM_PWM_FAST_ICR \
((TMR1B << WGM13) | (TMR1B << WGM12) | (TMR1A << WGM11)) // PWM Fast, TOP = ICR
#define TMR1_WFM_PWM_FAST_OCRA \
((TMR1B << WGM13) | (TMR1B << WGM12) | (TMR1A << WGM11) \
| (TMR1A << WGM10)) // PWM Fast, TOP = OCRA
// I/O port definitions:
#define PIN_INPUT 0
#define PIN_OUTPUT 1
#define ALL_INPUTS 0
#define ALL_OUTPUTS 0xff
#define ASDF_ROW_PORT PORTC
#define ASDF_ROW_DDR DDRC
#define ASDF_ROW_MASK 0x07
#define ASDF_ROW_OFFSET 0
#define ASDF_COL_PORT PORTB
#define ASDF_COL_PIN PINB
#define ASDF_COL_DDR DDRB
#define ASDF_COL_BIT 0
#define ASDF_COL_PULLUPS 0 // disable weak pullup
#define ASDF_COLCLK_PORT PORTB
#define ASDF_COLCLK_PINS PINB
#define ASDF_COLCLK_DDR DDRB
#define ASDF_COLCLK_BIT 2
#define ASDF_COLMODE_PORT PORTB
#define ASDF_COLMODE_PINS PINB
#define ASDF_COLMODE_DDR DDRB
#define ASDF_COLMODE_BIT 1
#define ASDF_ASCII_PORT PORTD
#define ASDF_ASCII_DDR DDRD
#define ASDF_CAPS_LED_PORT PORTC
#define ASDF_CAPS_LED_DDR DDRC
#define ASDF_CAPS_LED_BIT 3
#define ASDF_SCREEN_CLEAR_PORT PORTC
#define ASDF_SCREEN_CLEAR_DDR DDRC
#define ASDF_SCREEN_CLEAR_BIT 4
#define ASDF_SYS_RESET_PORT PORTC
#define ASDF_SYS_RESET_DDR DDRC
#define ASDF_SYS_RESET_BIT 5
#define ASDF_STROBE_PORT PORTB
#define ASDF_STROBE_PINS PINB
#define ASDF_STROBE_DDR DDRB
#define ASDF_STROBE_BIT 6
#define FUSE_INTERNAL_8MHZ_OSC_0MS (FUSE_CKSEL0 | FUSE_CKSEL2 | FUSE_CKSEL3 | FUSE_SUT0 | FUSE_SUT1)
#define FUSE_INTERNAL_8MHZ_OSC_4MS (FUSE_CKSEL0 | FUSE_CKSEL2 | FUSE_CKSEL3 | FUSE_SUT1)
#define FUSE_INTERNAL_8MHZ_OSC_65MS (FUSE_CKSEL0 | FUSE_CKSEL2 | FUSE_CKSEL3 | 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, (8000000 / 64(prescale)) / 1000(usec) - 1 = 124
#define TICK_COUNT 124
// 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_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.

View File

@ -0,0 +1,43 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch_test.h
//
// Architecture-dependent definitions for the unit-testing ASDF software.
//
// 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
#define FLASH
#define FLASH_READ (a) (*(a))
#define FLASH_READ_MATRIX_ELEMENT(mat,row,col) (mat)[(row)][(col)]
void asdf_arch_init(void);
void asdf_arch_tick(void);
uint8_t asdf_arch_read_row(uint8_t row);
#endif // !defined (ASDF_ARCH_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,128 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps.h
//
// 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_KEYMAPS_H)
#define ASDF_KEYMAPS_H
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_modifiers.h"
#define ASCII_PLAIN_MAP \
{ \
{ ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ASCII_DEL, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \
{ ACTION_BREAK, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \
{ ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \
{ ACTION_CLEAR, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, { ACTION_REPEAT, \
ACTION_HERE_IS, \
ACTION_SHIFT_LOCK, \
ASCII_CR, \
ASCII_LF, \
'o', \
'l', \
ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ \
ASCII_AT, '7', '6', '5', '4', '3', '2', '1' \
} \
}
#define ASCII_CAPS_MAP \
{ \
{ ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ASCII_DEL, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_BREAK, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_CLEAR, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, { ACTION_REPEAT, \
ACTION_HERE_IS, \
ACTION_SHIFT_LOCK, \
ASCII_CR, \
ASCII_LF, \
'O', \
'L', \
ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ \
ASCII_AT, '7', '6', '5', '4', '3', '2', '1' \
} \
}
#define ASCII_SHIFT_MAP \
{ \
{ ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \
{ ASCII_DEL, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_BREAK, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_CLEAR, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFT_LOCK, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \
{ ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \
'0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \
{ \
ASCII_GRAVE_ACCENT, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' \
} \
}
#define ASCII_CTRL_MAP \
{ \
{ ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \
{ ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \
ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \
{ ACTION_BREAK, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \
ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \
{ ACTION_CLEAR, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \
ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFT_LOCK, ASCII_CR, \
ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \
{ ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \
ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \
{ \
ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, ACTION_FN_4, ACTION_FN_3, \
ACTION_FN_2, ACTION_FN_2 \
} \
}
// PROCEDURE: asdf_keymaps_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Assigns the keymaps to the indices specified by the modifier
// index, to avoid hard-coding constant index values.
void asdf_keymaps_init(void);
// PROCEDURE: asdf_keymaps_get_code
// INPUTS: row, col: row and column of key that has been pressed
// modifiers_index: index into the keymap array, based on modifier state
// OUTPUTS: returns a key code.
// DESCRIPTION: Given a key row and column, and an index based on modifier
// state, return the appropriate keycode.
asdf_keycode_t asdf_keymaps_get_code(uint8_t row, uint8_t col, uint8_t modifier_index);
#endif /* !defined (ASDF_KEYMAPS_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,131 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps.h
//
// 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_KEYMAPS_H)
#define ASDF_KEYMAPS_H
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_modifiers.h"
#define ASCII_PLAIN_MAP \
{ \
{ ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \
{ ACTION_BREAK, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \
{ ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \
{ ACTION_CLEAR, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, { ACTION_REPEAT, \
ACTION_HERE_IS, \
ACTION_SHIFT_LOCK, \
ASCII_CR, \
ASCII_LF, \
'o', \
'l', \
ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ \
ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' \
} \
}
#define ASCII_CAPS_MAP \
{ \
{ ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_BREAK, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_CLEAR, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, { ACTION_REPEAT, \
ACTION_HERE_IS, \
ACTION_SHIFT_LOCK, \
ASCII_CR, \
ASCII_LF, \
'O', \
'L', \
ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ \
ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' \
} \
}
#define ASCII_SHIFT_MAP \
{ \
{ ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \
{ ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_BREAK, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_CLEAR, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFT_LOCK, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \
{ ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \
'0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \
{ \
ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' \
} \
}
#define ASCII_CTRL_MAP \
{ \
{ ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \
{ ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \
ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \
{ ACTION_BREAK, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \
ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \
{ ACTION_CLEAR, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \
ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFT_LOCK, ASCII_CR, \
ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \
{ ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \
ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \
{ \
ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, ACTION_FN_4, ACTION_FN_3, \
ACTION_FN_2, ACTION_FN_2 \
} \
}
// PROCEDURE: asdf_keymaps_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Assigns the keymaps to the indices specified by the modifier
// index, to avoid hard-coding constant index values.
void asdf_keymaps_init(void);
// PROCEDURE: asdf_keymaps_get_code
// INPUTS: row, col: row and column of key that has been pressed
// modifiers_index: index into the keymap array, based on modifier state
// OUTPUTS: returns a key code.
// DESCRIPTION: Given a key row and column, and an index based on modifier
// state, return the appropriate keycode.
asdf_keycode_t asdf_keymaps_get_code(uint8_t row, uint8_t col, uint8_t modifier_index);
#endif /* !defined (ASDF_KEYMAPS_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,21 @@
ARCH ?= atmega328p
KEYMAP ?= ascii
BUILD_DIR = ../build
all: app
app:
make -f Makefile.app
test:
make -f Makefile.test
clean:
make -f Makefile.app clean
make -f Makefile.test clean
cleanall:
make -f Makefile.app cleanall
make -f Makefile.test cleanall

View File

@ -0,0 +1,157 @@
ARCH ?= atmega328p
KEYMAP ?= ascii
ARCH_TOKEN = _Arch_$(ARCH)
TARGET = asdf
TEST_DIR = ../test
UNITY_DIR = $(TEST_DIR)/unity
BUILD_DIR = ../build
DEP_DIR := ./.deps
TARGET_BIN := $(BUILD_DIR)/$(TARGET).elf
TARGET_HEX := $(BUILD_DIR)/$(TARGET).hex
TARGET_MAP := $(BUILD_DIR)/$(TARGET).map
UNITY_SCRIPTS = $(UNITY_DIR)/auto
ARCH_DIR = Arch
KEYMAPS_DIR = Keymaps
VERSION =
RELEASE=
SIZE_COMMAND = avr-size
CLOCK = 8000000L
CLEAN_FILES =
CLEANALL_FILES =
CC = avr-gcc
CFLAGS = -std=c99
CFLAGS += -Wall
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -O2
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -Wpointer-arith
CFLAGS += -Wcast-align
CFLAGS += -Wwrite-strings
CFLAGS += -Wswitch-default
CFLAGS += -Wunreachable-code
CFLAGS += -Winit-self
CFLAGS += -Wmissing-field-initializers
CFLAGS += -Wno-unknown-pragmas
CFLAGS += -Wstrict-prototypes
CFLAGS += -Wundef
CFLAGS += -Wold-style-definition
CFLAGS += -mmcu=$(ARCH)
CFLAGS += -DF_CPU=$(CLOCK)
LDFLAGS = -Wl,-Map=$(TARGET_MAP)
LDFLAGS += -Wl,--start-group
LDFLAGS += -Wl,-lm
LDFLAGS += -Wl,--end-group
LDFLAGS += -Wl,--gc-sections
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
MAKEDEPEND = $(CPP) $(DEPFLAGS) $(CPPFLAGS) $< \
| sed -n 's,^\# *[0-9][0-9]* *"\([^"<]*\)".*,$@: \1\n\1:,p' \
| sort -u > $*.d
SRC_FILES = main.c asdf.c asdf_modifiers.c asdf_repeat.c asdf_keymaps.c asdf_buffer.c asdf_arch.c
OBJ_FILES := $(SRC_FILES:.c=.o)
DEP_FILES := $(SRC_FILES:%.c=$(DEP_DIR)/%.d)
MAP_FILE = $(TARGET).map
CLEAN_FILES += $(MAP_FILE)
CLEAN_FILES += $(TARGET_BIN)
CLEAN_FILES += $(TARGET_MAP)
CLEANALL_FILES += $(TARGET_HEX)
MAKEFILES = Makefile
GENERATED_FILES = conventions.h machine.h
ALL_FILES = $(MAKEFILES) $(SRC_FILES) $(TXTFILES) $(GENERATED_FILES)
.SUFFIXES:
.SUFFIXES: .c .o .bin .hex
all: $(TARGET_HEX)
%.d : %.c $(DEP_DIR)/%.d | $(DEP_DIR)
@$(MAKEDEPEND)
$(DEP_DIR): ; @mkdir -p $@
$(DEPFILES):
include $(wildcard $(DEPFILES))
%.o: %.c $(DEP_DIR)/%.d | $(DEP_DIR)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEPFLAGS) $<
asdf_keymaps.h: $(KEYMAPS_DIR)/asdf_keymaps_$(KEYMAP).h $(KEYMAP_H_TOKEN)
cp $< $@
GENERATED_FILES += asdf_keymaps.h
asdf_arch.c: $(ARCH_DIR)/asdf_arch_$(ARCH).c $(ARCH_C_TOKEN)
cp $< $@
GENERATED_FILES += asdf_arch.c
asdf_arch.h: $(ARCH_DIR)/asdf_arch_$(ARCH).h $(ARCH_H_TOKEN)
cp $< $@
GENERATED_FILES += asdf_arch.h
$(ARCH_H_TOKEN):
touch $@
$(ARCH_C_TOKEN):
touch $@
$(KEYMAP_H_TOKEN):
touch $@
size:
$(SIZE_COMMAND) $(TARGET_BIN)
$(TARGET_HEX): $(TARGET_BIN)
avr-objcopy -j .text -j .data -j .fuses -O ihex $< $@
$(TARGET_BIN): $(OBJ_FILES)
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $^
$(SIZE_COMMAND) $(TARGET_BIN)
asdf_keymaps.o: asdf_keymaps.c asdf.h asdf_ascii.h asdf_modifiers.h asdf_arch.h asdf_keymaps.h
main.o: main.c asdf.h asdf_arch.h
asdf.o: asdf.c asdf.h asdf_arch.h asdf_keymaps.h asdf_config.h
asdf_repeat.o: asdf_repeat.c asdf_repeat.h asdf_config.h
asdf_buffer.o: asdf_buffer.c asdf.h asdf_config.h
asdf_modifiers.o: asdf_modifiers.c asdf_modifiers.h
tags: $(SRC_FILES)
etags $(SRC_FILES)
CLEAN_FILES += $(TEST_BUILD_FILES) _Arch_* *.o
CLEAN_FILES += ~* *\#
CLEANALL_FILES += $(GENERATED_FILES) $(TARGET_BUILD_FILES) $(TEST_BUILD_FILES)
.PHONY: clean
clean:
rm -f $(CLEAN_FILES)
.PHONY: cleanall
cleanall:
rm -f $(CLEAN_FILES) $(CLEANALL_FILES)

View File

@ -0,0 +1,21 @@
# -*- makefile -*-
DEP_DIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
MAKEDEPEND = $(CPP) $(DEPFLAGS) $(CPPFLAGS) $< \
| sed -n 's,^\# *[0-9][0-9]* *"\([^"<]*\)".*,$@: \1\n\1:,p' \
| sort -u > $*.d
%.d : %.c $(DEP_DIR)/%.d | $(DEPDIR)
@$(MAKEDEPEND)
$(DEP_DIR): ; @mkdir -p $@
DEPFILES := $(SRC_FILES:%.c=$(DEP_DIR)/%.d)
$(DEPFILES):
include $(wildcard $(DEPFILES))

View File

@ -0,0 +1,155 @@
ARCH = test
ARCH = test
KEYMAP = test
ARCH_TOKEN = _Arch_$(ARCH)
TEST_DIR = ../test
UNITY_DIR = $(TEST_DIR)/unity
BUILD_DIR = ../build
UNITY_SCRIPTS = $(UNITY_DIR)/auto
ARCH_DIR = ./Arch
KEYMAPS_DIR = ./Keymaps
CC = gcc
VERSION =
RELEASE=
CLEAN_FILES =
CLEANALL_FILES =
CFLAGS=-std=c99
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -Wpointer-arith
CFLAGS += -Wcast-align
CFLAGS += -Wwrite-strings
CFLAGS += -Wswitch-default
CFLAGS += -Wunreachable-code
CFLAGS += -Winit-self
CFLAGS += -Wmissing-field-initializers
CFLAGS += -Wno-unknown-pragmas
CFLAGS += -Wstrict-prototypes
CFLAGS += -Wundef
CFLAGS += -Wold-style-definition
SRC_FILES = main.c asdf.c asdf_modifiers.c asdf_repeat.c asdf_keymaps.c asdf_buffer.c asdf_arch.c
OBJ_FILES = $(SRC_FILES:.c=.o)
ARCH_FILES = asdf_arch.c asdf_arch.h
CLEAN_FILES += ARCH_FILES
TESTS = repeat modifiers keymaps interface keyscan
TEST1 = asdf_repeat
TEST1_SRC = $(TEST_DIR)/test_$(TEST1).c
TEST1_DEPS = ./$(TEST1).c $(UNITY_DIR)/unity.c
TEST1_BUILD = $(BUILD_DIR)/test_$(TEST1)
TEST2 = asdf_modifiers
TEST2_SRC = $(TEST_DIR)/test_$(TEST2).c
TEST2_DEPS = ./$(TEST2).c $(UNITY_DIR)/unity.c
TEST2_BUILD = $(BUILD_DIR)/test_$(TEST2)
TEST3 = asdf_keymaps
TEST3_SRC = $(TEST_DIR)/test_$(TEST3).c
TEST3_DEPS = ./$(TEST3).c $(UNITY_DIR)/unity.c
TEST3_BUILD = $(BUILD_DIR)/test_$(TEST3)
TEST4 = asdf_buffer
TEST4_SRC = $(TEST_DIR)/test_$(TEST4).c
TEST4_DEPS = ./$(TEST4).c $(UNITY_DIR)/unity.c
TEST4_BUILD = $(BUILD_DIR)/test_$(TEST4)
TEST5 = asdf
TEST5_SRC = $(TEST_DIR)/test_$(TEST5).c
TEST5_DEPS = ./$(TEST5).c $(UNITY_DIR)/unity.c ./$(TEST1).c $(TEST2).c $(TEST3).c $(TEST4).c
TEST5_BUILD = $(BUILD_DIR)/test_$(TEST5)
.SUFFIXES:
.SUFFIXES: .c .o .bin .hex
%.o: %.c
$(TARGET_CC) -c $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $<
all: test
asdf_keymaps.h: Keymaps/asdf_keymaps_$(KEYMAP).h
cp $< $@
GENERATED_FILES += asdf_keymaps.h
asdf_arch.c: $(ARCH_DIR)/asdf_arch_$(ARCH).c _Arch_$(ARCH)
cp $< $@
GENERATED_FILES += asdf_arch.c
asdf_arch.h: $(ARCH_DIR)/asdf_arch_$(ARCH).h _Arch_$(ARCH)
cp $< $@
GENERATED_FILES += asdf_arch.h
$(ARCH_TOKEN):
touch $(ARCH_TOKEN)
asdf_keymaps.c: asdf.h asdf_ascii.h asdf_modifiers.h asdf_arch.h asdf_keymaps.h
tags: $(SRC_FILES)
etags $(SRC_FILES)
.PHONY: test
test: test1 test2 test3 test4 test5
.PHONY: test1
test1: $(TEST1_BUILD)
$(TEST1_BUILD)
.PHONY: test2
test2: $(TEST2_BUILD)
$(TEST2_BUILD)
.PHONY: test3
test3: $(TEST3_BUILD)
$(TEST3_BUILD)
.PHONY: test4
test4: $(TEST4_BUILD)
$(TEST4_BUILD)
.PHONY: test5
test5: $(TEST5_BUILD)
$(TEST5_BUILD)
$(TEST1_BUILD): $(TEST1_SRC) $(TEST1_DEPS)
$(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST1_SRC) $(TEST1_DEPS)
$(TEST2_BUILD): $(TEST2_SRC) $(TEST2_DEPS)
$(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST2_SRC) $(TEST2_DEPS)
$(TEST3_BUILD): $(TEST3_SRC) $(TEST3_DEPS)
$(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST3_SRC) $(TEST3_DEPS)
$(TEST4_BUILD): $(TEST4_SRC) $(TEST4_DEPS)
$(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST4_SRC) $(TEST4_DEPS)
$(TEST5_BUILD): $(TEST5_SRC) $(TEST5_DEPS)
$(CC) -o $@ -I. -I$(TEST_DIR) -I$(UNITY_DIR) $(CFLAGS) $(TEST5_SRC) $(TEST5_DEPS)
TEST_BUILD_FILES += $(TEST1_BUILD) $(TEST2_BUILD) $(TEST3_BUILD) $(TEST4_BUILD) $(TEST5_BUILD)
CLEAN_FILES += $(TEST_BUILD_FILES) _Arch_* *.o
CLEAN_FILES += ~* *\#
CLEANALL_FILES += $(GENERATED_FILES) $(TARGET_BUILD_FILES) $(TEST_BUILD_FILES)
.PHONY: clean
clean:
rm -f $(CLEAN_FILES)
.PHONY: cleanall
cleanall:
rm -f $(CLEAN_FILES) $(CLEANALL_FILES)
include Makefile.deps

View File

@ -0,0 +1,125 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// <FIXME-filename>.c
//
// 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/>.
//
//iring Information:
// Chip: {Microcontroller type and version}
//
// Example:
// PIN NAME FUNCTION
// 3 AN1 ADC INPUT: Line sense analog input
//
// 6 A4 INPUT: (T0CK) COUNT DOWN from quadrature decoder.
// configured to count on rising edge, synced with xtal
//
//
// Headers
//
#include <version.h>
//
// Global Variable declarations: Use very sparingly. Used for communication
// with ISR's. Exceptions should be documented.
//
// Examples:
// run_clock_thread (global uns 8) when this is set to TRUE (by the
// clock_tick() ISR every 20 ms), the main loop performs certain
// actions, and resets the value to FALSE (see main loop comments)
//
uint8 send_count = FALSE;
//
// ISR routines
//
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// COMPLEXITY:
//
//
// Regular functions
//
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
// PROCEDURE: main()
//
// Main program loop; invoked at processor startup.
//
main()
{
// INITIALIZATION SECTION
cold_start:
// re-initialize variables and re-enter control loop, when the "R" command
// is received
warm_start:
// END OF INITIALIZATION SECTION
// Main Section:
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,41 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// <FIXME-filename>.h
//
// 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 (FILENAME_H)
#define FILENAME_H
//
// Headers
//
//
// Device and peripheral definitions, comments should include use of devices.
// Please
//
#endif /* !defined (FILENAME_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,46 @@
---
BasedOnStyle: Mozilla
AlignAfterOpenBracket: Align
AlignOperands: 'true'
AlignTrailingComments: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'true'
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'true'
BinPackArguments: 'true'
BinPackParameters: 'true'
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Stroustrup
ColumnLimit: '100'
ConstructorInitializerIndentWidth: '2'
ContinuationIndentWidth: '2'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
IncludeBlocks: Preserve
IndentCaseLabels: 'true'
IndentPPDirectives: None
IndentWidth: '2'
IndentWrappedFunctionNames: 'false'
KeepEmptyLinesAtTheStartOfBlocks: 'true'
Language: Cpp
MaxEmptyLinesToKeep: '2'
PointerAlignment: Right
ReflowComments: 'true'
SortIncludes: 'false'
SpaceAfterCStyleCast: 'true'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '1'
SpacesInCStyleCastParentheses: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
TabWidth: '8'
UseTab: Never
...

450
firmware/asdf/src/asdf.c Normal file
View File

@ -0,0 +1,450 @@
// File recommented by recomment.cpp
// on Dec 9 2019 at 10:14:05.
//
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF firmware - small, fast, and simple keyboard encoder.
//
// asdf.c
//
// This file contains code for:
// - the main scan code and key handler routines
// - key matrix declarations and keyboard state variables not delegated
// elsewhere.
// - Key debouncing logic and data stuctures
// - dispatch of special functions bound to keys.
//
// 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 <stdint.h>
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_keymaps.h"
#include "asdf_repeat.h"
#include "asdf_modifiers.h"
#include "asdf_buffer.h"
#include "asdf_arch.h"
static asdf_cols_t last_stable_key_state[ASDF_NUM_ROWS];
// Each key is debounced separately, supporting true N-key rollover, allowing a
// new key to be pressed when the previously pressed key is still debouncing.
// This requires a debounce counter for each key. This is is a large RAM
// footprint, 64 bytes for an 8 x 8 key matrix. It would be possible to only
// debounce the most recently pressed key and reduce the RAM usage to a single
// debounce counuter. However, this would probably require different handling of
// key presses and releases, and special handling for modifier keys, perhaps
// including separate debounce logic in the handlers for toggle keys such as
// CAPS_LOCK.
static uint8_t debounce_counters[ASDF_NUM_ROWS][ASDF_NUM_COLS];
// store the last key pressed
static asdf_keycode_t last_key;
// handle for the char output buffer
static asdf_buffer_handle_t asdf_keycode_buffer;
// PROCEDURE: asdf_put_code
// INPUTS: (asdf_keycode_t) code: code to be buffered for output
// OUTPUTS: none
//
// DESCRIPTION: Takes a keycode argument and buffers for output.
//
// SIDE EFFECTS: modifies buffer state.
//
// NOTES: If buffer is full, silently drop the code.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_put_code(asdf_keycode_t code)
{
asdf_buffer_put(asdf_keycode_buffer, code);
}
// PROCEDURE: asdf_get_code
// INPUTS: none
// OUTPUTS: (asdf_keycode_t) returns next value in buffer.
//
// DESCRIPTION: Takes a keycode argument and buffers for output.
//
// SIDE EFFECTS: modifies buffer state.
//
// NOTES: If buffer is full, silently drop the code.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
asdf_keycode_t asdf_get_code(void)
{
return asdf_buffer_get(asdf_keycode_buffer);
}
// PROCEDURE: asdf_lookup_keycode
// INPUTS: row, col: specify a row and column in the keyboard matrix
// OUTPUTS: returns a keycode
//
// DESCRIPTION: Given a row and column in the keyboard matrix, returns the
// corresponding keycode, depending on the state of the modifier keys.
//
// SIDE EFFECTS: none
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 1
//
asdf_keycode_t asdf_lookup_keycode(uint8_t row, uint8_t col)
{
return asdf_keymaps_get_code(row, col, asdf_modifier_index());
}
// PROCEDURE: asdf_activate_action
// INPUTS: keycode: an action key code
// OUTPUTS: none
//
// DESCRIPTION: This routine is called when a key bound to an action code is
// pressed, and maps the action code to a function call, or other action
// appropriate for activation of the function.
//
// SIDE EFFECTS: All the actions may have side effects, depending on the function called.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_activate_action(action_t keycode)
{
switch (keycode) {
case ACTION_SHIFT: {
asdf_modifier_shift_activate();
break;
}
case ACTION_SHIFT_LOCK: {
asdf_modifier_shiftlock_activate();
break;
}
case ACTION_CAPS: {
asdf_modifier_capslock_activate();
break;
}
case ACTION_CTRL: {
asdf_modifier_ctrl_activate();
break;
}
case ACTION_REPEAT: {
asdf_repeat_activate();
break;
}
case ACTION_NOTHING:
case ACTION_LOCAL:
case ACTION_BREAK:
case ACTION_HERE_IS:
case ACTION_FN_1:
case ACTION_FN_2:
case ACTION_FN_3:
case ACTION_FN_4:
case ACTION_FN_5:
case ACTION_FN_6:
case ACTION_FN_7:
case ACTION_FN_8:
case ACTION_FN_9:
case ACTION_FN_10:
case ACTION_CLEAR:
default: break;
}
}
// PROCEDURE: asdf_deactivate_action
// INPUTS: keycode: an action key code
// OUTPUTS: none
//
// DESCRIPTION: This routine is called when a key bound to an action code is
// released, and maps the action code to a function call, or other action
// appropriate for deactivation of the function.
//
// SIDE EFFECTS: All the actions may have side effects, depending on the function called.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_deactivate_action(action_t keycode)
{
switch (keycode) {
case ACTION_SHIFT: {
asdf_modifier_shift_deactivate();
break;
}
case ACTION_SHIFT_LOCK: {
asdf_modifier_shiftlock_deactivate();
break;
}
case ACTION_CAPS: {
asdf_modifier_capslock_deactivate();
break;
}
case ACTION_CTRL: {
asdf_modifier_ctrl_deactivate();
break;
}
case ACTION_REPEAT: {
asdf_repeat_deactivate();
}
case ACTION_NOTHING:
case ACTION_LOCAL:
case ACTION_BREAK:
case ACTION_HERE_IS:
case ACTION_FN_1:
case ACTION_FN_2:
case ACTION_FN_3:
case ACTION_FN_4:
case ACTION_FN_5:
case ACTION_FN_6:
case ACTION_FN_7:
case ACTION_FN_8:
case ACTION_FN_9:
case ACTION_FN_10:
case ACTION_CLEAR:
default: break;
}
}
// PROCEDURE: asdf_activate_key
// INPUTS: keycode - the code for a key that has been pressed.
// OUTPUTS: none
//
// DESCRIPTION: Called when a key has been pressed. If the key is bound to a
// value, output the value. If the key is bound to an action, call the activate action
// handler with the keycode.
//
// SIDE EFFECTS: If the code is a value, the last key is updated to the current
// value, and repeat timer is reset. If the code is an action code, the activate
// action dispatcher produces side effects. See asdf_activate_action()
//
// SCOPE: private
//
// COMPLEXITY: 2
//
static void asdf_activate_key(asdf_keycode_t keycode)
{
if (keycode & ASDF_ACTION) {
asdf_activate_action((action_t) keycode);
}
else {
// activate a new codable keypress
asdf_put_code(keycode);
if (last_key != keycode) {
last_key = keycode;
asdf_repeat_reset_count();
}
}
}
// PROCEDURE: asdf_deactivate_key
// INPUTS: keycode - the code for a key that has been released
// OUTPUTS: none
//
// DESCRIPTION: Called when a key has been released. If the key is bound to a
// value, output the value. If the key is bound to an action, call the deactivate
// action handler with the keycode.
//
// SIDE EFFECTS: If the code is a value, the last key is set to ACTION_NOTHING,
// which is effectively a NOP. If the code is an action code, the deactivate action
// dispatcher produces side effects. See asdf_deactivate_action()
//
// SCOPE: private
//
// COMPLEXITY: 2
//
static void asdf_deactivate_key(asdf_keycode_t keycode)
{
if (keycode & ASDF_ACTION) {
asdf_deactivate_action((action_t) keycode);
}
else {
// deactivate a released keypress
if (last_key == keycode) {
last_key = ACTION_NOTHING;
}
}
}
// PROCEDURE: asdf_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Reserve an output buffer to hold keycodes to be sent, and
// initialize the keyboard state and debounce counters
//
// SIDE EFFECTS: see DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 3
//
void asdf_init(void)
{
last_key = ACTION_NOTHING;
asdf_modifiers_init();
asdf_repeat_init();
asdf_keymaps_init();
asdf_buffer_init();
// reserve a buffer:
asdf_keycode_buffer = asdf_buffer_new(ASDF_KEYCODE_BUFFER_SIZE);
for (uint8_t row = 0; row < ASDF_NUM_ROWS; row++) {
last_stable_key_state[row] = 0;
for (uint8_t col = 0; col < ASDF_NUM_COLS; col++) {
debounce_counters[row][col] = ASDF_DEBOUNCE_TIME_MS;
}
}
}
// PROCEDURE: asdf_handle_key_press_or_release
// INPUTS: row, col: the row and column number of the key that has changed.
// OUTPUTS: none
//
// DESCRIPTION: Given a row and column of a key that has changed:
//
// 1) Debounce the key by decrementing a debounce timer. If not yet debounced,
// return.
// 2) When the key is debounced, if the key is pressed, then call the activation
// function associated with the key. Otherwise, if the key is released, call
// the deactivation function for the key.
//
// SIDE EFFECTS: - Modifies debounce counter for the row and column
// - After key debounces, modifies the table of stable key states
// - Activate/deactivate functions have side effects
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 3
//
static void asdf_handle_key_press_or_release(uint8_t row, uint8_t col, uint8_t key_was_pressed)
{
uint8_t *debounce_count = &debounce_counters[row][col];
if (!(--(*debounce_count))) {
// debounce timed out. Set new stable state and activate or
// deactivate key.
*debounce_count = ASDF_DEBOUNCE_TIME_MS;
if (key_was_pressed) {
last_stable_key_state[row] |= 1 << col;
asdf_activate_key(asdf_lookup_keycode(row, col));
}
else {
// key was released
last_stable_key_state[row] &= ~(1 << col);
asdf_deactivate_key(asdf_lookup_keycode(row, col));
}
}
}
// PROCEDURE: asdf_handle_key_held_pressed
// INPUTS: row, col: The row and column of a key that is being held down
// OUTPUTS: none
//
// DESCRIPTION: Given a row and column of a key that has been debounced and
// continues to be pressed:
// 1) Determine if this is the last key pressed.
// 2) If it's the most recent key, then check to see if it's time to repeat the key code.
// 3) If it's time to repeat, then do the repeat and reset the repeat timer.
//
// SIDE EFFECTS:
// - Causes repeat timer to tick, and may reset the repeat timer.
// - activate_key() will send a key code.
//
// NOTES: last_key is always a key code, never an action function, so only valid
// key codes will be repeated.
//
// SCOPE: private
//
// COMPLEXITY: 3
//
static void asdf_handle_key_held_pressed(uint8_t row, uint8_t col)
{
if (asdf_lookup_keycode(row, col) == last_key) {
// if last debounced code-producing key is still pressed, handle repeat
if (asdf_repeat()) {
asdf_activate_key(last_key);
}
}
}
// PROCEDURE: asdf_keyscan
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Scans the key matrix. For each row, read the columns and compare
// with last stable state. For each changed key, call a key-change handler
// function. For each stable pressed key, call a "continued press" handler
// function.
//
// SIDE EFFECTS:
//
// NOTES: 1) The keyboard state is stored as an array of words, with one word
// per row, and each bit in a word representing one key in the row.
//
// 2) While it is tempting to use bit hacks to reduce the number of
// cycles through the inner loop, I have opted to just loop over all
// the bits (as long as there are some changed or pressed keys). For
// an 8-bit word, bit tricks don't deliver much performance boost,
// but do decrease code clarity.
//
// COMPLEXITY: 5
//
void asdf_keyscan(void)
{
for (uint8_t row = 0; row < ASDF_NUM_ROWS; row++) {
asdf_cols_t row_key_state = asdf_arch_read_row(row);
asdf_cols_t changed = row_key_state ^ last_stable_key_state[row];
// loop over the bits until all changed or pressed keys in the row are handled.
for (uint8_t col = 0; (changed | row_key_state) && col < ASDF_NUM_COLS; col++) {
if (changed & 1) {
// key state is different from last stable state
asdf_handle_key_press_or_release(row, col, row_key_state & 1);
}
else if (row_key_state & 1) {
asdf_handle_key_held_pressed(row, col);
}
changed >>= 1;
row_key_state >>= 1;
}
}
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

100
firmware/asdf/src/asdf.h Normal file
View File

@ -0,0 +1,100 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf.h
//
// 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_H)
#define ASDF_H
#define ASDF_NUM_ROWS 8
#define ASDF_NUM_COLS 8
#define ASDF_ACTION 0x80
#define ASDF_INVALID_CODE 0x80
// an action code is not a valid keycode.
// for efficiency on 8-bit machines, use 8 columns per row. For 16 columns per
// row, change cols_t to uint16_t and increase ASDF_NUM_COLS.
typedef uint8_t asdf_cols_t;
// ASCII keycodes are 7 bits. An 8-bit datatype encodes ASCII, plus a flag for a
// key function. For longer codes, such as extended ASCII or unicode, change
// keycode_t appropriately, and also change ASDF_ACTION so that the action key
// codes (enumerated in action_t) do not conflict with the encoding scheme.
typedef uint8_t asdf_keycode_t;
typedef enum {
ACTION_NOTHING = ASDF_ACTION,
ACTION_SHIFT = ASDF_ACTION + 0x01,
ACTION_SHIFT_LOCK = ASDF_ACTION + 0x02,
ACTION_CAPS = ASDF_ACTION + 0x03,
ACTION_CTRL = ASDF_ACTION + 0x04,
ACTION_REPEAT = ASDF_ACTION + 0x05,
ACTION_LOCAL = ASDF_ACTION + 0x06,
ACTION_BREAK = ASDF_ACTION + 0x07,
ACTION_HERE_IS = ASDF_ACTION + 0x08,
ACTION_CLEAR = ASDF_ACTION + 0x09,
ACTION_FN_1 = ASDF_ACTION + 0x11,
ACTION_FN_2 = ASDF_ACTION + 0x12,
ACTION_FN_3 = ASDF_ACTION + 0x13,
ACTION_FN_4 = ASDF_ACTION + 0x14,
ACTION_FN_5 = ASDF_ACTION + 0x15,
ACTION_FN_6 = ASDF_ACTION + 0x16,
ACTION_FN_7 = ASDF_ACTION + 0x17,
ACTION_FN_8 = ASDF_ACTION + 0x18,
ACTION_FN_9 = ASDF_ACTION + 0x19,
ACTION_FN_10 = ASDF_ACTION + 0x1a
} action_t;
// PROCEDURE: asdf_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: initialize the keyboard state and debounce counters
void asdf_init(void);
// PROCEDURE: asdf_keyscan
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Scans the key matrix. For each row, read the columns and compare
// with last stable state. For each changed key, call a key-change handler
// function. For each stable pressed key, call a "continued press" handler
// function.
void asdf_keyscan(void);
// PROCEDURE: asdf_put_code
// INPUTS: (asdf_keycode_t) code: code to be buffered for output
// OUTPUTS: none
// DESCRIPTION: Takes a keycode argument and buffers for output.
// NOTES: If buffer is full, silently drop the code.
void asdf_put_code(asdf_keycode_t code);
// PROCEDURE: asdf_get_code
// INPUTS: none
// OUTPUTS: (asdf_keycode_t) returns next value in buffer.
// DESCRIPTION: Takes a keycode argument and buffers for output.
asdf_keycode_t asdf_get_code(void);
#endif // !defined (ASDF_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,90 @@
// File recommented by recomment.cpp
// on Dec 9 2019 at 10:14:05.
//
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_ascii.h
//
// This file contains definitions of ASCII control cods and certain symbols, in
// order to avoid escaping special characters in the keymap definitions, and to
// improve keymap readability.
//
// 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_ASCII_H)
#define ASDF_ASCII_H
typedef enum {
ASCII_CTRL_A = 0x01,
ASCII_CTRL_B = 0x02,
ASCII_CTRL_C = 0x03,
ASCII_CTRL_D = 0x04,
ASCII_CTRL_E = 0x05,
ASCII_CTRL_F = 0x06,
ASCII_CTRL_G = 0x07,
ASCII_CTRL_H = 0x08,
ASCII_CTRL_I = 0x09,
ASCII_CTRL_J = 0x0a,
ASCII_CTRL_K = 0x0b,
ASCII_CTRL_L = 0x0c,
ASCII_CTRL_M = 0x0d,
ASCII_CTRL_N = 0x0e,
ASCII_CTRL_O = 0x0f,
ASCII_CTRL_P = 0x10,
ASCII_CTRL_Q = 0x11,
ASCII_CTRL_R = 0x12,
ASCII_CTRL_S = 0x13,
ASCII_CTRL_T = 0x14,
ASCII_CTRL_U = 0x15,
ASCII_CTRL_V = 0x16,
ASCII_CTRL_W = 0x17,
ASCII_CTRL_X = 0x18,
ASCII_CTRL_Y = 0x19,
ASCII_CTRL_Z = 0x1a,
ASCII_ESC = 0x1b,
ASCII_SPACE = 0x20,
ASCII_AT = 0x40,
ASCII_COMMA = 0x44,
ASCII_LT_CURLY_BRACE = 0x7b,
ASCII_RT_CURLY_BRACE = 0x7d,
ASCII_LT_SQUARE_BRACE = 0x5b,
ASCII_RT_SQUARE_BRACE = 0x5d,
ASCII_LT_PAREN = 0x28,
ASCII_RT_PAREN = 0x29,
ASCII_SINGLE_QUOTE = 0x27,
ASCII_DOUBLE_QUOTE = 0x22,
ASCII_BACKSLASH = 0x5c,
ASCII_GRAVE_ACCENT = 0x60,
ASCII_PERIOD = 0x2e,
ASCII_TILDE = 0x7e,
ASCII_VERT_BAR = 0x7c,
ASCII_DEL = 0x7f
} ascii;
#define ASCII_LF ASCII_CTRL_J
#define ASCII_CR ASCII_CTRL_M
#define ASCII_TAB ASCII_CTRL_I
#endif // !defined (ASDF_ASCII_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,183 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_buffer.c
//
// Provides an interface between the generation of keycodes and the
// hardware-level keycode transmission. Any buffering, etcc. occurs here.
//
// 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 <stdio.h>
#include <stdint.h>
#include "asdf.h"
#include "asdf_buffer.h"
typedef struct {
asdf_keycode_t *buf;
int16_t size;
uint8_t head;
uint8_t tail;
uint8_t count;
} asdf_buffer_t;
static asdf_keycode_t buffer_pool[ASDF_BUFFER_POOL_SIZE];
static asdf_buffer_t buffers[ASDF_BUFFER_NUM_HANDLES];
static int16_t buffer_free;
static asdf_buffer_handle_t next_handle;
// PROCEDURE: asdf_buffer_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize the buffer pool and handles
//
// SIDE EFFECTS: See description
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_buffer_init(void)
{
buffer_free = 0;
next_handle = 0;
}
// PROCEDURE: buffer_handle_valid
// INPUTS: (uint8_t) handle - handle to be checked
// OUTPUTS: returns TRUE if the handle is a valid allocated handle.
//
// DESCRIPTION: Returns TRUE if the handle is one that has been allocated.
//
// SIDE EFFECTS: none
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 1
//
uint8_t buffer_handle_valid(asdf_buffer_handle_t handle)
{
return ((handle >= 0) && (handle < next_handle));
}
// PROCEDURE: asdf_buffer_new
// INPUTS: (uint16_t) size: size of the buffer to allocate.
//
// OUTPUTS: returns a uint8_t handle to identify the buffer allocated from the
// pool.
//
// DESCRIPTION: Receives a request to allocate a fixed-size buffer from the
// pool. If there is enough room in the buffer pool, and if a buffer handle is
// available, then allocate space from the pool, initialize the next available
// buffer struct, and return the handle.
//
// SIDE EFFECTS: see above
//
// SCOPE: public
//
// COMPLEXITY: 3
//
asdf_buffer_handle_t asdf_buffer_new(int16_t size)
{
asdf_buffer_handle_t handle = ASDF_BUFFER_INVALID;
if (next_handle < ASDF_BUFFER_NUM_HANDLES) {
if (size <= (ASDF_BUFFER_POOL_SIZE - buffer_free)) {
handle = next_handle++;
buffers[handle].size = size;
buffers[handle].buf = &buffer_pool[buffer_free];
buffers[handle].head = 0;
buffers[handle].tail = 0;
buffers[handle].count = 0;
buffer_free += size;
}
}
return handle;
}
// PROCEDURE: asdf_buffer_put
//
// INPUTS:(asdf_buffer_t) buffer_handle: pointer to the buffer struct.
// (asdf_keycode_t) code: code to be added to the queue.
//
// OUTPUTS: None
//
// DESCRIPTION: Add the keycode to the head of the output buffer. If the buffer
// is full, quietly drop the keycode.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES:
//
// COMPLEXITY: 3
//
// SCOPE: public
//
void asdf_buffer_put(asdf_buffer_handle_t handle, asdf_keycode_t code)
{
if (buffer_handle_valid(handle)) {
if (buffers[handle].count < buffers[handle].size) {
buffers[handle].buf[buffers[handle].head] = code;
buffers[handle].head = (buffers[handle].head + 1) % buffers[handle].size;
buffers[handle].count++;
}
}
}
// PROCEDURE: asdf_buffer_get
//
// INPUTS: None
//
// OUTPUTS: returns next code in the buffer.
//
// DESCRIPTION: Gets the next queued code in the output buffer and return the
// value.
//
// SIDE EFFECTS: Removes a code from the queue.
//
// NOTES: If the buffer is empty, the code ASDF_INVALID_CODE is returned.
//
// COMPLEXITY: 2
//
// SCOPE: Public
//
asdf_keycode_t asdf_buffer_get(asdf_buffer_handle_t handle)
{
asdf_keycode_t code = ASDF_INVALID_CODE;
if (buffers[handle].count) {
code = buffers[handle].buf[buffers[handle].tail];
buffers[handle].tail = (buffers[handle].tail + 1) % buffers[handle].size;
buffers[handle].count--;
}
return code;
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,76 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_buffer.h
//
// Contains definitions and prototypes for the asdf keycode output buffer.
//
// 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_BUFFER_H)
#define ASDF_BUFFER_H
#include "asdf_config.h"
#define ASDF_BUFFER_POOL_SIZE ASDF_KEYCODE_BUFFER_SIZE
#define ASDF_BUFFER_INVALID -1
// Setting the number of handles to 1 will work if only one buffer is requrired,
// and will save a few bytes of RAM. But the test code needs at least 2 buffer
// handles to test the module, so we leave it at 2.
#define ASDF_BUFFER_NUM_HANDLES 2
typedef int16_t asdf_buffer_handle_t;
// PROCEDURE: asdf_buffer_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize the buffer pool and handles
void asdf_buffer_init(void);
// PROCEDURE: asdf_buffer_new
// INPUTS: (uint16_t) size: size of the buffer to allocate.
// OUTPUTS: returns (asdf_buffer_handle_t) handle to identify the buffer allocated from the
// pool.
// DESCRIPTION: Receives a request to allocate a fixed-size buffer from the
// pool. If there is enough room in the buffer pool, and if a buffer handle is
// available, then allocate space from the pool, initialize the next available
// buffer struct, and return the handle.
asdf_buffer_handle_t asdf_buffer_new(int16_t size);
// PROCEDURE: asdf_buffer_put
// INPUTS:(asdf_buffer_t) buffer_handle: pointer to the buffer struct.
// (asdf_keycode_t) code: code to be added to the queue.
// OUTPUTS: None
// DESCRIPTION: Add the keycode to the head of the output buffer. If the buffer
// is full, quietly drop the keycode.
void asdf_buffer_put(asdf_buffer_handle_t handle, asdf_keycode_t code);
// PROCEDURE: asdf_buffer_get
// INPUTS: None
// OUTPUTS: returns next code in the buffer.
// DESCRIPTION: Gets the next queued code in the output buffer and return the
// value.
asdf_keycode_t asdf_buffer_get(asdf_buffer_handle_t handle);
#endif // !defined (ASDF_BUFFER_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,54 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_config.h
//
// This file gathers configuration parameters related to the user-detectable
// keyboard experience. For example, put key debounce times, repeat rates,
// buffer sized, baud rates, etc. here. Details such as processor clock speed,
// etc. should go in the architecture-dependent files. System details such as
// number of buffer handles, etc. should go with the appropriate module, but
// certain buffer sized may go here if they can affect the user experience (such
// as how long a macro can be).
//
// 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 (CONFIG_H)
#define CONFIG_H
// size of the keycode output buffer.
#define ASDF_KEYCODE_BUFFER_SIZE 16
// key debounce period (in msec)
#define ASDF_DEBOUNCE_TIME_MS 10
// Autorepeat default behavior. Set to REPEAT_AUTO for default autorepeat.
// Set to REPEAT_OFF for default no autorepeat by default.
#define ASDF_DEFAULT_REPEAT_STATE REPEAT_AUTO
// time to hold down a key in milliseconds before autorepeat starts
#define ASDF_AUTOREPEAT_TIME_MS 525 // 525 msec.
// time between repeats of a character with repeat key held, or in autorepeat (milliseconds)
#define ASDF_REPEAT_TIME_MS (1000 / 15) // l5 characters per sec.
#endif /* !defined (CONFIG_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,82 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps.c
//
// 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 <stdint.h>
#include "asdf.h"
#include "asdf_arch.h"
#include "asdf_keymaps.h"
typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS];
static const FLASH keycode_matrix_t plain_matrix = ASCII_PLAIN_MAP;
static const FLASH keycode_matrix_t shift_matrix = ASCII_SHIFT_MAP;
static const FLASH keycode_matrix_t caps_matrix = ASCII_CAPS_MAP;
static const FLASH keycode_matrix_t ctrl_matrix = ASCII_CTRL_MAP;
static keycode_matrix_t const *modifier_matrix[MOD_NUM_MAPS];
// PROCEDURE: asdf_keymaps_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Assigns the keymaps to the indices specified by the modifier
// index, to avoid hard-coding constant index values.
//
// SIDE EFFECTS: builds up the private map table.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_keymaps_init(void)
{
modifier_matrix[MOD_PLAIN_MAP] = &plain_matrix;
modifier_matrix[MOD_SHIFT_MAP] = &shift_matrix;
modifier_matrix[MOD_CAPS_MAP] = &caps_matrix;
modifier_matrix[MOD_CTRL_MAP] = &ctrl_matrix;
}
// PROCEDURE: asdf_keymaps_get_code
// INPUTS: row, col: row and column of key that has been pressed
// modifiers_index: index into the keymap array, based on modifier state
// OUTPUTS: returns a key code.
//
// DESCRIPTION: Given a key row and column, and an index based on modifier
// state, return the appropriate keycode.
//
// SIDE EFFECTS: none
//
// SCOPE: public
//
// COMPLEXITY: 1
//
asdf_keycode_t asdf_keymaps_get_code(const uint8_t row, const uint8_t col,
const uint8_t modifier_index)
{
const keycode_matrix_t *matrix = modifier_matrix[modifier_index];
return FLASH_READ_MATRIX_ELEMENT(*matrix, row, col);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,220 @@
// File recommented by recomment.cpp
// on Dec 9 2019 at 10:14:05.
//
// -*-mode : C;
// tab - width : 2; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_modifiers.c
//
// This file contains the logic for the modifier keys. Any new modifiers or
// special handling goes here.
//
// 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 <stdint.h>
#include "asdf_modifiers.h"
static shift_state_t shift_state;
static caps_state_t caps_state;
static ctrl_state_t ctrl_state;
static shiftlock_mode_t asdf_toggle_shiftlock;
static const modifier_index_t modifier_indices[] = {
MOD_PLAIN_MAP, // 0x00: no modifiers
MOD_SHIFT_MAP, // 0x01: only SHIFT active
MOD_CAPS_MAP, // 0x02: only CAPS active
MOD_SHIFT_MAP, // 0x03: CAPS and SHIFT active
MOD_CTRL_MAP, // CTRL overrides SHIFT and CAPS
MOD_CTRL_MAP, MOD_CTRL_MAP, MOD_CTRL_MAP
};
// PROCEDURE: asdf_modifier_shift_activate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: sets SHIFT state to ON
//
// SIDE EFFECTS: see DESCRIPTION
//
// COMPLEXITY: 1
//
void asdf_modifier_shift_activate(void)
{
shift_state = SHIFT_ON_ST;
}
// PROCEDURE: asdf_modifier_shiftlock_activate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: sets SHIFTLOCK state depending on the mode.
//
// SHIFTLOCK normal mode:
// - SHIFTLOCK always activates shift mode
// - Pressing and Relasing SHIFT deactivates shift mode.
//
// SHIFTLOCK toggle mode:
// - Pressing SHIFTLOCK toggles the shift mode on and off
// - Pressing and Relasing SHIFT deactivates shift mode.
//
// NOTES: The test of the shiftlock mode constant always has the same result and
// will therefore be optimized by the compiler, so technically no added
// cyclometric complexity, but count it anyway, in case this is made into a
// user-definable behavior later.
//
// SIDE EFFECTS: affects shift_state as described.
//
// COMPLEXITY: 2
//
void asdf_modifier_shiftlock_activate(void)
{
if (asdf_toggle_shiftlock) {
shift_state ^= SHIFT_LOCKED_ST;
}
else {
shift_state |= SHIFT_LOCKED_ST;
}
}
// PROCEDURE: asdf_modifier_capslock_activate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Turns on Capslock state
//
// SIDE EFFECTS: see DESCRIPTION
//
// COMPLEXITY: 1
//
void asdf_modifier_capslock_activate(void)
{
caps_state ^= CAPS_ON_ST;
}
// PROCEDURE: asdf_modifier_ctrl_activate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Turns on CTRL mode
//
// SIDE EFFECTS: see DESCRIPTION
//
// COMPLEXITY: 1
//
void asdf_modifier_ctrl_activate(void)
{
ctrl_state = CTRL_ON_ST;
}
// PROCEDURE: asdf_modifier_shift_deactivate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Turns off shift mode.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES: this also clears any SHIFT_LOCK condition.
//
// COMPLEXITY: 1
//
void asdf_modifier_shift_deactivate(void)
{
shift_state = SHIFT_OFF_ST;
}
// PROCEDURE: asdf_modifier_ctrl_deactivate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Turns off CTRL mode
//
// SIDE EFFECTS: See DESCRIPTION
//
// COMPLEXITY: 1
//
void asdf_modifier_ctrl_deactivate(void)
{
ctrl_state = CTRL_OFF_ST;
}
// PROCEDURE: asdf_modifier_shiftlock_deactivate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Does nothing. This is called when releasing the SHIFT LOCK key,
// and no action is performed on releasing a SHIFT LOCK key
//
// SIDE EFFECTS: none
//
// COMPLEXITY: 1
//
void asdf_modifier_shiftlock_deactivate(void) {}
// PROCEDURE: asdf_modifier_capslock_deactivate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Does nothing. This is called when releasing the CAPS LOCK key,
// and no action is performed on releasing the CAPS LOCK key.
//
// SIDE EFFECTS: none
//
// COMPLEXITY: 1
//
void asdf_modifier_capslock_deactivate(void) {}
// PROCEDURE: asdf_modifiers_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize the modifier key state variables to OFF state
//
// SIDE EFFECTS: see DESCRIPTION
//
// COMPLEXITY: 1
//
void asdf_modifiers_init(void)
{
shift_state = SHIFT_OFF_ST;
caps_state = CAPS_OFF_ST;
ctrl_state = CTRL_OFF_ST;
asdf_toggle_shiftlock = HOLD_SHIFTLOCK;
}
// PROCEDURE: asdf_modifier_index
// INPUTS: none
// OUTPUTS: returns uint8_t index into key map, based on modifier key status
//
// DESCRIPTION: See OUTPUTS
//
// SIDE EFFECTS: none
//
// COMPLEXITY: 1
//
modifier_index_t asdf_modifier_index(void)
{
return modifier_indices[((uint8_t)(shift_state & 1) // shift active
| ((uint8_t)(shift_state >> 1)) // shiftlock active
| (uint8_t) caps_state // caps active
| (uint8_t) ctrl_state)]; // ctrl active
}

View File

@ -0,0 +1,116 @@
// File recommented by recomment.cpp
// on Dec 9 2019 at 10:14:05.
//
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_modifiers.h
//
// 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_MODIFIERS_H)
#define ASDF_MODIFIERS_H
typedef enum { SHIFT_OFF_ST = 0, SHIFT_ON_ST = 0x01, SHIFT_LOCKED_ST = 0x02 } shift_state_t;
typedef enum { CAPS_OFF_ST = 0, CAPS_ON_ST = 0x02 } caps_state_t;
typedef enum { CTRL_OFF_ST = 0, CTRL_ON_ST = 0x04 } ctrl_state_t;
typedef enum {
MOD_PLAIN_MAP = 0,
MOD_SHIFT_MAP,
MOD_CAPS_MAP,
MOD_CTRL_MAP,
MOD_NUM_MAPS
} modifier_index_t;
typedef enum { TOGGLE_SHIFTLOCK = 0, HOLD_SHIFTLOCK = 1 } shiftlock_mode_t;
// PROCEDURE: asdf_modifier_shift_activate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: sets SHIFT state to ON
//
void asdf_modifier_shift_activate(void);
// PROCEDURE: asdf_modifier_shiftlock_activate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: sets SHIFTLOCK state if in NORMAL mode, and toggle shiftlock if in TOGGLE mode.
//
void asdf_modifier_shiftlock_activate(void);
// PROCEDURE: asdf_modifier_capslock_activate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Turns on Capslock state
//
void asdf_modifier_capslock_activate(void);
// PROCEDURE: asdf_modifier_ctrl_activate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Turns on CTRL mode
//
void asdf_modifier_ctrl_activate(void);
// PROCEDURE: asdf_modifier_shift_deactivate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Turns off shift mode.
//
void asdf_modifier_shift_deactivate(void);
// PROCEDURE: asdf_modifier_ctrl_deactivate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Turns off CTRL mode
//
void asdf_modifier_ctrl_deactivate(void);
// PROCEDURE: asdf_modifier_shiftlock_deactivate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: No action. This is called when releasing the SHIFT LOCK key,
//
void asdf_modifier_shiftlock_deactivate(void);
// PROCEDURE: asdf_modifier_capslock_deactivate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: No action. Called when releasing the CAPS LOCK key.
//
void asdf_modifier_capslock_deactivate(void);
// PROCEDURE: asdf_modifiers_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize the modifier key state variables to OFF state
//
void asdf_modifiers_init(void);
// PROCEDURE: asdf_modifier_index
// INPUTS: none
// OUTPUTS: returns uint8_t index into key map, based on modifier key status
// DESCRIPTION: See OUTPUTS
//
modifier_index_t asdf_modifier_index(void);
#endif // !defined (ASDF_MODIFIERS_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,180 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_repeat.c
//
// This file contains the key repeat logic.
//
// 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 <stdint.h>
#include "asdf_repeat.h"
typedef uint16_t key_timer_t;
static repeat_state_t repeat_state;
static repeat_state_t base_repeat_state;
static key_timer_t key_repeat_timer;
// PROCEDURE: asdf_repeat_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize the repeat state state machine
//
// SIDE EFFECTS: see DESCRIPTION
//
// COMPLEXITY: 1
//
void asdf_repeat_init(void)
{
repeat_state = base_repeat_state = ASDF_DEFAULT_REPEAT_STATE;
key_repeat_timer = (uint16_t) repeat_state;
}
// PROCEDURE: asdf_repeast_reset_count
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: resets the repeat counter for the current key, to begin a new
// repeat cycle. Resest is based on repeat state (no repeat, autorepeat, normal repeat).
//
// SIDE EFFECTS: see DESCRIPTION
//
// COMPLEXITY: 1
//
void asdf_repeat_reset_count(void)
{
key_repeat_timer = (key_timer_t) repeat_state;
}
// PROCEDURE: asdf_repeat_auto_off
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Turns Autorepeat mode off by setting the base state to
// autorepeat. If key is repeating, then the new behavior will be realized after
// the repeat key is released.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_repeat_auto_off(void)
{
base_repeat_state = REPEAT_OFF;
if (REPEAT_ON != repeat_state) {
key_repeat_timer = repeat_state = base_repeat_state;
}
}
// PROCEDURE: asdf_repeat_auto_on
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Turns Autorepeat mode on by setting the base state to
// autorepeat. If key is repeating, then the new behavior will be realized after
// the repeat key is released.
//
// SIDE EFFECTS: see above
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_repeat_auto_on(void)
{
base_repeat_state = REPEAT_AUTO;
if (REPEAT_ON != repeat_state) {
key_repeat_timer = repeat_state = base_repeat_state;
}
}
// PROCEDURE: asdf_repeat_activate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: set repeat state machine to repeat mode. Called when REPEAT key
// is pressed.
//
// SIDE EFFECTS: see DESCRIPTION
//
// NOTES: If a key is pressed and the key timer is less than or equal to the
// normal repeat rate, then don't change the timing, to avoid appearance of
// stuttering.
//
// COMPLEXITY: 1
//
void asdf_repeat_activate(void)
{
if (key_repeat_timer > REPEAT_ON || REPEAT_OFF == repeat_state) {
key_repeat_timer = repeat_state = REPEAT_ON;
}
}
// PROCEDURE: asdf_repeat_deactivate
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Reset repeat state machine to default state. Called when REPEAT
// key is released.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES: Releasing repeat disrupts any repeat timers. aIf a key is still held
// down after REPEAT is released, and autorepeat mode is enabled, then restart
// the autorepeat timer. Otherwise disable repeat.
//
// COMPLEXITY: 1
//
void asdf_repeat_deactivate(void)
{
key_repeat_timer = repeat_state = base_repeat_state;
}
// PROCEDURE: asdf_repeat
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: counts down the repeat timer (if activated) and returns a TRUE
// value when the counter times out. A true values indicates that the last value
// should be repeated to the output.
//
// SIDE EFFECTS: none
//
// NOTES: The key_repeat_timer is only decremented if it is nonzero.
//
// COMPLEXITY: 2
//
uint8_t asdf_repeat(void)
{
uint8_t timeout = (key_repeat_timer && !(--key_repeat_timer));
if (timeout) {
key_repeat_timer = REPEAT_ON;
}
return timeout;
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,87 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_repeat.h
//
// 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_REPEAT_H)
#define ASDF_REPEAT_H
#include "asdf_config.h"
typedef enum {
REPEAT_OFF = 0,
REPEAT_ON = ASDF_REPEAT_TIME_MS,
REPEAT_AUTO = ASDF_AUTOREPEAT_TIME_MS
} repeat_state_t;
// PROCEDURE: asdf_repeat_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize the repeat state state machine
void asdf_repeat_init(void);
// PROCEDURE: asdf_repeast_reset_count
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: resets the repeat counter for the current key, to begin a new
// repeat cycle. Resest is based on repeat state (no repeat, autorepeat, normal repeat).
void asdf_repeat_reset_count(void);
// PROCEDURE: asdf_repeat_auto_off
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Turns Autorepeat mode off
void asdf_repeat_auto_off(void);
// PROCEDURE: asdf_repeat_auto_on
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Turns Autorepeat mode on
void asdf_repeat_auto_on(void);
// PROCEDURE: asdf_repeat_activate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: set repeat state machine to repeat mode. Called when REPEAT key
// is pressed.
void asdf_repeat_activate(void);
// PROCEDURE: asdf_repeat_deactivate
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Reset repeat state machine to default state. Called when REPEAT
// key is released.
void asdf_repeat_deactivate(void);
// PROCEDURE: asdf_repeat
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: counts down the repeat timer (if activated) and returns a TRUE
// value when the counter times out. A true values indicates that the last value
// should be repeated to the output.
uint8_t asdf_repeat(void);
#endif // !defined (FILENAME_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

84
firmware/asdf/src/main.c Normal file
View File

@ -0,0 +1,84 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// main.c
//
// main program loop. Initialize hardware. Schedule key scans and i/o.
//
// 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 <stdint.h>
#include "asdf.h"
#include "asdf_arch.h"
#include "asdf_buffer.h"
// PROCEDURE: main
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize hardware, Schedule key scans and i/o
//
// SIDE EFFECTS: See above
//
// NOTES: This code just initializes the hardware, and then loops. The loop
// includes:
//
// - Check every 1 ms (or whatever the tick is set to), calls the keyboard
// scan routine.
//
// - Check every pass through if any characters are buffered to send. If so,
// send them.
//
// This is not the most efficient use of the hardware, but is an example of how
// the keyboard scanner is used. Of course, this loop can be replaced with an
// RTOS process as well. If an RTOS is used, then asdf_buffer can be modified
// to use RTOS message queues instead of an internal buffer, or to keep the
// internal buffer and use a counting semaphore to indicate characters in the
// buffer.
//
// If you are adding special functions when using an RTOS, make sure the
// functions do not block, or do any heavy computation. Rather, they should be
// small and pass messages to appropriate processes to handle the activities.
//
// COMPLEXITY: 2
//
int main(void)
{
// initialize the hardware:
asdf_arch_init();
// initialize the keyboard logic:
asdf_init();
while (1) {
if (asdf_arch_tick()) {
asdf_keycode_t code = asdf_get_code();
if (code != ASDF_INVALID_CODE) {
asdf_arch_send_code(code);
}
asdf_keyscan();
}
}
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -0,0 +1,46 @@
---
BasedOnStyle: Mozilla
AlignAfterOpenBracket: Align
AlignOperands: 'true'
AlignTrailingComments: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'true'
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'true'
BinPackArguments: 'true'
BinPackParameters: 'true'
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Stroustrup
ColumnLimit: '100'
ConstructorInitializerIndentWidth: '2'
ContinuationIndentWidth: '2'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
IncludeBlocks: Preserve
IndentCaseLabels: 'true'
IndentPPDirectives: None
IndentWidth: '2'
IndentWrappedFunctionNames: 'false'
KeepEmptyLinesAtTheStartOfBlocks: 'true'
Language: Cpp
MaxEmptyLinesToKeep: '2'
PointerAlignment: Right
ReflowComments: 'true'
SortIncludes: 'false'
SpaceAfterCStyleCast: 'true'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '1'
SpacesInCStyleCastParentheses: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
TabWidth: '8'
UseTab: Never
...

View File

@ -0,0 +1,508 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "unity.h"
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_modifiers.h"
#include "asdf_keymaps.h"
#include "asdf_buffer.h"
#include "asdf_repeat.h"
#define A 'a'
#define B 'b'
#define TEST_STRING "abcdefghijklmnop"
#define NUM_REPEATS (ASDF_KEYCODE_BUFFER_SIZE - 2)
#define TESTMAP(row, col, mapname, mapname2) \
do { \
asdf_keycode_t expected = mapname##_matrix[(row)][(col)]; \
asdf_keycode_t result = asdf_keymaps_get_code((row), (col), MOD_##mapname2##_MAP); \
TEST_ASSERT_EQUAL_INT(expected, result); \
} while (0);
#define TESTPLAIN(row, col, n) TESTMAP((row), (col), PLAIN, n)
#define TESTSHIFT(row, col, n) TESTMAP((row), (col), SHIFT, n)
#define TESTCAPS(row, col, n) TESTMAP((row), (col), CAPS, n)
#define TESTCTRL(row, col, n) TESTMAP((row), (col), CTRL, n)
typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS];
const char test_string[] = TEST_STRING;
const asdf_keycode_t key_a = A;
const asdf_keycode_t key_b = B;
typedef struct {
int32_t row;
int32_t col;
} coord_t;
static const keycode_matrix_t PLAIN_matrix = ASCII_PLAIN_MAP;
static const keycode_matrix_t SHIFT_matrix = ASCII_SHIFT_MAP;
static const keycode_matrix_t CAPS_matrix = ASCII_CAPS_MAP;
static const keycode_matrix_t CTRL_matrix = ASCII_CTRL_MAP;
static uint32_t key_matrix[ASDF_NUM_ROWS];
void setUp(void)
{
asdf_buffer_init();
asdf_init();
// initialize simulated key matrix
for (uint32_t i = 0; i < ASDF_NUM_ROWS; i++) {
key_matrix[i] = 0;
}
}
void tearDown(void) {}
coord_t *find_code(asdf_keycode_t code)
{
uint32_t done = 0;
static coord_t location = { .row = -1, .col = -1 };
for (uint32_t row = 0; !done && (row < ASDF_NUM_ROWS); row++) {
for (uint32_t col = 0; !done && (col < ASDF_NUM_COLS); col++) {
if (PLAIN_matrix[row][col] == code) {
done = 1;
location.row = row;
location.col = col;
}
}
}
return &location;
}
asdf_keycode_t shifted(asdf_keycode_t code)
{
coord_t *location = find_code(code);
return SHIFT_matrix[location->row][location->col];
}
asdf_keycode_t caps(asdf_keycode_t code)
{
coord_t *xy = find_code(code);
return CAPS_matrix[xy->row][xy->col];
}
asdf_keycode_t ctrl(asdf_keycode_t code)
{
coord_t *xy = find_code(code);
return CTRL_matrix[xy->row][xy->col];
}
void keyscan_delay(int32_t ticks)
{
for (; ticks; ticks--) {
asdf_keyscan();
}
}
void press_no_debounce(asdf_keycode_t code)
{
coord_t *location = find_code(code);
key_matrix[location->row] |= (1 << location->col);
}
void release_no_debounce(asdf_keycode_t code)
{
coord_t *location = find_code(code);
key_matrix[location->row] &= ~(1 << location->col);
}
void press(asdf_keycode_t code)
{
press_no_debounce(code);
keyscan_delay(ASDF_DEBOUNCE_TIME_MS);
}
void release(asdf_keycode_t code)
{
release_no_debounce(code);
keyscan_delay(ASDF_DEBOUNCE_TIME_MS);
}
asdf_cols_t asdf_arch_read_row(uint8_t row)
{
return key_matrix[row];
}
// No repsonse to a keypress before it is debounced.
void pressing_a_gives_nothing_before_debounce(void)
{
press_no_debounce(key_a);
// no keypress after only ASDF_DEBOUNCE_TIME_MS -1 ticks (not yet debounced):
keyscan_delay(ASDF_DEBOUNCE_TIME_MS - 1);
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing 'A' gives 'a'
void pressing_a_gives_a(void)
{
press_no_debounce(key_a);
// no keypress after only ASDF_DEBOUNCE_TIME_MS -1 ticks (not yet debounced):
keyscan_delay(ASDF_DEBOUNCE_TIME_MS - 1);
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_get_code());
// allow the key to finish debounce
keyscan_delay(1);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (int32_t) asdf_get_code());
// no more codes in the buffer.
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing SHIFT+A gives 'A'
void pressing_shift_a_gives_shifted_a(void)
{
press(ACTION_SHIFT);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) shifted(key_a), (int32_t) asdf_get_code());
}
// pressing CAPS+A gives 'A'
void pressing_caps_a_gives_caps_a(void)
{
press(ACTION_CAPS);
release(ACTION_CAPS);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) caps(key_a), (int32_t) asdf_get_code());
}
// pressing CTRL+A gives 0x01 (Ctrl-A)
void pressing_ctrl_a_gives_ctrl_a(void)
{
press(ACTION_CTRL);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) ctrl(key_a), (int32_t) asdf_get_code());
}
// pressing REPT+A repeats 'a'
void pressing_rept_a_repeats_a(void)
{
press(ACTION_REPEAT);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
}
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing REPT+SHIFT+A repeats 'A'
void pressing_shift_rept_a_repeats_shifted_a(void)
{
press(ACTION_REPEAT);
press(ACTION_SHIFT);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) shifted(key_a), (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) shifted(key_a), (uint32_t) asdf_get_code());
}
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing REPT+CAPS+A repeats 'A'
void pressing_caps_rept_a_repeats_caps_a(void)
{
press(ACTION_REPEAT);
press(ACTION_CAPS);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) caps(key_a), (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) caps(key_a), (uint32_t) asdf_get_code());
}
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing REPT+CTRL+A repeats CTRL-A
void pressing_ctrl_rept_a_repeats_ctrl_a(void)
{
press(ACTION_REPEAT);
press(ACTION_CTRL);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) ctrl(key_a), (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
for (int i = 0; i < NUM_REPEATS + 1; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) ctrl(key_a), (uint32_t) asdf_get_code());
}
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing and holding 'A' autorepeats 'A'
void holding_a_autorepeats_a(void)
{
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(ASDF_AUTOREPEAT_TIME_MS);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing and holding 'A' autorepeats 'A'
void holding_a_autorepeats_slow_then_fast(void)
{
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(ASDF_AUTOREPEAT_TIME_MS);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
}
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing and holding 'A' and 'B' within less than debounce interval
// eventually returns 'A' then 'B'
void pressing_a_then_b_before_debounce_gives_a_then_b(void)
{
press_no_debounce(key_a);
// press B very quickly after a
keyscan_delay(1);
press(key_b);
// first get back A
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// next get back B
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
// and then verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing and holding a series of keys (up to buffer size) in rapid
// succession, allowing each key to debounce, before sending the next, sends all
// the keys in order. (n-key rollover)
void test_key_sequence_nkro(void)
{
for (int i = 0; i < (int32_t) strlen(test_string); i++) {
press((asdf_keycode_t) test_string[i]);
}
for (int i = 0; i < (int32_t) strlen(test_string); i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) test_string[i], (int32_t) asdf_get_code());
}
// and then verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// pressing and holding a series of keys (up to buffer size) in rapid succession
// without waiting for prior keys to debounce, eventually debounces and sends
// all the keys in order. (n-key rollover)
void test_key_sequence_nkro_simultaneous_debounce(void)
{
for (int i = 0; i < (int32_t) strlen(test_string); i++) {
press_no_debounce((asdf_keycode_t) test_string[i]);
keyscan_delay(1);
}
// several keys are already debounced, but now make sure they all are:
keyscan_delay(ASDF_DEBOUNCE_TIME_MS);
for (int i = 0; i < (int32_t) strlen(test_string); i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) test_string[i], (int32_t) asdf_get_code());
}
// and then verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// holding 'A' then pressing 'B' before autorepeat interval and holding 'B' gives 'A', then repeats
// 'B'
void holding_a_briefly_then_holding_b_gives_a_and_repeats_b(void)
{
press(key_a);
keyscan_delay(ASDF_AUTOREPEAT_TIME_MS / 2);
press(key_b);
// hold "a" and "b" for autorepeat delay:
keyscan_delay(ASDF_AUTOREPEAT_TIME_MS);
// hold "a" and "b" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
// should get "a" back, then "b"
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
// now get back NUM_REEPEATS repetitions of "b"
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
}
// and then verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// holding 'B' while repeating 'A' starts autorepeat delay, then starts repeating 'B'
void holding_a_then_holding_b_autorepeats_a_then_autorepeats_b(void)
{
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// hold "a" for AUTOREPEAT delay
keyscan_delay(ASDF_AUTOREPEAT_TIME_MS);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
// empty the buffer to make room for 'B'
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
}
// now press "b" while "a" is autorepeating:
press(key_b);
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
// hold "a" for autorepeat delay
keyscan_delay(ASDF_AUTOREPEAT_TIME_MS);
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
// empty the buffer to make room for 'B'
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
}
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
// Pressing and holding 'A' then holding 'B' with repeat key held repeats 'A' then 'B'
void repeating_with_a_then_adding_b_repeats_a_then_repeats_b(void)
{
press(ACTION_REPEAT);
press(key_a);
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
// empty the buffer to make room for 'B'
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) key_a, (uint32_t) asdf_get_code());
}
// now press "b" while "a" is autorepeating:
press(key_b);
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
// hold "a" for NUM_REPEATS repeat cycles:
keyscan_delay(NUM_REPEATS * ASDF_REPEAT_TIME_MS);
// empty the buffer to make room for 'B'
for (int i = 0; i < NUM_REPEATS; i++) {
TEST_ASSERT_EQUAL_INT32((int32_t) key_b, (uint32_t) asdf_get_code());
}
// and verify there are no more codes in buffer:
TEST_ASSERT_EQUAL_INT32((int32_t) ASDF_INVALID_CODE, (int32_t) asdf_get_code());
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(pressing_a_gives_nothing_before_debounce);
RUN_TEST(pressing_a_gives_a);
RUN_TEST(pressing_shift_a_gives_shifted_a);
RUN_TEST(pressing_caps_a_gives_caps_a);
RUN_TEST(pressing_ctrl_a_gives_ctrl_a);
RUN_TEST(pressing_rept_a_repeats_a);
RUN_TEST(pressing_shift_rept_a_repeats_shifted_a);
RUN_TEST(pressing_caps_rept_a_repeats_caps_a);
RUN_TEST(holding_a_autorepeats_a);
RUN_TEST(holding_a_autorepeats_slow_then_fast);
RUN_TEST(pressing_a_then_b_before_debounce_gives_a_then_b);
RUN_TEST(test_key_sequence_nkro);
RUN_TEST(test_key_sequence_nkro_simultaneous_debounce);
RUN_TEST(holding_a_briefly_then_holding_b_gives_a_and_repeats_b);
RUN_TEST(holding_a_then_holding_b_autorepeats_a_then_autorepeats_b);
RUN_TEST(repeating_with_a_then_adding_b_repeats_a_then_repeats_b);
return UNITY_END();
}

View File

@ -0,0 +1,201 @@
#include <stdio.h>
#include <stdint.h>
#include "unity.h"
#include "asdf.h"
#include "asdf_buffer.h"
#define TEST_VALUE 'a'
#define MAX_BUFFER ASDF_BUFFER_POOL_SIZE
#define HALF_BUFFER (ASDF_BUFFER_POOL_SIZE / 2)
static const char test_string[] = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char * const more_strings[] = {
"abcdefghijkl",
"12345",
"ABCDEFG",
"The quick brown",
"We the people",
"+"
};
static asdf_buffer_handle_t handle;
void setUp(void)
{
asdf_buffer_init();
handle = asdf_buffer_new(MAX_BUFFER);
}
void tearDown(void) {}
// allocating first buffer returns handle 0
void test_allocating_first_buffer_returns_handle_0(void)
{
TEST_ASSERT_EQUAL_INT32(0, (int32_t) handle);
}
// allocating second buffer returns handle 1
void test_allocating_second_buffer_returns_handle_1(void)
{
asdf_buffer_handle_t handle_1;
asdf_buffer_handle_t handle_2;
asdf_buffer_init();
handle_1 = asdf_buffer_new(HALF_BUFFER);
TEST_ASSERT_EQUAL_INT32(0, (int32_t) handle_1);
handle_2 = asdf_buffer_new(HALF_BUFFER);
TEST_ASSERT_EQUAL_INT32(1, (int32_t) handle_2);
}
// allocating more buffers than available returns invalid buffer handle
void test_allocating_too_many_buffers_returns_invalid(void)
{
asdf_buffer_init();
for (int i = 0; i <= ASDF_BUFFER_NUM_HANDLES; i++) {
handle = asdf_buffer_new(1);
}
TEST_ASSERT_EQUAL_INT32(ASDF_BUFFER_INVALID, (int32_t) handle);
}
// all of the alloted handles can be allocated
void test_all_handles_are_allocated(void)
{
asdf_buffer_init();
for (int i = 0; i < ASDF_BUFFER_NUM_HANDLES; i++) {
handle = asdf_buffer_new(1);
TEST_ASSERT_EQUAL_INT32(i, (int32_t) handle);
}
// and one more should be an invalid handle:
handle = asdf_buffer_new(1);
TEST_ASSERT_EQUAL_INT32(ASDF_BUFFER_INVALID, (int32_t) handle);
}
// allocating more space than available returns invalid buffer handle
void test_allocating_too_much_space_returns_invalid(void)
{
asdf_buffer_init();
handle = asdf_buffer_new(MAX_BUFFER + 1);
TEST_ASSERT_EQUAL_INT32(ASDF_BUFFER_INVALID, (int32_t) handle);
}
// get from an invalid buffer returns invalid code
void test_get_from_invalid_handle_returns_invalid_code(void)
{
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_buffer_get(ASDF_BUFFER_INVALID));
}
void test_get_from_unallocated_handle_returns_invalid_code(void)
{
asdf_keycode_t code = asdf_buffer_get(ASDF_BUFFER_NUM_HANDLES-1);
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) code);
}
// retrieving from empty queue gives invalid code
void get_from_empty_queue_returns_error(void)
{
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_buffer_get(handle));
}
// adding and retrieving give the same code back.
void sending_code_and_retrieve_returns_same_code(void)
{
asdf_buffer_put(handle, TEST_VALUE);
TEST_ASSERT_EQUAL_INT32(TEST_VALUE, (int32_t) asdf_buffer_get(handle));
}
// adding then fetching a string of codes one-by-one gives the same string back in order
void test_adding_and_retrieving_string_one_by_one(void)
{
for (int i = 0; i < (int) sizeof(test_string); i++) {
asdf_buffer_put(handle, (asdf_keycode_t) test_string[i]);
TEST_ASSERT_EQUAL_INT32((int32_t) test_string[i], (int32_t) asdf_buffer_get(handle));
}
}
// Filling the buffer first, then retrieving the characters from the buffer
// should return the same string.
void test_fill_buffer_then_retrieve_string(void)
{
for (int sent = 0; sent < MAX_BUFFER; sent++) {
asdf_buffer_put(handle, (asdf_keycode_t) test_string[sent]);
}
for (int received = 0; received < MAX_BUFFER; received++) {
int32_t code = (int32_t) asdf_buffer_get(handle);
TEST_ASSERT_EQUAL_INT32((int32_t) test_string[received],code);
}
// assert that next code request returns invalid code:
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_buffer_get(handle));
}
// adding a string longer than the buffer length gives the first BUFFER_LENGTH
// characters back, quietly dropping the overflow.
void test_overfilling_buffer_and_retrieve_drops_overflow(void)
{
// send the entire test string to overflow the buffer.
for (int i = 0; i < (int) sizeof(test_string); i++) {
asdf_buffer_put(handle, (asdf_keycode_t) test_string[i]);
}
// read until invalid character is received, testing that each character is
// correct.
for (int i = 0; i < MAX_BUFFER; i++) {
asdf_keycode_t code = asdf_buffer_get(handle);
TEST_ASSERT_EQUAL_INT32((int32_t) test_string[i], (int32_t) code);
}
// the next code request returns invalid code:
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_buffer_get(handle));
}
// with an alternating pattern of adding and retrieving codes, the sent code string matches the retrieved string.
void test_send_get_multiple_strings(void)
{
for (int i = 0; '+' != more_strings[i][0]; i++) {
for (const char * chrptr = (const char *) &more_strings[i][0]; *chrptr; chrptr++) {
asdf_buffer_put(handle, (asdf_keycode_t) *chrptr);
}
// read until invalid character is received, testing that each character is
// correct.
for (const char * chrptr = (const char *) &more_strings[i][0]; *chrptr; chrptr++) {
asdf_keycode_t code = asdf_buffer_get(handle);
TEST_ASSERT_EQUAL_INT32((int32_t) *chrptr, (int32_t) code);
}
// the next code request returns invalid code:
TEST_ASSERT_EQUAL_INT32(ASDF_INVALID_CODE, (int32_t) asdf_buffer_get(handle));
}
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_allocating_first_buffer_returns_handle_0);
RUN_TEST(test_allocating_second_buffer_returns_handle_1);
RUN_TEST(test_allocating_too_many_buffers_returns_invalid);
RUN_TEST(test_all_handles_are_allocated);
RUN_TEST(test_allocating_too_much_space_returns_invalid);
RUN_TEST(test_get_from_invalid_handle_returns_invalid_code);
RUN_TEST(test_get_from_unallocated_handle_returns_invalid_code);
RUN_TEST(get_from_empty_queue_returns_error);
RUN_TEST(sending_code_and_retrieve_returns_same_code);
RUN_TEST(test_adding_and_retrieving_string_one_by_one);
RUN_TEST(test_fill_buffer_then_retrieve_string);
RUN_TEST(test_overfilling_buffer_and_retrieve_drops_overflow);
RUN_TEST(test_send_get_multiple_strings);
return UNITY_END();
}

View File

@ -0,0 +1,118 @@
#include <stdint.h>
#include "unity.h"
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_modifiers.h"
#include "asdf_keymaps.h"
#define TESTALPHA 'a'
#define TESTNUM '2'
#define TESTMAP(row, col, mapname, mapname2) \
do { \
asdf_keycode_t expected = mapname##_matrix[(row)][(col)]; \
asdf_keycode_t result = asdf_keymaps_get_code((row), (col), MOD_ ## mapname2 ## _MAP); \
TEST_ASSERT_EQUAL_INT(expected, result); \
} while (0);
#define TEST_VALID_CODE(position) do { \
coord_t pos = position; \
TEST_ASSERT_FALSE(pos.row == -1); \
TEST_ASSERT_FALSE(pos.col == -1); \
} while (0);
#define TESTPLAIN(row, col, n) TESTMAP((row), (col), PLAIN, n)
#define TESTSHIFT(row, col, n) TESTMAP((row), (col), SHIFT, n)
#define TESTCAPS(row, col, n) TESTMAP((row), (col), CAPS, n)
#define TESTCTRL(row, col, n) TESTMAP((row), (col), CTRL, n)
typedef asdf_keycode_t keycode_matrix_t[ASDF_NUM_ROWS][ASDF_NUM_COLS];
typedef struct {
int32_t row;
int32_t col;
} coord_t;
static const keycode_matrix_t PLAIN_matrix = ASCII_PLAIN_MAP;
static const keycode_matrix_t SHIFT_matrix = ASCII_SHIFT_MAP;
static const keycode_matrix_t CAPS_matrix = ASCII_CAPS_MAP;
static const keycode_matrix_t CTRL_matrix = ASCII_CTRL_MAP;
static coord_t alpha_sample;
static coord_t num_sample;
coord_t *find_code(asdf_keycode_t code)
{
uint32_t done = 0;
static coord_t location = { .row = -1, .col = -1 };
for (uint32_t row = 0; !done && (row < ASDF_NUM_ROWS); row++) {
for (uint32_t col = 0; !done && (col < ASDF_NUM_COLS); col++) {
if (PLAIN_matrix[row][col] == code) {
done = 1;
location.row = row;
location.col = col;
}
}
}
return &location;
}
void setUp(void)
{
coord_t *temp;
asdf_keymaps_init();
temp = find_code(TESTALPHA);
alpha_sample = *temp;
temp = find_code(TESTNUM);
num_sample = *temp;
}
void tearDown(void) {}
void test_chars_are_in_map(void) {
TEST_VALID_CODE(alpha_sample);
TEST_VALID_CODE(num_sample);
}
void plain_map_gives_plain_values(void)
{
TESTPLAIN(alpha_sample.row, alpha_sample.col, PLAIN);
TESTPLAIN(num_sample.row, num_sample.col, PLAIN);
}
void shift_map_gives_shift_values(void)
{
TESTSHIFT(alpha_sample.row, alpha_sample.col, SHIFT);
TESTSHIFT(num_sample.row, num_sample.col, SHIFT);
}
void caps_map_gives_caps_values(void)
{
TESTCAPS(alpha_sample.row, alpha_sample.col, CAPS);
TESTCAPS(num_sample.row, num_sample.col, CAPS);
}
void ctrl_map_gives_ctrl_values(void)
{
TESTCTRL(alpha_sample.row, alpha_sample.col, CTRL);
TESTCTRL(num_sample.row, num_sample.col, CTRL);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_chars_are_in_map);
RUN_TEST(plain_map_gives_plain_values);
RUN_TEST(shift_map_gives_shift_values);
RUN_TEST(caps_map_gives_caps_values);
RUN_TEST(ctrl_map_gives_ctrl_values);
return UNITY_END();
}

View File

@ -0,0 +1,315 @@
#include <stdint.h>
#include "unity.h"
#include "asdf_modifiers.h"
#define TESTMAP(a) \
do { \
uint32_t map = (uint32_t) asdf_modifier_index(); \
TEST_ASSERT_EQUAL_INT((a), map); \
} while (0);
void setUp(void)
{
asdf_modifiers_init();
}
void tearDown(void) {}
// initial map is plain
void initial_map_is_plain(void)
{
TESTMAP(MOD_PLAIN_MAP);
}
// SHIFT gives shift map
void shift_gives_shiftmap(void)
{
asdf_modifier_shift_activate();
TESTMAP(MOD_SHIFT_MAP);
}
// SHIFT press & release gives plain map
void shift_and_release_gives_plain(void)
{
asdf_modifier_shift_activate();
TESTMAP(MOD_SHIFT_MAP);
asdf_modifier_shift_deactivate();
TESTMAP(MOD_PLAIN_MAP);
}
// CAPSLOCK gives caps map
void capslock_gives_caps(void)
{
asdf_modifier_capslock_activate();
TESTMAP(MOD_CAPS_MAP);
}
// CAPLOCK press and release gives caps map
void capslock_and_release_gives_caps(void)
{
asdf_modifier_capslock_activate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
}
// CAPS-release-CAPS give plain
void caps_release_caps_gives_plain(void)
{
asdf_modifier_capslock_activate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_capslock_activate();
TESTMAP(MOD_PLAIN_MAP);
}
// CAPS-release-CAPS-release will first activate CAPS mode then deactivation,
// resulting in final plain map.
void caps_release_caps_release_gives_plain(void)
{
asdf_modifier_capslock_activate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_capslock_activate();
TESTMAP(MOD_PLAIN_MAP);
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_PLAIN_MAP);
}
// If SHIFT and CAPS are activated, the SHIFT map results
void shift_and_caps_gives_shift(void)
{
asdf_modifier_capslock_activate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_shift_activate();
TESTMAP(MOD_SHIFT_MAP);
}
// IF CAPS map is active, pressing and releasing SHIFT reverts to CAPS
void caps_shift_unshift_gives_caps(void)
{
asdf_modifier_capslock_activate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_shift_activate();
TESTMAP(MOD_SHIFT_MAP);
asdf_modifier_shift_deactivate();
TESTMAP(MOD_CAPS_MAP);
}
// Capslock and SHiftlock gives SHIFT
void capslock_shiftlock_gives_shift(void)
{
asdf_modifier_capslock_activate();
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_SHIFT_MAP);
}
// Pressing CAPSLOCK and SHIFTLOCK, then CAPSLOCK again gives shift map.
void capslock_shiftlock_capslock_gives_shift(void)
{
asdf_modifier_capslock_activate();
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_SHIFT_MAP);
asdf_modifier_capslock_activate();
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_SHIFT_MAP);
}
// Pressing CAPSLOCK and SHIFTLOCK, then press and releast SHIFT (to deactivate
// the shiftlock) again gives shift map.
void capslock_shiftlock_shift_gives_caps(void)
{
asdf_modifier_capslock_activate();
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CAPS_MAP);
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_SHIFT_MAP);
asdf_modifier_shift_activate();
asdf_modifier_shift_deactivate();
TESTMAP(MOD_CAPS_MAP);
}
// SHIFTLOCK press gives shift map
void shiftlock_gives_shift(void)
{
asdf_modifier_shiftlock_activate();
TESTMAP(MOD_SHIFT_MAP);
}
// SHIFTLOCK press and release gives shift map
void shiftlock_and_release_gives_shift(void)
{
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_SHIFT_MAP);
}
// SHIFTLOCK and SHIFT gives shift map
void shiftlock_shift_gives_shift(void)
{
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_SHIFT_MAP);
asdf_modifier_shift_activate();
TESTMAP(MOD_SHIFT_MAP);
}
// SHIFTLOCK and SHIFT press and release gives plain map
void shiftlock_shift_release_gives_plain(void)
{
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_SHIFT_MAP);
asdf_modifier_shift_activate();
asdf_modifier_shift_deactivate();
TESTMAP(MOD_PLAIN_MAP);
}
// CTRL gives ctrl map
void ctrl_gives_ctrl_map(void)
{
asdf_modifier_ctrl_activate();
TESTMAP(MOD_CTRL_MAP);
}
// CTRL press and release gives plain map
void ctrl_release_gives_plain_map(void)
{
asdf_modifier_ctrl_activate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_ctrl_activate();
asdf_modifier_ctrl_deactivate();
TESTMAP(MOD_PLAIN_MAP);
}
// SHIFT + CTRL is ctrl map
void ctrl_shift_gives_ctrl_map(void)
{
asdf_modifier_ctrl_activate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_shift_activate();
TESTMAP(MOD_CTRL_MAP);
}
// CAPSLOCK and CTRL is ctrl map
void ctrl_caps_gives_ctrl_map(void)
{
asdf_modifier_ctrl_activate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_capslock_activate();
TESTMAP(MOD_CTRL_MAP);
}
// SHIFTLOCK and CTRL is ctrl map
void ctrl_shiftlock_gives_ctrl_map(void)
{
asdf_modifier_ctrl_activate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_shiftlock_activate();
TESTMAP(MOD_CTRL_MAP);
}
void ctrl_double_caps_returns_to_ctrl_map(void)
{
asdf_modifier_ctrl_activate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_capslock_activate();
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_capslock_activate();
asdf_modifier_capslock_deactivate();
TESTMAP(MOD_CTRL_MAP);
}
void ctrl_double_shiftlock_returns_to_ctrl_map(void)
{
asdf_modifier_ctrl_activate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_CTRL_MAP);
asdf_modifier_shiftlock_activate();
asdf_modifier_shiftlock_deactivate();
TESTMAP(MOD_CTRL_MAP);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(initial_map_is_plain);
RUN_TEST(shift_gives_shiftmap);
RUN_TEST(shift_and_release_gives_plain);
RUN_TEST(capslock_gives_caps);
RUN_TEST(capslock_and_release_gives_caps);
RUN_TEST(caps_release_caps_gives_plain);
RUN_TEST(caps_release_caps_release_gives_plain);
RUN_TEST(shift_and_caps_gives_shift);
RUN_TEST(caps_shift_unshift_gives_caps);
RUN_TEST(capslock_shiftlock_gives_shift);
RUN_TEST(capslock_shiftlock_capslock_gives_shift);
RUN_TEST(capslock_shiftlock_shift_gives_caps);
RUN_TEST(shiftlock_gives_shift);
RUN_TEST(shiftlock_and_release_gives_shift);
RUN_TEST(shiftlock_shift_gives_shift);
RUN_TEST(shiftlock_shift_release_gives_plain);
RUN_TEST(ctrl_gives_ctrl_map);
RUN_TEST(ctrl_release_gives_plain_map);
RUN_TEST(ctrl_shift_gives_ctrl_map);
RUN_TEST(ctrl_caps_gives_ctrl_map);
RUN_TEST(ctrl_shiftlock_gives_ctrl_map);
RUN_TEST(ctrl_double_caps_returns_to_ctrl_map);
RUN_TEST(ctrl_double_shiftlock_returns_to_ctrl_map);
// toggle shiftlock_mode switches the shiftlock behavior to toggle_mode
// calling toggle_shiftlock_mode twice leaves shiftlock behavior in hold mode
// calling toggle_shiftlock_mode three times leaves shiftlock behavior in toggle mode
return UNITY_END();
}

View File

@ -0,0 +1,448 @@
#include <stdio.h>
#include <stdint.h>
#include "unity.h"
#include "asdf_repeat.h"
#define REPEAT_TIMED_OUT 10000
#define NUM_REPETITIONS 10
uint32_t count_repeat_ticks(uint32_t timeout)
{
uint32_t count = 0;
uint32_t test;
do {
test = asdf_repeat();
count++;
} while (!test && count < timeout);
return count;
}
void setUp(void)
{
asdf_repeat_init();
}
void tearDown(void) {}
// On initialization, autorepeat should be enabled by default.
void test_asdf_repeat_init_resets_to_autorepeat_default(void)
{
uint32_t delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
}
// If autorepeat is turned off, then holding down a simulated key should not
// cause a repeat event.
void test_asdf_repeat_no_repeat_if_auto_turned_off(void)
{
uint32_t delay;
asdf_repeat_auto_off();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
}
// If autorepeat is turned on, then holding down a simulated key should cause a
// repeat event after the autorepeat interval.
void test_asdf_repeat_autorepeat_if_auto_turned_on(void)
{
uint32_t delay;
asdf_repeat_auto_off();
asdf_repeat_auto_on();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
}
// After the autorepeat interval, subsequent repeat events should occur at the
// regular repeat interval.
void test_asf_repeat_autorepeat_fast_repeat_after_delay(void)
{
uint32_t delay;
// wait out the autorepeat delay
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
// now verify the next repeat interval is short:
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
}
// If autorepeat is turned on, then holding down a key should cause a repeat
// event at the autorepeat interval. This should be true if autorepeat was
// previously off, or if it was already on, so test both cases here.
void test_asdf_repeat_auto_repeat_if_auto_turned_on(void)
{
uint32_t delay;
asdf_repeat_auto_on();
asdf_repeat_auto_on();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
asdf_repeat_auto_off();
asdf_repeat_auto_on();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
}
// When in autorepeat mode, calling asdf_repeat_reset_count() should reset the
// repeat timer to the autorepeat interval.
void test_asdf_repeat_reset_count_works_in_autorepeat_mode(void)
{
uint32_t delay;
// wait 1/2 of autorepeat time and release a key
delay = count_repeat_ticks(ASDF_AUTOREPEAT_TIME_MS / 2);
TEST_ASSERT_EQUAL_INT((ASDF_AUTOREPEAT_TIME_MS / 2), delay);
asdf_repeat_reset_count();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
}
// When in repeat mode (repeat key held down), calling asdf_repeat_reset_count()
// should reset the repeat timer to the repeat interval.
void test_asdf_repeat_reset_count_works_in_repeat_mode(void)
{
uint32_t delay;
// wait 1/2 of autorepeat time and release a key
asdf_repeat_activate();
delay = count_repeat_ticks(ASDF_REPEAT_TIME_MS / 2);
TEST_ASSERT_EQUAL_INT((ASDF_REPEAT_TIME_MS / 2), delay);
asdf_repeat_reset_count();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
}
// When Autoreat is enabled, activating repeat mode (pressing the repeat key)
// should cause repeat events to occur at the fast repeat rate, skipping the
// autorepeat interval.
void test_asdf_repeat_activate_with_auto_on(void)
{
uint32_t delay;
asdf_repeat_auto_on();
asdf_repeat_activate();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
}
// When Autoreat is off, activating repeat mode (pressing the repeat key)
// should cause repeat events to occur at the fast repeat rate
void test_asdf_repeat_activate_with_auto_off(void)
{
uint32_t delay;
asdf_repeat_auto_off();
asdf_repeat_activate();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
}
// If autorepeat is disabled, then activating and deactivating repeat mode
// (pressing and releasing the repeat key) should return to the autorepeat
// disabled mode.
void test_asdf_repeat_deactivate_returns_to_baseline_no_repeat(void)
{
uint32_t delay;
asdf_repeat_auto_off();
// simulate a brief REPEAT key press (3 repeat cycles)
asdf_repeat_activate();
delay = 0;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
}
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
asdf_repeat_deactivate();
// now that repeat is deactivated, we should time out before hitting a repeat
// event:
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
}
// If autorepeat is enabled, then activating and deactivating repeat mode
// (pressing and releasing the repeat key) should return to the autorepeat
// enabled mode.
void test_asdf_repeat_deactivate_returns_to_baseline_autorepeat(void)
{
uint32_t delay;
// simulate a brief REPEAT key press (1/2 autorepeat time)
asdf_repeat_activate();
delay = 0;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
}
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
asdf_repeat_deactivate();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
}
// When Autoreat is enabled, and the autorepeat timer is activated by holding
// down a key, then activating repeat (pressing the repeat key) should skip the
// rest of the autorepeat interval, and cause repeat events to occur at the fast
// repeat rate.
void test_asdf_repeat_repeat_key_circumvents_initial_autorepeat_delay(void)
{
uint32_t delay;
// simulate a brief keypress (1/2 autorepeat time)
delay = count_repeat_ticks(ASDF_AUTOREPEAT_TIME_MS / 2);
TEST_ASSERT_EQUAL_INT((ASDF_AUTOREPEAT_TIME_MS / 2), delay);
// simulate pressing the REPEAT key in the middle of an autorepeat interval
asdf_repeat_activate();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
}
// If autorepeat is on, and a key is being held down to start the autorepeat
// interval, then turning off autorepeat mode should prevent the key from
// repeating.
void test_asdf_repeat_turning_off_auto_cancels_autorepeat_delay_in_progress(void)
{
uint32_t delay;
asdf_repeat_auto_on();
// simulate a brief keypress (1/2 autorepeat time)
delay = count_repeat_ticks(ASDF_AUTOREPEAT_TIME_MS / 2);
TEST_ASSERT_EQUAL_INT((ASDF_AUTOREPEAT_TIME_MS / 2), delay);
asdf_repeat_auto_off();
// simulate continued holding down key
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
}
// If a key is autorepeating (held down until it repeats, without the repeat key
// being held down), then turning off autorepeat mode should stop the key from
// repeating.
void test_asdf_repeat_turning_off_auto_cancels_autorepeating_keypress(void)
{
uint32_t delay;
asdf_repeat_auto_on();
// simulate an autorepeating key. Wait out entire autorepeat delay.
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
// wait NUM_REPETITIONS repeat cycles:
delay = 0;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
}
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
asdf_repeat_auto_off();
for (delay = 0; !asdf_repeat() && (delay < REPEAT_TIMED_OUT); delay++) {
}
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
}
// If you press the REPEAT key while a key is already autorepeating (i.e., after
// the autorepeat delay interval), then the repeat timing shall not be affected.
void test_asdf_repeat_activate_while_autorepeating_wont_affect_timing(void)
{
uint32_t delay;
asdf_repeat_auto_on();
// simulate an autorepeating key. Wait out entire autorepeat delay.
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
// wait 1/2 fast repeat cycle:
// simulate an autorepeating key. Wait out entire autorepeat delay.
delay = count_repeat_ticks(ASDF_REPEAT_TIME_MS / 2);
TEST_ASSERT_EQUAL_INT((ASDF_REPEAT_TIME_MS / 2), delay);
// turn on repeat mode (press REPEAT key)
asdf_repeat_activate();
// now verify the repeat interval was not affected. Finish the current repeat
// interval
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
}
// If in autorepeat mode and the repeat key is released while a key is
// repeating, the next repeat event should occur after a new autorepeat delay
// interval.
void test_asdf_repeat_deactivate_while_repeating_resets_autorepeat_counter(void)
{
uint32_t delay;
asdf_repeat_auto_on();
asdf_repeat_activate();
// wait NUM_REPETITIONS repeat cycles:
delay = 0;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
}
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
// releast REPEAT key:
asdf_repeat_deactivate();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
// should have waited entire autorepeat delay interval
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
}
// If autorepeat is disabled and the repeat key is released while a key is
// repeating, then the key should stop repeating.
void test_asdf_repeat_deactivate_while_repeating_stops_repeating(void)
{
uint32_t delay;
asdf_repeat_auto_off();
asdf_repeat_activate();
// wait NUM_REPETITIONS repeat cycles:
delay = 0;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
}
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
// releast REPEAT key:
asdf_repeat_deactivate();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
// should have waited entire autorepeat delay interval
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
}
// pressing a new value key when REPEAT is active should start repeating right
// away.
void test_asdf_repeat_new_key_while_repeat_active_keeps_repeating(void)
{
uint32_t delay;
asdf_repeat_activate();
// wait NUM_REPETITIONS repeat cycles:
delay = 0;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
}
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
// simulate half a repeat interval
delay = count_repeat_ticks(ASDF_REPEAT_TIME_MS / 2);
// simulate a new key press:
asdf_repeat_reset_count();
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
// should have waited the key repeat interval
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
}
// pressing a new value key when autorepeating should start new autorepeat
// delay.
void test_asdf_repeat_new_key_while_autorepeating_starts_new_autorepeat(void)
{
uint32_t delay;
asdf_repeat_auto_on();
// simulate an autorepeating key. Wait out entire autorepeat delay.
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
// wait NUM_REPETITIONS repeat cycles:
delay = 0;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
}
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
// simulate new keypress:
asdf_repeat_reset_count();
// now measure interval until next repeat event.
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_asdf_repeat_init_resets_to_autorepeat_default);
RUN_TEST(test_asdf_repeat_no_repeat_if_auto_turned_off);
RUN_TEST(test_asdf_repeat_auto_repeat_if_auto_turned_on);
RUN_TEST(test_asf_repeat_autorepeat_fast_repeat_after_delay);
RUN_TEST(test_asdf_repeat_reset_count_works_in_autorepeat_mode);
RUN_TEST(test_asdf_repeat_reset_count_works_in_repeat_mode);
RUN_TEST(test_asdf_repeat_activate_with_auto_on);
RUN_TEST(test_asdf_repeat_activate_with_auto_off);
RUN_TEST(test_asdf_repeat_deactivate_returns_to_baseline_autorepeat);
RUN_TEST(test_asdf_repeat_deactivate_returns_to_baseline_no_repeat);
RUN_TEST(test_asdf_repeat_repeat_key_circumvents_initial_autorepeat_delay);
RUN_TEST(test_asdf_repeat_activate_while_autorepeating_wont_affect_timing);
RUN_TEST(test_asdf_repeat_turning_off_auto_cancels_autorepeating_keypress);
RUN_TEST(test_asdf_repeat_turning_off_auto_cancels_autorepeat_delay_in_progress);
RUN_TEST(test_asdf_repeat_deactivate_while_repeating_resets_autorepeat_counter);
RUN_TEST(test_asdf_repeat_deactivate_while_repeating_stops_repeating);
RUN_TEST(test_asdf_repeat_new_key_while_repeat_active_keeps_repeating);
RUN_TEST(test_asdf_repeat_new_key_while_autorepeating_starts_new_autorepeat);
return UNITY_END();
}

View File

@ -0,0 +1,118 @@
# ==========================================
# Unity Project - A Test Framework for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
if RUBY_PLATFORM =~ /(win|w)32$/
begin
require 'Win32API'
rescue LoadError
puts 'ERROR! "Win32API" library not found'
puts '"Win32API" is required for colour on a windows machine'
puts ' try => "gem install Win32API" on the command line'
puts
end
# puts
# puts 'Windows Environment Detected...'
# puts 'Win32API Library Found.'
# puts
end
class ColourCommandLine
def initialize
return unless RUBY_PLATFORM =~ /(win|w)32$/
get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
@set_console_txt_attrb =
Win32API.new('kernel32', 'SetConsoleTextAttribute', %w[L N], 'I')
@hout = get_std_handle.call(-11)
end
def change_to(new_colour)
if RUBY_PLATFORM =~ /(win|w)32$/
@set_console_txt_attrb.call(@hout, win32_colour(new_colour))
else
"\033[30;#{posix_colour(new_colour)};22m"
end
end
def win32_colour(colour)
case colour
when :black then 0
when :dark_blue then 1
when :dark_green then 2
when :dark_cyan then 3
when :dark_red then 4
when :dark_purple then 5
when :dark_yellow, :narrative then 6
when :default_white, :default, :dark_white then 7
when :silver then 8
when :blue then 9
when :green, :success then 10
when :cyan, :output then 11
when :red, :failure then 12
when :purple then 13
when :yellow then 14
when :white then 15
else
0
end
end
def posix_colour(colour)
# ANSI Escape Codes - Foreground colors
# | Code | Color |
# | 39 | Default foreground color |
# | 30 | Black |
# | 31 | Red |
# | 32 | Green |
# | 33 | Yellow |
# | 34 | Blue |
# | 35 | Magenta |
# | 36 | Cyan |
# | 37 | Light gray |
# | 90 | Dark gray |
# | 91 | Light red |
# | 92 | Light green |
# | 93 | Light yellow |
# | 94 | Light blue |
# | 95 | Light magenta |
# | 96 | Light cyan |
# | 97 | White |
case colour
when :black then 30
when :red, :failure then 31
when :green, :success then 32
when :yellow then 33
when :blue, :narrative then 34
when :purple, :magenta then 35
when :cyan, :output then 36
when :white, :default_white then 37
when :default then 39
else
39
end
end
def out_c(mode, colour, str)
case RUBY_PLATFORM
when /(win|w)32$/
change_to(colour)
$stdout.puts str if mode == :puts
$stdout.print str if mode == :print
change_to(:default_white)
else
$stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts
$stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print
end
end
end
def colour_puts(role, str)
ColourCommandLine.new.out_c(:puts, role, str)
end
def colour_print(role, str)
ColourCommandLine.new.out_c(:print, role, str)
end

View File

@ -0,0 +1,39 @@
# ==========================================
# Unity Project - A Test Framework for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
require_relative 'colour_prompt'
$colour_output = true
def report(message)
if !$colour_output
$stdout.puts(message)
else
message = message.join('\n') if message.class == Array
message.each_line do |line|
line.chomp!
colour = case line
when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i
Regexp.last_match(1).to_i.zero? ? :green : :red
when /PASS/
:green
when /^OK$/
:green
when /(?:FAIL|ERROR)/
:red
when /IGNORE/
:yellow
when /^(?:Creating|Compiling|Linking)/
:white
else
:silver
end
colour_puts(colour, line)
end
end
$stdout.flush
$stderr.flush
end

View File

@ -0,0 +1,36 @@
#this is a sample configuration file for generate_module
#you would use it by calling generate_module with the -ygenerate_config.yml option
#files like this are useful for customizing generate_module to your environment
:generate_module:
:defaults:
#these defaults are used in place of any missing options at the command line
:path_src: ../src/
:path_inc: ../src/
:path_tst: ../test/
:update_svn: true
:includes:
#use [] for no additional includes, otherwise list the includes on separate lines
:src:
- Defs.h
- Board.h
:inc: []
:tst:
- Defs.h
- Board.h
- Exception.h
:boilerplates:
#these are inserted at the top of generated files.
#just comment out or remove if not desired.
#use %1$s where you would like the file name to appear (path/extension not included)
:src: |
//-------------------------------------------
// %1$s.c
//-------------------------------------------
:inc: |
//-------------------------------------------
// %1$s.h
//-------------------------------------------
:tst: |
//-------------------------------------------
// Test%1$s.c : Units tests for %1$s.c
//-------------------------------------------

View File

@ -0,0 +1,306 @@
# ==========================================
# Unity Project - A Test Framework for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
# This script creates all the files with start code necessary for a new module.
# A simple module only requires a source file, header file, and test file.
# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware).
require 'rubygems'
require 'fileutils'
require 'pathname'
# TEMPLATE_TST
TEMPLATE_TST ||= '#include "unity.h"
%2$s#include "%1$s.h"
void setUp(void)
{
}
void tearDown(void)
{
}
void test_%1$s_NeedToImplement(void)
{
TEST_IGNORE_MESSAGE("Need to Implement %1$s");
}
'.freeze
# TEMPLATE_SRC
TEMPLATE_SRC ||= '%2$s#include "%1$s.h"
'.freeze
# TEMPLATE_INC
TEMPLATE_INC ||= '#ifndef _%3$s_H
#define _%3$s_H
%2$s
#endif // _%3$s_H
'.freeze
class UnityModuleGenerator
############################
def initialize(options = nil)
@options = UnityModuleGenerator.default_options
case options
when NilClass then @options
when String then @options.merge!(UnityModuleGenerator.grab_config(options))
when Hash then @options.merge!(options)
else raise 'If you specify arguments, it should be a filename or a hash of options'
end
# Create default file paths if none were provided
@options[:path_src] = "#{__dir__}/../src/" if @options[:path_src].nil?
@options[:path_inc] = @options[:path_src] if @options[:path_inc].nil?
@options[:path_tst] = "#{__dir__}/../test/" if @options[:path_tst].nil?
@options[:path_src] += '/' unless @options[:path_src][-1] == 47
@options[:path_inc] += '/' unless @options[:path_inc][-1] == 47
@options[:path_tst] += '/' unless @options[:path_tst][-1] == 47
# Built in patterns
@patterns = {
'src' => {
'' => { inc: [] }
},
'test' => {
'' => { inc: [] }
},
'dh' => {
'Driver' => { inc: [create_filename('%1$s', 'Hardware.h')] },
'Hardware' => { inc: [] }
},
'dih' => {
'Driver' => { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] },
'Interrupt' => { inc: [create_filename('%1$s', 'Hardware.h')] },
'Hardware' => { inc: [] }
},
'mch' => {
'Model' => { inc: [] },
'Conductor' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] },
'Hardware' => { inc: [] }
},
'mvp' => {
'Model' => { inc: [] },
'Presenter' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] },
'View' => { inc: [] }
}
}
end
############################
def self.default_options
{
pattern: 'src',
includes: {
src: [],
inc: [],
tst: []
},
update_svn: false,
boilerplates: {},
test_prefix: 'Test',
mock_prefix: 'Mock'
}
end
############################
def self.grab_config(config_file)
options = default_options
unless config_file.nil? || config_file.empty?
require 'yaml'
yaml_guts = YAML.load_file(config_file)
options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
raise "No :unity or :cmock section found in #{config_file}" unless options
end
options
end
############################
def files_to_operate_on(module_name, pattern = nil)
# strip any leading path information from the module name and save for later
subfolder = File.dirname(module_name)
module_name = File.basename(module_name)
# create triad definition
prefix = @options[:test_prefix] || 'Test'
triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] },
{ ext: '.h', path: @options[:path_inc], prefix: '', template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] },
{ ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst] }]
# prepare the pattern for use
pattern = (pattern || @options[:pattern] || 'src').downcase
patterns = @patterns[pattern]
raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil?
# single file patterns (currently just 'test') can reject the other parts of the triad
triad.select! { |v| v[:inc] == :tst } if pattern == 'test'
# Assemble the path/names of the files we need to work with.
files = []
triad.each do |cfg|
patterns.each_pair do |pattern_file, pattern_traits|
submodule_name = create_filename(module_name, pattern_file)
filename = cfg[:prefix] + submodule_name + cfg[:ext]
files << {
path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath,
name: submodule_name,
template: cfg[:template],
boilerplate: cfg[:boilerplate],
includes: case (cfg[:inc])
when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) })
when :inc then (@options[:includes][:inc] || [])
when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) })
end
}
end
end
files
end
############################
def create_filename(part1, part2 = '')
if part2.empty?
case (@options[:naming])
when 'bumpy' then part1
when 'camel' then part1
when 'snake' then part1.downcase
when 'caps' then part1.upcase
else part1
end
else
case (@options[:naming])
when 'bumpy' then part1 + part2
when 'camel' then part1 + part2
when 'snake' then part1.downcase + '_' + part2.downcase
when 'caps' then part1.upcase + '_' + part2.upcase
else part1 + '_' + part2
end
end
end
############################
def generate(module_name, pattern = nil)
files = files_to_operate_on(module_name, pattern)
# Abort if all of the module files already exist
all_files_exist = true
files.each do |file|
all_files_exist = false unless File.exist?(file[:path])
end
raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist
# Create Source Modules
files.each_with_index do |file, _i|
# If this file already exists, don't overwrite it.
if File.exist?(file[:path])
puts "File #{file[:path]} already exists!"
next
end
# Create the path first if necessary.
FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false)
File.open(file[:path], 'w') do |f|
f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil?
f.write(file[:template] % [file[:name],
file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join,
file[:name].upcase])
end
if @options[:update_svn]
`svn add \"#{file[:path]}\"`
if $!.exitstatus.zero?
puts "File #{file[:path]} created and added to source control"
else
puts "File #{file[:path]} created but FAILED adding to source control!"
end
else
puts "File #{file[:path]} created"
end
end
puts 'Generate Complete'
end
############################
def destroy(module_name, pattern = nil)
files_to_operate_on(module_name, pattern).each do |filespec|
file = filespec[:path]
if File.exist?(file)
if @options[:update_svn]
`svn delete \"#{file}\" --force`
puts "File #{file} deleted and removed from source control"
else
FileUtils.remove(file)
puts "File #{file} deleted"
end
else
puts "File #{file} does not exist so cannot be removed."
end
end
puts 'Destroy Complete'
end
end
############################
# Handle As Command Line If Called That Way
if $0 == __FILE__
destroy = false
options = {}
module_name = nil
# Parse the command line parameters.
ARGV.each do |arg|
case arg
when /^-d/ then destroy = true
when /^-u/ then options[:update_svn] = true
when /^-p\"?(\w+)\"?/ then options[:pattern] = Regexp.last_match(1)
when /^-s\"?(.+)\"?/ then options[:path_src] = Regexp.last_match(1)
when /^-i\"?(.+)\"?/ then options[:path_inc] = Regexp.last_match(1)
when /^-t\"?(.+)\"?/ then options[:path_tst] = Regexp.last_match(1)
when /^-n\"?(.+)\"?/ then options[:naming] = Regexp.last_match(1)
when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config(Regexp.last_match(1))
when /^(\w+)/
raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil?
module_name = arg
when /^-(h|-help)/
ARGV = [].freeze
else
raise "ERROR: Unknown option specified '#{arg}'"
end
end
unless ARGV[0]
puts ["\nGENERATE MODULE\n-------- ------",
"\nUsage: ruby generate_module [options] module_name",
" -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)",
" -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)",
" -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)",
' -p"MCH" sets the output pattern to MCH.',
' dh - driver hardware.',
' dih - driver interrupt hardware.',
' mch - model conductor hardware.',
' mvp - model view presenter.',
' src - just a source module, header and test. (DEFAULT)',
' test - just a test file.',
' -d destroy module instead of creating it.',
' -n"camel" sets the file naming convention.',
' bumpy - BumpyCaseFilenames.',
' camel - camelCaseFilenames.',
' snake - snake_case_filenames.',
' caps - CAPS_CASE_FILENAMES.',
' -u update subversion too (requires subversion command line)',
' -y"my.yml" selects a different yaml config file for module generation',
''].join("\n")
exit
end
raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil?
if destroy
UnityModuleGenerator.new(options).destroy(module_name)
else
UnityModuleGenerator.new(options).generate(module_name)
end
end

View File

@ -0,0 +1,471 @@
# ==========================================
# Unity Project - A Test Framework for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
class UnityTestRunnerGenerator
def initialize(options = nil)
@options = UnityTestRunnerGenerator.default_options
case options
when NilClass then @options
when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options))
when Hash then @options.merge!(options)
else raise 'If you specify arguments, it should be a filename or a hash of options'
end
require_relative 'type_sanitizer'
end
def self.default_options
{
includes: [],
defines: [],
plugins: [],
framework: :unity,
test_prefix: 'test|spec|should',
mock_prefix: 'Mock',
mock_suffix: '',
setup_name: 'setUp',
teardown_name: 'tearDown',
main_name: 'main', # set to :auto to automatically generate each time
main_export_decl: '',
cmdline_args: false,
use_param_tests: false
}
end
def self.grab_config(config_file)
options = default_options
unless config_file.nil? || config_file.empty?
require 'yaml'
yaml_guts = YAML.load_file(config_file)
options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
raise "No :unity or :cmock section found in #{config_file}" unless options
end
options
end
def run(input_file, output_file, options = nil)
@options.merge!(options) unless options.nil?
# pull required data from source file
source = File.read(input_file)
source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
tests = find_tests(source)
headers = find_includes(source)
testfile_includes = (headers[:local] + headers[:system])
used_mocks = find_mocks(testfile_includes)
testfile_includes = (testfile_includes - used_mocks)
testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
# build runner file
generate(input_file, output_file, tests, used_mocks, testfile_includes)
# determine which files were used to return them
all_files_used = [input_file, output_file]
all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty?
all_files_used += @options[:includes] unless @options[:includes].empty?
all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
all_files_used.uniq
end
def generate(input_file, output_file, tests, used_mocks, testfile_includes)
File.open(output_file, 'w') do |output|
create_header(output, used_mocks, testfile_includes)
create_externs(output, tests, used_mocks)
create_mock_management(output, used_mocks)
create_suite_setup(output)
create_suite_teardown(output)
create_reset(output, used_mocks)
create_main(output, input_file, tests, used_mocks)
end
return unless @options[:header_file] && !@options[:header_file].empty?
File.open(@options[:header_file], 'w') do |output|
create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
end
end
def find_tests(source)
tests_and_line_numbers = []
# contains characters which will be substituted from within strings, doing
# this prevents these characters from interferring with scrubbers
# @ is not a valid C character, so there should be no clashes with files genuinely containing these markers
substring_subs = { '{' => '@co@', '}' => '@cc@', ';' => '@ss@', '/' => '@fs@' }
substring_re = Regexp.union(substring_subs.keys)
substring_unsubs = substring_subs.invert # the inverse map will be used to fix the strings afterwords
substring_unsubs['@quote@'] = '\\"'
substring_unsubs['@apos@'] = '\\\''
substring_unre = Regexp.union(substring_unsubs.keys)
source_scrubbed = source.clone
source_scrubbed = source_scrubbed.gsub(/\\"/, '@quote@') # hide escaped quotes to allow capture of the full string/char
source_scrubbed = source_scrubbed.gsub(/\\'/, '@apos@') # hide escaped apostrophes to allow capture of the full string/char
source_scrubbed = source_scrubbed.gsub(/("[^"\n]*")|('[^'\n]*')/) { |s| s.gsub(substring_re, substring_subs) } # temporarily hide problematic
# characters within strings
source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments
source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments
lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line
| (;|\{|\}) /x) # Match ;, {, and } as end of lines
.map { |line| line.gsub(substring_unre, substring_unsubs) } # unhide the problematic characters previously removed
lines.each_with_index do |line, _index|
# find tests
next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/
arguments = Regexp.last_match(1)
name = Regexp.last_match(2)
call = Regexp.last_match(3)
params = Regexp.last_match(4)
args = nil
if @options[:use_param_tests] && !arguments.empty?
args = []
arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] }
end
tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 }
end
tests_and_line_numbers.uniq! { |v| v[:test] }
# determine line numbers and create tests to run
source_lines = source.split("\n")
source_index = 0
tests_and_line_numbers.size.times do |i|
source_lines[source_index..-1].each_with_index do |line, index|
next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/
source_index += index
tests_and_line_numbers[i][:line_number] = source_index + 1
break
end
end
tests_and_line_numbers
end
def find_includes(source)
# remove comments (block and line, in three steps to ensure correct precedence)
source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
# parse out includes
includes = {
local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten,
system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten
}
includes
end
def find_mocks(includes)
mock_headers = []
includes.each do |include_path|
include_file = File.basename(include_path)
mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}.*#{@options[:mock_suffix]}$/i
end
mock_headers
end
def create_header(output, mocks, testfile_includes = [])
output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
create_runtest(output, mocks)
output.puts("\n/*=======Automagically Detected Files To Include=====*/")
output.puts('#ifdef __WIN32__')
output.puts('#define UNITY_INCLUDE_SETUP_STUBS')
output.puts('#endif')
output.puts("#include \"#{@options[:framework]}.h\"")
output.puts('#include "cmock.h"') unless mocks.empty?
output.puts('#ifndef UNITY_EXCLUDE_SETJMP_H')
output.puts('#include <setjmp.h>')
output.puts('#endif')
output.puts('#include <stdio.h>')
if @options[:defines] && !@options[:defines].empty?
@options[:defines].each { |d| output.puts("#ifndef #{d}\n#define #{d}\n#endif /* #{d} */") }
end
if @options[:header_file] && !@options[:header_file].empty?
output.puts("#include \"#{File.basename(@options[:header_file])}\"")
else
@options[:includes].flatten.uniq.compact.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
testfile_includes.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
end
mocks.each do |mock|
output.puts("#include \"#{mock.gsub('.h', '')}.h\"")
end
output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
return unless @options[:enforce_strict_ordering]
output.puts('')
output.puts('int GlobalExpectCount;')
output.puts('int GlobalVerifyOrder;')
output.puts('char* GlobalOrderError;')
end
def create_externs(output, tests, _mocks)
output.puts("\n/*=======External Functions This Runner Calls=====*/")
output.puts("extern void #{@options[:setup_name]}(void);")
output.puts("extern void #{@options[:teardown_name]}(void);")
output.puts("\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif") if @options[:externc]
tests.each do |test|
output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
end
output.puts("#ifdef __cplusplus\n}\n#endif") if @options[:externc]
output.puts('')
end
def create_mock_management(output, mock_headers)
return if mock_headers.empty?
output.puts("\n/*=======Mock Management=====*/")
output.puts('static void CMock_Init(void)')
output.puts('{')
if @options[:enforce_strict_ordering]
output.puts(' GlobalExpectCount = 0;')
output.puts(' GlobalVerifyOrder = 0;')
output.puts(' GlobalOrderError = NULL;')
end
mocks = mock_headers.map { |mock| File.basename(mock) }
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Init();")
end
output.puts("}\n")
output.puts('static void CMock_Verify(void)')
output.puts('{')
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Verify();")
end
output.puts("}\n")
output.puts('static void CMock_Destroy(void)')
output.puts('{')
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Destroy();")
end
output.puts("}\n")
end
def create_suite_setup(output)
output.puts("\n/*=======Suite Setup=====*/")
output.puts('static void suite_setup(void)')
output.puts('{')
if @options[:suite_setup].nil?
# New style, call suiteSetUp() if we can use weak symbols
output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
output.puts(' suiteSetUp();')
output.puts('#endif')
else
# Old style, C code embedded in the :suite_setup option
output.puts(@options[:suite_setup])
end
output.puts('}')
end
def create_suite_teardown(output)
output.puts("\n/*=======Suite Teardown=====*/")
output.puts('static int suite_teardown(int num_failures)')
output.puts('{')
if @options[:suite_teardown].nil?
# New style, call suiteTearDown() if we can use weak symbols
output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
output.puts(' return suiteTearDown(num_failures);')
output.puts('#else')
output.puts(' return num_failures;')
output.puts('#endif')
else
# Old style, C code embedded in the :suite_teardown option
output.puts(@options[:suite_teardown])
end
output.puts('}')
end
def create_runtest(output, used_mocks)
cexception = @options[:plugins].include? :cexception
va_args1 = @options[:use_param_tests] ? ', ...' : ''
va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : ''
output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/")
output.puts('#define RUN_TEST_NO_ARGS') if @options[:use_param_tests]
output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\")
output.puts('{ \\')
output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\")
output.puts(' Unity.CurrentTestLineNumber = TestLineNum; \\')
output.puts(' if (UnityTestMatches()) { \\') if @options[:cmdline_args]
output.puts(' Unity.NumberOfTests++; \\')
output.puts(' CMock_Init(); \\') unless used_mocks.empty?
output.puts(' UNITY_CLR_DETAILS(); \\') unless used_mocks.empty?
output.puts(' if (TEST_PROTECT()) \\')
output.puts(' { \\')
output.puts(' CEXCEPTION_T e; \\') if cexception
output.puts(' Try { \\') if cexception
output.puts(" #{@options[:setup_name]}(); \\")
output.puts(" TestFunc(#{va_args2}); \\")
output.puts(' } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \\') if cexception
output.puts(' } \\')
output.puts(' if (TEST_PROTECT()) \\')
output.puts(' { \\')
output.puts(" #{@options[:teardown_name]}(); \\")
output.puts(' CMock_Verify(); \\') unless used_mocks.empty?
output.puts(' } \\')
output.puts(' CMock_Destroy(); \\') unless used_mocks.empty?
output.puts(' UnityConcludeTest(); \\')
output.puts(' } \\') if @options[:cmdline_args]
output.puts("}\n")
end
def create_reset(output, used_mocks)
output.puts("\n/*=======Test Reset Option=====*/")
output.puts('void resetTest(void);')
output.puts('void resetTest(void)')
output.puts('{')
output.puts(' CMock_Verify();') unless used_mocks.empty?
output.puts(' CMock_Destroy();') unless used_mocks.empty?
output.puts(" #{@options[:teardown_name]}();")
output.puts(' CMock_Init();') unless used_mocks.empty?
output.puts(" #{@options[:setup_name]}();")
output.puts('}')
end
def create_main(output, filename, tests, used_mocks)
output.puts("\n\n/*=======MAIN=====*/")
main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s
if @options[:cmdline_args]
if main_name != 'main'
output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);")
end
output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
output.puts('{')
output.puts(' int parse_status = UnityParseOptions(argc, argv);')
output.puts(' if (parse_status != 0)')
output.puts(' {')
output.puts(' if (parse_status < 0)')
output.puts(' {')
output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");")
output.puts(' UNITY_PRINT_EOL();')
if @options[:use_param_tests]
tests.each do |test|
if test[:args].nil? || test[:args].empty?
output.puts(" UnityPrint(\" #{test[:test]}(RUN_TEST_NO_ARGS)\");")
output.puts(' UNITY_PRINT_EOL();')
else
test[:args].each do |args|
output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");")
output.puts(' UNITY_PRINT_EOL();')
end
end
end
else
tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();") }
end
output.puts(' return 0;')
output.puts(' }')
output.puts(' return parse_status;')
output.puts(' }')
else
if main_name != 'main'
output.puts("#{@options[:main_export_decl]} int #{main_name}(void);")
end
output.puts("int #{main_name}(void)")
output.puts('{')
end
output.puts(' suite_setup();')
output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
if @options[:use_param_tests]
tests.each do |test|
if test[:args].nil? || test[:args].empty?
output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);")
else
test[:args].each { |args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});") }
end
end
else
tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") }
end
output.puts
output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
output.puts(' return suite_teardown(UnityEnd());')
output.puts('}')
end
def create_h_file(output, filename, tests, testfile_includes, used_mocks)
filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase
output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
output.puts("#ifndef _#{filename}")
output.puts("#define _#{filename}\n\n")
output.puts("#include \"#{@options[:framework]}.h\"")
output.puts('#include "cmock.h"') unless used_mocks.empty?
@options[:includes].flatten.uniq.compact.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
testfile_includes.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
output.puts "\n"
tests.each do |test|
if test[:params].nil? || test[:params].empty?
output.puts("void #{test[:test]}(void);")
else
output.puts("void #{test[:test]}(#{test[:params]});")
end
end
output.puts("#endif\n\n")
end
end
if $0 == __FILE__
options = { includes: [] }
# parse out all the options first (these will all be removed as we go)
ARGV.reject! do |arg|
case arg
when '-cexception'
options[:plugins] = [:cexception]
true
when /\.*\.ya?ml/
options = UnityTestRunnerGenerator.grab_config(arg)
true
when /--(\w+)=\"?(.*)\"?/
options[Regexp.last_match(1).to_sym] = Regexp.last_match(2)
true
when /\.*\.h/
options[:includes] << arg
true
else false
end
end
# make sure there is at least one parameter left (the input file)
unless ARGV[0]
puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)",
"\n input_test_file - this is the C file you want to create a runner for",
' output - this is the name of the runner file to generate',
' defaults to (input_test_file)_Runner',
' files:',
' *.yml / *.yaml - loads configuration from here in :unity or :cmock',
' *.h - header files are added as #includes in runner',
' options:',
' -cexception - include cexception support',
' -externc - add extern "C" for cpp support',
' --setup_name="" - redefine setUp func name to something else',
' --teardown_name="" - redefine tearDown func name to something else',
' --main_name="" - redefine main func name to something else',
' --test_prefix="" - redefine test prefix from default test|spec|should',
' --suite_setup="" - code to execute for setup of entire suite',
' --suite_teardown="" - code to execute for teardown of entire suite',
' --use_param_tests=1 - enable parameterized tests (disabled by default)',
' --header_file="" - path/name of test header file to generate too'].join("\n")
exit 1
end
# create the default test runner name if not specified
ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1]
UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
end

View File

@ -0,0 +1,322 @@
#============================================================
# Author: John Theofanopoulos
# A simple parser. Takes the output files generated during the
# build process and extracts information relating to the tests.
#
# Notes:
# To capture an output file under VS builds use the following:
# devenv [build instructions] > Output.txt & type Output.txt
#
# To capture an output file under Linux builds use the following:
# make | tee Output.txt
#
# This script can handle the following output formats:
# - normal output (raw unity)
# - fixture output (unity_fixture.h/.c)
# - fixture output with verbose flag set ("-v")
#
# To use this parser use the following command
# ruby parseOutput.rb [options] [file]
# options: -xml : produce a JUnit compatible XML file
# file: file to scan for results
#============================================================
# Parser class for handling the input file
class ParseOutput
def initialize
# internal data
@class_name_idx = 0
@path_delim = nil
# xml output related
@xml_out = false
@array_list = false
# current suite name and statistics
@test_suite = nil
@total_tests = 0
@test_passed = 0
@test_failed = 0
@test_ignored = 0
end
# Set the flag to indicate if there will be an XML output file or not
def set_xml_output
@xml_out = true
end
# If write our output to XML
def write_xml_output
output = File.open('report.xml', 'w')
output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@array_list.each do |item|
output << item << "\n"
end
end
# Pushes the suite info as xml to the array list, which will be written later
def push_xml_output_suite_info
# Insert opening tag at front
heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + @test_failed.to_s + '"' + ' skips="' + @test_ignored.to_s + '">'
@array_list.insert(0, heading)
# Push back the closing tag
@array_list.push '</testsuite>'
end
# Pushes xml output data to the array list, which will be written later
def push_xml_output_passed(test_name)
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
end
# Pushes xml output data to the array list, which will be written later
def push_xml_output_failed(test_name, reason)
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@array_list.push ' <failure type="ASSERT FAILED">' + reason + '</failure>'
@array_list.push ' </testcase>'
end
# Pushes xml output data to the array list, which will be written later
def push_xml_output_ignored(test_name, reason)
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@array_list.push ' <skipped type="TEST IGNORED">' + reason + '</skipped>'
@array_list.push ' </testcase>'
end
# This function will try and determine when the suite is changed. This is
# is the name that gets added to the classname parameter.
def test_suite_verify(test_suite_name)
# Split the path name
test_name = test_suite_name.split(@path_delim)
# Remove the extension and extract the base_name
base_name = test_name[test_name.size - 1].split('.')[0]
# Return if the test suite hasn't changed
return unless base_name.to_s != @test_suite.to_s
@test_suite = base_name
printf "New Test: %s\n", @test_suite
end
# Prepares the line for verbose fixture output ("-v")
def prepare_fixture_line(line)
line = line.sub('IGNORE_TEST(', '')
line = line.sub('TEST(', '')
line = line.sub(')', ',')
line = line.chomp
array = line.split(',')
array.map { |x| x.to_s.lstrip.chomp }
end
# Test was flagged as having passed so format the output.
# This is using the Unity fixture output and not the original Unity output.
def test_passed_unity_fixture(array)
class_name = array[0]
test_name = array[1]
test_suite_verify(class_name)
printf "%-40s PASS\n", test_name
push_xml_output_passed(test_name) if @xml_out
end
# Test was flagged as having failed so format the output.
# This is using the Unity fixture output and not the original Unity output.
def test_failed_unity_fixture(array)
class_name = array[0]
test_name = array[1]
test_suite_verify(class_name)
reason_array = array[2].split(':')
reason = reason_array[-1].lstrip.chomp + ' at line: ' + reason_array[-4]
printf "%-40s FAILED\n", test_name
push_xml_output_failed(test_name, reason) if @xml_out
end
# Test was flagged as being ignored so format the output.
# This is using the Unity fixture output and not the original Unity output.
def test_ignored_unity_fixture(array)
class_name = array[0]
test_name = array[1]
reason = 'No reason given'
if array.size > 2
reason_array = array[2].split(':')
tmp_reason = reason_array[-1].lstrip.chomp
reason = tmp_reason == 'IGNORE' ? 'No reason given' : tmp_reason
end
test_suite_verify(class_name)
printf "%-40s IGNORED\n", test_name
push_xml_output_ignored(test_name, reason) if @xml_out
end
# Test was flagged as having passed so format the output
def test_passed(array)
last_item = array.length - 1
test_name = array[last_item - 1]
test_suite_verify(array[@class_name_idx])
printf "%-40s PASS\n", test_name
return unless @xml_out
push_xml_output_passed(test_name) if @xml_out
end
# Test was flagged as having failed so format the line
def test_failed(array)
last_item = array.length - 1
test_name = array[last_item - 2]
reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3]
class_name = array[@class_name_idx]
if test_name.start_with? 'TEST('
array2 = test_name.split(' ')
test_suite = array2[0].sub('TEST(', '')
test_suite = test_suite.sub(',', '')
class_name = test_suite
test_name = array2[1].sub(')', '')
end
test_suite_verify(class_name)
printf "%-40s FAILED\n", test_name
push_xml_output_failed(test_name, reason) if @xml_out
end
# Test was flagged as being ignored so format the output
def test_ignored(array)
last_item = array.length - 1
test_name = array[last_item - 2]
reason = array[last_item].chomp.lstrip
class_name = array[@class_name_idx]
if test_name.start_with? 'TEST('
array2 = test_name.split(' ')
test_suite = array2[0].sub('TEST(', '')
test_suite = test_suite.sub(',', '')
class_name = test_suite
test_name = array2[1].sub(')', '')
end
test_suite_verify(class_name)
printf "%-40s IGNORED\n", test_name
push_xml_output_ignored(test_name, reason) if @xml_out
end
# Adjusts the os specific members according to the current path style
# (Windows or Unix based)
def detect_os_specifics(line)
if line.include? '\\'
# Windows X:\Y\Z
@class_name_idx = 1
@path_delim = '\\'
else
# Unix Based /X/Y/Z
@class_name_idx = 0
@path_delim = '/'
end
end
# Main function used to parse the file that was captured.
def process(file_name)
@array_list = []
puts 'Parsing file: ' + file_name
@test_passed = 0
@test_failed = 0
@test_ignored = 0
puts ''
puts '=================== RESULTS ====================='
puts ''
File.open(file_name).each do |line|
# Typical test lines look like these:
# ----------------------------------------------------
# 1. normal output:
# <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
# <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
# <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
#
# 2. fixture output
# <path>/<test_file>.c:63:TEST(<test_group>, <test_function>):FAIL: Expected 0x00001234 Was 0x00005A5A
# <path>/<test_file>.c:36:TEST(<test_group>, <test_function>):IGNORE
# Note: "PASS" information won't be generated in this mode
#
# 3. fixture output with verbose information ("-v")
# TEST(<test_group, <test_file>)<path>/<test_file>:168::FAIL: Expected 0x8D Was 0x8C
# TEST(<test_group>, <test_file>)<path>/<test_file>:22::IGNORE: This Test Was Ignored On Purpose
# IGNORE_TEST(<test_group, <test_file>)
# TEST(<test_group, <test_file>) PASS
#
# Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)!
detect_os_specifics(line)
line_array = line.split(':')
# If we were able to split the line then we can look to see if any of our target words
# were found. Case is important.
next unless (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
# check if the output is fixture output (with verbose flag "-v")
if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
line_array = prepare_fixture_line(line)
if line.include? ' PASS'
test_passed_unity_fixture(line_array)
@test_passed += 1
elsif line.include? 'FAIL'
test_failed_unity_fixture(line_array)
@test_failed += 1
elsif line.include? 'IGNORE'
test_ignored_unity_fixture(line_array)
@test_ignored += 1
end
# normal output / fixture output (without verbose "-v")
elsif line.include? ':PASS'
test_passed(line_array)
@test_passed += 1
elsif line.include? ':FAIL'
test_failed(line_array)
@test_failed += 1
elsif line.include? ':IGNORE:'
test_ignored(line_array)
@test_ignored += 1
elsif line.include? ':IGNORE'
line_array.push('No reason given')
test_ignored(line_array)
@test_ignored += 1
end
@total_tests = @test_passed + @test_failed + @test_ignored
end
puts ''
puts '=================== SUMMARY ====================='
puts ''
puts 'Tests Passed : ' + @test_passed.to_s
puts 'Tests Failed : ' + @test_failed.to_s
puts 'Tests Ignored : ' + @test_ignored.to_s
return unless @xml_out
# push information about the suite
push_xml_output_suite_info
# write xml output file
write_xml_output
end
end
# If the command line has no values in, used a default value of Output.txt
parse_my_file = ParseOutput.new
if ARGV.size >= 1
ARGV.each do |arg|
if arg == '-xml'
parse_my_file.set_xml_output
else
parse_my_file.process(arg)
break
end
end
end

View File

@ -0,0 +1,248 @@
#!/usr/bin/ruby
#
# unity_to_junit.rb
#
require 'fileutils'
require 'optparse'
require 'ostruct'
require 'set'
require 'pp'
VERSION = 1.0
class ArgvParser
#
# Return a structure describing the options.
#
def self.parse(args)
# The options specified on the command line will be collected in *options*.
# We set default values here.
options = OpenStruct.new
options.results_dir = '.'
options.root_path = '.'
options.out_file = 'results.xml'
opts = OptionParser.new do |o|
o.banner = 'Usage: unity_to_junit.rb [options]'
o.separator ''
o.separator 'Specific options:'
o.on('-r', '--results <dir>', 'Look for Unity Results files here.') do |results|
# puts "results #{results}"
options.results_dir = results
end
o.on('-p', '--root_path <path>', 'Prepend this path to files in results.') do |root_path|
options.root_path = root_path
end
o.on('-o', '--output <filename>', 'XML file to generate.') do |out_file|
# puts "out_file: #{out_file}"
options.out_file = out_file
end
o.separator ''
o.separator 'Common options:'
# No argument, shows at tail. This will print an options summary.
o.on_tail('-h', '--help', 'Show this message') do
puts o
exit
end
# Another typical switch to print the version.
o.on_tail('--version', 'Show version') do
puts "unity_to_junit.rb version #{VERSION}"
exit
end
end
opts.parse!(args)
options
end
end
class UnityToJUnit
include FileUtils::Verbose
attr_reader :report, :total_tests, :failures, :ignored
attr_writer :targets, :root, :out_file
def initialize
@report = ''
@unit_name = ''
end
def run
# Clean up result file names
results = @targets.map { |target| target.tr('\\', '/') }
# puts "Output File: #{@out_file}"
f = File.new(@out_file, 'w')
write_xml_header(f)
write_suites_header(f)
results.each do |result_file|
lines = File.readlines(result_file).map(&:chomp)
raise "Empty test result file: #{result_file}" if lines.empty?
result_output = get_details(result_file, lines)
tests, failures, ignored = parse_test_summary(lines)
result_output[:counts][:total] = tests
result_output[:counts][:failed] = failures
result_output[:counts][:ignored] = ignored
result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored])
# use line[0] from the test output to get the test_file path and name
test_file_str = lines[0].tr('\\', '/')
test_file_str = test_file_str.split(':')
test_file = if test_file_str.length < 2
result_file
else
test_file_str[0] + ':' + test_file_str[1]
end
result_output[:source][:path] = File.dirname(test_file)
result_output[:source][:file] = File.basename(test_file)
# save result_output
@unit_name = File.basename(test_file, '.*')
write_suite_header(result_output[:counts], f)
write_failures(result_output, f)
write_tests(result_output, f)
write_ignored(result_output, f)
write_suite_footer(f)
end
write_suites_footer(f)
f.close
end
def usage(err_msg = nil)
puts "\nERROR: "
puts err_msg if err_msg
puts 'Usage: unity_to_junit.rb [options]'
puts ''
puts 'Specific options:'
puts ' -r, --results <dir> Look for Unity Results files here.'
puts ' -p, --root_path <path> Prepend this path to files in results.'
puts ' -o, --output <filename> XML file to generate.'
puts ''
puts 'Common options:'
puts ' -h, --help Show this message'
puts ' --version Show version'
exit 1
end
protected
def get_details(_result_file, lines)
results = results_structure
lines.each do |line|
line = line.tr('\\', '/')
_src_file, src_line, test_name, status, msg = line.split(/:/)
case status
when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg }
when 'FAIL' then results[:failures] << { test: test_name, line: src_line, message: msg }
when 'PASS' then results[:successes] << { test: test_name, line: src_line, message: msg }
end
end
results
end
def parse_test_summary(summary)
raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
[Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i]
end
private
def results_structure
{
source: { path: '', file: '' },
successes: [],
failures: [],
ignores: [],
counts: { total: 0, passed: 0, failed: 0, ignored: 0 },
stdout: []
}
end
def write_xml_header(stream)
stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
end
def write_suites_header(stream)
stream.puts '<testsuites>'
end
def write_suite_header(counts, stream)
stream.puts "\t<testsuite errors=\"0\" skipped=\"#{counts[:ignored]}\" failures=\"#{counts[:failed]}\" tests=\"#{counts[:total]}\" name=\"unity\">"
end
def write_failures(results, stream)
result = results[:failures]
result.each do |item|
filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
stream.puts "\t\t\t<failure message=\"#{item[:message]}\" type=\"Assertion\"/>"
stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
stream.puts "\t\t</testcase>"
end
end
def write_tests(results, stream)
result = results[:successes]
result.each do |item|
stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\" />"
end
end
def write_ignored(results, stream)
result = results[:ignores]
result.each do |item|
filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
puts "Writing ignored tests for test harness: #{filename}"
stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
stream.puts "\t\t\t<skipped message=\"#{item[:message]}\" type=\"Assertion\"/>"
stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
stream.puts "\t\t</testcase>"
end
end
def write_suite_footer(stream)
stream.puts "\t</testsuite>"
end
def write_suites_footer(stream)
stream.puts '</testsuites>'
end
end
if $0 == __FILE__
# parse out the command options
options = ArgvParser.parse(ARGV)
# create an instance to work with
utj = UnityToJUnit.new
begin
# look in the specified or current directory for result files
targets = "#{options.results_dir.tr('\\', '/')}**/*.test*"
results = Dir[targets]
raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
utj.targets = results
# set the root path
utj.root = options.root_path
# set the output XML file name
# puts "Output File from options: #{options.out_file}"
utj.out_file = options.out_file
# run the summarizer
puts utj.run
rescue StandardError => e
utj.usage e.message
end
end

View File

@ -0,0 +1,25 @@
# ==========================================
# Unity Project - A Test Framework for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
require'yaml'
module RakefileHelpers
class TestFileFilter
def initialize(all_files = false)
@all_files = all_files
return unless @all_files
return unless File.exist?('test_file_filter.yml')
filters = YAML.load_file('test_file_filter.yml')
@all_files = filters[:all_files]
@only_files = filters[:only_files]
@exclude_files = filters[:exclude_files]
end
attr_accessor :all_files, :only_files, :exclude_files
end
end

View File

@ -0,0 +1,6 @@
module TypeSanitizer
def self.sanitize_c_identifier(unsanitized)
# convert filename to valid C identifier by replacing invalid chars with '_'
unsanitized.gsub(/[-\/\\\.\,\s]/, '_')
end
end

View File

@ -0,0 +1,139 @@
#! python3
# ==========================================
# Unity Project - A Test Framework for C
# Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de
# [Released under MIT License. Please refer to license.txt for details]
# Based on the ruby script by Mike Karlesky, Mark VanderVoord, Greg Williams
# ==========================================
import sys
import os
import re
from glob import glob
class UnityTestSummary:
def __init__(self):
self.report = ''
self.total_tests = 0
self.failures = 0
self.ignored = 0
def run(self):
# Clean up result file names
results = []
for target in self.targets:
results.append(target.replace('\\', '/'))
# Dig through each result file, looking for details on pass/fail:
failure_output = []
ignore_output = []
for result_file in results:
lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
if len(lines) == 0:
raise Exception("Empty test result file: %s" % result_file)
details = self.get_details(result_file, lines)
failures = details['failures']
ignores = details['ignores']
if len(failures) > 0: failure_output.append('\n'.join(failures))
if len(ignores) > 0: ignore_output.append('n'.join(ignores))
tests,failures,ignored = self.parse_test_summary('\n'.join(lines))
self.total_tests += tests
self.failures += failures
self.ignored += ignored
if self.ignored > 0:
self.report += "\n"
self.report += "--------------------------\n"
self.report += "UNITY IGNORED TEST SUMMARY\n"
self.report += "--------------------------\n"
self.report += "\n".join(ignore_output)
if self.failures > 0:
self.report += "\n"
self.report += "--------------------------\n"
self.report += "UNITY FAILED TEST SUMMARY\n"
self.report += "--------------------------\n"
self.report += '\n'.join(failure_output)
self.report += "\n"
self.report += "--------------------------\n"
self.report += "OVERALL UNITY TEST SUMMARY\n"
self.report += "--------------------------\n"
self.report += "{total_tests} TOTAL TESTS {failures} TOTAL FAILURES {ignored} IGNORED\n".format(total_tests = self.total_tests, failures=self.failures, ignored=self.ignored)
self.report += "\n"
return self.report
def set_targets(self, target_array):
self.targets = target_array
def set_root_path(self, path):
self.root = path
def usage(self, err_msg=None):
print("\nERROR: ")
if err_msg:
print(err_msg)
print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
print(" result_file_directory - The location of your results files.")
print(" Defaults to current directory if not specified.")
print(" Should end in / if specified.")
print(" root_path - Helpful for producing more verbose output if using relative paths.")
sys.exit(1)
def get_details(self, result_file, lines):
results = { 'failures': [], 'ignores': [], 'successes': [] }
for line in lines:
parts = line.split(':')
if len(parts) == 5:
src_file,src_line,test_name,status,msg = parts
elif len(parts) == 4:
src_file,src_line,test_name,status = parts
msg = ''
else:
continue
if len(self.root) > 0:
line_out = "%s%s" % (self.root, line)
else:
line_out = line
if status == 'IGNORE':
results['ignores'].append(line_out)
elif status == 'FAIL':
results['failures'].append(line_out)
elif status == 'PASS':
results['successes'].append(line_out)
return results
def parse_test_summary(self, summary):
m = re.search(r"([0-9]+) Tests ([0-9]+) Failures ([0-9]+) Ignored", summary)
if not m:
raise Exception("Couldn't parse test results: %s" % summary)
return int(m.group(1)), int(m.group(2)), int(m.group(3))
if __name__ == '__main__':
uts = UnityTestSummary()
try:
#look in the specified or current directory for result files
if len(sys.argv) > 1:
targets_dir = sys.argv[1]
else:
targets_dir = './'
targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
if len(targets) == 0:
raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
uts.set_targets(targets)
#set the root path
if len(sys.argv) > 2:
root_path = sys.argv[2]
else:
root_path = os.path.split(__file__)[0]
uts.set_root_path(root_path)
#run the summarizer
print(uts.run())
except Exception as e:
uts.usage(e)

View File

@ -0,0 +1,132 @@
# ==========================================
# Unity Project - A Test Framework for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
# !/usr/bin/ruby
#
# unity_test_summary.rb
#
require 'fileutils'
require 'set'
class UnityTestSummary
include FileUtils::Verbose
attr_reader :report, :total_tests, :failures, :ignored
attr_writer :targets, :root
def initialize(_opts = {})
@report = ''
@total_tests = 0
@failures = 0
@ignored = 0
end
def run
# Clean up result file names
results = @targets.map { |target| target.tr('\\', '/') }
# Dig through each result file, looking for details on pass/fail:
failure_output = []
ignore_output = []
results.each do |result_file|
lines = File.readlines(result_file).map(&:chomp)
raise "Empty test result file: #{result_file}" if lines.empty?
output = get_details(result_file, lines)
failure_output << output[:failures] unless output[:failures].empty?
ignore_output << output[:ignores] unless output[:ignores].empty?
tests, failures, ignored = parse_test_summary(lines)
@total_tests += tests
@failures += failures
@ignored += ignored
end
if @ignored > 0
@report += "\n"
@report += "--------------------------\n"
@report += "UNITY IGNORED TEST SUMMARY\n"
@report += "--------------------------\n"
@report += ignore_output.flatten.join("\n")
end
if @failures > 0
@report += "\n"
@report += "--------------------------\n"
@report += "UNITY FAILED TEST SUMMARY\n"
@report += "--------------------------\n"
@report += failure_output.flatten.join("\n")
end
@report += "\n"
@report += "--------------------------\n"
@report += "OVERALL UNITY TEST SUMMARY\n"
@report += "--------------------------\n"
@report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n"
@report += "\n"
end
def usage(err_msg = nil)
puts "\nERROR: "
puts err_msg if err_msg
puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/"
puts ' result_file_directory - The location of your results files.'
puts ' Defaults to current directory if not specified.'
puts ' Should end in / if specified.'
puts ' root_path - Helpful for producing more verbose output if using relative paths.'
exit 1
end
protected
def get_details(_result_file, lines)
results = { failures: [], ignores: [], successes: [] }
lines.each do |line|
_src_file, _src_line, _test_name, status, _msg = line.split(/:/)
line_out = (@root && (@root != 0) ? "#{@root}#{line}" : line).gsub(/\//, '\\')
case status
when 'IGNORE' then results[:ignores] << line_out
when 'FAIL' then results[:failures] << line_out
when 'PASS' then results[:successes] << line_out
end
end
results
end
def parse_test_summary(summary)
raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
[Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i]
end
end
if $0 == __FILE__
# parse out the command options
opts, args = ARGV.partition { |v| v =~ /^--\w+/ }
opts.map! { |v| v[2..-1].to_sym }
# create an instance to work with
uts = UnityTestSummary.new(opts)
begin
# look in the specified or current directory for result files
args[0] ||= './'
targets = "#{ARGV[0].tr('\\', '/')}**/*.test*"
results = Dir[targets]
raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
uts.targets = results
# set the root path
args[1] ||= Dir.pwd + '/'
uts.root = ARGV[1]
# run the summarizer
puts uts.run
rescue StandardError => e
uts.usage e.message
end
end

View File

@ -0,0 +1,146 @@
import sys
import os
from glob import glob
from pyparsing import *
from junit_xml import TestSuite, TestCase
class UnityTestSummary:
def __init__(self):
self.report = ''
self.total_tests = 0
self.failures = 0
self.ignored = 0
self.targets = 0
self.root = None
self.test_suites = dict()
def run(self):
# Clean up result file names
results = []
for target in self.targets:
results.append(target.replace('\\', '/'))
# Dig through each result file, looking for details on pass/fail:
for result_file in results:
lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
if len(lines) == 0:
raise Exception("Empty test result file: %s" % result_file)
# define an expression for your file reference
entry_one = Combine(
oneOf(list(alphas)) + ':/' +
Word(alphanums + '_-./'))
entry_two = Word(printables + ' ', excludeChars=':')
entry = entry_one | entry_two
delimiter = Literal(':').suppress()
tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName(
'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName(
'tc_status') + Optional(
delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
eol = LineEnd().suppress()
sol = LineStart().suppress()
blank_line = sol + eol
tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
"num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
"tc_summary")
tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result")
# run it and see...
pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line)
pp1.ignore(blank_line | OneOrMore("-"))
result = list()
for l in lines:
result.append((pp1.parseString(l)).asDict())
# delete empty results
result = filter(None, result)
tc_list = list()
for r in result:
if 'tc_line' in r:
tmp_tc_line = r['tc_line']
# get only the file name which will be used as the classname
file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
if 'tc_status' in tmp_tc_line:
if str(tmp_tc_line['tc_status']) == 'IGNORE':
if 'tc_msg' in tmp_tc_line:
tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'],
output=r'[File]={0}, [Line]={1}'.format(
tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
else:
tmp_tc.add_skipped_info(message=" ")
elif str(tmp_tc_line['tc_status']) == 'FAIL':
if 'tc_msg' in tmp_tc_line:
tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'],
output=r'[File]={0}, [Line]={1}'.format(
tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
else:
tmp_tc.add_failure_info(message=" ")
tc_list.append((str(result_file), tmp_tc))
for k, v in tc_list:
try:
self.test_suites[k].append(v)
except KeyError:
self.test_suites[k] = [v]
ts = []
for suite_name in self.test_suites:
ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
with open('result.xml', 'w') as f:
TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
return self.report
def set_targets(self, target_array):
self.targets = target_array
def set_root_path(self, path):
self.root = path
@staticmethod
def usage(err_msg=None):
print("\nERROR: ")
if err_msg:
print(err_msg)
print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
print(" result_file_directory - The location of your results files.")
print(" Defaults to current directory if not specified.")
print(" Should end in / if specified.")
print(" root_path - Helpful for producing more verbose output if using relative paths.")
sys.exit(1)
if __name__ == '__main__':
uts = UnityTestSummary()
try:
# look in the specified or current directory for result files
if len(sys.argv) > 1:
targets_dir = sys.argv[1]
else:
targets_dir = './'
targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
if len(targets) == 0:
raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
uts.set_targets(targets)
# set the root path
if len(sys.argv) > 2:
root_path = sys.argv[2]
else:
root_path = os.path.split(__file__)[0]
uts.set_root_path(root_path)
# run the summarizer
print(uts.run())
except Exception as e:
UnityTestSummary.usage(e)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,617 @@
/* ==========================================
Unity Project - A Test Framework for C
Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams
[Released under MIT License. Please refer to license.txt for details]
========================================== */
#ifndef UNITY_FRAMEWORK_H
#define UNITY_FRAMEWORK_H
#define UNITY
#define UNITY_VERSION_MAJOR 2
#define UNITY_VERSION_MINOR 5
#define UNITY_VERSION_BUILD 0
#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD)
#ifdef __cplusplus
extern "C"
{
#endif
#include "unity_internals.h"
/*-------------------------------------------------------
* Test Setup / Teardown
*-------------------------------------------------------*/
/* These functions are intended to be called before and after each test.
* If using unity directly, these will need to be provided for each test
* executable built. If you are using the test runner generator and/or
* Ceedling, these are optional. */
void setUp(void);
void tearDown(void);
/* These functions are intended to be called at the beginning and end of an
* entire test suite. suiteTearDown() is passed the number of tests that
* failed, and its return value becomes the exit code of main(). If using
* Unity directly, you're in charge of calling these if they are desired.
* If using Ceedling or the test runner generator, these will be called
* automatically if they exist. */
void suiteSetUp(void);
int suiteTearDown(int num_failures);
/*-------------------------------------------------------
* Test Reset and Verify
*-------------------------------------------------------*/
/* These functions are intended to be called before during tests in order
* to support complex test loops, etc. Both are NOT built into Unity. Instead
* the test runner generator will create them. resetTest will run teardown and
* setup again, verifying any end-of-test needs between. verifyTest will only
* run the verification. */
void resetTest(void);
void verifyTest(void);
/*-------------------------------------------------------
* Configuration Options
*-------------------------------------------------------
* All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
* Integers/longs/pointers
* - Unity attempts to automatically discover your integer sizes
* - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
* - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
* - If you cannot use the automatic methods above, you can force Unity by using these options:
* - define UNITY_SUPPORT_64
* - set UNITY_INT_WIDTH
* - set UNITY_LONG_WIDTH
* - set UNITY_POINTER_WIDTH
* Floats
* - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
* - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
* - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
* - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
* - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
* - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
* - define UNITY_DOUBLE_TYPE to specify something other than double
* - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors
* Output
* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
* - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
* Optimization
* - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
* - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
* Test Cases
* - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
* Parameterized Tests
* - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing
* Tests with Arguments
* - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity
*-------------------------------------------------------
* Basic Fail and Ignore
*-------------------------------------------------------*/
#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message))
#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message))
#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
#define TEST_MESSAGE(message) UnityMessage((message), __LINE__)
#define TEST_ONLY()
/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
* This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
#define TEST_PASS() TEST_ABORT()
#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while(0)
/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out
* which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */
#define TEST_FILE(a)
/*-------------------------------------------------------
* Test Asserts (simple)
*-------------------------------------------------------*/
/* Boolean */
#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
/* Integers (of all sizes) */
#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
/* Integer Greater Than/ Less Than (of all sizes) */
#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL)
/* Integer Array Ranges (of all sizes) */
#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
/* Structs and Strings */
#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
/* Arrays */
#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
/* Arrays Compared To Single Value */
#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL)
/* Floating Point (If Enabled) */
#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
/* Double (If Enabled) */
#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
/* Shorthand */
#ifdef UNITY_SHORTHAND_AS_OLD
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
#endif
#ifdef UNITY_SHORTHAND_AS_INT
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_MEM
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_RAW
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal")
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
#endif
#ifdef UNITY_SHORTHAND_AS_NONE
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
/*-------------------------------------------------------
* Test Asserts (with additional messages)
*-------------------------------------------------------*/
/* Boolean */
#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message))
#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
/* Integers (of all sizes) */
#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message))
#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message))
/* Integer Greater Than/ Less Than (of all sizes) */
#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message))
/* Integer Array Ranges (of all sizes) */
#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
/* Structs and Strings */
#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
/* Arrays */
#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
/* Arrays Compared To Single Value*/
#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message))
/* Floating Point (If Enabled) */
#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
/* Double (If Enabled) */
#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
/* Shorthand */
#ifdef UNITY_SHORTHAND_AS_OLD
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message))
#endif
#ifdef UNITY_SHORTHAND_AS_INT
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_MEM
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
#ifdef UNITY_SHORTHAND_AS_RAW
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message)
#endif
#ifdef UNITY_SHORTHAND_AS_NONE
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
#endif
/* end of UNITY_FRAMEWORK_H */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# Cherry_MX_LED
#
DEF Cherry_MX_LED SW** 0 0 N N 1 F N
F0 "SW**" 0 200 50 H V C CNN
F1 "Cherry_MX_LED" 0 -250 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
ENDDRAW
ENDDEF
#
#End Library

View File

@ -0,0 +1,12 @@
(module "Cherry aligner" (layer F.Cu) (tedit 5DA626D6)
(fp_text reference "REF**" (at -5.0292 -7.7724) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value "Cherry aligner" (at 0 7.9756) (layer B.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -6.985 6.985) (end 6.985 6.985) (layer Edge.Cuts) (width 0.12))
(fp_line (start -6.985 -6.985) (end 6.985 -6.985) (layer Edge.Cuts) (width 0.12))
(fp_line (start 6.985 6.985) (end 6.985 -6.985) (layer Edge.Cuts) (width 0.12))
(fp_line (start -6.985 -6.985) (end -6.985 6.985) (layer Edge.Cuts) (width 0.12))
)

View File

@ -0,0 +1,49 @@
(module D_DO-35_SOD27_P7.62mm_Horizontal_bypassed (layer F.Cu) (tedit 5DF278C4)
(descr "Diode, DO-35_SOD27 series, Axial, Horizontal, pin pitch=7.62mm, , length*diameter=4*2mm^2, , http://www.diodes.com/_files/packages/DO-35.pdf")
(tags "Diode DO-35_SOD27 series Axial Horizontal pin pitch 7.62mm length 4mm diameter 2mm")
(fp_text reference REF** (at 3.81 -2.12) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value D_DO-35_SOD27_P7.62mm_Horizontal (at 3.81 2.12) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text user K (at 0 -1.8) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text user K (at 0 -1.8) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text user %R (at 4.11 0) (layer F.Fab)
(effects (font (size 0.8 0.8) (thickness 0.12)))
)
(fp_line (start 8.67 -1.25) (end -1.05 -1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start 8.67 1.25) (end 8.67 -1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start -1.05 1.25) (end 8.67 1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start -1.05 -1.25) (end -1.05 1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start 2.29 -1.12) (end 2.29 1.12) (layer F.SilkS) (width 0.12))
(fp_line (start 2.53 -1.12) (end 2.53 1.12) (layer F.SilkS) (width 0.12))
(fp_line (start 2.41 -1.12) (end 2.41 1.12) (layer F.SilkS) (width 0.12))
(fp_line (start 6.58 0) (end 5.93 0) (layer F.SilkS) (width 0.12))
(fp_line (start 1.04 0) (end 1.69 0) (layer F.SilkS) (width 0.12))
(fp_line (start 5.93 -1.12) (end 1.69 -1.12) (layer F.SilkS) (width 0.12))
(fp_line (start 5.93 1.12) (end 5.93 -1.12) (layer F.SilkS) (width 0.12))
(fp_line (start 1.69 1.12) (end 5.93 1.12) (layer F.SilkS) (width 0.12))
(fp_line (start 1.69 -1.12) (end 1.69 1.12) (layer F.SilkS) (width 0.12))
(fp_line (start 2.31 -1) (end 2.31 1) (layer F.Fab) (width 0.1))
(fp_line (start 2.51 -1) (end 2.51 1) (layer F.Fab) (width 0.1))
(fp_line (start 2.41 -1) (end 2.41 1) (layer F.Fab) (width 0.1))
(fp_line (start 7.62 0) (end 5.81 0) (layer F.Fab) (width 0.1))
(fp_line (start 0 0) (end 1.81 0) (layer F.Fab) (width 0.1))
(fp_line (start 5.81 -1) (end 1.81 -1) (layer F.Fab) (width 0.1))
(fp_line (start 5.81 1) (end 5.81 -1) (layer F.Fab) (width 0.1))
(fp_line (start 1.81 1) (end 5.81 1) (layer F.Fab) (width 0.1))
(fp_line (start 1.81 -1) (end 1.81 1) (layer F.Fab) (width 0.1))
(fp_poly (pts (xy 7.239 0.127) (xy 0.381 0.127) (xy 0.381 0) (xy 7.239 0)) (layer F.Cu) (width 0.0508))
(pad 2 thru_hole oval (at 7.62 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask))
(pad 1 thru_hole rect (at 0 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask))
(model ${KISYS3DMOD}/Diode_THT.3dshapes/D_DO-35_SOD27_P7.62mm_Horizontal.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

View File

@ -0,0 +1,13 @@
(module "Futaba-MD-4PCS-aligner" (layer F.Cu) (tedit 5DA63068)
(fp_text reference "REF**" (at -3.937 -8.3566) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value "MD-4PCS-aligner" (at 0.1524 8.8646) (layer B.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 7.8232 0) (layer Edge.Cuts) (width 0.12))
(pad "" np_thru_hole circle (at 6.985 -6.985) (size 1.6256 1.6256) (drill 1.6256) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 6.985 6.985) (size 1.6256 1.6256) (drill 1.6256) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -6.985 6.985) (size 1.6256 1.6256) (drill 1.6256) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -6.985 -6.985) (size 1.6256 1.6256) (drill 1.6256) (layers *.Cu *.Mask))
)

View File

@ -0,0 +1,24 @@
(module "Key_MX" (layer F.Cu) (tedit 5DA6279D)
(fp_text reference "SW_**" (at -5.7912 -8.6106) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value "Key_MX" (at -5.334 8.6614) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -7.874 7.874) (end -7.874 -7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start 7.874 7.874) (end -7.874 7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start 7.874 -7.874) (end 7.874 7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start -7.874 -7.874) (end 7.874 -7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start -3.81 -2.54) (end -2.54 0) (layer F.Cu) (width 0.3048))
(fp_line (start -2.54 0) (end -2.54 1.27) (layer F.Cu) (width 0.3048))
(fp_line (start -2.54 1.27) (end 0 3.81) (layer F.Cu) (width 0.3048))
(fp_line (start 1.651 -5.08) (end 1.27 -5.08) (layer F.Cu) (width 0.3048))
(fp_line (start 1.27 -5.08) (end 0.7366 -4.6736) (layer F.Cu) (width 0.3048))
(pad "4" thru_hole circle (at -3.81 -2.54) (size 2.2352 2.2352) (drill 1.5748) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 0 0) (size 3.9878 3.9878) (drill 3.9878) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(pad "3" thru_hole circle (at 2.54 -5.08) (size 2.2352 2.2352) (drill 1.5748) (layers *.Cu *.Mask))
(pad "1" thru_hole circle (at 0 -4.0005) (size 2.2352 2.2352) (drill 1.397) (layers *.Cu *.Mask))
(pad "2" thru_hole circle (at 0 4.0005) (size 2.2352 2.2352) (drill 1.397) (layers *.Cu *.Mask))
)

View File

@ -0,0 +1,26 @@
(module Key_MX_LED (layer F.Cu) (tedit 5DF12B03)
(fp_text reference SW_** (at -5.7912 -8.6106) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value Key_MX (at -5.334 8.6614) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -7.874 7.874) (end -7.874 -7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start 7.874 7.874) (end -7.874 7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start 7.874 -7.874) (end 7.874 7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start -7.874 -7.874) (end 7.874 -7.874) (layer F.CrtYd) (width 0.12))
(fp_line (start -3.81 -2.54) (end -2.54 0) (layer F.Cu) (width 0.3048))
(fp_line (start -2.54 0) (end -2.54 1.27) (layer F.Cu) (width 0.3048))
(fp_line (start -2.54 1.27) (end 0 3.81) (layer F.Cu) (width 0.3048))
(fp_line (start 1.651 -5.08) (end 1.27 -5.08) (layer F.Cu) (width 0.3048))
(fp_line (start 1.27 -5.08) (end 0.7366 -4.6736) (layer F.Cu) (width 0.3048))
(pad 5 thru_hole circle (at -3.81 -2.54) (size 2.2352 2.2352) (drill 1.5748) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 0 0) (size 3.9878 3.9878) (drill 3.9878) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(pad 6 thru_hole circle (at 2.54 -5.08) (size 2.2352 2.2352) (drill 1.5748) (layers *.Cu *.Mask))
(pad 1 thru_hole circle (at 0 -4.0005) (size 2.2352 2.2352) (drill 1.397) (layers *.Cu *.Mask))
(pad 2 thru_hole circle (at 0 4.0005) (size 1.651 1.651) (drill 1.397) (layers *.Cu *.Mask))
(pad 4 thru_hole circle (at 1.27 5.08) (size 1.27 1.27) (drill 1.0668) (layers *.Cu *.Mask))
(pad 3 thru_hole circle (at -1.27 5.08) (size 1.27 1.27) (drill 1.0668) (layers *.Cu *.Mask))
)

View File

@ -0,0 +1,12 @@
(module "Cherry aligner" (layer F.Cu) (tedit 5D993F00)
(fp_text reference "REF**" (at -3.81 -6.858) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value "Cherry aligner" (at -0.508 6.985) (layer B.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -5.715 -5.715) (end -5.715 5.715) (layer Edge.Cuts) (width 0.12))
(fp_line (start 5.715 5.715) (end 5.715 -5.715) (layer Edge.Cuts) (width 0.12))
(fp_line (start -5.715 -5.715) (end 5.715 -5.715) (layer Edge.Cuts) (width 0.12))
(fp_line (start -5.715 5.715) (end 5.715 5.715) (layer Edge.Cuts) (width 0.12))
)

View File

@ -0,0 +1,44 @@
(module "MX_space_aligner" (layer F.Cu) (tedit 5DA62851)
(fp_text reference "SW**" (at -5.334 -7.874) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value "MX_space_aligner" (at -0.6096 7.9248) (layer B.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start 6.985 -6.985) (end 6.985 -1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start 6.985 -1.397) (end 63.3476 -1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start 63.3476 -1.397) (end 63.3476 -5.6896) (layer Edge.Cuts) (width 0.12))
(fp_line (start 63.3476 -5.6896) (end 70.0024 -5.6896) (layer Edge.Cuts) (width 0.12))
(fp_line (start 70.0024 -5.6896) (end 70.0024 -2.286) (layer Edge.Cuts) (width 0.12))
(fp_line (start 70.0024 -2.286) (end 70.866 -2.286) (layer Edge.Cuts) (width 0.12))
(fp_line (start 70.866 -2.286) (end 70.866 0.508) (layer Edge.Cuts) (width 0.12))
(fp_line (start 70.866 0.508) (end 70.0024 0.508) (layer Edge.Cuts) (width 0.12))
(fp_line (start 70.0024 0.508) (end 70.0024 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start 70.0024 6.604) (end 68.199 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start 68.199 6.604) (end 68.199 7.7724) (layer Edge.Cuts) (width 0.12))
(fp_line (start 68.199 7.7724) (end 65.151 7.7724) (layer Edge.Cuts) (width 0.12))
(fp_line (start 65.151 7.7724) (end 65.151 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start 65.151 6.604) (end 63.3476 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start 63.3476 6.604) (end 63.3476 1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start 63.3476 1.397) (end 6.985 1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start 6.985 1.397) (end 6.985 6.985) (layer Edge.Cuts) (width 0.12))
(fp_line (start 6.985 6.985) (end -6.985 6.985) (layer Edge.Cuts) (width 0.12))
(fp_line (start -6.985 6.985) (end -6.985 1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start -6.985 1.397) (end -63.3476 1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start -63.3476 1.397) (end -63.3476 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start -63.3476 6.604) (end -65.151 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start -65.151 6.604) (end -65.151 7.7724) (layer Edge.Cuts) (width 0.12))
(fp_line (start -65.151 7.7724) (end -68.199 7.7724) (layer Edge.Cuts) (width 0.12))
(fp_line (start -68.199 7.7724) (end -68.199 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start -68.199 6.604) (end -70.0024 6.604) (layer Edge.Cuts) (width 0.12))
(fp_line (start -70.0024 6.604) (end -70.0024 0.508) (layer Edge.Cuts) (width 0.12))
(fp_line (start -70.0024 0.508) (end -70.866 0.508) (layer Edge.Cuts) (width 0.12))
(fp_line (start -70.866 0.508) (end -70.866 -2.286) (layer Edge.Cuts) (width 0.12))
(fp_line (start -70.866 -2.286) (end -70.0024 -2.286) (layer Edge.Cuts) (width 0.12))
(fp_line (start -70.0024 -2.286) (end -70.0024 -5.6896) (layer Edge.Cuts) (width 0.12))
(fp_line (start -70.0024 -5.6896) (end -63.3476 -5.6896) (layer Edge.Cuts) (width 0.12))
(fp_line (start -63.3476 -5.6896) (end -63.3476 -1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start -63.3476 -1.397) (end -6.985 -1.397) (layer Edge.Cuts) (width 0.12))
(fp_line (start -6.985 -1.397) (end -6.985 -6.985) (layer Edge.Cuts) (width 0.12))
(fp_line (start -6.985 -6.985) (end 6.985 -6.985) (layer Edge.Cuts) (width 0.12))
)

View File

@ -0,0 +1,17 @@
(module MountingHole_3.5mm (layer F.Cu) (tedit 56D1B4CB)
(descr "Mounting Hole 3.5mm, no annular")
(tags "mounting hole 3.5mm no annular")
(attr virtual)
(fp_text reference REF** (at 0 -4.5) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value MountingHole_3.5mm (at 0 4.5) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 3.75 0) (layer F.CrtYd) (width 0.05))
(fp_circle (center 0 0) (end 3.5 0) (layer Cmts.User) (width 0.15))
(fp_text user %R (at 0.3 0) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 np_thru_hole circle (at 0 0) (size 3.5 3.5) (drill 3.5) (layers *.Cu *.Mask))
)

View File

@ -0,0 +1,75 @@
(module PinHeader_2x20_P2.54mm_Vertical (layer F.Cu) (tedit 5DEFFCEB)
(descr "Through hole straight pin header, 2x20, 2.54mm pitch, double rows")
(tags "Through hole pin header THT 2x20 2.54mm double row")
(fp_text reference REF** (at 1.2954 -2.5078) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value PinHeader_2x20_P2.54mm_Vertical (at 1.27 50.59) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start 2.5654 -1.4478) (end -1.2446 -1.4478) (layer F.Fab) (width 0.1))
(fp_line (start -1.2446 -1.4478) (end -1.2446 49.3522) (layer F.Fab) (width 0.1))
(fp_line (start -1.2446 49.3522) (end 3.8354 49.3522) (layer F.Fab) (width 0.1))
(fp_line (start 3.8354 49.3522) (end 3.8354 -0.1778) (layer F.Fab) (width 0.1))
(fp_line (start 3.8354 -0.1778) (end 2.5654 -1.4478) (layer F.Fab) (width 0.1))
(fp_line (start 3.8954 49.4122) (end -1.3046 49.4122) (layer F.SilkS) (width 0.12))
(fp_line (start 3.8954 1.0922) (end 3.8954 49.4122) (layer F.SilkS) (width 0.12))
(fp_line (start -1.3046 -1.5078) (end -1.3046 49.4122) (layer F.SilkS) (width 0.12))
(fp_line (start 3.8954 1.0922) (end 1.2954 1.0922) (layer F.SilkS) (width 0.12))
(fp_line (start 1.2954 1.0922) (end 1.2954 -1.5078) (layer F.SilkS) (width 0.12))
(fp_line (start 1.2954 -1.5078) (end -1.3046 -1.5078) (layer F.SilkS) (width 0.12))
(fp_line (start 3.8954 -0.1778) (end 3.8954 -1.5078) (layer F.SilkS) (width 0.12))
(fp_line (start 3.8954 -1.5078) (end 2.5654 -1.5078) (layer F.SilkS) (width 0.12))
(fp_line (start 4.3654 -1.9778) (end 4.3654 49.8722) (layer F.CrtYd) (width 0.05))
(fp_line (start 4.3654 49.8722) (end -1.7846 49.8722) (layer F.CrtYd) (width 0.05))
(fp_line (start -1.7846 49.8722) (end -1.7846 -1.9778) (layer F.CrtYd) (width 0.05))
(fp_line (start -1.7846 -1.9778) (end 4.3654 -1.9778) (layer F.CrtYd) (width 0.05))
(fp_text user %R (at 1.2954 23.9522 90) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 thru_hole rect (at 2.5654 -0.1778) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 2 thru_hole oval (at 0.0254 -0.1778) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 3 thru_hole oval (at 2.5654 2.3622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 4 thru_hole oval (at 0.0254 2.3622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 5 thru_hole oval (at 2.5654 4.9022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 6 thru_hole oval (at 0.0254 4.9022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 7 thru_hole oval (at 2.5654 7.4422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 8 thru_hole oval (at 0.0254 7.4422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 9 thru_hole oval (at 2.5654 9.9822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 10 thru_hole oval (at 0.0254 9.9822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 11 thru_hole oval (at 2.5654 12.5222) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 12 thru_hole oval (at 0.0254 12.5222) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 13 thru_hole oval (at 2.5654 15.0622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 14 thru_hole oval (at 0.0254 15.0622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 15 thru_hole oval (at 2.5654 17.6022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 16 thru_hole oval (at 0.0254 17.6022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 17 thru_hole oval (at 2.5654 20.1422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 18 thru_hole oval (at 0.0254 20.1422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 19 thru_hole oval (at 2.5654 22.6822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 20 thru_hole oval (at 0.0254 22.6822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 21 thru_hole oval (at 2.5654 25.2222) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 22 thru_hole oval (at 0.0254 25.2222) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 23 thru_hole oval (at 2.5654 27.7622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 24 thru_hole oval (at 0.0254 27.7622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 25 thru_hole oval (at 2.5654 30.3022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 26 thru_hole oval (at 0.0254 30.3022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 27 thru_hole oval (at 2.5654 32.8422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 28 thru_hole oval (at 0.0254 32.8422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 29 thru_hole oval (at 2.5654 35.3822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 30 thru_hole oval (at 0.0254 35.3822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 31 thru_hole oval (at 2.5654 37.9222) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 32 thru_hole oval (at 0.0254 37.9222) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 33 thru_hole oval (at 2.5654 40.4622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 34 thru_hole oval (at 0.0254 40.4622) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 35 thru_hole oval (at 2.5654 43.0022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 36 thru_hole oval (at 0.0254 43.0022) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 37 thru_hole oval (at 2.5654 45.5422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 38 thru_hole oval (at 0.0254 45.5422) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 39 thru_hole oval (at 2.5654 48.0822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(pad 40 thru_hole oval (at 0.0254 48.0822) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask))
(model ${KISYS3DMOD}/Connector_PinHeader_2.54mm.3dshapes/PinHeader_2x20_P2.54mm_Vertical.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# 74LS166
#
DEF 74LS166 U 0 40 Y Y 1 L N
F0 "U" -300 850 50 H V C CNN
F1 "74LS166" -300 -850 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
DIP?16*
$ENDFPLIST
DRAW
S -300 800 300 -800 1 1 10 f
X Ds 1 -500 700 200 R 50 50 1 0 I
X D3 10 500 200 200 L 50 50 1 0 I
X D2 11 500 100 200 L 50 50 1 0 I
X D1 12 500 0 200 L 50 50 1 0 I
X Qh 13 -500 200 200 R 50 50 1 0 O
X D0 14 500 -100 200 L 50 50 1 0 I
X SH_~LD 15 -500 50 200 R 50 50 1 0 I
X VCC 16 0 1000 200 D 50 50 1 0 W
X D7 2 500 600 200 L 50 50 1 0 I
X D6 3 500 500 200 L 50 50 1 0 I
X D5 4 500 400 200 L 50 50 1 0 I
X D4 5 500 300 200 L 50 50 1 0 I
X CK_INH 6 -500 -500 200 R 50 50 1 0 I
X CLK 7 -500 -100 200 R 50 50 1 0 I C
X GND 8 0 -1000 200 U 50 50 1 0 W
X Clr 9 -500 600 200 R 50 50 1 0 I I
ENDDRAW
ENDDEF
#
# ATmega328P-PU-MCU_Microchip_ATmega
#
DEF ATmega328P-PU-MCU_Microchip_ATmega U 0 20 Y Y 1 F N
F0 "U" -500 1450 50 H V L BNN
F1 "ATmega328P-PU-MCU_Microchip_ATmega" 100 -1450 50 H V L TNN
F2 "Package_DIP:DIP-28_W7.62mm" 0 0 50 H I C CIN
F3 "" 0 0 50 H I C CNN
$FPLIST
DIP*W7.62mm*
$ENDFPLIST
DRAW
S -500 -1400 500 1400 0 1 10 f
X ~RESET 1 600 -300 100 L 50 50 1 1 T
X PB7 10 600 500 100 L 50 50 1 1 T
X PD5 11 600 -1000 100 L 50 50 1 1 T
X PD6 12 600 -1100 100 L 50 50 1 1 T
X PD7 13 600 -1200 100 L 50 50 1 1 T
X PB0 14 600 1200 100 L 50 50 1 1 T
X PB1 15 600 1100 100 L 50 50 1 1 T
X PB2 16 600 1000 100 L 50 50 1 1 T
X MOSI 17 600 900 100 L 50 50 1 1 T
X MISO 18 600 800 100 L 50 50 1 1 T
X SCK 19 600 700 100 L 50 50 1 1 T
X PD0 2 600 -500 100 L 50 50 1 1 T
X AVCC 20 100 1500 100 D 50 50 1 1 W
X AREF 21 -600 1200 100 R 50 50 1 1 P
X GND 22 0 -1500 100 U 50 50 1 1 P N
X PC0 23 600 300 100 L 50 50 1 1 T
X PC1 24 600 200 100 L 50 50 1 1 T
X PC2 25 600 100 100 L 50 50 1 1 T
X PC3 26 600 0 100 L 50 50 1 1 T
X PC4 27 600 -100 100 L 50 50 1 1 T
X PC5 28 600 -200 100 L 50 50 1 1 T
X PD1 3 600 -600 100 L 50 50 1 1 T
X PD2 4 600 -700 100 L 50 50 1 1 T
X PD3 5 600 -800 100 L 50 50 1 1 T
X PD4 6 600 -900 100 L 50 50 1 1 T
X VCC 7 0 1500 100 D 50 50 1 1 W
X GND 8 0 -1500 100 U 50 50 1 1 W
X PB6 9 600 600 100 L 50 50 1 1 T
ENDDRAW
ENDDEF
#
#End Library

View File

@ -0,0 +1,281 @@
update=Saturday, November 23, 2019 at 09:32:10 AM
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]
[pcbnew]
version=1
PageLayoutDescrFile=
LastNetListRead=unikbd.net
CopperLayerCount=2
BoardThickness=1.6
AllowMicroVias=0
AllowBlindVias=0
RequireCourtyardDefinitions=0
ProhibitOverlappingCourtyards=1
MinTrackWidth=0.2
MinViaDiameter=0.4
MinViaDrill=0.3
MinMicroViaDiameter=0.2
MinMicroViaDrill=0.09999999999999999
MinHoleToHole=0.25
TrackWidth1=0.254
TrackWidth2=0.254
TrackWidth3=0.508
TrackWidth4=1.27
ViaDiameter1=0.8128
ViaDrill1=0.4064
ViaDiameter2=1.27
ViaDrill2=0.7112
dPairWidth1=0.2032
dPairGap1=0.254
dPairViaGap1=0.25
SilkLineWidth=0.15
SilkTextSizeV=1
SilkTextSizeH=1
SilkTextSizeThickness=0.15
SilkTextItalic=0
SilkTextUpright=1
CopperLineWidth=0.2
CopperTextSizeV=1.5
CopperTextSizeH=1.5
CopperTextThickness=0.3
CopperTextItalic=0
CopperTextUpright=1
EdgeCutLineWidth=0.09999999999999999
CourtyardLineWidth=0.05
OthersLineWidth=0.15
OthersTextSizeV=1
OthersTextSizeH=1
OthersTextSizeThickness=0.15
OthersTextItalic=0
OthersTextUpright=1
SolderMaskClearance=0
SolderMaskMinWidth=0
SolderPasteClearance=0
SolderPasteRatio=-0
[pcbnew/Layer.F.Cu]
Name=F.Cu
Type=0
Enabled=1
[pcbnew/Layer.In1.Cu]
Name=In1.Cu
Type=0
Enabled=0
[pcbnew/Layer.In2.Cu]
Name=In2.Cu
Type=0
Enabled=0
[pcbnew/Layer.In3.Cu]
Name=In3.Cu
Type=0
Enabled=0
[pcbnew/Layer.In4.Cu]
Name=In4.Cu
Type=0
Enabled=0
[pcbnew/Layer.In5.Cu]
Name=In5.Cu
Type=0
Enabled=0
[pcbnew/Layer.In6.Cu]
Name=In6.Cu
Type=0
Enabled=0
[pcbnew/Layer.In7.Cu]
Name=In7.Cu
Type=0
Enabled=0
[pcbnew/Layer.In8.Cu]
Name=In8.Cu
Type=0
Enabled=0
[pcbnew/Layer.In9.Cu]
Name=In9.Cu
Type=0
Enabled=0
[pcbnew/Layer.In10.Cu]
Name=In10.Cu
Type=0
Enabled=0
[pcbnew/Layer.In11.Cu]
Name=In11.Cu
Type=0
Enabled=0
[pcbnew/Layer.In12.Cu]
Name=In12.Cu
Type=0
Enabled=0
[pcbnew/Layer.In13.Cu]
Name=In13.Cu
Type=0
Enabled=0
[pcbnew/Layer.In14.Cu]
Name=In14.Cu
Type=0
Enabled=0
[pcbnew/Layer.In15.Cu]
Name=In15.Cu
Type=0
Enabled=0
[pcbnew/Layer.In16.Cu]
Name=In16.Cu
Type=0
Enabled=0
[pcbnew/Layer.In17.Cu]
Name=In17.Cu
Type=0
Enabled=0
[pcbnew/Layer.In18.Cu]
Name=In18.Cu
Type=0
Enabled=0
[pcbnew/Layer.In19.Cu]
Name=In19.Cu
Type=0
Enabled=0
[pcbnew/Layer.In20.Cu]
Name=In20.Cu
Type=0
Enabled=0
[pcbnew/Layer.In21.Cu]
Name=In21.Cu
Type=0
Enabled=0
[pcbnew/Layer.In22.Cu]
Name=In22.Cu
Type=0
Enabled=0
[pcbnew/Layer.In23.Cu]
Name=In23.Cu
Type=0
Enabled=0
[pcbnew/Layer.In24.Cu]
Name=In24.Cu
Type=0
Enabled=0
[pcbnew/Layer.In25.Cu]
Name=In25.Cu
Type=0
Enabled=0
[pcbnew/Layer.In26.Cu]
Name=In26.Cu
Type=0
Enabled=0
[pcbnew/Layer.In27.Cu]
Name=In27.Cu
Type=0
Enabled=0
[pcbnew/Layer.In28.Cu]
Name=In28.Cu
Type=0
Enabled=0
[pcbnew/Layer.In29.Cu]
Name=In29.Cu
Type=0
Enabled=0
[pcbnew/Layer.In30.Cu]
Name=In30.Cu
Type=0
Enabled=0
[pcbnew/Layer.B.Cu]
Name=B.Cu
Type=0
Enabled=1
[pcbnew/Layer.B.Adhes]
Enabled=1
[pcbnew/Layer.F.Adhes]
Enabled=1
[pcbnew/Layer.B.Paste]
Enabled=1
[pcbnew/Layer.F.Paste]
Enabled=1
[pcbnew/Layer.B.SilkS]
Enabled=1
[pcbnew/Layer.F.SilkS]
Enabled=1
[pcbnew/Layer.B.Mask]
Enabled=1
[pcbnew/Layer.F.Mask]
Enabled=1
[pcbnew/Layer.Dwgs.User]
Enabled=1
[pcbnew/Layer.Cmts.User]
Enabled=1
[pcbnew/Layer.Eco1.User]
Enabled=1
[pcbnew/Layer.Eco2.User]
Enabled=1
[pcbnew/Layer.Edge.Cuts]
Enabled=1
[pcbnew/Layer.Margin]
Enabled=1
[pcbnew/Layer.B.CrtYd]
Enabled=1
[pcbnew/Layer.F.CrtYd]
Enabled=1
[pcbnew/Layer.B.Fab]
Enabled=1
[pcbnew/Layer.F.Fab]
Enabled=1
[pcbnew/Layer.Rescue]
Enabled=0
[pcbnew/Netclasses]
[pcbnew/Netclasses/Default]
Name=Default
Clearance=0.2
TrackWidth=0.254
ViaDiameter=0.8128
ViaDrill=0.4064
uViaDiameter=0.3048
uViaDrill=0.1016
dPairWidth=0.2032
dPairGap=0.254
dPairViaGap=0.25
[pcbnew/Netclasses/1]
Name=power1
Clearance=0.254
TrackWidth=1.27
ViaDiameter=1.27
ViaDrill=0.7112
uViaDiameter=0.3048
uViaDrill=0.1016
dPairWidth=0.2032
dPairGap=0.254
dPairViaGap=0.25
[pcbnew/Netclasses/2]
Name=signal
Clearance=0.2032
TrackWidth=0.254
ViaDiameter=0.8128
ViaDrill=0.4064
uViaDiameter=0.3048
uViaDrill=0.1016
dPairWidth=0.2032
dPairGap=0.254
dPairViaGap=0.25
[schematic_editor]
version=1
PageLayoutDescrFile=
PlotDirectoryName=
SubpartIdSeparator=0
SubpartFirstId=65
NetFmtName=
SpiceAjustPassiveValues=0
LabSize=50
ERC_WriteFile=0
ERC_TestSimilarLabels=1
ERC_CheckUniqueGlobalLabels=1
ERC_CheckBusDriverConflicts=1
ERC_CheckBusEntryConflicts=1
ERC_CheckBusToBusConflicts=1
ERC_CheckBusToNetConflicts=1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,265 @@
update=6/24/2019 2:07:05 PM
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]
[pcbnew]
version=1
PageLayoutDescrFile=
LastNetListRead=unikbd.net
CopperLayerCount=2
BoardThickness=1.6
AllowMicroVias=0
AllowBlindVias=0
RequireCourtyardDefinitions=0
ProhibitOverlappingCourtyards=1
MinTrackWidth=0.2
MinViaDiameter=0.4
MinViaDrill=0.3
MinMicroViaDiameter=0.2
MinMicroViaDrill=0.09999999999999999
MinHoleToHole=0.25
TrackWidth1=0.254
TrackWidth2=0.254
TrackWidth3=0.508
TrackWidth4=1.27
ViaDiameter1=0.8128
ViaDrill1=0.4064
ViaDiameter2=1.27
ViaDrill2=0.7112
dPairWidth1=0.2032
dPairGap1=0.254
dPairViaGap1=0.25
SilkLineWidth=0.15
SilkTextSizeV=1
SilkTextSizeH=1
SilkTextSizeThickness=0.15
SilkTextItalic=0
SilkTextUpright=1
CopperLineWidth=0.2
CopperTextSizeV=1.5
CopperTextSizeH=1.5
CopperTextThickness=0.3
CopperTextItalic=0
CopperTextUpright=1
EdgeCutLineWidth=0.09999999999999999
CourtyardLineWidth=0.05
OthersLineWidth=0.15
OthersTextSizeV=1
OthersTextSizeH=1
OthersTextSizeThickness=0.15
OthersTextItalic=0
OthersTextUpright=1
SolderMaskClearance=0
SolderMaskMinWidth=0
SolderPasteClearance=0
SolderPasteRatio=-0
[pcbnew/Layer.F.Cu]
Name=F.Cu
Type=0
Enabled=1
[pcbnew/Layer.In1.Cu]
Name=In1.Cu
Type=0
Enabled=0
[pcbnew/Layer.In2.Cu]
Name=In2.Cu
Type=0
Enabled=0
[pcbnew/Layer.In3.Cu]
Name=In3.Cu
Type=0
Enabled=0
[pcbnew/Layer.In4.Cu]
Name=In4.Cu
Type=0
Enabled=0
[pcbnew/Layer.In5.Cu]
Name=In5.Cu
Type=0
Enabled=0
[pcbnew/Layer.In6.Cu]
Name=In6.Cu
Type=0
Enabled=0
[pcbnew/Layer.In7.Cu]
Name=In7.Cu
Type=0
Enabled=0
[pcbnew/Layer.In8.Cu]
Name=In8.Cu
Type=0
Enabled=0
[pcbnew/Layer.In9.Cu]
Name=In9.Cu
Type=0
Enabled=0
[pcbnew/Layer.In10.Cu]
Name=In10.Cu
Type=0
Enabled=0
[pcbnew/Layer.In11.Cu]
Name=In11.Cu
Type=0
Enabled=0
[pcbnew/Layer.In12.Cu]
Name=In12.Cu
Type=0
Enabled=0
[pcbnew/Layer.In13.Cu]
Name=In13.Cu
Type=0
Enabled=0
[pcbnew/Layer.In14.Cu]
Name=In14.Cu
Type=0
Enabled=0
[pcbnew/Layer.In15.Cu]
Name=In15.Cu
Type=0
Enabled=0
[pcbnew/Layer.In16.Cu]
Name=In16.Cu
Type=0
Enabled=0
[pcbnew/Layer.In17.Cu]
Name=In17.Cu
Type=0
Enabled=0
[pcbnew/Layer.In18.Cu]
Name=In18.Cu
Type=0
Enabled=0
[pcbnew/Layer.In19.Cu]
Name=In19.Cu
Type=0
Enabled=0
[pcbnew/Layer.In20.Cu]
Name=In20.Cu
Type=0
Enabled=0
[pcbnew/Layer.In21.Cu]
Name=In21.Cu
Type=0
Enabled=0
[pcbnew/Layer.In22.Cu]
Name=In22.Cu
Type=0
Enabled=0
[pcbnew/Layer.In23.Cu]
Name=In23.Cu
Type=0
Enabled=0
[pcbnew/Layer.In24.Cu]
Name=In24.Cu
Type=0
Enabled=0
[pcbnew/Layer.In25.Cu]
Name=In25.Cu
Type=0
Enabled=0
[pcbnew/Layer.In26.Cu]
Name=In26.Cu
Type=0
Enabled=0
[pcbnew/Layer.In27.Cu]
Name=In27.Cu
Type=0
Enabled=0
[pcbnew/Layer.In28.Cu]
Name=In28.Cu
Type=0
Enabled=0
[pcbnew/Layer.In29.Cu]
Name=In29.Cu
Type=0
Enabled=0
[pcbnew/Layer.In30.Cu]
Name=In30.Cu
Type=0
Enabled=0
[pcbnew/Layer.B.Cu]
Name=B.Cu
Type=0
Enabled=1
[pcbnew/Layer.B.Adhes]
Enabled=1
[pcbnew/Layer.F.Adhes]
Enabled=1
[pcbnew/Layer.B.Paste]
Enabled=1
[pcbnew/Layer.F.Paste]
Enabled=1
[pcbnew/Layer.B.SilkS]
Enabled=1
[pcbnew/Layer.F.SilkS]
Enabled=1
[pcbnew/Layer.B.Mask]
Enabled=1
[pcbnew/Layer.F.Mask]
Enabled=1
[pcbnew/Layer.Dwgs.User]
Enabled=1
[pcbnew/Layer.Cmts.User]
Enabled=1
[pcbnew/Layer.Eco1.User]
Enabled=1
[pcbnew/Layer.Eco2.User]
Enabled=1
[pcbnew/Layer.Edge.Cuts]
Enabled=1
[pcbnew/Layer.Margin]
Enabled=1
[pcbnew/Layer.B.CrtYd]
Enabled=1
[pcbnew/Layer.F.CrtYd]
Enabled=1
[pcbnew/Layer.B.Fab]
Enabled=1
[pcbnew/Layer.F.Fab]
Enabled=1
[pcbnew/Layer.Rescue]
Enabled=0
[pcbnew/Netclasses]
[pcbnew/Netclasses/Default]
Name=Default
Clearance=0.2
TrackWidth=0.254
ViaDiameter=0.8128
ViaDrill=0.4064
uViaDiameter=0.3048
uViaDrill=0.1016
dPairWidth=0.2032
dPairGap=0.254
dPairViaGap=0.25
[pcbnew/Netclasses/1]
Name=power1
Clearance=0.254
TrackWidth=1.27
ViaDiameter=1.27
ViaDrill=0.7112
uViaDiameter=0.3048
uViaDrill=0.1016
dPairWidth=0.2032
dPairGap=0.254
dPairViaGap=0.25
[pcbnew/Netclasses/2]
Name=signal
Clearance=0.2032
TrackWidth=0.254
ViaDiameter=0.8128
ViaDrill=0.4064
uViaDiameter=0.3048
uViaDrill=0.1016
dPairWidth=0.2032
dPairGap=0.254
dPairViaGap=0.25

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
update=05/04/2019 20:44:53
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[pcbnew]
version=1
LastNetListRead=
UseCmpFile=1
PadDrill=0.600000000000
PadDrillOvalY=0.600000000000
PadSizeH=1.500000000000
PadSizeV=1.500000000000
PcbTextSizeV=1.500000000000
PcbTextSizeH=1.500000000000
PcbTextThickness=0.300000000000
ModuleTextSizeV=1.000000000000
ModuleTextSizeH=1.000000000000
ModuleTextSizeThickness=0.150000000000
SolderMaskClearance=0.000000000000
SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
CopperEdgeClearance=0.000000000000
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
update=05/04/2019 20:44:53
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[pcbnew]
version=1
LastNetListRead=
UseCmpFile=1
PadDrill=0.600000000000
PadDrillOvalY=0.600000000000
PadSizeH=1.500000000000
PadSizeV=1.500000000000
PcbTextSizeV=1.500000000000
PcbTextSizeH=1.500000000000
PcbTextThickness=0.300000000000
ModuleTextSizeV=1.000000000000
ModuleTextSizeH=1.000000000000
ModuleTextSizeThickness=0.150000000000
SolderMaskClearance=0.000000000000
SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
CopperEdgeClearance=0.000000000000
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

View File

@ -0,0 +1,177 @@
(kicad_pcb (version 20171130) (host pcbnew "(5.1.4-0-10_14)")
(general
(thickness 1.6)
(drawings 35)
(tracks 0)
(zones 0)
(modules 0)
(nets 1)
)
(page B)
(title_block
(title "Universal Retro Keyboard")
(date 2019-08-25)
(rev 1.0)
(company OSIWeb.org)
(comment 1 "Key matrix w/ LED")
)
(layers
(0 F.Cu signal)
(31 B.Cu signal)
(32 B.Adhes user)
(33 F.Adhes user)
(34 B.Paste user)
(35 F.Paste user)
(36 B.SilkS user)
(37 F.SilkS user)
(38 B.Mask user)
(39 F.Mask user)
(40 Dwgs.User user)
(41 Cmts.User user)
(42 Eco1.User user)
(43 Eco2.User user)
(44 Edge.Cuts user)
(45 Margin user)
(46 B.CrtYd user)
(47 F.CrtYd user)
(48 B.Fab user)
(49 F.Fab user)
)
(setup
(last_trace_width 0.254)
(user_trace_width 0.254)
(user_trace_width 0.508)
(user_trace_width 1.27)
(trace_clearance 0.2)
(zone_clearance 0.508)
(zone_45_only no)
(trace_min 0.2)
(via_size 0.8128)
(via_drill 0.4064)
(via_min_size 0.4)
(via_min_drill 0.3)
(user_via 1.27 0.7112)
(uvia_size 0.3048)
(uvia_drill 0.1016)
(uvias_allowed no)
(uvia_min_size 0.2)
(uvia_min_drill 0.1)
(edge_width 0.1)
(segment_width 0.2)
(pcb_text_width 0.3)
(pcb_text_size 1.5 1.5)
(mod_edge_width 0.15)
(mod_text_size 1 1)
(mod_text_width 0.15)
(pad_size 3.9878 3.9878)
(pad_drill 3.9878)
(pad_to_mask_clearance 0)
(aux_axis_origin 61.4172 179.1081)
(visible_elements 7FFFEFFF)
(pcbplotparams
(layerselection 0x010fc_ffffffff)
(usegerberextensions false)
(usegerberattributes false)
(usegerberadvancedattributes false)
(creategerberjobfile false)
(excludeedgelayer true)
(linewidth 0.100000)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(padsonsilk false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 1)
(scaleselection 1)
(outputdirectory ""))
)
(net 0 "")
(net_class Default "This is the default net class."
(clearance 0.2)
(trace_width 0.254)
(via_dia 0.8128)
(via_drill 0.4064)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(net_class power1 ""
(clearance 0.254)
(trace_width 1.27)
(via_dia 1.27)
(via_drill 0.7112)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(net_class signal ""
(clearance 0.2032)
(trace_width 0.254)
(via_dia 0.8128)
(via_drill 0.4064)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(gr_line (start 78.359 175.133) (end 96.647 175.133) (layer B.Fab) (width 0.15) (tstamp 5D9294FB))
(gr_line (start 96.647 156.083) (end 96.647 175.133) (layer B.Fab) (width 0.15))
(gr_line (start 325.374 118.745) (end 320.548 118.745) (layer B.Fab) (width 0.15) (tstamp 5D92929E))
(gr_line (start 320.548 137.033) (end 320.548 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 320.548 118.745) (end 320.548 137.033) (layer B.Fab) (width 0.15))
(gr_line (start 325.374 80.645) (end 325.374 118.745) (layer B.Fab) (width 0.15))
(gr_circle (center 143.51 78.74) (end 145.0975 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D91233E))
(gr_circle (center 290.83 78.74) (end 292.4175 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123A8))
(gr_circle (center 284.607 171.45) (end 286.1945 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D9122A9))
(gr_circle (center 107.7595 171.45) (end 109.347 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D9122A9))
(gr_circle (center 300.7106 78.74) (end 302.2981 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D912365))
(gr_circle (center 348.9706 78.74) (end 350.5581 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D912368))
(gr_circle (center 217.17 78.74) (end 218.7575 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123AE))
(gr_circle (center 364.49 78.74) (end 366.0775 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123AB))
(gr_circle (center 363.22 171.45) (end 364.8075 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D911836))
(gr_circle (center 71.12 171.45) (end 72.7075 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D911836))
(gr_circle (center 69.85 78.74) (end 71.4375 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123B1))
(gr_line (start 78.486 99.695) (end 78.486 80.645) (layer B.Fab) (width 0.15))
(gr_line (start 68.834 99.695) (end 78.486 99.695) (layer B.Fab) (width 0.15))
(gr_line (start 68.834 117.983) (end 68.834 99.695) (layer B.Fab) (width 0.15))
(gr_line (start 73.406 117.983) (end 68.834 117.983) (layer B.Fab) (width 0.15))
(gr_line (start 73.406 137.033) (end 73.406 117.983) (layer B.Fab) (width 0.15))
(gr_line (start 78.359 137.033) (end 73.533 137.033) (layer B.Fab) (width 0.15))
(gr_line (start 78.359 175.133) (end 78.359 137.033) (layer B.Fab) (width 0.15))
(gr_line (start 121.158 156.083) (end 96.647 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 121.158 175.133) (end 121.158 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 272.923 175.133) (end 121.158 175.133) (layer B.Fab) (width 0.15) (tstamp 5D90C768))
(gr_line (start 272.923 156.083) (end 272.923 175.133) (layer B.Fab) (width 0.15))
(gr_line (start 320.548 156.083) (end 272.923 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 78.486 80.645) (end 325.374 80.645) (layer B.Fab) (width 0.15) (tstamp 5D90C80E))
(gr_line (start 64.77 177.8) (end 369.57 177.8) (layer Edge.Cuts) (width 0.1) (tstamp 5D911490))
(gr_line (start 64.77 73.914) (end 64.77 177.8) (layer Edge.Cuts) (width 0.1))
(gr_line (start 369.57 73.914) (end 64.77 73.914) (layer Edge.Cuts) (width 0.1) (tstamp 5D91148D))
(gr_line (start 369.57 177.8) (end 369.57 73.914) (layer Edge.Cuts) (width 0.1) (tstamp 5D91148A))
(gr_text "Distances:\nVertical: 0.75 inch\nHorizontal (1x - 1x): 0.75 inch\nHorizontal (1x - 1.5x): 0.939 inch\nHorizontal (Row 1 left key -> Row 2 left key): -0.379 inch\nHorizontal (Row 2 left key -> Row 3 left key): 0.187 inch\nHorizontal (Row 3 left key -> Row 4 left key): 0.186 inch\nHorizontal (Row 4 left key -> space bar): 4.310 inch" (at 38.4175 240.0681) (layer Cmts.User)
(effects (font (size 2.54 2.54) (thickness 0.3048)) (justify left))
)
)

View File

@ -0,0 +1,33 @@
update=22/05/2015 07:44:53
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[pcbnew]
version=1
LastNetListRead=
UseCmpFile=1
PadDrill=0.600000000000
PadDrillOvalY=0.600000000000
PadSizeH=1.500000000000
PadSizeV=1.500000000000
PcbTextSizeV=1.500000000000
PcbTextSizeH=1.500000000000
PcbTextThickness=0.300000000000
ModuleTextSizeV=1.000000000000
ModuleTextSizeH=1.000000000000
ModuleTextSizeThickness=0.150000000000
SolderMaskClearance=0.000000000000
SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

View File

@ -0,0 +1,174 @@
(kicad_pcb (version 20171130) (host pcbnew "(5.1.4-0-10_14)")
(general
(thickness 1.6)
(drawings 32)
(tracks 0)
(zones 0)
(modules 0)
(nets 1)
)
(page B)
(title_block
(title "Universal Retro Keyboard")
(date 2019-08-25)
(rev 1.0)
(company OSIWeb.org)
(comment 1 "Key matrix w/ LED")
)
(layers
(0 F.Cu signal)
(31 B.Cu signal)
(32 B.Adhes user)
(33 F.Adhes user)
(34 B.Paste user)
(35 F.Paste user)
(36 B.SilkS user)
(37 F.SilkS user)
(38 B.Mask user)
(39 F.Mask user)
(40 Dwgs.User user)
(41 Cmts.User user)
(42 Eco1.User user)
(43 Eco2.User user)
(44 Edge.Cuts user)
(45 Margin user)
(46 B.CrtYd user)
(47 F.CrtYd user)
(48 B.Fab user)
(49 F.Fab user)
)
(setup
(last_trace_width 0.254)
(user_trace_width 0.254)
(user_trace_width 0.508)
(user_trace_width 1.27)
(trace_clearance 0.2)
(zone_clearance 0.508)
(zone_45_only no)
(trace_min 0.2)
(via_size 0.8128)
(via_drill 0.4064)
(via_min_size 0.4)
(via_min_drill 0.3)
(user_via 1.27 0.7112)
(uvia_size 0.3048)
(uvia_drill 0.1016)
(uvias_allowed no)
(uvia_min_size 0.2)
(uvia_min_drill 0.1)
(edge_width 0.1)
(segment_width 0.2)
(pcb_text_width 0.3)
(pcb_text_size 1.5 1.5)
(mod_edge_width 0.15)
(mod_text_size 1 1)
(mod_text_width 0.15)
(pad_size 3.9878 3.9878)
(pad_drill 3.9878)
(pad_to_mask_clearance 0)
(aux_axis_origin 61.4172 179.1081)
(visible_elements 7FFFEFFF)
(pcbplotparams
(layerselection 0x010fc_ffffffff)
(usegerberextensions false)
(usegerberattributes false)
(usegerberadvancedattributes false)
(creategerberjobfile false)
(excludeedgelayer true)
(linewidth 0.100000)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(padsonsilk false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 1)
(scaleselection 1)
(outputdirectory ""))
)
(net 0 "")
(net_class Default "This is the default net class."
(clearance 0.2)
(trace_width 0.254)
(via_dia 0.8128)
(via_drill 0.4064)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(net_class power1 ""
(clearance 0.254)
(trace_width 1.27)
(via_dia 1.27)
(via_drill 0.7112)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(net_class signal ""
(clearance 0.2032)
(trace_width 0.254)
(via_dia 0.8128)
(via_drill 0.4064)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(gr_circle (center 143.51 78.74) (end 145.0975 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D91233E))
(gr_circle (center 290.83 78.74) (end 292.4175 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123A8))
(gr_circle (center 284.607 171.45) (end 286.1945 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D9122A9))
(gr_circle (center 107.7595 171.45) (end 109.347 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D9122A9))
(gr_circle (center 300.7106 78.74) (end 302.2981 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D912365))
(gr_circle (center 348.9706 78.74) (end 350.5581 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D912368))
(gr_circle (center 217.17 78.74) (end 218.7575 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123AE))
(gr_circle (center 364.49 78.74) (end 366.0775 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123AB))
(gr_circle (center 363.22 171.45) (end 364.8075 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D911836))
(gr_circle (center 71.12 171.45) (end 72.7075 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D911836))
(gr_circle (center 69.85 78.74) (end 71.4375 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123B1))
(gr_line (start 78.486 99.695) (end 78.486 80.645) (layer Edge.Cuts) (width 0.15))
(gr_line (start 68.834 99.695) (end 78.486 99.695) (layer Edge.Cuts) (width 0.15))
(gr_line (start 68.834 117.983) (end 68.834 99.695) (layer Edge.Cuts) (width 0.15))
(gr_line (start 73.406 117.983) (end 68.834 117.983) (layer Edge.Cuts) (width 0.15))
(gr_line (start 73.406 137.033) (end 73.406 117.983) (layer Edge.Cuts) (width 0.15))
(gr_line (start 78.359 137.033) (end 73.533 137.033) (layer Edge.Cuts) (width 0.15))
(gr_line (start 78.359 156.083) (end 78.359 137.033) (layer Edge.Cuts) (width 0.15))
(gr_line (start 121.158 156.083) (end 78.359 156.083) (layer Edge.Cuts) (width 0.15))
(gr_line (start 121.158 175.133) (end 121.158 156.083) (layer Edge.Cuts) (width 0.15))
(gr_line (start 272.923 175.133) (end 121.158 175.133) (layer Edge.Cuts) (width 0.15) (tstamp 5D90C768))
(gr_line (start 272.923 156.083) (end 272.923 175.133) (layer Edge.Cuts) (width 0.15))
(gr_line (start 358.648 156.083) (end 272.923 156.083) (layer Edge.Cuts) (width 0.15))
(gr_line (start 358.648 117.983) (end 358.648 156.083) (layer Edge.Cuts) (width 0.15))
(gr_line (start 363.347 117.983) (end 358.648 117.983) (layer Edge.Cuts) (width 0.15) (tstamp 5D90C7F7))
(gr_line (start 363.347 80.645) (end 363.347 117.983) (layer Edge.Cuts) (width 0.15))
(gr_line (start 78.486 80.645) (end 363.347 80.645) (layer Edge.Cuts) (width 0.15) (tstamp 5D90C80E))
(gr_line (start 64.77 177.8) (end 369.57 177.8) (layer Edge.Cuts) (width 0.1) (tstamp 5D911490))
(gr_line (start 64.77 73.914) (end 64.77 177.8) (layer Edge.Cuts) (width 0.1))
(gr_line (start 369.57 73.914) (end 64.77 73.914) (layer Edge.Cuts) (width 0.1) (tstamp 5D91148D))
(gr_line (start 369.57 177.8) (end 369.57 73.914) (layer Edge.Cuts) (width 0.1) (tstamp 5D91148A))
(gr_text "Distances:\nVertical: 0.75 inch\nHorizontal (1x - 1x): 0.75 inch\nHorizontal (1x - 1.5x): 0.939 inch\nHorizontal (Row 1 left key -> Row 2 left key): -0.379 inch\nHorizontal (Row 2 left key -> Row 3 left key): 0.187 inch\nHorizontal (Row 3 left key -> Row 4 left key): 0.186 inch\nHorizontal (Row 4 left key -> space bar): 4.310 inch" (at 38.4175 240.0681) (layer Cmts.User)
(effects (font (size 2.54 2.54) (thickness 0.3048)) (justify left))
)
)

View File

@ -0,0 +1,33 @@
update=22/05/2015 07:44:53
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[pcbnew]
version=1
LastNetListRead=
UseCmpFile=1
PadDrill=0.600000000000
PadDrillOvalY=0.600000000000
PadSizeH=1.500000000000
PadSizeV=1.500000000000
PcbTextSizeV=1.500000000000
PcbTextSizeH=1.500000000000
PcbTextThickness=0.300000000000
ModuleTextSizeV=1.000000000000
ModuleTextSizeH=1.000000000000
ModuleTextSizeThickness=0.150000000000
SolderMaskClearance=0.000000000000
SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

View File

@ -0,0 +1,176 @@
(kicad_pcb (version 20171130) (host pcbnew "(5.1.4-0-10_14)")
(general
(thickness 1.6)
(drawings 34)
(tracks 0)
(zones 0)
(modules 0)
(nets 1)
)
(page B)
(title_block
(title "Universal Retro Keyboard")
(date 2019-08-25)
(rev 1.0)
(company OSIWeb.org)
(comment 1 "Key matrix w/ LED")
)
(layers
(0 F.Cu signal)
(31 B.Cu signal)
(32 B.Adhes user)
(33 F.Adhes user)
(34 B.Paste user)
(35 F.Paste user)
(36 B.SilkS user)
(37 F.SilkS user)
(38 B.Mask user)
(39 F.Mask user)
(40 Dwgs.User user)
(41 Cmts.User user)
(42 Eco1.User user)
(43 Eco2.User user)
(44 Edge.Cuts user)
(45 Margin user)
(46 B.CrtYd user)
(47 F.CrtYd user)
(48 B.Fab user)
(49 F.Fab user)
)
(setup
(last_trace_width 0.254)
(user_trace_width 0.254)
(user_trace_width 0.508)
(user_trace_width 1.27)
(trace_clearance 0.2)
(zone_clearance 0.508)
(zone_45_only no)
(trace_min 0.2)
(via_size 0.8128)
(via_drill 0.4064)
(via_min_size 0.4)
(via_min_drill 0.3)
(user_via 1.27 0.7112)
(uvia_size 0.3048)
(uvia_drill 0.1016)
(uvias_allowed no)
(uvia_min_size 0.2)
(uvia_min_drill 0.1)
(edge_width 0.1)
(segment_width 0.2)
(pcb_text_width 0.3)
(pcb_text_size 1.5 1.5)
(mod_edge_width 0.15)
(mod_text_size 1 1)
(mod_text_width 0.15)
(pad_size 3.9878 3.9878)
(pad_drill 3.9878)
(pad_to_mask_clearance 0)
(aux_axis_origin 61.4172 179.1081)
(visible_elements 7FFFEFFF)
(pcbplotparams
(layerselection 0x010fc_ffffffff)
(usegerberextensions false)
(usegerberattributes false)
(usegerberadvancedattributes false)
(creategerberjobfile false)
(excludeedgelayer true)
(linewidth 0.100000)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(padsonsilk false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 1)
(scaleselection 1)
(outputdirectory ""))
)
(net 0 "")
(net_class Default "This is the default net class."
(clearance 0.2)
(trace_width 0.254)
(via_dia 0.8128)
(via_drill 0.4064)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(net_class power1 ""
(clearance 0.254)
(trace_width 1.27)
(via_dia 1.27)
(via_drill 0.7112)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(net_class signal ""
(clearance 0.2032)
(trace_width 0.254)
(via_dia 0.8128)
(via_drill 0.4064)
(uvia_dia 0.3048)
(uvia_drill 0.1016)
(diff_pair_width 0.2032)
(diff_pair_gap 0.254)
)
(gr_line (start 320.548 137.033) (end 320.548 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 339.598 137.033) (end 320.548 137.033) (layer B.Fab) (width 0.15))
(gr_line (start 339.598 118.745) (end 339.598 137.033) (layer B.Fab) (width 0.15))
(gr_line (start 325.374 118.745) (end 339.598 118.745) (layer B.Fab) (width 0.15))
(gr_line (start 325.374 80.645) (end 325.374 118.745) (layer B.Fab) (width 0.15))
(gr_circle (center 143.51 78.74) (end 145.0975 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D91233E))
(gr_circle (center 290.83 78.74) (end 292.4175 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123A8))
(gr_circle (center 284.607 171.45) (end 286.1945 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D9122A9))
(gr_circle (center 107.7595 171.45) (end 109.347 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D9122A9))
(gr_circle (center 300.7106 78.74) (end 302.2981 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D912365))
(gr_circle (center 348.9706 78.74) (end 350.5581 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D912368))
(gr_circle (center 217.17 78.74) (end 218.7575 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123AE))
(gr_circle (center 364.49 78.74) (end 366.0775 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123AB))
(gr_circle (center 363.22 171.45) (end 364.8075 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D911836))
(gr_circle (center 71.12 171.45) (end 72.7075 171.45) (layer Edge.Cuts) (width 0.1) (tstamp 5D911836))
(gr_circle (center 69.85 78.74) (end 71.4375 78.74) (layer Edge.Cuts) (width 0.1) (tstamp 5D9123B1))
(gr_line (start 78.486 99.695) (end 78.486 80.645) (layer B.Fab) (width 0.15))
(gr_line (start 68.834 99.695) (end 78.486 99.695) (layer B.Fab) (width 0.15))
(gr_line (start 68.834 117.983) (end 68.834 99.695) (layer B.Fab) (width 0.15))
(gr_line (start 73.406 117.983) (end 68.834 117.983) (layer B.Fab) (width 0.15))
(gr_line (start 73.406 137.033) (end 73.406 117.983) (layer B.Fab) (width 0.15))
(gr_line (start 78.359 137.033) (end 73.533 137.033) (layer B.Fab) (width 0.15))
(gr_line (start 78.359 156.083) (end 78.359 137.033) (layer B.Fab) (width 0.15))
(gr_line (start 121.158 156.083) (end 78.359 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 121.158 175.133) (end 121.158 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 272.923 175.133) (end 121.158 175.133) (layer B.Fab) (width 0.15) (tstamp 5D90C768))
(gr_line (start 272.923 156.083) (end 272.923 175.133) (layer B.Fab) (width 0.15))
(gr_line (start 320.548 156.083) (end 272.923 156.083) (layer B.Fab) (width 0.15))
(gr_line (start 78.486 80.645) (end 325.374 80.645) (layer B.Fab) (width 0.15) (tstamp 5D90C80E))
(gr_line (start 64.77 177.8) (end 369.57 177.8) (layer Edge.Cuts) (width 0.1) (tstamp 5D911490))
(gr_line (start 64.77 73.914) (end 64.77 177.8) (layer Edge.Cuts) (width 0.1))
(gr_line (start 369.57 73.914) (end 64.77 73.914) (layer Edge.Cuts) (width 0.1) (tstamp 5D91148D))
(gr_line (start 369.57 177.8) (end 369.57 73.914) (layer Edge.Cuts) (width 0.1) (tstamp 5D91148A))
(gr_text "Distances:\nVertical: 0.75 inch\nHorizontal (1x - 1x): 0.75 inch\nHorizontal (1x - 1.5x): 0.939 inch\nHorizontal (Row 1 left key -> Row 2 left key): -0.379 inch\nHorizontal (Row 2 left key -> Row 3 left key): 0.187 inch\nHorizontal (Row 3 left key -> Row 4 left key): 0.186 inch\nHorizontal (Row 4 left key -> space bar): 4.310 inch" (at 38.4175 240.0681) (layer Cmts.User)
(effects (font (size 2.54 2.54) (thickness 0.3048)) (justify left))
)
)

View File

@ -0,0 +1,33 @@
update=22/05/2015 07:44:53
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[pcbnew]
version=1
LastNetListRead=
UseCmpFile=1
PadDrill=0.600000000000
PadDrillOvalY=0.600000000000
PadSizeH=1.500000000000
PadSizeV=1.500000000000
PcbTextSizeV=1.500000000000
PcbTextSizeH=1.500000000000
PcbTextThickness=0.300000000000
ModuleTextSizeV=1.000000000000
ModuleTextSizeH=1.000000000000
ModuleTextSizeThickness=0.150000000000
SolderMaskClearance=0.000000000000
SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
update=22/05/2015 07:44:53
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[pcbnew]
version=1
LastNetListRead=
UseCmpFile=1
PadDrill=0.600000000000
PadDrillOvalY=0.600000000000
PadSizeH=1.500000000000
PadSizeV=1.500000000000
PcbTextSizeV=1.500000000000
PcbTextSizeH=1.500000000000
PcbTextThickness=0.300000000000
ModuleTextSizeV=1.000000000000
ModuleTextSizeH=1.000000000000
ModuleTextSizeThickness=0.150000000000
SolderMaskClearance=0.000000000000
SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

View File

@ -0,0 +1,464 @@
EESchema Schematic File Version 4
EELAYER 30 0
EELAYER END
$Descr USLetter 11000 8500
encoding utf-8
Sheet 1 3
Title "Universal Retro Keyboard"
Date "2019-08-25"
Rev "1.0"
Comp "OSIWeb.org"
Comment1 "Main sheet with connector"
Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
Text Label 2725 4300 2 50 ~ 0
Col0
Text Label 2725 4200 2 50 ~ 0
Col1
Text Label 2725 4100 2 50 ~ 0
Col2
Text Label 2725 4000 2 50 ~ 0
Col3
Text Label 2725 3900 2 50 ~ 0
Col4
Text Label 2725 3800 2 50 ~ 0
Col5
Text Label 2725 3700 2 50 ~ 0
Col6
Text Label 2725 3600 2 50 ~ 0
Col7
Text Label 2725 1800 2 50 ~ 0
Col0
Text Label 2725 1700 2 50 ~ 0
Col1
Text Label 2725 1600 2 50 ~ 0
Col2
Text Label 2725 1500 2 50 ~ 0
Col3
Text Label 2725 1400 2 50 ~ 0
Col4
Text Label 2725 1300 2 50 ~ 0
Col5
Text Label 2725 1200 2 50 ~ 0
Col6
Text Label 2725 4800 2 50 ~ 0
Row0
Text Label 2725 4700 2 50 ~ 0
Row1
Text Label 2725 4600 2 50 ~ 0
Row2
Text Label 2725 4500 2 50 ~ 0
Row3
Text Label 2725 2350 2 50 ~ 0
Row4
Text Label 2725 2250 2 50 ~ 0
Row5
Text Label 2725 2150 2 50 ~ 0
Row6
Text Label 2725 2050 2 50 ~ 0
Row7
$Sheet
S 775 900 1700 1900
U 5BC3EA0A
F0 "keys2" 60
F1 "keys2.sch" 60
F2 "Col0" I R 2475 1800 50
F3 "Col1" I R 2475 1700 50
F4 "Col2" I R 2475 1600 50
F5 "Col3" I R 2475 1500 50
F6 "Col4" I R 2475 1400 50
F7 "Col5" I R 2475 1300 50
F8 "Col6" I R 2475 1200 50
F9 "Col7" I R 2475 1100 50
F10 "Row4" I R 2475 2350 50
F11 "Row5" I R 2475 2250 50
F12 "Row6" I R 2475 2150 50
F13 "Row7" I R 2475 2050 50
$EndSheet
$Sheet
S 775 3400 1700 1900
U 5BC3E99D
F0 "keys1" 60
F1 "keys1.sch" 60
F2 "Col0" I R 2475 4300 50
F3 "Col1" I R 2475 4200 50
F4 "Col2" I R 2475 4100 50
F5 "Col3" I R 2475 4000 50
F6 "Col4" I R 2475 3900 50
F7 "Col5" I R 2475 3800 50
F8 "Col6" I R 2475 3700 50
F9 "Col7" I R 2475 3600 50
F10 "Row0" I R 2475 4800 50
F11 "Row1" I R 2475 4700 50
F12 "Row2" I R 2475 4600 50
F13 "Row3" I R 2475 4500 50
$EndSheet
Text Notes 580 7070 0 79 ~ 0
For OSI keyboards:\n“@“ (AT symbol) maps to “Shift Lock”, R0 C0\n“[“ (left bracket) maps to “Rub Out”, R6 C2\n“\” maps to “Repeat”, R0 C7\n“Rubout” maps to “Break”, \nDNP: “]” (right bracket), “^”, “Here is”, “Break”, “Repeat”, “Clear”
Text Notes 600 7905 0 79 ~ 0
For Apple II keyboards:\n"@" (AT symbol) maps to "Left arrow"\n"\" maps to "Right Arrow"\n"[" (left bracket) maps to "Reset"\n\nDNP: "]" (right bracket), "^", "Here is", "Rub", "Break", "Repeat", "Clear"
$Comp
L Switch:SW_Push_LED SW9
U 1 1 5DF7D21E
P 9250 2875
F 0 "SW9" V 9170 3115 50 0000 C CNN
F 1 "Caps_Lock" V 9000 2875 50 0000 C CNN
F 2 "unikbd:Key_MX_LED" H 9250 3175 50 0001 C CNN
F 3 "~" H 9250 3175 50 0001 C CNN
1 9250 2875
0 1 -1 0
$EndComp
$Comp
L Switch:SW_Push_LED SW32
U 1 1 5DF7DA75
P 9425 1850
F 0 "SW32" H 9150 2025 50 0000 C CNN
F 1 "@ (OSI shift lock)" H 9300 2125 50 0000 C CNN
F 2 "unikbd:Key_MX_LED" H 9425 2150 50 0001 C CNN
F 3 "~" H 9425 2150 50 0001 C CNN
1 9425 1850
-1 0 0 -1
$EndComp
NoConn ~ 7900 2850
NoConn ~ 7900 2950
NoConn ~ 7900 3050
NoConn ~ 7900 3150
$Comp
L Switch:SW_Push_LED SW61
U 1 1 5DF0C543
P 8730 1450
F 0 "SW61" H 8600 1660 50 0000 C CNN
F 1 "Power light" H 8760 1750 50 0000 C CNN
F 2 "unikbd:Key_MX_LED" H 8730 1750 50 0001 C CNN
F 3 "~" H 8730 1750 50 0001 C CNN
1 8730 1450
-1 0 0 -1
$EndComp
Wire Wire Line
8400 1450 8530 1450
Wire Wire Line
9000 1550 8400 1550
Wire Wire Line
9000 1450 9000 1550
Wire Wire Line
8930 1450 9000 1450
Wire Wire Line
8990 1350 8930 1350
Wire Wire Line
8990 1070 8990 1350
Wire Wire Line
8400 1070 8990 1070
Wire Wire Line
8400 1250 8400 1070
Wire Wire Line
8530 1350 8400 1350
NoConn ~ 8400 3150
NoConn ~ 8400 3050
NoConn ~ 8400 2950
NoConn ~ 8400 2850
NoConn ~ 8400 2750
NoConn ~ 8400 2650
$Comp
L Connector_Generic:Conn_02x20_Odd_Even J1
U 1 1 5D1E4169
P 8100 2150
F 0 "J1" H 8150 3267 50 0000 C CNN
F 1 "Controller" H 8150 3176 50 0000 C CNN
F 2 "Connector_PinHeader_2.54mm:PinHeader_2x20_P2.54mm_Vertical" H 8100 2150 50 0001 C CNN
F 3 "~" H 8100 2150 50 0001 C CNN
1 8100 2150
1 0 0 -1
$EndComp
Text Label 2725 1100 2 50 ~ 0
Col7
Text Label 7850 1250 2 50 ~ 0
Col7
Text Label 7850 1350 2 50 ~ 0
Col6
Text Label 7850 1550 2 50 ~ 0
Col4
Text Label 7850 1450 2 50 ~ 0
Col5
Text Label 7850 1750 2 50 ~ 0
Col2
Text Label 7850 1650 2 50 ~ 0
Col3
Text Label 7850 1850 2 50 ~ 0
Col1
Text Label 7850 1950 2 50 ~ 0
Col0
Text Label 7850 2050 2 50 ~ 0
Row7
Text Label 7850 2150 2 50 ~ 0
Row6
Text Label 7850 2250 2 50 ~ 0
Row5
Text Label 7850 2350 2 50 ~ 0
Row4
Text Label 7850 2450 2 50 ~ 0
Row3
Text Label 7850 2550 2 50 ~ 0
Row2
Text Label 7850 2650 2 50 ~ 0
Row1
Text Label 7850 2750 2 50 ~ 0
Row0
Entry Wire Line
2825 1800 2925 1700
Entry Wire Line
2825 1700 2925 1600
Entry Wire Line
2825 1600 2925 1500
Entry Wire Line
2825 1500 2925 1400
Entry Wire Line
2825 1400 2925 1300
Entry Wire Line
2825 1300 2925 1200
Entry Wire Line
2825 1200 2925 1100
Entry Wire Line
2825 1100 2925 1000
Entry Wire Line
2825 2350 2925 2250
Entry Wire Line
2825 2250 2925 2150
Entry Wire Line
2825 2150 2925 2050
Entry Wire Line
2825 2050 2925 1950
Entry Wire Line
2825 4300 2925 4200
Entry Wire Line
2825 4200 2925 4100
Entry Wire Line
2825 4100 2925 4000
Entry Wire Line
2825 4000 2925 3900
Entry Wire Line
2825 3900 2925 3800
Entry Wire Line
2825 3800 2925 3700
Entry Wire Line
2825 3700 2925 3600
Entry Wire Line
2825 3600 2925 3500
Entry Wire Line
2825 4800 2925 4700
Entry Wire Line
2825 4700 2925 4600
Entry Wire Line
2825 4600 2925 4500
Entry Wire Line
2825 4500 2925 4400
Entry Wire Line
7500 2750 7400 2650
Entry Wire Line
7500 2650 7400 2550
Entry Wire Line
7500 2550 7400 2450
Entry Wire Line
7500 2450 7400 2350
Entry Wire Line
7500 2350 7400 2250
Entry Wire Line
7500 2250 7400 2150
Entry Wire Line
7500 2150 7400 2050
Entry Wire Line
7500 2050 7400 1950
Entry Wire Line
7500 1950 7400 1850
Entry Wire Line
7500 1850 7400 1750
Entry Wire Line
7500 1750 7400 1650
Entry Wire Line
7500 1650 7400 1550
Entry Wire Line
7500 1550 7400 1450
Entry Wire Line
7500 1450 7400 1350
Entry Wire Line
7500 1350 7400 1250
Entry Wire Line
7500 1250 7400 1150
Wire Wire Line
7900 1250 7500 1250
Wire Wire Line
7500 1350 7900 1350
Wire Wire Line
7900 1450 7500 1450
Wire Wire Line
7900 1550 7500 1550
Wire Wire Line
7900 1650 7500 1650
Wire Wire Line
7500 1750 7900 1750
Wire Wire Line
7900 1850 7500 1850
Wire Wire Line
7500 1950 7900 1950
Wire Wire Line
7900 2050 7500 2050
Wire Wire Line
7500 2150 7900 2150
Wire Wire Line
7900 2250 7500 2250
Wire Wire Line
7500 2350 7900 2350
Wire Wire Line
7900 2450 7500 2450
Wire Wire Line
7500 2550 7900 2550
Wire Wire Line
7500 2650 7900 2650
Wire Wire Line
7500 2750 7900 2750
Wire Wire Line
2475 1100 2825 1100
Wire Wire Line
2825 1200 2475 1200
Wire Wire Line
2475 1300 2825 1300
Wire Wire Line
2825 1400 2475 1400
Wire Wire Line
2475 1500 2825 1500
Wire Wire Line
2825 1600 2475 1600
Wire Wire Line
2475 1700 2825 1700
Wire Wire Line
2825 1800 2475 1800
Wire Wire Line
2475 3600 2825 3600
Wire Wire Line
2825 3700 2475 3700
Wire Wire Line
2475 3800 2825 3800
Wire Wire Line
2825 3900 2475 3900
Wire Wire Line
2475 4000 2825 4000
Wire Wire Line
2825 4100 2475 4100
Wire Wire Line
2475 4200 2825 4200
Wire Wire Line
2825 4300 2475 4300
Wire Wire Line
2475 2050 2825 2050
Wire Wire Line
2825 2150 2475 2150
Wire Wire Line
2475 2250 2825 2250
Wire Wire Line
2825 2350 2475 2350
Wire Wire Line
2475 4500 2825 4500
Wire Wire Line
2825 4600 2475 4600
Wire Wire Line
2475 4700 2825 4700
Wire Wire Line
2825 4800 2475 4800
Wire Bus Line
2925 700 7400 700
Wire Wire Line
8400 2250 9250 2250
Wire Wire Line
9250 2250 9250 2675
Wire Wire Line
9250 3075 9100 3075
Wire Wire Line
9100 3075 9100 2350
Wire Wire Line
9100 2350 8400 2350
Entry Wire Line
10200 2670 10300 2570
Entry Wire Line
10200 3075 10300 2975
Wire Bus Line
10300 700 7400 700
Connection ~ 7400 700
Text Label 9850 2670 2 50 ~ 0
Row5
Text Label 9850 3075 2 50 ~ 0
Col2
$Comp
L Diode:1N4148 D?
U 1 1 5DFE048B
P 9550 2670
AR Path="/5BC3E99D/5DFE048B" Ref="D?" Part="1"
AR Path="/5BC3EA0A/5DFE048B" Ref="D?" Part="1"
AR Path="/5DFE048B" Ref="D10" Part="1"
F 0 "D10" H 9596 2591 50 0000 R CNN
F 1 "1N4148" H 9625 2770 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 9550 2495 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 9550 2670 50 0001 C CNN
1 9550 2670
-1 0 0 1
$EndComp
Wire Wire Line
10200 2670 9700 2670
Wire Wire Line
8400 2050 9700 2050
$Comp
L Switch:SW_Push SW?
U 1 1 5D6C3751
P 9900 2050
AR Path="/5BC3E99D/5D6C3751" Ref="SW?" Part="1"
AR Path="/5D6C3751" Ref="SW34" Part="1"
F 0 "SW34" H 9650 2100 50 0000 C CNN
F 1 "Rubout (OSI Break)" H 9770 2000 50 0000 C CNN
F 2 "unikbd:Key_MX" H 9900 2250 50 0001 C CNN
F 3 "" H 9900 2250 50 0001 C CNN
1 9900 2050
1 0 0 -1
$EndComp
Wire Wire Line
9225 1750 8400 1750
Wire Wire Line
9625 1750 9900 1750
Wire Wire Line
9900 1750 9900 1525
Wire Wire Line
9900 1525 9175 1525
Wire Wire Line
9175 1525 9175 1650
Wire Wire Line
9175 1650 8400 1650
Wire Wire Line
8400 1850 9225 1850
Wire Wire Line
9625 1850 9775 1850
Wire Wire Line
9775 1850 9775 1950
Wire Wire Line
9775 1950 8400 1950
Wire Wire Line
10100 2050 10150 2050
Wire Wire Line
10150 2050 10150 2150
Wire Wire Line
10150 2150 8400 2150
NoConn ~ 8400 2550
NoConn ~ 8400 2450
Text Notes 580 6180 0 79 ~ 0
For Classic ASCII keyboards:\n“@“ (AT symbol) is mapped to R7 C0\n“Rubout” is mapped to R1 C0\n“Power Button” is mapped to R0 C0\n
Wire Wire Line
9350 3075 10200 3075
Wire Wire Line
9400 2670 9350 2670
Wire Wire Line
9350 2670 9350 2675
Wire Bus Line
10300 700 10300 2975
Wire Bus Line
7400 700 7400 2650
Wire Bus Line
2925 700 2925 4700
$EndSCHEMATC

View File

@ -0,0 +1,866 @@
EESchema Schematic File Version 4
EELAYER 30 0
EELAYER END
$Descr A4 11693 8268
encoding utf-8
Sheet 3 3
Title "Universal Retro Keyboard"
Date "2019-08-25"
Rev "1.0"
Comp "OSIWeb.org"
Comment1 "Key Matrix part 2"
Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
Text HLabel 1450 4500 0 60 Input ~ 0
Row1
Text HLabel 1450 5400 0 60 Input ~ 0
Row2
Text HLabel 1450 6300 0 60 Input ~ 0
Row3
Text HLabel 1450 3600 0 60 Input ~ 0
Row0
Text HLabel 1450 1100 0 60 Input ~ 0
Col7
Text HLabel 1450 1300 0 60 Input ~ 0
Col6
Text HLabel 1450 1500 0 60 Input ~ 0
Col5
Text HLabel 1450 1700 0 60 Input ~ 0
Col4
Text HLabel 1450 1900 0 60 Input ~ 0
Col3
Text HLabel 1450 2100 0 60 Input ~ 0
Col2
Text HLabel 1450 2300 0 60 Input ~ 0
Col1
Text HLabel 1450 2500 0 60 Input ~ 0
Col0
$Comp
L Switch:SW_Push SW35
U 1 1 5BC3FD26
P 3800 3200
F 0 "SW35" H 3800 3485 50 0000 C CNN
F 1 "R_Shift" H 3800 3394 50 0000 C CNN
F 2 "unikbd:Key_MX" H 3800 3400 50 0001 C CNN
F 3 "" H 3800 3400 50 0001 C CNN
1 3800 3200
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW39
U 1 1 5BC3FE57
P 4600 3200
F 0 "SW39" H 4600 3485 50 0000 C CNN
F 1 "L_Shift" H 4600 3394 50 0000 C CNN
F 2 "unikbd:Key_MX" H 4600 3400 50 0001 C CNN
F 3 "" H 4600 3400 50 0001 C CNN
1 4600 3200
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW49
U 1 1 5BC3FF69
P 7000 3200
F 0 "SW49" H 7000 3485 50 0000 C CNN
F 1 "ESC" H 7000 3394 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7000 3400 50 0001 C CNN
F 3 "" H 7000 3400 50 0001 C CNN
1 7000 3200
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW57
U 1 1 5BC3FF70
P 8600 3200
F 0 "SW57" H 8600 3485 50 0000 C CNN
F 1 "Backslash" H 8600 3394 50 0000 C CNN
F 2 "unikbd:Key_MX" H 8600 3400 50 0001 C CNN
F 3 "" H 8600 3400 50 0001 C CNN
1 8600 3200
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW53
U 1 1 5BC3FF77
P 7800 3200
F 0 "SW53" H 7800 3485 50 0000 C CNN
F 1 "CTRL" H 7800 3394 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7800 3400 50 0001 C CNN
F 3 "" H 7800 3400 50 0001 C CNN
1 7800 3200
1 0 0 -1
$EndComp
$Comp
L Diode:1N4148 D36
U 1 1 5BC6C862
P 4000 3450
F 0 "D36" V 4046 3371 50 0000 R CNN
F 1 "1N4148" V 3955 3371 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4000 3275 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4000 3450 50 0001 C CNN
1 4000 3450
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D40
U 1 1 5BC6CA8E
P 4800 3450
F 0 "D40" V 4846 3371 50 0000 R CNN
F 1 "1N4148" V 4755 3371 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4800 3275 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4800 3450 50 0001 C CNN
1 4800 3450
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D50
U 1 1 5BC6CB1B
P 7200 3450
F 0 "D50" V 7246 3371 50 0000 R CNN
F 1 "1N4148" V 7155 3371 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 7200 3275 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 7200 3450 50 0001 C CNN
1 7200 3450
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D54
U 1 1 5BC6CB46
P 8000 3450
F 0 "D54" V 8046 3371 50 0000 R CNN
F 1 "1N4148" V 7955 3371 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8000 3275 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8000 3450 50 0001 C CNN
1 8000 3450
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D58
U 1 1 5BC6CB6F
P 8800 3450
F 0 "D58" V 8846 3371 50 0000 R CNN
F 1 "1N4148" V 8755 3371 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8800 3275 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8800 3450 50 0001 C CNN
1 8800 3450
0 -1 -1 0
$EndComp
$Comp
L Switch:SW_Push SW36
U 1 1 5BC6CD5D
P 3800 4100
F 0 "SW36" H 3800 4385 50 0000 C CNN
F 1 "P" H 3800 4294 50 0000 C CNN
F 2 "unikbd:Key_MX" H 3800 4300 50 0001 C CNN
F 3 "" H 3800 4300 50 0001 C CNN
1 3800 4100
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW43
U 1 1 5BC6CD64
P 5400 4100
F 0 "SW43" H 5400 4385 50 0000 C CNN
F 1 "Fwd_Slash" H 5400 4294 50 0000 C CNN
F 2 "unikbd:Key_MX" H 5400 4300 50 0001 C CNN
F 3 "" H 5400 4300 50 0001 C CNN
1 5400 4100
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW40
U 1 1 5BC6CD6B
P 4600 4100
F 0 "SW40" H 4600 4385 50 0000 C CNN
F 1 "Semicolon" H 4600 4294 50 0000 C CNN
F 2 "unikbd:Key_MX" H 4600 4300 50 0001 C CNN
F 3 "" H 4600 4300 50 0001 C CNN
1 4600 4100
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW46
U 1 1 5BC6CD72
P 6200 4100
F 0 "SW46" H 6200 4385 50 0000 C CNN
F 1 "SPACE" H 6200 4294 50 0000 C CNN
F 2 "unikbd:Key_MX" H 6200 4300 50 0001 C CNN
F 3 "" H 6200 4300 50 0001 C CNN
1 6200 4100
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW50
U 1 1 5BC6CD79
P 7000 4100
F 0 "SW50" H 7000 4385 50 0000 C CNN
F 1 "Z" H 7000 4294 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7000 4300 50 0001 C CNN
F 3 "" H 7000 4300 50 0001 C CNN
1 7000 4100
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW58
U 1 1 5BC6CD80
P 8600 4100
F 0 "SW58" H 8600 4385 50 0000 C CNN
F 1 "Q" H 8600 4294 50 0000 C CNN
F 2 "unikbd:Key_MX" H 8600 4300 50 0001 C CNN
F 3 "" H 8600 4300 50 0001 C CNN
1 8600 4100
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW54
U 1 1 5BC6CD87
P 7800 4100
F 0 "SW54" H 7800 4385 50 0000 C CNN
F 1 "A" H 7800 4294 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7800 4300 50 0001 C CNN
F 3 "" H 7800 4300 50 0001 C CNN
1 7800 4100
1 0 0 -1
$EndComp
$Comp
L Diode:1N4148 D37
U 1 1 5BC6CD8E
P 4000 4350
F 0 "D37" V 4046 4271 50 0000 R CNN
F 1 "1N4148" V 3955 4271 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4000 4175 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4000 4350 50 0001 C CNN
1 4000 4350
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D41
U 1 1 5BC6CD9C
P 4800 4350
F 0 "D41" V 4846 4271 50 0000 R CNN
F 1 "1N4148" V 4755 4271 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4800 4175 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4800 4350 50 0001 C CNN
1 4800 4350
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D44
U 1 1 5BC6CDA3
P 5600 4350
F 0 "D44" V 5646 4271 50 0000 R CNN
F 1 "1N4148" V 5555 4271 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 5600 4175 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 5600 4350 50 0001 C CNN
1 5600 4350
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D47
U 1 1 5BC6CDAA
P 6400 4350
F 0 "D47" V 6446 4271 50 0000 R CNN
F 1 "1N4148" V 6355 4271 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 6400 4175 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 6400 4350 50 0001 C CNN
1 6400 4350
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D51
U 1 1 5BC6CDB1
P 7200 4350
F 0 "D51" V 7246 4271 50 0000 R CNN
F 1 "1N4148" V 7155 4271 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 7200 4175 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 7200 4350 50 0001 C CNN
1 7200 4350
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D55
U 1 1 5BC6CDB8
P 8000 4350
F 0 "D55" V 8046 4271 50 0000 R CNN
F 1 "1N4148" V 7955 4271 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8000 4175 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8000 4350 50 0001 C CNN
1 8000 4350
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D59
U 1 1 5BC6CDBF
P 8800 4350
F 0 "D59" V 8846 4271 50 0000 R CNN
F 1 "1N4148" V 8755 4271 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8800 4175 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8800 4350 50 0001 C CNN
1 8800 4350
0 -1 -1 0
$EndComp
$Comp
L Switch:SW_Push SW33
U 1 1 5BC6CED6
P 3000 5000
F 0 "SW33" H 3000 5285 50 0000 C CNN
F 1 "Break" H 3000 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 3000 5200 50 0001 C CNN
F 3 "" H 3000 5200 50 0001 C CNN
1 3000 5000
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW37
U 1 1 5BC6CEDD
P 3800 5000
F 0 "SW37" H 3800 5285 50 0000 C CNN
F 1 "Comma" H 3800 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 3800 5200 50 0001 C CNN
F 3 "" H 3800 5200 50 0001 C CNN
1 3800 5000
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW44
U 1 1 5BC6CEE4
P 5400 5000
F 0 "SW44" H 5400 5285 50 0000 C CNN
F 1 "N" H 5400 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 5400 5200 50 0001 C CNN
F 3 "" H 5400 5200 50 0001 C CNN
1 5400 5000
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW41
U 1 1 5BC6CEEB
P 4600 5000
F 0 "SW41" H 4600 5285 50 0000 C CNN
F 1 "M" H 4600 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 4600 5200 50 0001 C CNN
F 3 "" H 4600 5200 50 0001 C CNN
1 4600 5000
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW47
U 1 1 5BC6CEF2
P 6200 5000
F 0 "SW47" H 6200 5285 50 0000 C CNN
F 1 "B" H 6200 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 6200 5200 50 0001 C CNN
F 3 "" H 6200 5200 50 0001 C CNN
1 6200 5000
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW51
U 1 1 5BC6CEF9
P 7000 5000
F 0 "SW51" H 7000 5285 50 0000 C CNN
F 1 "V" H 7000 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7000 5200 50 0001 C CNN
F 3 "" H 7000 5200 50 0001 C CNN
1 7000 5000
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW59
U 1 1 5BC6CF00
P 8600 5000
F 0 "SW59" H 8600 5285 50 0000 C CNN
F 1 "X" H 8600 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 8600 5200 50 0001 C CNN
F 3 "" H 8600 5200 50 0001 C CNN
1 8600 5000
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW55
U 1 1 5BC6CF07
P 7800 5000
F 0 "SW55" H 7800 5285 50 0000 C CNN
F 1 "C" H 7800 5194 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7800 5200 50 0001 C CNN
F 3 "" H 7800 5200 50 0001 C CNN
1 7800 5000
1 0 0 -1
$EndComp
$Comp
L Diode:1N4148 D38
U 1 1 5BC6CF0E
P 4000 5250
F 0 "D38" V 4046 5171 50 0000 R CNN
F 1 "1N4148" V 3955 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4000 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4000 5250 50 0001 C CNN
1 4000 5250
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D34
U 1 1 5BC6CF15
P 3200 5250
F 0 "D34" V 3246 5171 50 0000 R CNN
F 1 "1N4148" V 3155 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 3200 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 3200 5250 50 0001 C CNN
1 3200 5250
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D42
U 1 1 5BC6CF1C
P 4800 5250
F 0 "D42" V 4846 5171 50 0000 R CNN
F 1 "1N4148" V 4755 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4800 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4800 5250 50 0001 C CNN
1 4800 5250
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D45
U 1 1 5BC6CF23
P 5600 5250
F 0 "D45" V 5646 5171 50 0000 R CNN
F 1 "1N4148" V 5555 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 5600 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 5600 5250 50 0001 C CNN
1 5600 5250
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D48
U 1 1 5BC6CF2A
P 6400 5250
F 0 "D48" V 6446 5171 50 0000 R CNN
F 1 "1N4148" V 6355 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 6400 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 6400 5250 50 0001 C CNN
1 6400 5250
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D52
U 1 1 5BC6CF31
P 7200 5250
F 0 "D52" V 7246 5171 50 0000 R CNN
F 1 "1N4148" V 7155 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 7200 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 7200 5250 50 0001 C CNN
1 7200 5250
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D56
U 1 1 5BC6CF38
P 8000 5250
F 0 "D56" V 8046 5171 50 0000 R CNN
F 1 "1N4148" V 7955 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8000 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8000 5250 50 0001 C CNN
1 8000 5250
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D60
U 1 1 5BC6CF3F
P 8800 5250
F 0 "D60" V 8846 5171 50 0000 R CNN
F 1 "1N4148" V 8755 5171 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8800 5075 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8800 5250 50 0001 C CNN
1 8800 5250
0 -1 -1 0
$EndComp
$Comp
L Switch:SW_Push SW38
U 1 1 5BC6D0AD
P 3800 5900
F 0 "SW38" H 3800 6185 50 0000 C CNN
F 1 "K" H 3800 6094 50 0000 C CNN
F 2 "unikbd:Key_MX" H 3800 6100 50 0001 C CNN
F 3 "" H 3800 6100 50 0001 C CNN
1 3800 5900
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW45
U 1 1 5BC6D0B4
P 5400 5900
F 0 "SW45" H 5400 6185 50 0000 C CNN
F 1 "H" H 5400 6094 50 0000 C CNN
F 2 "unikbd:Key_MX" H 5400 6100 50 0001 C CNN
F 3 "" H 5400 6100 50 0001 C CNN
1 5400 5900
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW42
U 1 1 5BC6D0BB
P 4600 5900
F 0 "SW42" H 4600 6185 50 0000 C CNN
F 1 "J" H 4600 6094 50 0000 C CNN
F 2 "unikbd:Key_MX" H 4600 6100 50 0001 C CNN
F 3 "" H 4600 6100 50 0001 C CNN
1 4600 5900
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW48
U 1 1 5BC6D0C2
P 6200 5900
F 0 "SW48" H 6200 6185 50 0000 C CNN
F 1 "G" H 6200 6094 50 0000 C CNN
F 2 "unikbd:Key_MX" H 6200 6100 50 0001 C CNN
F 3 "" H 6200 6100 50 0001 C CNN
1 6200 5900
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW52
U 1 1 5BC6D0C9
P 7000 5900
F 0 "SW52" H 7000 6185 50 0000 C CNN
F 1 "F" H 7000 6094 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7000 6100 50 0001 C CNN
F 3 "" H 7000 6100 50 0001 C CNN
1 7000 5900
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW60
U 1 1 5BC6D0D0
P 8600 5900
F 0 "SW60" H 8600 6185 50 0000 C CNN
F 1 "S" H 8600 6094 50 0000 C CNN
F 2 "unikbd:Key_MX" H 8600 6100 50 0001 C CNN
F 3 "" H 8600 6100 50 0001 C CNN
1 8600 5900
1 0 0 -1
$EndComp
$Comp
L Switch:SW_Push SW56
U 1 1 5BC6D0D7
P 7800 5900
F 0 "SW56" H 7800 6185 50 0000 C CNN
F 1 "D" H 7800 6094 50 0000 C CNN
F 2 "unikbd:Key_MX" H 7800 6100 50 0001 C CNN
F 3 "" H 7800 6100 50 0001 C CNN
1 7800 5900
1 0 0 -1
$EndComp
$Comp
L Diode:1N4148 D39
U 1 1 5BC6D0DE
P 4000 6150
F 0 "D39" V 4046 6071 50 0000 R CNN
F 1 "1N4148" V 3955 6071 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4000 5975 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4000 6150 50 0001 C CNN
1 4000 6150
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D43
U 1 1 5BC6D0EC
P 4800 6150
F 0 "D43" V 4846 6071 50 0000 R CNN
F 1 "1N4148" V 4755 6071 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 4800 5975 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 4800 6150 50 0001 C CNN
1 4800 6150
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D46
U 1 1 5BC6D0F3
P 5600 6150
F 0 "D46" V 5646 6071 50 0000 R CNN
F 1 "1N4148" V 5555 6071 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 5600 5975 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 5600 6150 50 0001 C CNN
1 5600 6150
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D49
U 1 1 5BC6D0FA
P 6400 6150
F 0 "D49" V 6446 6071 50 0000 R CNN
F 1 "1N4148" V 6355 6071 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 6400 5975 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 6400 6150 50 0001 C CNN
1 6400 6150
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D53
U 1 1 5BC6D101
P 7200 6150
F 0 "D53" V 7246 6071 50 0000 R CNN
F 1 "1N4148" V 7155 6071 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 7200 5975 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 7200 6150 50 0001 C CNN
1 7200 6150
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D57
U 1 1 5BC6D108
P 8000 6150
F 0 "D57" V 8046 6071 50 0000 R CNN
F 1 "1N4148" V 7955 6071 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8000 5975 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8000 6150 50 0001 C CNN
1 8000 6150
0 -1 -1 0
$EndComp
$Comp
L Diode:1N4148 D61
U 1 1 5BC6D10F
P 8800 6150
F 0 "D61" V 8846 6071 50 0000 R CNN
F 1 "1N4148" V 8755 6071 50 0000 R CNN
F 2 "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal" H 8800 5975 50 0001 C CNN
F 3 "http://www.nxp.com/documents/data_sheet/1N4148_1N4448.pdf" H 8800 6150 50 0001 C CNN
1 8800 6150
0 -1 -1 0
$EndComp
Connection ~ 4000 3600
Wire Wire Line
4000 3600 4800 3600
Connection ~ 4800 3600
Connection ~ 7200 3600
Wire Wire Line
7200 3600 8000 3600
Connection ~ 8000 3600
Wire Wire Line
8000 3600 8800 3600
Connection ~ 4000 4500
Wire Wire Line
4000 4500 4800 4500
Connection ~ 4800 4500
Wire Wire Line
4800 4500 5600 4500
Connection ~ 5600 4500
Wire Wire Line
5600 4500 6400 4500
Connection ~ 6400 4500
Wire Wire Line
6400 4500 7200 4500
Connection ~ 7200 4500
Wire Wire Line
7200 4500 8000 4500
Connection ~ 8000 4500
Wire Wire Line
8000 4500 8800 4500
Wire Wire Line
3200 5400 4000 5400
Connection ~ 4000 5400
Wire Wire Line
4000 5400 4800 5400
Connection ~ 4800 5400
Wire Wire Line
4800 5400 5600 5400
Connection ~ 5600 5400
Wire Wire Line
5600 5400 6400 5400
Connection ~ 6400 5400
Wire Wire Line
6400 5400 7200 5400
Connection ~ 7200 5400
Wire Wire Line
7200 5400 8000 5400
Connection ~ 8000 5400
Wire Wire Line
8000 5400 8800 5400
Connection ~ 4000 6300
Wire Wire Line
4000 6300 4800 6300
Connection ~ 4800 6300
Wire Wire Line
4800 6300 5600 6300
Connection ~ 5600 6300
Wire Wire Line
5600 6300 6400 6300
Connection ~ 6400 6300
Wire Wire Line
6400 6300 7200 6300
Connection ~ 7200 6300
Wire Wire Line
7200 6300 8000 6300
Connection ~ 8000 6300
Wire Wire Line
8000 6300 8800 6300
Wire Wire Line
4000 5900 4000 6000
Wire Wire Line
4800 5900 4800 6000
Wire Wire Line
5600 5900 5600 6000
Wire Wire Line
6400 5900 6400 6000
Wire Wire Line
7200 5900 7200 6000
Wire Wire Line
8000 5900 8000 6000
Wire Wire Line
8800 6000 8800 5900
Wire Wire Line
8800 5000 8800 5100
Wire Wire Line
8000 5000 8000 5100
Wire Wire Line
7200 5000 7200 5100
Wire Wire Line
5600 5100 5600 5000
Wire Wire Line
6400 5100 6400 5000
Wire Wire Line
4800 5100 4800 5000
Wire Wire Line
4000 5100 4000 5000
Wire Wire Line
3200 5100 3200 5000
Wire Wire Line
4000 3200 4000 3300
Wire Wire Line
4000 4100 4000 4200
Wire Wire Line
4800 4100 4800 4200
Wire Wire Line
5600 4200 5600 4100
Wire Wire Line
6400 4200 6400 4100
Wire Wire Line
7200 4200 7200 4100
Wire Wire Line
8000 4200 8000 4100
Wire Wire Line
8800 4200 8800 4100
Wire Wire Line
4800 3300 4800 3200
Wire Wire Line
7200 3200 7200 3300
Wire Wire Line
8000 3200 8000 3300
Wire Wire Line
8800 3200 8800 3300
Wire Wire Line
1450 2500 2800 2500
Wire Wire Line
1450 2300 3600 2300
Wire Wire Line
3600 2300 3600 3200
Connection ~ 3600 3200
Wire Wire Line
3600 3200 3600 4100
Connection ~ 3600 4100
Wire Wire Line
3600 4100 3600 5000
Connection ~ 3600 5000
Wire Wire Line
3600 5000 3600 5900
Wire Wire Line
1450 2100 4400 2100
Wire Wire Line
4400 2100 4400 3200
Connection ~ 4400 3200
Wire Wire Line
4400 3200 4400 4100
Connection ~ 4400 4100
Wire Wire Line
4400 4100 4400 5000
Connection ~ 4400 5000
Wire Wire Line
4400 5000 4400 5900
Wire Wire Line
1450 1900 5200 1900
Connection ~ 5200 4100
Wire Wire Line
5200 4100 5200 5000
Connection ~ 5200 5000
Wire Wire Line
5200 5000 5200 5900
Wire Wire Line
1450 1700 6000 1700
Connection ~ 6000 4100
Wire Wire Line
6000 4100 6000 5000
Connection ~ 6000 5000
Wire Wire Line
6000 5000 6000 5900
Wire Wire Line
1450 1500 6800 1500
Wire Wire Line
6800 1500 6800 3200
Connection ~ 6800 3200
Wire Wire Line
6800 3200 6800 4100
Connection ~ 6800 4100
Wire Wire Line
6800 4100 6800 5000
Connection ~ 6800 5000
Wire Wire Line
6800 5000 6800 5900
Wire Wire Line
1450 1300 7600 1300
Wire Wire Line
7600 1300 7600 3200
Connection ~ 7600 3200
Wire Wire Line
7600 3200 7600 4100
Connection ~ 7600 4100
Wire Wire Line
7600 4100 7600 5000
Connection ~ 7600 5000
Wire Wire Line
7600 5000 7600 5900
Wire Wire Line
1450 1100 8400 1100
Wire Wire Line
8400 1100 8400 3200
Connection ~ 8400 3200
Wire Wire Line
8400 3200 8400 4100
Connection ~ 8400 4100
Wire Wire Line
8400 4100 8400 5000
Connection ~ 8400 5000
Wire Wire Line
8400 5000 8400 5900
Connection ~ 3200 5400
Text Notes 1100 7100 0 50 ~ 0
(Install either Row diodes or switch diodes. Jumper uninstalled diodes.
Text Label 2300 3600 0 50 ~ 0
Row0_keys
Text Label 2300 4500 0 50 ~ 0
Row1_keys
Text Label 2300 5400 0 50 ~ 0
Row2_keys
Wire Wire Line
5200 1900 5200 4100
Wire Wire Line
6000 1700 6000 4100
Wire Wire Line
4800 3600 7200 3600
Text Label 2300 6300 0 50 ~ 0
Row3_keys
Wire Wire Line
1450 4500 4000 4500
Wire Wire Line
1450 5400 3200 5400
Wire Wire Line
2800 2500 2800 5000
Wire Wire Line
1450 3600 4000 3600
Wire Wire Line
1450 6300 4000 6300
Text Notes 2960 4200 0 50 ~ 0
Rubout
$EndSCHEMATC

File diff suppressed because it is too large Load Diff