reorganization (large one) (mostly moving files)

partial-rewrite
Ben Blazak 2012-07-31 14:48:31 -07:00
parent f9b46c32bf
commit ddade5b5dc
47 changed files with 1166 additions and 1008 deletions

View File

@ -1,2 +0,0 @@
- make new branch and update for fredrick's new PCB (pre-prototype)

View File

@ -1,22 +0,0 @@
/* ----------------------------------------------------------------------------
* keyboard specific exports
*
* Different keyboards are included by modifying a variable in the makefile.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(keyboard/MAKEFILE_KEYBOARD.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc

View File

@ -1,5 +1,8 @@
/* ----------------------------------------------------------------------------
* ergoDOX: keyboard matrix specific code
* controller specific exports
*
* Files for different keyboards are used by modifying a variable in the
* Makefile
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,14 +10,7 @@
* ------------------------------------------------------------------------- */
#include "lib/data-types/common.h"
#include "matrix.h"
static bool _kb_is_pressed[KB_ROWS][KB_COLUMNS];
static bool _kb_was_pressed[KB_ROWS][KB_COLUMNS];
bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_is_pressed;
bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_was_pressed;
#include "src/lib/conditional-include.h"
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/controller.h )
#include INCLUDE

View File

@ -1,36 +0,0 @@
/* ----------------------------------------------------------------------------
* ergoDOX specific exports
* includes (for centralization) the public exports from all subfiles
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef ERGODOX_h
#define ERGODOX_h
#include "lib/data-types/common.h"
#include "ergodox/layout.h" // number of layers, layout
#include "ergodox/led.h" // logical led controls
#include "ergodox/matrix.h" // kb dimensions, matrix status
#include "ergodox/teensy-2-0.h" // LED controls
// note:
// - see your keyswitch specification for the necessary value. for
// cherry mx switches, the switch bounce time is speced to be <= 5ms.
// it looks like most switches are speced to be between 5 and 8 ms.
// - if timing is important, balance this value with the main() loop
// run time (~5ms, last i checked, nearly all of it in the i2c
// update() function)
#define KB_DEBOUNCE_TIME 5 // in ms
uint8_t kb_init(void);
uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]);
#endif

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX specific code: tying it all together
* ergoDOX : controller specific code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,12 +7,13 @@
* ------------------------------------------------------------------------- */
#include "lib/data-types/common.h"
#include "ergodox/matrix.h"
#include "ergodox/mcp23018--private.h"
#include "ergodox/teensy-2-0--private.h"
#include <stdbool.h>
#include <stdint.h>
#include "./matrix.h"
#include "./controller/mcp23018--functions.h"
#include "./controller/teensy-2-0--functions.h"
// ----------------------------------------------------------------------------
/* returns
* - success: 0

View File

@ -0,0 +1,27 @@
/* ----------------------------------------------------------------------------
* ergoDOX : controller specific exports
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef KEYBOARD__ERGODOX__CONTROLLER_h
#define KEYBOARD__ERGODOX__CONTROLLER_h
#include <stdbool.h>
#include <stdint.h>
#include "./matrix.h"
// --------------------------------------------------------------------
#include "./controller/teensy-2-0--led.h"
// --------------------------------------------------------------------
uint8_t kb_init(void);
uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]);
#endif

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX controller: MCP23018 specific exports : private
* ergoDOX : controller : MCP23018 specific exports : functions
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,14 +7,19 @@
* ------------------------------------------------------------------------- */
#ifndef MCP23018_h_PRIVATE
#define MCP23018_h_PRIVATE
#ifndef KEYBOARD__ERGODOX__CONTROLLER__MCP23018__FUNCTIONS_h
#define KEYBOARD__ERGODOX__CONTROLLER__MCP23018__FUNCTIONS_h
#include "lib/data-types/common.h"
#include "matrix.h"
#include <stdbool.h>
#include <stdint.h>
#include "../matrix.h"
// --------------------------------------------------------------------
#define MCP23018_TWI_ADDRESS 0b0100000
// --------------------------------------------------------------------
uint8_t mcp23018_init(void);
uint8_t mcp23018_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX controller: MCP23018 specific code
* ergoDOX : controller: MCP23018 specific code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,13 +7,14 @@
* ------------------------------------------------------------------------- */
#include <stdbool.h>
#include <stdint.h>
#include <util/twi.h>
#include "lib/data-types/common.h"
#include "lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
#include "matrix.h"
#include "mcp23018--private.h"
#include "src/lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
#include "../matrix.h"
#include "./mcp23018--functions.h"
// ----------------------------------------------------------------------------
// register addresses (see "mcp23018.md")
#define IODIRA 0x00 // i/o direction register
@ -29,6 +30,7 @@
#define TWI_ADDR_WRITE ( (MCP23018_TWI_ADDRESS<<1) | TW_WRITE )
#define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
// ----------------------------------------------------------------------------
/* returns:
* - success: 0

View File

@ -0,0 +1,23 @@
/* ----------------------------------------------------------------------------
* ergoDOX : controller : Teensy 2.0 specific exports : functions
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__FUNCTIONS_h
#define KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__FUNCTIONS_h
#include <stdbool.h>
#include <stdint.h>
#include "../matrix.h"
// --------------------------------------------------------------------
uint8_t teensy_init(void);
uint8_t teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
#endif

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX controller: Teensy 2.0 specific exports
* ergoDOX : controller : Teensy 2.0 specific exports : LED control
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,48 +7,52 @@
* ------------------------------------------------------------------------- */
#ifndef TEENSY_2_0_h
#define TEENSY_2_0_h
#ifndef KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__LED_h
#define KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__LED_h
#include <stdint.h>
#include <avr/io.h> // for the register macros
#include "lib/data-types/common.h"
// --------------------------------------------------------------------
// LED control
#define _kb_led_1_on() (DDRB |= (1<<5))
#define _kb_led_1_off() (DDRB &= ~(1<<5))
#define _kb_led_1_set(n) (OCR1A = (uint8_t)(n))
#define _kb_led_1_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
//
#define _kb_led_2_on() (DDRB |= (1<<6))
#define _kb_led_2_off() (DDRB &= ~(1<<6))
#define _kb_led_2_set(n) (OCR1B = (uint8_t)(n))
#define _kb_led_2_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
//
#define _kb_led_3_on() (DDRB |= (1<<7))
#define _kb_led_3_off() (DDRB &= ~(1<<7))
#define _kb_led_3_set(n) (OCR1C = (uint8_t)(n))
#define _kb_led_3_set_percent(n) (OCR1C = (uint8_t)((n) * 0xFF))
// ---
#define _kb_led_all_on() do { \
_kb_led_1_on(); \
_kb_led_2_on(); \
_kb_led_3_on(); \
} while(0)
#define _kb_led_all_off() do { \
_kb_led_1_off(); \
_kb_led_2_off(); \
_kb_led_3_off(); \
_kb_led_1_off(); \
_kb_led_2_off(); \
_kb_led_3_off(); \
} while(0)
#define _kb_led_all_set(n) do { \
_kb_led_1_set(n); \
_kb_led_2_set(n); \
_kb_led_3_set(n); \
_kb_led_1_set(n); \
_kb_led_2_set(n); \
_kb_led_3_set(n); \
} while(0)
#define _kb_led_all_set_percent(n) do { \
_kb_led_1_set_percent(n); \
_kb_led_2_set_percent(n); \
_kb_led_3_set_percent(n); \
_kb_led_1_set_percent(n); \
_kb_led_2_set_percent(n); \
_kb_led_3_set_percent(n); \
} while(0)
#endif

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX controller: Teensy 2.0 specific code
* ergoDOX : controller: Teensy 2.0 specific code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,16 +7,19 @@
* ------------------------------------------------------------------------- */
// for "lib/twi.h"
#define TWI_FREQ 400000
#include <stdbool.h>
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include "lib/data-types/common.h"
#define TWI_FREQ 400000
#include "lib/twi.h"
#include "matrix.h"
#include "teensy-2-0.h"
#include "teensy-2-0--private.h"
#include "src/lib/twi.h"
#include "../matrix.h"
#include "./teensy-2-0--functions.h"
#include "./teensy-2-0--led.h"
// ----------------------------------------------------------------------------
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
@ -39,47 +42,48 @@
* - note: if you change pin assignments, please be sure to update
* "teensy-2-0.md", and the '.svg' circuit diagram.
*/
// --- helpers
#define _teensypin_write(register, operation, pin_letter, pin_number) \
((register##pin_letter) operation (1<<(pin_number)))
#define teensypin_write(register, operation, pin) do { \
_teensypin_write(register, operation, pin); \
_delay_us(1); /* allow pins time to stabalize */ \
_delay_us(1); /* allow pins time to stabilize */ \
} while(0)
#define _teensypin_write(register, operation, pin_letter, pin_number) \
((register##pin_letter) operation (1<<(pin_number)))
#define teensypin_read(pin) \
_teensypin_read(pin)
#define _teensypin_read(pin_letter, pin_number) \
#define _teensypin_read(pin_letter, pin_number) \
((PIN##pin_letter) & (1<<(pin_number)))
#define teensypin_read(pin) \
_teensypin_read(pin)
#define teensypin_write_all_unused(register, operation) \
do { \
teensypin_write(register, operation, UNUSED_0); \
teensypin_write(register, operation, UNUSED_1); \
teensypin_write(register, operation, UNUSED_2); \
teensypin_write(register, operation, UNUSED_3); \
teensypin_write(register, operation, UNUSED_4); } \
#define teensypin_write_all_unused(register, operation) \
do { \
teensypin_write(register, operation, UNUSED_0); \
teensypin_write(register, operation, UNUSED_1); \
teensypin_write(register, operation, UNUSED_2); \
teensypin_write(register, operation, UNUSED_3); \
teensypin_write(register, operation, UNUSED_4); } \
while(0)
#define teensypin_write_all_row(register, operation) \
do { \
teensypin_write(register, operation, ROW_0); \
teensypin_write(register, operation, ROW_1); \
teensypin_write(register, operation, ROW_2); \
teensypin_write(register, operation, ROW_3); \
teensypin_write(register, operation, ROW_4); \
teensypin_write(register, operation, ROW_5); } \
#define teensypin_write_all_row(register, operation) \
do { \
teensypin_write(register, operation, ROW_0); \
teensypin_write(register, operation, ROW_1); \
teensypin_write(register, operation, ROW_2); \
teensypin_write(register, operation, ROW_3); \
teensypin_write(register, operation, ROW_4); \
teensypin_write(register, operation, ROW_5); } \
while(0)
#define teensypin_write_all_column(register, operation) \
do { \
teensypin_write(register, operation, COLUMN_0); \
teensypin_write(register, operation, COLUMN_1); \
teensypin_write(register, operation, COLUMN_2); \
teensypin_write(register, operation, COLUMN_3); \
teensypin_write(register, operation, COLUMN_4); \
teensypin_write(register, operation, COLUMN_5); \
teensypin_write(register, operation, COLUMN_6); } \
#define teensypin_write_all_column(register, operation) \
do { \
teensypin_write(register, operation, COLUMN_0); \
teensypin_write(register, operation, COLUMN_1); \
teensypin_write(register, operation, COLUMN_2); \
teensypin_write(register, operation, COLUMN_3); \
teensypin_write(register, operation, COLUMN_4); \
teensypin_write(register, operation, COLUMN_5); \
teensypin_write(register, operation, COLUMN_6); } \
while(0)
#define SET |=
@ -109,12 +113,17 @@
#define COLUMN_5 D, 3
#define COLUMN_6 C, 6
// ----------------------------------------------------------------------------
/* returns
* - success: 0
*/
uint8_t teensy_init(void) {
CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile
// CPU speed : should match F_CPU in makefile
#if F_CPU != 16000000
#error "Expecting different CPU frequency"
#endif
CPU_PRESCALE(CPU_16MHz);
// onboard LED
// (tied to GND for hardware convenience)

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout : exports
* ergoDOX : layout exports
*
* Different layouts are included by modifying a variable in the makefile.
* ----------------------------------------------------------------------------
@ -8,121 +8,16 @@
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef LAYOUT_h
#define LAYOUT_h
#include <avr/pgmspace.h>
#include "lib/data-types/common.h"
#include "lib/key-functions.h" // for `kbfun_funptr_t`
#ifndef KEYBOARD__ERGODOX__LAYOUT_h
#define KEYBOARD__ERGODOX__LAYOUT_h
#include "matrix.h" // for number of rows and columns
// --------------------------------------------------------------------
// include the appropriate keyboard layout header
// for:
// - possible non-default number of layers
// - possible non-default layout matrix definitions
// - possible non-default layout 'get' and 'set' definitions
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(layout/MAKEFILE_KEYBOARD_LAYOUT.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc
// default number of layers
#ifndef KB_LAYERS
#define KB_LAYERS 10
#endif
// default layout 'get' macros and `extern` matrix declarations
//
// these are for when the matrices are stored solely in Flash. layouts
// may redefine them if they wish and use RAM, EEPROM, or any
// combination of the three, as long as they maintain the same
// interface.
//
// - if the macro is overridden, the matrix declaration must be too,
// and vice versa.
//
// - 'set' functions are optional, and should be defined in the layout
// specific '.h'. they'll require the use of the EEPROM, possibly in
// clever conjunction with one of the other two memories (since the
// EEPROM is small). custom key functions will also need to be
// written.
//
// - to override these macros with real functions, set the macro equal
// to itself (e.g. `#define kb_layout_get kb_layout_get`) and provide
// function prototypes in the layout specific '.h'
#ifndef kb_layout_get
extern uint8_t PROGMEM \
_kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_get(layer,row,column) \
( (uint8_t) \
pgm_read_byte(&( \
_kb_layout[layer][row][column] )) )
#endif
#ifndef kb_layout_press_get
extern kbfun_funptr_t PROGMEM \
_kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_press_get(layer,row,column) \
( (kbfun_funptr_t) \
pgm_read_word(&( \
_kb_layout_press[layer][row][column] )) )
#endif
#ifndef kb_layout_release_get
extern kbfun_funptr_t PROGMEM \
_kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_release_get(layer,row,column) \
( (kbfun_funptr_t) \
pgm_read_word(&( \
_kb_layout_release[layer][row][column] )) )
#endif
// default logical LED macros (all defined to nothing)
#ifndef kb_led_num_on
#define kb_led_num_on()
#endif
#ifndef kb_led_num_off
#define kb_led_num_off()
#endif
#ifndef kb_led_caps_on
#define kb_led_caps_on()
#endif
#ifndef kb_led_caps_off
#define kb_led_caps_off()
#endif
#ifndef kb_led_scroll_on
#define kb_led_scroll_on()
#endif
#ifndef kb_led_scroll_off
#define kb_led_scroll_off()
#endif
#ifndef kb_led_compose_on
#define kb_led_compose_on()
#endif
#ifndef kb_led_compose_off
#define kb_led_compose_off()
#endif
#ifndef kb_led_kana_on
#define kb_led_kana_on()
#endif
#ifndef kb_led_kana_off
#define kb_led_kana_off()
#endif
#include "src/lib/conditional-include.h"
#define INCLUDE EXP_STR( ./layout/MAKEFILE_KEYBOARD_LAYOUT.h )
#include INCLUDE
#endif

View File

@ -3,33 +3,22 @@
Different layouts are included by modifying a variable in the makefile.
To write a new one:
* You must implement everything defined in [layout.h] (layout.h). Take a look
at existing layouts in the 'layout' subdir.
* Currently, see [qwerty.c] (layout/qwerty.c) and [qwerty.h]
(layout/qwerty.h). The latter is only important if you want more than
one layer. And I still need to write the functions to make that possible
(though that shouldn't be hard, I just haven't gotten to it yet). But
(at least for the QWERTY and Dvorak layouts I'd really like to include)
if you indicate it clealy in the layout, and provide complete
initializations for `kb_layout[][][]`, `kb_layout_press[][][]`, and
`kb_layout_release[][][]`, I'll make sure it gets working.
* The number of layers must be defined in the layout *.h file.
* Create new layout files under [layout] (layout) (see [qwerty.h]
(layout/qwerty.h) and [qwerty.c] (layout/qwerty.c)).
* Use `0` for no-operation (unused) keys, and `NULL` for no-operation (unused)
functions.
* See [matrix.md] (matrix.md) for how the key matrix maps to hardware.
* See [matrix/mapping.h] (matrix/mapping.h) for how the key matrix maps to
hardware.
* See [keyboard-usage-page--short-names.h]
(../../lib/_usb/keyboard-usage-page--short-names.h) for available keycodes.
* See [key-functions.c] (../../lib/_key-functions.c) for what functions keys
* See [key-functions.c] (../../lib/key-functions.c) for what functions keys
can call.
* See [_defaults.h] (layout/_defaults.h) for default function layers and
aliases.
## notes
* Each full layer takes 420 bytes of memory, wherever it's stored. (The matrix
size is 12x7, keycodes are 1 byte each, and function pointers are 2 bytes
each.)
* Each full layer takes 420 bytes of memory (the matrix size is 12x7, keycodes
are 1 byte each, and function pointers are 2 bytes each).
-------------------------------------------------------------------------------

View File

@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------------
* ergoDOX : layout : default LED control
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef KEYBOARD__ERGODOX__LAYOUT__DEFAULT__LED_CONTROL_h
#define KEYBOARD__ERGODOX__LAYOUT__DEFAULT__LED_CONTROL_h
// --------------------------------------------------------------------
/*
* state and delay macros
*/
#ifndef kb_led_state_power_on
#define kb_led_state_power_on() do { \
_kb_led_all_set_percent(0.05); \
_kb_led_all_on(); \
} while(0)
#endif
// note: need to delay for a total of ~1 second
#ifndef kb_led_delay_usb_init
#define kb_led_delay_usb_init() do { \
_kb_led_1_set_percent(0.5); \
_delay_ms(333); \
_kb_led_2_set_percent(0.5); \
_delay_ms(333); \
_kb_led_3_set_percent(0.5); \
_delay_ms(333); \
} while(0)
#endif
#ifndef kb_led_state_ready
#define kb_led_state_ready() do { \
_kb_led_all_off(); \
_kb_led_all_set_percent(0.5); \
} while(0)
#endif
/*
* logical LED macros
* - unused macros should be defined to nothing
* - they all are here, because they really need to be specified in
* the layout specific file
*/
#ifndef kb_led_num_on
#define kb_led_num_on()
#endif
#ifndef kb_led_num_off
#define kb_led_num_off()
#endif
#ifndef kb_led_caps_on
#define kb_led_caps_on()
#endif
#ifndef kb_led_caps_off
#define kb_led_caps_off()
#endif
#ifndef kb_led_scroll_on
#define kb_led_scroll_on()
#endif
#ifndef kb_led_scroll_off
#define kb_led_scroll_off()
#endif
#ifndef kb_led_compose_on
#define kb_led_compose_on()
#endif
#ifndef kb_led_compose_off
#define kb_led_compose_off()
#endif
#ifndef kb_led_kana_on
#define kb_led_kana_on()
#endif
#ifndef kb_led_kana_off
#define kb_led_kana_off()
#endif
#endif

View File

@ -0,0 +1,80 @@
/* ----------------------------------------------------------------------------
* ergoDOX : layout : default matrix control
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef KEYBOARD__ERGODOX__LAYOUT__DEFAULT__MATRIX_CONTROL_h
#define KEYBOARD__ERGODOX__LAYOUT__DEFAULT__MATRIX_CONTROL_h
#include <stdint.h>
#include <avr/pgmspace.h>
#include "src/lib/key-functions/public.h"
#include "../matrix.h"
// --------------------------------------------------------------------
#ifndef KB_LAYERS
#define KB_LAYERS 10
#endif
// --------------------------------------------------------------------
/*
* matrix 'get' macros, and `extern` matrix declarations
*
* These are written for when the matrices are stored solely in Flash.
* Layouts may redefine them if they wish and use Flash, RAM, EEPROM,
* or any combination of the three, as long as they maintain the same
* interface.
*
* - If the macro is overridden, the matrix declaration must be too,
* and vice versa.
*
* - 'set' functions are optional, and should be defined in the layout
* specific '.h'. They'll require the use of the EEPROM, possibly in
* clever conjunction with one of the other two memories (since the
* EEPROM is small). Custom key functions will also need to be
* written.
*
* - To override these macros with real functions, set the macro equal
* to itself (e.g. `#define kb_layout_get kb_layout_get`) and provide
* function prototypes, in the layout specific '.h'
*/
#ifndef kb_layout_get
extern uint8_t PROGMEM \
_kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_get(layer,row,column) \
( (uint8_t) \
pgm_read_byte(&( \
_kb_layout[layer][row][column] )) )
#endif
#ifndef kb_layout_press_get
extern kbfun_funptr_t PROGMEM \
_kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_press_get(layer,row,column) \
( (kbfun_funptr_t) \
pgm_read_word(&( \
_kb_layout_press[layer][row][column] )) )
#endif
#ifndef kb_layout_release_get
extern kbfun_funptr_t PROGMEM \
_kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_release_get(layer,row,column) \
( (kbfun_funptr_t) \
pgm_read_word(&( \
_kb_layout_release[layer][row][column] )) )
#endif
#endif

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout : QWERTY
*
* This is an overly basic implementation. It needs to be replaced.
* TODO: This is a temporary version. It will be replaced later.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -9,33 +9,40 @@
* ------------------------------------------------------------------------- */
#include <stdint.h>
#include <stddef.h>
#include <avr/pgmspace.h>
#include "lib/data-types/common.h"
#include "lib/usb/usage-page/keyboard--short-names.h"
#include "lib/key-functions.h"
#include "src/lib/usb/usage-page/keyboard--short-names.h"
#include "src/lib/key-functions/public.h"
#include "../matrix.h"
#include "../layout.h"
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// aliases
// --- basic
#define f_prrel &kbfun_press_release
#define f_toggl &kbfun_toggle
#define f_l_inc &kbfun_layer_inc
#define f_l_dec &kbfun_layer_dec
#define f_l_iex &kbfun_layer_inc_exec
#define f_l_dex &kbfun_layer_dec_exec
#define f_2kcap &kbfun_2_keys_capslock_press_release
// --- device
#define f_btldr &kbfun_jump_to_bootloader
// --- numpad
#define f_np_to &kbfun_layermask_numpad_toggle
#define f_np_on &kbfun_layermask_numpad_on
#define f_np_of &kbfun_layermask_numpad_off
#define f_btldr &kbfun_jump_to_bootloader
// --- special
#define f_l_iex &kbfun_layer_inc_exec
#define f_l_dex &kbfun_layer_dec_exec
#define f_2kcap &kbfun_2_keys_capslock_press_release
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 0: default
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // layout: layer 0: default
// unused
0,
// left hand
@ -56,8 +63,8 @@ _bracketL, _Q, _W, _E, _R, _T, _esc,
0, _space,
_ctrlR, 0, _enter,
_altR, _pageU, _pageD ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 1: function and symbol keys
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // layout: layer 1: function and symbol keys
// unused
0,
// left hand
@ -78,8 +85,8 @@ _ctrlR, 0, _enter,
0, _space,
_ctrlR, 0, _enter,
_altR, _pageU, _pageD ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 2: numpad
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // layout: layer 2: numpad
// unused
0,
// left hand
@ -92,7 +99,6 @@ _ctrlR, 0, _enter,
0, 0, 0,
0, 0, 0,
// right hand
//------- ------- ------- ------- ------- ------- -------
0, 0, _7_kp, _8_kp, _9_kp, _div_kp, 0,
0, 0, _4_kp, _5_kp, _6_kp, _mul_kp, 0,
0, _1_kp, _2_kp, _3_kp, _sub_kp, 0,
@ -101,13 +107,14 @@ _ctrlR, 0, _enter,
0, 0,
0, 0, 0,
0, 0, 0 )
// ----------------------------------------------------------------------------
// --------------------------------------------------------------------
};
// ----------------------------------------------------------------------------
kbfun_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 0: default
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // press: layer 0: default
// unused
NULL,
// left hand
@ -128,8 +135,8 @@ f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
NULL,f_prrel,
f_prrel, NULL,f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 1: function and symbol keys
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // press: layer 1: function and symbol keys
// unused
NULL,
// left hand
@ -150,8 +157,8 @@ f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
NULL,f_prrel,
f_prrel, NULL,f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 2: numpad
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // press: layer 2: numpad
// unused
NULL,
// left hand
@ -172,13 +179,14 @@ NULL,
NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL )
// ----------------------------------------------------------------------------
// --------------------------------------------------------------------
};
// ----------------------------------------------------------------------------
kbfun_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 0: default
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // release: layer 0: default
// unused
NULL,
// left hand
@ -199,8 +207,8 @@ f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
NULL,f_prrel,
f_prrel, NULL,f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 1: function and symbol keys
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // release: layer 1: function and symbol keys
// unused
NULL,
// left hand
@ -221,8 +229,8 @@ f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
NULL,f_prrel,
f_prrel, NULL,f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 2: numpad
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // release: layer 2: numpad
// unused
NULL,
// left hand
@ -243,9 +251,10 @@ NULL,
NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 3: nothing (just making sure unused functions
// don't get compiled out)
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // release: layer 3: nothing (just making sure unused
// functions don't get compiled
// out)
// unused
NULL,
// other
@ -259,6 +268,6 @@ f_2kcap, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
f_np_to, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
f_np_on, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
f_np_of, NULL, NULL, NULL, NULL, NULL, NULL, NULL )
// ----------------------------------------------------------------------------
// --------------------------------------------------------------------
};

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout : QWERTY : exports
* ergoDOX : layout : QWERTY : exports
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,11 +7,12 @@
* ------------------------------------------------------------------------- */
#ifndef LAYOUT_QWERTY_h
#define LAYOUT_QWERTY_h
#ifndef KEYBOARD__ERGODOX__LAYOUT__QWERTY_h
#define KEYBOARD__ERGODOX__LAYOUT__QWERTY_h
#include "../led.h"
#include "../controller.h"
// --------------------------------------------------------------------
#define kb_led_num_on() _kb_led_1_on()
#define kb_led_num_off() _kb_led_1_off()
@ -20,5 +21,10 @@
#define kb_led_scroll_on() _kb_led_3_on()
#define kb_led_scroll_off() _kb_led_3_off()
// --------------------------------------------------------------------
#include "./default--led-control.h"
#include "./default--matrix-control.h"
#endif

