improve layer switching

This commit is contained in:
tmk 2010-10-29 15:17:18 +09:00
parent 6c3b9a2ded
commit 45d4a7a898
21 changed files with 290 additions and 229 deletions

View file

@ -50,6 +50,7 @@
# List C source files here. (C dependencies are automatically generated.) # List C source files here. (C dependencies are automatically generated.)
SRC = tmk.c \ SRC = tmk.c \
layer.c \
key_process.c \ key_process.c \
usb_keyboard.c \ usb_keyboard.c \
usb_mouse.c \ usb_mouse.c \
@ -57,6 +58,7 @@ SRC = tmk.c \
usb.c \ usb.c \
jump_bootloader.c \ jump_bootloader.c \
print.c \ print.c \
timer.c \
util.c util.c
SRC += $(TARGET_SRC) SRC += $(TARGET_SRC)

8
README
View file

@ -93,9 +93,6 @@ debouncing logic
will be coded when bouncing occurs. will be coded when bouncing occurs.
bouncing doesnt occur on my ALPS switch so far. bouncing doesnt occur on my ALPS switch so far.
scan rate is too slow?(to be measure) scan rate is too slow?(to be measure)
layer switching
time before switching
timeout when not used during specific time
Trackpoint(PS/2) Trackpoint(PS/2)
receive PS/2 signal from TrackPoint receive PS/2 signal from TrackPoint
@ -136,6 +133,9 @@ debug on/off
key print on/off key print on/off
mouse print on/off mouse print on/off
2010/10/26 2010/10/26
layer switching
time before switching
timeout when not used during specific time
2010/10/30
EOF EOF

View file

@ -6,7 +6,7 @@
#define debug(s) if(debug_enable) print(s) #define debug(s) if(debug_enable) print(s)
#define debug_hex(c) if(debug_enable) phex(c) #define debug_hex(c) if(debug_enable) phex(c)
#define debug_hex16(i) if(debug_enable) phex(i) #define debug_hex16(i) if(debug_enable) phex16(i)
#define debug_bin(c) if(debug_enable) pbin(c) #define debug_bin(c) if(debug_enable) pbin(c)
#define debug_bin_reverse(c) if(debug_enable) pbin_reverse(c) #define debug_bin_reverse(c) if(debug_enable) pbin_reverse(c)

View file

@ -3,4 +3,10 @@
#include "controller_teensy.h" #include "controller_teensy.h"
/* matrix row size */
#define MATRIX_ROWS 8
/* matrix column size */
#define MATRIX_COLS 8
#endif #endif

View file

