Merge pull request #1 from Skrymir/patch-1

add ergodox layout
master
Joshua Colbeck 2016-07-06 20:29:29 -05:00 committed by GitHub
commit e0e1c119f0
12 changed files with 505 additions and 254 deletions

View File

@ -62,7 +62,7 @@ KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~
KC_SCOLON KC_SCLN 33 Keyboard ; and : KC_SCOLON KC_SCLN 33 Keyboard ; and :
KC_QUOTE KC_QUOT 34 Keyboard and “ KC_QUOTE KC_QUOT 34 Keyboard and “
KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde
KC_COMMA KC_COMM 36 Keyboard, and < KC_COMMA KC_COMM 36 Keyboard , and <
KC_DOT 37 Keyboard . and > KC_DOT 37 Keyboard . and >
KC_SLASH KC_SLSH 38 Keyboard / and ? KC_SLASH KC_SLSH 38 Keyboard / and ?
KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock
@ -92,7 +92,7 @@ KC_LEFT 50 Keyboard LeftArrow1
KC_DOWN 51 Keyboard DownArrow1 KC_DOWN 51 Keyboard DownArrow1
KC_UP 52 Keyboard UpArrow1 KC_UP 52 Keyboard UpArrow1
KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11 KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11
KC_KP_SLASH KC_PSLS 54 Keypad /1 KC_KP_SLASH KC_PSLS 54 Keypad /
KC_KP_ASTERISK KC_PAST 55 Keypad * KC_KP_ASTERISK KC_PAST 55 Keypad *
KC_KP_MINUS KC_PMNS 56 Keypad - KC_KP_MINUS KC_PMNS 56 Keypad -
KC_KP_PLUS KC_PPLS 57 Keypad + KC_KP_PLUS KC_PPLS 57 Keypad +

View File

@ -27,7 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DEVICE_VER 0x0001 #define DEVICE_VER 0x0001
#define MANUFACTURER ErgoDox EZ #define MANUFACTURER ErgoDox EZ
#define PRODUCT ErgoDox EZ #define PRODUCT ErgoDox EZ
#define DESCRIPTION t.m.k. keyboard firmware for Ergodox #define DESCRIPTION QMK keyboard firmware for Ergodox EZ
/* key matrix size */ /* key matrix size */
#define MATRIX_ROWS 14 #define MATRIX_ROWS 14
@ -40,12 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TAPPING_TOGGLE 1 #define TAPPING_TOGGLE 1
#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
#define ROWS (int []){ D0, D5, B5, B6 }
/* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW
/* define if matrix has ghost */ /* define if matrix has ghost */
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST
@ -53,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BACKLIGHT_LEVELS 3 #define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 2 #define DEBOUNCE 5
#define TAPPING_TERM 200 #define TAPPING_TERM 200
#define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.) #define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.)

View File

