Merge pull request #504 from keyboardio/hardware/base-class

Implement a kaleidoscope::Hardware base class
pull/508/head v1.94.0
Jesse Vincent 6 years ago committed by GitHub
commit eda312d392
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,271 @@
/* -*- mode: c++ -*-
* Kaleidoscope-Hardware -- Kaleidoscope Hardware Base class
* Copyright (C) 2017, 2018 Keyboard.io, Inc
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file kaleidoscope/Hardware.h
* Base class for Kaleidoscope hardware libraries.
*/
#pragma once
#ifndef CRGB
#error cRGB and CRGB *must* be defined before including this header!
#endif
/* All hardware libraries must define the following macros:
* HARDWARE_IMPLEMENTATION - the name of your public object conforming to
* the 'class Hardware' interface below.
* CRGB(r,g,b) - explained below
*/
/**
* Forward declaration of the cRGB structure.
*
* The base class does not define the cRGB structure, that is left up to the
* individual Hardware libraries. We do a forward declaration here, because the
* base hardware has methods that depend on a cRGB structure.
*
* The structure will need to have at least three members: r, g, and b -
* compilation will fail otherwise.
*
* Despite its name, the members do not need to be in the order r g b -- most
* likely they will be in an order that is convenient for the hardware. So
* initializing a cRGB with a struct literal will give surprising results for any
* colors where r, g, and b do not have the same value. Each Hardware library
* defines a CRGB(r,g,b) macro which returns a literal cRGB with the given values.
*/
typedef struct cRGB cRGB;
namespace kaleidoscope {
/** Kaleidoscope Hardware base class.
* Essential methods all hardware libraries must implement.
*/
class Hardware {
public:
/**
* @defgroup kaleidoscope_hardware_leds Kaleidoscope::Hardware/LEDs
* @{
*/
/**
* Sync the LEDs with the underlying hardware. This should make sure that
* changes made before this call are reflected on the device.
*/
void syncLeds(void) {}
/**
* Set the color of a per-key LED at a given row and column.
*
* Setting the color does not need to take effect immediately, it can be
* delayed until @ref syncLeds is called.
*
* @param row is the logical row position of the key.
* @param col is the logical column position of the key.
* @param color is the color to set the LED to.
*/
void setCrgbAt(byte row, byte col, cRGB color) {}
/**
* Set the color of a per-key LED at a given LED index.
*
* Setting the color does not need to take effect immediately, it can be
* delayed until @ref syncLeds is called.
*
* @param i is the LED index to change the color of.
* @param color is the color to set it to.
*/
void setCrgbAt(uint8_t i, cRGB color) {}
/**
* Returns the color of the LED at a given index.
*
* @param i is the index of the LED to return the color of.
*
* @returns The color at the given position.
*/
cRGB getCrgbAt(uint8_t i) {
cRGB c = {
0, 0, 0
};
return c;
}
/**
* Returns the index of the LED at a given row & column.
*
* @param row is the logical row position of the key.
* @param col is the logical column position of the key.
*
* @returns The index of the LED at the given position, or -1 if there are no
* LEDs there.
*/
int8_t getLedIndex(uint8_t row, byte col) {
return -1;
}
/** @} */
/** @defgroup kaleidoscope_hardware_matrix Kaleidoscope::Hardware/Matrix
* @{
*/
/**
* Scan the keyboard matrix, and act on it.
*/
void scanMatrix(void) {}
/**
* Read the state of the keyboard matrix.
*
* Do whatever is necessary to read the current keyboard state - but without
* acting on it.
*
* This is primarily used by @ref scanMatrix, but may have other uses too.
*/
void readMatrix(void) {}
/**
* Act on the scanned keyboard matrix.
*
* Iterate through the scanned state (@see readMatrix), and act on any events.
*/
void actOnMatrixScan(void) {}
/** @} */
/** @defgroup kaleidoscope_hardware_masking Kaleidoscope::Hardware/Key masking
*
* Sometimes there are situations when one wants to ignore key events for a
* while, to mask them out. Masked keys will be ignored until they are
* released.
*
* This is implemented in the Hardware library because that knows best how
* to mask efficiently, as this requires a deeper knowledge of the hardware,
* which is all but hidden from the rest of the plugins.
* @{
*/
/**
* Mask out a key.
*
* Masking a key out means that any other event than a release will be
* ignored until said release.
*
* @param row is the row the key is located at in the matrix.
* @param col is the column the key is located at in the matrix.
*/
void maskKey(byte row, byte col) {}
/**
* Unmask a key.
*
* Remove the mask - if any - for a given key. To be used when the mask
* needs to be removed without the key being released.
*
* @param row is the row the key is located at in the matrix.
* @param col is the column the key is located at in the matrix.
*/
void unMaskKey(byte row, byte col) {}
/**
* Check whether a key is masked or not.
*
* @param row is the row the key is located at in the matrix.
* @param col is the column the key is located at in the matrix.
*
* @returns true if the key is masked, false otherwise.
*/
bool isKeyMasked(byte row, byte col) {
return false;
}
/** @} */
/** @defgroup kaleidoscope_hardware_reattach Kaleidoscope::Hardware/Attach & Detach
*
* In situations where one wants to re-initialize the devices, perhaps to
* change settings inbetween, detaching from and then attaching back to the
* host is a desirable feature to have. Especially if this does not cut power,
* nor reboot the device.
*
* Because different hardware has different ways to accomplish this, the
* hardware plugin must provide these functions. Kaleidoscope will wrap them,
* so user code does not have to deal with KeyboardHardware.
* @{
*/
/**
* Detach the device from the host.
*
* Must detach the device, without rebooting or cutting power. Only the end
* points should get detached, the device must remain powered on.
*/
void detachFromHost() {
UDCON |= _BV(DETACH);
}
/**
* Attack the device to the host.
*
* Must restore the link detachFromHost severed.
*/
void attachToHost() {
UDCON &= ~_BV(DETACH);
}
/** @} */
/**
* @defgroup kaleidoscope_hardware_keyswitch_state Kaleidoscope::Hardware/Key-switch state
*
* These methods offer a way to peek at the key switch states, for those cases
* where we need to deal with the state closest to the hardware. Some methods
* offer a way to check if a key is pressed, others return the number of
* pressed keys.
*
* @{
*/
/**
* Check if a key is pressed at a given position.
*
* @param row is the row the key is located at in the matrix.
* @param col is the column the key is located at in the matrix.
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(byte row, byte col) {
return false;
}
/**
* Check if a key is pressed at a given position.
*
* @param keyIndex is the key index, as calculated by `keyIndex`.
*
* @note Key indexes start at 1, not 0!
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(uint8_t keyIndex) {
return false;
}
/**
* Check the number of key switches currently pressed.
*
* @returns the number of keys pressed.
*/
uint8_t pressedKeyswitchCount() {
return 0;
}
/** @} */
/**
* @defgroup kaleidoscope_hardware_misc Kaleidoscope::Hardware/Miscellaneous methods
* @{
*/
/**
* Method to do any hardware-specific initialization.
*
* Called once when the device boots, this should initialize the device, and
* bring it up into a useful state.
*/
void setup() {}
/** @} */
};
}

