matrix.c 4.5 KB

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