diff --git a/NEWS.md b/NEWS.md index 6c90cd11..abe27afd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -89,6 +89,8 @@ Kaleidoscope has been ported to the following devices: For more information, please see the hardware plugins' documentation. +To make it easier to port Kaleidoscope, we introduced the [ATMegaKeyboard](doc/plugin/ATMegaKeyboard.md) base class. For any board that's based on the ATMega MCU and a simple matrix, this might be a good foundation to develop the hardware plugin upon. + ## New plugins ### IdleLEDs diff --git a/doc/plugin/ATMegaKeyboard.md b/doc/plugin/ATMegaKeyboard.md new file mode 100644 index 00000000..e0697338 --- /dev/null +++ b/doc/plugin/ATMegaKeyboard.md @@ -0,0 +1,82 @@ +# 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