Moved stuff over from plugin Kaleidoscope-HardwareVirtual

Plugin Kaleidoscope-HardwareVirtual is now obsolete.
Everything device related has been incorporated in the
core repo as a virtual device in kaleidoscope/devices/virtual.

Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
pull/729/head
Florian Fleissner 5 years ago committed by Jesse Vincent
parent f524955253
commit 0356318fa8
No known key found for this signature in database
GPG Key ID: CC228463465E40BC

@ -0,0 +1,125 @@
/* Kaleidoscope - Firmware for computer input devices
* Copyright (C) 2013-2019 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/>.
*/
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
#include "DefaultHIDReportConsumer.h"
#include "MultiReport/Keyboard.h"
#include "Logging.h"
#include "virtual_io.h"
#undef min
#undef max
#include <sstream>
namespace kaleidoscope {
using namespace logging;
// For each bit set in 'bitfield', output the corresponding string to 'stream'
#define FOREACHBIT(bitfield, stream, str0, str1, str2, str3, str4, str5, str6, str7) \
if((bitfield) & 1<<0) stream << str0; \
if((bitfield) & 1<<1) stream << str1; \
if((bitfield) & 1<<2) stream << str2; \
if((bitfield) & 1<<3) stream << str3; \
if((bitfield) & 1<<4) stream << str4; \
if((bitfield) & 1<<5) stream << str5; \
if((bitfield) & 1<<6) stream << str6; \
if((bitfield) & 1<<7) stream << str7;
void DefaultHIDReportConsumer::processHIDReport(
uint8_t id, const void *data, int len, int result) {
if (id != HID_REPORTID_NKRO_KEYBOARD) {
log_info("***Ignoring hid report with id = %d\n", id);
return;
}
const HID_KeyboardReport_Data_t &report_data
= *static_cast<const HID_KeyboardReport_Data_t *>(data);
std::stringstream keypresses;
bool anything = false;
if (report_data.modifiers) anything = true;
else for (int i = 0; i < KEY_BYTES; i++) if (report_data.keys[i]) {
anything = true;
break;
}
if (!anything) {
keypresses << "none";
} else {
FOREACHBIT(report_data.modifiers, keypresses,
"lctrl ", "lshift ", "lalt ", "lgui ",
"rctrl ", "rshift ", "ralt ", "rgui ")
FOREACHBIT(report_data.keys[0], keypresses,
"NO_EVENT ", "ERROR_ROLLOVER ", "POST_FAIL ", "ERROR_UNDEFINED ",
"a ", "b ", "c ", "d ")
FOREACHBIT(report_data.keys[1], keypresses,
"e ", "f ", "g ", "h ", "i ", "j ", "k ", "l ")
FOREACHBIT(report_data.keys[2], keypresses,
"m ", "n ", "o ", "p ", "q ", "r ", "s ", "t ")
FOREACHBIT(report_data.keys[3], keypresses,
"u ", "v ", "w ", "x ", "y ", "z ", "1/! ", "2/@ ")
FOREACHBIT(report_data.keys[4], keypresses,
"3/# ", "4/$ ", "5/% ", "6/^ ", "7/& ", "8/* ", "9/( ", "0/) ")
FOREACHBIT(report_data.keys[5], keypresses,
"enter ", "esc ", "del/bksp ", "tab ",
"space ", "-/_ ", "=/+ ", "[/{ ")
FOREACHBIT(report_data.keys[6], keypresses,
"]/} ", "\\/| ", "#/~ ", ";/: ", "'/\" ", "`/~ ", ",/< ", "./> ")
FOREACHBIT(report_data.keys[7], keypresses,
"//? ", "capslock ", "F1 ", "F2 ", "F3 ", "F4 ", "F5 ", "F6 ")
FOREACHBIT(report_data.keys[8], keypresses,
"F7 ", "F8 ", "F9 ", "F10 ", "F11 ", "F12 ", "prtscr ", "scrolllock ")
FOREACHBIT(report_data.keys[9], keypresses,
"pause ", "ins ", "home ", "pgup ", "del ", "end ", "pgdn ", "r_arrow ")
FOREACHBIT(report_data.keys[10], keypresses,
"l_arrow ", "d_arrow ", "u_arrow ", "numlock ",
"num/ ", "num* ", "num- ", "num+ ")
FOREACHBIT(report_data.keys[11], keypresses,
"numenter ", "num1 ", "num2 ", "num3 ",
"num4 ", "num5 ", "num6 ", "num7 ")
FOREACHBIT(report_data.keys[12], keypresses,
"num8 ", "num9 ", "num0 ", "num. ", "\\/| ", "app ", "power ", "num= ")
FOREACHBIT(report_data.keys[13], keypresses,
"F13 ", "F14 ", "F15 ", "F16 ", "F17 ", "F18 ", "F19 ", "F20 ")
FOREACHBIT(report_data.keys[14], keypresses,
"F21 ", "F22 ", "F23 ", "F24 ", "exec ", "help ", "menu ", "sel ")
FOREACHBIT(report_data.keys[15], keypresses,
"stop ", "again ", "undo ", "cut ", "copy ", "paste ", "find ", "mute ")
FOREACHBIT(report_data.keys[16], keypresses,
"volup ", "voldn ", "capslock_l ", "numlock_l ",
"scrolllock_l ", "num, ", "num= ", "(other) ")
for (int i = 17; i < KEY_BYTES; i++) {
// A little imprecise, in two ways:
// (1) obviously, "(other)" refers to many distinct keys
// (2) this might undercount the number of "other" keys pressed
// Therefore, if any keys are frequently used, they should be handled above and not via "other"
if (report_data.keys[i]) keypresses << "(other) ";
}
}
log_info("Sent virtual HID report. Pressed keys: %s\n", keypresses.str().c_str());
logUSBEvent_keyboard("Keyboard HID report; pressed keys: " + keypresses.str());
}
} // namespace kaleidoscope
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD

