matrix.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. void matrix_init(void)
  36. {
  37. // all outputs for rows high
  38. DDRB = 0xFF;
  39. PORTB = 0xFF;
  40. // all inputs for columns
  41. DDRA = 0x00;
  42. DDRC &= ~(0x111111<<2);
  43. DDRD &= ~(1<<PIND7);
  44. // all columns are pulled-up
  45. PORTA = 0xFF;
  46. PORTC |= (0b111111<<2);
  47. PORTD |= (1<<PIND7);
  48. #ifdef RIGHT_HALF
  49. // initialize row and col
  50. mcp23018_status = init_mcp23018();
  51. #endif
  52. // initialize matrix state: all keys off
  53. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  54. matrix[row] = 0;
  55. matrix_debouncing[row] = 0;
  56. }
  57. debounce_init(MATRIX_ROWS);
  58. matrix_init_quantum();
  59. }
  60. uint8_t matrix_scan(void)
  61. {
  62. #ifdef RIGHT_HALF
  63. // Then the keyboard
  64. if (mcp23018_status != I2C_STATUS_SUCCESS) {
  65. if (++mcp23018_reset_loop == 0) {
  66. // if (++mcp23018_reset_loop >= 1300) {
  67. // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
  68. // this will be approx bit more frequent than once per second
  69. print("trying to reset mcp23018\n");
  70. mcp23018_status = init_mcp23018();
  71. if (mcp23018_status) {
  72. print("left side not responding\n");
  73. } else {
  74. print("left side attached\n");
  75. }
  76. }
  77. }
  78. #endif
  79. bool changed = false;
  80. for (uint8_t row = 0; row < MATRIX_ROWS; row++)
  81. {
  82. matrix_row_t cols;
  83. matrix_select_row(row);
  84. #ifndef RIGHT_HALF
  85. _delay_us(5);
  86. #endif
  87. cols = (
  88. // cols 0..7, PORTA 0 -> 7
  89. (~PINA) & 0xFF
  90. );
  91. #ifdef RIGHT_HALF
  92. uint8_t data = 0x7F;
  93. // Receive the columns from right half
  94. i2c_receive(I2C_ADDR_WRITE, &data, 1, MCP23018_I2C_TIMEOUT);
  95. cols |= ((~(data) & 0x7F) << 7);
  96. #endif
  97. if (matrix_debouncing[row] != cols) {
  98. matrix_debouncing[row] = cols;
  99. //debouncing = DEBOUNCE;
  100. changed = true;
  101. }
  102. }
  103. debounce(matrix_debouncing, matrix, MATRIX_ROWS, changed);
  104. matrix_scan_quantum();
  105. #ifdef DEBUG_MATRIX
  106. for (uint8_t c = 0; c < MATRIX_COLS; c++)
  107. for (uint8_t r = 0; r < MATRIX_ROWS; r++)
  108. if (matrix_is_on(r, c)) xprintf("r:%d c:%d \n", r, c);
  109. #endif
  110. return (uint8_t)changed;
  111. }
  112. inline
  113. matrix_row_t matrix_get_row(uint8_t row)
  114. {
  115. return matrix[row];
  116. }
  117. void matrix_print(void)
  118. {
  119. print("\nr/c 0123456789ABCDEF\n");
  120. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  121. print_hex8(row); print(": ");
  122. print_bin_reverse16(matrix_get_row(row));
  123. print("\n");
  124. }
  125. }
  126. uint8_t matrix_key_count(void)
  127. {
  128. uint8_t count = 0;
  129. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  130. count += bitpop16(matrix[i]);
  131. }
  132. return count;
  133. }
  134. static void matrix_select_row(uint8_t row)
  135. {
  136. #ifdef RIGHT_HALF
  137. uint8_t txdata[3];
  138. //Set the remote row on port A
  139. txdata[0] = GPIOA;
  140. txdata[1] = 0xFF & ~(1<<row);
  141. mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)txdata, 2, MCP23018_I2C_TIMEOUT);
  142. #endif
  143. // select other half
  144. DDRB = (1 << row);
  145. PORTB = ~(1 << row);
  146. }