View File

@ -1,46 +0,0 @@
/* ----------------------------------------------------------------------------
* led stuff that isn't microprocessor or layout specific
*
* you should also include this file for low-level led macros, as it will
* always include the file(s) containing those
*
* - low level LED macros (that have to be shared, but aren't really public)
* should all start with '_kb_led_'
* - public LED macros should start with 'kb_led_'
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef LED_h
#define LED_h
#include <util/delay.h>
#include "teensy-2-0.h" // for low-level led macros
#define kb_led_state_power_on() do { \
_kb_led_all_set_percent(0.05); \
_kb_led_all_on(); \
} while(0)
// note: need to delay for a total of ~1 second
#define kb_led_delay_usb_init() do { \
_kb_led_1_set_percent(0.5); \
_delay_ms(333); \
_kb_led_2_set_percent(0.5); \
_delay_ms(333); \
_kb_led_3_set_percent(0.5); \
_delay_ms(333); \
} while(0)
#define kb_led_state_ready() do { \
_kb_led_all_off(); \
_kb_led_all_set_percent(0.5); \
} while(0)
#endif

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX: keyboard matrix specific exports
* ergoDOX : matrix specific exports
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,17 +7,15 @@
* ------------------------------------------------------------------------- */
#ifndef MATRIX_h
#define MATRIX_h
#ifndef KEYBOARD__ERGODOX__MATRIX_h
#define KEYBOARD__ERGODOX__MATRIX_h
#include "lib/data-types/common.h"
// --------------------------------------------------------------------
#define KB_ROWS 12 // must match real life
#define KB_COLUMNS 7 // must match real life
extern bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS];
extern bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS];
// --------------------------------------------------------------------
/* mapping from spatial position to matrix position
* - spatial position: where the key is spatially, relative to other
@ -42,7 +40,7 @@
* right hand : cols 0..6, rows 0..5
* --------------------------------------------------------------------
*/
#define MATRIX_LAYER( \
#define KB_MATRIX_LAYER( \
/* for unused positions */ \
na, \
\
@ -81,7 +79,7 @@
{ kB0,kB1,kB2,kB3,kB4,kB5,kB6 } }
#define MATRIX_LAYER_SET_ALL(na, kxx) \
#define KB_MATRIX_LAYER_SET_ALL(na, kxx) \
LAYER( \
na, \
\
@ -103,6 +101,5 @@
kxx,kxx,kxx, \
kxx,kxx,kxx ) \
#endif