@ -0,0 +1,205 @@
#include "ergodox_ez.h"
#include "debug.h"
#include "action_layer.h"
#define BASE 0 // default layer
#define SYMB 1 // symbols
#define MDIA 2 // media keys
//macros
#define CTL_SFT_T 100
#define CTL_SFT_G 101
#define CTL_ALT_H 102
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Basic layer
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | = | 1 | 2 | 3 | 4 | 5 | ESC | | M 100| 6 | 7 | 8 | 9 | 0 | - |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* |TAB /Alt| Q | W | E | R | T | Meh | | Meh | Y | U | I | O | P |\ / ALT |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | LCTL | A | S | D | F | G |------| |------| H | J | K | L |; / L2|' / CTL |
* |--------+------+------+------+------+------| ~L1 | | ~L1 |------+------+------+------+------+--------|
* | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | WIN | ` | M 102| M 101|AltShf| |AltShf| Left | Down | Up | Right |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | App | LALT | | Alt | CAPS |
* ,------|------|------| |------+--------+------.
* | | | Home | | PgUp | | |
* | Space|Backsp|------| |------| Delete |Enter |
* | |ace | End | | PgDn | | |
* `--------------------' `----------------------'
*/
// If it accepts an argument (i.e, is a function), it doesn't need KC_.
// Otherwise, it needs KC_*
[BASE] = KEYMAP( // layer 0 : default
// left hand
KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
ALT_T(KC_TAB), KC_Q, KC_W, KC_E, KC_R, KC_T, ALL_T(KC_NO),
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, MO(SYMB),
KC_LGUI, KC_GRV, M(CTL_ALT_H),M(CTL_SFT_G),LALT(KC_LSFT),
CTL_T(KC_APP), KC_LALT,
KC_HOME,
KC_SPC,KC_BSPC,KC_END,
// right hand
M(CTL_SFT_T),KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
MEH_T(KC_NO),KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),CTL_T(KC_QUOT),
MO(SYMB), KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
LALT(KC_LSFT),KC_LEFT,KC_DOWN,KC_UP, KC_RIGHT,
KC_LALT, KC_CAPS,
KC_PGUP,
KC_PGDN,KC_DEL, KC_ENT
),
/* Keymap 1: Symbol Layer
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* |Version | F1 | F2 | F3 | F4 | F5 | F11 | | F12 | F6 | F7 | F8 | F9 | F10 | CALC |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | ! | @ | { | } | | | | | | | | | | | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | # | $ | ( | ) | ` |------| |------| Left | Down | Up | Right| | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | % | ^ | [ | ] | ~ | | | | | | | | | |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | | | | | | | | | | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*/
// SYMBOLS
[SYMB] = KEYMAP(
// left hand
M(0), KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F11,
KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,
KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,
// right hand
KC_F12, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_CALC,
KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_LEFT, KC_DOWN,KC_UP, KC_RIGHT,KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
/* Keymap 2: Media and mouse keys
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | | | | | | | | | | | | | | | |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | | | MsUp | | | | | | | | | | | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | | | | | | | | | | | Prev | Next | | |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | |Brwser|
* | | |------| |------| |Back |
* | | | | | | | |
* `--------------------' `--------------------'
*/
// MEDIA AND MOUSE
[MDIA] = KEYMAP(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
// right hand
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_WBAK
),
};
const uint16_t PROGMEM fn_actions[] = {
[1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
};
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
// MACRODOWN only works in this function
switch(id) {
case 0:
if (record->event.pressed) {
SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
}
break;
case CTL_SFT_T:
if (record->event.pressed) {
return MACRO(D(LCTL), D(LSFT), T(T), END);
}
return MACRO(U(LCTL), U(LSFT), END);
break;
case CTL_SFT_G:
if (record->event.pressed) {
return MACRO(D(LCTL), D(LSFT), T(G), END);
}
return MACRO(U(LCTL), U(LSFT), END);
break;
case CTL_ALT_H:
if (record->event.pressed) {
return MACRO(D(LCTL), D(LALT), T(H), END);
}
return MACRO(U(LCTL), U(LALT), END);
break;
}
return MACRO_NONE;
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
uint8_t layer = biton32(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
switch (layer) {
// TODO: Make this relevant to the ErgoDox EZ.
case 1:
ergodox_right_led_1_on();
break;
case 2:
ergodox_right_led_2_on();
break;
default:
// none
break;
}
};

View File

@ -0,0 +1,8 @@
Layout is based on the default layout that comes on the ergodox infinity. Focused mostly on making ctl and alt easy to reach. I spend most my day working in Eclipse which has just so many 3 key shortcuts.
* Removed numpad keys from symbol layer (I don't use them)
* Added arrow keys under h, j, k, l on symbol layer. vi movement keys!
* Added a few macros for eclipse hotkeys that I used all the time
* Added calc button on symbol layer
* tap vs hold on tab and \. Gives alt, ctl and shift on both sides of the keyboard

View File

@ -27,7 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include "wait.h"
#include "action_layer.h" #include "action_layer.h"
#include "print.h" #include "print.h"
#include "debug.h" #include "debug.h"
@ -166,6 +166,7 @@ uint8_t matrix_scan(void)
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
select_row(i); select_row(i);
wait_us(30); // without this wait read unstable value.
matrix_row_t cols = read_cols(i); matrix_row_t cols = read_cols(i);
if (matrix_debouncing[i] != cols) { if (matrix_debouncing[i] != cols) {
matrix_debouncing[i] = cols; matrix_debouncing[i] = cols;
@ -179,7 +180,7 @@ uint8_t matrix_scan(void)
if (debouncing) { if (debouncing) {
if (--debouncing) { if (--debouncing) {
_delay_ms(1); wait_us(1);
} else { } else {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i]; matrix[i] = matrix_debouncing[i];
@ -267,7 +268,6 @@ static matrix_row_t read_cols(uint8_t row)
return data; return data;
} }
} else { } else {
_delay_us(30); // without this wait read unstable value.
// read from teensy // read from teensy
return return
(PINF&(1<<0) ? 0 : (1<<0)) | (PINF&(1<<0) ? 0 : (1<<0)) |

View File

@ -197,8 +197,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#endif #endif
persistant_default_layer_set(1UL<<_QWERTY); persistant_default_layer_set(1UL<<_QWERTY);
} }
break;
return false; return false;
break;
case COLEMAK: case COLEMAK:
if (record->event.pressed) { if (record->event.pressed) {
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
@ -206,8 +206,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#endif #endif
persistant_default_layer_set(1UL<<_COLEMAK); persistant_default_layer_set(1UL<<_COLEMAK);
} }
break;
return false; return false;
break;
case DVORAK: case DVORAK:
if (record->event.pressed) { if (record->event.pressed) {
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
@ -215,8 +215,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#endif #endif
persistant_default_layer_set(1UL<<_DVORAK); persistant_default_layer_set(1UL<<_DVORAK);
} }
break;
return false; return false;
break;
case LOWER: case LOWER:
if (record->event.pressed) { if (record->event.pressed) {
layer_on(_LOWER); layer_on(_LOWER);
@ -225,8 +225,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
layer_off(_LOWER); layer_off(_LOWER);
update_tri_layer(_LOWER, _RAISE, _ADJUST); update_tri_layer(_LOWER, _RAISE, _ADJUST);
} }
break;
return false; return false;
break;
case RAISE: case RAISE:
if (record->event.pressed) { if (record->event.pressed) {
layer_on(_RAISE); layer_on(_RAISE);
@ -235,8 +235,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
layer_off(_RAISE); layer_off(_RAISE);
update_tri_layer(_LOWER, _RAISE, _ADJUST); update_tri_layer(_LOWER, _RAISE, _ADJUST);
} }
break;
return false; return false;
break;
case BACKLIT: case BACKLIT:
if (record->event.pressed) { if (record->event.pressed) {
register_code(KC_RSFT); register_code(KC_RSFT);
@ -246,8 +246,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
} else { } else {
unregister_code(KC_RSFT); unregister_code(KC_RSFT);
} }
break;
return false; return false;
break;
case PLOVER: case PLOVER:
if (record->event.pressed) { if (record->event.pressed) {
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
@ -265,8 +265,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
keymap_config.nkro = 1; keymap_config.nkro = 1;
eeconfig_update_keymap(keymap_config.raw); eeconfig_update_keymap(keymap_config.raw);
} }
break;
return false; return false;
break;
case EXT_PLV: case EXT_PLV:
if (record->event.pressed) { if (record->event.pressed) {
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
@ -274,8 +274,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#endif #endif
layer_off(_PLOVER); layer_off(_PLOVER);
} }
break;
return false; return false;
break;
} }
return true; return true;
} }

