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.
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:
// 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;
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 port does this, for example, by overriding the generic
readCols
with a more specialised, faster implementation.
See the Planck and Atreus ports for an example of how this class can be used in practice.