logo

qmk_firmware

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

matrix.c (5299B)


  1. /*
  2. Copyright 2021 MajorKoos <github.com/majorkoos>
  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 "i2c_master.h"
  16. #define RIGHT_HALF
  17. void matrix_set_row_status(uint8_t row);
  18. #if defined(RIGHT_HALF)
  19. /* ----------------------- hardware I/O abstraction ------------------------ */
  20. #define PORTCOLUMNS PORTB ///< port on which we read the state of the columns
  21. #define PINCOLUMNS PINB ///< port on which we read the state of the columns
  22. #define DDRCOLUMNS DDRB ///< port on which we read the state of the columns
  23. #define PORTROWS1 PORTA ///< first port connected to the matrix rows
  24. #define PINROWS1 PINA ///< first port connected to the matrix rows
  25. #define DDRROWS1 DDRA ///< first port connected to the matrix rows
  26. #define PORTROWS2 PORTC ///< second port connected to the matrix rows
  27. #define PINROWS2 PINC ///< second port connected to the matrix rows
  28. #define DDRROWS2 DDRC ///< second port connected to the matrix rows
  29. // register addresses (see "mcp23018.md")
  30. #define IODIRA 0x00 // i/o direction register
  31. #define IODIRB 0x01
  32. #define GPPUA 0x0C // GPIO pull-up resistor register
  33. #define GPPUB 0x0D
  34. #define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
  35. #define GPIOB 0x13
  36. #define OLATA 0x14 // output latch register
  37. #define OLATB 0x15
  38. #define TW_READ 1
  39. #define TW_WRITE 0
  40. #define MCP23018_TWI_ADDRESS 0b0100000
  41. // TWI aliases
  42. #define TWI_ADDR_WRITE ( (MCP23018_TWI_ADDRESS<<1) | TW_WRITE )
  43. #define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
  44. #define I2C_TIMEOUT 10
  45. #define MCP_ROWS_START 8
  46. uint8_t mcp23018_init(void) {
  47. uint8_t ret;
  48. uint8_t data[3];
  49. // set pin direction
  50. // - unused : input : 1
  51. // - input : input : 1
  52. // - driving : output : 0
  53. data[0] = IODIRA;
  54. data[1] = 0b00000000; // IODIRA
  55. data[2] = (0b11111111); // IODIRB
  56. ret = i2c_transmit(TWI_ADDR_WRITE, (uint8_t *)data, 3, I2C_TIMEOUT);
  57. if (ret) goto out; // make sure we got an ACK
  58. // set pull-up
  59. // - unused : on : 1
  60. // - input : on : 1
  61. // - driving : off : 0
  62. data[0] = GPPUA;
  63. data[1] = 0b00000000; // IODIRA
  64. data[2] = (0b11111111); // IODIRB
  65. ret = i2c_transmit(TWI_ADDR_WRITE, (uint8_t *)data, 3, I2C_TIMEOUT);
  66. if (ret) goto out; // make sure we got an ACK
  67. // set logical value (doesn't matter on inputs)
  68. // - unused : hi-Z : 1
  69. // - input : hi-Z : 1
  70. // - driving : hi-Z : 1
  71. data[0] = OLATA;
  72. data[1] = 0b11111111; // IODIRA
  73. data[2] = (0b11111111); // IODIRB
  74. ret = i2c_transmit(TWI_ADDR_WRITE, (uint8_t *)data, 3, I2C_TIMEOUT);
  75. out:
  76. return ret;
  77. }
  78. #endif
  79. void matrix_init_custom(void) {
  80. // initialize matrix ports - cols, rows
  81. // PB0-PB7 : col0 .. col7
  82. // PA0-PA7 : row0 .. row7
  83. // PC7-PC2 : row8 .. row13
  84. // PD0 : NUM
  85. // PD1 : CAPS
  86. // PD2 : D+ / Clock
  87. // PD3 : D- / Data
  88. // PD4 : FULL LED
  89. // PD5 : 3.6V switch TR
  90. // PD6 : SCRL
  91. // PD7 : row14
  92. // signal direction : col -> row
  93. // pc(PORTROWS1)0, 1 : twi
  94. DDRCOLUMNS = 0xFF; // all outputs for cols
  95. PORTCOLUMNS = 0xFF; // high
  96. // all inputs for rows
  97. DDRROWS1 = 0x00;
  98. DDRROWS2 &= ~(0x111111<<2); //0x00;
  99. DDRD &= ~(1<<PIND7); // row 14
  100. // all rows pull-up.
  101. PORTROWS1 = 0xFF;
  102. PORTROWS2 |= (0b111111<<2); //0x11111100;
  103. PORTD |= (1<<PIND7);// row 14
  104. i2c_init();
  105. #if defined(RIGHT_HALF)
  106. // Initialize the chip on the other half
  107. mcp23018_init();
  108. #endif
  109. }
  110. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  111. bool matrix_has_changed = false;
  112. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  113. // Store last value of row prior to reading
  114. matrix_row_t last_row_value = current_matrix[row];
  115. matrix_row_t cols = 0;
  116. // Select the row to scan
  117. matrix_set_row_status(row);
  118. matrix_io_delay();
  119. //Set the local row
  120. #if defined(RIGHT_HALF)
  121. // Initialize to 0x7F in case I2C read fails,
  122. // as 0x75 would be no keys pressed
  123. uint8_t data = 0x7F;
  124. // Receive the columns from right half
  125. i2c_receive(TWI_ADDR_WRITE, &data, 1, I2C_TIMEOUT);
  126. #endif
  127. // cols |= ((~(PINA | 0x80)) & 0x7F);
  128. cols |= ((~(PINA)) & 0xFF);
  129. #if defined(RIGHT_HALF)
  130. cols |= (((~(data | 0x80)) & 0x7F) << MCP_ROWS_START);
  131. #endif
  132. current_matrix[row] = cols;
  133. matrix_has_changed |= (last_row_value != current_matrix[row]);
  134. }
  135. return matrix_has_changed;
  136. }
  137. void matrix_set_row_status(uint8_t row) {
  138. #if defined(RIGHT_HALF)
  139. uint8_t txdata[3];
  140. //Set the remote row on port A
  141. txdata[0] = (GPIOA);
  142. txdata[1] = ( 0xFF & ~(1<<row) );
  143. i2c_transmit(TWI_ADDR_WRITE, (uint8_t *)txdata, 2, I2C_TIMEOUT);
  144. #endif
  145. //Set the local row on port B
  146. DDRB = (1 << row);
  147. PORTB = ~(1 << row);
  148. }