logo

qmk_firmware

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

matrix.c (6040B)


  1. /*
  2. Copyright 2018 listofoptions <listofoptions@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 <stdint.h>
  15. #include <stdbool.h>
  16. #include <string.h>
  17. #if defined(__AVR__)
  18. #include <avr/io.h>
  19. #endif
  20. #include <util/delay.h>
  21. #include "wait.h"
  22. #include "print.h"
  23. #include "debug.h"
  24. #include "util.h"
  25. #include "matrix.h"
  26. #include "timer.h"
  27. #include <LUFA/Drivers/Peripheral/SPI.h>
  28. #ifndef DEBOUNCE
  29. # define DEBOUNCE 5
  30. #endif
  31. #if ( DEBOUNCE > 0 )
  32. static uint16_t debouncing_time ;
  33. static bool debouncing = false ;
  34. #endif
  35. static uint8_t matrix [MATRIX_ROWS] = {0};
  36. #if ( DEBOUNCE > 0 )
  37. static uint8_t matrix_debounce_old [MATRIX_ROWS] = {0};
  38. static uint8_t matrix_debounce_new [MATRIX_ROWS] = {0};
  39. #endif
  40. __attribute__ ((weak))
  41. void matrix_init_kb(void) {
  42. matrix_init_user();
  43. }
  44. __attribute__ ((weak))
  45. void matrix_scan_kb(void) {
  46. matrix_scan_user();
  47. }
  48. __attribute__ ((weak))
  49. void matrix_init_user(void) {
  50. }
  51. __attribute__ ((weak))
  52. void matrix_scan_user(void) {
  53. }
  54. // the keyboard's internal wiring is such that the inputs to the logic are
  55. // a clock signal, and a reset line.
  56. // the output is a single output pin. im bitbanging here, but the SPI controller
  57. // would work normally
  58. //
  59. // the device functions, by using the clock signal to count 128 bits, the lower
  60. // 3 bits of this 7 bit counter are tied to a 1-of-8 multiplexer, this forms
  61. // the columns.
  62. // the upper 4 bits form the rows, and are decoded using bcd to decimal
  63. // decoders, so that 14 out of 16 of the outputs are wired to the rows of the
  64. // matrix. each switch has a diode, such that the row signal feeds into the
  65. // switch, and then into the diode, then into one of the columns into the
  66. // matrix. the reset pin can be used to reset the entire counter.
  67. #define HP_46010A_RESET_PIN B0
  68. #define HP_46010A_SCLK_PIN B1
  69. #define HP_46010A_SDATA_PIN B3
  70. #define HP_46010A_LED_PIN D6
  71. inline
  72. static
  73. void SCLK_increment(void) {
  74. gpio_write_pin_low(HP_46010A_SCLK_PIN);
  75. _delay_us( 4 ) ; // make sure the line is stable
  76. gpio_write_pin_high(HP_46010A_SCLK_PIN);
  77. _delay_us( 4 ) ;
  78. return ;
  79. }
  80. inline
  81. static
  82. void Matrix_Reset(void) {
  83. gpio_write_pin_high(HP_46010A_RESET_PIN);
  84. _delay_us( 4 ) ; // make sure the line is stable
  85. gpio_write_pin_low(HP_46010A_RESET_PIN);
  86. return ;
  87. }
  88. inline
  89. static
  90. uint8_t Matrix_ReceiveByte (void) {
  91. uint8_t received = 0 ;
  92. uint8_t temp = 0 ;
  93. for ( uint8_t bit = 0; bit < MATRIX_COLS; ++bit ) {
  94. // toggle the clock
  95. SCLK_increment();
  96. temp = gpio_read_pin(HP_46010A_SDATA_PIN) << 4 ;
  97. received |= temp >> bit ;
  98. }
  99. return received ;
  100. }
  101. inline
  102. static
  103. void Matrix_ThrowByte(void) {
  104. // we use MATRIX_COLS - 1 here because that would put us at 7 clocks
  105. for ( uint8_t bit = 0; bit < MATRIX_COLS - 1; ++bit ) {
  106. // toggle the clock
  107. SCLK_increment();
  108. }
  109. return ;
  110. }
  111. void matrix_init (void) {
  112. // debug_matrix = 1;
  113. // PB0 (SS) and PB1 (SCLK) set to outputs
  114. gpio_set_pin_output(HP_46010A_RESET_PIN);
  115. gpio_set_pin_output(HP_46010A_SCLK_PIN);
  116. // PB2, is unused, and PB3 is our serial input
  117. gpio_set_pin_input(HP_46010A_SDATA_PIN);
  118. // SS is reset for this board, and is active High
  119. // SCLK is the serial clock and is active High
  120. gpio_write_pin_low(HP_46010A_RESET_PIN);
  121. gpio_write_pin_high(HP_46010A_SCLK_PIN);
  122. // led pin
  123. gpio_set_pin_output(HP_46010A_LED_PIN);
  124. gpio_write_pin_low(HP_46010A_LED_PIN);
  125. matrix_init_kb();
  126. //toggle reset, to put the keyboard logic into a known state
  127. Matrix_Reset() ;
  128. }
  129. uint8_t matrix_scan(void) {
  130. // the first byte of the keyboard's output data can be ignored
  131. Matrix_ThrowByte();
  132. #if ( DEBOUNCE > 0 )
  133. for ( uint8_t row = 0 ; row < MATRIX_ROWS ; ++row ) {
  134. //transfer old debouncing values
  135. matrix_debounce_old[row] = matrix_debounce_new[row] ;
  136. // read new key-states in
  137. matrix_debounce_new[row] = Matrix_ReceiveByte() ;
  138. if ( matrix_debounce_new[row] != matrix_debounce_old[row] ) {
  139. debouncing = true ;
  140. debouncing_time = timer_read() ;
  141. }
  142. }
  143. #else
  144. // without debouncing we simply just read in the raw matrix
  145. for ( uint8_t row = 0 ; row < MATRIX_ROWS ; ++row ) {
  146. matrix[row] = Matrix_ReceiveByte ;
  147. }
  148. #endif
  149. #if ( DEBOUNCE > 0 )
  150. if ( debouncing && ( timer_elapsed( debouncing_time ) > DEBOUNCE ) ) {
  151. for ( uint8_t row = 0 ; row < MATRIX_ROWS ; ++row ) {
  152. matrix[row] = matrix_debounce_new[row] ;
  153. }
  154. debouncing = false ;
  155. }
  156. #endif
  157. Matrix_Reset() ;
  158. matrix_scan_kb() ;
  159. return 1;
  160. }
  161. inline
  162. uint8_t matrix_get_row( uint8_t row ) {
  163. return matrix[row];
  164. }
  165. void matrix_print(void)
  166. {
  167. print("\nr/c 01234567\n");
  168. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  169. print_hex8(row); print(": ");
  170. print_bin_reverse8(matrix_get_row(row));
  171. print("\n");
  172. }
  173. }
  174. inline
  175. uint8_t matrix_rows(void) {
  176. return MATRIX_ROWS;
  177. }
  178. inline
  179. uint8_t matrix_cols(void) {
  180. return MATRIX_COLS;
  181. }
  182. // as an aside, I used the M0110 converter:
  183. // tmk_core/common/keyboard.c, quantum/matrix.c, and the project layout of the planck
  184. // the online ducmentation starting from :
  185. // https://docs.qmk.fm/#/config_options
  186. // https://docs.qmk.fm/#/understanding_qmk
  187. // and probably a few i forgot....