View File

@ -191,8 +191,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#endif #endif
persistant_default_layer_set(1UL<<_QWERTY); persistant_default_layer_set(1UL<<_QWERTY);
} }
break;
return false; return false;
break;
case COLEMAK: case COLEMAK:
if (record->event.pressed) { if (record->event.pressed) {
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
@ -200,8 +200,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#endif #endif
persistant_default_layer_set(1UL<<_COLEMAK); persistant_default_layer_set(1UL<<_COLEMAK);
} }
break;
return false; return false;
break;
case DVORAK: case DVORAK:
if (record->event.pressed) { if (record->event.pressed) {
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
@ -209,8 +209,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#endif #endif
persistant_default_layer_set(1UL<<_DVORAK); persistant_default_layer_set(1UL<<_DVORAK);
} }
break;
return false; return false;
break;
case LOWER: case LOWER:
if (record->event.pressed) { if (record->event.pressed) {
layer_on(_LOWER); layer_on(_LOWER);
@ -219,8 +219,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
layer_off(_LOWER); layer_off(_LOWER);
update_tri_layer(_LOWER, _RAISE, _ADJUST); update_tri_layer(_LOWER, _RAISE, _ADJUST);
} }
break;
return false; return false;
break;
case RAISE: case RAISE:
if (record->event.pressed) { if (record->event.pressed) {
layer_on(_RAISE); layer_on(_RAISE);
@ -229,8 +229,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
layer_off(_RAISE); layer_off(_RAISE);
update_tri_layer(_LOWER, _RAISE, _ADJUST); update_tri_layer(_LOWER, _RAISE, _ADJUST);
} }
break;
return false; return false;
break;
case BACKLIT: case BACKLIT:
if (record->event.pressed) { if (record->event.pressed) {
register_code(KC_RSFT); register_code(KC_RSFT);
@ -240,8 +240,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
} else { } else {
unregister_code(KC_RSFT); unregister_code(KC_RSFT);
} }
break;
return false; return false;
break;
} }
return true; return true;
}; };

