KeyboardManager: a class to manage the polling of a switch-matrix keyboard
Embed:
(wiki syntax)
Show/hide line numbers
KeyboardState.cpp
00001 #include "kbd_mgr/KeyboardState.h" 00002 00003 #include <algorithm> 00004 #include <iomanip> 00005 00006 namespace kbd_mgr { 00007 00008 KeyboardState::KeyboardState() : 00009 numRows(0), numKeysPerRow(0), rowMask(0), numRowsPerWord(0), numKeysPerWord(0), numWords(0), data(0) 00010 { } 00011 00012 KeyboardState::KeyboardState(std::size_t numRows, std::size_t numKeysPerRow) : 00013 numRows(numRows), numKeysPerRow(numKeysPerRow), rowMask((1 << numKeysPerRow) -1), 00014 numRowsPerWord((sizeof(int) * 8) / numKeysPerRow), numKeysPerWord(numRowsPerWord * numKeysPerRow), 00015 numWords((numRows + (numRowsPerWord-1)) / numRowsPerWord), 00016 data(numWords, 0) 00017 { } 00018 00019 void KeyboardState::clear() { 00020 std::fill(this->data.begin(), this->data.end(), 0); 00021 } 00022 00023 int KeyboardState::getRowInfo(std::size_t row, std::size_t &wordIndex, std::size_t &rowShift, int &rowMask) const 00024 { 00025 std::size_t rowInWord = row % numRowsPerWord; 00026 wordIndex = row / numRowsPerWord; 00027 rowShift = numKeysPerRow * rowInWord; 00028 rowMask = this->rowMask << rowShift; 00029 00030 return this->data[wordIndex]; 00031 } 00032 00033 void KeyboardState::setRowState(std::size_t row, int rowState) { 00034 std::size_t wordIndex; 00035 std::size_t rowShift; 00036 int rowMask; 00037 int v = getRowInfo(row, wordIndex, rowShift, rowMask); 00038 v = (v & ~rowMask) | ((rowState & this->rowMask) << rowShift); 00039 this->data[wordIndex] = v; 00040 } 00041 00042 int KeyboardState::getRowState(std::size_t row) const { 00043 std::size_t wordIndex; 00044 std::size_t rowShift; 00045 int rowMask; 00046 int v = getRowInfo(row, wordIndex, rowShift, rowMask); 00047 return (v & rowMask) >> rowShift; 00048 } 00049 00050 bool KeyboardState::getKeyState(std::size_t key) const { 00051 std::size_t row = key / this->numKeysPerRow; 00052 std::size_t keyInRow = key % this->numKeysPerRow; 00053 int keyMask = 1 << keyInRow; 00054 00055 return (getRowState(row) & keyMask) != 0; 00056 } 00057 00058 KeyboardState KeyboardState::operator&(const KeyboardState &other) const { 00059 KeyboardState result(this->numRows, this->numKeysPerRow); 00060 00061 typedef Data::const_iterator SourceIterator; 00062 typedef Data::iterator TargetIterator; 00063 00064 SourceIterator a = this->data.begin(); 00065 SourceIterator b = other.data.begin(); 00066 TargetIterator t = result.data.begin(); 00067 while (a != this->data.end() && b != other.data.end() && t != result.data.end()) 00068 { 00069 *t = *a & *b; 00070 ++a; ++b; ++t; 00071 } 00072 00073 return result; 00074 } 00075 00076 bool KeyboardState::operator==(const KeyboardState &other) const { 00077 if (this == &other) { 00078 return true; 00079 } 00080 00081 if (this->numRows != other.numRows || this->numKeysPerRow != other.numKeysPerRow) 00082 return false; 00083 00084 Data::const_iterator p = this->data.begin(); 00085 Data::const_iterator q = other.data.begin(); 00086 while (p != this->data.end() && q != other.data.end()) { 00087 if (*p != *q) { 00088 return false; 00089 } 00090 ++p; ++q; 00091 } 00092 00093 return true; 00094 } 00095 00096 bool KeyboardState::empty() const { 00097 for(Data::const_iterator p = this->data.begin(); p != this->data.end(); ++p) { 00098 if (*p != 0) { 00099 return false; 00100 } 00101 } 00102 00103 return true; 00104 } 00105 00106 namespace { 00107 int getBitNumber(int v) 00108 { 00109 if (v == 0) { 00110 return -1; 00111 } 00112 00113 int key = 0; 00114 while (v != 1) { 00115 key++; 00116 v >>= 1; 00117 } 00118 00119 return key; 00120 } 00121 } 00122 00123 KeyboardState::KeyPressType KeyboardState::getKeyPressType(int *key) const 00124 { 00125 if (key) { 00126 *key = -1; 00127 } 00128 00129 Data::const_iterator p = this->data.begin(); 00130 std::size_t wordIndex = 0; 00131 while (p != this->data.end() && *p == 0) { 00132 ++p; 00133 ++wordIndex; 00134 } 00135 if (p != this->data.end()) { 00136 int v = *p; 00137 if (v != (v & -v)) { 00138 return MultiKeyPress; 00139 } 00140 int k = getBitNumber(v) + wordIndex * this->numKeysPerWord; 00141 ++p; 00142 while (p != this->data.end() && *p == 0) { 00143 ++p; 00144 } 00145 if (p == this->data.end()) { 00146 if (key) { 00147 *key = k; 00148 } 00149 return SingleKeyPress; 00150 } 00151 else { 00152 return MultiKeyPress; 00153 } 00154 } 00155 else { 00156 return Idle; 00157 } 00158 } 00159 00160 void KeyboardState::streamTo(std::ostream &out) const { 00161 using namespace std; 00162 std::size_t width = (this->numKeysPerWord + 3) / 4; 00163 ios_base::fmtflags f = out.flags(); 00164 for(Data::const_reverse_iterator p = this->data.rbegin(); p != this->data.rend(); ++p) { 00165 out << hex << setw(width) << setfill('0') << *p; 00166 } 00167 out.flags(f); 00168 } 00169 00170 } // kbd_mgr
Generated on Thu Jul 14 2022 19:25:04 by 1.7.2