@ -51,14 +51,6 @@ void ATMegaKeyboard::setup(void) {
TIMSK1 = _BV(TOIE1); TIMSK1 = _BV(TOIE1);
} }
void ATMegaKeyboard::detachFromHost() {
UDCON |= _BV(DETACH);
}
void ATMegaKeyboard::attachToHost() {
UDCON &= ~_BV(DETACH);
}
void __attribute__((optimize(3))) ATMegaKeyboard::readMatrix(void) { void __attribute__((optimize(3))) ATMegaKeyboard::readMatrix(void) {
for (uint8_t current_row = 0; current_row < KeyboardHardware.matrix_rows; current_row++) { for (uint8_t current_row = 0; current_row < KeyboardHardware.matrix_rows; current_row++) {
uint16_t mask, cols; uint16_t mask, cols;

@ -39,6 +39,8 @@ struct cRGB {
#endif #endif
#include "kaleidoscope/Hardware.h"
#define ROW_PIN_LIST(...) __VA_ARGS__ #define ROW_PIN_LIST(...) __VA_ARGS__
#define COL_PIN_LIST(...) __VA_ARGS__ #define COL_PIN_LIST(...) __VA_ARGS__
@ -69,85 +71,21 @@ struct cRGB {
namespace kaleidoscope { namespace kaleidoscope {
namespace hardware { namespace hardware {
class ATMegaKeyboard { class ATMegaKeyboard : public kaleidoscope::Hardware {
public: public:
ATMegaKeyboard(void) {} ATMegaKeyboard(void) {}
// these will be overridden by the subclass
static uint8_t debounce; static uint8_t debounce;
void syncLeds(void) {}
void setCrgbAt(uint8_t row, byte col, cRGB color) {}
void setCrgbAt(int8_t i, cRGB crgb) {}
cRGB getCrgbAt(int8_t i) {
return CRGB(0, 0, 0);
}
int8_t getLedIndex(uint8_t row, byte col) {
return -1;
}
void setup(void); void setup(void);
/** Detaching from / attaching to the host.
*
* These two functions should detach the device from (or attach it to) the
* host, preferably without rebooting the device. Their purpose is to allow
* one to do some configuration inbetween, so the re-attach happens with
* different properties. The device remains powered between these operations,
* only the connection to the host gets severed.
*/
void detachFromHost();
void attachToHost();
void readMatrix(void); void readMatrix(void);
void actOnMatrixScan();
void scanMatrix();
/**
* Check the number of key switches currently pressed.
*
* @returns the number of keys pressed.
*/
uint8_t pressedKeyswitchCount(); uint8_t pressedKeyswitchCount();
/** Key switch states
*
* These methods offer a way to peek at the key switch states, for those cases
* where we need to deal with the state closest to the hardware. Some methods
* offer a way to check if a key is pressed, others return the number of
* pressed keys.
*/
/**
* Check if a key is pressed at a given position.
*
* @param row is the row the key is located at in the matrix.
* @param col is the column the key is located at in the matrix.
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(uint8_t row, byte col); bool isKeyswitchPressed(uint8_t row, byte col);
/**
* Check if a key is pressed at a given position.
*
* @param keyIndex is the key index, as calculated by `keyIndex`.
*
* @note Key indexes start at 1, not 0!
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(uint8_t keyIndex); bool isKeyswitchPressed(uint8_t keyIndex);
void actOnMatrixScan();
void scanMatrix();
/* Key masking
* -----------
*
* There are situations when one wants to ignore key events for a while, and
* mask them out. These functions help do that. In isolation, they do nothing,
* plugins and the core firmware is expected to make use of these.
*
* See `handleKeyswitchEvent` in the Kaleidoscope sources for a use-case.
*/
void maskKey(byte row, byte col); void maskKey(byte row, byte col);
void unMaskKey(byte row, byte col); void unMaskKey(byte row, byte col);
bool isKeyMasked(byte row, byte col); bool isKeyMasked(byte row, byte col);

@ -223,14 +223,6 @@ void ErgoDox::debounceRow(uint8_t change, uint8_t row) {
} }
} }
void ErgoDox::detachFromHost() {
UDCON |= (1 << DETACH);
}
void ErgoDox::attachToHost() {
UDCON &= ~(1 << DETACH);
}
bool ErgoDox::isKeyswitchPressed(byte row, byte col) { bool ErgoDox::isKeyswitchPressed(byte row, byte col) {
return (bitRead(keyState_[row], col) != 0); return (bitRead(keyState_[row], col) != 0);
} }

@ -42,11 +42,13 @@ struct cRGB {
#define CRGB(r,g,b) (cRGB){b, g, r} #define CRGB(r,g,b) (cRGB){b, g, r}
#include "kaleidoscope/Hardware.h"
namespace kaleidoscope { namespace kaleidoscope {
namespace hardware { namespace hardware {
namespace ez { namespace ez {
class ErgoDox { class ErgoDox : public kaleidoscope::Hardware {
public: public:
ErgoDox(void) {} ErgoDox(void) {}
@ -54,76 +56,17 @@ class ErgoDox {
static constexpr byte matrix_rows = 14; static constexpr byte matrix_rows = 14;
static constexpr int8_t led_count = 0; static constexpr int8_t led_count = 0;
void syncLeds(void) {}
void setCrgbAt(byte row, byte col, cRGB color) {}
void setCrgbAt(int8_t i, cRGB crgb) {}
cRGB getCrgbAt(int8_t i) {
return CRGB(0, 0, 0);
}
int8_t getLedIndex(byte row, byte col) {
return -1;
}
void scanMatrix(void); void scanMatrix(void);
void readMatrix(void); void readMatrix(void);
void actOnMatrixScan(void); void actOnMatrixScan(void);
void setup(); void setup();
/** Detaching from / attaching to the host.
*
* These two functions should detach the device from (or attach it to) the
* host, preferably without rebooting the device. Their purpose is to allow
* one to do some configuration inbetween, so the re-attach happens with
* different properties. The device remains powered between these operations,
* only the connection to the host gets severed.
*/
void detachFromHost();
void attachToHost();
/* Key masking
* -----------
*
* There are situations when one wants to ignore key events for a while, and
* mask them out. These functions help do that. In isolation, they do nothing,
* plugins and the core firmware is expected to make use of these.
*
* See `handleKeyswitchEvent` in the Kaleidoscope sources for a use-case.
*/
void maskKey(byte row, byte col); void maskKey(byte row, byte col);
void unMaskKey(byte row, byte col); void unMaskKey(byte row, byte col);
bool isKeyMasked(byte row, byte col); bool isKeyMasked(byte row, byte col);
/** Key switch states
*
* These methods offer a way to peek at the key switch states, for those cases
* where we need to deal with the state closest to the hardware. Some methods
* offer a way to check if a key is pressed, others return the number of
* pressed keys.
*/
/**
* Check if a key is pressed at a given position.
*
* @param row is the row the key is located at in the matrix.
* @param col is the column the key is located at in the matrix.
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(byte row, byte col); bool isKeyswitchPressed(byte row, byte col);
/**
* Check if a key is pressed at a given position.
*
* @param keyIndex is the key index, as calculated by `keyIndex`.
*
* @note Key indexes start at 1, not 0!
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(uint8_t keyIndex); bool isKeyswitchPressed(uint8_t keyIndex);
/**
* Check the number of key switches currently pressed.
*
* @returns the number of keys pressed.
*/
uint8_t pressedKeyswitchCount(); uint8_t pressedKeyswitchCount();
// ErgoDox-specific stuff // ErgoDox-specific stuff

@ -292,14 +292,6 @@ void Model01::setKeyscanInterval(uint8_t interval) {
rightHand.setKeyscanInterval(interval); rightHand.setKeyscanInterval(interval);
} }
void Model01::detachFromHost() {
UDCON |= (1 << DETACH);
}
void Model01::attachToHost() {
UDCON &= ~(1 << DETACH);
}
bool Model01::isKeyswitchPressed(byte row, byte col) { bool Model01::isKeyswitchPressed(byte row, byte col) {
if (col <= 7) { if (col <= 7) {
return (bitRead(leftHandState.rows[row], 7 - col) != 0); return (bitRead(leftHandState.rows[row], 7 - col) != 0);

@ -29,11 +29,13 @@
#define CRGB(r,g,b) (cRGB){b, g, r} #define CRGB(r,g,b) (cRGB){b, g, r}
#include "kaleidoscope/Hardware.h"
namespace kaleidoscope { namespace kaleidoscope {
namespace hardware { namespace hardware {
namespace keyboardio { namespace keyboardio {
class Model01 { class Model01 : public kaleidoscope::Hardware {
public: public:
Model01(void); Model01(void);
@ -53,17 +55,6 @@ class Model01 {
void setup(); void setup();
void rebootBootloader(); void rebootBootloader();
/** Detaching from / attaching to the host.
*
* These two functions should detach the device from (or attach it to) the
* host, preferably without rebooting the device. Their purpose is to allow
* one to do some configuration inbetween, so the re-attach happens with
* different properties. The device remains powered between these operations,
* only the connection to the host gets severed.
*/
void detachFromHost();
void attachToHost();
/* These public functions are things supported by the Model 01, but /* These public functions are things supported by the Model 01, but
* aren't necessarily part of the Kaleidoscope API * aren't necessarily part of the Kaleidoscope API
*/ */
@ -72,51 +63,13 @@ class Model01 {
void setKeyscanInterval(uint8_t interval); void setKeyscanInterval(uint8_t interval);
boolean ledPowerFault(void); boolean ledPowerFault(void);
/* Key masking
* -----------
*
* There are situations when one wants to ignore key events for a while, and
* mask them out. These functions help do that. In isolation, they do nothing,
* plugins and the core firmware is expected to make use of these.
*
* See `handleKeyswitchEvent` in the Kaleidoscope sources for a use-case.
*/
void maskKey(byte row, byte col); void maskKey(byte row, byte col);
void unMaskKey(byte row, byte col); void unMaskKey(byte row, byte col);
bool isKeyMasked(byte row, byte col); bool isKeyMasked(byte row, byte col);
void maskHeldKeys(void); void maskHeldKeys(void);
/** Key switch states
*
* These methods offer a way to peek at the key switch states, for those cases
* where we need to deal with the state closest to the hardware. Some methods
* offer a way to check if a key is pressed, others return the number of
* pressed keys.
*/
/**
* Check if a key is pressed at a given position.
*
* @param row is the row the key is located at in the matrix.
* @param col is the column the key is located at in the matrix.
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(byte row, byte col); bool isKeyswitchPressed(byte row, byte col);
/**
* Check if a key is pressed at a given position.
*
* @param keyIndex is the key index, as calculated by `keyIndex`.
*
* @note Key indexes start at 1, not 0!
*
* @returns true if the key is pressed, false otherwise.
*/
bool isKeyswitchPressed(uint8_t keyIndex); bool isKeyswitchPressed(uint8_t keyIndex);
/**
* Check the number of key switches currently pressed.
*
* @returns the number of keys pressed.
*/
uint8_t pressedKeyswitchCount(); uint8_t pressedKeyswitchCount();
keydata_t leftHandState; keydata_t leftHandState;

Loading…
Cancel
Save