16
src/keyboard/layout.h Normal file
View File

@ -0,0 +1,16 @@
/* ----------------------------------------------------------------------------
* layout specific exports
*
* Files for different keyboards are used by modifying a variable in the
* Makefile
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include "src/lib/conditional-include.h"
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/layout.h )
#include INCLUDE

16
src/keyboard/matrix.h Normal file
View File

@ -0,0 +1,16 @@
/* ----------------------------------------------------------------------------
* matrix specific exports
*
* Files for different keyboards are used by modifying a variable in the
* Makefile
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include "src/lib/conditional-include.h"
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/matrix.h )
#include INCLUDE

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* Common data types
* Macros to help with conditional includes
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,12 +7,7 @@
* ------------------------------------------------------------------------- */
#ifndef DATA_TYPES_COMMON_h
#define DATA_TYPES_COMMON_h
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#endif
#undef INCLUDE
#define STR(s) #s // stringify
#define EXP_STR(s) STR(s) // expand -> stringify

View File

@ -7,11 +7,12 @@
* ------------------------------------------------------------------------- */
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "lib/data-types/common.h"
#include "linked-list.h"
#include "./linked-list.h"
// ----------------------------------------------------------------------------
// local macros (undefined later)
#define _NEW_POINTER(type, name) type * name = (type *) malloc(sizeof(type))
@ -19,6 +20,7 @@
#define _node_t linked_list_node_t
#define _data_t LINKED_LIST_DATA_TYPE
// ----------------------------------------------------------------------------
/*
* new()
@ -225,6 +227,7 @@ void linked_list_free(_list_t * list) {
free(list);
}
// ----------------------------------------------------------------------------
// local macros (undefined here)
#undef _NEW_POINTER

View File

@ -10,14 +10,16 @@
#ifndef DATA_TYPES_LINKED_LIST_h
#define DATA_TYPES_LINKED_LIST_h
#include "lib/data-types/common.h"
#include <stdint.h>
// --------------------------------------------------------------------
// default data type for the list
#ifndef LINKED_LIST_DATA_TYPE
#define LINKED_LIST_DATA_TYPE uint8_t
#endif
// --------------------------------------------------------------------
// structs
struct linked_list_node {
@ -26,7 +28,7 @@
};
struct linked_list {
uint8_t length; // 'uint8_t' to save ram
uint8_t length; // 'uint8_t' to save memory
struct linked_list_node * head;
struct linked_list_node * tail;
};

View File

@ -10,13 +10,14 @@
#ifndef DATA_TYPES_LIST_h
#define DATA_TYPES_LIST_h
// for "linked-list.h"
#ifdef LIST_DATA_TYPE
#define LINKED_LIST_DATA_TYPE LIST_DATA_TYPE
#endif
#include "linked-list.h"
typedef linked_list_t * list_t;
typedef linked_list_node_t * list_node_t;
#include "./linked-list.h"
// --------------------------------------------------------------------
#define list_new linked_list_new
#define list_insert linked_list_insert
@ -25,5 +26,10 @@
#define list_copy linked_list_copy
#define list_free linked_list_free
// --------------------------------------------------------------------
typedef linked_list_t * list_t;
typedef linked_list_node_t * list_node_t;
#endif

View File

@ -10,13 +10,14 @@
#ifndef DATA_TYPES_QUEUE_h
#define DATA_TYPES_QUEUE_h
// for "linked-list.h"
#ifdef QUEUE_DATA_TYPE
#define LINKED_LIST_DATA_TYPE QUEUE_DATA_TYPE
#endif
#include "linked-list.h"
typedef linked_list_t * queue_t;
typedef linked_list_node_t * queue_node_t;
#include "./linked-list.h"
// --------------------------------------------------------------------
#define queue_new linked_list_new
#define queue_append(list, data) linked_list_insert(list, -1, data)
@ -25,5 +26,10 @@
#define queue_copy linked_list_copy
#define queue_free linked_list_free
// --------------------------------------------------------------------
typedef linked_list_t * queue_t;
typedef linked_list_node_t * queue_node_t;
#endif

View File

@ -10,13 +10,14 @@
#ifndef DATA_TYPES_STACK_h
#define DATA_TYPES_STACK_h
// for "linked-list.h"
#ifdef STACK_DATA_TYPE
#define LINKED_LIST_DATA_TYPE STACK_DATA_TYPE
#endif
#include "linked-list.h"
typedef linked_list_t * stack_t;
typedef linked_list_node_t * stack_node_t;
#include "./linked-list.h"
// --------------------------------------------------------------------
#define stack_new linked_list_new
#define stack_push(list, data) linked_list_insert(list, 0, data)
@ -25,5 +26,10 @@
#define stack_copy linked_list_copy
#define stack_free linked_list_free
// --------------------------------------------------------------------
typedef linked_list_t * stack_t;
typedef linked_list_node_t * stack_node_t;
#endif

View File

@ -1,510 +0,0 @@
/* ----------------------------------------------------------------------------
* key functions: code
*
* These functions may do.. pretty much anything rational that thay like. If
* they want keycodes to be sent to the host in an aggrate report, they're
* responsible for modifying the appropriate report variables.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include <avr/interrupt.h>
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "lib/data-types/common.h"
#include "lib/usb/usage-page/keyboard.h"
#include "keyboard.h"
#include "key-functions.h"
#include "key-functions--private.h"
// ----------------------------------------------------------------------------
// public functions (not for keys)
// ----------------------------------------------------------------------------
/*
* Exec key
* - Execute the keypress or keyrelease function (if it exists) of the key at
* the current possition. Pass the keycode at the current position, and pass
* all other arguments as received
*/
void _kbfun_exec_key( KBFUN_FUNCTION_ARGS ) {
kbfun_funptr_t key_function =
( (pressed_)
? kb_layout_press_get(layer_, *row_, *col_)
: kb_layout_release_get(layer_, *row_, *col_) );
if (key_function)
(*key_function)(
pressed_,
kb_layout_get(layer_, *row_, *col_),
layer_,
row_,
col_,
current_layer_,
current_layers_,
pressed_layers_ );
}
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
/*
* Generate a normal keypress or keyrelease
*
* Arguments
* - keycode: the keycode to use
* - pressed: whether to generate a keypress (true) or keyrelease (false)
*
* Note
* - Because of the way USB does things, what this actually does is either add
* or remove 'keycode' from the list of currently pressed keys, to be sent at
* the end of the current cycle (see main.c)
*/
void _press_release(bool pressed, uint8_t keycode) {
// no-op
if (keycode == 0)
return;
// modifier keys
switch (keycode) {
case KEY_LeftControl: (pressed)
? (keyboard_modifier_keys |= (1<<0))
: (keyboard_modifier_keys &= ~(1<<0));
return;
case KEY_LeftShift: (pressed)
? (keyboard_modifier_keys |= (1<<1))
: (keyboard_modifier_keys &= ~(1<<1));
return;
case KEY_LeftAlt: (pressed)
? (keyboard_modifier_keys |= (1<<2))
: (keyboard_modifier_keys &= ~(1<<2));
return;
case KEY_LeftGUI: (pressed)
? (keyboard_modifier_keys |= (1<<3))
: (keyboard_modifier_keys &= ~(1<<3));
return;
case KEY_RightControl: (pressed)
? (keyboard_modifier_keys |= (1<<4))
: (keyboard_modifier_keys &= ~(1<<4));
return;
case KEY_RightShift: (pressed)
? (keyboard_modifier_keys |= (1<<5))
: (keyboard_modifier_keys &= ~(1<<5));
return;
case KEY_RightAlt: (pressed)
? (keyboard_modifier_keys |= (1<<6))
: (keyboard_modifier_keys &= ~(1<<6));
return;
case KEY_RightGUI: (pressed)
? (keyboard_modifier_keys |= (1<<7))
: (keyboard_modifier_keys &= ~(1<<7));
return;
}
// all others
for (uint8_t i=0; i<6; i++) {
if (pressed) {
if (keyboard_keys[i] == 0) {
keyboard_keys[i] = keycode;
return;
}
} else {
if (keyboard_keys[i] == keycode) {
keyboard_keys[i] = 0;
return;
}
}
}
}
/*
* Set current layer
* - Sets any keys currently set to the overall current layer to the new layer,
* and then sets the overall current layer
*
* Arguments
* - layer: the new layer value
* - current_layer: (a pointer to) the overall current layer (see main.c)
* - current_layers: (a pointer to a matrix of) the current layer for each key
* (see main.c and lib/key-functions.h)
*
* Note
* - Leaving all non-current layer values alone allows changing layers while
* maintaining a possibly enabled layer mask (as might be used to implement
* firmware enabled numlock)
*/
void _layer_set_current(
uint8_t layer,
uint8_t * current_layer,
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
return;
for (uint8_t row=0; row<KB_ROWS; row++)
for (uint8_t col=0; col<KB_COLUMNS; col++)
// if a key is set to a non-current layer, leave it
if ((*current_layers)[row][col] == *current_layer)
(*current_layers)[row][col] = layer;
(*current_layer) = layer;
}
/*
* Set layer mask
* - Sets the specified key positions to the specified layer
*/
void _layer_set_mask(
uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS],
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
return;
for (uint8_t row=0; row<KB_ROWS; row++)
for (uint8_t col=0; col<KB_COLUMNS; col++)
if (positions[row][col])
(*current_layers)[row][col] = layer;
}
/*
* Is the given keycode pressed?
*/
bool _is_pressed(uint8_t keycode) {
// modifier keys
switch (keycode) {
case KEY_LeftControl: if (keyboard_modifier_keys & (1<<0))
return true;
case KEY_LeftShift: if (keyboard_modifier_keys & (1<<1))
return true;
case KEY_LeftAlt: if (keyboard_modifier_keys & (1<<2))
return true;
case KEY_LeftGUI: if (keyboard_modifier_keys & (1<<3))
return true;
case KEY_RightControl: if (keyboard_modifier_keys & (1<<4))
return true;
case KEY_RightShift: if (keyboard_modifier_keys & (1<<5))
return true;
case KEY_RightAlt: if (keyboard_modifier_keys & (1<<6))
return true;
case KEY_RightGUI: if (keyboard_modifier_keys & (1<<7))
return true;
}
// all others
for (uint8_t i=0; i<6; i++)
if (keyboard_keys[i] == keycode)
return true;
return false;
}
// ----------------------------------------------------------------------------
// public functions
// ----------------------------------------------------------------------------
/*
* Press|Release
* - Generate a normal keypress or keyrelease
*/
void kbfun_press_release( KBFUN_FUNCTION_ARGS ) {
_press_release(pressed_, keycode_);
}
/*
* Toggle
* - Toggle the key pressed or unpressed
*/
void kbfun_toggle( KBFUN_FUNCTION_ARGS ) {
if (_is_pressed(keycode_))
_press_release(false, keycode_);
else
_press_release(true, keycode_);
}
/*
* Increase layer
* - Increment the current layer by the value specified in the keymap (for all
* non-masked keys)
*/
void kbfun_layer_inc( KBFUN_FUNCTION_ARGS ) {
_layer_set_current(
(*current_layer_) + keycode_,
current_layer_,
current_layers_ );
}
/*
* Decrease layer
* - Decrement the current layer by the value specified in the keymap (for all
* non-masked keys)
*/
void kbfun_layer_dec( KBFUN_FUNCTION_ARGS ) {
_layer_set_current(
(*current_layer_) - keycode_,
current_layer_,
current_layers_ );
}
/*
* Increase layer, Execute key
* - Increment the current layer by the value specified in the keymap (for all
* non-masked keys), and execute (usually press|release) the key in the same
* position on that new layer
*
* Note
* - Meant to be paired with `kbfun_layer_dec_exec()`
*/
void kbfun_layer_inc_exec( KBFUN_FUNCTION_ARGS ) {
// switch layers
_layer_set_current(
(*current_layer_) + keycode_,
current_layer_,
current_layers_ );
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// between the press and release
_kbfun_exec_key(
pressed_, 0, layer_+keycode_,
row_, col_, current_layer_,
current_layers_, pressed_layers_ );
}
/*
* Decrease layer, Execute key
* - Decrement the current layer by the value specified in the keymap (for all
* non-masked keys), and execute (usually press|release) the key in the same
* position on that new layer
*
* Note
* - Meant to be paired with `kbfun_layer_inc_exec()`
*/
void kbfun_layer_dec_exec( KBFUN_FUNCTION_ARGS ) {
// switch layers
_layer_set_current(
(*current_layer_) - keycode_,
current_layer_,
current_layers_ );
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// between the press and release
_kbfun_exec_key(
pressed_, 0, layer_+keycode_,
row_, col_, current_layer_,
current_layers_, pressed_layers_ );
}
/*
* Two keys => capslock
* - When assigned to two keys (e.g. the physical left and right shift keys)
* (in both the press and release matrices), pressing and holding down one of
* the keys will make the second key toggle capslock
*
* Note
* - If either of the shifts are pressed when the second key is pressed, they
* wil be released so that capslock will register properly when pressed.
* Capslock will then be pressed and released, and the original state of the
* shifts will be restored
*/
void kbfun_2_keys_capslock_press_release( KBFUN_FUNCTION_ARGS ) {
static uint8_t keys_pressed;
static bool lshift_pressed;
static bool rshift_pressed;
if (!pressed_) keys_pressed--;
// take care of the key that was actually pressed
_press_release(pressed_, keycode_);
// take care of capslock (only on the press of the 2nd key)
if (keys_pressed == 1 && pressed_) {
// save the state of left and right shift
lshift_pressed = _is_pressed(KEY_LeftShift);
rshift_pressed = _is_pressed(KEY_RightShift);
// disable both
_press_release(false, KEY_LeftShift);
_press_release(false, KEY_RightShift);
// press capslock, then release it
_press_release(true, KEY_CapsLock);
usb_keyboard_send();
_press_release(false, KEY_CapsLock);
usb_keyboard_send();
// restore the state of left and right shift
if (lshift_pressed)
_press_release(true, KEY_LeftShift);
if (rshift_pressed)
_press_release(true, KEY_RightShift);
}
if (pressed_) keys_pressed++;
}
// TODO: maybe the numpad functions (and other logical sets of functions?) need
// to be in (a) seaparate file(s).
/* ----------------------------------------------------------------------------
* Numpad functions
* - Functions to implement an embedded numpad
*
* Notes
* - The numpad is toggled by shifting (without changing the overall current
* layer) the layer of the keys specified in this function to the value
* specified in the keymap
* - When the numpad is toggled, the numlock is set to on (for active) or off
* (for inactive) as well
* - All these functions cooperate, but if more than one layer mask of this
* type is used (by a different set of functions) at the same time, the
* second will override the first, and any keys covered by both will be reset
* to the overall current layer when either is released (even if the other is
* still pressed)
* ------------------------------------------------------------------------- */
// prefix function (undefined later)
// - to keep these names reasonable in this block, and obviously not global
// outside it
// - 'L' is for 'local'
#define L(name) _kbfun_layermask_numpad__##name
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// vars
static bool L(numpad_activated) = false;
static bool L(layer_mask)[KB_ROWS][KB_COLUMNS] =
MATRIX_LAYER(
// unused
0,
// left hand
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0,
0, 0, 0,
0, 0, 0,
// right hand
0, 0, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 0,
0, 0, 0,
0, 0, 0 );
// functions
static inline void L(toggle_numlock)(void) {
_press_release(true, KEYPAD_NumLock_Clear);
usb_keyboard_send();
_press_release(false, KEYPAD_NumLock_Clear);
usb_keyboard_send();
}
static void L(toggle_numpad)(
uint8_t numpad_layer,
uint8_t current_layer,
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
if (L(numpad_activated)) {
// deactivate numpad
_layer_set_mask(current_layer, L(layer_mask), current_layers);
L(numpad_activated) = false;
// if: numlock on
if (keyboard_leds & (1<<0))
L(toggle_numlock)();
} else {
// activate numpad
_layer_set_mask(numpad_layer, L(layer_mask), current_layers);
L(numpad_activated) = true;
// if: numlock off
if (!(keyboard_leds & (1<<0)))
L(toggle_numlock)();
}
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/*
* Numpad toggle
* - Toggles the numpad and sets numlock on (for active) or off (for inactive)
* with it, if it's not already in that state
*/
void kbfun_layermask_numpad_toggle( KBFUN_FUNCTION_ARGS ) {
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
}
/*
* Numpad on
* - Set the numpad on (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_on( KBFUN_FUNCTION_ARGS ) {
if (!L(numpad_activated))
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
}
/*
* Numpad off
* - Set the numpad off (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_off( KBFUN_FUNCTION_ARGS ) {
if (L(numpad_activated))
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// prefix function (undefined here)
#undef L
/* ----------------------------------------------------------------------------
* ------------------------------------------------------------------------- */
// ----------------------------------------------------------------------------
// public functions (device specific)
// ----------------------------------------------------------------------------
void kbfun_jump_to_bootloader( KBFUN_FUNCTION_ARGS ) {
// from PJRC (slightly modified)
// <http://www.pjrc.com/teensy/jump_to_bootloader.html>
#if MAKEFILE_BOARD == teensy-2-0
// --- for all Teensy boards
cli();
// disable watchdog, if enabled
// disable all peripherals
UDCON = 1;
USBCON = (1<<FRZCLK); // disable USB
UCSR1B = 0;
_delay_ms(5);
// --- Teensy 2.0 specific
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0x7E00");
#endif
// else, function does nothing
}

View File

@ -1,64 +0,0 @@
/* ----------------------------------------------------------------------------
* key functions: exports
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef KEY_FUNCTIONS_h
#define KEY_FUNCTIONS_h
#include "lib/data-types/common.h"
// --------------------------------------------------------------------
// include the appropriate 'matrix.h'
// -------
// we're not simply including 'keyboard.h' here because this header is
// meant to be included by 'keyboard/layout/*.c', which is indirectly
// included by 'keyboard.h'; and that would lead to a circular include,
// which gcc might (depending on the order of include statements it
// encounters) deal with by processing this file before 'matrix.h',
// which would give us undefined macros here
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(keyboard/MAKEFILE_KEYBOARD/matrix.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc
// --------------------------------------------------------------------
#define KBFUN_FUNCTION_ARGS \
bool pressed_, \
uint8_t keycode_, \
uint8_t layer_, \
uint8_t * row_, \
uint8_t * col_, \
uint8_t * current_layer_, \
uint8_t (*current_layers_)[KB_ROWS][KB_COLUMNS], \
uint8_t (*pressed_layers_)[KB_ROWS][KB_COLUMNS]
typedef void (*kbfun_funptr_t)( KBFUN_FUNCTION_ARGS );
void _kbfun_exec_key ( KBFUN_FUNCTION_ARGS );
void kbfun_press_release (KBFUN_FUNCTION_ARGS);
void kbfun_toggle (KBFUN_FUNCTION_ARGS);
void kbfun_layer_inc (KBFUN_FUNCTION_ARGS);
void kbfun_layer_dec (KBFUN_FUNCTION_ARGS);
void kbfun_layer_inc_exec (KBFUN_FUNCTION_ARGS);
void kbfun_layer_dec_exec (KBFUN_FUNCTION_ARGS);
void kbfun_2_keys_capslock_press_release (KBFUN_FUNCTION_ARGS);
void kbfun_layermask_numpad_toggle (KBFUN_FUNCTION_ARGS);
void kbfun_layermask_numpad_on (KBFUN_FUNCTION_ARGS);
void kbfun_layermask_numpad_off (KBFUN_FUNCTION_ARGS);
void kbfun_jump_to_bootloader (KBFUN_FUNCTION_ARGS);
#endif

View File

@ -0,0 +1,173 @@
/* ----------------------------------------------------------------------------
* key functions : private : code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include <stdbool.h>
#include <stdint.h>
#include "src/lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "src/lib/usb/usage-page/keyboard.h"
#include "src/keyboard/layout.h"
#include "src/keyboard/matrix.h"
#include "./public.h"
// ----------------------------------------------------------------------------
/*
* Generate a normal keypress or keyrelease
*
* Arguments
* - keycode: the keycode to use
* - pressed: whether to generate a keypress (true) or keyrelease (false)
*
* Note
* - Because of the way USB does things, what this actually does is either add
* or remove 'keycode' from the list of currently pressed keys, to be sent at
* the end of the current cycle (see main.c)
*/
void _kbfun_press_release(bool pressed, uint8_t keycode) {
// no-op
if (keycode == 0)
return;
// modifier keys
switch (keycode) {
case KEY_LeftControl: (pressed)
? (keyboard_modifier_keys |= (1<<0))
: (keyboard_modifier_keys &= ~(1<<0));
return;
case KEY_LeftShift: (pressed)
? (keyboard_modifier_keys |= (1<<1))
: (keyboard_modifier_keys &= ~(1<<1));
return;
case KEY_LeftAlt: (pressed)
? (keyboard_modifier_keys |= (1<<2))
: (keyboard_modifier_keys &= ~(1<<2));
return;
case KEY_LeftGUI: (pressed)
? (keyboard_modifier_keys |= (1<<3))
: (keyboard_modifier_keys &= ~(1<<3));
return;
case KEY_RightControl: (pressed)
? (keyboard_modifier_keys |= (1<<4))
: (keyboard_modifier_keys &= ~(1<<4));
return;
case KEY_RightShift: (pressed)
? (keyboard_modifier_keys |= (1<<5))
: (keyboard_modifier_keys &= ~(1<<5));
return;
case KEY_RightAlt: (pressed)
? (keyboard_modifier_keys |= (1<<6))
: (keyboard_modifier_keys &= ~(1<<6));
return;
case KEY_RightGUI: (pressed)
? (keyboard_modifier_keys |= (1<<7))
: (keyboard_modifier_keys &= ~(1<<7));
return;
}
// all others
for (uint8_t i=0; i<6; i++) {
if (pressed) {
if (keyboard_keys[i] == 0) {
keyboard_keys[i] = keycode;
return;
}
} else {
if (keyboard_keys[i] == keycode) {
keyboard_keys[i] = 0;
return;
}
}
}
}
/*
* Set current layer
* - Sets any keys currently set to the overall current layer to the new layer,
* and then sets the overall current layer
*
* Arguments
* - layer: the new layer value
* - current_layer: (a pointer to) the overall current layer (see main.c)
* - current_layers: (a pointer to a matrix of) the current layer for each key
* (see main.c and lib/key-functions.h)
*
* Note
* - Leaving all non-current layer values alone allows changing layers while
* maintaining a possibly enabled layer mask (as might be used to implement
* firmware enabled numlock)
*/
void _kbfun_layer_set_current(
uint8_t layer,
uint8_t * current_layer,
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
return;
for (uint8_t row=0; row<KB_ROWS; row++)
for (uint8_t col=0; col<KB_COLUMNS; col++)
// if a key is set to a non-current layer, leave it
if ((*current_layers)[row][col] == *current_layer)
(*current_layers)[row][col] = layer;
(*current_layer) = layer;
}
/*
* Set layer mask
* - Sets the specified key positions to the specified layer
*/
void _kbfun_layer_set_mask(
uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS],
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
return;
for (uint8_t row=0; row<KB_ROWS; row++)
for (uint8_t col=0; col<KB_COLUMNS; col++)
if (positions[row][col])
(*current_layers)[row][col] = layer;
}
/*
* Is the given keycode pressed?
*/
bool _kbfun_is_pressed(uint8_t keycode) {
// modifier keys
switch (keycode) {
case KEY_LeftControl: if (keyboard_modifier_keys & (1<<0))
return true;
case KEY_LeftShift: if (keyboard_modifier_keys & (1<<1))
return true;
case KEY_LeftAlt: if (keyboard_modifier_keys & (1<<2))
return true;
case KEY_LeftGUI: if (keyboard_modifier_keys & (1<<3))
return true;
case KEY_RightControl: if (keyboard_modifier_keys & (1<<4))
return true;
case KEY_RightShift: if (keyboard_modifier_keys & (1<<5))
return true;
case KEY_RightAlt: if (keyboard_modifier_keys & (1<<6))
return true;
case KEY_RightGUI: if (keyboard_modifier_keys & (1<<7))
return true;
}
// all others
for (uint8_t i=0; i<6; i++)
if (keyboard_keys[i] == keycode)
return true;
return false;
}

