The new device APIs were built on top of composition (instead of inheritance, like the former one). At the highest level, we have `kaleidoscope::device::Base` and `kaleidoscope::device::BaseProps`. The latter is a set of overrideable properties, components that make up the device: the key scanner, LEDs, MCU, and so on. Many components - like the key scanner and LEDs - also come in a similar setup: the base class and properties, because this allows us to make them fairly efficient templates. All of the existing devices have been ported to the new APIs. While the old `Hardware` base class remains - for now, and deprecated - it is not guaranteed to work. Signed-off-by: Gergely Nagy <algernon@keyboard.io>pull/695/head
parent
cfeff8f2cf
commit
d39a8dc46c
@ -0,0 +1,58 @@
|
|||||||
|
# kaleidoscope::driver::bootloader
|
||||||
|
|
||||||
|
We rarely have to work with or care about the bootloader from the user firmware,
|
||||||
|
but there's one scenario when we do: if we want to reset the device, and put it
|
||||||
|
into bootloader (programmable) mode, we need to do that in a bootloader-specific
|
||||||
|
manner.
|
||||||
|
|
||||||
|
This driver provides a number of helpers that implement the reset functionality
|
||||||
|
for various bootloaders.
|
||||||
|
|
||||||
|
## Using the driver
|
||||||
|
|
||||||
|
To use the driver, we need to include the appropriate header, from the hardware plugin of
|
||||||
|
our keyboard:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include <kaleidoscope/driver/bootloader/avr/Caterina.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, we set up the device `Properties` so that it includes the override for our
|
||||||
|
bootloader:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct OurBoardProps : kaleidoscope::device::BaseProps {
|
||||||
|
typedef kaleidoscope::driver::bootloader::avr::Caterina Bootloader;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The base classes will do all the rest.
|
||||||
|
|
||||||
|
## Methods provided by all bootloader drivers
|
||||||
|
|
||||||
|
### `.rebootBootloader()`
|
||||||
|
|
||||||
|
> Resets the device, and forces it into bootloader (programmable) mode.
|
||||||
|
|
||||||
|
## List of bootloaders
|
||||||
|
|
||||||
|
All of the drivers below live below the `kaleidoscope::driver::bootloader`
|
||||||
|
namespace.
|
||||||
|
|
||||||
|
## `avr::Caterina`:
|
||||||
|
|
||||||
|
Used by many (most?) arduino MCUs. Provided by
|
||||||
|
`kaleidoscope/driver/bootloader/avr/Caterina.h`.
|
||||||
|
|
||||||
|
### `avr::HalfKay`
|
||||||
|
|
||||||
|
Used by the Teensy2. Provided by `kaleidoscope/driver/bootloader/avr/HalfKay.h`.
|
||||||
|
|
||||||
|
### `avr::FLIP`
|
||||||
|
|
||||||
|
Used by the ATMega32U4 MCUs by default, unless another bootloader has been
|
||||||
|
flashed on them. Provided by `kaleidoscope/driver/bootloader/avr/FLIP.h`.
|
||||||
|
|
||||||
|
For this driver to work, one also needs to define the
|
||||||
|
`KALEIDOSCOPE_BOOTLOADER_FLIP_WORKAROUND` macro before including the driver
|
||||||
|
header, for technical reasons.
|
@ -1,82 +0,0 @@
|
|||||||
# ATMegaKeyboard
|
|
||||||
|
|
||||||
A lot of custom keyboards are built upon the ATMega MCU (most often an
|
|
||||||
`atmega32u4`), and the vast majority of them follow a similar architecture, so
|
|
||||||
much so that the vast majority of code can be lifted out into a base class,
|
|
||||||
making porting to these keyboards trivial. All we have to do is tell it our
|
|
||||||
pinout, and we're all done.
|
|
||||||
|
|
||||||
## Porting hardware using the ATMegaKeyboard class
|
|
||||||
|
|
||||||
The plugin assumes a simple matrix layout, which we can tell it by using the
|
|
||||||
`ATMEGA_KEYBOARD_CONFIG` macro, which takes two arguments: a list of row and
|
|
||||||
column pins. In the `.cpp`, simply use `ATMEGA_KEYBOARD_DATA`, with the hardware
|
|
||||||
object as its argument:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
// Kaleidoscope-Vendor-ExampleHardware.h
|
|
||||||
#define KALEIDOSCOPE_WITH_ATMEGA_KEYBOARD 1
|
|
||||||
#include "kaleidoscope/hardware/vendor/ExampleHardware.h"
|
|
||||||
|
|
||||||
// kaleidoscope/hardware/vendor/ExampleHardware.h
|
|
||||||
namespace kaleidoscope {
|
|
||||||
namespace hardware {
|
|
||||||
namespace vendor {
|
|
||||||
class ExampleKeyboard: public ATMegaKeyboard {
|
|
||||||
public:
|
|
||||||
ExampleKeyboard() {}
|
|
||||||
|
|
||||||
ATMEGA_KEYBOARD_CONFIG(
|
|
||||||
ROW_PIN_LIST({PIN_D1, PIN_D2}),
|
|
||||||
COL_PIN_LIST({PIN_F6, PIN_F7})
|
|
||||||
);
|
|
||||||
|
|
||||||
static constexpr int8_t led_count = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define KEYMAP( \
|
|
||||||
r0c0 ,r0c1 \
|
|
||||||
,r1c0 ,r1c1 \
|
|
||||||
) \
|
|
||||||
{ r0c0 ,r0c1 }, \
|
|
||||||
{ r1c0 ,r1c1 }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// kaleidoscope/hardware/vendor/ExampleHardware.cpp
|
|
||||||
namespace kaleidoscope {
|
|
||||||
namespace hardware {
|
|
||||||
namespace vendor {
|
|
||||||
|
|
||||||
ATMEGA_KEYBOARD_DATA(ExampleHardware);
|
|
||||||
constexpr int8_t ExampleHardware::led_count;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HARDWARE_IMPLEMENTATION KeyboardHardware;
|
|
||||||
kaleidoscope::hardware::vendor::ExampleHardware &ExampleHardware = KeyboardHardware;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Overriding methods
|
|
||||||
|
|
||||||
For performance and space-saving reasons, the base class does not use virtual
|
|
||||||
methods. Instead, whenever it calls a method of its own, it will call it through
|
|
||||||
the `KeyboardHardware` singleton object, which is always an instance of the
|
|
||||||
exact hardware plugin. Thus, implementing a function in the subclass will shadow
|
|
||||||
the one in the base class.
|
|
||||||
|
|
||||||
This can be used to implement more efficient methods, would it be needed. The
|
|
||||||
[Atreus][hardware:atreus] port does this, for example, by overriding the generic
|
|
||||||
`readCols` with a more specialised, faster implementation.
|
|
||||||
|
|
||||||
## Further reading
|
|
||||||
|
|
||||||
See the [Planck][hardware:planck] and [Atreus][hardware:atreus] ports for an
|
|
||||||
example of how this class can be used in practice.
|
|
||||||
|
|
||||||
[hardware:planck]: ../../src/kaleidoscope/hardware/olkb/Planck.h
|
|
||||||
[hardware:atreus]: ../../src/kaleidoscope/hardware/technomancy/Atreus.h
|
|
@ -0,0 +1,59 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* device::ATMega32U4Keyboard -- Generic ATMega32U4 keyboard base class
|
||||||
|
* Copyright (C) 2019 Keyboard.io, Inc
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 3 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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 __AVR__
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "kaleidoscope/device/Base.h"
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/mcu/ATMega32U4.h"
|
||||||
|
#include "kaleidoscope/driver/storage/ATMega32U4EEPROMProps.h"
|
||||||
|
#include "kaleidoscope/driver/storage/AVREEPROM.h"
|
||||||
|
|
||||||
|
#define ATMEGA32U4_KEYBOARD(BOARD_, BOOTLOADER_, ROW_PINS_, COL_PINS_) \
|
||||||
|
struct BOARD_##Props : kaleidoscope::device::ATMega32U4KeyboardProps { \
|
||||||
|
struct KeyScannerProps : public kaleidoscope::driver::keyscanner::AVRProps { \
|
||||||
|
AVR_KEYSCANNER_PROPS(ROW_PIN_LIST(ROW_PINS_), COL_PIN_LIST(COL_PINS_)); \
|
||||||
|
}; \
|
||||||
|
typedef kaleidoscope::driver::keyscanner::AVR<KeyScannerProps> KeyScanner; \
|
||||||
|
typedef kaleidoscope::driver::bootloader::avr::BOOTLOADER_ BootLoader; \
|
||||||
|
}; \
|
||||||
|
class BOARD_: public kaleidoscope::device::ATMega32U4Keyboard<BOARD_##Props> {};
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace device {
|
||||||
|
|
||||||
|
struct ATMega32U4KeyboardProps : kaleidoscope::device::BaseProps {
|
||||||
|
typedef kaleidoscope::driver::mcu::ATMega32U4 MCU;
|
||||||
|
typedef kaleidoscope::driver::storage::ATMega32U4EEPROMProps StorageProps;
|
||||||
|
typedef kaleidoscope::driver::storage::AVREEPROM<StorageProps> Storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _DeviceProps>
|
||||||
|
class ATMega32U4Keyboard : public kaleidoscope::device::Base<_DeviceProps> {
|
||||||
|
public:
|
||||||
|
auto serialPort() -> decltype(Serial) & {
|
||||||
|
return Serial;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,150 +0,0 @@
|
|||||||
/* -*- mode: c++ -*-
|
|
||||||
* Kaleidoscope-Hardware-ATMegaKeyboard -- Base class for some ATMega-based boards
|
|
||||||
* Copyright (C) 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Kaleidoscope.h"
|
|
||||||
|
|
||||||
#if KALEIDOSCOPE_WITH_ATMEGA_KEYBOARD
|
|
||||||
|
|
||||||
#include "kaleidoscope/device/ATMegaKeyboard.h"
|
|
||||||
|
|
||||||
namespace kaleidoscope {
|
|
||||||
namespace device {
|
|
||||||
|
|
||||||
uint8_t ATMegaKeyboard::debounce = 3;
|
|
||||||
|
|
||||||
void ATMegaKeyboard::setup(void) {
|
|
||||||
wdt_disable();
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < Kaleidoscope.device().matrix_columns; i++) {
|
|
||||||
DDR_INPUT(Kaleidoscope.device().matrix_col_pins[i]);
|
|
||||||
ENABLE_PULLUP(Kaleidoscope.device().matrix_col_pins[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < Kaleidoscope.device().matrix_rows; i++) {
|
|
||||||
DDR_OUTPUT(Kaleidoscope.device().matrix_row_pins[i]);
|
|
||||||
OUTPUT_HIGH(Kaleidoscope.device().matrix_row_pins[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up Timer1 for 1700usec */
|
|
||||||
TCCR1B = _BV(WGM13);
|
|
||||||
TCCR1A = 0;
|
|
||||||
|
|
||||||
const uint32_t cycles = (F_CPU / 2000000) * 1700;
|
|
||||||
|
|
||||||
ICR1 = cycles;
|
|
||||||
TCCR1B = _BV(WGM13) | _BV(CS10);
|
|
||||||
TIMSK1 = _BV(TOIE1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((optimize(3))) ATMegaKeyboard::readMatrix(void) {
|
|
||||||
for (uint8_t current_row = 0; current_row < Kaleidoscope.device().matrix_rows; current_row++) {
|
|
||||||
uint16_t mask, cols;
|
|
||||||
|
|
||||||
mask = Kaleidoscope.device().debounceMaskForRow(current_row);
|
|
||||||
|
|
||||||
OUTPUT_TOGGLE(Kaleidoscope.device().matrix_row_pins[current_row]);
|
|
||||||
cols = (Kaleidoscope.device().readCols() & mask) | (Kaleidoscope.device().keyState_[current_row] & ~mask);
|
|
||||||
OUTPUT_TOGGLE(Kaleidoscope.device().matrix_row_pins[current_row]);
|
|
||||||
Kaleidoscope.device().debounceRow(cols ^ Kaleidoscope.device().keyState_[current_row], current_row);
|
|
||||||
Kaleidoscope.device().keyState_[current_row] = cols;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ATMegaKeyboard::pressedKeyswitchCount() {
|
|
||||||
uint8_t count = 0;
|
|
||||||
|
|
||||||
for (int8_t r = 0; r < Kaleidoscope.device().matrix_rows; r++) {
|
|
||||||
count += __builtin_popcount(Kaleidoscope.device().keyState_[r]);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ATMegaKeyboard::previousPressedKeyswitchCount() {
|
|
||||||
uint8_t count = 0;
|
|
||||||
|
|
||||||
for (int8_t r = 0; r < Kaleidoscope.device().matrix_rows; r++) {
|
|
||||||
count += __builtin_popcount(Kaleidoscope.device().previousKeyState_[r]);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((optimize(3))) ATMegaKeyboard::actOnMatrixScan() {
|
|
||||||
for (byte row = 0; row < Kaleidoscope.device().matrix_rows; row++) {
|
|
||||||
for (byte col = 0; col < Kaleidoscope.device().matrix_columns; col++) {
|
|
||||||
uint8_t keyState = (bitRead(Kaleidoscope.device().previousKeyState_[row], col) << 0) |
|
|
||||||
(bitRead(Kaleidoscope.device().keyState_[row], col) << 1);
|
|
||||||
if (keyState) {
|
|
||||||
handleKeyswitchEvent(Key_NoKey, ::KeyAddr(row, col), keyState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Kaleidoscope.device().previousKeyState_[row] = Kaleidoscope.device().keyState_[row];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ATMegaKeyboard::scanMatrix() {
|
|
||||||
// We ALWAYS want to tell Kaleidoscope about the state of the matrix
|
|
||||||
Kaleidoscope.device().actOnMatrixScan();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function has loop unrolling disabled on purpose: we want to give the
|
|
||||||
* hardware enough time to produce stable PIN reads for us. If we unroll the
|
|
||||||
* loop, we will not have that, because even with the NOP, the codepath is too
|
|
||||||
* fast. If we don't have stable reads, then entire rows or columns will behave
|
|
||||||
* erratically.
|
|
||||||
*
|
|
||||||
* For this reason, we ask the compiler to not unroll our loop, which in turn,
|
|
||||||
* gives hardware enough time to produce stable reads, at the cost of a little
|
|
||||||
* bit of speed.
|
|
||||||
*
|
|
||||||
* Do not remove the attribute!
|
|
||||||
*/
|
|
||||||
__attribute__((optimize("no-unroll-loops")))
|
|
||||||
uint16_t ATMegaKeyboard::readCols() {
|
|
||||||
uint16_t results = 0x00 ;
|
|
||||||
for (uint8_t i = 0; i < Kaleidoscope.device().matrix_columns; i++) {
|
|
||||||
asm("NOP"); // We need to pause a beat before reading or we may read before the pin is hot
|
|
||||||
results |= (!READ_PIN(Kaleidoscope.device().matrix_col_pins[i]) << i);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ATMegaKeyboard::debounceMaskForRow(uint8_t row) {
|
|
||||||
uint16_t result = 0;
|
|
||||||
|
|
||||||
for (uint16_t c = 0; c < Kaleidoscope.device().matrix_columns; ++c) {
|
|
||||||
if (Kaleidoscope.device().debounce_matrix_[row][c]) {
|
|
||||||
--Kaleidoscope.device().debounce_matrix_[row][c];
|
|
||||||
} else {
|
|
||||||
result |= _BV(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ATMegaKeyboard::debounceRow(uint16_t change, uint8_t row) {
|
|
||||||
for (uint16_t i = 0; i < Kaleidoscope.device().matrix_columns; ++i) {
|
|
||||||
if (change & _BV(i)) {
|
|
||||||
Kaleidoscope.device().debounce_matrix_[row][i] = debounce;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,166 +0,0 @@
|
|||||||
/* -*- mode: c++ -*-
|
|
||||||
* Kaleidoscope-Hardware-ATMegaKeyboard -- Base class for some ATMega-based boards
|
|
||||||
* Copyright (C) 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if KALEIDOSCOPE_WITH_ATMEGA_KEYBOARD
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <KeyboardioHID.h>
|
|
||||||
#include "Kaleidoscope-HIDAdaptor-KeyboardioHID.h"
|
|
||||||
#include "kaleidoscope/MatrixAddr.h"
|
|
||||||
|
|
||||||
#include "kaleidoscope/macro_helpers.h"
|
|
||||||
#include "kaleidoscope/device/avr/pins_and_ports.h"
|
|
||||||
|
|
||||||
#include <avr/wdt.h>
|
|
||||||
|
|
||||||
#ifndef CRGB
|
|
||||||
|
|
||||||
struct cRGB {
|
|
||||||
uint8_t r, g, b;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CRGB(r,g,b) (cRGB){b, g, r}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "kaleidoscope/Hardware.h"
|
|
||||||
#include "kaleidoscope/driver/MCU.h"
|
|
||||||
|
|
||||||
#define ROW_PIN_LIST(...) __VA_ARGS__
|
|
||||||
#define COL_PIN_LIST(...) __VA_ARGS__
|
|
||||||
|
|
||||||
// By implementing all KeyAddr based access methods via macros in
|
|
||||||
// the derived hardware classes, we deal with the problem that
|
|
||||||
// keyboard matrix dimension (matrix_rows/matrix_columns)
|
|
||||||
// and thus type KeyAddr is only known to the derived hardware classes
|
|
||||||
// but not to ATMegaKeyboard.
|
|
||||||
//
|
|
||||||
#define ATMEGA_KEYBOARD_MATRIX_ACCESS_METHODS \
|
|
||||||
bool isKeyswitchPressed(KeyAddr key_addr) { \
|
|
||||||
return (bitRead(keyState_[key_addr.row()], \
|
|
||||||
key_addr.col()) != 0); \
|
|
||||||
} \
|
|
||||||
DEPRECATED(ROW_COL_FUNC) bool isKeyswitchPressed(uint8_t row, byte col)\
|
|
||||||
{ \
|
|
||||||
return isKeyswitchPressed(KeyAddr(row, col)); \
|
|
||||||
} \
|
|
||||||
bool isKeyswitchPressed(uint8_t keyIndex) { \
|
|
||||||
keyIndex--; \
|
|
||||||
return isKeyswitchPressed(KeyAddr(keyIndex)); \
|
|
||||||
} \
|
|
||||||
bool wasKeyswitchPressed(KeyAddr key_addr) { \
|
|
||||||
return (bitRead(previousKeyState_[key_addr.row()], \
|
|
||||||
key_addr.col()) != 0); \
|
|
||||||
} \
|
|
||||||
DEPRECATED(ROW_COL_FUNC) bool wasKeyswitchPressed(uint8_t row, byte col)\
|
|
||||||
{ \
|
|
||||||
return wasKeyswitchPressed(KeyAddr(row, col)); \
|
|
||||||
} \
|
|
||||||
bool wasKeyswitchPressed(uint8_t keyIndex) { \
|
|
||||||
keyIndex--; \
|
|
||||||
return wasKeyswitchPressed(KeyAddr(keyIndex)); \
|
|
||||||
} \
|
|
||||||
void maskKey(KeyAddr key_addr) { \
|
|
||||||
if (!key_addr.isValid()) \
|
|
||||||
return; \
|
|
||||||
\
|
|
||||||
bitWrite(masks_[key_addr.row()], key_addr.col(), 1); \
|
|
||||||
} \
|
|
||||||
DEPRECATED(ROW_COL_FUNC) void maskKey(byte row, byte col) { \
|
|
||||||
maskKey(KeyAddr(row, col)); \
|
|
||||||
} \
|
|
||||||
void unMaskKey(KeyAddr key_addr) { \
|
|
||||||
if (!key_addr.isValid()) \
|
|
||||||
return; \
|
|
||||||
\
|
|
||||||
bitWrite(masks_[key_addr.row()], key_addr.col(), 0); \
|
|
||||||
} \
|
|
||||||
DEPRECATED(ROW_COL_FUNC) void unMaskKey(byte row, byte col) { \
|
|
||||||
unMaskKey(KeyAddr(row, col)); \
|
|
||||||
} \
|
|
||||||
bool isKeyMasked(KeyAddr key_addr) { \
|
|
||||||
if (!key_addr.isValid()) \
|
|
||||||
return false; \
|
|
||||||
\
|
|
||||||
return bitRead(masks_[key_addr.row()], \
|
|
||||||
key_addr.col()); \
|
|
||||||
} \
|
|
||||||
DEPRECATED(ROW_COL_FUNC) bool isKeyMasked(byte row, byte col) { \
|
|
||||||
return isKeyMasked(KeyAddr(row, col)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ATMEGA_KEYBOARD_CONFIG(ROW_PINS_, COL_PINS_) \
|
|
||||||
static const int8_t matrix_rows = NUM_ARGS(ROW_PINS_); \
|
|
||||||
static const int8_t matrix_columns = NUM_ARGS(COL_PINS_); \
|
|
||||||
static constexpr uint8_t matrix_row_pins[matrix_rows] = ROW_PINS_; \
|
|
||||||
static constexpr uint8_t matrix_col_pins[matrix_columns] = COL_PINS_; \
|
|
||||||
typedef MatrixAddr<NUM_ARGS(ROW_PINS_), NUM_ARGS(COL_PINS_)> KeyAddr; \
|
|
||||||
\
|
|
||||||
static uint16_t previousKeyState_[matrix_rows]; \
|
|
||||||
static volatile uint16_t keyState_[matrix_rows]; \
|
|
||||||
static uint16_t masks_[matrix_rows]; \
|
|
||||||
static volatile uint8_t debounce_matrix_[matrix_rows][matrix_columns]; \
|
|
||||||
\
|
|
||||||
ATMEGA_KEYBOARD_MATRIX_ACCESS_METHODS
|
|
||||||
|
|
||||||
#define ATMEGA_KEYBOARD_DATA(BOARD) \
|
|
||||||
const int8_t BOARD::matrix_rows; \
|
|
||||||
const int8_t BOARD::matrix_columns; \
|
|
||||||
constexpr uint8_t BOARD::matrix_row_pins[matrix_rows]; \
|
|
||||||
constexpr uint8_t BOARD::matrix_col_pins[matrix_columns]; \
|
|
||||||
uint16_t BOARD::previousKeyState_[matrix_rows]; \
|
|
||||||
volatile uint16_t BOARD::keyState_[matrix_rows]; \
|
|
||||||
uint16_t BOARD::masks_[matrix_rows]; \
|
|
||||||
volatile uint8_t BOARD::debounce_matrix_[matrix_rows][matrix_columns]; \
|
|
||||||
\
|
|
||||||
ISR(TIMER1_OVF_vect) { \
|
|
||||||
Kaleidoscope.device().readMatrix(); \
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace kaleidoscope {
|
|
||||||
namespace device {
|
|
||||||
class ATMegaKeyboard : public kaleidoscope::Hardware {
|
|
||||||
public:
|
|
||||||
ATMegaKeyboard(void) {}
|
|
||||||
|
|
||||||
static uint8_t debounce;
|
|
||||||
|
|
||||||
void setup(void);
|
|
||||||
void readMatrix(void);
|
|
||||||
void actOnMatrixScan();
|
|
||||||
void scanMatrix();
|
|
||||||
|
|
||||||
uint8_t pressedKeyswitchCount();
|
|
||||||
|
|
||||||
uint8_t previousPressedKeyswitchCount();
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
kaleidoscope::driver::mcu::ATMega32U4 mcu_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
uint16_t readCols();
|
|
||||||
uint16_t debounceMaskForRow(uint8_t row);
|
|
||||||
void debounceRow(uint16_t change, uint8_t row);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -0,0 +1,504 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::device::Base -- Kaleidoscope device Base class
|
||||||
|
* Copyright (C) 2017, 2018, 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file kaleidoscope/device/Base.h
|
||||||
|
* Base class for Kaleidoscope device libraries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "kaleidoscope/MatrixAddr.h"
|
||||||
|
#include "kaleidoscope_internal/deprecations.h"
|
||||||
|
#include "kaleidoscope/macro_helpers.h"
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/keyscanner/None.h"
|
||||||
|
#include "kaleidoscope/driver/led/None.h"
|
||||||
|
#include "kaleidoscope/driver/mcu/None.h"
|
||||||
|
#include "kaleidoscope/driver/bootloader/None.h"
|
||||||
|
#include "kaleidoscope/driver/storage/None.h"
|
||||||
|
|
||||||
|
#ifndef CRGB
|
||||||
|
#error cRGB and CRGB *must* be defined before including this header!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* All hardware libraries must define the following types and macros:
|
||||||
|
* kaleidoscope::Device - a typedef to your device's class.
|
||||||
|
* CRGB(r,g,b) - explained below
|
||||||
|
* cRGB, a structure with 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace device {
|
||||||
|
|
||||||
|
struct BaseProps {
|
||||||
|
typedef kaleidoscope::driver::keyscanner::BaseProps KeyScannerProps;
|
||||||
|
typedef kaleidoscope::driver::keyscanner::None KeyScanner;
|
||||||
|
typedef kaleidoscope::driver::led::BaseProps LEDDriverProps;
|
||||||
|
typedef kaleidoscope::driver::led::None LEDDriver;
|
||||||
|
typedef kaleidoscope::driver::mcu::None MCU;
|
||||||
|
typedef kaleidoscope::driver::bootloader::None Bootloader;
|
||||||
|
typedef kaleidoscope::driver::storage::BaseProps StorageProps;
|
||||||
|
typedef kaleidoscope::driver::storage::None Storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename _DeviceProps>
|
||||||
|
class Base {
|
||||||
|
private:
|
||||||
|
class NoOpSerial {
|
||||||
|
public:
|
||||||
|
NoOpSerial() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static NoOpSerial noop_serial_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Base() {}
|
||||||
|
|
||||||
|
typedef _DeviceProps Props;
|
||||||
|
|
||||||
|
typedef typename _DeviceProps::KeyScanner KeyScanner;
|
||||||
|
typedef typename _DeviceProps::KeyScannerProps KeyScannerProps;
|
||||||
|
typedef typename _DeviceProps::KeyScannerProps::KeyAddr KeyAddr;
|
||||||
|
typedef typename _DeviceProps::LEDDriverProps LEDDriverProps;
|
||||||
|
typedef typename _DeviceProps::LEDDriver LEDDriver;
|
||||||
|
typedef typename _DeviceProps::MCU MCU;
|
||||||
|
typedef typename _DeviceProps::Bootloader Bootloader;
|
||||||
|
typedef typename _DeviceProps::StorageProps StorageProps;
|
||||||
|
typedef typename _DeviceProps::Storage Storage;
|
||||||
|
|
||||||
|
static constexpr uint8_t matrix_rows = KeyScannerProps::matrix_rows;
|
||||||
|
static constexpr uint8_t matrix_columns = KeyScannerProps::matrix_columns;
|
||||||
|
static constexpr uint8_t led_count = LEDDriverProps::led_count;
|
||||||
|
static constexpr typename LEDDriver::LEDs &LEDs() {
|
||||||
|
return LEDDriver::LEDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the number of keys on the keyboard.
|
||||||
|
*/
|
||||||
|
static constexpr int8_t numKeys() {
|
||||||
|
return matrix_columns * matrix_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the storage driver used by the keyboard.
|
||||||
|
*/
|
||||||
|
Storage &storage() {
|
||||||
|
return storage_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the serial port driver used by the keyboard.
|
||||||
|
*/
|
||||||
|
NoOpSerial &serialPort() {
|
||||||
|
return noop_serial_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
led_driver_.syncLeds();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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 key_addr is the matrix address of the LED.
|
||||||
|
* @param color is the color to set the LED to.
|
||||||
|
*/
|
||||||
|
void setCrgbAt(KeyAddr key_addr, cRGB color) {
|
||||||
|
setCrgbAt(getLedIndex(key_addr), color);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
DEPRECATED(ROW_COL_FUNC) void setCrgbAt(byte row, byte col, cRGB color) {
|
||||||
|
setCrgbAt(KeyAddr(row, col), 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) {
|
||||||
|
led_driver_.setCrgbAt(i, 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) {
|
||||||
|
return led_driver_.getCrgbAt(i);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the color of the LED at a given index.
|
||||||
|
*
|
||||||
|
* @param key_addr is the key address of the LED to return the color of.
|
||||||
|
*
|
||||||
|
* @returns The color at the given position.
|
||||||
|
*/
|
||||||
|
cRGB getCrgbAt(KeyAddr key_addr) {
|
||||||
|
return getCrgbAt(getLedIndex(key_addr));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the index of the LED at a given row & column.
|
||||||
|
*
|
||||||
|
* @param key_addr is the matrix address of the LED.
|
||||||
|
*
|
||||||
|
* @returns The index of the LED at the given position, or -1 if there are no
|
||||||
|
* LEDs there.
|
||||||
|
*/
|
||||||
|
int8_t getLedIndex(KeyAddr key_addr) {
|
||||||
|
return led_driver_.getLedIndex(key_addr.toInt());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
DEPRECATED(ROW_COL_FUNC) int8_t getLedIndex(uint8_t row, byte col) {
|
||||||
|
return led_driver_.getLedIndex(KeyAddr(row, col));
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** @defgroup kaleidoscope_hardware_matrix Kaleidoscope::Hardware/Matrix
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Scan the keyboard matrix, and act on it.
|
||||||
|
*/
|
||||||
|
void scanMatrix(void) {
|
||||||
|
key_scanner_.scanMatrix();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
key_scanner_.readMatrix();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Act on the scanned keyboard matrix.
|
||||||
|
*
|
||||||
|
* Iterate through the scanned state (@see readMatrix), and act on any events.
|
||||||
|
*/
|
||||||
|
void actOnMatrixScan(void) {
|
||||||
|
key_scanner_.actOnMatrixScan();
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** @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 key_addr is the matrix address of the key.
|
||||||
|
*/
|
||||||
|
void maskKey(KeyAddr key_addr) {
|
||||||
|
key_scanner_.maskKey(key_addr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
DEPRECATED(ROW_COL_FUNC) void maskKey(byte row, byte col) {
|
||||||
|
key_scanner_.maskKey(KeyAddr(row, 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 key_addr is the matrix address of the key.
|
||||||
|
*/
|
||||||
|
void unMaskKey(KeyAddr key_addr) {
|
||||||
|
key_scanner_.unMaskKey(key_addr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
DEPRECATED(ROW_COL_FUNC) void unMaskKey(byte row, byte col) {
|
||||||
|
key_scanner_.unMaskKey(KeyAddr(row, col));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check whether a key is masked or not.
|
||||||
|
*
|
||||||
|
* @param key_addr is the matrix address of the key.
|
||||||
|
*
|
||||||
|
* @returns true if the key is masked, false otherwise.
|
||||||
|
*/
|
||||||
|
bool isKeyMasked(KeyAddr key_addr) {
|
||||||
|
return key_scanner_.isKeyMasked(key_addr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
DEPRECATED(ROW_COL_FUNC) bool isKeyMasked(byte row, byte col) {
|
||||||
|
return key_scanner_.isKeyMasked(KeyAddr(row, col));
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** @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 them directly.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 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() {
|
||||||
|
mcu_.detachFromHost();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Attack the device to the host.
|
||||||
|
*
|
||||||
|
* Must restore the link detachFromHost severed.
|
||||||
|
*/
|
||||||
|
void attachToHost() {
|
||||||
|
mcu_.attachToHost();
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 key_addr is the matrix address of the key.
|
||||||
|
*
|
||||||
|
* @returns true if the key is pressed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool isKeyswitchPressed(KeyAddr key_addr) {
|
||||||
|
return key_scanner_.isKeyswitchPressed(key_addr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
DEPRECATED(ROW_COL_FUNC) bool isKeyswitchPressed(byte row, byte col) {
|
||||||
|
return key_scanner_.isKeyswitchPressed(KeyAddr(row, 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) {
|
||||||
|
return key_scanner_.isKeyswitchPressed(KeyAddr(--keyIndex));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check the number of key switches currently pressed.
|
||||||
|
*
|
||||||
|
* @returns the number of keys pressed.
|
||||||
|
*/
|
||||||
|
uint8_t pressedKeyswitchCount() {
|
||||||
|
return key_scanner_.pressedKeyswitchCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a key was pressed at a given position on the previous scan
|
||||||
|
*
|
||||||
|
* @param key_addr is the matrix address of the key.
|
||||||
|
*
|
||||||
|
* @returns true if the key was pressed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool wasKeyswitchPressed(KeyAddr key_addr) {
|
||||||
|
return key_scanner_.wasKeyswitchPressed(key_addr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check if a key was pressed at a given position on the previous scan
|
||||||
|
*
|
||||||
|
* @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 was pressed, false otherwise.
|
||||||
|
*/
|
||||||
|
DEPRECATED(ROW_COL_FUNC) bool wasKeyswitchPressed(byte row, byte col) {
|
||||||
|
return key_scanner_.wasKeyswitchPressed(KeyAddr(row, col));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check if a key was pressed at a given position on the previous scan.
|
||||||
|
*
|
||||||
|
* @param keyIndex is the key index, as calculated by `keyIndex`.
|
||||||
|
*
|
||||||
|
* @note Key indexes start at 1, not 0!
|
||||||
|
*
|
||||||
|
* @returns true if the key was pressed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool wasKeyswitchPressed(uint8_t keyIndex) {
|
||||||
|
return key_scanner_.wasKeyswitchPressed(KeyAddr(--keyIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the number of key switches pressed in the previous scan.
|
||||||
|
*
|
||||||
|
* @returns the number of keys pressed.
|
||||||
|
*/
|
||||||
|
uint8_t previousPressedKeyswitchCount() {
|
||||||
|
return key_scanner_.previousPressedKeyswitchCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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() {
|
||||||
|
bootloader_.setup();
|
||||||
|
mcu_.setup();
|
||||||
|
storage_.setup();
|
||||||
|
key_scanner_.setup();
|
||||||
|
led_driver_.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to configure the device for a hardware test mode
|
||||||
|
*
|
||||||
|
* Called by the Kaleidoscope Hardware test plugin, this method should
|
||||||
|
* do any device-specific initialization needed for factory hardware testing
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void enableHardwareTestMode() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to put the device into programmable/bootloader mode.
|
||||||
|
*
|
||||||
|
* This is the old, legacy name of the method.
|
||||||
|
*/
|
||||||
|
DEPRECATED(HARDWARE_RESETDEVICE) void resetDevice() {
|
||||||
|
bootloader_.rebootBootloader();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to put the device into programmable/bootloader mode.
|
||||||
|
*/
|
||||||
|
void rebootBootloader() {
|
||||||
|
bootloader_.rebootBootloader();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
protected:
|
||||||
|
KeyScanner key_scanner_;
|
||||||
|
LEDDriver led_driver_;
|
||||||
|
MCU mcu_;
|
||||||
|
Bootloader bootloader_;
|
||||||
|
Storage storage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::bootloader::base -- Base Bootloader Driver
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace bootloader {
|
||||||
|
|
||||||
|
class Base {
|
||||||
|
public:
|
||||||
|
Base() {}
|
||||||
|
|
||||||
|
void setup() {}
|
||||||
|
static void rebootBootloader() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::bootloader::None -- Dummy Bootloader driver
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
#include "kaleidoscope/driver/bootloader/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace bootloader {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The purpose of this class is to serve as a default inside the base
|
||||||
|
* `kaleidoscope::device::Base` class, with a name more descriptive than
|
||||||
|
* `bootloader::Base`. In practice, one shouldn't use it, and should override
|
||||||
|
* the bootloader in the device description.
|
||||||
|
*/
|
||||||
|
class None : public kaleidoscope::driver::bootloader::Base {};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::bootloader::avr::Caterina -- Driver for the Caterina bootloader
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
#include "kaleidoscope/driver/bootloader/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace bootloader {
|
||||||
|
namespace avr {
|
||||||
|
|
||||||
|
class Caterina : public kaleidoscope::driver::bootloader::Base {
|
||||||
|
public:
|
||||||
|
static void rebootBootloader() {
|
||||||
|
// Set the magic bits to get a Caterina-based device
|
||||||
|
// to reboot into the bootloader and stay there, rather
|
||||||
|
// than run move onward
|
||||||
|
//
|
||||||
|
// These values are the same as those defined in
|
||||||
|
// Caterina.c:
|
||||||
|
// https://github.com/arduino/ArduinoCore-avr/blob/5755ddea49fa69d6c505c772ebee5af5078e2ebf/bootloaders/caterina/Caterina.c#L130-L133
|
||||||
|
|
||||||
|
uint16_t bootKey = 0x7777;
|
||||||
|
uint16_t *const bootKeyPtr = reinterpret_cast<uint16_t *>(0x0800);
|
||||||
|
|
||||||
|
// Stash the magic key
|
||||||
|
*bootKeyPtr = bootKey;
|
||||||
|
|
||||||
|
// Set a watchdog timer
|
||||||
|
wdt_enable(WDTO_120MS);
|
||||||
|
|
||||||
|
while (true) {} // This infinite loop ensures nothing else
|
||||||
|
// happens before the watchdog reboots us
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::bootloader::avr::FLIP -- Driver for the Atmel FLIP bootloader
|
||||||
|
* Copyright (C) 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 <Kaleidoscope.h>
|
||||||
|
|
||||||
|
#ifdef KALEIDOSCOPE_BOOTLOADER_FLIP_WORKAROUND
|
||||||
|
#include "kaleidoscope/driver/bootloader/avr/FLIP.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace bootloader {
|
||||||
|
namespace avr {
|
||||||
|
|
||||||
|
// The FLIP bootloader does not provide a way to boot into bootloader mode from
|
||||||
|
// within the firmware: it will always start the user firmware if available, and
|
||||||
|
// if the reset wasn't triggered by the physical reset button. To enter the
|
||||||
|
// bootloader mode, we need to jump there from the user firmware ourselves.
|
||||||
|
//
|
||||||
|
// Since we do not want to unconditionally jump into bootloader, we set a static
|
||||||
|
// memory address to a magic value, to signal our intention, then reboot via the
|
||||||
|
// watchdog timer. We need to reboot to clear registers and have a clean slate
|
||||||
|
// for the bootloader.
|
||||||
|
//
|
||||||
|
// For this to work, we need to run our signal checking code before `main()`, so
|
||||||
|
// we put the checker function into a special section that does that.
|
||||||
|
//
|
||||||
|
// Since this code cannot be optimized out on keyboards that use another
|
||||||
|
// bootloader, we need to guard this implementation with an ifdef (see above).
|
||||||
|
//
|
||||||
|
// For more information, see:
|
||||||
|
// http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
|
||||||
|
|
||||||
|
#define BOOTLOADER_RESET_KEY 0xB007B007
|
||||||
|
static uint32_t reset_key __attribute__((section(".noinit")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function runs before main(), and jumps to the bootloader after a reset
|
||||||
|
* initiated by .resetDevice().
|
||||||
|
*/
|
||||||
|
static void _bootloader_jump_after_watchdog_reset()
|
||||||
|
__attribute__((used, naked, section(".init3")));
|
||||||
|
static void _bootloader_jump_after_watchdog_reset() {
|
||||||
|
if ((MCUSR & (1 << WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
|
||||||
|
reset_key = 0;
|
||||||
|
|
||||||
|
((void (*)(void))(((FLASHEND + 1L) - 4096) >> 1))();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FLIP::rebootBootloader() {
|
||||||
|
reset_key = BOOTLOADER_RESET_KEY;
|
||||||
|
wdt_enable(WDTO_250MS);
|
||||||
|
while (true) {} // This infinite loop ensures nothing else
|
||||||
|
// happens before the watchdog reboots us
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,41 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::bootloader::avr::FLIP -- Driver for the Atmel FLIP bootloader
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
|
||||||
|
#ifndef KALEIDOSCOPE_BOOTLOADER_FLIP_WORKAROUND
|
||||||
|
#error To use the FLIP bootloader driver, KALEIDOSCOPE_BOOTLOADER_FLIP_WORKAROUND *must* be defined prior to including this header!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/bootloader/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace bootloader {
|
||||||
|
namespace avr {
|
||||||
|
|
||||||
|
class FLIP : public kaleidoscope::driver::bootloader::Base {
|
||||||
|
public:
|
||||||
|
static void rebootBootloader();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::bootloader::avr::HalfKay -- Driver for the HalfKay bootloader
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
#include "kaleidoscope/driver/bootloader/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace bootloader {
|
||||||
|
namespace avr {
|
||||||
|
|
||||||
|
class HalfKay : public kaleidoscope::driver::bootloader::Base {
|
||||||
|
public:
|
||||||
|
// To reset a Teensy with the HalfKay bootloader, we need to disable all
|
||||||
|
// interrupts, all peripherals we have attached, USB, the watchdog timer, etc.
|
||||||
|
// Once done, we can jump to the bootloader address.
|
||||||
|
//
|
||||||
|
// Documentation: https://www.pjrc.com/teensy/jump_to_bootloader.html
|
||||||
|
static void rebootBootloader() {
|
||||||
|
cli();
|
||||||
|
UDCON = 1;
|
||||||
|
USBCON = (1 << FRZCLK);
|
||||||
|
UCSR1B = 0;
|
||||||
|
_delay_ms(5);
|
||||||
|
|
||||||
|
EIMSK = 0;
|
||||||
|
PCICR = 0;
|
||||||
|
SPCR = 0;
|
||||||
|
ACSR = 0;
|
||||||
|
EECR = 0;
|
||||||
|
ADCSRA = 0;
|
||||||
|
TIMSK0 = 0;
|
||||||
|
TIMSK1 = 0;
|
||||||
|
TIMSK3 = 0;
|
||||||
|
TIMSK4 = 0;
|
||||||
|
UCSR1B = 0;
|
||||||
|
TWCR = 0;
|
||||||
|
DDRB = 0;
|
||||||
|
DDRC = 0;
|
||||||
|
DDRD = 0;
|
||||||
|
DDRE = 0;
|
||||||
|
DDRF = 0;
|
||||||
|
TWCR = 0;
|
||||||
|
PORTB = 0;
|
||||||
|
PORTC = 0;
|
||||||
|
PORTD = 0;
|
||||||
|
PORTE = 0;
|
||||||
|
PORTF = 0;
|
||||||
|
asm volatile("jmp 0x7E00");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,239 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::keyscanner::AVR -- AVR-based keyscanner component
|
||||||
|
* Copyright (C) 2018-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
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Kaleidoscope-HIDAdaptor-KeyboardioHID.h"
|
||||||
|
|
||||||
|
#include "kaleidoscope/macro_helpers.h"
|
||||||
|
#include "kaleidoscope/driver/keyscanner/Base.h"
|
||||||
|
#include "kaleidoscope/device/avr/pins_and_ports.h"
|
||||||
|
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
|
||||||
|
#define ROW_PIN_LIST(...) __VA_ARGS__
|
||||||
|
#define COL_PIN_LIST(...) __VA_ARGS__
|
||||||
|
|
||||||
|
#define AVR_KEYSCANNER_PROPS(ROW_PINS_, COL_PINS_) \
|
||||||
|
KEYSCANNER_PROPS(NUM_ARGS(ROW_PINS_), NUM_ARGS(COL_PINS_)); \
|
||||||
|
static constexpr uint8_t matrix_row_pins[matrix_rows] = ROW_PINS_; \
|
||||||
|
static constexpr uint8_t matrix_col_pins[matrix_columns] = COL_PINS_;
|
||||||
|
|
||||||
|
#define AVR_KEYSCANNER_BOILERPLATE \
|
||||||
|
KEYSCANNER_PROPS_BOILERPLATE(kaleidoscope::Device::KeyScannerProps); \
|
||||||
|
constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_row_pins[matrix_rows]; \
|
||||||
|
constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_col_pins[matrix_columns]; \
|
||||||
|
template<> \
|
||||||
|
volatile uint16_t kaleidoscope::Device::KeyScanner::previousKeyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; \
|
||||||
|
template<> \
|
||||||
|
volatile uint16_t kaleidoscope::Device::KeyScanner::keyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; \
|
||||||
|
template<> \
|
||||||
|
uint16_t kaleidoscope::Device::KeyScanner::masks_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; \
|
||||||
|
template<> \
|
||||||
|
uint8_t kaleidoscope::Device::KeyScanner::debounce_matrix_[kaleidoscope::Device::KeyScannerProps::matrix_rows][kaleidoscope::Device::KeyScannerProps::matrix_columns] = {}; \
|
||||||
|
\
|
||||||
|
ISR(TIMER1_OVF_vect) { \
|
||||||
|
Kaleidoscope.device().readMatrix(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace keyscanner {
|
||||||
|
|
||||||
|
struct AVRProps: kaleidoscope::driver::keyscanner::BaseProps {
|
||||||
|
static const uint8_t debounce = 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following two lines declare an empty array. Both of these must be
|
||||||
|
* shadowed by the descendant keyscanner description class.
|
||||||
|
*/
|
||||||
|
static constexpr uint8_t matrix_row_pins[] = {};
|
||||||
|
static constexpr uint8_t matrix_col_pins[] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _KeyScannerProps>
|
||||||
|
class AVR : public kaleidoscope::driver::keyscanner::Base<_KeyScannerProps> {
|
||||||
|
private:
|
||||||
|
typedef AVR<_KeyScannerProps> ThisType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setup() {
|
||||||
|
static_assert(
|
||||||
|
sizeof(_KeyScannerProps::matrix_row_pins) > 0,
|
||||||
|
"The key scanner description has an empty array of matrix row pins."
|
||||||
|
);
|
||||||
|
static_assert(
|
||||||
|
sizeof(_KeyScannerProps::matrix_col_pins) > 0,
|
||||||
|
"The key scanner description has an empty array of matrix column pins."
|
||||||
|
);
|
||||||
|
|
||||||
|
wdt_disable();
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < _KeyScannerProps::matrix_columns; i++) {
|
||||||
|
DDR_INPUT(_KeyScannerProps::matrix_col_pins[i]);
|
||||||
|
ENABLE_PULLUP(_KeyScannerProps::matrix_col_pins[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < _KeyScannerProps::matrix_rows; i++) {
|
||||||
|
DDR_OUTPUT(_KeyScannerProps::matrix_row_pins[i]);
|
||||||
|
OUTPUT_HIGH(_KeyScannerProps::matrix_row_pins[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up Timer1 for 1700usec */
|
||||||
|
TCCR1B = _BV(WGM13);
|
||||||
|
TCCR1A = 0;
|
||||||
|
|
||||||
|
const uint32_t cycles = (F_CPU / 2000000) * 1700;
|
||||||
|
|
||||||
|
ICR1 = cycles;
|
||||||
|
TCCR1B = _BV(WGM13) | _BV(CS10);
|
||||||
|
TIMSK1 = _BV(TOIE1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((optimize(3))) readMatrix(void) {
|
||||||
|
for (uint8_t current_row = 0; current_row < _KeyScannerProps::matrix_rows; current_row++) {
|
||||||
|
uint16_t mask, cols;
|
||||||
|
|
||||||
|
mask = debounceMaskForRow(current_row);
|
||||||
|
|
||||||
|
OUTPUT_TOGGLE(_KeyScannerProps::matrix_row_pins[current_row]);
|
||||||
|
cols = (readCols() & mask) | (keyState_[current_row] & ~mask);
|
||||||
|
OUTPUT_TOGGLE(_KeyScannerProps::matrix_row_pins[current_row]);
|
||||||
|
debounceRow(cols ^ keyState_[current_row], current_row);
|
||||||
|
keyState_[current_row] = cols;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void scanMatrix() {
|
||||||
|
actOnMatrixScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((optimize(3))) actOnMatrixScan() {
|
||||||
|
for (byte row = 0; row < _KeyScannerProps::matrix_rows; row++) {
|
||||||
|
for (byte col = 0; col < _KeyScannerProps::matrix_columns; col++) {
|
||||||
|
uint8_t keyState = (bitRead(previousKeyState_[row], col) << 0) |
|
||||||
|
(bitRead(keyState_[row], col) << 1);
|
||||||
|
if (keyState) {
|
||||||
|
ThisType::handleKeyswitchEvent(Key_NoKey, typename _KeyScannerProps::KeyAddr(row, col), keyState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previousKeyState_[row] = keyState_[row];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t pressedKeyswitchCount() {
|
||||||
|
uint8_t count = 0;
|
||||||
|
|
||||||
|
for (int8_t r = 0; r < _KeyScannerProps::matrix_rows; r++) {
|
||||||
|
count += __builtin_popcount(keyState_[r]);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
bool isKeyswitchPressed(typename _KeyScannerProps::KeyAddr key_addr) {
|
||||||
|
return (bitRead(keyState_[key_addr.row()],
|
||||||
|
key_addr.col()) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t previousPressedKeyswitchCount() {
|
||||||
|
uint8_t count = 0;
|
||||||
|
|
||||||
|
for (int8_t r = 0; r < _KeyScannerProps::matrix_rows; r++) {
|
||||||
|
count += __builtin_popcount(previousKeyState_[r]);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
bool wasKeyswitchPressed(typename _KeyScannerProps::KeyAddr key_addr) {
|
||||||
|
return (bitRead(previousKeyState_[key_addr.row()],
|
||||||
|
key_addr.col()) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void maskKey(typename _KeyScannerProps::KeyAddr key_addr) {
|
||||||
|
if (!key_addr.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bitWrite(masks_[key_addr.row()], key_addr.col(), 1);
|
||||||
|
}
|
||||||
|
void unMaskKey(typename _KeyScannerProps::KeyAddr key_addr) {
|
||||||
|
if (!key_addr.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bitWrite(masks_[key_addr.row()], key_addr.col(), 0);
|
||||||
|
}
|
||||||
|
bool isKeyMasked(typename _KeyScannerProps::KeyAddr key_addr) {
|
||||||
|
if (!key_addr.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return bitRead(masks_[key_addr.row()],
|
||||||
|
key_addr.col());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef _KeyScannerProps KeyScannerProps_;
|
||||||
|
static volatile uint16_t previousKeyState_[_KeyScannerProps::matrix_rows];
|
||||||
|
static volatile uint16_t keyState_[_KeyScannerProps::matrix_rows];
|
||||||
|
static uint16_t masks_[_KeyScannerProps::matrix_rows];
|
||||||
|
static uint8_t debounce_matrix_[_KeyScannerProps::matrix_rows][_KeyScannerProps::matrix_columns];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function has loop unrolling disabled on purpose: we want to give the
|
||||||
|
* hardware enough time to produce stable PIN reads for us. If we unroll the
|
||||||
|
* loop, we will not have that, because even with the NOP, the codepath is too
|
||||||
|
* fast. If we don't have stable reads, then entire rows or columns will behave
|
||||||
|
* erratically.
|
||||||
|
*
|
||||||
|
* For this reason, we ask the compiler to not unroll our loop, which in turn,
|
||||||
|
* gives hardware enough time to produce stable reads, at the cost of a little
|
||||||
|
* bit of speed.
|
||||||
|
*
|
||||||
|
* Do not remove the attribute!
|
||||||
|
*/
|
||||||
|
__attribute__((optimize("no-unroll-loops")))
|
||||||
|
uint16_t readCols() {
|
||||||
|
uint16_t results = 0x00 ;
|
||||||
|
for (uint8_t i = 0; i < _KeyScannerProps::matrix_columns; i++) {
|
||||||
|
asm("NOP"); // We need to pause a beat before reading or we may read before the pin is hot
|
||||||
|
results |= (!READ_PIN(_KeyScannerProps::matrix_col_pins[i]) << i);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t debounceMaskForRow(uint8_t row) {
|
||||||
|
uint16_t result = 0;
|
||||||
|
|
||||||
|
for (uint16_t c = 0; c < _KeyScannerProps::matrix_columns; ++c) {
|
||||||
|
if (debounce_matrix_[row][c]) {
|
||||||
|
--debounce_matrix_[row][c];
|
||||||
|
} else {
|
||||||
|
result |= _BV(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void debounceRow(uint16_t change, uint8_t row) {
|
||||||
|
for (uint16_t i = 0; i < _KeyScannerProps::matrix_columns; ++i) {
|
||||||
|
if (change & _BV(i)) {
|
||||||
|
debounce_matrix_[row][i] = _KeyScannerProps::debounce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::keyscanner::base -- Keyscanner base class
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include "kaleidoscope/key_defs.h"
|
||||||
|
#include "kaleidoscope/MatrixAddr.h"
|
||||||
|
|
||||||
|
#define KEYSCANNER_PROPS(ROWS_, COLS_) \
|
||||||
|
static constexpr uint8_t matrix_rows = ROWS_; \
|
||||||
|
static constexpr uint8_t matrix_columns = COLS_; \
|
||||||
|
typedef MatrixAddr<matrix_rows, matrix_columns> KeyAddr;
|
||||||
|
|
||||||
|
#define KEYSCANNER_PROPS_BOILERPLATE(BOARD) \
|
||||||
|
const uint8_t BOARD::matrix_rows; \
|
||||||
|
const uint8_t BOARD::matrix_columns;
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace keyscanner {
|
||||||
|
|
||||||
|
struct BaseProps {
|
||||||
|
static constexpr uint8_t matrix_rows = 0;
|
||||||
|
static constexpr uint8_t matrix_columns = 0;
|
||||||
|
|
||||||
|
typedef MatrixAddr<matrix_rows, matrix_columns> KeyAddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _KeyScannerProps>
|
||||||
|
class Base {
|
||||||
|
public:
|
||||||
|
Base() {}
|
||||||
|
|
||||||
|
typedef typename _KeyScannerProps::KeyAddr KeyAddr;
|
||||||
|
|
||||||
|
static void handleKeyswitchEvent(Key mappedKey, KeyAddr key_addr, uint8_t keyState);
|
||||||
|
|
||||||
|
void setup() {}
|
||||||
|
void readMatrix() {}
|
||||||
|
void scanMatrix() {}
|
||||||
|
void actOnMatrixScan() {}
|
||||||
|
|
||||||
|
uint8_t pressedKeyswitchCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool isKeyswitchPressed(KeyAddr key_addr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t previousPressedKeyswitchCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool wasKeyswitchPressed(KeyAddr key_addr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void maskKey(KeyAddr key_addr) {}
|
||||||
|
void unMaskKey(KeyAddr key_addr) {}
|
||||||
|
bool isKeyMasked(KeyAddr key_addr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::keyscanner::None -- Dummy keyscanner component
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/keyscanner/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace keyscanner {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The purpose of this class is to serve as a default inside the base
|
||||||
|
* `kaleidoscope::device::Base` class, with a name more descriptive than
|
||||||
|
* `keyscanner::Base`. In practice, one shouldn't use it, and should override
|
||||||
|
* the bootloader in the device description.
|
||||||
|
*/
|
||||||
|
class None : public kaleidoscope::driver::keyscanner::Base<BaseProps> {};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::led::Base -- LED hardware driver base class for Kaleidoscope
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#ifndef CRGB
|
||||||
|
#error cRGB and CRGB *must* be defined before including this header!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace led {
|
||||||
|
|
||||||
|
struct BaseProps {
|
||||||
|
static constexpr uint8_t led_count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _LEDDriverProps>
|
||||||
|
class Base {
|
||||||
|
public:
|
||||||
|
Base() {}
|
||||||
|
|
||||||
|
void setup() {}
|
||||||
|
void syncLeds(void) {}
|
||||||
|
void setCrgbAt(uint8_t i, cRGB color) {}
|
||||||
|
cRGB getCrgbAt(uint8_t i) {
|
||||||
|
cRGB c = {
|
||||||
|
0, 0, 0
|
||||||
|
};
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
uint8_t getLedIndex(uint8_t key_offset) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LEDs {
|
||||||
|
private:
|
||||||
|
uint8_t offset_;
|
||||||
|
public:
|
||||||
|
LEDs() : offset_(0) {}
|
||||||
|
LEDs(uint8_t offset) : offset_(offset) {}
|
||||||
|
|
||||||
|
typedef LEDs ThisType;
|
||||||
|
|
||||||
|
constexpr uint8_t offset() {
|
||||||
|
return offset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisType operator++() {
|
||||||
|
++offset_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisType operator++(int) { // postfix ++
|
||||||
|
ThisType copy(*this);
|
||||||
|
++*this; // call the prefix increment
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisType operator--() {
|
||||||
|
--offset_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisType operator--(int) { // postfix ++
|
||||||
|
ThisType copy(*this);
|
||||||
|
--*this; // call the prefix increment
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ThisType &other) const {
|
||||||
|
return offset_ == other.offset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ThisType &other) const {
|
||||||
|
return offset_ != other.offset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Range {
|
||||||
|
typedef ThisType Iterator;
|
||||||
|
static constexpr ThisType begin() {
|
||||||
|
return ThisType(uint8_t(0));
|
||||||
|
}
|
||||||
|
static constexpr ThisType end() {
|
||||||
|
return ThisType(_LEDDriverProps::led_count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr Range all() {
|
||||||
|
return Range{};
|
||||||
|
}
|
||||||
|
constexpr const ThisType &operator*() const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr bool isValid(uint8_t index) {
|
||||||
|
return (_LEDDriverProps::led_count > 0 && index < _LEDDriverProps::led_count);
|
||||||
|
}
|
||||||
|
} LEDs;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef _LEDDriverProps Props_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::led::None -- Dummy LED hardware driver for Kaleidoscope
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#ifndef CRGB
|
||||||
|
|
||||||
|
struct cRGB {
|
||||||
|
uint8_t r, g, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CRGB(r,g,b) (cRGB){b, g, r}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/led/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace led {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The purpose of this class is to serve as a default inside the base
|
||||||
|
* `kaleidoscope::device::Base` class, with a name more descriptive than
|
||||||
|
* `leddriver::Base`. In practice, one shouldn't use it, and should override the
|
||||||
|
* bootloader in the device description.
|
||||||
|
*/
|
||||||
|
class None : public kaleidoscope::driver::led::Base<BaseProps> {};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* driver::mcu::Base -- MCU driver base class for Kaleidoscope
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace mcu {
|
||||||
|
|
||||||
|
class Base {
|
||||||
|
public:
|
||||||
|
Base() {}
|
||||||
|
|
||||||
|
void setup() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {}
|
||||||
|
/**
|
||||||
|
* Attack the device to the host.
|
||||||
|
*
|
||||||
|
* Must restore the link detachFromHost severed.
|
||||||
|
*/
|
||||||
|
void attachToHost() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* driver::MCU::None -- Dummy MCU driver for Kaleidoscope
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/mcu/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace mcu {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The purpose of this class is to serve as a default inside the base
|
||||||
|
* `kaleidoscope::device::Base` class, with a name more descriptive than
|
||||||
|
* `mcu::Base`. In practice, one shouldn't use it, and should override the
|
||||||
|
* bootloader in the device description.
|
||||||
|
*/
|
||||||
|
class None : public kaleidoscope::driver::mcu::Base {};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::storage::ATMega32U4StorageProps -- Storage driver props for ATMega32U4
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/storage/AVREEPROM.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace storage {
|
||||||
|
|
||||||
|
struct ATMega32U4EEPROMProps : kaleidoscope::driver::storage::AVREEPROMProps {
|
||||||
|
static constexpr uint16_t length = 1024;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::storage::AVREEPROM -- Storage driver with AVR EEPROM backend
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/storage/Base.h"
|
||||||
|
#include <EEPROM.h>
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace storage {
|
||||||
|
|
||||||
|
struct AVREEPROMProps : kaleidoscope::driver::storage::BaseProps {
|
||||||
|
static constexpr uint16_t length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _StorageProps>
|
||||||
|
class AVREEPROM : public kaleidoscope::driver::storage::Base<_StorageProps> {
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
static T& get(uint16_t offset, T& t) {
|
||||||
|
return EEPROM.get(offset, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static const T& put(uint16_t offset, T& t) {
|
||||||
|
return EEPROM.put(offset, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read(int idx) {
|
||||||
|
return EEPROM.read(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(int idx, uint8_t val) {
|
||||||
|
EEPROM.write(idx, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(int idx, uint8_t val) {
|
||||||
|
EEPROM.update(idx, val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::storage::Base -- Base Storage driver class
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace storage {
|
||||||
|
|
||||||
|
struct BaseProps {
|
||||||
|
static constexpr uint16_t length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _StorageProps>
|
||||||
|
class Base {
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
static T& get(uint16_t offset, T& t) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static const T& put(uint16_t offset, T& t) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read(int idx) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(int idx, uint8_t val) {}
|
||||||
|
|
||||||
|
void update(int idx, uint8_t val) {}
|
||||||
|
|
||||||
|
const uint16_t length() {
|
||||||
|
return _StorageProps::length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {}
|
||||||
|
void commit() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* kaleidoscope::driver::storage::None -- Dummy Storage hardware driver for Kaleidoscope
|
||||||
|
* Copyright (C) 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
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/storage/Base.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace storage {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The purpose of this class is to serve as a default inside the base
|
||||||
|
* `kaleidoscope::device::Base` class, with a name more descriptive than
|
||||||
|
* `storage::Base`. In practice, one shouldn't use it, and should override the
|
||||||
|
* bootloader in the device description.
|
||||||
|
*/
|
||||||
|
class None : public kaleidoscope::driver::storage::Base<BaseProps> {};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue