removed linked lists; changed KBFUN_FUNCTION_ARGS handling

- linked lists need to be rewritten to be more memory efficient
- all kbfun functions are now of type `(void kbfun_...(void))`, and the
  arguments they need are passed via a group of global `main_arg_...`
  variables (and other `main_...` variables)
partial-rewrite
Ben Blazak 2012-08-06 15:57:23 -07:00
parent ddade5b5dc
commit d7c1ffe0c4
28 changed files with 291 additions and 624 deletions

12
src/TODO Normal file
View File

@ -0,0 +1,12 @@
- making the 'kbfun...'s work with the new global vars (instead of passed args)
from main()
- write macros so that either rows or columns can be the driving pins (macro
should be set in the keyboard/.../controller folder somewhere, i think
- then change stuff to correspond with the PCB Fredrik made
- then i'll think about how to implement variable length arrays, and write some
- then i'll think about how to use them as stacks, to deal with layer issues

View File

@ -10,7 +10,7 @@
* ------------------------------------------------------------------------- */
#include "src/lib/conditional-include.h"
#include "../lib/conditional-include.h"
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/controller.h )
#include INCLUDE

View File

@ -10,7 +10,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <util/twi.h>
#include "src/lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
#include "../../../lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
#include "../matrix.h"
#include "./mcp23018--functions.h"

View File

@ -4,7 +4,7 @@
* `+` indicates connected pin
* `o` indicates unconnected pin
* '=' is used to list other things the pin is connected to
* `=` is used to list other things the pin is connected to
* `-`s inserted between some of the pin functions for readability
### MCP23018

View File

@ -14,7 +14,7 @@
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include "src/lib/twi.h"
#include "../../../lib/twi.h"
#include "../matrix.h"
#include "./teensy-2-0--functions.h"
#include "./teensy-2-0--led.h"

View File

@ -4,7 +4,7 @@
* `+` indicates connected pin
* `o` indicates unconnected pin
* '=' is used to list other things the pin is connected to
* `=` is used to list other things the pin is connected to
* `-`s inserted between some of the pin functions for readability
* `OC**` pins enclosed in parenthesis had lines over them in the pinout

View File

@ -15,7 +15,7 @@
// --------------------------------------------------------------------
// include the appropriate keyboard layout header
#include "src/lib/conditional-include.h"
#include "../../lib/conditional-include.h"
#define INCLUDE EXP_STR( ./layout/MAKEFILE_KEYBOARD_LAYOUT.h )
#include INCLUDE

View File

@ -12,7 +12,8 @@
#include <stdint.h>
#include <avr/pgmspace.h>
#include "src/lib/key-functions/public.h"
#include "../../../lib/data-types/misc.h"
#include "../../../lib/key-functions/public.h"
#include "../matrix.h"
// --------------------------------------------------------------------
@ -56,21 +57,21 @@
#endif
#ifndef kb_layout_press_get
extern kbfun_funptr_t PROGMEM \
extern void_funptr_t PROGMEM \
_kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_press_get(layer,row,column) \
( (kbfun_funptr_t) \
( (void_funptr_t) \
pgm_read_word(&( \
_kb_layout_press[layer][row][column] )) )
#endif
#ifndef kb_layout_release_get
extern kbfun_funptr_t PROGMEM \
extern void_funptr_t PROGMEM \
_kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_release_get(layer,row,column) \
( (kbfun_funptr_t) \
( (void_funptr_t) \
pgm_read_word(&( \
_kb_layout_release[layer][row][column] )) )

View File

@ -12,8 +12,9 @@
#include <stdint.h>
#include <stddef.h>
#include <avr/pgmspace.h>
#include "src/lib/usb/usage-page/keyboard--short-names.h"
#include "src/lib/key-functions/public.h"
#include "../../../lib/data-types/misc.h"
#include "../../../lib/usb/usage-page/keyboard--short-names.h"
#include "../../../lib/key-functions/public.h"
#include "../matrix.h"
#include "../layout.h"
@ -112,7 +113,7 @@ _ctrlR, 0, _enter,
// ----------------------------------------------------------------------------
kbfun_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
void_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // press: layer 0: default
// unused
@ -184,7 +185,7 @@ NULL,
// ----------------------------------------------------------------------------
kbfun_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
void_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // release: layer 0: default
// unused

View File

@ -10,7 +10,7 @@
* ------------------------------------------------------------------------- */
#include "src/lib/conditional-include.h"
#include "../lib/conditional-include.h"
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/layout.h )
#include INCLUDE

View File

@ -10,7 +10,7 @@
* ------------------------------------------------------------------------- */
#include "src/lib/conditional-include.h"
#include "../lib/conditional-include.h"
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/matrix.h )
#include INCLUDE