@ -0,0 +1,34 @@
/* Kaleidoscope - Firmware for computer input devices
* Copyright (C) 2013-2019 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/>.
*/
#pragma once
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
#include <stdint.h>
namespace kaleidoscope {
class DefaultHIDReportConsumer {
public:
static void processHIDReport(uint8_t id, const void *data,
int len, int result);
};
} // namespace kaleidoscope
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD

@ -0,0 +1,94 @@
/*
Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
*/
// This is a modified version of the original HID.cpp from
// library KeyboardioHID. It replaces all hardware related stuff
// with stub implementations.
// Include KeyboardioHID's HID.h header
//
#include "HID.h"
#include "HIDReportObserver.h"
#if defined(USBCON)
HID_ &HID() {
static HID_ obj;
return obj;
}
int HID_::getInterface(uint8_t *interfaceCount) {
*interfaceCount += 1; // uses 1
return 0;
}
int HID_::getDescriptor(USBSetup &setup) {
return 1;
}
uint8_t HID_::getShortName(char *name) {
name[0] = 'v';
name[1] = 'i';
name[2] = 'r';
name[3] = 't';
name[4] = 'u';
name[5] = 'a';
name[6] = 'l';
return 7;
}
void HID_::AppendDescriptor(HIDSubDescriptor *node) {
if (!rootNode) {
rootNode = node;
} else {
HIDSubDescriptor *current = rootNode;
while (current->next) {
current = current->next;
}
current->next = node;
}
descriptorSize += node->length;
}
int HID_::SendReport(uint8_t id, const void *data, int len) {
HIDReportObserver::observeReport(id, data, len, 0);
return 1;
}
bool HID_::setup(USBSetup &setup) {
return true;
}
HID_::HID_(void) : PluggableUSBModule(1, 1, epType),
rootNode(NULL), descriptorSize(0),
protocol(HID_REPORT_PROTOCOL), idle(1) {
setReportData.reportId = 0;
setReportData.leds = 0;
epType[0] = EP_TYPE_INTERRUPT_IN;
//PluggableUSB().plug(this);
}
int HID_::begin(void) {
return 0;
}
#endif /* if defined(USBCON) */

