keybrd library is an open source library for creating custom-keyboard firmware.
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

Row.cpp 4.4KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* debounce() function
  2. Debounce uses multiple samples to debounces switch states,
  3. where each sample contains the switch states for a row of switches, one bit per switch.
  4. Debounce uses Dr. Marty's debounce algorithm from
  5. http://drmarty.blogspot.com.br/2009/05/best-switch-debounce-routine-ever.html
  6. I2C and TWI protocols do not include any Packet Error Checking (PEC).
  7. The goal of Marty's debounce routine is to reject spurious signals,
  8. which is useful when connecting split keyboards with a cable using I2C or TWI.
  9. Was tested on split keyboard with 3-meter long telephone wire to I/O expander
  10. Dr. Marty's debounce algorithm:
  11. Periodically read samples and update the state when a number consecutive sample bits are equal.
  12. Output from keybrd/examples/debounce_unit_test.cpp with SAMPLE_COUNT 4:
  13. button pressed: 100000001111111110000
  14. bouncy signal: 100001001111011110000
  15. debounced signal: 000000000001111111110
  16. isFallingEdge: 000000000000000000001
  17. isRisingEdge: 000000000001000000000
  18. There is a latency equal to SAMPLE_COUNT, between button press and debounced signal.
  19. samples[SAMPLE_COUNT] is a ring buffer. samplesIndex is it's current write index.
  20. SAMPLE_COUNT is the number of consecutive equal samples needed to debounce.
  21. SAMPLE_COUNT is a macro because it defines samples[SAMPLE_COUNT] array size at compile time.
  22. SAMPLE_COUNT should be at lease 1.
  23. Keyboards with a long I2C wire or in environment with strong electromagnetic interference (EMI)
  24. need a larger SAMPLE_COUNT for reliability.
  25. Larger SAMPLE_COUNTs are more reliable but consume more memory, where
  26. SAMPLE_COUNT*ROW_COUNT = bytes of memory consumed by keyboard
  27. SAMPLE_COUNT = 4 is very reliable for a keyboard.
  28. Avoid sampling the switch input at a rate synchronous to events in the environment
  29. that might create periodic EMI. For instance, 50 and 60 Hz.
  30. A keyboard with a faster scan rate responds faster.
  31. Follow these step to tune DELAY_MICROSECONDS for maximum scan rate for a given SAMPLE_COUNT:
  32. Initialize DELAY_MICROSECONDS in your sketch:
  33. const unsigned int Row::DELAY_MICROSECONDS = 1000;
  34. Add this to the sketch's loop() function:
  35. debug.print_microseconds_per_scan();
  36. Compile and load the sketch into the microcontroller; microseconds_per_scan is printed every second.
  37. Adjust the value of DELAY_MICROSECONDS and repeat until:
  38. debug.print_microseconds_per_scan() <= DEBOUNCE_TIME / SAMPLE_COUNT
  39. DEBOUNCE_TIME can be obtained from the switch's datasheet. Some switch bounce times are:
  40. Cherry MX specifies 5msec bounce time http://www.cherrycorp.com/english/switches/key/mx.htm
  41. hasu measured Cherry MX bounce times .3ms to 1.4ms http://geekhack.org/index.php?topic=42385.0
  42. Tactile switch MJTP series bounce 10 ms http://www.apem.com/files/apem/brochures/MJTP_6MM.pdf
  43. Polling I2C may slow the scan rate enough so that no additional delay is needed:
  44. const unsigned int Row::DELAY_MICROSECONDS = 0;
  45. Slow-scan trick for debug messages that print too fast:
  46. change DELAY_MICROSECONDS to a large number like 10000
  47. That way debug messages are printed at a managable rate.
  48. */
  49. /* debounce() function
  50. Parameter rowState is bitwise, 1 means pressed, 0 means released.
  51. Returns bitwise debouncedChanged.
  52. */
  53. #include "Row.h"
  54. uint8_t Row::debounce(const uint8_t rowState)
  55. {
  56. uint8_t debounced; //bitwise, 1 means pressed, 0 means released
  57. uint8_t debouncedChanged; //bitwise, 1 means debounced changed
  58. uint8_t all_1 = ~0; //bitwise
  59. uint8_t all_0 = 0; //bitwise
  60. samples[samplesIndex] = rowState; //insert rowState into samples[] ring buffer
  61. if (++samplesIndex >= SAMPLE_COUNT) //if end of ring buffer
  62. {
  63. samplesIndex = 0; //wrap samplesIndex to beginning of ring buffer
  64. }
  65. for (uint8_t j = 0; j < SAMPLE_COUNT; j++) //traverse the sample[] ring buffer
  66. {
  67. all_1 &= samples[j]; //1 if all samples are 1
  68. all_0 |= samples[j]; //0 if all samples are 0
  69. }
  70. // update newDebounce if all the samples agree with one another
  71. // if all samples=1 then debounced=1
  72. // elseif all samples=0 then debounced=0
  73. // else debounced=previousDebounced i.e. no change
  74. debounced = all_1 | (all_0 & previousDebounced);
  75. debouncedChanged = debounced xor previousDebounced;
  76. previousDebounced = debounced;
  77. return debouncedChanged;
  78. }