logo

qmk_firmware

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

ec_switch_matrix.c (4092B)


  1. /* Copyright 2020 sekigon-gonnoc
  2. *
  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. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "ec_switch_matrix.h"
  17. #include <avr/interrupt.h>
  18. #include "analog.h"
  19. #include "print.h"
  20. // pin connections
  21. const uint8_t row_pins[] = MATRIX_ROW_PINS;
  22. const uint8_t col_channels[] = MATRIX_COL_CHANNELS;
  23. const uint8_t mux_sel_pins[] = MUX_SEL_PINS;
  24. _Static_assert(sizeof(mux_sel_pins) == 3, "invalid MUX_SEL_PINS");
  25. static ecsm_config_t config;
  26. static uint16_t ecsm_sw_value[MATRIX_ROWS][MATRIX_COLS];
  27. static inline void discharge_capacitor(void) { gpio_set_pin_output(DISCHARGE_PIN); }
  28. static inline void charge_capacitor(uint8_t row) {
  29. gpio_set_pin_input(DISCHARGE_PIN);
  30. gpio_write_pin_high(row_pins[row]);
  31. }
  32. static inline void clear_all_row_pins(void) {
  33. for (int row = 0; row < sizeof(row_pins); row++) {
  34. gpio_write_pin_low(row_pins[row]);
  35. }
  36. }
  37. static inline void init_mux_sel(void) {
  38. for (int idx = 0; idx < sizeof(mux_sel_pins); idx++) {
  39. gpio_set_pin_output(mux_sel_pins[idx]);
  40. }
  41. }
  42. static inline void select_mux(uint8_t col) {
  43. uint8_t ch = col_channels[col];
  44. gpio_write_pin(mux_sel_pins[0], ch & 1);
  45. gpio_write_pin(mux_sel_pins[1], ch & 2);
  46. gpio_write_pin(mux_sel_pins[2], ch & 4);
  47. }
  48. static inline void init_row(void) {
  49. for (int idx = 0; idx < sizeof(row_pins); idx++) {
  50. gpio_set_pin_output(row_pins[idx]);
  51. gpio_write_pin_low(row_pins[idx]);
  52. }
  53. }
  54. // Initialize pins
  55. int ecsm_init(ecsm_config_t const* const ecsm_config) {
  56. // save config
  57. config = *ecsm_config;
  58. // initialize discharge pin as discharge mode
  59. gpio_write_pin_low(DISCHARGE_PIN);
  60. gpio_set_pin_output(DISCHARGE_PIN);
  61. // set analog reference
  62. analogReference(ADC_REF_POWER);
  63. // initialize drive lines
  64. init_row();
  65. // initialize multiplexer select pin
  66. init_mux_sel();
  67. // set discharge pin to charge mode
  68. gpio_set_pin_input(DISCHARGE_PIN);
  69. return 0;
  70. }
  71. // Read key value of key (row, col)
  72. uint16_t ecsm_readkey_raw(uint8_t row, uint8_t col) {
  73. uint16_t sw_value = 0;
  74. discharge_capacitor();
  75. select_mux(col);
  76. clear_all_row_pins();
  77. cli();
  78. charge_capacitor(row);
  79. sw_value = analogReadPin(ANALOG_PORT);
  80. sei();
  81. return sw_value;
  82. }
  83. // Update press/release state of key at (row, col)
  84. bool ecsm_update_key(matrix_row_t* current_row, uint8_t col, uint16_t sw_value) {
  85. bool current_state = (*current_row >> col) & 1;
  86. // press to release
  87. if (current_state && sw_value < config.low_threshold) {
  88. *current_row &= ~(1 << col);
  89. return true;
  90. }
  91. // release to press
  92. if ((!current_state) && sw_value > config.high_threshold) {
  93. *current_row |= (1 << col);
  94. return true;
  95. }
  96. return false;
  97. }
  98. // Scan key values and update matrix state
  99. bool ecsm_matrix_scan(matrix_row_t current_matrix[]) {
  100. bool updated = false;
  101. for (int col = 0; col < sizeof(col_channels); col++) {
  102. for (int row = 0; row < sizeof(row_pins); row++) {
  103. ecsm_sw_value[row][col] = ecsm_readkey_raw(row, col);
  104. updated |= ecsm_update_key(&current_matrix[row], col, ecsm_sw_value[row][col]);
  105. }
  106. }
  107. return updated;
  108. }
  109. // Print key values
  110. void ecsm_print_matrix(void) {
  111. for (int row = 0; row < sizeof(row_pins); row++) {
  112. for (int col = 0; col < sizeof(col_channels); col++) {
  113. xprintf("%4d", ecsm_sw_value[row][col]);
  114. }
  115. xprintf("\n");
  116. }
  117. }