View File

@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* key functions: private
* key functions : private : exports
*
* Things to be used only by keyfunctions. Exported any layouts would like to
* use these functions to help define their own.
* Things to be used only by keyfunctions. Exported so layouts can use these
* functions to help define their own, if they like.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -10,19 +10,23 @@
* ------------------------------------------------------------------------- */
#ifndef KEY_FUNCTIONS_h_PRIVATE
#define KEY_FUNCTIONS_h_PRIVATE
#ifndef LIB__KEY_FUNCTIONS__INTERNAL_h
#define LIB__KEY_FUNCTIONS__INTERNAL_h
void _press_release(bool pressed, uint8_t keycode);
void _layer_set_current(
#include "./public.h"
// --------------------------------------------------------------------
void _kbfun_press_release(bool pressed, uint8_t keycode);
void _kbfun_layer_set_current(
uint8_t value,
uint8_t * current_layer,
uint8_t (*current_layers_)[KB_ROWS][KB_COLUMNS] );
void _layer_set_mask(
void _kbfun_layer_set_mask(
uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS],
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] );
bool _is_pressed(uint8_t keycode);
bool _kbfun_is_pressed(uint8_t keycode);
#endif

View File

@ -0,0 +1,55 @@
/* ----------------------------------------------------------------------------
* key functions : public exports
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef LIB__KEY_FUNCTIONS__COMMON_h
#define LIB__KEY_FUNCTIONS__COMMON_h
#include <stdbool.h>
#include <stdint.h>
#include "src/keyboard/matrix.h"
// --------------------------------------------------------------------
#define KBFUN_FUNCTION_ARGS \
bool pressed_, \
uint8_t keycode_, \
uint8_t layer_, \
uint8_t * row_, \
uint8_t * col_, \
uint8_t * current_layer_, \
uint8_t (*current_layers_)[KB_ROWS][KB_COLUMNS], \
uint8_t (*pressed_layers_)[KB_ROWS][KB_COLUMNS]
// --------------------------------------------------------------------
typedef void (*kbfun_funptr_t)( KBFUN_FUNCTION_ARGS );
// --------------------------------------------------------------------
// basic
void kbfun_press_release ( KBFUN_FUNCTION_ARGS );
void kbfun_toggle ( KBFUN_FUNCTION_ARGS );
void kbfun_layer_inc ( KBFUN_FUNCTION_ARGS );
void kbfun_layer_dec ( KBFUN_FUNCTION_ARGS );
// device
void kbfun_jump_to_bootloader ( KBFUN_FUNCTION_ARGS );
// numpad
void kbfun_layermask_numpad_toggle ( KBFUN_FUNCTION_ARGS );
void kbfun_layermask_numpad_on ( KBFUN_FUNCTION_ARGS );
void kbfun_layermask_numpad_off ( KBFUN_FUNCTION_ARGS );
// special
void kbfun_layer_inc_exec ( KBFUN_FUNCTION_ARGS );
void kbfun_layer_dec_exec ( KBFUN_FUNCTION_ARGS );
void kbfun_2_keys_capslock_press_release ( KBFUN_FUNCTION_ARGS );
#endif

View File

@ -0,0 +1,57 @@
/* ----------------------------------------------------------------------------
* key functions : basic : code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include "../public.h"
#include "../private.h"
// ----------------------------------------------------------------------------
/*
* Press|Release
* - Generate a normal keypress or keyrelease
*/
void kbfun_press_release( KBFUN_FUNCTION_ARGS ) {
_kbfun_press_release(pressed_, keycode_);
}
/*
* Toggle
* - Toggle the key pressed or unpressed
*/
void kbfun_toggle( KBFUN_FUNCTION_ARGS ) {
if (_kbfun_is_pressed(keycode_))
_kbfun_press_release(false, keycode_);
else
_kbfun_press_release(true, keycode_);
}
/*
* Increase layer
* - Increment the current layer by the value specified in the keymap (for all
* non-masked keys)
*/
void kbfun_layer_inc( KBFUN_FUNCTION_ARGS ) {
_kbfun_layer_set_current(
(*current_layer_) + keycode_,
current_layer_,
current_layers_ );
}
/*
* Decrease layer
* - Decrement the current layer by the value specified in the keymap (for all
* non-masked keys)
*/
void kbfun_layer_dec( KBFUN_FUNCTION_ARGS ) {
_kbfun_layer_set_current(
(*current_layer_) - keycode_,
current_layer_,
current_layers_ );
}

