taken from Hasu codebase (https://github.com/tmk/tmk_keyboard) usb.c/.h
and usb_extra.c/.h, though these files only have the PJRC
copyright/license in the header
as desired, it is possible to hold the sticky key down for short number
runs and it is now a more frequently used key that toggle. Also added
notes about mac keycodes that I found in search of play/next/prev
buttons. I suspect that codes need to be inserted into the USB data
stream to indicate that a media key is being pressed.
the behavior for transparent keys not affecting sticky key state was
broken because kbfun_transparent() was only getting called for key
press and not for key release because the layer for the key was cached
on keypress. By caching the transparent key press result on key press
we can ensure that the main_arg_trans_key_pressed is set correctly for
any key function called on key release
kbfun_press_release_preserve_sticky() is meant to replace
kbfun_press_release as the function used for standard modifiers (shift,
control, alt, and gui) so that the sticky state is preserved and it is
possible to key in chorded commands using a key on another layer
pressing the keys in the chord one key at a time simultaneously without
breaking the sticky state. (e.g. ctrl+F2 as lsticky2, ctrl, x [where x
is defined as F2 on layer 2]
TODO: Noticed a bug where the transparent behavior does not work as
expected for modifiers. lsticky2, ctrl, x does not produce ctrl+F2 when
ctrl is defined as transparent on layer 2 and keycode=ctrl,
press=kprrel, release=kprrel on layer 0.
sticky layers in the one time state were being popped anytime
kbfun_press_release() was called, which should only happen if the key
was defined for the sticky layer, i.e. kbfun_transparent() was not the
first function mapped to that key in the topmost layer.
This function gives similar behavior to sticky keys for modifiers
available on most operating systems. It is considered an accessibility
feature because it alleviates the user from having to hold down
modifiers while pressing a key to produce the modified key function. It
is useful for fast touch typing because you can avoid chording motions
which both strain your hands and take your hands out of home-row
position while pressing normal alpha keys.
This function emulates the 3-state behavior which is default on OS X
and optional in Windows where the modifier cycles between
Off->Once->Locked states. This is particularly handy for symbol layers
where you typically only type one symbol before you want to return to
unmodified typing (layer 0), e.g. 'if (condition) { a = "b" + "c"; }'.
If you assign a symbol layer to a thumb key as a layer sticky cycle,
you can type the entire line of code without taking your hands out of
home row position and you do not need to toggle off the layer after
each symbol is pressed, only immediately before keying the symbol.
The exact behavior of the layer sticky cycle function is defined as
follows for each state:
1) One time down (set on key press) - The layer was not active and the
key has been pressed but not yet released. The layer is pushed in the
one time down state.
2) One time up (set on key release) - The layer was active when the
layer sticky key was released. If a key on this layer (not set to
transparent) was pressed before the key was released, the layer will be
popped. If a non-transparent key was not pressed, the layer is popped
and pushed again in the one time up state.
3) Locked (set on key press) - The layer was active and in the one time
up state when the layer sticky key was pressed again. The layer will be
popped if the function is invoked on a subsequent keypress.
------- jjt -------
I increased the spacing of the layout sections and made all layers follow the
spacing for consistency.
I also made changes to the positions of the layer keys, added a number symbol
row on layer 1 (I found it easier to reach) and made a QWERTY layer, mostly for
gaming. And I switched the primary thumb buttons, also for gaming.
-------------------
- rewrote the layer functions in main() (easiest way to get the to
work.. :) )
- fixed the keymap (i had the numpad keys pushing layer 2 instead of
layer 3)
- changed the numlock keycode.. i was using the wrong one, lol
- and some minor aesthetic changes
- NOT TESTED YET. still need to do that
- also, got an idea for layer masking...
possible future changes:
- i'd like to make the layer matrices just '_kb_layout_values', and
'_kb_layout_functions'.
- i'd like to make layer masks implemented with a special function
'kbfun_layermask_transparent' or something similar. a function that
looks up what would have been pressed if that layer wasn't active.
they could be chainable, i.e. a lookup for such a function could end
up calling the same function (if two layermasks were active on top of
on another), which would then call a real key. these wouldn't be
allowed on the base layer, of course... and then, all i'd have to do
to keep track of layers would be keep a variable length array (or
not... maybe an array of length 10 or something) of which layer is
active... :)
- i'd like to have a thing (this isn't a very complete thought yet)
where keypresses are looked up first in the EEPROM, to see if there's
a definition there. if there isn't (which should usually be the case)
then the standard definition for that key from the matrices would be
used. this would allow macros (and redefinitions) without reflashing.
this would also be convenient, once the mechanism was implemented, for
assigning keys multiple decomposable actions... dunno exactly how
it'll work out yet though. layer stuff comes first.
- rows are now 0..6, cols now 0..D (matching the pics Fredrik posted of
his first flippable PCB)
- either rows or columns can now be the driving pins. the option is in
".../keyboard/.../options.h"
- 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)
- new ergodox website
- clarification in licence indicating that parts of the project may not
be under that license/copyright
- currently the stuff in src/lib, and soon the stuff in contrib,
(are|will be) under different copyrights, and possibly different
licenses.
- also, just so it's written down somewhere: some of my documentation
may be considered derivative works of the specs|docs i was taking
things from, but i hope i'm safe (fair use?). i tried to make clear
in each file where i got stuff though.
- the numpad functions are reorganized, and there are more of them now,
so the numpad can be treated either as something that's toggled or
something that's locked
- the numpad functions may need to be split into a separate file, to
keep things pretty. i'll look into it later.
- the linked-list functions are being written so that hopefully i can
change the concept of how layers (with transitions and masking) are
handled. they're incomplete in this check in because i took a break
to fix the numpad functions for dox
also added another layer to _kb_layout_release[][][], mostly NULL, but
including at least one of each available kbfun*(). this way, all the
functions appear to be used, and none of them get optimised out by the
compiler
- changed KBFUN_FUNCTION_ARGS again
- changed kbfun's
- condensed `kbfun_press()` and `kbfun_release()` to `kbfun_press_release()`
- added `kbfun_toggle()`, which toggles keycodes on or off
- added `kbfun_layer_inc_dec_press_release()` which is like
...press_release(), except it increments the layer first (and
decrements it on keyrelease)
- added `_kbfun_exec_key()` (which is a public kbfun*(), but not for
assignment to keycodes) for convenience. used by main(), and
currently 1 of the kbfun*()s. it doesn't save a lot of code, but i
think it makes things slightly easier to read. not quite as elegant
a solution as i'd like, but it might have to do
- changed keymap accordingly
- changed main()
- now using `_kbfun_exec_key()` (instead of essentially inlining the code)
- now sending the USB report once every cycle. i was sending once for
every keypress (lol, by mistake: what i meant to do was only send it
if any keys had been pressed).
so that _kb_layout_press... and ...release... are of type uint8_t
instead of kbfun_funptr_t (saving 1 byte per key per layer per matrix =
40% of the total layout size).
this brings the total firmware size with 10 layers to 6574 bytes instead
of 8302 bytes. the teensy 2.0 has 32256 bytes of flash.
i'm going to revert to the old way. partly because the space savings
don't seem consequential compared to what we have to work with. mostly
because doing it with an array separates the function pointer to macro
(or const var) correlation in qwerty.c, and because i then have to
extern the _kb_layout_functions[6] array in layout.h (or qwerty.h).
also, using an enum instead of macros with manually assigned numbers
corresponding to the array indices would be more error prone, i think,
because (since it has to be visible outside qwerty.c) it would have to
be declared in a header.
hopefully all that makes sense. i'm in a bit of a hurry. but look at
the code: i think, even with a bit of formatting help, it'd still look
less clean
- addition to references.md
- keymap modification
- now using 2 shifts => capslock
- the previous capslock key -> tab
- the previous tab key -> left bracket
- bug and omission fixes; notably:
- _is_pressed() no longer changes the value of
`keyboard_modifier_keys`, lol
- kbfun_2_keys_capslock_press_release() now works. (capslock doesn't
register if left or right shift is pressed, so the shift state has
to be stored, cleared, capslock pressed, and shift state restored)
- main() no longer locally overwrites the value of `current_layer`
before sending it to the kbfun. (i didn't realize i was using the
same variable name for two different things)
- improvements
- kbfun_layer_inc() and ...dec() are now variable
there is now a toplevel makefile for making dist, so that we can keep
the project build systems separate (in src and contrib/UI*), and then
build dist from the root dir
before, if you pressed a key, then shifted layers, then released it, the
first layer's press() would be called, and the 2nd layer's release()
would be called, causing keys to stick, and probably other errors. now,
the layer that the key was on when it was pressed is kept track of, and
the proper release() is called.
also, layers can be shifted per key now, instead of just for the whole
board at once
i also changed how keyboard-private includes are handled. "private"
stuff is now in its own file, instead of being nested in an extra
`#ifdef`.
and i think that's it. i'm pretty tired right now, so there may be
errors, but it seemed to work all right with cursory tests.
without this we have ghosting problems on the bottommost keys of the
teensy side
thanks to hasu (on geekhack) for the suggestion, and PrinsValium for
confirming erratic behavior with his firmware without these delays.
thanks DOX for making the changes and trying it out. i'm just adding it
to the repo.
- added high-level (logical) led macros, so that the top level firmware
doens't need to know what numbers leds are (or how many there are)
- left low-level (processor specific) led macros in
keyboard/.../teensy-2-0.h , where they were
- put non processor|layout specific led macros in keyboard/.../led.h
- put layout specific led macros into keyboard/.../layout/*.h (with
default empty macro definitions in keyboard/.../layout.h)
also
- cleaned up some typos and such
- moved the debounce time macro to 'keyboard/ergodox.h', since it's
technically keyboard (keyswitch) specific
aggregate changes for PCB update
- documentation updated to reflect that the columns are now the driving
pins, and the columns are the read pins. both are still treated as
open drain.
- macros for led pins 1 and 2 were swapped
- update functions now cycle through columns->low, read rows
- added a matrix macro to map from how we want the key layouts
represented, to how things are scanned into the matrix
(plus a few small aesthetic things in /src/keyboard. i changed some
function like macros to lower-case, because someday they might be
implemented as real functions... and there's no real reason to
distinguish between functions and function like macros in the main() and
other higher level code. at least that's what it seems like to me right
now.)