View File

@ -26,32 +26,46 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "util.h" #include "util.h"
#include "matrix.h" #include "matrix.h"
#ifdef MATRIX_HAS_GHOST /* Set 0 if debouncing isn't needed */
# error "The universal matrix.c file cannot be used for this keyboard." /*
#endif * This constant define not debouncing time in msecs, but amount of matrix
* scan loops which should be made to get stable debounced results.
*
* On Ergodox matrix scan rate is relatively low, because of slow I2C.
* Now it's only 317 scans/second, or about 3.15 msec/scan.
* According to Cherry specs, debouncing time is 5 msec.
*
* And so, there is no sense to have DEBOUNCE higher than 2.
*/
#ifndef DEBOUNCING_DELAY #ifndef DEBOUNCING_DELAY
# define DEBOUNCING_DELAY 5 # define DEBOUNCING_DELAY 5
#endif #endif
static uint8_t debouncing = DEBOUNCING_DELAY;
static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
/* matrix state */
#if DIODE_DIRECTION == COL2ROW
static matrix_row_t matrix[MATRIX_ROWS];
#else
static matrix_col_t matrix[MATRIX_COLS];
#endif
static int8_t debouncing_delay = -1;
#if DIODE_DIRECTION == COL2ROW /* matrix state(1:on, 0:off) */
static void toggle_row(uint8_t row); static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t read_cols(void); static matrix_row_t matrix_debouncing[MATRIX_ROWS];
#else
static void toggle_col(uint8_t col); #if DIODE_DIRECTION == ROW2COL
static matrix_col_t read_rows(void); static matrix_row_t matrix_reversed[MATRIX_COLS];
static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
#endif #endif
#if MATRIX_COLS > 16
#define SHIFTER 1UL
#else
#define SHIFTER 1
#endif
static matrix_row_t read_cols(void);
static void init_cols(void);
static void unselect_rows(void);
static void select_row(uint8_t row);
__attribute__ ((weak)) __attribute__ ((weak))
void matrix_init_quantum(void) { void matrix_init_quantum(void) {
matrix_init_kb(); matrix_init_kb();
@ -80,10 +94,12 @@ __attribute__ ((weak))
void matrix_scan_user(void) { void matrix_scan_user(void) {
} }
inline
uint8_t matrix_rows(void) { uint8_t matrix_rows(void) {
return MATRIX_ROWS; return MATRIX_ROWS;
} }
inline
uint8_t matrix_cols(void) { uint8_t matrix_cols(void) {
return MATRIX_COLS; return MATRIX_COLS;
} }
@ -113,161 +129,179 @@ uint8_t matrix_cols(void) {
// } // }
void matrix_init(void) { void matrix_init(void) {
/* frees PORTF by setting the JTD bit twice within four cycles */ // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
#ifdef __AVR_ATmega32U4__ #ifdef __AVR_ATmega32U4__
MCUCR |= _BV(JTD); MCUCR |= _BV(JTD);
MCUCR |= _BV(JTD); MCUCR |= _BV(JTD);
#endif #endif
/* initializes the I/O pins */
#if DIODE_DIRECTION == COL2ROW // initialize row and col
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { unselect_rows();
/* DDRxn */ init_cols();
_SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF);
toggle_row(r); // initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
matrix_debouncing[i] = 0;
} }
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* PORTxn */
_SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
}
#else
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* DDRxn */
_SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
toggle_col(c);
}
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
/* PORTxn */
_SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF);
}
#endif
matrix_init_quantum(); matrix_init_quantum();
} }
uint8_t matrix_scan(void)
{
#if DIODE_DIRECTION == COL2ROW #if DIODE_DIRECTION == COL2ROW
uint8_t matrix_scan(void) { for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
static matrix_row_t debouncing_matrix[MATRIX_ROWS]; select_row(i);
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { wait_us(30); // without this wait read unstable value.
toggle_row(r); matrix_row_t cols = read_cols();
matrix_row_t state = read_cols(); if (matrix_debouncing[i] != cols) {
if (debouncing_matrix[r] != state) { matrix_debouncing[i] = cols;
debouncing_matrix[r] = state; if (debouncing) {
debouncing_delay = DEBOUNCING_DELAY; debug("bounce!: "); debug_hex(debouncing); debug("\n");
}
debouncing = DEBOUNCING_DELAY;
} }
toggle_row(r); unselect_rows();
} }
if (debouncing_delay >= 0) {
dprintf("Debouncing delay remaining: %X\n", debouncing_delay); if (debouncing) {
--debouncing_delay; if (--debouncing) {
if (debouncing_delay >= 0) { wait_us(1);
wait_ms(1); } else {
} for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
else { matrix[i] = matrix_debouncing[i];
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
matrix[r] = debouncing_matrix[r];
} }
} }
} }
matrix_scan_quantum();
return 1;
}
static void toggle_row(uint8_t row) {
/* PINxn */
_SFR_IO8((row_pins[row] >> 4)) = _BV(row_pins[row] & 0xF);
}
static matrix_row_t read_cols(void) {
matrix_row_t state = 0;
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* PINxn */
if (!(_SFR_IO8((col_pins[c] >> 4)) & _BV(col_pins[c] & 0xF))) {
state |= (matrix_row_t)1 << c;
}
}
return state;
}
matrix_row_t matrix_get_row(uint8_t row) {
return matrix[row];
}
#else #else
uint8_t matrix_scan(void) { for (uint8_t i = 0; i < MATRIX_COLS; i++) {
static matrix_col_t debouncing_matrix[MATRIX_COLS]; select_row(i);
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { wait_us(30); // without this wait read unstable value.
toggle_col(c); matrix_row_t rows = read_cols();
matrix_col_t state = read_rows(); if (matrix_reversed_debouncing[i] != rows) {
if (debouncing_matrix[c] != state) { matrix_reversed_debouncing[i] = rows;
debouncing_matrix[c] = state; if (debouncing) {
debouncing_delay = DEBOUNCING_DELAY; debug("bounce!: "); debug_hex(debouncing); debug("\n");
}
debouncing = DEBOUNCING_DELAY;
} }
toggle_col(c); unselect_rows();
} }
if (debouncing_delay >= 0) {
dprintf("Debouncing delay remaining: %X\n", debouncing_delay); if (debouncing) {
--debouncing_delay; if (--debouncing) {
if (debouncing_delay >= 0) { wait_us(1);
wait_ms(1); } else {
} for (uint8_t i = 0; i < MATRIX_COLS; i++) {
else { matrix_reversed[i] = matrix_reversed_debouncing[i];
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
matrix[c] = debouncing_matrix[c];
} }
} }
} }
matrix_scan_quantum(); for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
return 1; matrix_row_t row = 0;
} for (uint8_t x = 0; x < MATRIX_COLS; x++) {
row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
static void toggle_col(uint8_t col) {
/* PINxn */
_SFR_IO8((col_pins[col] >> 4)) = _BV(col_pins[col] & 0xF);
}
static matrix_col_t read_rows(void) {
matrix_col_t state = 0;
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
/* PINxn */
if (!(_SFR_IO8((row_pins[r] >> 4)) & _BV(row_pins[r] & 0xF))) {
state |= (matrix_col_t)1 << r;
} }
matrix[y] = row;
} }
return state;
}
matrix_row_t matrix_get_row(uint8_t row) {
matrix_row_t state = 0;
matrix_col_t mask = (matrix_col_t)1 << row;
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
if (matrix[c] & mask) {
state |= (matrix_row_t)1 << c;
}
}
return state;
}
#endif #endif
bool matrix_is_modified(void) { matrix_scan_quantum();
if (debouncing_delay >= 0) return false;
return 1;
}
bool matrix_is_modified(void)
{
if (debouncing) return false;
return true; return true;
} }
bool matrix_is_on(uint8_t row, uint8_t col) { inline
return matrix_get_row(row) & (matrix_row_t)1 << col; bool matrix_is_on(uint8_t row, uint8_t col)
{
return (matrix[row] & ((matrix_row_t)1<col));
} }
void matrix_print(void) { inline
dprintln("Human-readable matrix state:"); matrix_row_t matrix_get_row(uint8_t row)
for (uint8_t r = 0; r < MATRIX_ROWS; r++) { {
dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r))); return matrix[row];
}
void matrix_print(void)
{
print("\nr/c 0123456789ABCDEF\n");
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
phex(row); print(": ");
pbin_reverse16(matrix_get_row(row));
print("\n");
} }
} }
uint8_t matrix_key_count(void) { uint8_t matrix_key_count(void)
{
uint8_t count = 0; uint8_t count = 0;
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
count += bitpop16(matrix_get_row(r)); count += bitpop16(matrix[i]);
} }
return count; return count;
} }
static void init_cols(void)
{
#if DIODE_DIRECTION == COL2ROW
for(int x = 0; x < MATRIX_COLS; x++) {
int pin = col_pins[x];
#else
for(int x = 0; x < MATRIX_ROWS; x++) {
int pin = row_pins[x];
#endif
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
}
}
static matrix_row_t read_cols(void)
{
matrix_row_t result = 0;
#if DIODE_DIRECTION == COL2ROW
for(int x = 0; x < MATRIX_COLS; x++) {
int pin = col_pins[x];
#else
for(int x = 0; x < MATRIX_ROWS; x++) {
int pin = row_pins[x];
#endif
result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x);
}
return result;
}
static void unselect_rows(void)
{
#if DIODE_DIRECTION == COL2ROW
for(int x = 0; x < MATRIX_ROWS; x++) {
int pin = row_pins[x];
#else
for(int x = 0; x < MATRIX_COLS; x++) {
int pin = col_pins[x];
#endif
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
}
}
static void select_row(uint8_t row)
{
#if DIODE_DIRECTION == COL2ROW
int pin = row_pins[row];
#else
int pin = col_pins[row];
#endif
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF);
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);
}

