summaryrefslogtreecommitdiff
path: root/quantum/keyboard.h
blob: f82f2fa58af7de99d2c35f77888311fe0f4d6416 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/* key matrix position */
typedef struct {
    uint8_t col;
    uint8_t row;
} keypos_t;

/* key event */
typedef struct {
    keypos_t key;
    bool     pressed;
    uint16_t time;
} keyevent_t;

/* equivalent test of keypos_t */
#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col)

/* special keypos_t entries */
#define KEYLOC_TICK 255
#define KEYLOC_COMBO 254
#define KEYLOC_ENCODER_CW 253
#define KEYLOC_ENCODER_CCW 252

/* Rules for No Event:
 * 1) (time == 0) to handle (keyevent_t){} as empty event
 * 2) Matrix(255, 255) to make TICK event available
 */
static inline bool IS_NOEVENT(keyevent_t event) {
    return event.time == 0 || (event.key.row == KEYLOC_TICK && event.key.col == KEYLOC_TICK);
}
static inline bool IS_EVENT(keyevent_t event) {
    return !IS_NOEVENT(event);
}
static inline bool IS_KEYEVENT(keyevent_t event) {
    return event.key.row < MATRIX_ROWS && event.key.col < MATRIX_COLS;
}
static inline bool IS_COMBOEVENT(keyevent_t event) {
    return event.key.row == KEYLOC_COMBO;
}
static inline bool IS_ENCODEREVENT(keyevent_t event) {
    return event.key.row == KEYLOC_ENCODER_CW || event.key.row == KEYLOC_ENCODER_CCW;
}
static inline bool IS_PRESSED(keyevent_t event) {
    return IS_EVENT(event) && event.pressed;
}
static inline bool IS_RELEASED(keyevent_t event) {
    return IS_EVENT(event) && !event.pressed;
}

/* Common keyevent object factory */
#define MAKE_KEYPOS(row_num, col_num) ((keypos_t){.row = (row_num), .col = (col_num)})

/**
 * @brief Constructs a key event for a pressed or released key.
 */
#define MAKE_KEYEVENT(row_num, col_num, press) ((keyevent_t){.key = MAKE_KEYPOS((row_num), (col_num)), .pressed = (press), .time = (timer_read() | 1)})

/**
 * @brief Constructs a internal tick event that is used to drive the internal QMK state machine.
 */
#define TICK_EVENT MAKE_KEYEVENT(KEYLOC_TICK, KEYLOC_TICK, false)

#ifdef ENCODER_MAP_ENABLE
/* Encoder events */
#    define ENCODER_CW_EVENT(enc_id, press) MAKE_KEYEVENT(KEYLOC_ENCODER_CW, (enc_id), (press))
#    define ENCODER_CCW_EVENT(enc_id, press) MAKE_KEYEVENT(KEYLOC_ENCODER_CCW, (enc_id), (press))
#endif // ENCODER_MAP_ENABLE

/* it runs once at early stage of startup before keyboard_init. */
void keyboard_setup(void);
/* it runs once after initializing host side protocol, debug and MCU peripherals. */
void keyboard_init(void);
/* it runs repeatedly in main loop */
void keyboard_task(void);
/* it runs whenever code has to behave differently on a slave */
bool is_keyboard_master(void);
/* it runs whenever code has to behave differently on left vs right split */
bool is_keyboard_left(void);

void keyboard_pre_init_kb(void);
void keyboard_pre_init_user(void);
void keyboard_post_init_kb(void);
void keyboard_post_init_user(void);

void housekeeping_task(void);      // To be executed by the main loop in each backend TMK protocol
void housekeeping_task_kb(void);   // To be overridden by keyboard-level code
void housekeeping_task_user(void); // To be overridden by user/keymap-level code

uint32_t last_input_activity_time(void);    // Timestamp of the last matrix or encoder or pointing device activity
uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder or pointing device activity

uint32_t last_matrix_activity_time(void);    // Timestamp of the last matrix activity
uint32_t last_matrix_activity_elapsed(void); // Number of milliseconds since the last matrix activity

uint32_t last_encoder_activity_time(void);    // Timestamp of the last encoder activity
uint32_t last_encoder_activity_elapsed(void); // Number of milliseconds since the last encoder activity

uint32_t last_pointing_device_activity_time(void);    // Timestamp of the last pointing device activity
uint32_t last_pointing_device_activity_elapsed(void); // Number of milliseconds since the last  pointing device activity

void set_activity_timestamps(uint32_t matrix_timestamp, uint32_t encoder_timestamp, uint32_t pointing_device_timestamp); // Set the timestamps of the last matrix and encoder activity

uint32_t get_matrix_scan_rate(void);

#ifdef __cplusplus
}
#endif