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.

171 lines
4.2 KiB

  1. /*
  2. Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
  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. #include "matrix.h"
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include <avr/io.h>
  18. #include "wait.h"
  19. #include "action_layer.h"
  20. #include "print.h"
  21. #include "debug.h"
  22. #include "util.h"
  23. #include "sp64.h"
  24. #include "debounce.h"
  25. /* matrix state(1:on, 0:off) */
  26. static matrix_row_t matrix[MATRIX_ROWS];
  27. // Debouncing: store for each key the number of scans until it's eligible to
  28. // change. When scanning the matrix, ignore any changes in keys that have
  29. // already changed in the last DEBOUNCE scans.
  30. static matrix_row_t matrix_debouncing[MATRIX_ROWS];
  31. static void matrix_select_row(uint8_t row);
  32. #ifdef RIGHT_HALF
  33. static uint8_t mcp23018_reset_loop = 0;
  34. #endif
  35. // user-defined overridable functions
  36. __attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
  37. __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
  38. __attribute__((weak)) void matrix_init_user(void) {}
  39. __attribute__((weak)) void matrix_scan_user(void) {}
  40. // helper functions
  41. void matrix_init(void)
  42. {
  43. // all outputs for rows high
  44. DDRB = 0xFF;
  45. PORTB = 0xFF;
  46. // all inputs for columns
  47. DDRA = 0x00;
  48. DDRC &= ~(0x111111<<2);
  49. DDRD &= ~(1<<PIND7);
  50. // all columns are pulled-up
  51. PORTA = 0xFF;
  52. PORTC |= (0b111111<<2);
  53. PORTD |= (1<<PIND7);
  54. #ifdef RIGHT_HALF
  55. // initialize row and col
  56. mcp23018_status = init_mcp23018();
  57. #endif
  58. // initialize matrix state: all keys off
  59. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  60. matrix[row] = 0;
  61. matrix_debouncing[row] = 0;
  62. }
  63. debounce_init(MATRIX_ROWS);
  64. matrix_init_quantum();
  65. }
  66. uint8_t matrix_scan(void)
  67. {
  68. #ifdef RIGHT_HALF
  69. // Then the keyboard
  70. if (mcp23018_status != I2C_STATUS_SUCCESS) {
  71. if (++mcp23018_reset_loop == 0) {
  72. // if (++mcp23018_reset_loop >= 1300) {
  73. // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
  74. // this will be approx bit more frequent than once per second
  75. print("trying to reset mcp23018\n");
  76. mcp23018_status = init_mcp23018();
  77. if (mcp23018_status) {
  78. print("left side not responding\n");
  79. } else {
  80. print("left side attached\n");
  81. }
  82. }
  83. }
  84. #endif
  85. bool changed = false;
  86. for (uint8_t row = 0; row < MATRIX_ROWS; row++)
  87. {
  88. matrix_row_t cols;
  89. matrix_select_row(row);
  90. #ifndef RIGHT_HALF
  91. _delay_us(5);
  92. #endif
  93. cols = (
  94. // cols 0..7, PORTA 0 -> 7
  95. (~PINA) & 0xFF
  96. );
  97. #ifdef RIGHT_HALF
  98. uint8_t data = 0x7F;
  99. // Receive the columns from right half
  100. i2c_receive(I2C_ADDR_WRITE, &data, 1, MCP23018_I2C_TIMEOUT);
  101. cols |= ((~(data) & 0x7F) << 7);
  102. #endif
  103. if (matrix_debouncing[row] != cols) {
  104. matrix_debouncing[row] = cols;
  105. //debouncing = DEBOUNCE;
  106. changed = true;
  107. }
  108. }
  109. debounce(matrix_debouncing, matrix, MATRIX_ROWS, changed);
  110. matrix_scan_quantum();
  111. #ifdef DEBUG_MATRIX
  112. for (uint8_t c = 0; c < MATRIX_COLS; c++)
  113. for (uint8_t r = 0; r < MATRIX_ROWS; r++)
  114. if (matrix_is_on(r, c)) xprintf("r:%d c:%d \n", r, c);
  115. #endif
  116. return (uint8_t)changed;
  117. }
  118. inline
  119. matrix_row_t matrix_get_row(uint8_t row)
  120. {
  121. return matrix[row];
  122. }
  123. void matrix_print(void)
  124. {
  125. print("\nr/c 0123456789ABCDEF\n");
  126. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  127. print_hex8(row); print(": ");
  128. print_bin_reverse16(matrix_get_row(row));
  129. print("\n");
  130. }
  131. }
  132. static void matrix_select_row(uint8_t row)
  133. {
  134. #ifdef RIGHT_HALF
  135. uint8_t txdata[3];
  136. //Set the remote row on port A
  137. txdata[0] = GPIOA;
  138. txdata[1] = 0xFF & ~(1<<row);
  139. mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)txdata, 2, MCP23018_I2C_TIMEOUT);
  140. #endif
  141. // select other half
  142. DDRB = (1 << row);
  143. PORTB = ~(1 << row);
  144. }