7 #include <util/delay.h>
10 #include "matrix_skel.h"
13 #if (MATRIX_COLS > 16)
14 # error "MATRIX_COLS must not exceed 16"
16 #if (MATRIX_ROWS > 255)
17 # error "MATRIX_ROWS must not exceed 255"
21 // matrix state buffer(1:on, 0:off)
22 #if (MATRIX_COLS <= 8)
23 static uint8_t *matrix;
24 static uint8_t *matrix_prev;
25 static uint8_t _matrix0[MATRIX_ROWS];
26 static uint8_t _matrix1[MATRIX_ROWS];
28 static uint16_t *matrix;
29 static uint16_t *matrix_prev;
30 static uint16_t _matrix0[MATRIX_ROWS];
31 static uint16_t _matrix1[MATRIX_ROWS];
34 #ifdef MATRIX_HAS_GHOST
35 static bool matrix_has_ghost_in_row(uint8_t row);
39 // matrix is active low. (key on: 0/key off: 1)
41 // HHKB has no ghost and no bounce.
42 // row: HC4051 select input channel(0-8)
43 // PB0, PB1, PB2(A, B, C)
44 // col: LS145 select low output line(0-8)
45 // PB3, PB4, PB5, PB6(A, B, C, D)
46 // use D as ENABLE: (enable: 0/unenable: 1)
47 // key: KEY: (on: 0/ off:1)
48 // KEY_PREV: (on: 1/ off: 0)
49 // PE6,PE7(KEY, KEY_PREV)
50 #define COL_ENABLE (1<<6)
51 #define KEY_SELELCT(ROW, COL) (PORTB = (PORTB&(1<<7))|COL_ENABLE|(((COL)&0x07)<<3)|((ROW)&0x07))
52 #define KEY_ENABLE (PORTB &= ~COL_ENABLE)
53 #define KEY_UNABLE (PORTB |= COL_ENABLE)
54 #define KEY_STATE (PINE&(1<<6))
55 #define KEY_PREV_ON (PORTE |= (1<<7))
56 #define KEY_PREV_OFF (PORTE &= ~(1<<7))
60 uint8_t matrix_rows(void)
66 uint8_t matrix_cols(void)
71 void matrix_init(void)
73 // row & col output(PB0-6)
76 // KEY: input with pullup(PE6)
77 // KEY_PREV: output(PE7)
81 // initialize matrix state: all keys off
82 for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
83 for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
85 matrix_prev = _matrix1;
88 uint8_t matrix_scan(void)
96 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
97 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
98 KEY_SELELCT(row, col);
99 _delay_us(40); // from logic analyzer chart
100 if (matrix_prev[row] & (1<<col)) {
103 _delay_us(7); // from logic analyzer chart
105 _delay_us(10); // from logic analyzer chart
107 matrix[row] &= ~(1<<col);
109 matrix[row] |= (1<<col);
113 _delay_us(150); // from logic analyzer chart
119 bool matrix_is_modified(void)
121 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
122 if (matrix[i] != matrix_prev[i])
129 bool matrix_has_ghost(void)
131 #ifdef MATRIX_HAS_GHOST
132 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
133 if (matrix_has_ghost_in_row(i))
141 bool matrix_is_on(uint8_t row, uint8_t col)
143 return (matrix[row] & (1<<col));
147 #if (MATRIX_COLS <= 8)
148 uint8_t matrix_get_row(uint8_t row)
150 uint16_t matrix_get_row(uint8_t row)
156 void matrix_print(void)
158 #if (MATRIX_COLS <= 8)
159 print("\nr/c 01234567\n");
161 print("\nr/c 0123456789ABCDEF\n");
163 for (uint8_t row = 0; row < matrix_rows(); row++) {
164 phex(row); print(": ");
165 #if (MATRIX_COLS <= 8)
166 pbin_reverse(matrix_get_row(row));
168 pbin_reverse16(matrix_get_row(row));
170 #ifdef MATRIX_HAS_GHOST
171 if (matrix_has_ghost_in_row(row)) {
179 uint8_t matrix_key_count(void)
182 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
183 #if (MATRIX_COLS <= 8)
184 count += bitpop(matrix[i]);
186 count += bitpop16(matrix[i]);
192 #ifdef MATRIX_HAS_GHOST
194 static bool matrix_has_ghost_in_row(uint8_t row)
196 // no ghost exists in case less than 2 keys on
197 if (((matrix[row] - 1) & matrix[row]) == 0)
200 // ghost exists in case same state as other row
201 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
202 if (i != row && (matrix[i] & matrix[row]) == matrix[row])