View File

@ -114,8 +114,10 @@ bool suspend_wakeup_condition(void)
matrix_power_up(); matrix_power_up();
matrix_scan(); matrix_scan();
matrix_power_down(); matrix_power_down();
if (matrix_key_count()) return true; for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
return false; if (matrix_get_row(r)) return true;
}
return false;
} }
// run immediately after wakeup // run immediately after wakeup

View File

@ -106,13 +106,15 @@ void bootmagic(void)
} }
} }
static bool scan_keycode(uint8_t keycode) { static bool scan_keycode(uint8_t keycode)
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { {
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
matrix_row_t matrix_row = matrix_get_row(r); matrix_row_t matrix_row = matrix_get_row(r);
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { for (uint8_t c = 0; c < MATRIX_COLS; c++) {
if (matrix_row & (matrix_row_t)1 << c) { if (matrix_row & ((matrix_row_t)1<<c)) {
keypos_t key = (keypos_t){ .row = r, .col = c }; if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) {
if (keycode == keymap_key_to_keycode(0, key)) return true; return true;
}
} }
} }
} }
@ -124,4 +126,4 @@ bool bootmagic_scan_keycode(uint8_t keycode)
if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;
return scan_keycode(keycode); return scan_keycode(keycode);
} }

View File

@ -51,17 +51,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif #endif
#ifdef MATRIX_HAS_GHOST #ifdef MATRIX_HAS_GHOST
static bool is_row_ghosting(uint8_t row){ static bool has_ghost_in_row(uint8_t row)
matrix_row_t state = matrix_get_row(row); {
/* no ghosting happens when only one key in the row is pressed */ matrix_row_t matrix_row = matrix_get_row(row);
if (!(state - 1 & state)) return false; // No ghost exists when less than 2 keys are down on the row
/* ghosting occurs when two keys in the same column are pressed */ if (((matrix_row - 1) & matrix_row) == 0)
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { return false;
if (r != row && matrix_get_row(r) & state) return true;
// Ghost occurs when the row shares column line with other row
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
if (i != row && (matrix_get_row(i) & matrix_row))
return true;
} }
return false; return false;
} }
#endif #endif
__attribute__ ((weak)) __attribute__ ((weak))
@ -100,72 +103,86 @@ void keyboard_init(void) {
#endif #endif
} }
/* does routine keyboard jobs */ /*
void keyboard_task(void) { * Do keyboard routine jobs: scan mantrix, light LEDs, ...
static uint8_t led_status; * This is repeatedly called as fast as possible.
matrix_scan(); */
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { void keyboard_task(void)
static matrix_row_t previous_matrix[MATRIX_ROWS]; {
matrix_row_t state = matrix_get_row(r); static matrix_row_t matrix_prev[MATRIX_ROWS];
matrix_row_t changes = state ^ previous_matrix[r];
if (changes) {
#ifdef MATRIX_HAS_GHOST #ifdef MATRIX_HAS_GHOST
static matrix_row_t deghosting_matrix[MATRIX_ROWS]; static matrix_row_t matrix_ghost[MATRIX_ROWS];
if (is_row_ghosting(r)) { #endif
/* debugs the deghosting mechanism */ static uint8_t led_status = 0;
/* doesn't update previous_matrix until the ghosting has stopped matrix_row_t matrix_row = 0;
* in order to prevent the last key from being lost matrix_row_t matrix_change = 0;
matrix_scan();
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
matrix_row = matrix_get_row(r);
matrix_change = matrix_row ^ matrix_prev[r];
if (matrix_change) {
#ifdef MATRIX_HAS_GHOST
if (has_ghost_in_row(r)) {
/* Keep track of whether ghosted status has changed for
* debugging. But don't update matrix_prev until un-ghosted, or
* the last key would be lost.
*/ */
if (debug_matrix && deghosting_matrix[r] != state) { if (debug_matrix && matrix_ghost[r] != matrix_row) {
matrix_print(); matrix_print();
} }
deghosting_matrix[r] = state; matrix_ghost[r] = matrix_row;
continue; continue;
} }
deghosting_matrix[r] = state; matrix_ghost[r] = matrix_row;
#endif #endif
if (debug_matrix) matrix_print(); if (debug_matrix) matrix_print();
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { for (uint8_t c = 0; c < MATRIX_COLS; c++) {
matrix_row_t mask = (matrix_row_t)1 << c; if (matrix_change & ((matrix_row_t)1<<c)) {
if (changes & mask) { action_exec((keyevent_t){
keyevent_t event; .key = (keypos_t){ .row = r, .col = c },
event.key = (keypos_t){ .row = r, .col = c }; .pressed = (matrix_row & ((matrix_row_t)1<<c)),
event.pressed = state & mask; .time = (timer_read() | 1) /* time should not be 0 */
/* the time should not be 0 */ });
event.time = timer_read() | 1; // record a processed key
action_exec(event); matrix_prev[r] ^= ((matrix_row_t)1<<c);
/* records the processed key event */ // process a key per task call
previous_matrix[r] ^= mask; goto MATRIX_LOOP_END;
/* processes one key event per call */
goto event_processed;
} }
} }
} }
} }
/* sends tick events when the keyboard is idle */ // call with pseudo tick event when no real key event.
action_exec(TICK); action_exec(TICK);
event_processed:
MATRIX_LOOP_END:
#ifdef MOUSEKEY_ENABLE #ifdef MOUSEKEY_ENABLE
/* repeats and accelerates the mouse keys */ // mousekey repeat & acceleration
mousekey_task(); mousekey_task();
#endif #endif
#ifdef PS2_MOUSE_ENABLE #ifdef PS2_MOUSE_ENABLE
ps2_mouse_task(); ps2_mouse_task();
#endif #endif
#ifdef SERIAL_MOUSE_ENABLE #ifdef SERIAL_MOUSE_ENABLE
serial_mouse_task(); serial_mouse_task();
#endif #endif
#ifdef ADB_MOUSE_ENABLE #ifdef ADB_MOUSE_ENABLE
adb_mouse_task(); adb_mouse_task();
#endif #endif
/* updates the LEDs */
// update LED
if (led_status != host_keyboard_leds()) { if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds(); led_status = host_keyboard_leds();
keyboard_set_leds(led_status); keyboard_set_leds(led_status);
} }
} }
void keyboard_set_leds(uint8_t leds) { void keyboard_set_leds(uint8_t leds)
if (debug_keyboard) dprintf("Keyboard LEDs state: %x\n", leds); {
if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
led_set(leds); led_set(leds);
} }