View File

@ -1,237 +0,0 @@
/* ----------------------------------------------------------------------------
* linked list : 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 <stddef.h>
#include <stdlib.h>
#include "./linked-list.h"
// ----------------------------------------------------------------------------
// local macros (undefined later)
#define _NEW_POINTER(type, name) type * name = (type *) malloc(sizeof(type))
#define _list_t linked_list_t
#define _node_t linked_list_node_t
#define _data_t LINKED_LIST_DATA_TYPE
// ----------------------------------------------------------------------------
/*
* new()
*
* Returns
* - success: a pointer to a new linked list
* - failure: NULL
*/
_list_t * linked_list_new(void) {
_NEW_POINTER(_list_t, list);
if (!list) return NULL;
list->head = NULL;
list->tail = NULL;
list->length = 0;
return list;
}
/*
* insert()
*
* Arguments
* - index: the index of the position that the new node will occupy. if index
* is negative, we set index += length (as in Python). so:
* - 0 => the first node in the list
* - 1 => the second node in the list
* - -1 => the last node in the list
* - -2 => the second from the last node in the list
* - out of bounds positions wrap around, so:
* - [length] => 0 => the first node in the list
* - -[length+1] => -1 => the last node in the list
*
* Returns
* - success: the pointer to the list that was passed
* - failure: NULL
*
* Notes
* - in this function, 'list->length' is incremented before the index is
* calculated|used, so that we have a consistent way to think of adding an
* element to the end of the list
*/
_list_t * linked_list_insert(_list_t * list, int index, _data_t data) {
_NEW_POINTER(_node_t, node);
if (!node) return NULL;
list->length++;
node->data = data;
if (list->length == 1) {
// insert as only node (no others exist yet)
list->head = node;
list->tail = node;
node->next = NULL;
} else {
// find positive, in-bounds index
index = index % list->length;
if (index < 0)
index += list->length;
if (index == 0) {
// insert as first node
node->next = list->head;
list->head = node;
} else if (index == list->length-1) {
// insert as last node
list->tail->next = node;
list->tail = node;
node->next = NULL;
} else {
// insert as other node
_node_t * previous = list->head;
for (int i=1; i<index; i++)
previous = previous->next;
node->next = previous->next;
previous->next = node;
}
}
return list;
}
/*
* peek()
*
* Arguments
* - index: [see 'insert()']
*
* Returns
* - success: the data field of the node at the given index
* - failure: (_data_t) 0
*/
_data_t linked_list_peek(_list_t * list, int index) {
// if: no nodes exist
if (list->length == 0)
return (_data_t) 0;
// find positive, in-bounds index
index = index % list->length;
if (index < 0)
index += list->length;
// if: last node
if (index == list->length-1)
return list->tail->data;
// else
_node_t * node = list->head;
for (int i=0; i<index; i++)
node = node->next;
return node->data;
}
/*
* pop()
*
* Arguments
* - index: [see 'insert()']
*
* Returns
* - success: the data field of the node at the given index
* - failure: (_data_t) 0
*/
_data_t linked_list_pop(_list_t * list, int index) {
// if: no nodes exist
if (list->length == 0)
return (_data_t) 0;
// find positive, in-bounds index
index = index % list->length;
if (index < 0)
index += list->length;
// vars
_data_t data;
_node_t * node;
if (index == 0) {
// pop first node
data = list->head->data;
node = list->head;
list->head = node->next;
} else {
// find the index-1'th node
_node_t * previous;
previous = list->head;
for (int i=1; i<index; i++)
previous = previous->next;
// if: last node
if (index == list->length-1)
list->tail = previous;
// pop the node at index
data = previous->next->data;
node = previous->next;
previous->next = node->next;
}
free(node);
list->length--;
return data;
}
/*
* copy()
*
* Returns
* - success: a new pointer to a (deep) copy of the list that was passed
* - failure: NULL
*/
_list_t * linked_list_copy(_list_t * list) {
_list_t * copy = linked_list_new();
if (!copy) return NULL;
bool error;
_node_t * node = list->head;
for (int i=0; i<(list->length); i++) {
error = ! linked_list_insert(copy, -1, node->data);
if (error) {
linked_list_free(copy);
return NULL;
}
node = node->next;
}
return copy;
}
/*
* free()
* - Free the memory allocated to all the nodes, then free the memory allocated
* to the list.
*/
void linked_list_free(_list_t * list) {
_node_t * node;
for (int i=0; i<(list->length); i++) {
node = list->head;
list->head = list->head->next;
free(node);
}
free(list);
}
// ----------------------------------------------------------------------------
// local macros (undefined here)
#undef _NEW_POINTER
#undef _list_t
#undef _node_t
#undef _data_t