View File

@ -0,0 +1,52 @@
/* ----------------------------------------------------------------------------
* key functions : device specific : code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include <avr/interrupt.h>
#include <util/delay.h>
#include "../public.h"
// ----------------------------------------------------------------------------
#if MAKEFILE_BOARD == teensy-2-0
// ----------------------------------------------------------------------------
// from PJRC (slightly modified)
// <http://www.pjrc.com/teensy/jump_to_bootloader.html>
void kbfun_jump_to_bootloader( KBFUN_FUNCTION_ARGS ) {
// --- for all Teensy boards ---
cli();
// disable watchdog, if enabled
// disable all peripherals
UDCON = 1;
USBCON = (1<<FRZCLK); // disable USB
UCSR1B = 0;
_delay_ms(5);
// --- Teensy 2.0 specific ---
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0x7E00");
}
// ----------------------------------------------------------------------------
#else
// ----------------------------------------------------------------------------
void kbfun_jump_to_bootloader( KBFUN_FUNCTION_ARGS ) {}
// ----------------------------------------------------------------------------
#endif
// ----------------------------------------------------------------------------

View File

@ -0,0 +1,134 @@
/* ----------------------------------------------------------------------------
* key functions : numpad : code
*
* Numpad functions
* - Functions to implement an embedded numpad
*
* Notes
* - The numpad is toggled by shifting (without changing the overall current
* layer) the layer of the keys specified in this function to the value
* specified in the keymap
* - When the numpad is toggled, the numlock is set to on (for active) or off
* (for inactive) as well
* - All these functions cooperate, but if more than one layer mask of this
* type is used (by a different set of functions) at the same time, the
* second will override the first, and any keys covered by both will be reset
* to the overall current layer when either is released (even if the other is
* still pressed)
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include <stdbool.h>
#include <stdint.h>
#include "src/lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "src/lib/usb/usage-page/keyboard.h"
#include "src/keyboard/matrix.h"
#include "../public.h"
#include "../private.h"
// ----------------------------------------------------------------------------
// vars
// ----------------------------------------------------------------------------
static bool _numpad_activated = false;
static bool _layer_mask[KB_ROWS][KB_COLUMNS] =
KB_MATRIX_LAYER(
// unused
0,
// left hand
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0,
0, 0, 0,
0, 0, 0,
// right hand
0, 0, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 0,
0, 0, 0,
0, 0, 0 );
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
static inline void _toggle_numlock(void) {
_kbfun_press_release(true, KEYPAD_NumLock_Clear);
usb_keyboard_send();
_kbfun_press_release(false, KEYPAD_NumLock_Clear);
usb_keyboard_send();
}
static void _toggle_numpad(
uint8_t numpad_layer,
uint8_t current_layer,
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
if (_numpad_activated) {
// deactivate numpad
_kbfun_layer_set_mask(
current_layer, _layer_mask, current_layers );
_numpad_activated = false;
// if: numlock on
if (keyboard_leds & (1<<0))
_toggle_numlock();
} else {
// activate numpad
_kbfun_layer_set_mask(
numpad_layer, _layer_mask, current_layers );
_numpad_activated = true;
// if: numlock off
if (!(keyboard_leds & (1<<0)))
_toggle_numlock();
}
}
// ----------------------------------------------------------------------------
// public functions
// ----------------------------------------------------------------------------
/*
* Numpad toggle
* - Toggles the numpad and sets numlock on (for active) or off (for inactive)
* with it, if it's not already in that state
*/
void kbfun_layermask_numpad_toggle( KBFUN_FUNCTION_ARGS ) {
_toggle_numpad(keycode_, *current_layer_, current_layers_);
}
/*
* Numpad on
* - Set the numpad on (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_on( KBFUN_FUNCTION_ARGS ) {
if (!_numpad_activated)
_toggle_numpad(keycode_, *current_layer_, current_layers_);
}
/*
* Numpad off
* - Set the numpad off (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_off( KBFUN_FUNCTION_ARGS ) {
if (_numpad_activated)
_toggle_numpad(keycode_, *current_layer_, current_layers_);
}

View File

@ -0,0 +1,118 @@
/* ----------------------------------------------------------------------------
* key functions : special : code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include <stdbool.h>
#include <stdint.h>
#include "src/lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "src/lib/usb/usage-page/keyboard.h"
#include "src/main.h"
#include "../public.h"
#include "../private.h"
// ----------------------------------------------------------------------------
/*
* Increase layer, Execute key
* - Increment the current layer by the value specified in the keymap (for all
* non-masked keys), and execute (usually press|release) the key in the same
* position on that new layer
*
* Note
* - Meant to be paired with `kbfun_layer_dec_exec()`
*/
void kbfun_layer_inc_exec( KBFUN_FUNCTION_ARGS ) {
// switch layers
_kbfun_layer_set_current(
(*current_layer_) + keycode_,
current_layer_,
current_layers_ );
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// between the press and release
main_exec_key(
pressed_, 0, layer_+keycode_,
row_, col_, current_layer_,
current_layers_, pressed_layers_ );
}
/*
* Decrease layer, Execute key
* - Decrement the current layer by the value specified in the keymap (for all
* non-masked keys), and execute (usually press|release) the key in the same
* position on that new layer
*
* Note
* - Meant to be paired with `kbfun_layer_inc_exec()`
*/
void kbfun_layer_dec_exec( KBFUN_FUNCTION_ARGS ) {
// switch layers
_kbfun_layer_set_current(
(*current_layer_) - keycode_,
current_layer_,
current_layers_ );
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// between the press and release
main_exec_key(
pressed_, 0, layer_+keycode_,
row_, col_, current_layer_,
current_layers_, pressed_layers_ );
}
/*
* Two keys => capslock
* - When assigned to two keys (e.g. the physical left and right shift keys)
* (in both the press and release matrices), pressing and holding down one of
* the keys will make the second key toggle capslock
*
* Note
* - If either of the shifts are pressed when the second key is pressed, they
* wil be released so that capslock will register properly when pressed.
* Capslock will then be pressed and released, and the original state of the
* shifts will be restored
*/
void kbfun_2_keys_capslock_press_release( KBFUN_FUNCTION_ARGS ) {
static uint8_t keys_pressed;
static bool lshift_pressed;
static bool rshift_pressed;
if (!pressed_) keys_pressed--;
// take care of the key that was actually pressed
_kbfun_press_release(pressed_, keycode_);
// take care of capslock (only on the press of the 2nd key)
if (keys_pressed == 1 && pressed_) {
// save the state of left and right shift
lshift_pressed = _kbfun_is_pressed(KEY_LeftShift);
rshift_pressed = _kbfun_is_pressed(KEY_RightShift);
// disable both
_kbfun_press_release(false, KEY_LeftShift);
_kbfun_press_release(false, KEY_RightShift);
// press capslock, then release it
_kbfun_press_release(true, KEY_CapsLock);
usb_keyboard_send();
_kbfun_press_release(false, KEY_CapsLock);
usb_keyboard_send();
// restore the state of left and right shift
if (lshift_pressed)
_kbfun_press_release(true, KEY_LeftShift);
if (rshift_pressed)
_kbfun_press_release(true, KEY_RightShift);
}
if (pressed_) keys_pressed++;
}