View File

@ -20,59 +20,48 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#if MATRIX_COLS <= 8
typedef uint8_t matrix_row_t; #if (MATRIX_COLS <= 8)
#elif MATRIX_COLS <= 16 typedef uint8_t matrix_row_t;
typedef uint16_t matrix_row_t; #elif (MATRIX_COLS <= 16)
#elif MATRIX_COLS <= 32 typedef uint16_t matrix_row_t;
typedef uint32_t matrix_row_t; #elif (MATRIX_COLS <= 32)
typedef uint32_t matrix_row_t;
#else #else
# error "There are too many columns." #error "MATRIX_COLS: invalid value"
#endif #endif
#if DIODE_DIRECTION == ROW2COL #define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col))
# if MATRIX_ROWS <= 8
typedef uint8_t matrix_col_t;
# elif MATRIX_ROWS <= 16
typedef uint16_t matrix_col_t;
# elif MATRIX_ROWS <= 32
typedef uint32_t matrix_col_t;
# else
# error "There are too many rows."
# endif
#endif
typedef struct {
uint8_t input_addr:4;
uint8_t bit:4;
} io_pin_t;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* counts the number of rows in the matrix */
/* number of matrix rows */
uint8_t matrix_rows(void); uint8_t matrix_rows(void);
/* counts the number of columns in the matrix */ /* number of matrix columns */
uint8_t matrix_cols(void); uint8_t matrix_cols(void);
/* sets up the matrix before matrix_init */ /* should be called at early stage of startup before matrix_init.(optional) */
void matrix_setup(void); void matrix_setup(void);
/* intializes the matrix */ /* intialize matrix for scaning. */
void matrix_init(void); void matrix_init(void);
/* scans the entire matrix */ /* scan all key states on matrix */
uint8_t matrix_scan(void); uint8_t matrix_scan(void);
/* checks if the matrix has been modified */ /* whether modified from previous scan. used after matrix_scan. */
bool matrix_is_modified(void) __attribute__ ((deprecated)); bool matrix_is_modified(void) __attribute__ ((deprecated));
/* checks if a key is pressed */ /* whether a swtich is on */
bool matrix_is_on(uint8_t row, uint8_t col); bool matrix_is_on(uint8_t row, uint8_t col);
/* inspects the state of a row in the matrix */ /* matrix state on row */
matrix_row_t matrix_get_row(uint8_t row); matrix_row_t matrix_get_row(uint8_t row);
/* prints the matrix for debugging */ /* print matrix for debug */
void matrix_print(void); void matrix_print(void);
/* counts the total number of keys pressed */
uint8_t matrix_key_count(void);
/* controls power to the matrix */ /* power control */
void matrix_power_up(void); void matrix_power_up(void);
void matrix_power_down(void); void matrix_power_down(void);
/* executes code for Quantum */ /* executes code for Quantum */
void matrix_init_quantum(void); void matrix_init_quantum(void);
void matrix_scan_quantum(void); void matrix_scan_quantum(void);