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

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