Last active
April 20, 2018 18:07
-
-
Save noseglasses/d47f3ef70ef97535bf9fb7bc71759b32 to your computer and use it in GitHub Desktop.
Noseglasses Model01 sketch 2018-04-20
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- mode: c++ -*- | |
// Copyright 2016 Keyboardio, inc. <jesse@keyboard.io> | |
// See "LICENSE" for license details | |
#ifndef BUILD_INFORMATION | |
#define BUILD_INFORMATION "locally built" | |
#endif | |
// The Kaleidoscope core | |
#include "Kaleidoscope.h" | |
#include <kaleidoscope/hid.h> | |
// Support for papageno features | |
#define KALEIDOSCOPE_PAPAGENO_POSTPONE_INITIALIZATION | |
#include "Kaleidoscope-Papageno.h" | |
// Support for keys that move the mouse | |
#include "Kaleidoscope-MouseKeys.h" | |
// Support for macros | |
#include "Kaleidoscope-Macros.h" | |
// Support for controlling the keyboard's LEDs | |
#include "Kaleidoscope-LEDControl.h" | |
#include "Kaleidoscope-LED-ActiveModColor.h" | |
// Support for an "LED off mode" | |
#include "LED-Off.h" | |
#include "Kaleidoscope-OneShot.h" | |
// Support for the "Boot greeting" effect, which pulses the 'LED' button for 10s | |
// when the keyboard is connected to a computer (or that computer is powered on) | |
#include "Kaleidoscope-LEDEffect-BootGreeting.h" | |
enum { MACRO_VERSION_INFO, | |
MACRO_ANY | |
}; | |
enum { NORMAN, M1, M2, M3 }; // layers | |
const Key keymaps[][ROWS][COLS] PROGMEM = { | |
[NORMAN] = KEYMAP_STACKED | |
(___, ___, ___, ___, ___, LCTRL(Key_X), LCTRL(Key_X), | |
OSL(M3), Key_Q, Key_W, Key_D, Key_F, Key_K, LCTRL(Key_C), | |
OSL(M2), Key_A, Key_S, Key_E, Key_T, Key_G, // home row | |
OSM(LeftControl),Key_Z, Key_X, Key_C, Key_V, Key_B, LCTRL(Key_V), | |
LCTRL(Key_F), Key_Backspace, OSM(LeftShift),OSM(LeftAlt), | |
OSM(LeftAlt), | |
___, ___, ___, ___, ___, ___, ___, | |
___, Key_J, Key_U, Key_R, Key_L, Key_Semicolon, Key_Escape, | |
Key_Y, Key_N, Key_I, Key_O, Key_H, OSL(M2), | |
LCTRL(Key_S), Key_P, Key_M, Key_Comma, Key_Period,Key_Slash,OSM(LeftControl), | |
OSM(LeftAlt), OSL(M1), Key_Space, ___, | |
OSM(LeftAlt)), | |
[M1] = KEYMAP_STACKED | |
(___, ___, ___, ___, ___, ___, ___, | |
___, LSHIFT(Key_2), LSHIFT(Key_Minus), Key_LeftBracket, Key_RightBracket, LSHIFT(Key_6), ___, | |
___, Key_Backslash, Key_Backtick, LSHIFT(Key_LeftBracket), LSHIFT(Key_RightBracket), LSHIFT(Key_8), | |
___, LSHIFT(Key_3), LSHIFT(Key_Backtick), Key_Pipe, LSHIFT(Key_4), RALT(Key_5), ___, | |
___, ___, ___, ___, | |
___, | |
___, ___, ___, ___, ___, ___, ___, | |
___, LSHIFT(Key_1), LSHIFT(Key_Comma), LSHIFT(Key_Period), Key_Equals, LSHIFT(Key_7), ___, | |
LSHIFT(Key_Slash), LSHIFT(Key_9), LSHIFT(Key_0), Key_Minus, LSHIFT(Key_Semicolon), ___, | |
___, LSHIFT(Key_Equals), LSHIFT(Key_5), LSHIFT(Key_Quote), Key_Quote, Key_Semicolon, ___, | |
___, ___, ___, ___, | |
___), | |
[M2] = KEYMAP_STACKED | |
(___, ___, ___, ___, ___, ___, ___, | |
___, Key_PageUp, Key_Backspace, Key_UpArrow, Key_Delete, Key_PageDown, ___, | |
___, Key_Home, Key_LeftArrow, Key_DownArrow, Key_RightArrow, Key_End, | |
___, XXX, Key_Tab, XXX, Key_Enter, XXX, ___, | |
___, ___, ___, ___, | |
___, | |
___, ___, ___, ___, ___, ___, ___, | |
___, XXX, Key_7, Key_8, Key_9, XXX, ___, | |
XXX, Key_4, Key_5, Key_6, Key_Period,___, | |
___, Key_0, Key_1, Key_2, Key_3, Key_Comma,___, | |
___, ___, ___, ___, | |
___), | |
[M3] = KEYMAP_STACKED | |
(___, ___, ___, ___, ___, ___, ___, | |
___, ___, ___, ___, ___, ___, ___, | |
___, ___, ___, ___, ___, ___, | |
___, ___, ___, ___, ___, ___, ___, | |
___, ___, ___, ___, | |
___, | |
___, ___, ___, ___, ___, ___, ___, | |
___, XXX, Key_F7, Key_F8, Key_F9, Key_F12, ___, | |
XXX, Key_F4, Key_F5, Key_F6, Key_F11, ___, | |
___, XXX, Key_F1, Key_F2, Key_F3, Key_F10, ___, | |
___, ___, ___, ___, | |
___) | |
}; | |
static void versionInfoMacro(uint8_t keyState) { | |
if (keyToggledOn(keyState)) { | |
Macros.type(PSTR("Keyboardio Model 01 - Kaleidoscope ")); | |
Macros.type(PSTR(BUILD_INFORMATION)); | |
} | |
} | |
const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) { | |
switch (macroIndex) { | |
case MACRO_VERSION_INFO: | |
versionInfoMacro(keyState); | |
break; | |
} | |
return MACRO_NONE; | |
} | |
/** The 'setup' function is one of the two standard Arduino sketch functions. | |
* It's called when your keyboard first powers up. This is where you set up | |
* Kaleidoscope and any plugins. | |
*/ | |
void setup() { | |
// For usb serial debugging | |
// | |
// Serial.begin(9600); | |
// Serial.println("setup"); | |
// First, call Kaleidoscope's internal setup function | |
Kaleidoscope.setup(); | |
// #if 0 | |
// Next, tell Kaleidoscope which plugins you want to use. | |
// The order can be important. For example, LED effects are | |
// added in the order they're listed here. | |
Kaleidoscope.use( | |
&Papageno, | |
&OneShot, | |
// LEDControl provides support for other LED modes | |
&LEDControl, | |
// We start with the LED effect that turns off all the LEDs. | |
// &LEDOff, | |
&ActiveModColorEffect, | |
// The boot greeting effect pulses the LED button for 10 seconds after the keyboard is first connected | |
&BootGreetingEffect | |
); | |
} | |
void loop() { | |
Papageno.loop(); | |
} | |
/* | |
glockenspiel_begin | |
default: event_timeout = $ 200 $ | |
%############################################################################### | |
% Inputs | |
%############################################################################### | |
% Thumb keys are numbered left to right | |
% | |
input: LeftThumb1 <KEYPOS> = $ 0, 7 $ | |
input: LeftThumb2 <KEYPOS> = $ 1, 7 $ | |
input: LeftThumb3 <KEYPOS> = $ 2, 7 $ | |
input: LeftThumb4 <KEYPOS> = $ 3, 7 $ | |
input: RightThumb1 <KEYPOS> = $ 3, 8 $ | |
input: RightThumb2 <KEYPOS> = $ 2, 8 $ | |
input: RightThumb3 <KEYPOS> = $ 1, 8 $ | |
input: RightThumb4 <KEYPOS> = $ 0, 8 $ | |
input: Special1 <KEYPOS> = $ 2, 9 $ | |
input: Special2 <KEYPOS> = $ 0, 9 $ | |
input: Special3 <KEYPOS> = $ 0, 6 $ | |
input: Special4 <KEYPOS> = $ 1, 6 $ | |
input: Special5 <KEYPOS> = $ 2, 6 $ | |
input: Special6 <KEYPOS> = $ 1, 9 $ | |
% Key alias for keys on Norman layout | |
% | |
input: NG_Key_E <KEYPOS> = $ 2, 3 $ | |
input: NG_Key_O <KEYPOS> = $ 2, 13 $ | |
input: NG_Key_I <KEYPOS> = $ 2, 12 $ | |
input: NG_Key_S <KEYPOS> = $ 2, 2 $ | |
input: NG_Prog_Key <KEYPOS> = $ 0, 0 $ | |
%############################################################################### | |
% Actions | |
%############################################################################### | |
action: aShiftTab <COMPLEX_KEYCODE> = $ LSHIFT(Key_Tab) $ | |
action: leftCTRL_F <COMPLEX_KEYCODE> = $ LCTRL(Key_F) $ | |
action: shiftCtrlC <COMPLEX_KEYCODE> = $ LCTRL(LSHIFT(Key_C)) $ | |
action: doubleTab <USER_FUNCTION> = $ doubleTabCB, NULL $ | |
action: repeatLastCommand <USER_FUNCTION> = $ repeatLastCommandCB, NULL $ | |
action: ordinarySearch <USER_FUNCTION> = $ ordinarySearchCB, NULL $ | |
action: fileSearch <USER_FUNCTION> = $ fileSearchCB, NULL $ | |
action: umlaut_A <USER_FUNCTION> = $ umlautCB, (void*)Key_A.raw $ | |
action: umlaut_O <USER_FUNCTION> = $ umlautCB, (void*)Key_O.raw $ | |
action: umlaut_U <USER_FUNCTION> = $ umlautCB, (void*)Key_U.raw $ | |
action: umlaut_S <COMPLEX_KEYCODE> = $ RALT(Key_S) $ | |
action: toggleLEDEffect <COMPLEX_KEYCODE> = $ Key_LEDEffectNext $ | |
action: reboot <USER_FUNCTION> = $ rebootCB, NULL $ | |
%############################################################################### | |
% Patterns | |
%############################################################################### | |
% A cluster that causes enter (key order arbitrary) | |
% | |
{LeftThumb3, RightThumb2} : Key_Enter | |
% Allow to trigger enter with one hand if necessary | |
% | |
|LeftThumb4|*2 : Key_Enter | |
|LeftThumb1|*2 : Key_Enter | |
% Double tap on the left inner thumb key triggers a user function | |
% | |
|LeftThumb3|*2 : doubleTab | |
% A note line with two thumb keys triggers tab | |
% | |
|LeftThumb3| -> |RightThumb3| : Key_Tab | |
% Double tap on right inner thumb key | |
% | |
|RightThumb2|*2 : aShiftTab | |
% Note line | |
% | |
|RightThumb2| -> |LeftThumb2| : Key_Delete | |
% Tap dance | |
% | |
|Special1|*2 : repeatLastCommand | |
|Special3|*3 : ordinarySearch@2, fileSearch@3 | |
|Special4|*2 : leftCTRL_F | |
|Special5|*2 : Key_F3 | |
|Special6|*2 : shiftCtrlC | |
|NG_Prog_Key|*5 : toggleLEDEffect@2, reboot@5 | |
% Assign german umlauts as tripple taps to | |
% suitable and non-colliding (digraphs!) keys of the home row | |
% | |
% Occurence probabilities of umlauts in written german: | |
% | |
% a-umlaut 0,54% | |
% o-umlaut 0,30% | |
% u-umlaut 0,65% | |
% s-umlaut 0,37% | |
% | |
% These are used together with the EURKEY keyboard layout | |
% that is available on Linux and Windows | |
% | |
% TODO: Disable the following on layers higher than 0 | |
% | |
|NG_Key_E|*3 : umlaut_A | |
|NG_Key_O|*3 : umlaut_O | |
|NG_Key_I|*3 : umlaut_U | |
|NG_Key_S|*3 : umlaut_S | |
glockenspiel_end | |
*/ | |
inline | |
void pressKey(const Key &k) { | |
handleKeyswitchEvent(k, UNKNOWN_KEYSWITCH_LOCATION, IS_PRESSED); | |
kaleidoscope::hid::sendKeyboardReport(); | |
} | |
inline | |
void releaseKey(const Key &k) { | |
handleKeyswitchEvent(k, UNKNOWN_KEYSWITCH_LOCATION, WAS_PRESSED); | |
kaleidoscope::hid::sendKeyboardReport(); | |
} | |
inline | |
void tapKey(const Key &k) { | |
pressKey(k); | |
releaseKey(k); | |
} | |
#define NG_CALLBACK_NO_REPEAT \ | |
if(activation_flags & PPG_Action_Activation_Flags_Repeated) { return; } | |
#define NG_CALLBACK_ONLY_ACTIVATION \ | |
if(!(activation_flags & PPG_Action_Activation_Flags_Active)) { return; } | |
// User callback the emulates double tab for | |
// shell auto completion | |
// | |
void doubleTabCB(PPG_Count activation_flags, void *user_data) | |
{ | |
NG_CALLBACK_NO_REPEAT | |
NG_CALLBACK_ONLY_ACTIVATION | |
tapKey(Key_Tab); | |
tapKey(Key_Tab); | |
} | |
// User callback that repeats the most recent shell | |
// command | |
// | |
void repeatLastCommandCB(PPG_Count activation_flags, void *user_data) | |
{ | |
NG_CALLBACK_NO_REPEAT | |
NG_CALLBACK_ONLY_ACTIVATION | |
tapKey(Key_UpArrow); | |
tapKey(Key_Enter); | |
} | |
// Issues a search command that can be used with | |
// any editor that is configured in a way that F1 | |
// opens the search entry with the string that the cursor | |
// currently rests on. | |
// | |
void ordinarySearchCB(PPG_Count activation_flags, void *user_data) | |
{ | |
NG_CALLBACK_NO_REPEAT | |
NG_CALLBACK_ONLY_ACTIVATION | |
tapKey(LCTRL(Key_F)); | |
tapKey(Key_Enter); | |
} | |
// Similar the search callback above, but for a search | |
// in multiple files. This works with editors | |
// that have been customized to feature Shift+F1 | |
// as command to open the search-in-files menu. | |
// | |
void fileSearchCB(PPG_Count activation_flags, void *user_data) | |
{ | |
NG_CALLBACK_NO_REPEAT | |
NG_CALLBACK_ONLY_ACTIVATION | |
tapKey(LSHIFT(Key_F1)); | |
tapKey(Key_Enter); | |
} | |
void umlautCB(PPG_Count activation_flags, void *user_data) | |
{ | |
// NG_CALLBACK_NO_REPEAT | |
Key k; | |
k.raw = (uint16_t)user_data; | |
PPG_LOG("umlautCB\n") | |
// Note, as we might be dealing with one-shot shift, we cannot | |
// inject the keys (as one-shot does not deal with injected stuff) | |
// | |
if(activation_flags & PPG_Action_Activation_Flags_Active) { | |
handleKeyswitchEvent(RALT(k), UNKNOWN_KEYSWITCH_LOCATION, IS_PRESSED/* | INJECTED*/); | |
} | |
else { | |
PPG_LOG("releasing umlaut\n") | |
handleKeyswitchEvent(RALT(k), UNKNOWN_KEYSWITCH_LOCATION, WAS_PRESSED/* | INJECTED*/); | |
} | |
} | |
void rebootCB(PPG_Count activation_flags, void *user_data) | |
{ | |
#ifndef ARDUINO_VIRTUAL | |
KeyboardHardware.rebootBootloader(); | |
#endif | |
} | |
// TODO: Add a mode of operation where Papageno only tracks events | |
// but passes them on instead of swallowing them. | |
// TODO: Enable Glockenspiel optimization flags by default. | |
extern "C" { | |
#include "Kaleidoscope-Papageno-Sketch.hpp" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment