fixing up the ...exec_key...() functions
just need to implement eeprom_macro's in a layout now, to test them!partial-rewrite
parent
c5afdb9659
commit
74c685a8b4
|
@ -145,7 +145,11 @@
|
|||
|
||||
* [Why do we need C Unions?]
|
||||
(http://stackoverflow.com/questions/252552/why-do-we-need-c-unions)
|
||||
Some good examples of what Unions are good for.
|
||||
Some examples of what unions are good for.
|
||||
|
||||
* [Using and Abusing Unions]
|
||||
(http://critical.eschertech.com/2010/03/12/using-and-abusing-unions/)
|
||||
A good discussion on when to use unions and when not to.
|
||||
|
||||
* [C preprocessor, recursive macros]
|
||||
(http://stackoverflow.com/questions/5641836/c-preprocessor-recursive-macros)
|
||||
|
@ -728,7 +732,7 @@
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Copyright © 2012, 2013, 2014 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Copyright (c) 2012, 2014 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
@ -57,7 +57,13 @@ void kb__led__delay__usb_init (void);
|
|||
void kb__led__logical_on (char led);
|
||||
void kb__led__logical_off (char led);
|
||||
// -------
|
||||
void kb__layout__exec_key (bool pressed, uint8_t row, uint8_t column);
|
||||
void kb__layout__exec_key ( bool pressed,
|
||||
uint8_t row,
|
||||
uint8_t column );
|
||||
void kb__layout__exec_key_layer ( bool pressed,
|
||||
uint8_t layer,
|
||||
uint8_t row,
|
||||
uint8_t column );
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -280,3 +286,22 @@ void kb__layout__exec_key (bool pressed, uint8_t row, uint8_t column);
|
|||
* etc. from `main()`.
|
||||
*/
|
||||
|
||||
// === kb__layout__exec_key_layer ===
|
||||
/** functions/kb__layout__exec_key_layer/description
|
||||
* Perform the appropriate actions for a "press" or "release" of the key at the
|
||||
* given position, on the given layer.
|
||||
*
|
||||
* Arguments:
|
||||
* - `pressed`:
|
||||
* - `true`: Indicates that the key to be "executed" has been pressed
|
||||
* - `false`: Indicates that the key to be "executed" has been released
|
||||
* - `layer`: The layer of the key to be "executed"
|
||||
* - `row`: The row of the key to be "executed"
|
||||
* - `column`: The column of the key to be "executed"
|
||||
*
|
||||
* Notes:
|
||||
* - If the implementation does not support layers, the `layer` argument should
|
||||
* be ignored, and this function will be equivalent to
|
||||
* `kb__layout__exec_key()`.
|
||||
*/
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "../../../../../firmware/lib/timer.h"
|
||||
#include "../../../../../firmware/lib/usb.h"
|
||||
#include "../../../../../firmware/lib/usb/usage-page/keyboard.h"
|
||||
#include "../../../../../firmware/lib/layout/eeprom-macro.h"
|
||||
#include "../../../../../firmware/lib/layout/key-functions.h"
|
||||
#include "../../../../../firmware/lib/layout/layer-stack.h"
|
||||
#include "../../../../../firmware/keyboard.h"
|
||||
|
|
|
@ -12,55 +12,63 @@
|
|||
*/
|
||||
|
||||
|
||||
/** functions/kb__layout__exec_key/description
|
||||
* Assumptions:
|
||||
* - All arguments are valid.
|
||||
*
|
||||
* Implementation notes:
|
||||
* - The default layer is layer 0.
|
||||
* - This function is only responsible for layer resolution (which includes the
|
||||
* handling of transparent keys). Everything else, it passes to
|
||||
* `kb__layout__exec_key_layer()`.
|
||||
*/
|
||||
void kb__layout__exec_key(bool pressed, uint8_t row, uint8_t column) {
|
||||
|
||||
// if we press a key, we need to keep track of the layer it was pressed on,
|
||||
// so we can release it on the same layer
|
||||
// - if the release is transparent, search through the layer stack for a
|
||||
// non-transparent release in the same position, as normal
|
||||
// - to keep track of the layer a key was pressed on, so we can release on
|
||||
// the same layer
|
||||
static uint8_t pressed_layer[OPT__KB__ROWS][OPT__KB__COLUMNS];
|
||||
|
||||
void (*function)(void);
|
||||
uint8_t layer;
|
||||
void (*function)(void);
|
||||
|
||||
// - add 1 to the stack size because we spend the first iteration checking
|
||||
// to see if we need to release on a previously stored layer
|
||||
// - add 1 to the stack size in order to peek out of bounds on the last
|
||||
// iteration (if we get that far), so that layer 0 is our default (see
|
||||
// the documentation for ".../firmware/lib/layout/layer-stack.h")
|
||||
for (uint8_t i=0; i < layer_stack__size()+1+1; i++) { // i = offset+1
|
||||
if (i == 0)
|
||||
if (!pressed)
|
||||
layer = pressed_layer[row][column];
|
||||
else
|
||||
continue;
|
||||
else
|
||||
layer = layer_stack__peek(i-1);
|
||||
// handle the case that a key is released, and the layer it was pressed on
|
||||
// has a non-transparent release function in the given location
|
||||
|
||||
if (! pressed) {
|
||||
layer = pressed_layer[row][column];
|
||||
function = (void (*)(void))
|
||||
pgm_read_word( &( layout[ layer ]
|
||||
[ row ]
|
||||
[ column ]
|
||||
[ (pressed) ? 0 : 1 ] ) );
|
||||
pgm_read_word( &( layout[ layer ]
|
||||
[ row ]
|
||||
[ column ]
|
||||
[ !pressed ] ) );
|
||||
|
||||
if (function == &KF(transp))
|
||||
function = NULL;
|
||||
if (function != &KF(transp)) {
|
||||
kb__layout__exec_key_layer( pressed, layer, row, column );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (function) {
|
||||
// otherwise, search through the layer stack for a layer with a
|
||||
// non-transparent key-function in the given location
|
||||
|
||||
// - altogether, unless we find a non-transparent key-function earlier, we
|
||||
// want to peek at offsets `0` through `layer_stack__size()`. this will
|
||||
// cause us to peek out of bounds on the last iteration, so that layer 0
|
||||
// will be the default (see the documentation for
|
||||
// ".../lib/layout/layer-stack")
|
||||
for (uint8_t i=0; i <= layer_stack__size(); i++) {
|
||||
layer = layer_stack__peek(i);
|
||||
function = (void (*)(void))
|
||||
pgm_read_word( &( layout[ layer ]
|
||||
[ row ]
|
||||
[ column ]
|
||||
[ !pressed ] ) );
|
||||
|
||||
if (function != &KF(transp)) {
|
||||
if (pressed)
|
||||
pressed_layer[row][column] = layer;
|
||||
|
||||
flags.tick_keypresses = (pressed) ? true : false; // set default
|
||||
|
||||
(*function)();
|
||||
|
||||
// TODO: *always* tick keypresses
|
||||
// TODO: instead of this, set a flag for the type of key pressed,
|
||||
// and any functions that execute can check it, and conditionally
|
||||
// reschedule themselves to run later, if they so desire
|
||||
if (flags.tick_keypresses)
|
||||
timer___tick_keypresses();
|
||||
|
||||
kb__layout__exec_key_layer( pressed, layer, row, column );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -68,3 +76,38 @@ void kb__layout__exec_key(bool pressed, uint8_t row, uint8_t column) {
|
|||
// if we get here, there was a transparent key in layer 0; do nothing
|
||||
}
|
||||
|
||||
/** functions/kb__layout__exec_key_layer/description
|
||||
* Assumptions:
|
||||
* - All arguments are valid.
|
||||
*
|
||||
* TODO:
|
||||
* - take care of the recording and such of macros :)
|
||||
*/
|
||||
void kb__layout__exec_key_layer( bool pressed,
|
||||
uint8_t layer,
|
||||
uint8_t row,
|
||||
uint8_t column ) {
|
||||
|
||||
void (*function)(void) = (void (*)(void))
|
||||
pgm_read_word( &( layout[ layer ]
|
||||
[ row ]
|
||||
[ column ]
|
||||
[ !pressed ] ) );
|
||||
if (! function) return;
|
||||
|
||||
// set default values
|
||||
// - the key-function will not be able to see the values set previously
|
||||
// - any function scheduled to run will be able to see the values set
|
||||
// previously; but that may change in the future, so it shouldn't be
|
||||
// relied on. if functions need to communicate with each other, they
|
||||
// should share a file-local or global variable.
|
||||
flags.key_type.sticky = false;
|
||||
flags.key_type.layer_shift = false;
|
||||
flags.key_type.layer_lock = false;
|
||||
|
||||
(*function)();
|
||||
|
||||
if (pressed)
|
||||
timer___tick_keypresses();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,17 +20,24 @@ static layout_t layout PROGMEM;
|
|||
/** variables/flags/description
|
||||
* A collection of flags pertaining to the operation of `...exec_key()`
|
||||
*
|
||||
* Notes:
|
||||
* - These should be set within key-functions, but only read inside
|
||||
* `...exec_key()`. The ability to read them outside that function should
|
||||
* not be counted on.
|
||||
*
|
||||
* Struct members:
|
||||
* - `tick_keypresses`: A predicate indicating whether or not to "tick"
|
||||
* keypresses on this run of the function (see the documentation in
|
||||
* ".../firmware/lib/timer.h" for more precisely what this means)
|
||||
* - This is useful for defining things like sticky keys, if, e.g., you
|
||||
* want to make it so that you can press more than one and have none of
|
||||
* them release until the press of the next normal key.
|
||||
* - `key_type`: To indicate the type of key most recently pressed
|
||||
* - More than one type flag may be set (e.g. a key may be both a
|
||||
* layer-shift key and a sticky key).
|
||||
* - `key_type.sticky`
|
||||
* - `key_type.layer_shift`
|
||||
* - `key_type.layer_lock`
|
||||
*/
|
||||
static struct {
|
||||
bool tick_keypresses : 1;
|
||||
} flags = {
|
||||
.tick_keypresses = true,
|
||||
};
|
||||
struct {
|
||||
bool sticky : 1;
|
||||
bool layer_shift : 1;
|
||||
bool layer_lock : 1;
|
||||
} key_type;
|
||||
} flags;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Copyright (c) 2013, 2014 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
|
|
@ -20,8 +20,9 @@
|
|||
* alternating between valid and deleted. This would give us 1019/5/2 ~=
|
||||
* 100 noncontiguous deleted macros, which would be about as many copy
|
||||
* objects (plus a few write objects) in ".../lib/eeprom", so about 500
|
||||
* bytes. SRAM is 2kB. Because of the way ".../lib/eeprom" is written,
|
||||
* much of this data would have to be contiguous.
|
||||
* bytes. SRAM is 2560 bytes (per the PJRC website). Because of the way
|
||||
* ".../lib/eeprom" is written, much of this data would have to be
|
||||
* contiguous.
|
||||
* - At some point, I should probably consider changing how
|
||||
* ".../lib/eeprom" (and the layer-stack code, and everything else that
|
||||
* needs a variable amount of memory) manages its memory. Again, not
|
||||
|
|
|
@ -190,7 +190,7 @@ void timer___tick_keypresses (void);
|
|||
|
||||
// === timer___tick_keypresses() ===
|
||||
/** functions/timer___tick_keypresses/description
|
||||
* Increment the counter for the number of keypresses, and perform scheduled
|
||||
* Increment the counter for the number of key-presses, and perform scheduled
|
||||
* tasks
|
||||
*
|
||||
* Meant to be used only by `kb__layout__exec_key()`
|
||||
|
|
Loading…
Reference in New Issue