aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/keycode.txt4
-rw-r--r--keyboards/ergodox_ez/config.h10
-rw-r--r--keyboards/ergodox_ez/matrix.c6
-rw-r--r--quantum/matrix.c292
-rw-r--r--tmk_core/common/avr/suspend.c6
-rw-r--r--tmk_core/common/bootmagic.c16
-rw-r--r--tmk_core/common/keyboard.c107
-rw-r--r--tmk_core/common/matrix.h57
8 files changed, 268 insertions, 230 deletions
diff --git a/doc/keycode.txt b/doc/keycode.txt
index 44d7e27cd..c1134f9bf 100644
--- a/doc/keycode.txt
+++ b/doc/keycode.txt
@@ -62,7 +62,7 @@ KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~
62KC_SCOLON KC_SCLN 33 Keyboard ; and : 62KC_SCOLON KC_SCLN 33 Keyboard ; and :
63KC_QUOTE KC_QUOT 34 Keyboard ‘ and “ 63KC_QUOTE KC_QUOT 34 Keyboard ‘ and “
64KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde 64KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde
65KC_COMMA KC_COMM 36 Keyboard, and < 65KC_COMMA KC_COMM 36 Keyboard , and <
66KC_DOT 37 Keyboard . and > 66KC_DOT 37 Keyboard . and >
67KC_SLASH KC_SLSH 38 Keyboard / and ? 67KC_SLASH KC_SLSH 38 Keyboard / and ?
68KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock 68KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock
@@ -92,7 +92,7 @@ KC_LEFT 50 Keyboard LeftArrow1
92KC_DOWN 51 Keyboard DownArrow1 92KC_DOWN 51 Keyboard DownArrow1
93KC_UP 52 Keyboard UpArrow1 93KC_UP 52 Keyboard UpArrow1
94KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11 94KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11
95KC_KP_SLASH KC_PSLS 54 Keypad /1 95KC_KP_SLASH KC_PSLS 54 Keypad /
96KC_KP_ASTERISK KC_PAST 55 Keypad * 96KC_KP_ASTERISK KC_PAST 55 Keypad *
97KC_KP_MINUS KC_PMNS 56 Keypad - 97KC_KP_MINUS KC_PMNS 56 Keypad -
98KC_KP_PLUS KC_PPLS 57 Keypad + 98KC_KP_PLUS KC_PPLS 57 Keypad +
diff --git a/keyboards/ergodox_ez/config.h b/keyboards/ergodox_ez/config.h
index 6a391ffb5..2bb56731b 100644
--- a/keyboards/ergodox_ez/config.h
+++ b/keyboards/ergodox_ez/config.h
@@ -27,7 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
27#define DEVICE_VER 0x0001 27#define DEVICE_VER 0x0001
28#define MANUFACTURER ErgoDox EZ 28#define MANUFACTURER ErgoDox EZ
29#define PRODUCT ErgoDox EZ 29#define PRODUCT ErgoDox EZ
30#define DESCRIPTION t.m.k. keyboard firmware for Ergodox 30#define DESCRIPTION QMK keyboard firmware for Ergodox EZ
31 31
32/* key matrix size */ 32/* key matrix size */
33#define MATRIX_ROWS 14 33#define MATRIX_ROWS 14
@@ -40,12 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
40 40
41#define TAPPING_TOGGLE 1 41#define TAPPING_TOGGLE 1
42 42
43#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
44#define ROWS (int []){ D0, D5, B5, B6 }
45
46/* COL2ROW or ROW2COL */
47#define DIODE_DIRECTION COL2ROW
48
49/* define if matrix has ghost */ 43/* define if matrix has ghost */
50//#define MATRIX_HAS_GHOST 44//#define MATRIX_HAS_GHOST
51 45
@@ -53,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
53#define BACKLIGHT_LEVELS 3 47#define BACKLIGHT_LEVELS 3
54 48
55/* Set 0 if debouncing isn't needed */ 49/* Set 0 if debouncing isn't needed */
56#define DEBOUNCE 2 50#define DEBOUNCE 5
57#define TAPPING_TERM 200 51#define TAPPING_TERM 200
58#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.) 52#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.)
59 53
diff --git a/keyboards/ergodox_ez/matrix.c b/keyboards/ergodox_ez/matrix.c
index b87fddbad..9c1efa1d0 100644
--- a/keyboards/ergodox_ez/matrix.c
+++ b/keyboards/ergodox_ez/matrix.c
@@ -27,7 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
27#include <stdint.h> 27#include <stdint.h>
28#include <stdbool.h> 28#include <stdbool.h>
29#include <avr/io.h> 29#include <avr/io.h>
30#include <util/delay.h> 30#include "wait.h"
31#include "action_layer.h" 31#include "action_layer.h"
32#include "print.h" 32#include "print.h"
33#include "debug.h" 33#include "debug.h"
@@ -166,6 +166,7 @@ uint8_t matrix_scan(void)
166 166
167 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 167 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
168 select_row(i); 168 select_row(i);
169 wait_us(30); // without this wait read unstable value.
169 matrix_row_t cols = read_cols(i); 170 matrix_row_t cols = read_cols(i);
170 if (matrix_debouncing[i] != cols) { 171 if (matrix_debouncing[i] != cols) {
171 matrix_debouncing[i] = cols; 172 matrix_debouncing[i] = cols;
@@ -179,7 +180,7 @@ uint8_t matrix_scan(void)
179 180
180 if (debouncing) { 181 if (debouncing) {
181 if (--debouncing) { 182 if (--debouncing) {
182 _delay_ms(1); 183 wait_us(1);
183 } else { 184 } else {
184 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 185 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
185 matrix[i] = matrix_debouncing[i]; 186 matrix[i] = matrix_debouncing[i];
@@ -267,7 +268,6 @@ static matrix_row_t read_cols(uint8_t row)
267 return data; 268 return data;
268 } 269 }
269 } else { 270 } else {
270 _delay_us(30); // without this wait read unstable value.
271 // read from teensy 271 // read from teensy
272 return 272 return
273 (PINF&(1<<0) ? 0 : (1<<0)) | 273 (PINF&(1<<0) ? 0 : (1<<0)) |
diff --git a/quantum/matrix.c b/quantum/matrix.c
index a38c13f15..094917025 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -26,32 +26,46 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
26#include "util.h" 26#include "util.h"
27#include "matrix.h" 27#include "matrix.h"
28 28
29#ifdef MATRIX_HAS_GHOST 29/* Set 0 if debouncing isn't needed */
30# error "The universal matrix.c file cannot be used for this keyboard." 30/*
31#endif 31 * This constant define not debouncing time in msecs, but amount of matrix
32 * scan loops which should be made to get stable debounced results.
33 *
34 * On Ergodox matrix scan rate is relatively low, because of slow I2C.
35 * Now it's only 317 scans/second, or about 3.15 msec/scan.
36 * According to Cherry specs, debouncing time is 5 msec.
37 *
38 * And so, there is no sense to have DEBOUNCE higher than 2.
39 */
32 40
33#ifndef DEBOUNCING_DELAY 41#ifndef DEBOUNCING_DELAY
34# define DEBOUNCING_DELAY 5 42# define DEBOUNCING_DELAY 5
35#endif 43#endif
44static uint8_t debouncing = DEBOUNCING_DELAY;
36 45
37static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 46static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
38static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 47static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
39/* matrix state */ 48
40#if DIODE_DIRECTION == COL2ROW 49/* matrix state(1:on, 0:off) */
41static matrix_row_t matrix[MATRIX_ROWS]; 50static matrix_row_t matrix[MATRIX_ROWS];
42#else 51static matrix_row_t matrix_debouncing[MATRIX_ROWS];
43static matrix_col_t matrix[MATRIX_COLS]; 52
53#if DIODE_DIRECTION == ROW2COL
54 static matrix_row_t matrix_reversed[MATRIX_COLS];
55 static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
44#endif 56#endif
45static int8_t debouncing_delay = -1;
46 57
47#if DIODE_DIRECTION == COL2ROW 58#if MATRIX_COLS > 16
48static void toggle_row(uint8_t row); 59 #define SHIFTER 1UL
49static matrix_row_t read_cols(void);
50#else 60#else
51static void toggle_col(uint8_t col); 61 #define SHIFTER 1
52static matrix_col_t read_rows(void);
53#endif 62#endif
54 63
64static matrix_row_t read_cols(void);
65static void init_cols(void);
66static void unselect_rows(void);
67static void select_row(uint8_t row);
68
55__attribute__ ((weak)) 69__attribute__ ((weak))
56void matrix_init_quantum(void) { 70void matrix_init_quantum(void) {
57 matrix_init_kb(); 71 matrix_init_kb();
@@ -80,10 +94,12 @@ __attribute__ ((weak))
80void matrix_scan_user(void) { 94void matrix_scan_user(void) {
81} 95}
82 96
97inline
83uint8_t matrix_rows(void) { 98uint8_t matrix_rows(void) {
84 return MATRIX_ROWS; 99 return MATRIX_ROWS;
85} 100}
86 101
102inline
87uint8_t matrix_cols(void) { 103uint8_t matrix_cols(void) {
88 return MATRIX_COLS; 104 return MATRIX_COLS;
89} 105}
@@ -113,161 +129,179 @@ uint8_t matrix_cols(void) {
113// } 129// }
114 130
115void matrix_init(void) { 131void matrix_init(void) {
116 /* frees PORTF by setting the JTD bit twice within four cycles */ 132 // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
117 #ifdef __AVR_ATmega32U4__ 133 #ifdef __AVR_ATmega32U4__
118 MCUCR |= _BV(JTD); 134 MCUCR |= _BV(JTD);
119 MCUCR |= _BV(JTD); 135 MCUCR |= _BV(JTD);
120 #endif 136 #endif
121 /* initializes the I/O pins */ 137
122#if DIODE_DIRECTION == COL2ROW 138 // initialize row and col
123 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 139 unselect_rows();
124 /* DDRxn */ 140 init_cols();
125 _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); 141
126 toggle_row(r); 142 // initialize matrix state: all keys off
127 } 143 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
128 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 144 matrix[i] = 0;
129 /* PORTxn */ 145 matrix_debouncing[i] = 0;
130 _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
131 }
132#else
133 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
134 /* DDRxn */
135 _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
136 toggle_col(c);
137 }
138 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
139 /* PORTxn */
140 _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF);
141 } 146 }
142#endif 147
143 matrix_init_quantum(); 148 matrix_init_quantum();
144} 149}
145 150
151uint8_t matrix_scan(void)
152{
153
146#if DIODE_DIRECTION == COL2ROW 154#if DIODE_DIRECTION == COL2ROW
147uint8_t matrix_scan(void) { 155 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
148 static matrix_row_t debouncing_matrix[MATRIX_ROWS]; 156 select_row(i);
149 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 157 wait_us(30); // without this wait read unstable value.
150 toggle_row(r); 158 matrix_row_t cols = read_cols();
151 matrix_row_t state = read_cols(); 159 if (matrix_debouncing[i] != cols) {
152 if (debouncing_matrix[r] != state) { 160 matrix_debouncing[i] = cols;
153 debouncing_matrix[r] = state; 161 if (debouncing) {
154 debouncing_delay = DEBOUNCING_DELAY; 162 debug("bounce!: "); debug_hex(debouncing); debug("\n");
155 }
156 toggle_row(r);
157 }
158 if (debouncing_delay >= 0) {
159 dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
160 --debouncing_delay;
161 if (debouncing_delay >= 0) {
162 wait_ms(1);
163 }
164 else {
165 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
166 matrix[r] = debouncing_matrix[r];
167 } 163 }
164 debouncing = DEBOUNCING_DELAY;
168 } 165 }
166 unselect_rows();
169 } 167 }
170 matrix_scan_quantum();
171 return 1;
172}
173
174static void toggle_row(uint8_t row) {
175 /* PINxn */
176 _SFR_IO8((row_pins[row] >> 4)) = _BV(row_pins[row] & 0xF);
177}
178 168
179static matrix_row_t read_cols(void) { 169 if (debouncing) {
180 matrix_row_t state = 0; 170 if (--debouncing) {
181 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 171 wait_us(1);
182 /* PINxn */ 172 } else {
183 if (!(_SFR_IO8((col_pins[c] >> 4)) & _BV(col_pins[c] & 0xF))) { 173 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
184 state |= (matrix_row_t)1 << c; 174 matrix[i] = matrix_debouncing[i];
175 }
185 } 176 }
186 } 177 }
187 return state;
188}
189
190matrix_row_t matrix_get_row(uint8_t row) {
191 return matrix[row];
192}
193
194#else 178#else
195uint8_t matrix_scan(void) { 179 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
196 static matrix_col_t debouncing_matrix[MATRIX_COLS]; 180 select_row(i);
197 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 181 wait_us(30); // without this wait read unstable value.
198 toggle_col(c); 182 matrix_row_t rows = read_cols();
199 matrix_col_t state = read_rows(); 183 if (matrix_reversed_debouncing[i] != rows) {
200 if (debouncing_matrix[c] != state) { 184 matrix_reversed_debouncing[i] = rows;
201 debouncing_matrix[c] = state; 185 if (debouncing) {
202 debouncing_delay = DEBOUNCING_DELAY; 186 debug("bounce!: "); debug_hex(debouncing); debug("\n");
187 }
188 debouncing = DEBOUNCING_DELAY;
203 } 189 }
204 toggle_col(c); 190 unselect_rows();
205 } 191 }
206 if (debouncing_delay >= 0) { 192
207 dprintf("Debouncing delay remaining: %X\n", debouncing_delay); 193 if (debouncing) {
208 --debouncing_delay; 194 if (--debouncing) {
209 if (debouncing_delay >= 0) { 195 wait_us(1);
210 wait_ms(1); 196 } else {
211 } 197 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
212 else { 198 matrix_reversed[i] = matrix_reversed_debouncing[i];
213 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
214 matrix[c] = debouncing_matrix[c];
215 } 199 }
216 } 200 }
217 } 201 }
202 for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
203 matrix_row_t row = 0;
204 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
205 row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
206 }
207 matrix[y] = row;
208 }
209#endif
210
218 matrix_scan_quantum(); 211 matrix_scan_quantum();
212
219 return 1; 213 return 1;
220} 214}
221 215
222static void toggle_col(uint8_t col) { 216bool matrix_is_modified(void)
223 /* PINxn */ 217{
224 _SFR_IO8((col_pins[col] >> 4)) = _BV(col_pins[col] & 0xF); 218 if (debouncing) return false;
219 return true;
225} 220}
226 221
227static matrix_col_t read_rows(void) { 222inline
228 matrix_col_t state = 0; 223bool matrix_is_on(uint8_t row, uint8_t col)
229 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 224{
230 /* PINxn */ 225 return (matrix[row] & ((matrix_row_t)1<col));
231 if (!(_SFR_IO8((row_pins[r] >> 4)) & _BV(row_pins[r] & 0xF))) { 226}
232 state |= (matrix_col_t)1 << r; 227
233 } 228inline
229matrix_row_t matrix_get_row(uint8_t row)
230{
231 return matrix[row];
232}
233
234void matrix_print(void)
235{
236 print("\nr/c 0123456789ABCDEF\n");
237 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
238 phex(row); print(": ");
239 pbin_reverse16(matrix_get_row(row));
240 print("\n");
234 } 241 }
235 return state;
236} 242}
237 243
238matrix_row_t matrix_get_row(uint8_t row) { 244uint8_t matrix_key_count(void)
239 matrix_row_t state = 0; 245{
240 matrix_col_t mask = (matrix_col_t)1 << row; 246 uint8_t count = 0;
241 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 247 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
242 if (matrix[c] & mask) { 248 count += bitpop16(matrix[i]);
243 state |= (matrix_row_t)1 << c;
244 }
245 } 249 }
246 return state; 250 return count;
247} 251}
248 252
253static void init_cols(void)
254{
255#if DIODE_DIRECTION == COL2ROW
256 for(int x = 0; x < MATRIX_COLS; x++) {
257 int pin = col_pins[x];
258#else
259 for(int x = 0; x < MATRIX_ROWS; x++) {
260 int pin = row_pins[x];
249#endif 261#endif
250 262 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
251bool matrix_is_modified(void) { 263 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
252 if (debouncing_delay >= 0) return false; 264 }
253 return true;
254} 265}
255 266
256bool matrix_is_on(uint8_t row, uint8_t col) { 267static matrix_row_t read_cols(void)
257 return matrix_get_row(row) & (matrix_row_t)1 << col; 268{
258} 269 matrix_row_t result = 0;
259 270
260void matrix_print(void) { 271#if DIODE_DIRECTION == COL2ROW
261 dprintln("Human-readable matrix state:"); 272 for(int x = 0; x < MATRIX_COLS; x++) {
262 for (uint8_t r = 0; r < MATRIX_ROWS; r++) { 273 int pin = col_pins[x];
263 dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r))); 274#else
275 for(int x = 0; x < MATRIX_ROWS; x++) {
276 int pin = row_pins[x];
277#endif
278 result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x);
264 } 279 }
280 return result;
265} 281}
266 282
267uint8_t matrix_key_count(void) { 283static void unselect_rows(void)
268 uint8_t count = 0; 284{
269 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 285#if DIODE_DIRECTION == COL2ROW
270 count += bitpop16(matrix_get_row(r)); 286 for(int x = 0; x < MATRIX_ROWS; x++) {
287 int pin = row_pins[x];
288#else
289 for(int x = 0; x < MATRIX_COLS; x++) {
290 int pin = col_pins[x];
291#endif
292 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
293 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
271 } 294 }
272 return count; 295}
296
297static void select_row(uint8_t row)
298{
299
300#if DIODE_DIRECTION == COL2ROW
301 int pin = row_pins[row];
302#else
303 int pin = col_pins[row];
304#endif
305 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF);
306 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);
273} 307}
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
index a6f3c6441..8a7272bbc 100644
--- a/tmk_core/common/avr/suspend.c
+++ b/tmk_core/common/avr/suspend.c
@@ -114,8 +114,10 @@ bool suspend_wakeup_condition(void)
114 matrix_power_up(); 114 matrix_power_up();
115 matrix_scan(); 115 matrix_scan();
116 matrix_power_down(); 116 matrix_power_down();
117 if (matrix_key_count()) return true; 117 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
118 return false; 118 if (matrix_get_row(r)) return true;
119 }
120 return false;
119} 121}
120 122
121// run immediately after wakeup 123// run immediately after wakeup
diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c
index 90275a18b..6730a2a4a 100644
--- a/tmk_core/common/bootmagic.c
+++ b/tmk_core/common/bootmagic.c
@@ -106,13 +106,15 @@ void bootmagic(void)
106 } 106 }
107} 107}
108 108
109static bool scan_keycode(uint8_t keycode) { 109static bool scan_keycode(uint8_t keycode)
110 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 110{
111 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
111 matrix_row_t matrix_row = matrix_get_row(r); 112 matrix_row_t matrix_row = matrix_get_row(r);
112 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 113 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
113 if (matrix_row & (matrix_row_t)1 << c) { 114 if (matrix_row & ((matrix_row_t)1<<c)) {
114 keypos_t key = (keypos_t){ .row = r, .col = c }; 115 if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) {
115 if (keycode == keymap_key_to_keycode(0, key)) return true; 116 return true;
117 }
116 } 118 }
117 } 119 }
118 } 120 }
@@ -124,4 +126,4 @@ bool bootmagic_scan_keycode(uint8_t keycode)
124 if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; 126 if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;
125 127
126 return scan_keycode(keycode); 128 return scan_keycode(keycode);
127} 129} \ No newline at end of file
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
index 34e1ceeca..81df8eb73 100644
--- a/tmk_core/common/keyboard.c
+++ b/tmk_core/common/keyboard.c
@@ -51,17 +51,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
51#endif 51#endif
52 52
53#ifdef MATRIX_HAS_GHOST 53#ifdef MATRIX_HAS_GHOST
54static bool is_row_ghosting(uint8_t row){ 54static bool has_ghost_in_row(uint8_t row)
55 matrix_row_t state = matrix_get_row(row); 55{
56 /* no ghosting happens when only one key in the row is pressed */ 56 matrix_row_t matrix_row = matrix_get_row(row);
57 if (!(state - 1 & state)) return false; 57 // No ghost exists when less than 2 keys are down on the row
58 /* ghosting occurs when two keys in the same column are pressed */ 58 if (((matrix_row - 1) & matrix_row) == 0)
59 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 59 return false;
60 if (r != row && matrix_get_row(r) & state) return true; 60
61 // Ghost occurs when the row shares column line with other row
62 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
63 if (i != row && (matrix_get_row(i) & matrix_row))
64 return true;
61 } 65 }
62 return false; 66 return false;
63} 67}
64
65#endif 68#endif
66 69
67__attribute__ ((weak)) 70__attribute__ ((weak))
@@ -100,72 +103,86 @@ void keyboard_init(void) {
100#endif 103#endif
101} 104}
102 105
103/* does routine keyboard jobs */ 106/*
104void keyboard_task(void) { 107 * Do keyboard routine jobs: scan mantrix, light LEDs, ...
105 static uint8_t led_status; 108 * This is repeatedly called as fast as possible.
109 */
110void keyboard_task(void)
111{
112 static matrix_row_t matrix_prev[MATRIX_ROWS];
113#ifdef MATRIX_HAS_GHOST
114 static matrix_row_t matrix_ghost[MATRIX_ROWS];
115#endif
116 static uint8_t led_status = 0;
117 matrix_row_t matrix_row = 0;
118 matrix_row_t matrix_change = 0;
119
106 matrix_scan(); 120 matrix_scan();
107 for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 121 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
108 static matrix_row_t previous_matrix[MATRIX_ROWS]; 122 matrix_row = matrix_get_row(r);
109 matrix_row_t state = matrix_get_row(r); 123 matrix_change = matrix_row ^ matrix_prev[r];
110 matrix_row_t changes = state ^ previous_matrix[r]; 124 if (matrix_change) {
111 if (changes) {
112#ifdef MATRIX_HAS_GHOST 125#ifdef MATRIX_HAS_GHOST
113 static matrix_row_t deghosting_matrix[MATRIX_ROWS]; 126 if (has_ghost_in_row(r)) {
114 if (is_row_ghosting(r)) { 127 /* Keep track of whether ghosted status has changed for
115 /* debugs the deghosting mechanism */ 128 * debugging. But don't update matrix_prev until un-ghosted, or
116 /* doesn't update previous_matrix until the ghosting has stopped 129 * the last key would be lost.
117 * in order to prevent the last key from being lost
118 */ 130 */
119 if (debug_matrix && deghosting_matrix[r] != state) { 131 if (debug_matrix && matrix_ghost[r] != matrix_row) {
120 matrix_print(); 132 matrix_print();
121 } 133 }
122 deghosting_matrix[r] = state; 134 matrix_ghost[r] = matrix_row;
123 continue; 135 continue;
124 } 136 }
125 deghosting_matrix[r] = state; 137 matrix_ghost[r] = matrix_row;
126#endif 138#endif
127 if (debug_matrix) matrix_print(); 139 if (debug_matrix) matrix_print();
128 for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 140 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
129 matrix_row_t mask = (matrix_row_t)1 << c; 141 if (matrix_change & ((matrix_row_t)1<<c)) {
130 if (changes & mask) { 142 action_exec((keyevent_t){
131 keyevent_t event; 143 .key = (keypos_t){ .row = r, .col = c },
132 event.key = (keypos_t){ .row = r, .col = c }; 144 .pressed = (matrix_row & ((matrix_row_t)1<<c)),
133 event.pressed = state & mask; 145 .time = (timer_read() | 1) /* time should not be 0 */
134 /* the time should not be 0 */ 146 });
135 event.time = timer_read() | 1; 147 // record a processed key
136 action_exec(event); 148 matrix_prev[r] ^= ((matrix_row_t)1<<c);
137 /* records the processed key event */ 149 // process a key per task call
138 previous_matrix[r] ^= mask; 150 goto MATRIX_LOOP_END;
139 /* processes one key event per call */
140 goto event_processed;
141 } 151 }
142 } 152 }
143 } 153 }
144 } 154 }
145 /* sends tick events when the keyboard is idle */ 155 // call with pseudo tick event when no real key event.
146 action_exec(TICK); 156 action_exec(TICK);
147event_processed: 157
158MATRIX_LOOP_END:
159
148#ifdef MOUSEKEY_ENABLE 160#ifdef MOUSEKEY_ENABLE
149 /* repeats and accelerates the mouse keys */ 161 // mousekey repeat & acceleration
150 mousekey_task(); 162 mousekey_task();
151#endif 163#endif
164
152#ifdef PS2_MOUSE_ENABLE 165#ifdef PS2_MOUSE_ENABLE
153 ps2_mouse_task(); 166 ps2_mouse_task();
154#endif 167#endif
168
155#ifdef SERIAL_MOUSE_ENABLE 169#ifdef SERIAL_MOUSE_ENABLE
156 serial_mouse_task(); 170 serial_mouse_task();
157#endif 171#endif
172
158#ifdef ADB_MOUSE_ENABLE 173#ifdef ADB_MOUSE_ENABLE
159 adb_mouse_task(); 174 adb_mouse_task();
160#endif 175#endif
161 /* updates the LEDs */ 176
177 // update LED
162 if (led_status != host_keyboard_leds()) { 178 if (led_status != host_keyboard_leds()) {
163 led_status = host_keyboard_leds(); 179 led_status = host_keyboard_leds();
164 keyboard_set_leds(led_status); 180 keyboard_set_leds(led_status);
165 } 181 }
166} 182}
167 183
168void keyboard_set_leds(uint8_t leds) { 184void keyboard_set_leds(uint8_t leds)
169 if (debug_keyboard) dprintf("Keyboard LEDs state: %x\n", leds); 185{
186 if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
170 led_set(leds); 187 led_set(leds);
171} 188}
diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h
index 5f2f831b4..71153a5f5 100644
--- a/tmk_core/common/matrix.h
+++ b/tmk_core/common/matrix.h
@@ -20,59 +20,48 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
20#include <stdint.h> 20#include <stdint.h>
21#include <stdbool.h> 21#include <stdbool.h>
22 22
23#if MATRIX_COLS <= 8 23
24typedef uint8_t matrix_row_t; 24#if (MATRIX_COLS <= 8)
25#elif MATRIX_COLS <= 16 25typedef uint8_t matrix_row_t;
26typedef uint16_t matrix_row_t; 26#elif (MATRIX_COLS <= 16)
27#elif MATRIX_COLS <= 32 27typedef uint16_t matrix_row_t;
28typedef uint32_t matrix_row_t; 28#elif (MATRIX_COLS <= 32)
29typedef uint32_t matrix_row_t;
29#else 30#else
30# error "There are too many columns." 31#error "MATRIX_COLS: invalid value"
31#endif 32#endif
32 33
33#if DIODE_DIRECTION == ROW2COL 34#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col))
34# if MATRIX_ROWS <= 8
35typedef uint8_t matrix_col_t;
36# elif MATRIX_ROWS <= 16
37typedef uint16_t matrix_col_t;
38# elif MATRIX_ROWS <= 32
39typedef uint32_t matrix_col_t;
40# else
41# error "There are too many rows."
42# endif
43#endif
44 35
45typedef struct {
46 uint8_t input_addr:4;
47 uint8_t bit:4;
48} io_pin_t;
49 36
50#ifdef __cplusplus 37#ifdef __cplusplus
51extern "C" { 38extern "C" {
52#endif 39#endif
53/* counts the number of rows in the matrix */ 40
41/* number of matrix rows */
54uint8_t matrix_rows(void); 42uint8_t matrix_rows(void);
55/* counts the number of columns in the matrix */ 43/* number of matrix columns */
56uint8_t matrix_cols(void); 44uint8_t matrix_cols(void);
57/* sets up the matrix before matrix_init */ 45/* should be called at early stage of startup before matrix_init.(optional) */
58void matrix_setup(void); 46void matrix_setup(void);
59/* intializes the matrix */ 47/* intialize matrix for scaning. */
60void matrix_init(void); 48void matrix_init(void);
61/* scans the entire matrix */ 49/* scan all key states on matrix */
62uint8_t matrix_scan(void); 50uint8_t matrix_scan(void);
63/* checks if the matrix has been modified */ 51/* whether modified from previous scan. used after matrix_scan. */
64bool matrix_is_modified(void) __attribute__ ((deprecated)); 52bool matrix_is_modified(void) __attribute__ ((deprecated));
65/* checks if a key is pressed */ 53/* whether a swtich is on */
66bool matrix_is_on(uint8_t row, uint8_t col); 54bool matrix_is_on(uint8_t row, uint8_t col);
67/* inspects the state of a row in the matrix */ 55/* matrix state on row */
68matrix_row_t matrix_get_row(uint8_t row); 56matrix_row_t matrix_get_row(uint8_t row);
69/* prints the matrix for debugging */ 57/* print matrix for debug */
70void matrix_print(void); 58void matrix_print(void);
71/* counts the total number of keys pressed */ 59
72uint8_t matrix_key_count(void); 60
73/* controls power to the matrix */ 61/* power control */
74void matrix_power_up(void); 62void matrix_power_up(void);
75void matrix_power_down(void); 63void matrix_power_down(void);
64
76/* executes code for Quantum */ 65/* executes code for Quantum */
77void matrix_init_quantum(void); 66void matrix_init_quantum(void);
78void matrix_scan_quantum(void); 67void matrix_scan_quantum(void);