Olivier Smeesters
/
DtmfKit
A DTMF sequence editor and player for HAM radio equipment command & control.
KeyboardManager/KeyboardState.cpp@0:1324e7d9d471, 2011-03-07 (annotated)
- Committer:
- osmeest
- Date:
- Mon Mar 07 22:51:19 2011 +0000
- Revision:
- 0:1324e7d9d471
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
osmeest | 0:1324e7d9d471 | 1 | #include "kbd_mgr/KeyboardState.h" |
osmeest | 0:1324e7d9d471 | 2 | |
osmeest | 0:1324e7d9d471 | 3 | #include <algorithm> |
osmeest | 0:1324e7d9d471 | 4 | #include <iomanip> |
osmeest | 0:1324e7d9d471 | 5 | |
osmeest | 0:1324e7d9d471 | 6 | namespace kbd_mgr { |
osmeest | 0:1324e7d9d471 | 7 | |
osmeest | 0:1324e7d9d471 | 8 | KeyboardState::KeyboardState() : |
osmeest | 0:1324e7d9d471 | 9 | numRows(0), numKeysPerRow(0), rowMask(0), numRowsPerWord(0), numKeysPerWord(0), numWords(0), data(0) |
osmeest | 0:1324e7d9d471 | 10 | { } |
osmeest | 0:1324e7d9d471 | 11 | |
osmeest | 0:1324e7d9d471 | 12 | KeyboardState::KeyboardState(std::size_t numRows, std::size_t numKeysPerRow) : |
osmeest | 0:1324e7d9d471 | 13 | numRows(numRows), numKeysPerRow(numKeysPerRow), rowMask((1 << numKeysPerRow) -1), |
osmeest | 0:1324e7d9d471 | 14 | numRowsPerWord((sizeof(int) * 8) / numKeysPerRow), numKeysPerWord(numRowsPerWord * numKeysPerRow), |
osmeest | 0:1324e7d9d471 | 15 | numWords((numRows + (numRowsPerWord-1)) / numRowsPerWord), |
osmeest | 0:1324e7d9d471 | 16 | data(numWords, 0) |
osmeest | 0:1324e7d9d471 | 17 | { } |
osmeest | 0:1324e7d9d471 | 18 | |
osmeest | 0:1324e7d9d471 | 19 | void KeyboardState::clear() { |
osmeest | 0:1324e7d9d471 | 20 | std::fill(this->data.begin(), this->data.end(), 0); |
osmeest | 0:1324e7d9d471 | 21 | } |
osmeest | 0:1324e7d9d471 | 22 | |
osmeest | 0:1324e7d9d471 | 23 | int KeyboardState::getRowInfo(std::size_t row, std::size_t &wordIndex, std::size_t &rowShift, int &rowMask) const |
osmeest | 0:1324e7d9d471 | 24 | { |
osmeest | 0:1324e7d9d471 | 25 | std::size_t rowInWord = row % numRowsPerWord; |
osmeest | 0:1324e7d9d471 | 26 | wordIndex = row / numRowsPerWord; |
osmeest | 0:1324e7d9d471 | 27 | rowShift = numKeysPerRow * rowInWord; |
osmeest | 0:1324e7d9d471 | 28 | rowMask = this->rowMask << rowShift; |
osmeest | 0:1324e7d9d471 | 29 | |
osmeest | 0:1324e7d9d471 | 30 | return this->data[wordIndex]; |
osmeest | 0:1324e7d9d471 | 31 | } |
osmeest | 0:1324e7d9d471 | 32 | |
osmeest | 0:1324e7d9d471 | 33 | void KeyboardState::setRowState(std::size_t row, int rowState) { |
osmeest | 0:1324e7d9d471 | 34 | std::size_t wordIndex; |
osmeest | 0:1324e7d9d471 | 35 | std::size_t rowShift; |
osmeest | 0:1324e7d9d471 | 36 | int rowMask; |
osmeest | 0:1324e7d9d471 | 37 | int v = getRowInfo(row, wordIndex, rowShift, rowMask); |
osmeest | 0:1324e7d9d471 | 38 | v = (v & ~rowMask) | ((rowState & this->rowMask) << rowShift); |
osmeest | 0:1324e7d9d471 | 39 | this->data[wordIndex] = v; |
osmeest | 0:1324e7d9d471 | 40 | } |
osmeest | 0:1324e7d9d471 | 41 | |
osmeest | 0:1324e7d9d471 | 42 | int KeyboardState::getRowState(std::size_t row) const { |
osmeest | 0:1324e7d9d471 | 43 | std::size_t wordIndex; |
osmeest | 0:1324e7d9d471 | 44 | std::size_t rowShift; |
osmeest | 0:1324e7d9d471 | 45 | int rowMask; |
osmeest | 0:1324e7d9d471 | 46 | int v = getRowInfo(row, wordIndex, rowShift, rowMask); |
osmeest | 0:1324e7d9d471 | 47 | return (v & rowMask) >> rowShift; |
osmeest | 0:1324e7d9d471 | 48 | } |
osmeest | 0:1324e7d9d471 | 49 | |
osmeest | 0:1324e7d9d471 | 50 | bool KeyboardState::getKeyState(std::size_t key) const { |
osmeest | 0:1324e7d9d471 | 51 | std::size_t row = key / this->numKeysPerRow; |
osmeest | 0:1324e7d9d471 | 52 | std::size_t keyInRow = key % this->numKeysPerRow; |
osmeest | 0:1324e7d9d471 | 53 | int keyMask = 1 << keyInRow; |
osmeest | 0:1324e7d9d471 | 54 | |
osmeest | 0:1324e7d9d471 | 55 | return (getRowState(row) & keyMask) != 0; |
osmeest | 0:1324e7d9d471 | 56 | } |
osmeest | 0:1324e7d9d471 | 57 | |
osmeest | 0:1324e7d9d471 | 58 | KeyboardState KeyboardState::operator&(const KeyboardState &other) const { |
osmeest | 0:1324e7d9d471 | 59 | KeyboardState result(this->numRows, this->numKeysPerRow); |
osmeest | 0:1324e7d9d471 | 60 | |
osmeest | 0:1324e7d9d471 | 61 | typedef Data::const_iterator SourceIterator; |
osmeest | 0:1324e7d9d471 | 62 | typedef Data::iterator TargetIterator; |
osmeest | 0:1324e7d9d471 | 63 | |
osmeest | 0:1324e7d9d471 | 64 | SourceIterator a = this->data.begin(); |
osmeest | 0:1324e7d9d471 | 65 | SourceIterator b = other.data.begin(); |
osmeest | 0:1324e7d9d471 | 66 | TargetIterator t = result.data.begin(); |
osmeest | 0:1324e7d9d471 | 67 | while (a != this->data.end() && b != other.data.end() && t != result.data.end()) |
osmeest | 0:1324e7d9d471 | 68 | { |
osmeest | 0:1324e7d9d471 | 69 | *t = *a & *b; |
osmeest | 0:1324e7d9d471 | 70 | ++a; ++b; ++t; |
osmeest | 0:1324e7d9d471 | 71 | } |
osmeest | 0:1324e7d9d471 | 72 | |
osmeest | 0:1324e7d9d471 | 73 | return result; |
osmeest | 0:1324e7d9d471 | 74 | } |
osmeest | 0:1324e7d9d471 | 75 | |
osmeest | 0:1324e7d9d471 | 76 | bool KeyboardState::operator==(const KeyboardState &other) const { |
osmeest | 0:1324e7d9d471 | 77 | if (this == &other) { |
osmeest | 0:1324e7d9d471 | 78 | return true; |
osmeest | 0:1324e7d9d471 | 79 | } |
osmeest | 0:1324e7d9d471 | 80 | |
osmeest | 0:1324e7d9d471 | 81 | if (this->numRows != other.numRows || this->numKeysPerRow != other.numKeysPerRow) |
osmeest | 0:1324e7d9d471 | 82 | return false; |
osmeest | 0:1324e7d9d471 | 83 | |
osmeest | 0:1324e7d9d471 | 84 | Data::const_iterator p = this->data.begin(); |
osmeest | 0:1324e7d9d471 | 85 | Data::const_iterator q = other.data.begin(); |
osmeest | 0:1324e7d9d471 | 86 | while (p != this->data.end() && q != other.data.end()) { |
osmeest | 0:1324e7d9d471 | 87 | if (*p != *q) { |
osmeest | 0:1324e7d9d471 | 88 | return false; |
osmeest | 0:1324e7d9d471 | 89 | } |
osmeest | 0:1324e7d9d471 | 90 | ++p; ++q; |
osmeest | 0:1324e7d9d471 | 91 | } |
osmeest | 0:1324e7d9d471 | 92 | |
osmeest | 0:1324e7d9d471 | 93 | return true; |
osmeest | 0:1324e7d9d471 | 94 | } |
osmeest | 0:1324e7d9d471 | 95 | |
osmeest | 0:1324e7d9d471 | 96 | bool KeyboardState::empty() const { |
osmeest | 0:1324e7d9d471 | 97 | for(Data::const_iterator p = this->data.begin(); p != this->data.end(); ++p) { |
osmeest | 0:1324e7d9d471 | 98 | if (*p != 0) { |
osmeest | 0:1324e7d9d471 | 99 | return false; |
osmeest | 0:1324e7d9d471 | 100 | } |
osmeest | 0:1324e7d9d471 | 101 | } |
osmeest | 0:1324e7d9d471 | 102 | |
osmeest | 0:1324e7d9d471 | 103 | return true; |
osmeest | 0:1324e7d9d471 | 104 | } |
osmeest | 0:1324e7d9d471 | 105 | |
osmeest | 0:1324e7d9d471 | 106 | namespace { |
osmeest | 0:1324e7d9d471 | 107 | int getBitNumber(int v) |
osmeest | 0:1324e7d9d471 | 108 | { |
osmeest | 0:1324e7d9d471 | 109 | if (v == 0) { |
osmeest | 0:1324e7d9d471 | 110 | return -1; |
osmeest | 0:1324e7d9d471 | 111 | } |
osmeest | 0:1324e7d9d471 | 112 | |
osmeest | 0:1324e7d9d471 | 113 | int key = 0; |
osmeest | 0:1324e7d9d471 | 114 | while (v != 1) { |
osmeest | 0:1324e7d9d471 | 115 | key++; |
osmeest | 0:1324e7d9d471 | 116 | v >>= 1; |
osmeest | 0:1324e7d9d471 | 117 | } |
osmeest | 0:1324e7d9d471 | 118 | |
osmeest | 0:1324e7d9d471 | 119 | return key; |
osmeest | 0:1324e7d9d471 | 120 | } |
osmeest | 0:1324e7d9d471 | 121 | } |
osmeest | 0:1324e7d9d471 | 122 | |
osmeest | 0:1324e7d9d471 | 123 | KeyboardState::KeyPressType KeyboardState::getKeyPressType(int *key) const |
osmeest | 0:1324e7d9d471 | 124 | { |
osmeest | 0:1324e7d9d471 | 125 | if (key) { |
osmeest | 0:1324e7d9d471 | 126 | *key = -1; |
osmeest | 0:1324e7d9d471 | 127 | } |
osmeest | 0:1324e7d9d471 | 128 | |
osmeest | 0:1324e7d9d471 | 129 | Data::const_iterator p = this->data.begin(); |
osmeest | 0:1324e7d9d471 | 130 | std::size_t wordIndex = 0; |
osmeest | 0:1324e7d9d471 | 131 | while (p != this->data.end() && *p == 0) { |
osmeest | 0:1324e7d9d471 | 132 | ++p; |
osmeest | 0:1324e7d9d471 | 133 | ++wordIndex; |
osmeest | 0:1324e7d9d471 | 134 | } |
osmeest | 0:1324e7d9d471 | 135 | if (p != this->data.end()) { |
osmeest | 0:1324e7d9d471 | 136 | int v = *p; |
osmeest | 0:1324e7d9d471 | 137 | if (v != (v & -v)) { |
osmeest | 0:1324e7d9d471 | 138 | return MultiKeyPress; |
osmeest | 0:1324e7d9d471 | 139 | } |
osmeest | 0:1324e7d9d471 | 140 | int k = getBitNumber(v) + wordIndex * this->numKeysPerWord; |
osmeest | 0:1324e7d9d471 | 141 | ++p; |
osmeest | 0:1324e7d9d471 | 142 | while (p != this->data.end() && *p == 0) { |
osmeest | 0:1324e7d9d471 | 143 | ++p; |
osmeest | 0:1324e7d9d471 | 144 | } |
osmeest | 0:1324e7d9d471 | 145 | if (p == this->data.end()) { |
osmeest | 0:1324e7d9d471 | 146 | if (key) { |
osmeest | 0:1324e7d9d471 | 147 | *key = k; |
osmeest | 0:1324e7d9d471 | 148 | } |
osmeest | 0:1324e7d9d471 | 149 | return SingleKeyPress; |
osmeest | 0:1324e7d9d471 | 150 | } |
osmeest | 0:1324e7d9d471 | 151 | else { |
osmeest | 0:1324e7d9d471 | 152 | return MultiKeyPress; |
osmeest | 0:1324e7d9d471 | 153 | } |
osmeest | 0:1324e7d9d471 | 154 | } |
osmeest | 0:1324e7d9d471 | 155 | else { |
osmeest | 0:1324e7d9d471 | 156 | return Idle; |
osmeest | 0:1324e7d9d471 | 157 | } |
osmeest | 0:1324e7d9d471 | 158 | } |
osmeest | 0:1324e7d9d471 | 159 | |
osmeest | 0:1324e7d9d471 | 160 | void KeyboardState::streamTo(std::ostream &out) const { |
osmeest | 0:1324e7d9d471 | 161 | using namespace std; |
osmeest | 0:1324e7d9d471 | 162 | std::size_t width = (this->numKeysPerWord + 3) / 4; |
osmeest | 0:1324e7d9d471 | 163 | ios_base::fmtflags f = out.flags(); |
osmeest | 0:1324e7d9d471 | 164 | for(Data::const_reverse_iterator p = this->data.rbegin(); p != this->data.rend(); ++p) { |
osmeest | 0:1324e7d9d471 | 165 | out << hex << setw(width) << setfill('0') << *p; |
osmeest | 0:1324e7d9d471 | 166 | } |
osmeest | 0:1324e7d9d471 | 167 | out.flags(f); |
osmeest | 0:1324e7d9d471 | 168 | } |
osmeest | 0:1324e7d9d471 | 169 | |
osmeest | 0:1324e7d9d471 | 170 | } // kbd_mgr |