@ -6,16 +6,13 @@
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "usb_keyboard.h" #include "usb_keyboard.h"
#include "usb_keycodes.h" #include "usb_keycodes.h"
#include "matrix.h"
#include "print.h" #include "print.h"
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include "keymap.h" #include "controller.h"
#include "keymap_skel.h"
#define FN_KEYCODE(fn) (pgm_read_byte(&fn_keycode[(fn)]))
#define FN_LAYER(fn) (pgm_read_byte(&fn_layer[(fn)]))
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
#define KEYMAP( \ #define KEYMAP( \
R3C1, R3C0, R0C0, R1C0, R1C1, R2C0, R2C1, R4C0, R4C1, R6C0, R6C1, R7C0, R7C1, R5C0, R5C1, \ R3C1, R3C0, R0C0, R1C0, R1C1, R2C0, R2C1, R4C0, R4C1, R6C0, R6C1, R7C0, R7C1, R5C0, R5C1, \
R3C2, R0C1, R0C2, R1C3, R1C2, R2C3, R2C2, R4C2, R4C3, R6C2, R6C3, R7C3, R7C2, R5C2, \ R3C2, R0C1, R0C2, R1C3, R1C2, R2C3, R2C2, R4C2, R4C3, R6C2, R6C3, R7C3, R7C2, R5C2, \
@ -34,9 +31,7 @@
{ R7C0, R7C1, R7C2, R7C3, R7C4, R7C5, R7C6, KB_NO } \ { R7C0, R7C1, R7C2, R7C3, R7C4, R7C5, R7C6, KB_NO } \
} }
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
static int current_layer = 0;
static bool layer_used = false;
/* layer to change into while Fn key pressed */ /* layer to change into while Fn key pressed */
@ -153,76 +148,22 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
}; };
uint8_t keymap_get_keycode(int row, int col) uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
{ {
return keymap_get_keycodel(current_layer, row, col); return KEYCODE(layer, row, col);
} }
uint8_t keymap_get_keycodel(int layer, int row, int col) int keymap_fn_layer(uint8_t fn_bits)
{ {
uint8_t code = KEYCODE(layer, row, col); return pgm_read_byte(&fn_layer[biton(fn_bits)]);
// normal key or mouse key
if (IS_KEY(code) || IS_MOUSE(code))
layer_used = true;
return code;
} }
inline uint8_t keymap_fn_keycode(uint8_t fn_bits)
int keymap_get_layer(void)
{ {
return current_layer; return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
} }
inline
int keymap_set_layer(int layer)
{
current_layer = layer;
return current_layer;
}
inline
bool keymap_is_special_mode(uint8_t fn_bits) bool keymap_is_special_mode(uint8_t fn_bits)
{ {
return (keyboard_modifier_keys == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI)); return (keyboard_modifier_keys == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));
} }
void keymap_fn_proc(uint8_t fn_bits)
{
// layer switching
static uint8_t last_bits = 0;
static uint8_t last_mod = 0;
if (usb_keyboard_has_key() || fn_bits == last_bits) {
// do nothing during press other than Fn key
return;
} else if (fn_bits == 0) {
// send key when Fn key is released without using the layer
if (!layer_used) {
uint8_t code = FN_KEYCODE(biton(last_bits));
if (code != KB_NO) {
if (IS_MOD(code)) {
keyboard_modifier_keys = last_mod | 1<<(code & 0x07);
} else {
keyboard_keys[0] = code;
keyboard_modifier_keys = last_mod;
}
usb_keyboard_send();
usb_keyboard_print();
usb_keyboard_clear();
}
}
last_bits = 0;
last_mod = 0;
layer_used = false;
keymap_set_layer(0); // default layer
} else if ((fn_bits & (fn_bits - 1)) == 0) {
// switch layer when just one Fn Key is pressed
last_bits = fn_bits;
last_mod = keyboard_modifier_keys;
layer_used = false;
keymap_set_layer(FN_LAYER(biton(fn_bits)));
debug("layer: "); phex(current_layer); debug("(");
debug_bin(last_bits); debug(")\n");
debug("last_mod: "); debug_hex(last_mod); debug("\n");
}
}

View file

@ -1,7 +0,0 @@
#ifndef KEYMAP_H
#define KEYMAP_H 1
#include "usb_keycodes.h"
#include "keymap_skel.h"
#endif

View file

@ -5,9 +5,10 @@
#include <stdbool.h> #include <stdbool.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include <util/delay.h>
#include "matrix.h"
#include "print.h" #include "print.h"
#include "util.h" #include "util.h"
#include "controller.h"
#include "matrix_skel.h"
// matrix is active low. (key on: 0/key off: 1) // matrix is active low. (key on: 0/key off: 1)
// //
@ -27,8 +28,8 @@
#define KEY_ON ((PINE&(1<<6)) ? false : true) #define KEY_ON ((PINE&(1<<6)) ? false : true)
// matrix state buffer // matrix state buffer
uint8_t *matrix; static uint8_t *matrix;
uint8_t *matrix_prev; static uint8_t *matrix_prev;
static uint8_t _matrix0[MATRIX_ROWS]; static uint8_t _matrix0[MATRIX_ROWS];
static uint8_t _matrix1[MATRIX_ROWS]; static uint8_t _matrix1[MATRIX_ROWS];

View file

@ -1,15 +0,0 @@
#ifndef MATRIX_H
#define MATRIX_H 1
#include <stdbool.h>
#include "matrix_skel.h"
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
extern uint8_t *matrix;
extern uint8_t *matrix_prev;
#endif

