KeyboardManager: a class to manage the polling of a switch-matrix keyboard
Diff: KeyboardState.cpp
- Revision:
- 3:1310c57aca77
- Parent:
- 2:eb4cc53ff33d
--- a/KeyboardState.cpp Sun Jan 23 23:15:36 2011 +0000 +++ b/KeyboardState.cpp Thu Feb 03 22:01:57 2011 +0000 @@ -1,170 +1,170 @@ -#include "kbd_mgr/KeyboardState.h" - -#include <algorithm> -#include <iomanip> - -namespace kbd_mgr { - -KeyboardState::KeyboardState() : - numRows(0), numKeysPerRow(0), rowMask(0), numRowsPerWord(0), numKeysPerWord(0), numWords(0), data(0) -{ } - -KeyboardState::KeyboardState(std::size_t numRows, std::size_t numKeysPerRow) : - numRows(numRows), numKeysPerRow(numKeysPerRow), rowMask((1 << numKeysPerRow) -1), - numRowsPerWord((sizeof(int) * 8) / numKeysPerRow), numKeysPerWord(numRowsPerWord * numKeysPerRow), - numWords((numRows + (numRowsPerWord-1)) / numRowsPerWord), - data(numWords, 0) -{ } - -void KeyboardState::clear() { - std::fill(this->data.begin(), this->data.end(), 0); -} - -int KeyboardState::getRowInfo(std::size_t row, std::size_t &wordIndex, std::size_t &rowShift, int &rowMask) const -{ - std::size_t rowInWord = row % numRowsPerWord; - wordIndex = row / numRowsPerWord; - rowShift = numKeysPerRow * rowInWord; - rowMask = this->rowMask << rowShift; - - return this->data[wordIndex]; -} - -void KeyboardState::setRowState(std::size_t row, int rowState) { - std::size_t wordIndex; - std::size_t rowShift; - int rowMask; - int v = getRowInfo(row, wordIndex, rowShift, rowMask); - v = (v & ~rowMask) | ((rowState & this->rowMask) << rowShift); - this->data[wordIndex] = v; -} - -int KeyboardState::getRowState(std::size_t row) const { - std::size_t wordIndex; - std::size_t rowShift; - int rowMask; - int v = getRowInfo(row, wordIndex, rowShift, rowMask); - return (v & rowMask) >> rowShift; -} - -bool KeyboardState::getKeyState(std::size_t key) const { - std::size_t row = key / this->numKeysPerRow; - std::size_t keyInRow = key % this->numKeysPerRow; - int keyMask = 1 << keyInRow; - - return (getRowState(row) & keyMask) != 0; -} - -KeyboardState KeyboardState::operator&(const KeyboardState &other) const { - KeyboardState result(this->numRows, this->numKeysPerRow); - - typedef Data::const_iterator SourceIterator; - typedef Data::iterator TargetIterator; - - SourceIterator a = this->data.begin(); - SourceIterator b = other.data.begin(); - TargetIterator t = result.data.begin(); - while (a != this->data.end() && b != other.data.end() && t != result.data.end()) - { - *t = *a & *b; - ++a; ++b; ++t; - } - - return result; -} - -bool KeyboardState::operator==(const KeyboardState &other) const { - if (this == &other) { - return true; - } - - if (this->numRows != other.numRows || this->numKeysPerRow != other.numKeysPerRow) - return false; - - Data::const_iterator p = this->data.begin(); - Data::const_iterator q = other.data.begin(); - while (p != this->data.end() && q != other.data.end()) { - if (*p != *q) { - return false; - } - ++p; ++q; - } - - return true; -} - -bool KeyboardState::empty() const { - for(Data::const_iterator p = this->data.begin(); p != this->data.end(); ++p) { - if (*p != 0) { - return false; - } - } - - return true; -} - -namespace { - int getBitNumber(int v) - { - if (v == 0) { - return -1; - } - - int key = 0; - while (v != 1) { - key++; - v >>= 1; - } - - return key; - } -} - -KeyboardState::KeyPressType KeyboardState::getKeyPressType(int *key) const -{ - if (key) { - *key = -1; - } - - Data::const_iterator p = this->data.begin(); - std::size_t wordIndex = 0; - while (p != this->data.end() && *p == 0) { - ++p; - ++wordIndex; - } - if (p != this->data.end()) { - int v = *p; - if (v != (v & -v)) { - return MultiKeyPress; - } - int k = getBitNumber(v) + wordIndex * this->numKeysPerWord; - ++p; - while (p != this->data.end() && *p == 0) { - ++p; - } - if (p == this->data.end()) { - if (key) { - *key = k; - } - return SingleKeyPress; - } - else { - return MultiKeyPress; - } - } - else { - return Idle; - } -} - -void KeyboardState::streamTo(std::ostream &out) const { - using namespace std; - std::size_t width = (this->numKeysPerWord + 3) / 4; - ios_base::fmtflags f = out.flags(); - for(Data::const_reverse_iterator p = this->data.rbegin(); p != this->data.rend(); ++p) { - out << hex << setw(width) << setfill('0') << *p; - } - out.flags(f); -} - +#include "kbd_mgr/KeyboardState.h" + +#include <algorithm> +#include <iomanip> + +namespace kbd_mgr { + +KeyboardState::KeyboardState() : + numRows(0), numKeysPerRow(0), rowMask(0), numRowsPerWord(0), numKeysPerWord(0), numWords(0), data(0) +{ } + +KeyboardState::KeyboardState(std::size_t numRows, std::size_t numKeysPerRow) : + numRows(numRows), numKeysPerRow(numKeysPerRow), rowMask((1 << numKeysPerRow) -1), + numRowsPerWord((sizeof(int) * 8) / numKeysPerRow), numKeysPerWord(numRowsPerWord * numKeysPerRow), + numWords((numRows + (numRowsPerWord-1)) / numRowsPerWord), + data(numWords, 0) +{ } + +void KeyboardState::clear() { + std::fill(this->data.begin(), this->data.end(), 0); +} + +int KeyboardState::getRowInfo(std::size_t row, std::size_t &wordIndex, std::size_t &rowShift, int &rowMask) const +{ + std::size_t rowInWord = row % numRowsPerWord; + wordIndex = row / numRowsPerWord; + rowShift = numKeysPerRow * rowInWord; + rowMask = this->rowMask << rowShift; + + return this->data[wordIndex]; +} + +void KeyboardState::setRowState(std::size_t row, int rowState) { + std::size_t wordIndex; + std::size_t rowShift; + int rowMask; + int v = getRowInfo(row, wordIndex, rowShift, rowMask); + v = (v & ~rowMask) | ((rowState & this->rowMask) << rowShift); + this->data[wordIndex] = v; +} + +int KeyboardState::getRowState(std::size_t row) const { + std::size_t wordIndex; + std::size_t rowShift; + int rowMask; + int v = getRowInfo(row, wordIndex, rowShift, rowMask); + return (v & rowMask) >> rowShift; +} + +bool KeyboardState::getKeyState(std::size_t key) const { + std::size_t row = key / this->numKeysPerRow; + std::size_t keyInRow = key % this->numKeysPerRow; + int keyMask = 1 << keyInRow; + + return (getRowState(row) & keyMask) != 0; +} + +KeyboardState KeyboardState::operator&(const KeyboardState &other) const { + KeyboardState result(this->numRows, this->numKeysPerRow); + + typedef Data::const_iterator SourceIterator; + typedef Data::iterator TargetIterator; + + SourceIterator a = this->data.begin(); + SourceIterator b = other.data.begin(); + TargetIterator t = result.data.begin(); + while (a != this->data.end() && b != other.data.end() && t != result.data.end()) + { + *t = *a & *b; + ++a; ++b; ++t; + } + + return result; +} + +bool KeyboardState::operator==(const KeyboardState &other) const { + if (this == &other) { + return true; + } + + if (this->numRows != other.numRows || this->numKeysPerRow != other.numKeysPerRow) + return false; + + Data::const_iterator p = this->data.begin(); + Data::const_iterator q = other.data.begin(); + while (p != this->data.end() && q != other.data.end()) { + if (*p != *q) { + return false; + } + ++p; ++q; + } + + return true; +} + +bool KeyboardState::empty() const { + for(Data::const_iterator p = this->data.begin(); p != this->data.end(); ++p) { + if (*p != 0) { + return false; + } + } + + return true; +} + +namespace { + int getBitNumber(int v) + { + if (v == 0) { + return -1; + } + + int key = 0; + while (v != 1) { + key++; + v >>= 1; + } + + return key; + } +} + +KeyboardState::KeyPressType KeyboardState::getKeyPressType(int *key) const +{ + if (key) { + *key = -1; + } + + Data::const_iterator p = this->data.begin(); + std::size_t wordIndex = 0; + while (p != this->data.end() && *p == 0) { + ++p; + ++wordIndex; + } + if (p != this->data.end()) { + int v = *p; + if (v != (v & -v)) { + return MultiKeyPress; + } + int k = getBitNumber(v) + wordIndex * this->numKeysPerWord; + ++p; + while (p != this->data.end() && *p == 0) { + ++p; + } + if (p == this->data.end()) { + if (key) { + *key = k; + } + return SingleKeyPress; + } + else { + return MultiKeyPress; + } + } + else { + return Idle; + } +} + +void KeyboardState::streamTo(std::ostream &out) const { + using namespace std; + std::size_t width = (this->numKeysPerWord + 3) / 4; + ios_base::fmtflags f = out.flags(); + for(Data::const_reverse_iterator p = this->data.rbegin(); p != this->data.rend(); ++p) { + out << hex << setw(width) << setfill('0') << *p; + } + out.flags(f); +} + } // kbd_mgr \ No newline at end of file