You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.8 KiB

  1. /* Copyright 2023 ebastler and elpekenin
  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 "matrix.h"
  17. #include "pca9555.h"
  18. #include "timer.h"
  19. // PCA9555 i2c address, 0x20: A0 = 0, A1 = 0, A2 = 0
  20. #define IC1 0x20
  21. // Define how long to wait to reach the IO expander after connection loss again
  22. // Since this board is modular, it should not spam unnecessary i2c requests if used without a module
  23. #define RETRY_TIMESPAN 2000
  24. typedef enum {
  25. PLUGGED,
  26. DOUBTFUL,
  27. UNPLUGGED
  28. } expander_status_t;
  29. void pca9555_setup(void) {
  30. // Initialize the expander, no need to set ports to inputs as that is the default behavior
  31. pca9555_init(IC1);
  32. }
  33. void matrix_init_custom(void) {
  34. // Encoder pushbutton on the MCU is connected to PD2
  35. setPinInputHigh(D2);
  36. pca9555_setup();
  37. }
  38. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  39. static expander_status_t status = DOUBTFUL;
  40. static uint32_t retry_timer = 0;
  41. // initialize one byte filled with 1
  42. uint8_t pin_states = 0xFF;
  43. if (status != UNPLUGGED || timer_elapsed32(retry_timer) > RETRY_TIMESPAN) {
  44. // If the chip was unplugged before, it needs to be re-initialized
  45. if(status==UNPLUGGED) {
  46. pca9555_setup();
  47. }
  48. // Read the entire port into this byte, 1 = not pressed, 0 = pressed
  49. bool ret = pca9555_read_pins(IC1, PCA9555_PORT0, &pin_states);
  50. // Update state
  51. if (ret) {
  52. status = PLUGGED;
  53. } else {
  54. switch (status) {
  55. case PLUGGED:
  56. status = DOUBTFUL;
  57. break;
  58. case DOUBTFUL:
  59. status = UNPLUGGED;
  60. break;
  61. // If we've diagnosed as unplugged, update timer to not read I2C
  62. case UNPLUGGED:
  63. retry_timer = timer_read32();
  64. }
  65. }
  66. }
  67. // Shift pin states by 1 to make room for the switch connected to the MCU, then OR them together and invert (as QMK uses inverted logic compared to the electrical levels)
  68. matrix_row_t data = ~(pin_states << 1 | readPin(D2));
  69. bool changed = current_matrix[0] != data;
  70. current_matrix[0] = data;
  71. return changed;
  72. }