logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

matrix.c (9091B)


  1. /*
  2. Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
  3. 2020 Pierre Chevalier <pierrechevalier83@gmail.com>
  4. 2021 weteor
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. /*
  17. * This code was heavily inspired by the ergodox_ez keymap, and modernized
  18. * to take advantage of the quantum.h microcontroller agnostics gpio control
  19. * abstractions and use the macros defined in config.h for the wiring as opposed
  20. * to repeating that information all over the place.
  21. */
  22. #include "matrix.h"
  23. #include "debug.h"
  24. #include "wait.h"
  25. #include "i2c_master.h"
  26. extern i2c_status_t tca9555_status;
  27. #define I2C_TIMEOUT 1000
  28. // I2C address:
  29. // All address pins of the tca9555 are connected to the ground
  30. // | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
  31. // | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
  32. #define I2C_ADDR (0b0100000 << 1)
  33. // Register addresses
  34. #define IODIRA 0x06 // i/o direction register
  35. #define IODIRB 0x07
  36. #define IREGP0 0x00 // GPIO pull-up resistor register
  37. #define IREGP1 0x01
  38. #define OREGP0 0x02 // general purpose i/o port register (write modifies OLAT)
  39. #define OREGP1 0x03
  40. bool i2c_initialized = 0;
  41. i2c_status_t tca9555_status = I2C_ADDR;
  42. uint8_t init_tca9555(void) {
  43. print("starting init");
  44. tca9555_status = I2C_ADDR;
  45. // I2C subsystem
  46. if (i2c_initialized == 0) {
  47. i2c_init(); // on pins D(1,0)
  48. i2c_initialized = true;
  49. wait_ms(I2C_TIMEOUT);
  50. }
  51. // set pin direction
  52. // - unused : input : 1
  53. // - input : input : 1
  54. // - driving : output : 0
  55. uint8_t conf[2] = {
  56. // This means: read all pins of port 0
  57. 0b11111111,
  58. // This means: we will write on pins 0 to 3 on port 1. read rest
  59. 0b11110000,
  60. };
  61. tca9555_status = i2c_write_register(I2C_ADDR, IODIRA, conf, 2, I2C_TIMEOUT);
  62. return tca9555_status;
  63. }
  64. /* matrix state(1:on, 0:off) */
  65. static matrix_row_t matrix[MATRIX_ROWS]; // debounced values
  66. static matrix_row_t read_cols(uint8_t row);
  67. static void init_cols(void);
  68. static void unselect_rows(void);
  69. static void select_row(uint8_t row);
  70. static uint8_t tca9555_reset_loop;
  71. void matrix_init_custom(void) {
  72. // initialize row and col
  73. tca9555_status = init_tca9555();
  74. unselect_rows();
  75. init_cols();
  76. // initialize matrix state: all keys off
  77. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  78. matrix[i] = 0;
  79. }
  80. }
  81. void matrix_power_up(void) {
  82. tca9555_status = init_tca9555();
  83. unselect_rows();
  84. init_cols();
  85. // initialize matrix state: all keys off
  86. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  87. matrix[i] = 0;
  88. }
  89. }
  90. // Reads and stores a row, returning
  91. // whether a change occurred.
  92. static inline bool store_matrix_row(matrix_row_t current_matrix[], uint8_t index) {
  93. matrix_row_t temp = read_cols(index);
  94. if (current_matrix[index] != temp) {
  95. current_matrix[index] = temp;
  96. return true;
  97. }
  98. return false;
  99. }
  100. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  101. if (tca9555_status) { // if there was an error
  102. if (++tca9555_reset_loop == 0) {
  103. // since tca9555_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
  104. // this will be approx bit more frequent than once per second
  105. dprint("trying to reset tca9555\n");
  106. tca9555_status = init_tca9555();
  107. if (tca9555_status) {
  108. dprint("right side not responding\n");
  109. } else {
  110. dprint("right side attached\n");
  111. }
  112. }
  113. }
  114. bool changed = false;
  115. for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
  116. // select rows from left and right hands
  117. uint8_t left_index = i;
  118. uint8_t right_index = i + MATRIX_ROWS_PER_SIDE;
  119. select_row(left_index);
  120. select_row(right_index);
  121. // we don't need a 30us delay anymore, because selecting a
  122. // left-hand row requires more than 30us for i2c.
  123. changed |= store_matrix_row(current_matrix, left_index);
  124. changed |= store_matrix_row(current_matrix, right_index);
  125. unselect_rows();
  126. }
  127. return changed;
  128. }
  129. static void init_cols(void) {
  130. // init on tca9555
  131. // not needed, already done as part of init_tca9555()
  132. // init on mcu
  133. pin_t matrix_col_pins_mcu[MATRIX_COLS_PER_SIDE] = MATRIX_COL_PINS_L;
  134. for (int pin_index = 0; pin_index < MATRIX_COLS_PER_SIDE; pin_index++) {
  135. pin_t pin = matrix_col_pins_mcu[pin_index];
  136. gpio_set_pin_input(pin);
  137. gpio_write_pin_high(pin);
  138. }
  139. }
  140. static matrix_row_t read_cols(uint8_t row) {
  141. if (row < MATRIX_ROWS_PER_SIDE) {
  142. pin_t matrix_col_pins_mcu[MATRIX_COLS_PER_SIDE] = MATRIX_COL_PINS_L;
  143. matrix_row_t current_row_value = 0;
  144. // For each col...
  145. for (uint8_t col_index = 0; col_index < MATRIX_COLS_PER_SIDE; col_index++) {
  146. // Select the col pin to read (active low)
  147. uint8_t pin_state = gpio_read_pin(matrix_col_pins_mcu[col_index]);
  148. // Populate the matrix row with the state of the col pin
  149. current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
  150. }
  151. return current_row_value;
  152. } else {
  153. if (tca9555_status) { // if there was an error
  154. return 0;
  155. } else {
  156. uint8_t data = 0;
  157. uint8_t port0 = 0;
  158. tca9555_status = i2c_read_register(I2C_ADDR, IREGP0, &port0, 1, I2C_TIMEOUT);
  159. if (tca9555_status) { // if there was an error
  160. // do nothing
  161. return 0;
  162. } else {
  163. port0 = ~port0;
  164. // We read all the pins on GPIOA.
  165. // The initial state was all ones and any depressed key at a given column for the currently selected row will have its bit flipped to zero.
  166. // The return value is a row as represented in the generic matrix code were the rightmost bits represent the lower columns and zeroes represent non-depressed keys while ones represent depressed keys.
  167. // the pins connected to eact columns are sequential, but in reverse order, and counting from zero down (col 5 -> GPIO04, col6 -> GPIO03 and so on).
  168. data |= (port0 & 0x01) << 4;
  169. data |= (port0 & 0x02) << 2;
  170. data |= (port0 & 0x04);
  171. data |= (port0 & 0x08) >> 2;
  172. data |= (port0 & 0x10) >> 4;
  173. tca9555_status = I2C_STATUS_SUCCESS;
  174. return data;
  175. }
  176. }
  177. }
  178. }
  179. static void unselect_rows(void) {
  180. // no need to unselect on tca9555, because the select step sets all
  181. // the other row bits high, and it's not changing to a different
  182. // direction
  183. // unselect rows on microcontroller
  184. pin_t matrix_row_pins_mcu[MATRIX_ROWS_PER_SIDE] = MATRIX_ROW_PINS_L;
  185. for (int pin_index = 0; pin_index < MATRIX_ROWS_PER_SIDE; pin_index++) {
  186. pin_t pin = matrix_row_pins_mcu[pin_index];
  187. gpio_set_pin_input(pin);
  188. gpio_write_pin_low(pin);
  189. }
  190. }
  191. static void select_row(uint8_t row) {
  192. uint8_t port1 = 0xff;
  193. if (row < MATRIX_ROWS_PER_SIDE) {
  194. // select on atmega32u4
  195. pin_t matrix_row_pins_mcu[MATRIX_ROWS_PER_SIDE] = MATRIX_ROW_PINS_L;
  196. pin_t pin = matrix_row_pins_mcu[row];
  197. gpio_set_pin_output(pin);
  198. gpio_write_pin_low(pin);
  199. } else {
  200. // select on tca9555
  201. if (tca9555_status) { // if there was an error
  202. // do nothing
  203. } else {
  204. switch(row) {
  205. case 4: port1 &= ~(1 << 0); break;
  206. case 5: port1 &= ~(1 << 1); break;
  207. case 6: port1 &= ~(1 << 2); break;
  208. case 7:
  209. port1 &= ~(1 << 3);
  210. break;
  211. default: break;
  212. }
  213. tca9555_status = i2c_write_register(I2C_ADDR, OREGP1, &port1, 1, I2C_TIMEOUT);
  214. // Select the desired row by writing a byte for the entire GPIOB bus where only the bit representing the row we want to select is a zero (write instruction) and every other bit is a one.
  215. // Note that the row - MATRIX_ROWS_PER_SIDE reflects the fact that being on the right hand, the columns are numbered from MATRIX_ROWS_PER_SIDE to MATRIX_ROWS, but the pins we want to write to are indexed from zero up on the GPIOB bus.
  216. }
  217. }
  218. }