KeyboardManager: a class to manage the polling of a switch-matrix keyboard
KeyboardManager.cpp@1:a74ffceb67e5, 2011-01-19 (annotated)
- Committer:
- osmeest
- Date:
- Wed Jan 19 23:05:30 2011 +0000
- Revision:
- 1:a74ffceb67e5
- Parent:
- 0:f813c207f78f
- Child:
- 2:eb4cc53ff33d
Remove debug messages from lib. Make polling frequency configurable.
Add parameter checking (constructor).
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
osmeest | 0:f813c207f78f | 1 | #include "KeyboardManager.h" |
osmeest | 1:a74ffceb67e5 | 2 | #include <algorithm> |
osmeest | 1:a74ffceb67e5 | 3 | #include <stdexcept> |
osmeest | 0:f813c207f78f | 4 | |
osmeest | 0:f813c207f78f | 5 | enum { |
osmeest | 0:f813c207f78f | 6 | InPortShift = 15, |
osmeest | 0:f813c207f78f | 7 | OutPortShift = 6 |
osmeest | 0:f813c207f78f | 8 | }; |
osmeest | 0:f813c207f78f | 9 | |
osmeest | 0:f813c207f78f | 10 | KeyboardManager::KeyboardManager( |
osmeest | 0:f813c207f78f | 11 | PortName inPort, int inLowestBit, PortName outPort, int outLowestBit, |
osmeest | 1:a74ffceb67e5 | 12 | KeyEventHandler handler, float pollingPeriod) : |
osmeest | 0:f813c207f78f | 13 | handler(handler), |
osmeest | 0:f813c207f78f | 14 | in(inPort, 0x0f << inLowestBit), inBitShift(inLowestBit), |
osmeest | 0:f813c207f78f | 15 | out(outPort, 0x0f << outLowestBit), outBitShift(outLowestBit), |
osmeest | 1:a74ffceb67e5 | 16 | ticker(), pollingPeriod(std::max<float>(pollingPeriod, 0.000020)), |
osmeest | 1:a74ffceb67e5 | 17 | scanRow(0), currentState(0), lastState(0), lastReportedState(0) |
osmeest | 0:f813c207f78f | 18 | { |
osmeest | 1:a74ffceb67e5 | 19 | if (inPort == outPort) { |
osmeest | 1:a74ffceb67e5 | 20 | int inMask = 0x0f << inLowestBit, |
osmeest | 1:a74ffceb67e5 | 21 | outMask = 0x0f << outLowestBit; |
osmeest | 1:a74ffceb67e5 | 22 | if (inMask & outMask) { |
osmeest | 1:a74ffceb67e5 | 23 | printf("KeyboardManager: ERROR: Input and output bits are overlapping."); |
osmeest | 1:a74ffceb67e5 | 24 | } |
osmeest | 1:a74ffceb67e5 | 25 | } |
osmeest | 0:f813c207f78f | 26 | } |
osmeest | 0:f813c207f78f | 27 | |
osmeest | 0:f813c207f78f | 28 | void KeyboardManager::start() |
osmeest | 0:f813c207f78f | 29 | { |
osmeest | 0:f813c207f78f | 30 | this->in.mode(PullDown); |
osmeest | 1:a74ffceb67e5 | 31 | this->ticker.attach(this, &KeyboardManager::timerHandler, this->pollingPeriod); |
osmeest | 0:f813c207f78f | 32 | } |
osmeest | 0:f813c207f78f | 33 | |
osmeest | 0:f813c207f78f | 34 | void KeyboardManager::stop() |
osmeest | 0:f813c207f78f | 35 | { |
osmeest | 0:f813c207f78f | 36 | this->ticker.detach(); |
osmeest | 0:f813c207f78f | 37 | this->in.mode(OpenDrain); |
osmeest | 0:f813c207f78f | 38 | } |
osmeest | 0:f813c207f78f | 39 | |
osmeest | 0:f813c207f78f | 40 | namespace { |
osmeest | 0:f813c207f78f | 41 | bool isSingleKey(int state) { |
osmeest | 0:f813c207f78f | 42 | if (state == 0) { |
osmeest | 0:f813c207f78f | 43 | return false; |
osmeest | 0:f813c207f78f | 44 | } |
osmeest | 0:f813c207f78f | 45 | |
osmeest | 0:f813c207f78f | 46 | return (state == (state & (-state))); |
osmeest | 0:f813c207f78f | 47 | } |
osmeest | 0:f813c207f78f | 48 | |
osmeest | 0:f813c207f78f | 49 | int getKeyId(int state) { |
osmeest | 0:f813c207f78f | 50 | if (state == 0) { |
osmeest | 0:f813c207f78f | 51 | return 0; |
osmeest | 0:f813c207f78f | 52 | } |
osmeest | 0:f813c207f78f | 53 | |
osmeest | 0:f813c207f78f | 54 | int key = 1; |
osmeest | 0:f813c207f78f | 55 | while ((state & 1) == 0) { |
osmeest | 0:f813c207f78f | 56 | key++; |
osmeest | 0:f813c207f78f | 57 | state >>= 1; |
osmeest | 0:f813c207f78f | 58 | } |
osmeest | 0:f813c207f78f | 59 | return key; |
osmeest | 0:f813c207f78f | 60 | } |
osmeest | 0:f813c207f78f | 61 | } |
osmeest | 0:f813c207f78f | 62 | |
osmeest | 0:f813c207f78f | 63 | void KeyboardManager::timerHandler() |
osmeest | 0:f813c207f78f | 64 | { |
osmeest | 0:f813c207f78f | 65 | unsigned r = 1 << (this->scanRow + this->outBitShift); |
osmeest | 0:f813c207f78f | 66 | out.write(r); |
osmeest | 0:f813c207f78f | 67 | wait_us(10); |
osmeest | 0:f813c207f78f | 68 | unsigned v = in.read() >> this->inBitShift; |
osmeest | 1:a74ffceb67e5 | 69 | this->currentState |= v << (4 * this->scanRow); |
osmeest | 0:f813c207f78f | 70 | this->scanRow = (this->scanRow + 1) & 3; |
osmeest | 0:f813c207f78f | 71 | |
osmeest | 0:f813c207f78f | 72 | if (this->scanRow == 0) { |
osmeest | 0:f813c207f78f | 73 | if (this->currentState != this->lastState) { |
osmeest | 0:f813c207f78f | 74 | if (isSingleKey(this->currentState) && this->lastReportedState == 0) |
osmeest | 0:f813c207f78f | 75 | { |
osmeest | 0:f813c207f78f | 76 | int key = getKeyId(this->currentState); |
osmeest | 0:f813c207f78f | 77 | |
osmeest | 0:f813c207f78f | 78 | if (this->handler) { |
osmeest | 0:f813c207f78f | 79 | this->handler(key, true); |
osmeest | 0:f813c207f78f | 80 | } |
osmeest | 1:a74ffceb67e5 | 81 | |
osmeest | 0:f813c207f78f | 82 | this->lastReportedState = this->currentState; |
osmeest | 0:f813c207f78f | 83 | } |
osmeest | 0:f813c207f78f | 84 | else if (this->lastReportedState != 0 && |
osmeest | 0:f813c207f78f | 85 | (this->currentState & this->lastReportedState) == 0) |
osmeest | 0:f813c207f78f | 86 | { |
osmeest | 0:f813c207f78f | 87 | int key = getKeyId(this->lastReportedState); |
osmeest | 0:f813c207f78f | 88 | |
osmeest | 0:f813c207f78f | 89 | if (this->handler) { |
osmeest | 0:f813c207f78f | 90 | this->handler(key, false); |
osmeest | 0:f813c207f78f | 91 | } |
osmeest | 1:a74ffceb67e5 | 92 | |
osmeest | 0:f813c207f78f | 93 | this->lastReportedState = 0; |
osmeest | 0:f813c207f78f | 94 | } |
osmeest | 0:f813c207f78f | 95 | |
osmeest | 0:f813c207f78f | 96 | this->lastState = this->currentState; |
osmeest | 0:f813c207f78f | 97 | } |
osmeest | 0:f813c207f78f | 98 | |
osmeest | 0:f813c207f78f | 99 | this->currentState = 0; |
osmeest | 0:f813c207f78f | 100 | } |
osmeest | 0:f813c207f78f | 101 | } |