ergodox-firmware/firmware/keyboard/ergodox/layout/common/keys.c.h

324 lines
14 KiB
C

/* ----------------------------------------------------------------------------
* Copyright (c) 2013 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>
* ------------------------------------------------------------------------- */
/** description
* This file implements and extends the definitions in ".../lib/layout/keys.h"
* and extends the definitions in ".../lib/layout/key-functions.h"
*
* Meant to be included *only* by the layout using it.
*/
// TODO: write a chordmak (or asetniop) layout, on top of a standard colemak
// layout, using chained sticky keys for the modifiers
// TODO: write tutorials
// - about
// - basic key functions
// - mention where people should look for more information; probably, the
// usb, key_functions, and keys headers; and others?
// - sticky keys
// - macros
// - chorded keys
// - timed keys
// - automatic repetition of utf-8 sequence keys
// - layers
// - making layouts
// - changing the meaning of the LEDs
// - put the tutorials in the readme.md of
// ".../firmware/keyboard/ergodox/layout"
#ifndef ERGODOX_FIRMWARE__KEYBOARD__ERGODOX__LAYOUT__COMMON__KEYS__C__H
#define ERGODOX_FIRMWARE__KEYBOARD__ERGODOX__LAYOUT__COMMON__KEYS__C__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include "./definitions.h"
// ----------------------------------------------------------------------------
/** macros/KEYS__DEFAULT/description
* Define the functions for a default key (i.e. a normal key that presses and
* releases a keycode as you'd expect)
*
* Needed by ".../lib/layout/keys.h"
*/
#define KEYS__DEFAULT(name, value) \
void P(name) (void) { KF(press)(value); } \
void R(name) (void) { KF(release)(value); }
/** macros/KEYS__SHIFTED/description
* Define the functions for a "shifted" key (i.e. a key that sends a "shift"
* along with the keycode)
*
* Needed by ".../lib/layout/keys.h"
*/
#define KEYS__SHIFTED(name, value) \
void P(name) (void) { KF(press)(KEYBOARD__LeftShift); \
KF(press)(value); } \
void R(name) (void) { KF(release)(value); \
KF(release)(KEYBOARD__LeftShift); }
/** macros/KEYS__LAYER__PUSH_POP/description
* Define the functions for a layer push-pop key (i.e. a layer shift key).
*
* Naming Convention:
* - Example: In the name `lpupo1l1`, we have the following:
* - `l` : this is a layer key
* - `pu` : it pushes the layer element onto the stack on "press"
* - `po` : it pops the layer element out of the stack on "release"
* - `1` : it pushes and pops the layer element with `layer_id` = 1
* - `l` : (separate the `layer_id` from the `layer_number`)
* - `1` : it pushes a layer element with `layer_number` = 1
*
* - The first and second number do not have to be the same (that is, the
* `layer_id` and `layer_number` can be different; there may be situations
* where you want or need this).
*
* - Only one of `pu` or `po` is necessary. A key with only `pu` should *only*
* push the layer onto the stack, not pop anything out of it. A key with
* only `po` should *only* pop the layer out of the stack.
*
* - If the function *only* pops the layer-element, the `layer_number` is not
* important: layers are popped based only on their `layer_id`.
*
* Notes:
* - To save space, if you define a push-pop function, the push (only) and pop
* (only) functions may be defined as follows (using the example `lpupo1l1`
* from above):
*
* #define keys__press__lpu1l1 P(lpupo1l1)
* #define keys__release__lpu1l1 KF(nop)
* #define keys__press__lpo1l1 R(lpupo1l1)
* #define keys__release__lpo1l1 KF(nop)
*/
#define KEYS__LAYER__PUSH_POP(ID, LAYER) \
void P(lpupo##ID##l##LAYER) (void) { layer_stack__push(0, ID, LAYER); \
_flags.tick_keypresses = false; } \
void R(lpupo##ID##l##LAYER) (void) { layer_stack__pop_id(ID); \
_flags.tick_keypresses = false; }
/** macros/(group) layer : number pad/description
* Define functions for pushing and popping the number pad (namely `numPush`,
* `numPop`, and `numPuPo`)
*
* Members:
* - `KEYS__LAYER__NUM_PU_PO`
* - `KEYS__LAYER__NUM_PUSH`
* - `KEYS__LAYER__NUM_POP`
*
* These macros are meant to be used (if necessary) in the layout file, since
* they need to know the layer on which the number pad has been placed.
*
* Notes:
* - `KEYBOARD__LockingNumLock` appears to be the correct keycode for OS X.
* For Linux, the correct keycode is reportedly `KEYPAD__NumLock_Clear`. For
* Windows, I haven't heard, but one of them has to work :) .
*/
#define KEYS__LAYER__NUM_PU_PO(ID, LAYER) \
void P(numPuPo) (void) { layer_stack__push(0, ID, LAYER); \
KF(press)(KEYBOARD__LockingNumLock); \
KF(press)(KEYPAD__NumLock_Clear); \
usb__kb__send_report(); \
KF(release)(KEYBOARD__LockingNumLock); \
KF(release)(KEYPAD__NumLock_Clear); \
usb__kb__send_report(); \
_flags.tick_keypresses = false; } \
void R(numPuPo) (void) { layer_stack__pop_id(ID); \
KF(press)(KEYBOARD__LockingNumLock); \
KF(press)(KEYPAD__NumLock_Clear); \
usb__kb__send_report(); \
KF(release)(KEYBOARD__LockingNumLock); \
KF(release)(KEYPAD__NumLock_Clear); \
usb__kb__send_report(); \
_flags.tick_keypresses = false; }
#define KEYS__LAYER__NUM_PUSH(ID, LAYER) \
void P(numPush) (void) { layer_stack__push(0, ID, LAYER); \
KF(press)(KEYBOARD__LockingNumLock); \
KF(press)(KEYPAD__NumLock_Clear); \
_flags.tick_keypresses = false; } \
void R(numPush) (void) { KF(release)(KEYBOARD__LockingNumLock); \
KF(release)(KEYPAD__NumLock_Clear); \
_flags.tick_keypresses = false; }
#define KEYS__LAYER__NUM_POP(ID) \
void P(numPop) (void) { layer_stack__pop_id(ID); \
KF(press)(KEYBOARD__LockingNumLock); \
KF(press)(KEYPAD__NumLock_Clear); \
_flags.tick_keypresses = false; } \
void R(numPop) (void) { KF(release)(KEYBOARD__LockingNumLock); \
KF(release)(KEYPAD__NumLock_Clear); \
_flags.tick_keypresses = false; }
// ----------------------------------------------------------------------------
/** functions/KF(2_keys_capslock)/description
* Press the given keycode, and also press "capslock" if this is the second
* consecutive time this function has been called with `pressed == true`.
*
* Meant to be used with the left and right "shift" keys.
*/
void KF(2_keys_capslock)(bool pressed, uint8_t keycode) {
static uint8_t counter = 0;
if (pressed) {
counter++;
KF(press)(keycode);
}
if (counter == 2 && pressed) {
KF(toggle_capslock)();
}
if (!pressed) {
counter--;
KF(release)(keycode);
}
}
// ----------------------------------------------------------------------------
// --- default key definitions ------------------------------------------------
#include "../../../../../firmware/lib/layout/keys.h"
// --- special keycode --------------------------------------------------------
KEYS__DEFAULT( power, KEYBOARD__Power );
KEYS__DEFAULT( volumeU, KEYBOARD__VolumeUp );
KEYS__DEFAULT( volumeD, KEYBOARD__VolumeDown );
KEYS__DEFAULT( mute, KEYBOARD__Mute );
// --- special function -------------------------------------------------------
/** keys/shL2kcap/description
* left shift + toggle capslock (if both shifts are pressed)
*
* This key always generates a left shift. If the `shR2kcap` is pressed at
* the same time, "capslock" will be toggled.
*/
void P(shL2kcap) (void) { KF(2_keys_capslock)(true, KEYBOARD__LeftShift); }
void R(shL2kcap) (void) { KF(2_keys_capslock)(false, KEYBOARD__LeftShift); }
/** keys/shR2kcap/description
* right shift + toggle capslock (if both shifts are pressed)
*
* This key always generates a right shift. If the `shL2kcaps` is pressed at
* the same time, "capslock" will be toggled.
*/
void P(shR2kcap) (void) { KF(2_keys_capslock)(true, KEYBOARD__RightShift); }
void R(shR2kcap) (void) { KF(2_keys_capslock)(false, KEYBOARD__RightShift); }
/** keys/btldr/description
* jump to the bootloader
*
* This prepares the Teensy to load a new firmware. If you press this without
* meaning to, you must turn your keyboard off then on again (usually by
* unplugging it, then plugging it back in).
*/
void P(btldr) (void) { KF(jump_to_bootloader)(); }
void R(btldr) (void) {}
/** keys/dmp_sram/description
* type the contents of SRAM, in ihex format
*
* This may take a while. To cancel, you must turn your keyboard off then on
* again (usually by unplugging it, then plugging it back in).
*/
void P(dmp_sram) (void) { KF(dump_sram_ihex)( (void *)0, (void *)-1 ); }
void R(dmp_sram) (void) {}
/** keys/dmp_prog/description
* type the contents of PROGMEM, in ihex format
*
* This may take a while. To cancel, you must turn your keyboard off then on
* again (usually by unplugging it, then plugging it back in).
*/
void P(dmp_prog) (void) { KF(dump_progmem_ihex)( (void *)0, (void *)-1 ); }
void R(dmp_prog) (void) {}
/** keys/dmp_eepr/description
* type the contents of the EEPROM, in ihex format
*
* This may take a while. To cancel, you must turn your keyboard off then on
* again (usually by unplugging it, then plugging it back in).
*/
void P(dmp_eepr) (void) { KF(dump_eeprom_ihex)( (void *)0, (void *)-1 ); }
void R(dmp_eepr) (void) {}
// ----------------------------------------------------------------------------
// --- layer ------------------------------------------------------------------
// note: these are just some default layer key definitions; no need to stick to
// them if they're inconvenient
KEYS__LAYER__PUSH_POP(0, 0);
#define keys__press__lpu0l0 P(lpupo0l0)
#define keys__release__lpu0l0 KF(nop)
#define keys__press__lpo0l0 R(lpupo0l0)
#define keys__release__lpo0l0 KF(nop)
KEYS__LAYER__PUSH_POP(1, 1);
#define keys__press__lpu1l1 P(lpupo1l1)
#define keys__release__lpu1l1 KF(nop)
#define keys__press__lpo1l1 R(lpupo1l1)
#define keys__release__lpo1l1 KF(nop)
KEYS__LAYER__PUSH_POP(2, 2);
#define keys__press__lpu2l2 P(lpupo2l2)
#define keys__release__lpu2l2 KF(nop)
#define keys__press__lpo2l2 R(lpupo2l2)
#define keys__release__lpo2l2 KF(nop)
KEYS__LAYER__PUSH_POP(3, 3);
#define keys__press__lpu3l3 P(lpupo3l3)
#define keys__release__lpu3l3 KF(nop)
#define keys__press__lpo3l3 R(lpupo3l3)
#define keys__release__lpo3l3 KF(nop)
KEYS__LAYER__PUSH_POP(4, 4);
#define keys__press__lpu4l4 P(lpupo4l4)
#define keys__release__lpu4l4 KF(nop)
#define keys__press__lpo4l4 R(lpupo4l4)
#define keys__release__lpo4l4 KF(nop)
KEYS__LAYER__PUSH_POP(5, 5);
#define keys__press__lpu5l5 P(lpupo5l5)
#define keys__release__lpu5l5 KF(nop)
#define keys__press__lpo5l5 R(lpupo5l5)
#define keys__release__lpo5l5 KF(nop)
KEYS__LAYER__PUSH_POP(6, 6);
#define keys__press__lpu6l6 P(lpupo6l6)
#define keys__release__lpu6l6 KF(nop)
#define keys__press__lpo6l6 R(lpupo6l6)
#define keys__release__lpo6l6 KF(nop)
KEYS__LAYER__PUSH_POP(7, 7);
#define keys__press__lpu7l7 P(lpupo7l7)
#define keys__release__lpu7l7 KF(nop)
#define keys__press__lpo7l7 R(lpupo7l7)
#define keys__release__lpo7l7 KF(nop)
KEYS__LAYER__PUSH_POP(8, 8);
#define keys__press__lpu8l8 P(lpupo8l8)
#define keys__release__lpu8l8 KF(nop)
#define keys__press__lpo8l8 R(lpupo8l8)
#define keys__release__lpo8l8 KF(nop)
KEYS__LAYER__PUSH_POP(9, 9);
#define keys__press__lpu9l9 P(lpupo9l9)
#define keys__release__lpu9l9 KF(nop)
#define keys__press__lpo9l9 R(lpupo9l9)
#define keys__release__lpo9l9 KF(nop)
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif // ERGODOX_FIRMWARE__KEYBOARD__ERGODOX__LAYOUT__COMMON__KEYS__C__H