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.

312 lines
7.5 KiB

  1. /*
  2. Copyright 2019 worthlessowl
  3. based on work by:
  4. Jun Wako <wakojun@gmail.com>
  5. Cole Markham <cole@ccmcomputing.net>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /*
  18. * scan matrix
  19. */
  20. #include <stdint.h>
  21. #include <stdbool.h>
  22. #include "owlet60.h"
  23. #include "wait.h"
  24. #include "print.h"
  25. #include "debug.h"
  26. #include "util.h"
  27. #include "matrix.h"
  28. #include "config.h"
  29. #include "timer.h"
  30. #if (MATRIX_COLS <= 8)
  31. # define print_matrix_header() print("\nr/c 01234567\n")
  32. # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
  33. # define matrix_bitpop(i) bitpop(matrix[i])
  34. # define ROW_SHIFTER ((uint8_t)1)
  35. #elif (MATRIX_COLS <= 16)
  36. # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
  37. # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
  38. # define matrix_bitpop(i) bitpop16(matrix[i])
  39. # define ROW_SHIFTER ((uint16_t)1)
  40. #elif (MATRIX_COLS <= 32)
  41. # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
  42. # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
  43. # define matrix_bitpop(i) bitpop32(matrix[i])
  44. # define ROW_SHIFTER ((uint32_t)1)
  45. #endif
  46. static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
  47. static const uint8_t col_select_pins[3] = MATRIX_COL_SELECT_PINS;
  48. static const uint8_t dat_pin = MATRIX_COL_DATA_PIN;
  49. /* matrix state(1:on, 0:off) */
  50. static matrix_row_t raw_matrix[MATRIX_ROWS]; //raw values
  51. static matrix_row_t matrix[MATRIX_ROWS]; //raw values
  52. /* 2d array containing binary representation of its index */
  53. static const uint8_t num_in_binary[8][3] = {
  54. {0, 0, 0},
  55. {0, 0, 1},
  56. {0, 1, 0},
  57. {0, 1, 1},
  58. {1, 0, 0},
  59. {1, 0, 1},
  60. {1, 1, 0},
  61. {1, 1, 1},
  62. };
  63. static void select_col_analog(uint8_t col);
  64. static void mux_pin_control(const uint8_t binary[]);
  65. void debounce_init(uint8_t num_rows);
  66. void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed);
  67. __attribute__ ((weak))
  68. void matrix_init_user(void) {}
  69. __attribute__ ((weak))
  70. void matrix_scan_user(void) {}
  71. __attribute__ ((weak))
  72. void matrix_init_kb(void) {
  73. matrix_init_user();
  74. }
  75. __attribute__ ((weak))
  76. void matrix_scan_kb(void) {
  77. matrix_scan_user();
  78. }
  79. inline
  80. uint8_t matrix_rows(void)
  81. {
  82. return MATRIX_ROWS;
  83. }
  84. inline
  85. uint8_t matrix_cols(void)
  86. {
  87. return MATRIX_COLS;
  88. }
  89. inline
  90. bool matrix_is_on(uint8_t row, uint8_t col)
  91. {
  92. return (matrix[row] & ((matrix_row_t)1<<col));
  93. }
  94. inline
  95. matrix_row_t matrix_get_row(uint8_t row)
  96. {
  97. // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
  98. // switch blocker installed and the switch is always pressed.
  99. #ifdef MATRIX_MASKED
  100. return matrix[row] & matrix_mask[row];
  101. #else
  102. return matrix[row];
  103. #endif
  104. }
  105. void matrix_print(void)
  106. {
  107. print_matrix_header();
  108. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  109. print_hex8(row); print(": ");
  110. print_matrix_row(row);
  111. print("\n");
  112. }
  113. }
  114. uint8_t matrix_key_count(void)
  115. {
  116. uint8_t count = 0;
  117. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  118. count += matrix_bitpop(i);
  119. }
  120. return count;
  121. }
  122. // uses standard row code
  123. static void select_row(uint8_t row)
  124. {
  125. setPinOutput(row_pins[row]);
  126. writePinLow(row_pins[row]);
  127. }
  128. static void unselect_row(uint8_t row)
  129. {
  130. setPinInputHigh(row_pins[row]);
  131. }
  132. static void unselect_rows(void)
  133. {
  134. for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
  135. setPinInputHigh(row_pins[x]);
  136. }
  137. }
  138. static void init_pins(void) { // still need some fixing, this might not work
  139. unselect_rows(); // with the loop
  140. /*
  141. for (uint8_t x = 0; x < MATRIX_COLS; x++) {
  142. setPinInputHigh(col_pins[x]);
  143. }
  144. */
  145. setPinInputHigh(dat_pin);
  146. }
  147. static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
  148. {
  149. // Store last value of row prior to reading
  150. matrix_row_t last_row_value = current_matrix[current_row];
  151. // Clear data in matrix row
  152. current_matrix[current_row] = 0;
  153. // Select row and wait for row selecton to stabilize
  154. select_row(current_row);
  155. wait_us(30);
  156. // For each col...
  157. for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
  158. // Select the col pin to read (active low)
  159. select_col_analog(col_index);
  160. wait_us(30);
  161. uint8_t pin_state = readPin(dat_pin);
  162. // Populate the matrix row with the state of the col pin
  163. current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
  164. }
  165. // Unselect row
  166. unselect_row(current_row);
  167. return (last_row_value != current_matrix[current_row]);
  168. }
  169. void matrix_init(void) {
  170. // initialize key pins
  171. init_pins();
  172. // initialize matrix state: all keys off
  173. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  174. raw_matrix[i] = 0;
  175. matrix[i] = 0;
  176. }
  177. debounce_init(MATRIX_ROWS);
  178. matrix_init_quantum();
  179. setPinInput(D5);
  180. setPinInput(B0);
  181. }
  182. // modified for per col read matrix scan
  183. uint8_t matrix_scan(void)
  184. {
  185. bool changed = false;
  186. for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
  187. changed |= read_cols_on_row(raw_matrix, current_row);
  188. }
  189. debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
  190. matrix_scan_quantum();
  191. return (uint8_t)changed;
  192. }
  193. /*
  194. uint8_t matrix_scan(void)
  195. {
  196. bool changed = false;
  197. #if (DIODE_DIRECTION == COL2ROW)
  198. // Set row, read cols
  199. for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
  200. changed |= read_cols_on_row(raw_matrix, current_row);
  201. }
  202. #endif
  203. debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
  204. matrix_scan_quantum();
  205. return (uint8_t)changed;
  206. }
  207. */
  208. static void select_col_analog(uint8_t col) {
  209. switch(col) {
  210. case 0:
  211. mux_pin_control(num_in_binary[0]);
  212. break;
  213. case 1:
  214. mux_pin_control(num_in_binary[1]);
  215. break;
  216. case 2:
  217. mux_pin_control(num_in_binary[2]);
  218. break;
  219. case 3:
  220. mux_pin_control(num_in_binary[3]);
  221. break;
  222. case 4:
  223. mux_pin_control(num_in_binary[4]);
  224. break;
  225. case 5:
  226. mux_pin_control(num_in_binary[5]);
  227. break;
  228. case 6:
  229. mux_pin_control(num_in_binary[6]);
  230. break;
  231. case 7:
  232. mux_pin_control(num_in_binary[7]);
  233. break;
  234. default:
  235. break;
  236. }
  237. }
  238. static void mux_pin_control(const uint8_t binary[]) {
  239. // set pin0
  240. setPinOutput(col_select_pins[0]);
  241. if(binary[2] == 0) {
  242. writePinLow(col_select_pins[0]);
  243. }
  244. else {
  245. writePinHigh(col_select_pins[0]);
  246. }
  247. // set pin1
  248. setPinOutput(col_select_pins[1]);
  249. if(binary[1] == 0) {
  250. writePinLow(col_select_pins[1]);
  251. }
  252. else {
  253. writePinHigh(col_select_pins[1]);
  254. }
  255. // set pin2
  256. setPinOutput(col_select_pins[2]);
  257. if(binary[0] == 0) {
  258. writePinLow(col_select_pins[2]);
  259. }
  260. else {
  261. writePinHigh(col_select_pins[2]);
  262. }
  263. }