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

Dependents:   KeyboardTest

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers KeyboardState.cpp Source File

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