KeyboardManager: a class to manage the polling of a switch-matrix keyboard

Dependents:   KeyboardTest

Committer:
osmeest
Date:
Thu Feb 03 22:01:57 2011 +0000
Revision:
3:1310c57aca77
Parent:
2:eb4cc53ff33d
improve code structure, add key mapping and long key press handling

Who changed what in which revision?

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