View file

@ -1,17 +1,18 @@
#include <stdbool.h> #include <stdbool.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "timer.h"
#include "util.h"
#include "jump_bootloader.h"
#include "usb_keyboard.h" #include "usb_keyboard.h"
#include "usb_mouse.h" #include "usb_mouse.h"
#include "usb_keycodes.h" #include "usb_keycodes.h"
#include "print.h" #include "layer.h"
#include "debug.h"
#include "util.h"
#include "jump_bootloader.h"
#include "matrix_skel.h" #include "matrix_skel.h"
#include "keymap_skel.h" #include "keymap_skel.h"
#include "controller.h" #include "controller.h"
#include "key_process.h" #include "key_process.h"
@ -61,7 +62,7 @@ void proc_matrix(void) {
for (int col = 0; col < matrix_cols(); col++) { for (int col = 0; col < matrix_cols(); col++) {
if (!matrix_is_on(row, col)) continue; if (!matrix_is_on(row, col)) continue;
uint8_t code = keymap_get_keycode(row, col); uint8_t code = layer_get_keycode(row, col);
if (code == KB_NO) { if (code == KB_NO) {
// do nothing // do nothing
} else if (IS_MOD(code)) { } else if (IS_MOD(code)) {
@ -95,12 +96,25 @@ void proc_matrix(void) {
} }
} }
} }
keymap_fn_proc(fn_bits); layer_switching(fn_bits);
// when 4 left modifier keys down // when 4 left modifier keys down
if (keymap_is_special_mode(fn_bits)) { if (keymap_is_special_mode(fn_bits)) {
switch (keyboard_keys[0]) { switch (keyboard_keys[0]) {
case KB_B: // bootloader case KB_H: // help
print_enable = true;
print("b: jump to bootloader\n");
print("d: debug print toggle\n");
print("k: keyboard debug toggle\n");
print("m: mouse debug toggle\n");
print("x: matrix debug toggle\n");
print("v: print version\n");
print("t: print timer count\n");
print("p: print enable toggle\n");
_delay_ms(500);
print_enable = false;
break;
case KB_B: // bootloader
usb_keyboard_clear(); usb_keyboard_clear();
usb_keyboard_send(); usb_keyboard_send();
print_enable = true; print_enable = true;
@ -113,8 +127,8 @@ void proc_matrix(void) {
usb_keyboard_send(); usb_keyboard_send();
debug_enable = !debug_enable; debug_enable = !debug_enable;
if (debug_enable) { if (debug_enable) {
print("debug enabled.\n");
print_enable = true; print_enable = true;
print("debug enabled.\n");
debug_matrix = true; debug_matrix = true;
debug_keyboard = true; debug_keyboard = true;
debug_mouse = true; debug_mouse = true;
@ -160,9 +174,29 @@ void proc_matrix(void) {
case KB_V: // print version & information case KB_V: // print version & information
usb_keyboard_clear(); usb_keyboard_clear();
usb_keyboard_send(); usb_keyboard_send();
print_enable = true;
print(STR(DESCRIPTION) "\n"); print(STR(DESCRIPTION) "\n");
_delay_ms(1000); _delay_ms(1000);
break; break;
case KB_T: // print timer
usb_keyboard_clear();
usb_keyboard_send();
print_enable = true;
print("timer: "); phex16(timer_count); print("\n");
_delay_ms(500);
break;
case KB_P: // print toggle
usb_keyboard_clear();
usb_keyboard_send();
if (print_enable) {
print("print disabled.\n");
print_enable = false;
} else {
print_enable = true;
print("print enabled.\n");
}
_delay_ms(1000);
break;
} }
} }

View file

@ -6,13 +6,16 @@
#include "usb_keycodes.h" #include "usb_keycodes.h"
uint8_t keymap_get_keycode(int row, int col); /* keycode in specific layer */
uint8_t keymap_get_keycodel(int layer, int row, int col); uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
int keymap_get_layer(void);
int keymap_set_layer(int layer);
/* layer to move during press Fn key */
int keymap_fn_layer(uint8_t fn_bits);
/* keycode to send when release Fn key without using */
uint8_t keymap_fn_keycode(uint8_t fn_bits);
/* whether special key combination */
bool keymap_is_special_mode(uint8_t fn_bits); bool keymap_is_special_mode(uint8_t fn_bits);
/* process Fn keys. This.should be called every scan. */
void keymap_fn_proc(uint8_t fn_bits);
#endif #endif

92
layer.c Normal file
View file

@ -0,0 +1,92 @@
#include "keymap_skel.h"
#include "usb_keyboard.h"
#include "debug.h"
#include "timer.h"
#include "layer.h"
/*
* LAYER_ENTER_DELAY: prevent from moving new layer
* press release
* Fn key sate ____|~~~~~~~~~~~~~~~~~~~|_______________
*
* enter_delay |======|
* new layer
* Layer sw ___________|~~~~~~~~~~~~|_______________
*/
#define LAYER_ENTER_DELAY 10
/*
* LAYER_SEND_FN_TERM: send keycode if release key in this term
* press release(send)
* Fn key state ____|~~~~~~~~~~~~~|_______________
* press | release(not send)
* Fn key state ____|~~~~~~~~~~~~~|~~~~~~|__________
* | |
* send_fn_term |=============o==| x
*/
#define LAYER_SEND_FN_TERM 30
static uint8_t current_layer = 0;
static bool layer_used = false;
uint8_t layer_get_keycode(uint8_t row, uint8_t col)
{
uint8_t code = keymap_get_keycode(current_layer, row, col);
// normal key or mouse key
if ((IS_KEY(code) || IS_MOUSE(code)))
layer_used = true;
return code;
}
void layer_switching(uint8_t fn_bits)
{
// layer switching
static uint8_t last_bits = 0;
static uint8_t last_mod = 0;
static uint16_t last_timer = 0;
//uint16_t now_timer;
if (fn_bits == last_bits) {
// switch layer when specific time elapsed
if (current_layer != keymap_fn_layer(fn_bits) &&
timer_elapsed(last_timer) > LAYER_ENTER_DELAY) {
current_layer = keymap_fn_layer(fn_bits);
debug("time_elapsed: "); debug_hex16(timer_elapsed(last_timer)); debug("\n");
debug("switch layer: "); debug_hex(current_layer); debug("\n");
}
} else if (fn_bits == 0) {
// send key when Fn key is released without using the layer and within specific time
if ((!layer_used || current_layer != keymap_fn_layer(last_bits)) &&
timer_elapsed(last_timer) < LAYER_SEND_FN_TERM) {
uint8_t code = keymap_fn_keycode(last_bits);
if (code != KB_NO) {
if (IS_MOD(code)) {
keyboard_modifier_keys = last_mod | MOD_BIT(code);
} else {
keyboard_keys[0] = code;
keyboard_modifier_keys = last_mod;
}
usb_keyboard_send();
usb_keyboard_print();
usb_keyboard_clear();
}
}
last_bits = 0;
last_mod = 0;
layer_used = false;
current_layer = 0; // default layer
} else if ((fn_bits & (fn_bits - 1)) == 0) {
// switch layer when just one Fn Key is pressed
if (!usb_keyboard_has_key()) {
last_bits = fn_bits;
last_mod = keyboard_modifier_keys;
last_timer = timer_read();
debug("last_bits: "); debug_bin(last_bits); debug("\n");
debug("last_mod: "); debug_hex(last_mod); debug("\n");
debug("last_timer: "); debug_hex16(last_timer); debug("\n");
}
}
}

13
layer.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef LAYER_H
#define LAYER_H 1
#include <stdint.h>
/* return keycode for switch */
uint8_t layer_get_keycode(uint8_t row, uint8_t col);
/* process layer switching */
void layer_switching(uint8_t fn_bits);
#endif

View file

@ -3,4 +3,10 @@
#include "controller_teensy.h" #include "controller_teensy.h"
/* matrix row size */
#define MATRIX_ROWS 9
/* matrix column size */
#define MATRIX_COLS 8
#endif #endif

View file

@ -4,18 +4,16 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "usb_keyboard.h" #include "usb_keyboard.h"
#include "usb_keycodes.h" #include "usb_keycodes.h"
#include "matrix.h"
#include "print.h" #include "print.h"
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include "keymap.h" #include "controller.h"
#include "keymap_skel.h"
#define FN_KEYCODE(fn) (pgm_read_byte(&fn_keycode[(fn)]))
#define FN_LAYER(fn) (pgm_read_byte(&fn_layer[(fn)]))
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
#define KEYMAP( \ #define KEYMAP( \
R1C1, R1C0, R2C0, R3C0, R4C0, R4C1, R5C1, R5C0, R6C0, R7C0, R8C0, R8C1, R6C1, R0C2, \ R1C1, R1C0, R2C0, R3C0, R4C0, R4C1, R5C1, R5C0, R6C0, R7C0, R8C0, R8C1, R6C1, R0C2, \
R1C2, R1C3, R2C3, R3C3, R4C3, R4C2, R5C2, R5C3, R6C3, R7C3, R8C3, R8C2, R6C2, \ R1C2, R1C3, R2C3, R3C3, R4C3, R4C2, R5C2, R5C3, R6C3, R7C3, R8C3, R8C2, R6C2, \
@ -34,14 +32,11 @@
{ R8C0, R8C1, R8C2, R8C3, R8C4, R8C5, KB_NO, R8C7 } \ { R8C0, R8C1, R8C2, R8C3, R8C4, R8C5, KB_NO, R8C7 } \
} }
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
static int current_layer = 0;
static bool layer_used = false;
/* layer to change into while Fn key pressed */ static const uint8_t PROGMEM fn_layer[] = { 0, 1, 2, 3, 4, 0, 2, 3 };
static const int PROGMEM fn_layer[] = { 0, 1, 2, 3, 4, 0, 2, 3 };
/* keycode to sent when Fn key released without using layer keys. */
static const uint8_t PROGMEM fn_keycode[] = { static const uint8_t PROGMEM fn_keycode[] = {
KB_NO, // FN_0 [NOT USED] KB_NO, // FN_0 [NOT USED]
KB_NO, // FN_1 layer 1 KB_NO, // FN_1 layer 1
@ -73,6 +68,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, KB_SLSH,KB_RSFT,FN_1, \ KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, KB_SLSH,KB_RSFT,FN_1, \
FN_7, KB_LGUI,KB_LALT,KB_SPC, FN_6, KB_BSLS,KB_GRV, KB_NO, KB_NO), FN_7, KB_LGUI,KB_LALT,KB_SPC, FN_6, KB_BSLS,KB_GRV, KB_NO, KB_NO),
/* Layer 1: HHKB mode (HHKB Fn) /* Layer 1: HHKB mode (HHKB Fn)
* ,-----------------------------------------------------------. * ,-----------------------------------------------------------.
* |Pow| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | * |Pow| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
@ -92,6 +88,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KP_PLUS,KP_MINS,KB_END, KB_PGDN,KB_DOWN,KB_RSFT,FN_1, \ KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KP_PLUS,KP_MINS,KB_END, KB_PGDN,KB_DOWN,KB_RSFT,FN_1, \
KB_NO, KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_NO, KB_NO, KB_NO, KB_NO), KB_NO, KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_NO, KB_NO, KB_NO, KB_NO),
/* Layer 2: Vi mode (Quote/Rmeta) /* Layer 2: Vi mode (Quote/Rmeta)
* ,-----------------------------------------------------------. * ,-----------------------------------------------------------.
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| ` | * | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| ` |
@ -111,6 +108,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_RSFT,KB_NO, \ KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_RSFT,KB_NO, \
KB_NO, KB_LGUI,KB_LALT,KB_SPC, FN_6, KB_NO, KB_NO, KB_NO, KB_NO), KB_NO, KB_LGUI,KB_LALT,KB_SPC, FN_6, KB_NO, KB_NO, KB_NO, KB_NO),
/* Layer 3: Mouse mode (Semicolon) /* Layer 3: Mouse mode (Semicolon)
* ,-------------------------------------------------------- --. * ,-------------------------------------------------------- --.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
@ -131,6 +129,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KB_LSFT,KB_NO, MS_DOWN,KB_NO, KB_NO, KB_NO, MS_BTN2,MS_BTN1,MS_BTN2,MS_BTN3,KB_NO, KB_RSFT,KB_NO, \ KB_LSFT,KB_NO, MS_DOWN,KB_NO, KB_NO, KB_NO, MS_BTN2,MS_BTN1,MS_BTN2,MS_BTN3,KB_NO, KB_RSFT,KB_NO, \
FN_7, KB_LGUI,KB_LALT,MS_BTN1,KB_RALT,KB_NO, KB_NO, KB_NO, KB_NO), FN_7, KB_LGUI,KB_LALT,MS_BTN1,KB_RALT,KB_NO, KB_NO, KB_NO, KB_NO),
/* Layer 4: Matias half keyboard style (Space) /* Layer 4: Matias half keyboard style (Space)
* ,-----------------------------------------------------------. * ,-----------------------------------------------------------.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
@ -152,76 +151,22 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
}; };
uint8_t keymap_get_keycode(int row, int col) uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
{ {
return keymap_get_keycodel(current_layer, row, col); return KEYCODE(layer, row, col);
} }
uint8_t keymap_get_keycodel(int layer, int row, int col) int keymap_fn_layer(uint8_t fn_bits)
{ {
uint8_t code = KEYCODE(layer, row, col); return pgm_read_byte(&fn_layer[biton(fn_bits)]);
// normal key or mouse key
if (IS_KEY(code) || IS_MOUSE(code))
layer_used = true;
return code;
} }
inline uint8_t keymap_fn_keycode(uint8_t fn_bits)
int keymap_get_layer(void)
{ {
return current_layer; return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
} }
inline
int keymap_set_layer(int layer)
{
current_layer = layer;
return current_layer;
}
inline
bool keymap_is_special_mode(uint8_t fn_bits) bool keymap_is_special_mode(uint8_t fn_bits)
{ {
return (keyboard_modifier_keys == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI)); return (keyboard_modifier_keys == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));
} }
void keymap_fn_proc(uint8_t fn_bits)
{
// layer switching
static int last_bits = 0;
static uint8_t last_mod = 0;
if (usb_keyboard_has_key() || fn_bits == last_bits) {
// do nothing during press other than Fn key
return;
} else if (fn_bits == 0) {
// send key when Fn key is released without using the layer
if (!layer_used) {
uint8_t code = FN_KEYCODE(biton(last_bits));
if (code != KB_NO) {
if (IS_MOD(code)) {
keyboard_modifier_keys = last_mod | 1<<(code & 0x07);
} else {
keyboard_keys[0] = code;
keyboard_modifier_keys = last_mod;
}
usb_keyboard_send();
usb_keyboard_print();
usb_keyboard_clear();
}
}
last_bits = 0;
last_mod = 0;
layer_used = false;
keymap_set_layer(0); // default layer
} else if ((fn_bits & (fn_bits - 1)) == 0) {
// switch layer when just one Fn Key is pressed
last_bits = fn_bits;
last_mod = keyboard_modifier_keys;
layer_used = false;
keymap_set_layer(FN_LAYER(biton(fn_bits)));
debug("layer: "); phex(current_layer); debug("(");
debug_bin(last_bits); debug(")\n");
debug("last_mod: "); debug_hex(last_mod); debug("\n");
}
}

View file

@ -1,7 +0,0 @@
#ifndef KEYMAP_H
#define KEYMAP_H 1
#include "usb_keycodes.h"
#include "keymap_skel.h"
#endif

View file

@ -5,9 +5,10 @@
#include <stdbool.h> #include <stdbool.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include <util/delay.h>
#include "matrix.h"
#include "print.h" #include "print.h"
#include "util.h" #include "util.h"
#include "controller.h"
#include "matrix_skel.h"
// matrix is active low. (key on: 0/key off: 1) // matrix is active low. (key on: 0/key off: 1)
// row: Hi-Z(unselected)/low output(selected) // row: Hi-Z(unselected)/low output(selected)
@ -16,8 +17,8 @@
// PB0-PB7 // PB0-PB7
// matrix state buffer // matrix state buffer
uint8_t *matrix; static uint8_t *matrix;
uint8_t *matrix_prev; static uint8_t *matrix_prev;
static uint8_t _matrix0[MATRIX_ROWS]; static uint8_t _matrix0[MATRIX_ROWS];
static uint8_t _matrix1[MATRIX_ROWS]; static uint8_t _matrix1[MATRIX_ROWS];

View file

@ -1,15 +0,0 @@
#ifndef MATRIX_H
#define MATRIX_H 1
#include <stdint.h>
#include "matrix_skel.h"
#define MATRIX_ROWS 9
#define MATRIX_COLS 8
extern uint8_t *matrix;
extern uint8_t *matrix_prev;
#endif

View file

@ -1,5 +1,5 @@
#ifndef MATRIX_SKEL_H #ifndef MATRIX_SKEL_H
#define MATRIX_SKEL_H 1 #define MATRIX_SKEL_H 1
#include <stdbool.h> #include <stdbool.h>

61
timer.c Normal file
View file

@ -0,0 +1,61 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include "timer.h"
uint16_t timer_count = 0;
// Configure timer 0 to generate a timer overflow interrupt every
// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
// This demonstrates how to use interrupts to implement a simple
// inactivity timeout.
void timer_init(void)
{
TCCR0A = 0x00;
TCCR0B = 0x05;
TIMSK0 = (1<<TOIE0);
}
inline
void timer_clear(void)
{
cli();
timer_count = 0;
sei();
}
inline
uint16_t timer_read(void)
{
uint8_t _sreg = SREG;
uint16_t t;
cli();
t = timer_count;
SREG = _sreg;
return t;
}
inline
uint16_t timer_elapsed(uint16_t last)
{
uint8_t _sreg = SREG;
uint16_t t;
cli();
t = timer_count;
SREG = _sreg;
return TIMER_DIFF(t, last);
}
// This interrupt routine is run approx 61 times per second.
// A very simple inactivity timeout is implemented, where we
// will send a space character and print a message to the
// hid_listen debug message window.
ISR(TIMER0_OVF_vect)
{
timer_count++;
}

17
timer.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef TIMER_H
#define TIMER_H 1
#include <stdint.h>
#define TIMER_DIFF(a, b) ((a) >= (b) ? (a) - (b) : UINT16_MAX - (b) + (a))
extern uint16_t timer_count;
void timer_init(void);
void timer_clear(void);
uint16_t timer_read(void);
uint16_t timer_elapsed(uint16_t last);
#endif

23
tmk.c
View file

@ -35,17 +35,17 @@
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include "controller.h" #include "controller.h"
#include "timer.h"
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
bool debug_enable = false; bool debug_enable = false;
bool debug_matrix = false; bool debug_matrix = false;
bool debug_keyboard = false; bool debug_keyboard = false;
bool debug_mouse = false; bool debug_mouse = false;
uint16_t idle_count=0;
int main(void) int main(void)
{ {
@ -58,14 +58,7 @@ int main(void)
usb_init(); usb_init();
while (!usb_configured()) /* wait */ ; while (!usb_configured()) /* wait */ ;
// Configure timer 0 to generate a timer overflow interrupt every timer_init();
// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
// This demonstrates how to use interrupts to implement a simple
// inactivity timeout.
TCCR0A = 0x00;
TCCR0B = 0x05;
TIMSK0 = (1<<TOIE0);
matrix_init(); matrix_init();
matrix_scan(); matrix_scan();
@ -97,13 +90,3 @@ int main(void)
_delay_ms(2); _delay_ms(2);
} }
} }
// This interrupt routine is run approx 61 times per second.
// A very simple inactivity timeout is implemented, where we
// will send a space character and print a message to the
// hid_listen debug message window.
ISR(TIMER0_OVF_vect)
{
idle_count++;
}