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

Dependents:   KeyboardTest

kbd_mgr/KeyboardState.h

Committer:
osmeest
Date:
2011-02-03
Revision:
3:1310c57aca77
Parent:
2:eb4cc53ff33d

File content as of revision 3:1310c57aca77:

#ifndef KEYBOARD_STATE_H_
#define KEYBOARD_STATE_H_

#include <vector>
#include <iostream>

namespace kbd_mgr {

/**
 * @brief A class to hold the state of a keyboard.
 * A keyboard is handled as a set of key rows. Each row can have as many keys as there are bits in integers.
 * The class maintains an array of integers to handle the number of rows.
 * If possible, multiple rows are combined in a single integer to reduce memory footprint.
 */
class KeyboardState {
public:
    /**
     * @brief Constructor for a 0x0 keyboard state.
     */
    KeyboardState();
    
    /**
     * @brief Constructor for a NxM keyboard state.
     * @param numRows       Number of key rows (unlimited)
     * @param numKeysPerRow Number of keys per row (limited to the number of bits in an integer).
     */
    KeyboardState(std::size_t numRows, std::size_t numKeysPerRow);

    std::size_t getNumRows() const { return this->numRows; }
    std::size_t getNumKeysPerRow() const { return this->numKeysPerRow; }
    std::size_t getNumKeys() const { return this->numRows * this->numKeysPerRow; }
    
    void clear();
    void setRowState(std::size_t row, int rowState);
    int getRowState(std::size_t row) const;
    bool getKeyState(std::size_t key) const;
    
    /**
     * @brief Executes a XOR between two states.
     * @return a state that represents the keys that changed of state.
     */
    KeyboardState operator^(const KeyboardState &other) const;
    
    /**
     * @brief Executes an AND between two states.
     */
    KeyboardState operator&(const KeyboardState &mask) const;
    
    bool operator==(const KeyboardState &other) const;
    bool operator!=(const KeyboardState &other) const { return !(*this == other); }
    
    /**
     * @brief Checks if a keyboard state is full of 0.
     */
    bool empty() const;
    
    enum KeyPressType {
        Idle, SingleKeyPress, MultiKeyPress
    };
    
    /**
     * @brief Determines the kind of key press present in the state.
     * The keyboard state can represent an idle keyboard, a single key pressed
     * or a key combination. This method determines which type of state this is.
     * If a single key is represented, the key index can be retrieved.
     * @param key   An integer where the single key pressed should be stored.
     */
    KeyPressType getKeyPressType(int *key = NULL) const;
    KeyPressType getKeyPressType(int &key) const { return getKeyPressType(&key); }
    
    void streamTo(std::ostream &out) const;
    
private:
    int getRowInfo(std::size_t row, std::size_t &wordIndex, std::size_t &rowShift, int &rowMask) const;

    std::size_t numRows;
    std::size_t numKeysPerRow;
    int rowMask;
    std::size_t numRowsPerWord;
    std::size_t numKeysPerWord;
    std::size_t numWords;
    
    typedef std::vector<int> Data;
    Data data;
};

inline std::ostream & operator<<(std::ostream &out, const KeyboardState &s) {
    s.streamTo(out);
    return out;
}

} // kbd_mgr

#endif // KEYBOARD_STATE_H_