View File

@ -1,53 +0,0 @@
/* ----------------------------------------------------------------------------
* linked list : 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 DATA_TYPES_LINKED_LIST_h
#define DATA_TYPES_LINKED_LIST_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 {
LINKED_LIST_DATA_TYPE data;
struct linked_list_node * next;
};
struct linked_list {
uint8_t length; // 'uint8_t' to save memory
struct linked_list_node * head;
struct linked_list_node * tail;
};
// typedefs
typedef struct linked_list linked_list_t;
typedef struct linked_list_node linked_list_node_t;
// functions
#define _list_t linked_list_t
#define _data_t LINKED_LIST_DATA_TYPE
_list_t * linked_list_new (void);
_list_t * linked_list_insert (_list_t * list, int index, _data_t data);
_data_t linked_list_peek (_list_t * list, int index);
_data_t linked_list_pop (_list_t * list, int index);
_list_t * linked_list_copy (_list_t * list);
void linked_list_free (_list_t * list);
#undef _list_t
#undef _data_t
#endif

View File

@ -1,35 +0,0 @@
/* ----------------------------------------------------------------------------
* list : 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 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"
// --------------------------------------------------------------------
#define list_new linked_list_new
#define list_insert linked_list_insert
#define list_peek linked_list_peek
#define list_pop linked_list_pop
#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

16
src/lib/data-types/misc.h Normal file
View File

@ -0,0 +1,16 @@
/* ----------------------------------------------------------------------------
* miscellaneous data types
* ----------------------------------------------------------------------------
* 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__DATA_TYPES_h
#define LIB__DATA_TYPES_h
typedef void (*void_funptr_t)(void);
#endif

View File

@ -1,35 +0,0 @@
/* ----------------------------------------------------------------------------
* queue : 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 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"
// --------------------------------------------------------------------
#define queue_new linked_list_new
#define queue_append(list, data) linked_list_insert(list, -1, data)
#define queue_peek linked_list_peek
#define queue_pop(list) linked_list_pop(list, 0)
#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

@ -1,35 +0,0 @@
/* ----------------------------------------------------------------------------
* stack : 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 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"
// --------------------------------------------------------------------
#define stack_new linked_list_new
#define stack_push(list, data) linked_list_insert(list, 0, data)
#define stack_peek linked_list_peek
#define stack_pop(list) linked_list_pop(list, 0)
#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

@ -9,10 +9,11 @@
#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 "../../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "../../lib/usb/usage-page/keyboard.h"
#include "../../keyboard/layout.h"
#include "../../keyboard/matrix.h"
#include "../../main.h"
#include "./public.h"
// ----------------------------------------------------------------------------
@ -21,50 +22,50 @@
* Generate a normal keypress or keyrelease
*
* Arguments
* - press: whether to generate a keypress (true) or keyrelease (false)
* - 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) {
void _kbfun_press_release(bool press, uint8_t keycode) {
// no-op
if (keycode == 0)
return;
// modifier keys
switch (keycode) {
case KEY_LeftControl: (pressed)
case KEY_LeftControl: (press)
? (keyboard_modifier_keys |= (1<<0))
: (keyboard_modifier_keys &= ~(1<<0));
return;
case KEY_LeftShift: (pressed)
case KEY_LeftShift: (press)
? (keyboard_modifier_keys |= (1<<1))
: (keyboard_modifier_keys &= ~(1<<1));
return;
case KEY_LeftAlt: (pressed)
case KEY_LeftAlt: (press)
? (keyboard_modifier_keys |= (1<<2))
: (keyboard_modifier_keys &= ~(1<<2));
return;
case KEY_LeftGUI: (pressed)
case KEY_LeftGUI: (press)
? (keyboard_modifier_keys |= (1<<3))
: (keyboard_modifier_keys &= ~(1<<3));
return;
case KEY_RightControl: (pressed)
case KEY_RightControl: (press)
? (keyboard_modifier_keys |= (1<<4))
: (keyboard_modifier_keys &= ~(1<<4));
return;
case KEY_RightShift: (pressed)
case KEY_RightShift: (press)
? (keyboard_modifier_keys |= (1<<5))
: (keyboard_modifier_keys &= ~(1<<5));
return;
case KEY_RightAlt: (pressed)
case KEY_RightAlt: (press)
? (keyboard_modifier_keys |= (1<<6))
: (keyboard_modifier_keys &= ~(1<<6));
return;
case KEY_RightGUI: (pressed)
case KEY_RightGUI: (press)
? (keyboard_modifier_keys |= (1<<7))
: (keyboard_modifier_keys &= ~(1<<7));
return;
@ -72,7 +73,7 @@ void _kbfun_press_release(bool pressed, uint8_t keycode) {
// all others
for (uint8_t i=0; i<6; i++) {
if (pressed) {
if (press) {
if (keyboard_keys[i] == 0) {
keyboard_keys[i] = keycode;
return;
@ -91,22 +92,12 @@ void _kbfun_press_release(bool pressed, uint8_t keycode) {
* - 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] ) {
void _kbfun_layer_set_current(uint8_t layer) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
return;
@ -114,10 +105,10 @@ void _kbfun_layer_set_current(
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;
if (main_layers_press[row][col] == main_layers_current)
main_layers_press[row][col] = layer;
(*current_layer) = layer;
main_layers_current = layer;
}
/*
@ -126,8 +117,7 @@ void _kbfun_layer_set_current(
*/
void _kbfun_layer_set_mask(
uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS],
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
bool positions[KB_ROWS][KB_COLUMNS] ) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
@ -136,7 +126,7 @@ void _kbfun_layer_set_mask(
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;
main_layers_press[row][col] = layer;
}
/*

View File

@ -13,20 +13,17 @@
#ifndef LIB__KEY_FUNCTIONS__INTERNAL_h
#define LIB__KEY_FUNCTIONS__INTERNAL_h
#include "./public.h"
#include <stdbool.h>
#include <stdint.h>
#include "../../keyboard/matrix.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 _kbfun_layer_set_mask(
uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS],
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] );
bool _kbfun_is_pressed(uint8_t keycode);
void _kbfun_press_release (bool press, uint8_t keycode);
void _kbfun_layer_set_current (uint8_t layer);
void _kbfun_layer_set_mask ( uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS] );
bool _kbfun_is_pressed (uint8_t keycode);
#endif

View File

@ -12,44 +12,27 @@
#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 );
void kbfun_press_release (void);
void kbfun_toggle (void);
void kbfun_layer_inc (void);
void kbfun_layer_dec (void);
// device
void kbfun_jump_to_bootloader ( KBFUN_FUNCTION_ARGS );
void kbfun_jump_to_bootloader (void);
// 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 );
void kbfun_layermask_numpad_toggle (void);
void kbfun_layermask_numpad_on (void);
void kbfun_layermask_numpad_off (void);
// 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 );
void kbfun_layer_inc_exec (void);
void kbfun_layer_dec_exec (void);
void kbfun_2_keys_capslock_press_release (void);
#endif

View File

@ -7,28 +7,42 @@
* ------------------------------------------------------------------------- */
#include "../../../main.h"
#include "../../../keyboard/layout.h"
#include "../public.h"
#include "../private.h"
// ----------------------------------------------------------------------------
// convenience macros
#define layer main_arg_layer
#define row main_arg_row
#define col main_arg_col
#define is_pressed main_arg_is_pressed
#define was_pressed main_arg_was_pressed
// ----------------------------------------------------------------------------
/*
* Press|Release
* - Generate a normal keypress or keyrelease
*/
void kbfun_press_release( KBFUN_FUNCTION_ARGS ) {
_kbfun_press_release(pressed_, keycode_);
void kbfun_press_release(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
_kbfun_press_release(is_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_);
void kbfun_toggle(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
if (_kbfun_is_pressed(keycode))
_kbfun_press_release(false, keycode);
else
_kbfun_press_release(true, keycode_);
_kbfun_press_release(true, keycode);
}
/*
@ -36,11 +50,9 @@ void kbfun_toggle( KBFUN_FUNCTION_ARGS ) {
* - 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_ );
void kbfun_layer_inc(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
_kbfun_layer_set_current(main_layers_current + keycode);
}
/*
@ -48,10 +60,8 @@ void kbfun_layer_inc( KBFUN_FUNCTION_ARGS ) {
* - 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_ );
void kbfun_layer_dec(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
_kbfun_layer_set_current(main_layers_current - keycode);
}

View File

@ -11,13 +11,14 @@
#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 ) {
void kbfun_jump_to_bootloader(void) {
// --- for all Teensy boards ---
cli();
@ -43,7 +44,7 @@ void kbfun_jump_to_bootloader( KBFUN_FUNCTION_ARGS ) {
#else
// ----------------------------------------------------------------------------
void kbfun_jump_to_bootloader( KBFUN_FUNCTION_ARGS ) {}
void kbfun_jump_to_bootloader(void) {}
// ----------------------------------------------------------------------------

View File

@ -24,12 +24,22 @@
#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 "../../../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "../../../lib/usb/usage-page/keyboard.h"
#include "../../../keyboard/layout.h"
#include "../../../keyboard/matrix.h"
#include "../../../main.h"
#include "../public.h"
#include "../private.h"
// ----------------------------------------------------------------------------
// convenience macros
#define layer main_arg_layer
#define row main_arg_row
#define col main_arg_col
#define is_pressed main_arg_is_pressed
#define was_pressed main_arg_was_pressed
// ----------------------------------------------------------------------------
// vars
@ -74,15 +84,10 @@ static inline void _toggle_numlock(void) {
usb_keyboard_send();
}
static void _toggle_numpad(
uint8_t numpad_layer,
uint8_t current_layer,
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
static void _toggle_numpad(uint8_t numpad_layer) {
if (_numpad_activated) {
// deactivate numpad
_kbfun_layer_set_mask(
current_layer, _layer_mask, current_layers );
_kbfun_layer_set_mask(main_layers_current, _layer_mask);
_numpad_activated = false;
// if: numlock on
@ -90,8 +95,7 @@ static void _toggle_numpad(
_toggle_numlock();
} else {
// activate numpad
_kbfun_layer_set_mask(
numpad_layer, _layer_mask, current_layers );
_kbfun_layer_set_mask(numpad_layer, _layer_mask);
_numpad_activated = true;
// if: numlock off
@ -110,25 +114,28 @@ static void _toggle_numpad(
* - 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_);
void kbfun_layermask_numpad_toggle(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
_toggle_numpad(keycode);
}
/*
* Numpad on
* - Set the numpad on (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_on( KBFUN_FUNCTION_ARGS ) {
void kbfun_layermask_numpad_on(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
if (!_numpad_activated)
_toggle_numpad(keycode_, *current_layer_, current_layers_);
_toggle_numpad(keycode);
}
/*
* Numpad off
* - Set the numpad off (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_off( KBFUN_FUNCTION_ARGS ) {
void kbfun_layermask_numpad_off(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
if (_numpad_activated)
_toggle_numpad(keycode_, *current_layer_, current_layers_);
_toggle_numpad(keycode);
}

View File

@ -9,14 +9,24 @@
#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 "../../../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "../../../lib/usb/usage-page/keyboard.h"
#include "../../../keyboard/layout.h"
#include "../../../main.h"
#include "../public.h"
#include "../private.h"
// ----------------------------------------------------------------------------
// convenience macros
#define layer main_arg_layer
#define row main_arg_row
#define col main_arg_col
#define is_pressed main_arg_is_pressed
#define was_pressed main_arg_was_pressed
// ----------------------------------------------------------------------------
/*
* Increase layer, Execute key
* - Increment the current layer by the value specified in the keymap (for all
@ -26,20 +36,17 @@
* Note
* - Meant to be paired with `kbfun_layer_dec_exec()`
*/
void kbfun_layer_inc_exec( KBFUN_FUNCTION_ARGS ) {
void kbfun_layer_inc_exec(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
// switch layers
_kbfun_layer_set_current(
(*current_layer_) + keycode_,
current_layer_,
current_layers_ );
_kbfun_layer_set_current(main_layers_current + keycode);
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// - `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_ );
layer += keycode;
main_exec_key();
}
@ -52,20 +59,17 @@ void kbfun_layer_inc_exec( KBFUN_FUNCTION_ARGS ) {
* Note
* - Meant to be paired with `kbfun_layer_inc_exec()`
*/
void kbfun_layer_dec_exec( KBFUN_FUNCTION_ARGS ) {
void kbfun_layer_dec_exec(void) {
uint8_t keycode = kb_layout_get(layer, row, col);
// switch layers
_kbfun_layer_set_current(
(*current_layer_) - keycode_,
current_layer_,
current_layers_ );
_kbfun_layer_set_current(main_layers_current - keycode);
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// - `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_ );
layer += keycode;
main_exec_key();
}
@ -81,18 +85,20 @@ void kbfun_layer_dec_exec( KBFUN_FUNCTION_ARGS ) {
* 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 ) {
void kbfun_2_keys_capslock_press_release(void) {
static uint8_t keys_pressed;
static bool lshift_pressed;
static bool rshift_pressed;
if (!pressed_) keys_pressed--;
uint8_t keycode = kb_layout_get(layer, row, col);
if (!is_pressed) keys_pressed--;
// take care of the key that was actually pressed
_kbfun_press_release(pressed_, keycode_);
_kbfun_press_release(is_pressed, keycode);
// take care of capslock (only on the press of the 2nd key)
if (keys_pressed == 1 && pressed_) {
if (keys_pressed == 1 && is_pressed) {
// save the state of left and right shift
lshift_pressed = _kbfun_is_pressed(KEY_LeftShift);
rshift_pressed = _kbfun_is_pressed(KEY_RightShift);
@ -113,6 +119,6 @@ void kbfun_2_keys_capslock_press_release( KBFUN_FUNCTION_ARGS ) {
_kbfun_press_release(true, KEY_RightShift);
}
if (pressed_) keys_pressed++;
if (is_pressed) keys_pressed++;
}

View File

@ -10,7 +10,7 @@
* ------------------------------------------------------------------------- */
#include "src/lib/conditional-include.h"
#include "../lib/conditional-include.h"
#define INCLUDE EXP_STR( ./twi/MAKEFILE_BOARD.h )
#include INCLUDE

View File

@ -11,37 +11,33 @@
#include <stdbool.h>
#include <stdint.h>
#include <util/delay.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 "./lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "./lib/key-functions/public.h"
#include "./keyboard/controller.h"
#include "./keyboard/layout.h"
#include "./keyboard/matrix.h"
#include "./main.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_) );
static bool _main_kb_is_pressed[KB_ROWS][KB_COLUMNS];
bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_main_kb_is_pressed;
if (key_function)
(*key_function)(
pressed_,
kb_layout_get(layer_, *row_, *col_),
layer_,
row_,
col_,
current_layer_,
current_layers_,
pressed_layers_ );
}
static bool _main_kb_was_pressed[KB_ROWS][KB_COLUMNS];
bool (*main_kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_main_kb_was_pressed;
uint8_t main_layers_current;
uint8_t main_layers_press[KB_ROWS][KB_COLUMNS];
uint8_t main_layers_release[KB_ROWS][KB_COLUMNS];
uint8_t main_loop_row;
uint8_t main_loop_col;
uint8_t main_arg_layer;
uint8_t main_arg_row;
uint8_t main_arg_col;
bool main_arg_is_pressed;
bool main_arg_was_pressed;
// ----------------------------------------------------------------------------
@ -60,31 +56,15 @@ 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;
// swap `main_kb_is_pressed` and `main_kb_was_pressed`, then update
bool (*temp)[KB_ROWS][KB_COLUMNS] = main_kb_was_pressed;
main_kb_was_pressed = main_kb_is_pressed;
main_kb_is_pressed = temp;
// the overall current layer
static uint8_t current_layer;
// the current layer for each key
static uint8_t current_layers[KB_ROWS][KB_COLUMNS];
// the layer each key was on when it was last pressed
static uint8_t pressed_layers[KB_ROWS][KB_COLUMNS];
// swap `kb_is_pressed` and `kb_was_pressed`, then update
bool (*temp)[KB_ROWS][KB_COLUMNS] = kb_was_pressed;
kb_was_pressed = kb_is_pressed;
kb_is_pressed = temp;
kb_update_matrix(*kb_is_pressed);
kb_update_matrix(*main_kb_is_pressed);
// this loop is responsible to
// - "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)
// - "execute" keys when they change state
// - keep track of which layers the keys were on when they were pressed
// (so they can be released using the function from that layer)
//
@ -92,34 +72,41 @@ int main(void) {
// - everything else is the key function's responsibility
// - see the keyboard layout file ("keyboard/ergodox/layout/*.c") for
// which key is assigned which function (per layer)
// - see "lib/key-functions.c" for the function definitions
// - anything passed to the key function by reference is fair game for
// that function to modify
for (uint8_t row=0; row<KB_ROWS; row++) {
for (uint8_t col=0; col<KB_COLUMNS; col++) {
bool is_pressed = (*kb_is_pressed)[row][col];
bool was_pressed = (*kb_was_pressed)[row][col];
// - see "lib/key-functions/public/*.c" for the function definitions
#define row main_loop_row
#define col main_loop_col
#define layer main_arg_layer
#define is_pressed main_arg_is_pressed
#define was_pressed main_arg_was_pressed
for (row=0; row<KB_ROWS; row++) {
for (col=0; col<KB_COLUMNS; col++) {
is_pressed = (*main_kb_is_pressed)[row][col];
was_pressed = (*main_kb_was_pressed)[row][col];
if (is_pressed != was_pressed) {
uint8_t layer = ( (is_pressed)
? current_layers[row][col]
: pressed_layers[row][col] );
if (is_pressed) {
layer = main_layers_press[row][col];
main_layers_release[row][col] = layer;
} else {
layer = main_layers_release[row][col];
}
if (is_pressed)
pressed_layers[row][col] = layer;
main_exec_key(
is_pressed, 0, layer,
&row, &col, &current_layer,
&current_layers, &pressed_layers );
// set remaining vars, and "execute" key
main_arg_row = row;
main_arg_col = col;
main_exec_key();
}
}
}
#undef row
#undef col
#undef layer
#undef is_pressed
#undef was_pressed
// send the USB report (even if nothing's changed)
usb_keyboard_send();
_delay_ms(KB_DEBOUNCE_TIME);
_delay_ms(MAKEFILE_DEBOUNCE_TIME);
// update LEDs
if (keyboard_leds & (1<<0)) { kb_led_num_on(); }
@ -137,3 +124,31 @@ int main(void) {
return 0;
}
// ----------------------------------------------------------------------------
// convenience macros (for the helper functions below)
#define layer main_arg_layer
#define row main_arg_row
#define col main_arg_col
#define is_pressed main_arg_is_pressed
#define was_pressed main_arg_was_pressed
// ----------------------------------------------------------------------------
/*
* Exec key
* - Execute the keypress or keyrelease function (if it exists) of the key at
* the current possition.
*/
void main_exec_key(void) {
void (*key_function)(void) =
( (is_pressed)
? kb_layout_press_get(layer, row, col)
: kb_layout_release_get(layer, row, col) );
if (key_function)
(*key_function)();
}
// ----------------------------------------------------------------------------

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* main() : functions that may be useful externally
* main() : functions and data that may be useful externally
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -10,9 +10,32 @@
#ifndef MAIN_h
#define MAIN_h
#include "lib/key-functions/public.h"
#include <stdbool.h>
#include <stdint.h>
#include "./lib/key-functions/public.h"
#include "./keyboard/matrix.h"
void main_exec_key( KBFUN_FUNCTION_ARGS );
// --------------------------------------------------------------------
extern bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS];
extern bool (*main_kb_was_pressed)[KB_ROWS][KB_COLUMNS];
extern uint8_t main_layers_current;
extern uint8_t main_layers_press[KB_ROWS][KB_COLUMNS];
extern uint8_t main_layers_release[KB_ROWS][KB_COLUMNS];
extern uint8_t main_loop_row;
extern uint8_t main_loop_col;
extern uint8_t main_arg_layer;
extern uint8_t main_arg_row;
extern uint8_t main_arg_col;
extern bool main_arg_is_pressed;
extern bool main_arg_was_pressed;
// --------------------------------------------------------------------
void main_exec_key(void);
#endif

View File

@ -23,8 +23,8 @@ 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
DEBOUNCE_TIME := 5 # in ms; see keyswitch spec for necessary value; 5ms should
# be good for cherry mx switches
# firmware stuff
SRC := $(wildcard *.c)
@ -38,11 +38,12 @@ SRC += $(wildcard keyboard/$(KEYBOARD)/*.c)
SRC += $(wildcard keyboard/$(KEYBOARD)/controller/*.c)
SRC += $(wildcard keyboard/$(KEYBOARD)/layout/$(LAYOUT)*.c)
# library stuff
# - should be last in the list of files to compile, in case there are default
# macros that have to be overridden in other source files
# - 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)
@ -58,12 +59,11 @@ 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 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 += -DMAKEFILE_DEBOUNCE_TIME='$(strip $(DEBOUNCE_TIME))'
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -std=gnu99 # use C99 plus GCC extensions
CFLAGS += -Os # optimize for size