$(COMMON_DIR)/print.c \ | $(COMMON_DIR)/print.c \ | ||||
$(COMMON_DIR)/bootloader.c \ | $(COMMON_DIR)/bootloader.c \ | ||||
$(COMMON_DIR)/suspend.c \ | $(COMMON_DIR)/suspend.c \ | ||||
$(COMMON_DIR)/xprintf.S \ | |||||
$(COMMON_DIR)/avr/xprintf.S \ | |||||
$(COMMON_DIR)/util.c | $(COMMON_DIR)/util.c | ||||
#endif | #endif | ||||
} | } | ||||
bool is_tap_key(key_t key) | |||||
bool is_tap_key(keypos_t key) | |||||
{ | { | ||||
action_t action = layer_switch_get_action(key); | action_t action = layer_switch_get_action(key); | ||||
#include "action_macro.h" | #include "action_macro.h" | ||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/* tapping count and state */ | /* tapping count and state */ | ||||
typedef struct { | typedef struct { | ||||
bool interrupted :1; | bool interrupted :1; | ||||
#endif | #endif | ||||
} keyrecord_t; | } keyrecord_t; | ||||
/* Execute action per keyevent */ | /* Execute action per keyevent */ | ||||
void action_exec(keyevent_t event); | void action_exec(keyevent_t event); | ||||
/* action for key */ | /* action for key */ | ||||
action_t action_for_key(uint8_t layer, key_t key); | |||||
action_t action_for_key(uint8_t layer, keypos_t key); | |||||
/* macro */ | /* macro */ | ||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); | const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); | ||||
void clear_keyboard(void); | void clear_keyboard(void); | ||||
void clear_keyboard_but_mods(void); | void clear_keyboard_but_mods(void); | ||||
void layer_switch(uint8_t new_layer); | void layer_switch(uint8_t new_layer); | ||||
bool is_tap_key(key_t key); | |||||
bool is_tap_key(keypos_t key); | |||||
/* debug */ | /* debug */ | ||||
void debug_event(keyevent_t event); | void debug_event(keyevent_t event); | ||||
void debug_record(keyrecord_t record); | void debug_record(keyrecord_t record); | ||||
void debug_action(action_t action); | void debug_action(action_t action); | ||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* ACTION_H */ | #endif /* ACTION_H */ |
action_t layer_switch_get_action(key_t key) | |||||
action_t layer_switch_get_action(keypos_t key) | |||||
{ | { | ||||
action_t action; | action_t action; | ||||
action.code = ACTION_TRANSPARENT; | action.code = ACTION_TRANSPARENT; |
/* return action depending on current layer status */ | /* return action depending on current layer status */ | ||||
action_t layer_switch_get_action(key_t key); | |||||
action_t layer_switch_get_action(keypos_t key); | |||||
#endif | #endif |
You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | ||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include <util/delay.h> | |||||
#include "action.h" | #include "action.h" | ||||
#include "action_util.h" | #include "action_util.h" | ||||
#include "action_macro.h" | #include "action_macro.h" | ||||
#include "wait.h" | |||||
#ifdef DEBUG_ACTION | #ifdef DEBUG_ACTION | ||||
#include "debug.h" | #include "debug.h" | ||||
#ifndef NO_ACTION_MACRO | #ifndef NO_ACTION_MACRO | ||||
#define MACRO_READ() (macro = pgm_read_byte(macro_p++)) | |||||
#define MACRO_READ() (macro = MACRO_GET(macro_p++)) | |||||
void action_macro_play(const macro_t *macro_p) | void action_macro_play(const macro_t *macro_p) | ||||
{ | { | ||||
macro_t macro = END; | macro_t macro = END; | ||||
case WAIT: | case WAIT: | ||||
MACRO_READ(); | MACRO_READ(); | ||||
dprintf("WAIT(%u)\n", macro); | dprintf("WAIT(%u)\n", macro); | ||||
{ uint8_t ms = macro; while (ms--) _delay_ms(1); } | |||||
{ uint8_t ms = macro; while (ms--) wait_ms(1); } | |||||
break; | break; | ||||
case INTERVAL: | case INTERVAL: | ||||
interval = MACRO_READ(); | interval = MACRO_READ(); | ||||
return; | return; | ||||
} | } | ||||
// interval | // interval | ||||
{ uint8_t ms = interval; while (ms--) _delay_ms(1); } | |||||
{ uint8_t ms = interval; while (ms--) wait_ms(1); } | |||||
} | } | ||||
} | } | ||||
#endif | #endif |
#ifndef ACTION_MACRO_H | #ifndef ACTION_MACRO_H | ||||
#define ACTION_MACRO_H | #define ACTION_MACRO_H | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <avr/pgmspace.h> | |||||
#include "progmem.h" | |||||
#define MACRO_NONE 0 | |||||
#define MACRO(...) ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; }) | |||||
#define MACRO_NONE 0 | |||||
#define MACRO(...) ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; }) | |||||
#define MACRO_GET(p) pgm_read_byte(p) | |||||
typedef uint8_t macro_t; | typedef uint8_t macro_t; | ||||
static uint8_t weak_mods = 0; | static uint8_t weak_mods = 0; | ||||
#ifdef USB_6KRO_ENABLE | #ifdef USB_6KRO_ENABLE | ||||
#define RO_ADD(a, b) ((a + b) % REPORT_KEYS) | |||||
#define RO_SUB(a, b) ((a - b + REPORT_KEYS) % REPORT_KEYS) | |||||
#define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) | |||||
#define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) | |||||
#define RO_INC(a) RO_ADD(a, 1) | #define RO_INC(a) RO_ADD(a, 1) | ||||
#define RO_DEC(a) RO_SUB(a, 1) | #define RO_DEC(a) RO_SUB(a, 1) | ||||
static int8_t cb_head = 0; | static int8_t cb_head = 0; | ||||
void clear_keys(void) | void clear_keys(void) | ||||
{ | { | ||||
// not clear mods | // not clear mods | ||||
for (int8_t i = 1; i < REPORT_SIZE; i++) { | |||||
for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) { | |||||
keyboard_report->raw[i] = 0; | keyboard_report->raw[i] = 0; | ||||
} | } | ||||
} | } | ||||
uint8_t has_anykey(void) | uint8_t has_anykey(void) | ||||
{ | { | ||||
uint8_t cnt = 0; | uint8_t cnt = 0; | ||||
for (uint8_t i = 1; i < REPORT_SIZE; i++) { | |||||
for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) { | |||||
if (keyboard_report->raw[i]) | if (keyboard_report->raw[i]) | ||||
cnt++; | cnt++; | ||||
} | } | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | if (keyboard_nkro) { | ||||
uint8_t i = 0; | uint8_t i = 0; | ||||
for (; i < REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | |||||
for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | |||||
; | ; | ||||
return i<<3 | biton(keyboard_report->nkro.bits[i]); | return i<<3 | biton(keyboard_report->nkro.bits[i]); | ||||
} | } | ||||
#else | #else | ||||
int8_t i = 0; | int8_t i = 0; | ||||
int8_t empty = -1; | int8_t empty = -1; | ||||
for (; i < REPORT_KEYS; i++) { | |||||
for (; i < KEYBOARD_REPORT_KEYS; i++) { | |||||
if (keyboard_report->keys[i] == code) { | if (keyboard_report->keys[i] == code) { | ||||
break; | break; | ||||
} | } | ||||
empty = i; | empty = i; | ||||
} | } | ||||
} | } | ||||
if (i == REPORT_KEYS) { | |||||
if (i == KEYBOARD_REPORT_KEYS) { | |||||
if (empty != -1) { | if (empty != -1) { | ||||
keyboard_report->keys[empty] = code; | keyboard_report->keys[empty] = code; | ||||
} | } | ||||
} while (i != cb_tail); | } while (i != cb_tail); | ||||
} | } | ||||
#else | #else | ||||
for (uint8_t i = 0; i < REPORT_KEYS; i++) { | |||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | |||||
if (keyboard_report->keys[i] == code) { | if (keyboard_report->keys[i] == code) { | ||||
keyboard_report->keys[i] = 0; | keyboard_report->keys[i] = 0; | ||||
} | } | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
static inline void add_key_bit(uint8_t code) | static inline void add_key_bit(uint8_t code) | ||||
{ | { | ||||
if ((code>>3) < REPORT_BITS) { | |||||
if ((code>>3) < KEYBOARD_REPORT_BITS) { | |||||
keyboard_report->nkro.bits[code>>3] |= 1<<(code&7); | keyboard_report->nkro.bits[code>>3] |= 1<<(code&7); | ||||
} else { | } else { | ||||
dprintf("add_key_bit: can't add: %02X\n", code); | dprintf("add_key_bit: can't add: %02X\n", code); | ||||
static inline void del_key_bit(uint8_t code) | static inline void del_key_bit(uint8_t code) | ||||
{ | { | ||||
if ((code>>3) < REPORT_BITS) { | |||||
if ((code>>3) < KEYBOARD_REPORT_BITS) { | |||||
keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7)); | keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7)); | ||||
} else { | } else { | ||||
dprintf("del_key_bit: can't del: %02X\n", code); | dprintf("del_key_bit: can't del: %02X\n", code); |
#include <stdint.h> | #include <stdint.h> | ||||
#include "report.h" | #include "report.h" | ||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
extern report_keyboard_t *keyboard_report; | extern report_keyboard_t *keyboard_report; | ||||
void send_keyboard_report(void); | void send_keyboard_report(void); | ||||
uint8_t has_anykey(void); | uint8_t has_anykey(void); | ||||
uint8_t has_anymod(void); | uint8_t has_anymod(void); | ||||
uint8_t get_first_key(void); | uint8_t get_first_key(void); | ||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif | #endif |
matrix_row_t matrix_row = matrix_get_row(r); | matrix_row_t matrix_row = matrix_get_row(r); | ||||
for (uint8_t c = 0; c < MATRIX_COLS; 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)) { | ||||
if (keycode == keymap_key_to_keycode(0, (key_t){ .row = r, .col = c })) { | |||||
if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) { | |||||
return true; | return true; | ||||
} | } | ||||
} | } |
*/ | */ | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <avr/interrupt.h> | |||||
//#include <avr/interrupt.h> | |||||
#include "keycode.h" | #include "keycode.h" | ||||
#include "host.h" | #include "host.h" | ||||
#include "util.h" | #include "util.h" | ||||
if (debug_keyboard) { | if (debug_keyboard) { | ||||
dprint("keyboard_report: "); | dprint("keyboard_report: "); | ||||
for (uint8_t i = 0; i < REPORT_SIZE; i++) { | |||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { | |||||
dprintf("%02X ", report->raw[i]); | dprintf("%02X ", report->raw[i]); | ||||
} | } | ||||
dprint("\n"); | dprint("\n"); |
for (uint8_t c = 0; c < MATRIX_COLS; c++) { | for (uint8_t c = 0; c < MATRIX_COLS; c++) { | ||||
if (matrix_change & ((matrix_row_t)1<<c)) { | if (matrix_change & ((matrix_row_t)1<<c)) { | ||||
action_exec((keyevent_t){ | action_exec((keyevent_t){ | ||||
.key = (key_t){ .row = r, .col = c }, | |||||
.key = (keypos_t){ .row = r, .col = c }, | |||||
.pressed = (matrix_row & ((matrix_row_t)1<<c)), | .pressed = (matrix_row & ((matrix_row_t)1<<c)), | ||||
.time = (timer_read() | 1) /* time should not be 0 */ | .time = (timer_read() | 1) /* time should not be 0 */ | ||||
}); | }); |
typedef struct { | typedef struct { | ||||
uint8_t col; | uint8_t col; | ||||
uint8_t row; | uint8_t row; | ||||
} key_t; | |||||
} keypos_t; | |||||
/* key event */ | /* key event */ | ||||
typedef struct { | typedef struct { | ||||
key_t key; | |||||
keypos_t key; | |||||
bool pressed; | bool pressed; | ||||
uint16_t time; | uint16_t time; | ||||
} keyevent_t; | } keyevent_t; | ||||
/* equivalent test of key_t */ | |||||
/* equivalent test of keypos_t */ | |||||
#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col) | #define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col) | ||||
/* Rules for No Event: | /* Rules for No Event: | ||||
/* Tick event */ | /* Tick event */ | ||||
#define TICK (keyevent_t){ \ | #define TICK (keyevent_t){ \ | ||||
.key = (key_t){ .row = 255, .col = 255 }, \ | |||||
.key = (keypos_t){ .row = 255, .col = 255 }, \ | |||||
.pressed = false, \ | .pressed = false, \ | ||||
.time = (timer_read() | 1) \ | .time = (timer_read() | 1) \ | ||||
} | } |
/* converts key to action */ | /* converts key to action */ | ||||
action_t action_for_key(uint8_t layer, key_t key) | |||||
action_t action_for_key(uint8_t layer, keypos_t key) | |||||
{ | { | ||||
uint8_t keycode = keymap_key_to_keycode(layer, key); | uint8_t keycode = keymap_key_to_keycode(layer, key); | ||||
switch (keycode) { | switch (keycode) { | ||||
* Consider using new keymap API instead. | * Consider using new keymap API instead. | ||||
*/ | */ | ||||
__attribute__ ((weak)) | __attribute__ ((weak)) | ||||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key) | |||||
uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key) | |||||
{ | { | ||||
return keymap_get_keycode(layer, key.row, key.col); | return keymap_get_keycode(layer, key.row, key.col); | ||||
} | } |
/* translates key to keycode */ | /* translates key to keycode */ | ||||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key); | |||||
uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key); | |||||
/* translates Fn keycode to action */ | /* translates Fn keycode to action */ | ||||
action_t keymap_fn_to_action(uint8_t keycode); | action_t keymap_fn_to_action(uint8_t keycode); |
#if defined(__AVR__) | #if defined(__AVR__) | ||||
#include "xprintf.h" | |||||
#include "avr/xprintf.h" | |||||
// TODO: avoid collision with arduino/Print.h | // TODO: avoid collision with arduino/Print.h |
/* key report size(NKRO or boot mode) */ | /* key report size(NKRO or boot mode) */ | ||||
#if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE) | #if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE) | ||||
# include "usb.h" | # include "usb.h" | ||||
# define REPORT_SIZE KBD2_SIZE | |||||
# define REPORT_KEYS (KBD2_SIZE - 2) | |||||
# define REPORT_BITS (KBD2_SIZE - 1) | |||||
# define KEYBOARD_REPORT_SIZE KBD2_SIZE | |||||
# define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2) | |||||
# define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1) | |||||
#elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE) | #elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE) | ||||
# include "protocol/lufa/descriptor.h" | # include "protocol/lufa/descriptor.h" | ||||
# define REPORT_SIZE NKRO_EPSIZE | |||||
# define REPORT_KEYS (NKRO_EPSIZE - 2) | |||||
# define REPORT_BITS (NKRO_EPSIZE - 1) | |||||
# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE | |||||
# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2) | |||||
# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) | |||||
#else | #else | ||||
# define REPORT_SIZE 8 | |||||
# define REPORT_KEYS 6 | |||||
# define KEYBOARD_REPORT_SIZE 8 | |||||
# define KEYBOARD_REPORT_KEYS 6 | |||||
#endif | #endif | ||||
* | * | ||||
*/ | */ | ||||
typedef union { | typedef union { | ||||
uint8_t raw[REPORT_SIZE]; | |||||
uint8_t raw[KEYBOARD_REPORT_SIZE]; | |||||
struct { | struct { | ||||
uint8_t mods; | uint8_t mods; | ||||
uint8_t reserved; | uint8_t reserved; | ||||
uint8_t keys[REPORT_KEYS]; | |||||
uint8_t keys[KEYBOARD_REPORT_KEYS]; | |||||
}; | }; | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
struct { | struct { | ||||
uint8_t mods; | uint8_t mods; | ||||
uint8_t bits[REPORT_BITS]; | |||||
uint8_t bits[KEYBOARD_REPORT_BITS]; | |||||
} nkro; | } nkro; | ||||
#endif | #endif | ||||
} __attribute__ ((packed)) report_keyboard_t; | } __attribute__ ((packed)) report_keyboard_t; |
#ifndef WAIT_H | |||||
#define WAIT_H | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#if defined(__AVR__) | |||||
# include <util/delay.h> | |||||
# define wait_ms(ms) _delay_ms(ms) | |||||
# define wait_us(us) _delay_us(us) | |||||
#elif defined(__arm__) | |||||
# include "wait_api.h" | |||||
#endif | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif |
#include "stdint.h" | #include "stdint.h" | ||||
#include "stdbool.h" | #include "stdbool.h" | ||||
#include "USBHID.h" | #include "USBHID.h" | ||||
typedef union { | |||||
uint8_t raw[8]; | |||||
struct { | |||||
uint8_t mods; | |||||
uint8_t reserved; | |||||
uint8_t keys[6]; | |||||
}; | |||||
} __attribute__ ((packed)) report_keyboard_t; | |||||
#include "report.h" | |||||
class HIDKeyboard : public USBDevice { | class HIDKeyboard : public USBDevice { |
OBJECTS = \ | OBJECTS = \ | ||||
$(OBJDIR)/./HIDKeyboard.o \ | $(OBJDIR)/./HIDKeyboard.o \ | ||||
$(OBJDIR)/./mbed_driver.o \ | |||||
$(OBJDIR)/./main.o | $(OBJDIR)/./main.o | ||||
SYS_OBJECTS = | SYS_OBJECTS = |
OBJECTS += \ | OBJECTS += \ | ||||
$(OBJDIR)/$(COMMON_DIR)/mbed/timer.o \ | $(OBJDIR)/$(COMMON_DIR)/mbed/timer.o \ | ||||
$(OBJDIR)/$(COMMON_DIR)/mbed/xprintf.o \ | $(OBJDIR)/$(COMMON_DIR)/mbed/xprintf.o \ | ||||
$(OBJDIR)/$(COMMON_DIR)/action.o \ | |||||
$(OBJDIR)/$(COMMON_DIR)/action_tapping.o \ | |||||
$(OBJDIR)/$(COMMON_DIR)/action_macro.o \ | |||||
$(OBJDIR)/$(COMMON_DIR)/action_layer.o \ | |||||
$(OBJDIR)/$(COMMON_DIR)/action_util.o \ | |||||
$(OBJDIR)/$(COMMON_DIR)/host.o \ | |||||
INCLUDE_PATHS += \ | INCLUDE_PATHS += \ | ||||
-I$(TMK_DIR)/$(COMMON_DIR) | -I$(TMK_DIR)/$(COMMON_DIR) | ||||
# $(OBJDIR)/$(COMMON_DIR)/action.o \ | |||||
# $(OBJDIR)/$(COMMON_DIR)/host.o \ | |||||
# $(OBJDIR)/$(COMMON_DIR)/keyboard.o \ | # $(OBJDIR)/$(COMMON_DIR)/keyboard.o \ | ||||
# $(OBJDIR)/$(COMMON_DIR)/action_tapping.o \ | |||||
# $(OBJDIR)/$(COMMON_DIR)/action_macro.o \ | |||||
# $(OBJDIR)/$(COMMON_DIR)/action_layer.o \ | |||||
# $(OBJDIR)/$(COMMON_DIR)/action_util.o \ | |||||
# $(OBJDIR)/$(COMMON_DIR)/keymap.o \ | # $(OBJDIR)/$(COMMON_DIR)/keymap.o \ | ||||
# $(OBJDIR)/$(COMMON_DIR)/bootloader.o \ | # $(OBJDIR)/$(COMMON_DIR)/bootloader.o \ | ||||
# $(OBJDIR)/$(COMMON_DIR)/suspend.o \ | # $(OBJDIR)/$(COMMON_DIR)/suspend.o \ |