View File

@ -0,0 +1,12 @@
# src/lib/key-functions
These functions may do.. pretty much anything rational that they like. If they
want keycodes to be sent to the host in an aggregate report, they're responsible
for modifying the appropriate report variables.
-------------------------------------------------------------------------------
Copyright &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>
Released under The MIT License (MIT) (see "license.md")
Project located at <https://github.com/benblazak/ergodox-firmware>

View File

@ -10,14 +10,7 @@
* ------------------------------------------------------------------------- */
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(twi/MAKEFILE_BOARD.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc
#include "src/lib/conditional-include.h"
#define INCLUDE EXP_STR( ./twi/MAKEFILE_BOARD.h )
#include INCLUDE

View File

@ -21,10 +21,17 @@
* ------------------------------------------------------------------------- */
#include <util/twi.h>
#include "lib/twi.h"
// ----------------------------------------------------------------------------
// conditional compile
#if MAKEFILE_BOARD == teensy-2-0
// ----------------------------------------------------------------------------
#include <util/twi.h>
#include "./teensy-2-0.h"
// ----------------------------------------------------------------------------
void twi_init(void) {
// set the prescaler value to 0
TWSR &= ~( (1<<TWPS1)|(1<<TWPS0) );
@ -81,3 +88,8 @@ uint8_t twi_read(uint8_t * data) {
return 0; // success
}
// ----------------------------------------------------------------------------
#endif
// ----------------------------------------------------------------------------

View File

@ -10,16 +10,19 @@
#ifndef TWI_h
#define TWI_h
// --------------------------------------------------------------------
#ifndef TWI_FREQ
#define TWI_FREQ 100000 // in Hz
#endif
// --------------------------------------------------------------------
void twi_init(void);
uint8_t twi_start(void);
void twi_stop(void);
uint8_t twi_send(uint8_t data);
uint8_t twi_read(uint8_t * data);
void twi_init (void);
uint8_t twi_start (void);
void twi_stop (void);
uint8_t twi_send (uint8_t data);
uint8_t twi_read (uint8_t * data);
#endif

View File

@ -36,7 +36,7 @@
// ----------------------------------------------------------------------------
#include "lib/data-types/common.h"
#include <stdint.h>
// ----------------------------------------------------------------------------

View File

@ -17,7 +17,7 @@
// ----------------------------------------------------------------------------
#include "keyboard.h"
#include "./keyboard.h"
// ----------------------------------------------------------------------------

View File

@ -8,14 +8,46 @@
* ------------------------------------------------------------------------- */
#include <stdbool.h>
#include <stdint.h>
#include <util/delay.h>
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "lib/data-types/common.h"
#include "lib/key-functions.h"
#include "src/lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "src/lib/key-functions/public.h"
#include "src/keyboard/controller.h"
#include "src/keyboard/layout.h"
#include "src/keyboard/matrix.h"
#include "keyboard.h"
// ----------------------------------------------------------------------------
/*
* Exec key
* - Execute the keypress or keyrelease function (if it exists) of the key at
* the current possition. Pass the keycode at the current position, and pass
* all other arguments as received
*/
void main_exec_key( KBFUN_FUNCTION_ARGS ) {
kbfun_funptr_t key_function =
( (pressed_)
? kb_layout_press_get(layer_, *row_, *col_)
: kb_layout_release_get(layer_, *row_, *col_) );
if (key_function)
(*key_function)(
pressed_,
kb_layout_get(layer_, *row_, *col_),
layer_,
row_,
col_,
current_layer_,
current_layers_,
pressed_layers_ );
}
// ----------------------------------------------------------------------------
/*
* main()
*/
int main(void) {
kb_init(); // does controller initialization too
@ -28,6 +60,13 @@ int main(void) {
kb_led_state_ready();
for (;;) {
// matrix of keys currently pressed
static bool _kb_is_pressed[KB_ROWS][KB_COLUMNS];
static bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_is_pressed;
// matrix of keys previously pressed
static bool _kb_was_pressed[KB_ROWS][KB_COLUMNS];
static bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_was_pressed;
// the overall current layer
static uint8_t current_layer;
// the current layer for each key
@ -43,9 +82,9 @@ int main(void) {
kb_update_matrix(*kb_is_pressed);
// this loop is responsible to
// - "execute" keys when they change state (call `_kbfun_exec_key()`,
// - "execute" keys when they change state (call `main_exec_key()`,
// which will call the appropriate function with the appropriate
// keycode argument from the kb_layout* matrices)
// keycode argument from the kb_layout... matrices)
// - keep track of which layers the keys were on when they were pressed
// (so they can be released using the function from that layer)
//
@ -70,7 +109,7 @@ int main(void) {
if (is_pressed)
pressed_layers[row][col] = layer;
_kbfun_exec_key(
main_exec_key(
is_pressed, 0, layer,
&row, &col, &current_layer,
&current_layers, &pressed_layers );

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX controller: Teensy 2.0 specific exports : private
* main() : functions that may be useful externally
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,13 +7,12 @@
* ------------------------------------------------------------------------- */
#ifndef TEENSY_2_0_h_PRIVATE
#define TEENSY_2_0_h_PRIVATE
#ifndef MAIN_h
#define MAIN_h
#include "matrix.h"
#include "lib/key-functions/public.h"
uint8_t teensy_init(void);
uint8_t teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
void main_exec_key( KBFUN_FUNCTION_ARGS );
#endif

View File

@ -23,6 +23,9 @@ MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
BOARD := teensy-2-0 # see the libraries you're using for what's available
F_CPU := 16000000 # processor speed, in Hz
KB_DEBOUNCE_TIME := 5 # in ms; see keyswitch spec for necessary value; 5ms
# should be good for cherry mx switches
# firmware stuff
SRC := $(wildcard *.c)
# keyboard and layout stuff
@ -32,12 +35,14 @@ LAYOUT := $(strip $(LAYOUT))
# --- include stuff
SRC += $(wildcard keyboard/$(KEYBOARD)*.c)
SRC += $(wildcard keyboard/$(KEYBOARD)/*.c)
SRC += $(wildcard keyboard/$(KEYBOARD)/controller/*.c)
SRC += $(wildcard keyboard/$(KEYBOARD)/layout/$(LAYOUT)*.c)
# library stuff
# - add more "*/*/..."s as necessary to compile everything.
# - parts of the stuff under "lib" may not be necessary, depending on other
# options, but it's all included here. hopefully any unnecessary stuff gets
# compiled out. else, the makefile will have to become more complicated.
SRC += $(wildcard lib/*.c)
SRC += $(wildcard lib/*/*.c)
SRC += $(wildcard lib/*/*/*.c)
@ -48,15 +53,17 @@ SRC += $(wildcard lib-other/*/*/*.c)
OBJ = $(SRC:%.c=%.o)
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS := -mmcu=$(MCU) # processor type (teensy 2.0); must match real
# life
CFLAGS += -DF_CPU=$(F_CPU) # processor frequency; must match initialization
# in source
CFLAGS += -I. # search for includes in the current directory
CFLAGS += -I.. # search for includes in the toplevel directory
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -DMAKEFILE_BOARD='$(strip $(BOARD))'
CFLAGS += -DMAKEFILE_KEYBOARD='$(strip $(KEYBOARD))'
CFLAGS += -DMAKEFILE_KEYBOARD_LAYOUT='$(strip $(LAYOUT))'
CFLAGS += -DKB_DEBOUNCE_TIME='$(strip $(KB_DEBOUNCE_TIME))'
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -std=gnu99 # use C99 plus GCC extensions
CFLAGS += -Os # optimize for size
@ -83,6 +90,7 @@ LDFLAGS += -Wl,--gc-sections # discard unused functions and data
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
GENDEPFLAGS += -MMD -MP -MF $@.dep # generate dependency files
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CC := avr-gcc