You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
10 KiB

  1. /*
  2. Copyright 2012-2018 Jun Wako, Jack Humbert, Mike Roberts
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /*
  15. * This matrix.c has been hacked up to support some columns being on an ex pander in ROW2COL mode.
  16. * The columns are only ever selected and unselected, never read. Unselecting a single column via the expander is not
  17. * implemented because updating one column costs the same as updating all the columns in a bank. Currently both banks
  18. * are unselected but two i2c transactions could be removed if we only unselect the the proper half.
  19. */
  20. #include <stdint.h>
  21. #include <stdbool.h>
  22. #if defined(__AVR__)
  23. #include <avr/io.h>
  24. #endif
  25. #include "wait.h"
  26. #include "print.h"
  27. #include "debug.h"
  28. #include "util.h"
  29. #include "matrix.h"
  30. #include "timer.h"
  31. #include "mcp23017.h"
  32. #include "outputselect.h"
  33. /* Set 0 if debouncing isn't needed */
  34. #ifndef DEBOUNCE
  35. # define DEBOUNCE 5
  36. #endif
  37. #if (DEBOUNCE > 0)
  38. static uint16_t debouncing_time;
  39. static bool debouncing = false;
  40. #endif
  41. #if (MATRIX_COLS <= 8)
  42. # define print_matrix_header() print("\nr/c 01234567\n")
  43. # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
  44. # define matrix_bitpop(i) bitpop(matrix[i])
  45. # define ROW_SHIFTER ((uint8_t)1)
  46. #elif (MATRIX_COLS <= 16)
  47. # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
  48. # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
  49. # define matrix_bitpop(i) bitpop16(matrix[i])
  50. # define ROW_SHIFTER ((uint16_t)1)
  51. #elif (MATRIX_COLS <= 32)
  52. # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
  53. # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
  54. # define matrix_bitpop(i) bitpop32(matrix[i])
  55. # define ROW_SHIFTER ((uint32_t)1)
  56. #endif
  57. #ifdef MATRIX_MASKED
  58. extern const matrix_row_t matrix_mask[];
  59. #endif
  60. #if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
  61. static const uint8_t row_pins[MATRIX_ROWS] = NEK_MATRIX_ROW_PINS;
  62. static const uint8_t col_pins[MATRIX_COLS] = NEK_MATRIX_COL_PINS;
  63. static const bool col_expanded[MATRIX_COLS] = COL_EXPANDED;
  64. #endif
  65. /* matrix state(1:on, 0:off) */
  66. static matrix_row_t matrix[MATRIX_ROWS];
  67. static matrix_row_t matrix_debouncing[MATRIX_ROWS];
  68. #if (DIODE_DIRECTION == COL2ROW)
  69. static void init_cols(void);
  70. static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
  71. static void unselect_rows(void);
  72. static void select_row(uint8_t row);
  73. static void unselect_row(uint8_t row);
  74. #elif (DIODE_DIRECTION == ROW2COL)
  75. static void init_rows(void);
  76. static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
  77. static void unselect_cols(void);
  78. static void unselect_col(uint8_t col);
  79. static void select_col(uint8_t col);
  80. #endif
  81. __attribute__ ((weak))
  82. void matrix_init_quantum(void) {
  83. expander_init();
  84. matrix_init_kb();
  85. }
  86. __attribute__ ((weak))
  87. void matrix_scan_quantum(void) {
  88. matrix_scan_kb();
  89. }
  90. __attribute__ ((weak))
  91. void matrix_init_kb(void) {
  92. matrix_init_user();
  93. }
  94. __attribute__ ((weak))
  95. void matrix_scan_kb(void) {
  96. matrix_scan_user();
  97. }
  98. __attribute__ ((weak))
  99. void matrix_init_user(void) {
  100. }
  101. __attribute__ ((weak))
  102. void matrix_scan_user(void) {
  103. }
  104. inline
  105. uint8_t matrix_rows(void) {
  106. return MATRIX_ROWS;
  107. }
  108. inline
  109. uint8_t matrix_cols(void) {
  110. return MATRIX_COLS;
  111. }
  112. void matrix_init(void) {
  113. // initialize row and col
  114. #if (DIODE_DIRECTION == COL2ROW)
  115. unselect_rows();
  116. init_cols();
  117. #elif (DIODE_DIRECTION == ROW2COL)
  118. unselect_cols();
  119. init_rows();
  120. #endif
  121. // initialize matrix state: all keys off
  122. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  123. matrix[i] = 0;
  124. matrix_debouncing[i] = 0;
  125. }
  126. matrix_init_quantum();
  127. set_output(OUTPUT_AUTO);
  128. }
  129. uint8_t matrix_scan(void)
  130. {
  131. #if (DIODE_DIRECTION == COL2ROW)
  132. // Set row, read cols
  133. for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
  134. # if (DEBOUNCE > 0)
  135. bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
  136. if (matrix_changed) {
  137. debouncing = true;
  138. debouncing_time = timer_read();
  139. }
  140. # else
  141. read_cols_on_row(matrix, current_row);
  142. # endif
  143. }
  144. #elif (DIODE_DIRECTION == ROW2COL)
  145. // Set col, read rows
  146. for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
  147. # if (DEBOUNCE > 0)
  148. bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
  149. if (matrix_changed) {
  150. debouncing = true;
  151. debouncing_time = timer_read();
  152. }
  153. # else
  154. read_rows_on_col(matrix, current_col);
  155. # endif
  156. }
  157. #endif
  158. # if (DEBOUNCE > 0)
  159. if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) {
  160. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  161. matrix[i] = matrix_debouncing[i];
  162. }
  163. debouncing = false;
  164. }
  165. # endif
  166. matrix_scan_quantum();
  167. return 1;
  168. }
  169. bool matrix_is_modified(void)
  170. {
  171. #if (DEBOUNCE > 0)
  172. if (debouncing) return false;
  173. #endif
  174. return true;
  175. }
  176. inline
  177. bool matrix_is_on(uint8_t row, uint8_t col)
  178. {
  179. return (matrix[row] & ((matrix_row_t)1<col));
  180. }
  181. inline
  182. matrix_row_t matrix_get_row(uint8_t row)
  183. {
  184. // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
  185. // switch blocker installed and the switch is always pressed.
  186. #ifdef MATRIX_MASKED
  187. return matrix[row] & matrix_mask[row];
  188. #else
  189. return matrix[row];
  190. #endif
  191. }
  192. void matrix_print(void)
  193. {
  194. print_matrix_header();
  195. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  196. print_hex8(row); print(": ");
  197. print_matrix_row(row);
  198. print("\n");
  199. }
  200. }
  201. uint8_t matrix_key_count(void)
  202. {
  203. uint8_t count = 0;
  204. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  205. count += matrix_bitpop(i);
  206. }
  207. return count;
  208. }
  209. #if (DIODE_DIRECTION == COL2ROW)
  210. static void init_cols(void)
  211. {
  212. for(uint8_t x = 0; x < MATRIX_COLS; x++) {
  213. uint8_t pin = col_pins[x];
  214. _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
  215. _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
  216. }
  217. }
  218. static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
  219. {
  220. // Store last value of row prior to reading
  221. matrix_row_t last_row_value = current_matrix[current_row];
  222. // Clear data in matrix row
  223. current_matrix[current_row] = 0;
  224. // Select row and wait for row selecton to stabilize
  225. select_row(current_row);
  226. wait_us(30);
  227. // For each col...
  228. for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
  229. // Select the col pin to read (active low)
  230. uint8_t pin = col_pins[col_index];
  231. uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
  232. // Populate the matrix row with the state of the col pin
  233. current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
  234. }
  235. // Unselect row
  236. unselect_row(current_row);
  237. return (last_row_value != current_matrix[current_row]);
  238. }
  239. static void select_row(uint8_t row)
  240. {
  241. uint8_t pin = row_pins[row];
  242. _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
  243. _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
  244. }
  245. static void unselect_row(uint8_t row)
  246. {
  247. uint8_t pin = row_pins[row];
  248. _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
  249. _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
  250. }
  251. static void unselect_rows(void)
  252. {
  253. for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
  254. uint8_t pin = row_pins[x];
  255. _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
  256. _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
  257. }
  258. }
  259. #elif (DIODE_DIRECTION == ROW2COL)
  260. static void init_rows(void)
  261. {
  262. for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
  263. uint8_t pin = row_pins[x];
  264. _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
  265. _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
  266. }
  267. }
  268. static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
  269. {
  270. bool matrix_changed = false;
  271. // Select col and wait for col selecton to stabilize
  272. select_col(current_col);
  273. wait_us(30);
  274. // For each row...
  275. for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
  276. {
  277. // Store last value of row prior to reading
  278. matrix_row_t last_row_value = current_matrix[row_index];
  279. // Check row pin state
  280. if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
  281. {
  282. // Pin LO, set col bit
  283. current_matrix[row_index] |= (ROW_SHIFTER << current_col);
  284. }
  285. else
  286. {
  287. // Pin HI, clear col bit
  288. current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
  289. }
  290. // Determine if the matrix changed state
  291. if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
  292. {
  293. matrix_changed = true;
  294. }
  295. }
  296. // Unselect col
  297. unselect_col(current_col);
  298. return matrix_changed;
  299. }
  300. static void select_col(uint8_t col)
  301. {
  302. uint8_t pin = col_pins[col];
  303. if (col_expanded[col])
  304. {
  305. expander_select(pin);
  306. }
  307. else
  308. {
  309. _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
  310. _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
  311. }
  312. }
  313. static void unselect_col(uint8_t col)
  314. {
  315. uint8_t pin = col_pins[col];
  316. if (col_expanded[col])
  317. {
  318. expander_unselect_all();
  319. }
  320. else
  321. {
  322. _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
  323. _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
  324. }
  325. }
  326. static void unselect_cols(void)
  327. {
  328. expander_unselect_all();
  329. for(uint8_t col = 0; col < MATRIX_COLS; col++) {
  330. uint8_t pin = col_pins[col];
  331. if (!col_expanded[col])
  332. {
  333. _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
  334. _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
  335. }
  336. }
  337. }
  338. #endif