@ -0,0 +1,33 @@
/* Kaleidoscope - Firmware for computer input devices
* Copyright (C) 2013-2019 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/>.
*/
#include "Logging.h"
namespace kaleidoscope {
namespace logging {
static bool __verboseOutputEnabled = true;
void toggleVerboseOutput(bool state) {
__verboseOutputEnabled = state;
}
bool verboseOutputEnabled() {
return __verboseOutputEnabled;
}
} // namespace logging
} // namespace kaleidoscope

@ -0,0 +1,96 @@
/* Kaleidoscope - Firmware for computer input devices
* Copyright (C) 2013-2019 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/>.
*/
#pragma once
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
#include "utility"
#include "stdio.h"
namespace kaleidoscope {
namespace logging {
extern void toggleVerboseOutput(bool state);
extern bool verboseOutputEnabled();
// Please note that we prefer stdio based logging against
// stream based output, to stay compatible with possible future global
// logging functions introduced by Kaleidoscope. Stream
// based logging is not available on the target platform due to restricted
// resources.
// Below, we use perfect forwarding to pass printf style log messages
// to different printf derivates. gcc warns when the the format string
// is not a literal, which is not the case here due to our forwarding.
// To silence the related warning, which is not desired in our application,
// we disable the format-security diagnostic until the end of this file.
// Disable diagnostic for literal format strings.
//
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-security"
#ifdef KALEIDOSCOPE_HARDWARE_VIRTUAL_NO_LOGGING
template<typename... Args__>
inline
void log_debug(Args__&&... args) {}
template<typename... Args__>
inline
void log_info(Args__&&... args) {}
#else // #ifdef KALEIDOSCOPE_HARDWARE_VIRTUAL_NO_LOGGING
template<typename... Args__>
inline
void log_debug(Args__&&... args) {
if (verboseOutputEnabled()) {
fprintf(stdout, std::forward<Args__>(args)...);
}
}
template<typename... Args__>
inline
void log_info(Args__&&... args) {
if (verboseOutputEnabled()) {
fprintf(stdout, std::forward<Args__>(args)...);
}
}
#endif // #ifdef KALEIDOSCOPE_HARDWARE_VIRTUAL_NO_LOGGING
template<typename... Args__>
inline
void log_error(Args__&&... args) {
fprintf(stderr, std::forward<Args__>(args)...);
}
template<typename... Args__>
inline
void log_critical(Args__&&... args) {
fprintf(stderr, std::forward<Args__>(args)...);
}
} // namespace logging
} // namespace kaleidoscope
// Re-enable diagnostic for literal format strings.
//
#pragma GCC diagnostic pop
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD

@ -0,0 +1,396 @@
/* -*- mode: c++ -*-
* Kaleidoscope-Hardware-Model01 -- Keyboard.io Model01 hardware support for Kaleidoscope
* Copyright (C) 2017-2019 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/>.
*/
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
#include "kaleidoscope/device/virtual/Virtual.h"
#include "kaleidoscope/device/virtual/DefaultHIDReportConsumer.h"
#include "kaleidoscope/device/virtual/Logging.h"
#include "kaleidoscope/keyswitch_state.h"
#include "Kaleidoscope.h"
#include "HIDReportObserver.h"
#include "virtual_io.h"
#include "EEPROM.h"
#include <sstream>
#include <string>
#include <iomanip>
// FIXME: This relates to virtual/cores/arduino/EEPROM.h.
// EEPROM static data must be defined here as only
// the device knows about the EEPROM size.
//
// It might be better to move the EEPROM.h header here as
// well???
uint8_t EERef::eeprom_[kaleidoscope::DeviceProps::StorageProps::length];
EEPROMClass EEPROM;
uint16_t EEPROMClass::length() {
return kaleidoscope::DeviceProps::StorageProps::length;
}
namespace kaleidoscope {
namespace device {
namespace virt {
using namespace kaleidoscope::logging;
//##############################################################################
// VirtualKeyScanner
//##############################################################################
VirtualKeyScanner::VirtualKeyScanner()
: n_pressed_switches_{0},
n_previously_pressed_switches_{0},
read_matrix_enabled_{true} {
}
void VirtualKeyScanner::setup() {
HIDReportObserver::resetHook(&DefaultHIDReportConsumer::processHIDReport);
for (auto key_addr : KeyAddr::all()) {
keystates_[key_addr.toInt()] = KeyState::NotPressed;
keystates_prev_[key_addr.toInt()] = KeyState::NotPressed;
mask_[key_addr.toInt()] = false;
}
}
enum Mode {
M_TAP,
M_DOWN,
M_UP,
};
// FIXME: getRCfromPhysicalKey only works for the Model01 with default
// layout. We might want to remove this as the virtual hardware
// intents to simulate any type of keyboard.
//
// static KeyAddr getRCfromPhysicalKey(std::string keyname) {
// if (keyname == "prog") return KeyAddr{0, 0};
// else if (keyname == "1") return KeyAddr{0, 1};
// else if (keyname == "2") return KeyAddr{0, 2};
// else if (keyname == "3") return KeyAddr{0, 3};
// else if (keyname == "4") return KeyAddr{0, 4};
// else if (keyname == "5") return KeyAddr{0, 5};
// else if (keyname == "led") return KeyAddr{0, 6};
// else if (keyname == "any") return KeyAddr{0, 9};
// else if (keyname == "6") return KeyAddr{0, 10};
// else if (keyname == "7") return KeyAddr{0, 11};
// else if (keyname == "8") return KeyAddr{0, 12};
// else if (keyname == "9") return KeyAddr{0, 13};
// else if (keyname == "0") return KeyAddr{0, 14};
// else if (keyname == "num") return KeyAddr{0, 15};
// else if (keyname == "`") return KeyAddr{1, 0};
// else if (keyname == "q") return KeyAddr{1, 1};
// else if (keyname == "w") return KeyAddr{1, 2};
// else if (keyname == "e") return KeyAddr{1, 3};
// else if (keyname == "r") return KeyAddr{1, 4};
// else if (keyname == "t") return KeyAddr{1, 5};
// else if (keyname == "tab") return KeyAddr{1, 6};
// else if (keyname == "enter") return KeyAddr{1, 9};
// else if (keyname == "y") return KeyAddr{1, 10};
// else if (keyname == "u") return KeyAddr{1, 11};
// else if (keyname == "i") return KeyAddr{1, 12};
// else if (keyname == "o") return KeyAddr{1, 13};
// else if (keyname == "p") return KeyAddr{1, 14};
// else if (keyname == "=") return KeyAddr{1, 15};
// else if (keyname == "pgup") return KeyAddr{2, 0};
// else if (keyname == "a") return KeyAddr{2, 1};
// else if (keyname == "s") return KeyAddr{2, 2};
// else if (keyname == "d") return KeyAddr{2, 3};
// else if (keyname == "f") return KeyAddr{2, 4};
// else if (keyname == "g") return KeyAddr{2, 5};
// else if (keyname == "h") return KeyAddr{2, 10};
// else if (keyname == "j") return KeyAddr{2, 11};
// else if (keyname == "k") return KeyAddr{2, 12};
// else if (keyname == "l") return KeyAddr{2, 13};
// else if (keyname == ";") return KeyAddr{2, 14};
// else if (keyname == "'") return KeyAddr{2, 15};
// else if (keyname == "pgdn") return KeyAddr{3, 0};
// else if (keyname == "z") return KeyAddr{3, 1};
// else if (keyname == "x") return KeyAddr{3, 2};
// else if (keyname == "c") return KeyAddr{3, 3};
// else if (keyname == "v") return KeyAddr{3, 4};
// else if (keyname == "b") return KeyAddr{3, 5};
// else if (keyname == "esc") return KeyAddr{2, 6}; // yes, row 2
// else if (keyname == "fly") return KeyAddr{2, 9}; // yes, row 2
// else if (keyname == "n") return KeyAddr{3, 10};
// else if (keyname == "m") return KeyAddr{3, 11};
// else if (keyname == ",") return KeyAddr{3, 12};
// else if (keyname == ".") return KeyAddr{3, 13};
// else if (keyname == "/") return KeyAddr{3, 14};
// else if (keyname == "-") return KeyAddr{3, 15};
// else if (keyname == "lctrl") return KeyAddr{0, 7};
// else if (keyname == "bksp") return KeyAddr{1, 7};
// else if (keyname == "cmd") return KeyAddr{2, 7};
// else if (keyname == "lshift") return KeyAddr{3, 7};
// else if (keyname == "rshift") return KeyAddr{3, 8};
// else if (keyname == "alt") return KeyAddr{2, 8};
// else if (keyname == "space") return KeyAddr{1, 8};
// else if (keyname == "rctrl") return KeyAddr{0, 8};
// else if (keyname == "lfn") return KeyAddr{3, 6};
// else if (keyname == "rfn") return KeyAddr{3, 9};
//
// return KeyAddr{}; // Invalid key
// }
void VirtualKeyScanner::readMatrix() {
if (!read_matrix_enabled_) return;
std::stringstream sline;
sline << getLineOfInput(anythingHeld());
Mode mode = M_TAP;
while (true) {
std::string token;
std::getline(sline, token, ' ');
if (token == "") break; // end of line
else if (token == "#") break; // skip the rest of the line
else if ((token == "?" || token == "help") && isInteractive()) {
printHelp();
} else if (token == "Q") {
exit(0);
} else if (token == "T") {
mode = M_TAP;
} else if (token == "D") {
mode = M_DOWN;
} else if (token == "U") {
mode = M_UP;
} else if (token == "C") {
for (auto key_addr : KeyAddr::all()) {
keystates_[key_addr.toInt()] = KeyState::NotPressed;
}
} else {
KeyAddr key_addr;
if (token.front() == '(' && token.back() == ')') {
size_t commapos = token.find_first_of(',');
if (commapos == std::string::npos) {
log_error("Bad (r,c) pair: %s\n", token.c_str());
continue;
} else {
key_addr = KeyAddr(
(uint8_t)std::stoi(token.substr(1, commapos - 1)),
(uint8_t)std::stoi(token.substr(commapos + 1, token.length() - commapos - 1))
);
if (!key_addr.isValid()) {
log_error("Bad coordinates: %s\n", token.c_str());
continue;
}
}
} else {
// TODO: Is there a device independent
// way to determine KeyAddr from key names?
// key_addr = getRCfromPhysicalKey(token);
//
// if (!key_addr.isValid()) {
// log_error("Unrecognized command: %s\n", token.c_str());
// continue;
// }
}
keystates_[key_addr.toInt()] =
(mode == M_DOWN) ? KeyState::Pressed :
(mode == M_UP) ? KeyState::NotPressed :
KeyState::Tap;
}
}
}
void VirtualKeyScanner::actOnMatrixScan() {
n_pressed_switches_ = 0;
n_previously_pressed_switches_ = 0;
for (auto key_addr : KeyAddr::all()) {
uint8_t key_state = 0;
switch (keystates_prev_[key_addr.toInt()]) {
case KeyState::Pressed:
key_state |= WAS_PRESSED;
++n_previously_pressed_switches_;
break;
case KeyState::Tap:
log_error("Error: assertion failed, keystates_prev_ should not be KeyState::Tap\n");
break;
case KeyState::NotPressed:
default:
/* do nothing */
break;
}
switch (keystates_[key_addr.toInt()]) {
case KeyState::Pressed:
case KeyState::Tap:
key_state |= IS_PRESSED;
++n_pressed_switches_;
break;
case KeyState::NotPressed:
default:
/* do nothing */
break;
}
handleKeyswitchEvent(Key_NoKey, key_addr, key_state);
keystates_prev_[key_addr.toInt()] = keystates_[key_addr.toInt()];
if (keystates_[key_addr.toInt()] == KeyState::Tap) {
key_state = WAS_PRESSED & ~IS_PRESSED;
handleKeyswitchEvent(Key_NoKey, key_addr, key_state);
keystates_[key_addr.toInt()] = KeyState::NotPressed;
keystates_prev_[key_addr.toInt()] = KeyState::NotPressed;
}
}
}
uint8_t VirtualKeyScanner::pressedKeyswitchCount() const {
return n_pressed_switches_;
}
bool VirtualKeyScanner::isKeyswitchPressed(KeyAddr key_addr) const {
if (keystates_[key_addr.toInt()] == KeyState::NotPressed) {
return false;
}
return true;
}
uint8_t VirtualKeyScanner::previousPressedKeyswitchCount() const {
return n_previously_pressed_switches_;
}
bool VirtualKeyScanner::wasKeyswitchPressed(KeyAddr key_addr) const {
if (keystates_prev_[key_addr.toInt()] == KeyState::NotPressed) {
return false;
}
return true;
}
void VirtualKeyScanner::maskKey(KeyAddr key_addr) {
if (!key_addr.isValid()) {
log_error("Virtual::maskKey: key_addr invalid\n");
return;
}
mask_[key_addr.toInt()] = true;
}
void VirtualKeyScanner::unMaskKey(KeyAddr key_addr) {
if (!key_addr.isValid()) {
log_error("Virtual::unMaskKey: key_addr invalid\n");
return;
}
mask_[key_addr.toInt()] = false;
}
bool VirtualKeyScanner::isKeyMasked(KeyAddr key_addr) const {
if (!key_addr.isValid()) {
log_error("Virtual::isKeyMasked: key_addr invalid\n");
return false;
}
return mask_[key_addr.toInt()];
}
void VirtualKeyScanner::setKeystate(KeyAddr keyAddr, KeyState ks) {
keystates_[keyAddr.toInt()] = ks;
}
VirtualKeyScanner::KeyState VirtualKeyScanner::getKeystate(KeyAddr keyAddr) const {
return keystates_[keyAddr.toInt()];
}
bool VirtualKeyScanner::anythingHeld() {
for (auto key_addr : KeyAddr::all()) {
if (keystates_[key_addr.toInt()] == KeyState::Pressed) return true;
}
return false;
}
//##############################################################################
// VirtualLEDDriver
//##############################################################################
void VirtualLEDDriver::setup() {
for (int i = 0; i < led_count; i++) {
led_states_[i] = CRGB(0, 0, 0);
}
}
void VirtualLEDDriver::syncLeds() {
// log format: red.green.blue where values are written in hex; followed by a space, followed by the next LED
std::stringstream ss;
ss << std::hex;
for (int i = 0; i < led_count; i++) {
const cRGB state = led_states_[i];
ss << (unsigned int) state.r << "." << (unsigned int) state.g << "." << (unsigned int) state.b << " ";
}
ss << std::endl;
logLEDStates(ss.str());
}
void VirtualLEDDriver::setCrgbAt(uint8_t i, cRGB color) {
if ((int)i >= (int)led_count) {
log_error("Virtual::setCrgbAt: Index %d out of bounds\n", i);
return;
}
led_states_[i] = color;
}
cRGB VirtualLEDDriver::getCrgbAt(uint8_t i) const {
if ((int)i >= (int)led_count) {
log_error("Virtual::getCrgbAt: Index %d out of bounds\n", i);
return CRGB(0, 0, 0);
}
return led_states_[i];
}
uint8_t VirtualLEDDriver::getLedIndex(uint8_t key_offset) const {
return kaleidoscope::DeviceProps::LEDDriverProps::getLedIndex(key_offset);
}
} // namespace virt
} // namespace device
namespace driver {
namespace led {
template<>
Base<kaleidoscope::DeviceProps::LEDDriverProps>::LEDs
Base<kaleidoscope::DeviceProps::LEDDriverProps>::LEDs_{};
} // namespace led
} // namespace driver
} // namespace kaleidoscope
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD

@ -0,0 +1,160 @@
/* -*- mode: c++ -*-
* Kaleidoscope-Hardware-Model01 -- Keyboard.io Model01 hardware support for Kaleidoscope
* Copyright (C) 2017-2019 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/>.
*/
#pragma once
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
#include KALEIDOSCOPE_HARDWARE_H
#include "kaleidoscope/driver/bootloader/None.h"
#include "kaleidoscope/driver/led/Base.h"
namespace kaleidoscope {
namespace device {
namespace virt {
class VirtualKeyScanner
: public kaleidoscope::driver::keyscanner::Base<kaleidoscope::DeviceProps::KeyScannerProps> {
private:
typedef VirtualKeyScanner ThisType;
typedef kaleidoscope::driver::keyscanner::Base<kaleidoscope::DeviceProps::KeyScannerProps> ParentType;
public:
typedef typename ParentType::KeyAddr KeyAddr;
enum class KeyState {
Pressed,
NotPressed,
Tap
};
static constexpr uint8_t matrix_rows = kaleidoscope::DeviceProps::KeyScannerProps::matrix_rows;
static constexpr uint8_t matrix_columns = kaleidoscope::DeviceProps::KeyScannerProps::matrix_columns;
VirtualKeyScanner();
void setup();
void readMatrix();
void scanMatrix() {
this->readMatrix();
this->actOnMatrixScan();
}
void actOnMatrixScan();
uint8_t pressedKeyswitchCount() const;
bool isKeyswitchPressed(KeyAddr key_addr) const;
uint8_t previousPressedKeyswitchCount() const;
bool wasKeyswitchPressed(KeyAddr key_addr) const;
void maskKey(KeyAddr key_addr);
void unMaskKey(KeyAddr key_addr);
bool isKeyMasked(KeyAddr key_addr) const;
void setEnableReadMatrix(bool state) {
read_matrix_enabled_ = state;
}
void setKeystate(KeyAddr keyAddr, KeyState ks);
KeyState getKeystate(KeyAddr keyAddr) const;
private:
bool anythingHeld();
private:
uint8_t n_pressed_switches_,
n_previously_pressed_switches_;
bool read_matrix_enabled_;
KeyState keystates_[matrix_rows * matrix_columns];
KeyState keystates_prev_[matrix_rows * matrix_columns];
bool mask_[matrix_rows * matrix_columns];
};
class VirtualLEDDriver
: public driver::led::Base<kaleidoscope::DeviceProps::LEDDriverProps> {
public:
typedef driver::led::Base<kaleidoscope::DeviceProps::LEDDriverProps>
ParentType;
using typename ParentType::LEDs;
static constexpr uint8_t led_count = kaleidoscope::DeviceProps::LEDDriverProps::led_count;
void setup();
void syncLeds();
void setCrgbAt(uint8_t i, cRGB color);
cRGB getCrgbAt(uint8_t i) const;
uint8_t getLedIndex(uint8_t key_offset) const;
private:
cRGB led_states_[led_count];
};
// This overrides only the drivers and keeps the driver props of
// the physical keyboard.
//
struct VirtualProps : public kaleidoscope::DeviceProps {
typedef typename kaleidoscope::DeviceProps::KeyScannerProps
KeyScannerProps;
typedef VirtualKeyScanner
KeyScanner;
typedef KeyScannerProps::KeyAddr
KeyAddr;
typedef typename kaleidoscope::DeviceProps::LEDDriverProps
LEDDriverProps;
typedef VirtualLEDDriver
LEDDriver;
typedef kaleidoscope::driver::mcu::None MCU;
typedef kaleidoscope::driver::bootloader::None
BootLoader;
typedef typename kaleidoscope::DeviceProps::StorageProps
StorageProps;
typedef typename kaleidoscope::DeviceProps::Storage
Storage;
};
class VirtualDevice
: public kaleidoscope::device::Base<device::virt::VirtualProps> {
public:
auto serialPort() -> decltype(Serial) & {
return Serial;
}
};
} // namespace virt
} // namespace device
typedef device::virt::VirtualDevice Device;
} // namespace kaleidoscope
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD
Loading…
Cancel
Save