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.

RowBase.cpp 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "RowBase.h"
  2. /*
  3. scans the row and calls any newly pressed or released keys.
  4. */
  5. void RowBase::process(const bool activeHigh)
  6. {
  7. //these variables are all bitwise, one bit per key
  8. uint8_t rowState; //1 means pressed, 0 means released
  9. uint16_t rowEnd; //1 bit marks positioned after last key of row
  10. uint8_t debouncedChanged; //1 means debounced changed
  11. scan(activeHigh); //save column-port-pin values to portState
  12. rowState = getRowState(rowEnd, activeHigh);
  13. debouncedChanged = debounce(rowState);
  14. pressRelease(rowEnd, debouncedChanged);
  15. }
  16. void RowBase::wait()
  17. {
  18. delayMicroseconds(DELAY_MICROSECONDS); //delay between Row scans to debounce switches
  19. }
  20. /*
  21. Strobes the row and reads the columns.
  22. Strobe is on for shortest possible time to preserve IR LED on DodoHand's optic switch.
  23. */
  24. void RowBase::scan(const bool activeHigh)
  25. {
  26. //strobe row on
  27. if (activeHigh)
  28. {
  29. refRowPort.setActivePinHigh(rowPin);
  30. }
  31. else //activeLow
  32. {
  33. refRowPort.setActivePinLow(rowPin);
  34. }
  35. //read all the column ports
  36. for (uint8_t i=0; i < colPortCount; i++)
  37. {
  38. ptrsColPorts[i]->read();
  39. }
  40. //strobe row off
  41. if (activeHigh)
  42. {
  43. refRowPort.setActivePinLow(rowPin);
  44. }
  45. else //activeLow
  46. {
  47. refRowPort.setActivePinHigh(rowPin);
  48. }
  49. }
  50. /*
  51. Copies column pins to rowState. Unused column pins are not copied.
  52. Sets rowEnd and returns rowState.
  53. rowEnd is bitwise, where 1 bit corrsiponds to place immediatly after last key of row.
  54. rowEnd and rowMask are larger type than portMask so that they can not overflow.
  55. */
  56. uint8_t RowBase::getRowState(uint16_t& rowEnd, const bool activeHigh)
  57. {
  58. uint16_t rowMask = 1; //bitwise, one col per bit, active col bit is 1
  59. uint8_t rowState = 0; //bitwise, one key per bit, 1 means key is pressed
  60. for (uint8_t i=0; i < colPortCount; i++) //for each col port
  61. {
  62. //bitwise colPins, 1 means pin is connected to column
  63. uint8_t colPins = ptrsColPorts[i]->getColPins();
  64. //bitwise colPortState, pin values where set in ColPort::read(), get them now
  65. uint8_t colPortState = ptrsColPorts[i]->getPortState();
  66. if (activeHigh)
  67. {
  68. colPortState = ~colPortState;
  69. }
  70. for ( uint8_t portMask = 1; portMask > 0; portMask <<= 1 ) //shift portMask until overflow
  71. { //for each pin of col port
  72. if (portMask & colPins) //if pin is connected to column
  73. {
  74. if (portMask & ~colPortState) //if pin detected a key press
  75. {
  76. rowState |= rowMask; //set rowState bit for that key
  77. }
  78. rowMask <<= 1; //shift rowMask to next key
  79. }
  80. }
  81. }
  82. rowEnd = rowMask;
  83. return rowState;
  84. }
  85. /*
  86. pressRelease() calls key's press() or release() function if it was pressed or released.
  87. Both parameters are bitwise.
  88. */
  89. void RowBase::pressRelease(const uint16_t rowEnd, const uint8_t debouncedChanged)
  90. {
  91. uint8_t isFallingEdge; //1 means falling edge
  92. uint8_t isRisingEdge; //1 means rising edge
  93. uint8_t rowMask; //bitwise, active col bit is 1
  94. uint8_t col; //index for ptrsKeys[col] array
  95. //bit=1 if last debounced changed from 1 to 0, else bit=0
  96. isFallingEdge = debouncedChanged & ~previousDebounced;
  97. //bit=1 if last debounced changed from 0 to 1, else bit=0
  98. isRisingEdge = debouncedChanged & previousDebounced;
  99. for (rowMask=1, col=0; rowMask<rowEnd; rowMask<<=1, col++) //for each key in row
  100. {
  101. //release before press avoids impossible key sequence
  102. if (rowMask & isFallingEdge) //if key was released
  103. {
  104. ptrsKeys[col]->release();
  105. }
  106. if (rowMask & isRisingEdge) //if key was pressed
  107. {
  108. ptrsKeys[col]->press();
  109. keyWasPressed();
  110. }
  111. }
  112. }
  113. void RowBase::keyWasPressed()
  114. {
  115. //empty in RowBase class. To unstick sticky keys, override keyWasPressed() in derived class.
  116. }