logo

qmk_firmware

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

matrix.c (6908B)


  1. /* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
  2. * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
  3. * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
  4. *
  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. *
  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. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "moonlander.h"
  19. #include "mcp23018.h"
  20. #pragma GCC push_options
  21. #pragma GCC optimize("-O3")
  22. /*
  23. #define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 } outputs
  24. #define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 } inputs
  25. #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs
  26. #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs
  27. */
  28. /* matrix state(1:on, 0:off) */
  29. extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
  30. extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
  31. static matrix_row_t raw_matrix_right[MATRIX_ROWS];
  32. #define MCP_ROWS_PER_HAND (MATRIX_ROWS / 2)
  33. extern bool mcp23018_leds[3];
  34. extern bool is_launching;
  35. static uint16_t mcp23018_reset_loop;
  36. uint8_t mcp23018_errors;
  37. bool io_expander_ready(void) {
  38. uint8_t tx;
  39. return mcp23018_read_pins(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTA, &tx);
  40. }
  41. void matrix_init_custom(void) {
  42. // outputs
  43. gpio_set_pin_output(B10);
  44. gpio_set_pin_output(B11);
  45. gpio_set_pin_output(B12);
  46. gpio_set_pin_output(B13);
  47. gpio_set_pin_output(B14);
  48. gpio_set_pin_output(B15);
  49. // inputs
  50. gpio_set_pin_input_low(A0);
  51. gpio_set_pin_input_low(A1);
  52. gpio_set_pin_input_low(A2);
  53. gpio_set_pin_input_low(A3);
  54. gpio_set_pin_input_low(A6);
  55. gpio_set_pin_input_low(A7);
  56. gpio_set_pin_input_low(B0);
  57. mcp23018_init(MCP23018_DEFAULT_ADDRESS);
  58. mcp23018_errors += !mcp23018_set_config(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTA, 0b00000000);
  59. mcp23018_errors += !mcp23018_set_config(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTB, 0b00111111);
  60. if (!mcp23018_errors) {
  61. is_launching = true;
  62. }
  63. }
  64. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  65. bool changed = false;
  66. // Attempt to reset the mcp23018 if it's not initialized
  67. if (mcp23018_errors) {
  68. if (++mcp23018_reset_loop > 0x1FFF) {
  69. if (io_expander_ready()) {
  70. // If we managed to initialize the mcp23018 - we need to reinitialize the matrix / layer state. During an electric discharge the i2c peripherals might be in a weird state. Giving a delay and resetting the MCU allows to recover from this.
  71. wait_ms(200);
  72. mcu_reset();
  73. }
  74. }
  75. }
  76. matrix_row_t data = 0;
  77. // actual matrix
  78. for (uint8_t row = 0; row <= MCP_ROWS_PER_HAND; row++) {
  79. // strobe row
  80. switch (row) {
  81. case 0:
  82. gpio_write_pin_high(B10);
  83. break;
  84. case 1:
  85. gpio_write_pin_high(B11);
  86. break;
  87. case 2:
  88. gpio_write_pin_high(B12);
  89. break;
  90. case 3:
  91. gpio_write_pin_high(B13);
  92. break;
  93. case 4:
  94. gpio_write_pin_high(B14);
  95. break;
  96. case 5:
  97. gpio_write_pin_high(B15);
  98. break;
  99. case 6:
  100. break; // Left hand has 6 rows
  101. }
  102. // Selecting the row on the right side of the keyboard.
  103. if (!mcp23018_errors) {
  104. // select row
  105. mcp23018_errors += !mcp23018_set_output_all(MCP23018_DEFAULT_ADDRESS, (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7), ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7));
  106. }
  107. // Reading the left side of the keyboard.
  108. if (row < MCP_ROWS_PER_HAND) {
  109. // i2c comm incur enough wait time
  110. if (mcp23018_errors) {
  111. // need wait to settle pin state
  112. matrix_io_delay();
  113. }
  114. // read col data
  115. data = ((gpio_read_pin(A0) << 0) | (gpio_read_pin(A1) << 1) | (gpio_read_pin(A2) << 2) | (gpio_read_pin(A3) << 3) | (gpio_read_pin(A6) << 4) | (gpio_read_pin(A7) << 5) | (gpio_read_pin(B0) << 6));
  116. // unstrobe row
  117. switch (row) {
  118. case 0:
  119. gpio_write_pin_low(B10);
  120. break;
  121. case 1:
  122. gpio_write_pin_low(B11);
  123. break;
  124. case 2:
  125. gpio_write_pin_low(B12);
  126. break;
  127. case 3:
  128. gpio_write_pin_low(B13);
  129. break;
  130. case 4:
  131. gpio_write_pin_low(B14);
  132. break;
  133. case 5:
  134. gpio_write_pin_low(B15);
  135. break;
  136. case 6:
  137. break;
  138. }
  139. if (current_matrix[row] != data) {
  140. current_matrix[row] = data;
  141. changed = true;
  142. }
  143. }
  144. // Reading the right side of the keyboard.
  145. if (!mcp23018_errors) {
  146. uint8_t rx;
  147. mcp23018_errors += !mcp23018_read_pins(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTB, &rx);
  148. data = ~(rx & 0b00111111);
  149. } else {
  150. data = 0;
  151. }
  152. if (raw_matrix_right[row] != data) {
  153. raw_matrix_right[row] = data;
  154. changed = true;
  155. }
  156. }
  157. for (uint8_t row = 0; row < MCP_ROWS_PER_HAND; row++) {
  158. current_matrix[11 - row] = 0;
  159. for (uint8_t col = 0; col < MATRIX_COLS; col++) {
  160. current_matrix[11 - row] |= ((raw_matrix_right[6 - col] & (1 << row) ? 1 : 0) << col);
  161. }
  162. }
  163. return changed;
  164. }
  165. // DO NOT REMOVE
  166. // Needed for proper wake/sleep
  167. void matrix_power_up(void) {
  168. bool temp_launching = is_launching;
  169. matrix_init_custom();
  170. is_launching = temp_launching;
  171. if (!is_launching) {
  172. ML_LED_1(false);
  173. ML_LED_2(false);
  174. ML_LED_3(false);
  175. ML_LED_4(false);
  176. ML_LED_5(false);
  177. ML_LED_6(false);
  178. }
  179. // initialize matrix state: all keys off
  180. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  181. matrix[i] = 0;
  182. }
  183. }
  184. bool is_transport_connected(void) {
  185. return (bool)(mcp23018_errors == 0);
  186. }
  187. #pragma GCC pop_options