keyboard.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* Copyright 2023 Manuel Jinger
  2. * Copyright 2023 Dual Tachyon
  3. * https://github.com/DualTachyon
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include "bsp/dp32g030/gpio.h"
  18. #include "driver/gpio.h"
  19. #include "driver/keyboard.h"
  20. #include "driver/systick.h"
  21. #include "driver/i2c.h"
  22. #include "misc.h"
  23. #ifdef ENABLE_SCREEN_DUMP
  24. KEY_Code_t gSimulateKey = KEY_INVALID;
  25. KEY_Code_t gSimulateHold = KEY_INVALID;
  26. uint8_t gDebounceDefeat = 0;
  27. uint8_t gPttCounter = 0;
  28. #endif
  29. KEY_Code_t gKeyReading0 = KEY_INVALID;
  30. KEY_Code_t gKeyReading1 = KEY_INVALID;
  31. uint16_t gDebounceCounter = 0;
  32. bool gWasFKeyPressed = false;
  33. static const struct {
  34. // Using a 16 bit pre-calculated shift and invert is cheaper
  35. // than using 8 bit and doing shift and invert in code.
  36. uint16_t set_to_zero_mask;
  37. // We are very fortunate.
  38. // The key and pin defines fit together in a single u8, making this very efficient
  39. struct {
  40. KEY_Code_t key : 5;
  41. uint8_t pin : 3; // Pin 6 is highest
  42. } pins[4];
  43. } keyboard[] = {
  44. { // Zero row
  45. // Set to zero to handle special case of nothing pulled down
  46. .set_to_zero_mask = 0xffff,
  47. .pins = {
  48. { .key = KEY_SIDE1, .pin = GPIOA_PIN_KEYBOARD_0},
  49. { .key = KEY_SIDE2, .pin = GPIOA_PIN_KEYBOARD_1},
  50. // Duplicate to fill the array with valid values
  51. { .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1},
  52. { .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1}
  53. }
  54. },
  55. { // First row
  56. .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_4) & 0xffff,
  57. .pins = {
  58. { .key = KEY_MENU, .pin = GPIOA_PIN_KEYBOARD_0},
  59. { .key = KEY_1, .pin = GPIOA_PIN_KEYBOARD_1},
  60. { .key = KEY_4, .pin = GPIOA_PIN_KEYBOARD_2},
  61. { .key = KEY_7, .pin = GPIOA_PIN_KEYBOARD_3}
  62. }
  63. },
  64. { // Second row
  65. .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_5) & 0xffff,
  66. .pins = {
  67. { .key = KEY_UP, .pin = GPIOA_PIN_KEYBOARD_0},
  68. { .key = KEY_2 , .pin = GPIOA_PIN_KEYBOARD_1},
  69. { .key = KEY_5 , .pin = GPIOA_PIN_KEYBOARD_2},
  70. { .key = KEY_8 , .pin = GPIOA_PIN_KEYBOARD_3}
  71. }
  72. },
  73. { // Third row
  74. .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_6) & 0xffff,
  75. .pins = {
  76. { .key = KEY_DOWN, .pin = GPIOA_PIN_KEYBOARD_0},
  77. { .key = KEY_3 , .pin = GPIOA_PIN_KEYBOARD_1},
  78. { .key = KEY_6 , .pin = GPIOA_PIN_KEYBOARD_2},
  79. { .key = KEY_9 , .pin = GPIOA_PIN_KEYBOARD_3}
  80. }
  81. },
  82. { // Fourth row
  83. .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_7) & 0xffff,
  84. .pins = {
  85. { .key = KEY_EXIT, .pin = GPIOA_PIN_KEYBOARD_0},
  86. { .key = KEY_STAR, .pin = GPIOA_PIN_KEYBOARD_1},
  87. { .key = KEY_0 , .pin = GPIOA_PIN_KEYBOARD_2},
  88. { .key = KEY_F , .pin = GPIOA_PIN_KEYBOARD_3}
  89. }
  90. }
  91. };
  92. KEY_Code_t KEYBOARD_Poll(void)
  93. {
  94. #ifdef ENABLE_SCREEN_DUMP
  95. if(gSimulateKey != KEY_INVALID)
  96. {
  97. const KEY_Code_t temp = gSimulateKey;
  98. if(gDebounceDefeat++ >= 5)
  99. gSimulateKey = KEY_INVALID;
  100. return temp;
  101. }
  102. if(gSimulateHold != KEY_INVALID)
  103. {
  104. if(gSimulateHold == KEY_PTT)
  105. {
  106. if(gPttCounter == 0)
  107. gSimulateHold = KEY_INVALID;
  108. else
  109. gPttCounter--;
  110. }
  111. return gSimulateHold;
  112. }
  113. #endif
  114. KEY_Code_t Key = KEY_INVALID;
  115. // if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT))
  116. // return KEY_PTT;
  117. // *****************
  118. for (unsigned int j = 0; j < ARRAY_SIZE(keyboard); j++)
  119. {
  120. uint16_t reg;
  121. unsigned int i;
  122. unsigned int k;
  123. // Set all high
  124. GPIOA->DATA |= 1u << GPIOA_PIN_KEYBOARD_4 |
  125. 1u << GPIOA_PIN_KEYBOARD_5 |
  126. 1u << GPIOA_PIN_KEYBOARD_6 |
  127. 1u << GPIOA_PIN_KEYBOARD_7;
  128. // Clear the pin we are selecting
  129. GPIOA->DATA &= keyboard[j].set_to_zero_mask;
  130. // Read all 4 GPIO pins at once .. with de-noise, max of 8 sample loops
  131. for (i = 0, k = 0, reg = 0; i < 3 && k < 8; i++, k++) {
  132. SYSTICK_DelayUs(1);
  133. uint16_t reg2 = GPIOA->DATA;
  134. i *= reg == reg2;
  135. reg = reg2;
  136. }
  137. if (i < 3)
  138. break; // noise is too bad
  139. for (unsigned int i = 0; i < ARRAY_SIZE(keyboard[j].pins); i++)
  140. {
  141. const uint16_t mask = 1u << keyboard[j].pins[i].pin;
  142. if (!(reg & mask))
  143. {
  144. Key = keyboard[j].pins[i].key;
  145. break;
  146. }
  147. }
  148. if (Key != KEY_INVALID)
  149. break;
  150. }
  151. // Create I2C stop condition since we might have toggled I2C pins
  152. // This leaves GPIOA_PIN_KEYBOARD_4 and GPIOA_PIN_KEYBOARD_5 high
  153. I2C_Stop();
  154. // Reset VOICE pins
  155. GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
  156. GPIO_SetBit( &GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);
  157. return Key;
  158. }