Merge branch 'master' into pr_host_keymap

pull/721/head
Jesse Vincent 4 years ago committed by GitHub
commit f074b58d8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

2
.gitignore vendored

@ -6,3 +6,5 @@
/docs/generated
/docs/doxyoutput
/docs/api
/_build/
/results/

@ -1,5 +1,4 @@
dist: trusty
sudo: false
dist: focal
language: c
os:
- linux
@ -7,20 +6,46 @@ addons:
apt:
packages:
- shellcheck
- cmake
env:
global:
- LC_ALL: C
git:
quiet: true
before_install:
- ccache --set-config=compiler_check=content -M 1G -F 0
install:
- git clone --depth 1 --recurse-submodules https://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio ../hardware/keyboardio
- git clone --depth 1 --recurse-submodules --shallow-submodules git://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio ../hardware/keyboardio
## We delete the Bundle's version of Kaleidoscope, and symlink ourselves in.
## This makes sure we're using the current version of the library.
- rm -rf ../hardware/keyboardio/avr/libraries/Kaleidoscope
- ln -s $(pwd) ../hardware/keyboardio/avr/libraries/Kaleidoscope
- export KALEIDOSCOPE_TEMP_PATH=$TRAVIS_BUILD_DIR/.kaleidoscope-build-cache
- export BOARD_HARDWARE_PATH=$TRAVIS_BUILD_DIR/../hardware
- export ARDUINO_PATH=$TRAVIS_BUILD_DIR/arduino-1.8.13
- make adjust-git-timestamps
- make travis-install-arduino
- make prepare-ccache
jobs:
include:
- env: TEST_TARGET=smoke-sketches
- env: TEST_TARGET=travis-simulator-tests
- env: TEST_TARGET=cpplint
- env: TEST_TARGET=find-filename-conflicts
- env: TEST_TARGET=shellcheck
- env: TEST_TARGET=travis-check-astyle
script:
- make travis-test KALEIDOSCOPE_TEMP_PATH=$(pwd)/.kaleidoscope-build-cache BOARD_HARDWARE_PATH=$(pwd)/../hardware
- unset CC
- make -j 2 $TEST_TARGET
notifications:
email:
on_success: change
on_failure: change
cache:
apt: true
ccache: true
directories:
- .download-cache
- .kaleidoscope-build-cache
- .ccache

@ -30,15 +30,22 @@ mkdir -p $HOME/Arduino/hardware
cd $HOME/Arduino/hardware
```
### Windows
### Windows (Assuming cmd)
```sh
mkdir %userprofile%\Documents\Arduino\hardware
cd %userprofile%\Documents\Arduino\hardware
```
*TODO*: Write me
### Install the libraries and hardware definitions
## Clone the hardware definitions
Because git for Windows doesn't always have symlink support enabled by default, you may need to enable it for Kaleidoscope. To do that, add '-c core.symlinks=true' to your commandline. On all other platforms, that option is safe, but not necessary, as symlinks should work by default.
```sh
git clone --recursive https://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio.git keyboardio
git clone -c core.symlinks=true --recursive https://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio.git keyboardio
```

@ -70,7 +70,7 @@ for my $path (@paths) {
}
if ( $devices{$path}{'ID_MM_CANDIDATE'}) {
my $rules = "$Bin/../etc/99-kaleidoscope.rules";
my $rules = "$Bin/../etc/60-kaleidoscope.rules";
print_warning <<EOWARN
WARNING: your udev rules are currently configured to suggest
@ -90,4 +90,3 @@ EOWARN
#debug("ERROR: I couldn't find a USB device matching the keyboard's USB Vendor and Device IDs\n");
#print_warning(join("\n",@log));

@ -10,6 +10,10 @@ use strict;
my $vid = shift @ARGV;
my $pid = shift @ARGV;
if (!defined $vid || !defined $pid) {
die "$0 has two required parameters, VID and PID";
}
# ioreg might be more machine-readable than system_profiler, but I haven't been able to
# get it to produce useful output
my @output = qx(/usr/sbin/system_profiler SPUSBDataType 2> /dev/null);
@ -51,28 +55,42 @@ sub try_for_raw_serialnum {
# High Sierra sometimes has a mismatch between the serial number and the device
# filename. I'm not sure why, but system_profiler has a serial number ending in "E",
# whereas the device filename ends in "1". In fact, when I change HID.getShortName()
# to return "kbio02", the final character is replaced with a "1", so we should do the
# same here. If the serial number doesn't end in a digit, however, we may want to append
# rather than replace the last character with a 1.
# to return "kbio02", the final character is replaced with a "1".
if ($serial_port_name =~ /\d$/) {
$serial_port_name =~ s/.$/1/;
chop $serial_port_name;
exit_with_port_if_exists($serial_port_name . "1");
} else {
$serial_port_name .= "1";
# If the serial port name doesn't end with a digit, try -appending- rather than replacing
# the last character of the port name
exit_with_port_if_exists($serial_port_name . "1");
# and if that didn't work, try replacing the last character with a "1" anyway.
# Jason Koh reports that he saw this behavior as required on Catalina in May 2020.
chop $serial_port_name;
exit_with_port_if_exists($serial_port_name . "1");
}
exit_with_port_if_exists($serial_port_name);
}
sub try_for_location_id {
my $location_id = shift;
# Here, also, the final character is always a "1", so if macOS ever stops doing that, this
# will need an update, as well.
my $loc = substr($location_id, 2, 3);
exit_with_port_if_exists("/dev/cu.usbmodem" . $loc . 1);
# macOS truncates the string of "0"s from the right of the location id.
# Here, also, the final character is an appended "1", so if macOS ever stops doing that,
# this will need an update, as well.
if ($location_id =~ /0x(\d+?)0*\b/) {
my $loc = $1;
exit_with_port_if_exists("/dev/cu.usbmodem" . $loc . "1");
}
}
sub try_for_sn_prefix {
my $sn = shift;
# If macOS has appended 'E', take it off to maximise our chances of a match.
$sn =~ s/E$//;
# If none of the above tests succeeds, just list the directory and see if there are any
# files that have the device shortname that we expect:

@ -0,0 +1,55 @@
#!/usr/bin/env bash
# find-filename-conflicts - Finds cpp files with conflicting filenames
# Copyright (C) 2020 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/>.
## When building Kaleidoscope, the compiled object files are linked together
## into a static archive. This static archive has a very simple structure, and
## only stores filenames, not paths, not even relative ones. As such, we can't
## have files with the same name, because they will conflict, and one will
## override the other.
##
## To avoid this situation, this script will find all cpp source files (we don't
## need to care about header-only things, those do not result in an object
## file), and will comb through them to find conflicting filenames.
##
## If a conflict is found, it will print all files that share the name, and will
## exit with an error at the end. It does not exit at the first duplicate, but
## will find and print all of them.
##
## If no conflict is found, the script just prints its status message and exits
## with zero.
set -e
FILE_LIST="$(find src -name '*.cpp' | sed -e 's,\(\(.*\)/\([^/]*\)\),\3 \1,')"
exit_code=0
echo -n "Looking for conflicting filenames... "
for f in $(echo "${FILE_LIST}" | cut -f1 -d" "); do
count=$(echo "${FILE_LIST}" | grep -c "^${f}")
if [ "$count" -gt 1 ]; then
echo >&2
echo " Conflict found for ${f}: " >&2
echo "${FILE_LIST}" | grep "${f}" | cut -d" " -f2 | sed -e 's,^, ,' >&2
exit_code=1
fi
done
if [ "${exit_code}" -eq 0 ]; then
echo "done."
fi
exit ${exit_code}

@ -19,16 +19,22 @@ set -e
###### Build and output configuration
######
absolute_filename() {
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
build_version () {
GIT_VERSION="$(cd "$(find_sketch)"; if [ -d .git ]; then echo -n '-g' && git describe --abbrev=4 --dirty --always; fi)"
GIT_VERSION="$(cd "${SKETCH_DIR}"; if [ -d .git ]; then echo -n '-g' && git describe --abbrev=4 --dirty --always; fi)"
LIB_PROPERTIES_PATH="${LIB_PROPERTIES_PATH:-"../.."}"
LIB_VERSION="$(cd "$(find_sketch)"; (grep version= "${LIB_PROPERTIES_PATH}/library.properties" 2>/dev/null || echo version=0.0.0) | cut -d= -f2)${GIT_VERSION}"
LIB_VERSION="$(cd "${SKETCH_DIR}"; (grep version= "${LIB_PROPERTIES_PATH}/library.properties" 2>/dev/null || echo version=0.0.0) | cut -d= -f2)${GIT_VERSION}"
}
build_paths() {
# We don't really want to use find
# shellcheck disable=SC2012
SKETCH_IDENTIFIER="$(ls -id "$(find_sketch)/${SKETCH}.ino" | cut -d ' ' -f 1)-${SKETCH}.ino"
# We need that echo because we\re piping to cksum
# shellcheck disable=SC2005
SKETCH_IDENTIFIER="$(echo "$(absolute_filename "${SKETCH_DIR}/${SKETCH}.ino")" | cksum | cut -d ' ' -f 1)-${SKETCH}.ino"
KALEIDOSCOPE_TEMP_PATH="${KALEIDOSCOPE_TEMP_PATH:-${TMPDIR:-/tmp}/kaleidoscope-${USER}}"
@ -49,10 +55,11 @@ build_paths() {
}
build_filenames () {
OUTPUT_FILE_PREFIX="${SKETCH}-${LIB_VERSION}"
HEX_FILE_PATH="${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.hex"
HEX_FILE_WITH_BOOTLOADER_PATH="${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}-with-bootloader.hex"
ELF_FILE_PATH="${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.elf"
OUTPUT_FILE_PREFIX="${OUTPUT_FILE_PREFIX:-${SKETCH}-${LIB_VERSION}}"
HEX_FILE_PATH="${HEX_FILE_PATH:-${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.hex}"
HEX_FILE_WITH_BOOTLOADER_PATH="${HEX_FILE_WITH_BOOTLOADER_PATH:-${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}-with-bootloader.hex}"
ELF_FILE_PATH="${ELF_FILE_PATH:-${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.elf}"
LIB_FILE_PATH="${LIB_FILE_PATH:-${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.a}"
}
@ -60,32 +67,32 @@ enable_ccache () {
if [ -z "${CCACHE_NOT_SUPPORTED}" ] && [ "$(command -v ccache)" ]; then
if ! [ -d "$CCACHE_WRAPPER_PATH" ]; then
mkdir -p "$CCACHE_WRAPPER_PATH"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${C_COMPILER_BASENAME}" ]; then
ln -s "$(command -v ccache)" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${C_COMPILER_BASENAME}"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}" ]; then
ln -s "$(command -v ccache)" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}nm" ]; then
ln -s "${AVR_NM}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}nm"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}objcopy" ]; then
ln -s "${AVR_OBJCOPY}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}objcopy"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}ar" ]; then
ln -s "${AVR_AR}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}ar"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}size" ]; then
ln -s "${AVR_SIZE}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}size"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${C_COMPILER_BASENAME}" ]; then
ln -s "$(command -v ccache)" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${C_COMPILER_BASENAME}"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}" ]; then
ln -s "$(command -v ccache)" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}nm" ]; then
ln -s "${AVR_NM}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}nm"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}objcopy" ]; then
ln -s "${AVR_OBJCOPY}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}objcopy"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}ar" ]; then
ln -s "${AVR_AR}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}ar"
fi
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}size" ]; then
ln -s "${AVR_SIZE}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}size"
fi
fi
export CCACHE_PATH=${COMPILER_PATH}/
CCACHE_ENABLE="-prefs compiler.path=${CCACHE_WRAPPER_PATH}/"
fi
@ -129,12 +136,17 @@ find_sketch () {
echo "SKETCH, LIBRARY, SOURCEDIR, and ROOT need to be set before including this file!" >&2
exit 1
fi
SKETCH_DIR="$SKETCH"
SKETCH_FILE=$(basename "$SKETCH")
for path in "examples/${LIBRARY}" \
for path in "${SKETCH_DIR}" \
"examples/${LIBRARY}" \
"src" \
"."; do
if [ -f "${path}/${SKETCH}.ino" ]; then
echo "${path}"
if [ -f "${path}/${SKETCH_FILE}.ino" ]; then
SKETCH_DIR="${path}"
SKETCH="${SKETCH_FILE}"
return
fi
done
@ -163,19 +175,26 @@ prompt_before_flashing () {
flash () {
maybe_build "$@"
# Check to see if we can see a keyboard bootloader port.
# Check to see if we can see a keyboard bootloader port.
# If we -can-, then we should skip over the "reset to bootloader" thing
find_bootloader_ports
if [ -z "${DEVICE_PORT_BOOTLOADER}" ]; then
prompt_before_flashing
# This is defined in the (optional) user config.
# shellcheck disable=SC2154
${preFlash_HOOKS}
reset_device
sleep 2
find_bootloader_ports
# If we're -not- doing a manual reset, then try to do it automatically
if [ -z "${MANUAL_RESET}" ]; then
reset_device
sleep 2
find_bootloader_ports
# Otherwise, poll for a bootloader port.
else
wait_for_bootloader_port
fi
fi
check_bootloader_port_and_flash
@ -185,6 +204,25 @@ flash () {
${postFlash_HOOKS}
}
wait_for_bootloader_port() {
declare -i tries
tries=15
while [ "$tries" -gt 0 ] && [ -z "${DEVICE_PORT_BOOTLOADER}" ]; do
sleep 1
printf "."
find_bootloader_ports
# the variable annotations do appear to be necessary
# shellcheck disable=SC2004
tries=$(($tries-1))
done
if [ "$tries" -gt 0 ]; then
echo "Found."
else
echo "Timed out."
fi
}
check_bootloader_port () {
if [ -z "${DEVICE_PORT_BOOTLOADER}" ]; then
@ -201,11 +239,11 @@ check_bootloader_port_and_flash () {
if ! check_bootloader_port; then
return 1
fi
echo "Flashing your keyboard:"
# If the flash fails, try a second time
if ! flash_over_usb; then
if ! flash_over_usb; then
sleep 2
if ! flash_over_usb; then
if [ "${ARDUINO_VERBOSE}" != "-verbose" ]; then
@ -279,7 +317,7 @@ hex_with_bootloader () {
echo "Using ${BOOTLOADER_PATH}"
${MD5} "${BOOTLOADER_PATH}"
cat "${BOOTLOADER_PATH}" >> "${HEX_FILE_WITH_BOOTLOADER_PATH}"
ln -sf -- "${HEX_FILE_WITH_BOOTLOADER_PATH}" "${OUTPUT_PATH}/${SKETCH}-latest-with-bootloader.hex"
ln -sf -- "${OUTPUT_FILE_PREFIX}-with-bootloader.hex" "${OUTPUT_PATH}/${SKETCH}-latest-with-bootloader.hex"
cat <<- EOF
Combined firmware and bootloader are now at ${HEX_FILE_WITH_BOOTLOADER_PATH}
@ -291,14 +329,13 @@ hex_with_bootloader () {
}
maybe_build () {
find_sketch
build_version
build_paths
build_filenames
if [ ! -e "${HEX_FILE_PATH}" ]; then
build "$@"
else
SKETCH_DIR="$(find_sketch)"
fi
}
@ -308,17 +345,22 @@ build () {
size "$@"
}
prepare_ccache () {
build_paths
enable_ccache
}
compile () {
find_sketch
build_version
build_paths
build_filenames
enable_ccache
install -d "${OUTPUT_PATH}"
SKETCH_DIR="$(find_sketch)"
echo "Building ${SKETCH_DIR}/${SKETCH} ${LIB_VERSION} into ${OUTPUT_PATH}"
echo "Building ${SKETCH_DIR}/${SKETCH}"
# This is defined in the (optional) user config.
# shellcheck disable=SC2154
@ -336,7 +378,7 @@ compile () {
# We want literal backslashes here, not arrays.
ARDUINO_PACKAGES="-hardware \"${ARDUINO_PACKAGE_PATH}\""
fi
SAVED_BOARD="${BOARD}"
SAVED_FQBN="${FQBN}"
if [ -e "${SKETCH_DIR}/.kaleidoscope-builder.conf" ]; then
@ -353,6 +395,10 @@ compile () {
fi
fi
_CMD_CXX="${CXX:-${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}${COMPILER_SUFFIX}}"
_CMD_CC="${CC:-${COMPILER_PREFIX}${C_COMPILER_BASENAME}${COMPILER_SUFFIX}}"
_CMD_AR="${AR:-${COMPILER_PREFIX}${AR_BASENAME}${COMPILER_SUFFIX}}"
# SC2091: We do not care if quotes or backslashes are not respected.
# SC2086: We want word splitting.
# shellcheck disable=SC2086,SC2090
@ -375,19 +421,25 @@ compile () {
-built-in-libraries "${ARDUINO_PATH}/libraries" \
-prefs "compiler.cpp.extra_flags=${ARDUINO_CFLAGS} ${LOCAL_CFLAGS}" \
-prefs "compiler.path=${COMPILER_PATH}" \
-prefs "compiler.c.cmd=${COMPILER_PREFIX}${C_COMPILER_BASENAME}" \
-prefs "compiler.cpp.cmd=${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}" \
-prefs "compiler.c.cmd=${_CMD_CC}" \
-prefs "compiler.cpp.cmd=${_CMD_CXX}" \
-prefs "compiler.ar.cmd=${_CMD_AR}" \
-prefs "compiler.c.elf.cmd=${_CMD_CXX}" \
$CCACHE_ENABLE \
-warnings all \
${ARDUINO_VERBOSE} \
${ARDUINO_AVR_GCC_PREFIX_PARAM} \
"${SKETCH_DIR}/${SKETCH}.ino"
cp "${BUILD_PATH}/${SKETCH}.ino.hex" "${HEX_FILE_PATH}"
cp "${BUILD_PATH}/${SKETCH}.ino.elf" "${ELF_FILE_PATH}"
ln -sf "${OUTPUT_FILE_PREFIX}.hex" "${OUTPUT_PATH}/${SKETCH}-latest.hex"
ln -sf "${OUTPUT_FILE_PREFIX}.elf" "${OUTPUT_PATH}/${SKETCH}-latest.elf"
if [ -z "${LIBONLY}" ]; then
cp "${BUILD_PATH}/${SKETCH}.ino.hex" "${HEX_FILE_PATH}"
cp "${BUILD_PATH}/${SKETCH}.ino.elf" "${ELF_FILE_PATH}"
ln -sf "${OUTPUT_FILE_PREFIX}.hex" "${OUTPUT_PATH}/${SKETCH}-latest.hex"
ln -sf "${OUTPUT_FILE_PREFIX}.elf" "${OUTPUT_PATH}/${SKETCH}-latest.elf"
else
cp "${BUILD_PATH}/${SKETCH}.ino.a" "${LIB_FILE_PATH}"
ln -sf "${OUTPUT_FILE_PREFIX}.a" "${OUTPUT_PATH}/${SKETCH}-latest.a"
fi
if [ "${ARDUINO_VERBOSE}" = "-verbose" ]; then
echo "Build artifacts can be found in ${BUILD_PATH}";
@ -397,7 +449,7 @@ compile () {
FQBN="${SAVED_FQBN}"
}
_find_all () {
find_all_sketches () {
for plugin in ./*.ino \
$([ -d examples ] && find examples -name '*.ino') \
src/*.ino; do
@ -418,7 +470,7 @@ _find_all () {
}
build_all () {
plugins="$(_find_all)"
plugins="$(find_all_sketches)"
for plugin in ${plugins}; do
export SKETCH="${plugin}"
@ -429,7 +481,7 @@ build_all () {
compile_all () {
plugins="$(_find_all)"
plugins="$(find_all_sketches)"
for plugin in ${plugins}; do
export SKETCH="${plugin}"
@ -473,6 +525,11 @@ decompile () {
clean () {
rm -rf -- "${OUTPUT_PATH}"
kaleidoscope_dir="$(dirname "$0")/.."
(install -d "${kaleidoscope_dir}/testing/googletest/build" &&
cd "${kaleidoscope_dir}/testing/googletest/build" &&
cmake .. &&
make clean)
}
reset_device() {
@ -536,6 +593,25 @@ EOF
fi
}
build_gtest_gmock() {
kaleidoscope_dir="$(dirname "$0")/.."
(cd "${kaleidoscope_dir}/testing/googletest" && cmake . && make)
}
run_tests() {
(cd "${BOARD_HARDWARE_PATH}/keyboardio" && make prepare-virtual)
build_gtest_gmock
kaleidoscope_dir="$(dirname "$0")/.."
cd "${kaleidoscope_dir}/tests"
${MAKE:-make}
}
docker_tests() {
kaleidoscope_dir="$(dirname "$0")/.."
cd "${kaleidoscope_dir}"
bin/run-docker make -C tests all
}
usage () {
cat <<- EOF
Usage: $0 SKETCH commands...
@ -573,6 +649,9 @@ usage () {
build-all
Build all Sketches we can find.
run-tests | docker-tests
Builds and runs the test suite, on the host, and in docker, respectively.
EOF
}
@ -667,12 +746,6 @@ done
LIBRARY="${SKETCH}"
case "${SKETCH}" in
*/*)
SKETCH="$(basename "${SKETCH}")"
;;
esac
export SKETCH
export LIBRARY

@ -0,0 +1,19 @@
#! /bin/sh
## -*- mode: sh -*-
set -e
uname_S=$(uname -s 2>/dev/null || echo not)
ARDUINO_LOCAL_LIB_PATH="${ARDUINO_LOCAL_LIB_PATH:-${HOME}/Arduino}"
if [ "${uname_S}" = "Darwin" ]; then
ARDUINO_LOCAL_LIB_PATH="${ARDUINO_LOCAL_LIB_PATH:-${HOME}/Documents/Arduino}"
fi
BOARD_HARDWARE_PATH="${BOARD_HARDWARE_PATH:-${ARDUINO_LOCAL_LIB_PATH}/hardware}"
docker build -t kaleidoscope/docker etc
docker run --rm -it \
-v "${BOARD_HARDWARE_PATH}/keyboardio:/kaleidoscope/hardware/keyboardio" \
-v "$(pwd):/kaleidoscope/hardware/keyboardio/avr/libraries/Kaleidoscope" \
kaleidoscope/docker -c "$*"

@ -0,0 +1,15 @@
#!/bin/bash -e
# This script sets all of the files inside src and example to have mtimes
# that match the times of the last git commit that touched each file
# This can be useful when build tools depend on file timestamps to
# make caching decisions
find src examples -type f -exec sh -c '
timestamp=$(git log --pretty=format:%ad --date=format:%Y%m%d%H%M.%S -n 1 HEAD "$1" 2> /dev/null)
if [ "x$timestamp" != "x" ]; then
touch -t "$timestamp" "$1"
fi
' sh {} \;

File diff suppressed because it is too large Load Diff

@ -74,23 +74,23 @@ See the [Kaleidoscope-USB-Quirks][plugin:USB-Quirks] plugin for a use-case.
### Finer stickability controls for OneShot
The [OneShot plugin](doc/plugin/OneShot.md) gained finer stickability controls, one can now control whether the double-tap stickiness is enabled on a per-key basis. See [UPGRADING.md](UPGRADING.md#finer-oneshot-stickability-control) for more information.
The [OneShot plugin](plugins/OneShot.md) gained finer stickability controls, one can now control whether the double-tap stickiness is enabled on a per-key basis. See [UPGRADING.md](UPGRADING.md#finer-oneshot-stickability-control) for more information.
### A way to slow down Unicode input
In certain cases we need to delay the unicode input sequence, otherwise the host is unable to process the input properly. For this reason, the [Unicode](doc/plugin/Unicode.md) gained an `.input_delay()` method that lets us do just that. It still defaults to no delay.
In certain cases we need to delay the unicode input sequence, otherwise the host is unable to process the input properly. For this reason, the [Unicode](plugins/Unicode.md) gained an `.input_delay()` method that lets us do just that. It still defaults to no delay.
### Better support for modifiers in the Cycle plugin
The [Cycle](doc/plugin/Cycle.md) plugin has much better support for cycling through keys with modifiers applied to them, such as `LSHIFT(Key_A)`. Please see the documentation and the updated example for more information.
The [Cycle](plugins/Cycle.md) plugin has much better support for cycling through keys with modifiers applied to them, such as `LSHIFT(Key_A)`. Please see the documentation and the updated example for more information.
### More control over when to send reports during Macro playback
There are situations where one would like to disable sending a report after each and every step of a macro, and rather have direct control over when reports are sent. The new `WITH_EXPLICIT_REPORT`, `WITH_IMPLICIT_REPORT` and `SEND_REPORT` steps help with that. Please see the [Macros](doc/plugin/Macros.md) documentation for more information.
There are situations where one would like to disable sending a report after each and every step of a macro, and rather have direct control over when reports are sent. The new `WITH_EXPLICIT_REPORT`, `WITH_IMPLICIT_REPORT` and `SEND_REPORT` steps help with that. Please see the [Macros](plugins/Macros.md) documentation for more information.
### LED-ActiveModColor can be asked to not highlight normal modifiers
The plugin was intended to work with OneShot primarily, and that's where it is most useful. To make it less surprising, and more suitable to include it in default-like firmware, we made it possible to ask it not to highlight normal modifiers. Please see the [LED-ActiveModColor](doc/plugin/LED-ActiveModColor.md) documentation for more information.
The plugin was intended to work with OneShot primarily, and that's where it is most useful. To make it less surprising, and more suitable to include it in default-like firmware, we made it possible to ask it not to highlight normal modifiers. Please see the [LED-ActiveModColor](plugins/LED-ActiveModColor.md) documentation for more information.
### Events now trigger on layer changes
@ -113,46 +113,46 @@ New `PER_KEY_DATA` and `PER_KEY_DATA_STACKED` macros are available (when defined
Kaleidoscope has been ported to the following devices:
- [Atreus](doc/plugin/Hardware-Technomancy-Atreus.md): All known variants of the original Atreus are supported. From the Legacy Teensy variant, through the pre-2016 PCB with an A* MCU, the post-2016 PCB, and FalbaTech's handwired one too. Apart from the legacy Teensy variant, the other support both the A* or a Teensy as an MCU.
- [ErgoDox](doc/plugin/Hardware-EZ-ErgoDox.md): Originally developed to support the ErgoDox EZ, but all other compatible hardware is supported, such as the original ErgoDox and anything else wired like it, like some Dactyls.
- [Planck](doc/plugin/Hardware-OLKB-Planck.md): AVR-based Plancks, and anything else wired similarly should be supported, as long as they use a Teensy.
- [Splitography](doc/plugin/Hardware-SOFTHRUF-Splitography.md): Initial support for the Splitography Steno keyboard.
- [Atreus](hardware-devices/Hardware-Technomancy-Atreus.md): All known variants of the original Atreus are supported. From the Legacy Teensy variant, through the pre-2016 PCB with an A* MCU, the post-2016 PCB, and FalbaTech's handwired one too. Apart from the legacy Teensy variant, the other support both the A* or a Teensy as an MCU.
- [ErgoDox](hardware-devices/Hardware-EZ-ErgoDox.md): Originally developed to support the ErgoDox EZ, but all other compatible hardware is supported, such as the original ErgoDox and anything else wired like it, like some Dactyls.
- [Planck](hardware-devices/Hardware-OLKB-Planck.md): AVR-based Plancks, and anything else wired similarly should be supported, as long as they use a Teensy.
- [Splitography](hardware-devices/Hardware-SOFTHRUF-Splitography.md): Initial support for the Splitography Steno keyboard.
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.
To make it easier to port Kaleidoscope, we introduced the [ATMegaKeyboard](plugins/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
### DynamicMacros
The [DynamicMacros](doc/plugin/DynamicMacros.md) plugin provides a way to use and update macros via the Focus API, through Chrysalis.
The [DynamicMacros](plugins/DynamicMacros.md) plugin provides a way to use and update macros via the Focus API, through Chrysalis.
### IdleLEDs
The [IdleLEDs](doc/plugin/IdleLEDs.md) plugin is a simple, yet, useful one: it will turn the keyboard LEDs off after a period of inactivity, and back on upon the next key event.
The [IdleLEDs](plugins/IdleLEDs.md) plugin is a simple, yet, useful one: it will turn the keyboard LEDs off after a period of inactivity, and back on upon the next key event.
### LEDActiveLayerColor
The [LEDActiveLayerColor][doc/plugin/LEDActiveLayerColor.md] plugin makes it possible to set the color of all LEDs to the same color, depending on which layer is active topmost.
The [LEDActiveLayerColor][plugins/LEDActiveLayerColor.md] plugin makes it possible to set the color of all LEDs to the same color, depending on which layer is active topmost.
### LED-Wavepool
We integrated the [LEDWavepool](doc/plugin/LED-Wavepool.md) plugin by [ToyKeeper][wavepool:origin], with a few updates and new features added.
We integrated the [LEDWavepool](plugins/LED-Wavepool.md) plugin by [ToyKeeper][wavepool:origin], with a few updates and new features added.
[wavepool:origin]: https://github.com/ToyKeeper/Kaleidoscope-LED-Wavepool
### Turbo
The [Turbo](doc/plugin/Turbo.md) plugin provides a way to send keystrokes in very quick succession while holding down a key.
The [Turbo](plugins/Turbo.md) plugin provides a way to send keystrokes in very quick succession while holding down a key.
### WinKeyToggle
The [WinKeyToggle](doc/plugin/WinKeyToggle.md) plugin assists with toggling the Windows key on and off - a little something for those of us who game under Windows and are tired of accidentally popping up the start menu.
The [WinKeyToggle](plugins/WinKeyToggle.md) plugin assists with toggling the Windows key on and off - a little something for those of us who game under Windows and are tired of accidentally popping up the start menu.
### FirmwareDump
The [FirmwareDump](doc/plugin/FirmwareDump.md) plugin makes it possible to dump one's firmware over Focus.
The [FirmwareDump](plugins/FirmwareDump.md) plugin makes it possible to dump one's firmware over Focus.
## Breaking changes
@ -185,33 +185,37 @@ The `NumPad` plugin used to toggle `NumLock` when switching to the NumPad layer.
### The `RxCy` macros and peeking into the keyswitch state
The `RxCy` macros changed from being indexes into a per-hand bitmap to being an index across the whole keyboard. This mostly affected the [MagicCombo](doc/plugin/MagicCombo.md) plugin.
The `RxCy` macros changed from being indexes into a per-hand bitmap to being an index across the whole keyboard. This mostly affected the [MagicCombo](plugins/MagicCombo.md) plugin.
Please see the [relevant upgrade notes](UPGRADING.md#the-rxcy-macros-and-peeking-into-the-keyswitch-state) for more information.
### The `Redial` plugin had a breaking API change
The [Redial](doc/plugin/Redial.md) plugin was simplified, one no longer needs to define `Key_Redial` on their own, the plugin defines it itself. See the [upgrade notes](UPGRADING.md#Redial) for more information about how to upgrade.
The [Redial](plugins/Redial.md) plugin was simplified, one no longer needs to define `Key_Redial` on their own, the plugin defines it itself. See the [upgrade notes](UPGRADING.md#Redial) for more information about how to upgrade.
### Color palette storage has changed
The [LED-Palette-Theme](doc/plugin/LED-Palette-Theme.md) had to be changed to store the palette colors in reverse. This change had to be made in order to not default to a bright white palette, that would draw so much power that most operating systems would disconnect the keyboard due to excessive power usage. With inverting the colors, we now default to a black palette instead. This sadly breaks existing palettes, and you will have to re-set the colors.
The [LED-Palette-Theme](plugins/LED-Palette-Theme.md) had to be changed to store the palette colors in reverse. This change had to be made in order to not default to a bright white palette, that would draw so much power that most operating systems would disconnect the keyboard due to excessive power usage. With inverting the colors, we now default to a black palette instead. This sadly breaks existing palettes, and you will have to re-set the colors.
We also changed when we reserve space for the palette in EEPROM: we used to do it as soon as possible, but that made it impossible to go from a firmware that does not use the plugin to one that does, and still have a compatible EEPROM layout. We now reserve space as late as possible. This breaks existing EEPROM layouts however.
### EEPROM-Keymap changed Focus commands
The [EEPROMKeymap](doc/plugin/EEPROM-Keymap.md) plugin was changed to treat built-in (default) and EEPROM-stored (custom) layers separately, because that's less surprising, and easier to work with from Chrysalis. The old `keymap.map` and `keymap.roLayers` commands are gone, the new `keymap.default` and `keymap.custom` commands should be used instead.
The [EEPROMKeymap](plugins/EEPROM-Keymap.md) plugin was changed to treat built-in (default) and EEPROM-stored (custom) layers separately, because that's less surprising, and easier to work with from Chrysalis. The old `keymap.map` and `keymap.roLayers` commands are gone, the new `keymap.default` and `keymap.custom` commands should be used instead.
### EEPROMSettings' version() setter has been deprecated
We're repurposing the `version` setting: instead of it being something end-users
can set, we'll be using it internally to track changes made to
[EEPROMSettings](doc/plugin/EEPROM-Settings.md) itself, with the goal of
[EEPROMSettings](plugins/EEPROM-Settings.md) itself, with the goal of
allowing external tools to aid in migrations. The setting wasn't widely used -
if at all -, which is why we chose to repurpose it instead of adding a new
field.
### Key masking has been deprecated
Key masking was a band-aid introduced to avoid accidentally sending unintended keys when key mapping changes between a key being pressed and released. Since the introduction of keymap caching, this is no longer necessary, as long as we can keep the mapping consistent. Users of key masking are encouraged to find ways to use the caching mechanism instead.
## Bugfixes
We fixed way too many issues to list here, so we're going to narrow it down to the most important, most visible ones.

@ -12,16 +12,15 @@ If any of this does not make sense to you, or you have trouble updating your .in
- [Bidirectional communication for plugins](#bidirectional-communication-for-plugins)
- [Consistent timing](#consistent-timing)
+ [Breaking changes](#breaking-changes)
- [Deprecation of the HID facade](#deprecation-of-the-hid-facade)
- [Implementation of type Key internally changed from C++ union to class](#implementation-of-type-key-internally-changed-from-union-to-class)
- [`LEDControl.paused` has been deprecated](#ledcontrolpaused-has-been-deprecated)
- [The `RxCy` macros and peeking into the keyswitch state](#the-rxcy-macros-and-peeking-into-the-keyswitch-state)
- [HostOS](#hostos)
- [MagicCombo](#magiccombo)
- [TypingBreaks](#typingbreaks)
- [Redial](#redial)
- [Key mapping has been deprecated](#key-mapping-has-been-deprecated)
+ [Deprecated APIs and their replacements](#deprecated-apis-and-their-replacements)
- [Class/global instance Kaleidoscope_/Kaleidoscope renamed to kaleidoscope::Runtime_/kaleidoscope::Runtime](#classglobal-instance-kaleidoscope_kaleidoscope-renamed-to-kaleidoscoperuntime_kaleidoscoperuntime)
- [Transition to linear indexing](#transition-to-linear-indexing)
- [Source code and namespace rearrangement](#source-code-and-namespace-rearrangement)
* [Removed APIs](#removed-apis)
@ -41,7 +40,7 @@ For end users, this doesn't come with any breaking changes. A few things have be
For those wishing to port Kaleidoscope to devices it doesn't support yet, the new API should make most things considerably easier. Please see the (work in progress) documentation in [doc/device-apis.md](doc/device-apis.md).
The old symbols and APIs will be removed by **2020-03-15**.
The old symbols and APIs are no longer available.
### New plugin API
@ -315,8 +314,14 @@ As a developer, one can continue using `millis()`, but migrating to `Kaleidoscop
## Breaking changes
### Deprecation of the HID facade
With the new Device APIs it became possible to replace the HID facade (the `kaleidoscope::hid` family of functions) with a driver. As such, the old APIs are deprecated, and will be removed by **2020-09-16**. Please use `Kaleidoscope.hid()` instead.
### Implementation of type Key internally changed from C++ union to class
The deprecated functions continue to work, but they will be removed by **2020-09-16**.
#### For end-users
This is a breaking change only if your code accesses the member `raw` of
@ -354,44 +359,6 @@ k.setKeyCode(Key_A.getKeyCode());
k.setFlags(Key_A.getFlags());
```
### `LEDControl.paused` has been deprecated
Wherever we used `LEDControl.paused`, we'll need to use one of
`LEDControl.disable()`, `LEDControl.enable()`, or `LEDControl.isEnabled()`
instead. `LEDControl.paused` will still compile, but will emit deprecation
warnings, and will be removed after **2020-03-15**.
Keep in mind that `.enable()` and `.disable()` do more than what `paused` did:
they will refresh and turn off LEDs too, respectively.
A few examples to show how to transition to the new APIs follow, old use first, new second.
```c++
if (someCondition) {
LEDControl.set_all_leds_to({0, 0, 0});
LEDControl.syncLeds();
LEDControl.paused = true;
} else if (someOtherCondition) {
LEDControl.paused = false;
LEDControl.refreshAll();
}
if (LEDControl.paused) {
// do things...
}
```
```c++
if (someCondition) {
LEDControl.disable();
} else if (someOtherCondition) {
LEDControl.enable();
}
if (!LEDControl.isEnabled()) {
// do things...
}
```
### The `RxCy` macros and peeking into the keyswitch state
The `RxCy` macros changed from being indexes into a per-hand bitmap to being an
@ -467,7 +434,7 @@ The new API is much shorter, and is inspired by the way the [Leader][leader]
plugin works: instead of having a list, and a dispatching function like
`magicComboActions`, we include the action method in the list too!
[leader]: doc/plugin/Leader.md
[leader]: plugins/Leader.md
We also don't make a difference between left- and right-hand anymore, you can
just list keys for either in the same list. This will be very handy for
@ -525,21 +492,15 @@ Storing the settable settings in EEPROM makes it depend on `Kaleidoscope-EEPROM-
Older versions of the plugin required one to set up `Key_Redial` manually, and let the plugin know about it via `Redial.key`. This is no longer required, as the plugin sets up the redial key itself. As such, `Redial.key` was removed, and `Key_Redial` is defined by the plugin itself. To upgrade, simply remove your definition of `Key_Redial` and the `Redial.key` assignment from your sketch.
## Deprecated APIs and their replacements
### Key masking has been deprecated
### Class/global instance Kaleidoscope_/Kaleidoscope renamed to kaleidoscope::Runtime_/kaleidoscope::Runtime
Key masking was a band-aid introduced to avoid accidentally sending unintended keys when key mapping changes between a key being pressed and released. Since the introduction of keymap caching, this is no longer necessary, as long as we can keep the mapping consistent. Users of key masking are encouraged to find ways to use the caching mechanism instead.
After the renaming, Kaleidoscope core should be using `kaleidoscope::Runtime`.
The former `Kaleidoscope` global symbol is to be used by sketches only - and
only because to not diverge too much from the Arduino naming style. Deprecated
symbols are scheduled for removal on **2020-03-15**.
As an example, if you had a key event handler that in some cases masked a key, it should now map it to `Key_NoKey` instead, until released.
### Transition to linear indexing
The masking API has been deprecated, and is scheduled to be removed after **2020-11-25**.
Row/col based indexing was replaced by linear indexing throughout the whole firmware. A compatibility layer of functions was introduced that allows
the firmware to remain backwards compatible, however, these functions are deprecated and will be removed in future versions of the firmware.
Also a new version of the onKeyswitchEvent-handler has been introduced. The old version is deprecated, and will be removed after **2020-03-15**.
## Deprecated APIs and their replacements
### Source code and namespace rearrangement
@ -548,29 +509,92 @@ With the move towards a monorepo-based source, some headers have moved to a new
The following headers and names have changed:
- `layers.h`, `key_defs_keymaps.h` and `macro_helpers.h` are obsolete, and should not be included in the first place, as `Kaleidoscope.h` will pull them in. In the rare case that one needs them, prefixing them with `kaleidoscope/` is the way to go. Of the various headers provided under the `kaleidoscope/` space, only `kaleidoscope/macro_helpers.h` should be included directly, and only by hardware plugins that can't pull `Kaleidoscope.h` in due to circular dependencies.
- `LED-Off.h`, provided by [LEDControl](doc/plugin/LEDControl.md) is obsolete, the `LEDOff` LED mode is automatically provided by `Kaleidoscope-LEDControl.h`. The `LED-Off.h` includes can be safely removed.
- `LED-Off.h`, provided by [LEDControl](plugins/LEDControl.md) is obsolete, the `LEDOff` LED mode is automatically provided by `Kaleidoscope-LEDControl.h`. The `LED-Off.h` includes can be safely removed.
- `LEDUtils.h` is automatically pulled in by `Kaleiodscope-LEDControl.h`, too, and there's no need to directly include it anymore.
- Plugins that implement LED modes should subclass `kaleidoscope::plugin::LEDMode` instead of `kaleidoscope::LEDMode`.
- [GhostInTheFirmware](doc/plugin/GhostInTheFirmware.md) had the `kaleidoscope::GhostInTheFirmware::GhostKey` type replaced by `kaleidoscope::plugin::GhostInTheFirmware::GhostKey`.
- [HostOS](doc/plugin/HostOS.md) no longer provides the `Kaleidoscope/HostOS-select.h` header, and there is no backwards compatibility header either.
- [Leader](doc/plugin/Leader.md) had the `kaleidoscope::Leader::dictionary_t` type replaced by `kaleidoscope::plugin::Leader::dictionary_t`.
- [LED-AlphaSquare](doc/plugin/LED-AlphaSquare.md) used to provide extra symbol graphics in the `kaleidoscope::alpha_square::symbols` namespace. This is now replaced by `kaleidoscope::plugin::alpha_square::symbols`.
- [LEDEffect-SolidColor](doc/plugin/LEDEffect-SolidColor.md) replaced the base class - `kaleidoscope::LEDSolidColor` - with `kaleidoscope::plugin::LEDSolidColor`.
- [Qukeys](doc/plugin/Qukeys.md) had the `kaleidoscope::Qukey` type replaced by `kaleidoscope::plugin::Qukey`.
- [ShapeShifter](doc/plugin/ShateShifter.md) had the `kaleidoscope::ShapeShifter::dictionary_t` type replaced by `kaleidoscope::plugin::ShapeShifter::dictionary_t`.
- [SpaceCadet](doc/plugin/SpaceCadet.md) had the `kaleidoscope::SpaceCadet::KeyBinding` type replaced by `kaleidoscope::plugin::SpaceCadet::KeyBinding`.
- [Syster](doc/plugin/Syster.md) had the `kaleidoscope::Syster::action_t` type replaced by `kaleidoscope::plugin::Syster::action_t`.
- [TapDance](doc/plugin/TapDance.md) had the `kaleidoscope::TapDance::ActionType` type replaced by `kaleidoscope::plugin::TapDance::ActionType`.
- [GhostInTheFirmware](plugins/GhostInTheFirmware.md) had the `kaleidoscope::GhostInTheFirmware::GhostKey` type replaced by `kaleidoscope::plugin::GhostInTheFirmware::GhostKey`.
- [HostOS](plugins/HostOS.md) no longer provides the `Kaleidoscope/HostOS-select.h` header, and there is no backwards compatibility header either.
- [Leader](plugins/Leader.md) had the `kaleidoscope::Leader::dictionary_t` type replaced by `kaleidoscope::plugin::Leader::dictionary_t`.
- [LED-AlphaSquare](plugins/LED-AlphaSquare.md) used to provide extra symbol graphics in the `kaleidoscope::alpha_square::symbols` namespace. This is now replaced by `kaleidoscope::plugin::alpha_square::symbols`.
- [LEDEffect-SolidColor](plugins/LEDEffect-SolidColor.md) replaced the base class - `kaleidoscope::LEDSolidColor` - with `kaleidoscope::plugin::LEDSolidColor`.
- [Qukeys](plugins/Qukeys.md) had the `kaleidoscope::Qukey` type replaced by `kaleidoscope::plugin::Qukey`.
- [ShapeShifter](plugins/ShateShifter.md) had the `kaleidoscope::ShapeShifter::dictionary_t` type replaced by `kaleidoscope::plugin::ShapeShifter::dictionary_t`.
- [SpaceCadet](plugins/SpaceCadet.md) had the `kaleidoscope::SpaceCadet::KeyBinding` type replaced by `kaleidoscope::plugin::SpaceCadet::KeyBinding`.
- [Syster](plugins/Syster.md) had the `kaleidoscope::Syster::action_t` type replaced by `kaleidoscope::plugin::Syster::action_t`.
- [TapDance](plugins/TapDance.md) had the `kaleidoscope::TapDance::ActionType` type replaced by `kaleidoscope::plugin::TapDance::ActionType`.
# Removed APIs
### Removed on 2020-06-16
#### The old device API
After the introduction of the new device API, the old APIs (`ROWS`, `COLS`, `LED_COUNT`, `KeyboardHardware`, the old `Hardware` base class, etc) were removed on **2020-06-16**.
#### `LEDControl.mode_add()`
Since March of 2019, this method has been deprecated, and turned into a no-op. While no removal date was posted at the time, after more than a year of deprecation, it has been removed on **2020-06-16**.
#### `LEDControl.paused`
Wherever we used `LEDControl.paused`, we'll need to use one of
`LEDControl.disable()`, `LEDControl.enable()`, or `LEDControl.isEnabled()`
instead. `LEDControl.paused` has been removed on **2020-06-16**.
Keep in mind that `.enable()` and `.disable()` do more than what `paused` did:
they will refresh and turn off LEDs too, respectively.
A few examples to show how to transition to the new APIs follow, old use first, new second.
```c++
if (someCondition) {
LEDControl.set_all_leds_to({0, 0, 0});
LEDControl.syncLeds();
LEDControl.paused = true;
} else if (someOtherCondition) {
LEDControl.paused = false;
LEDControl.refreshAll();
}
if (LEDControl.paused) {
// do things...
}
```
```c++
if (someCondition) {
LEDControl.disable();
} else if (someOtherCondition) {
LEDControl.enable();
}
if (!LEDControl.isEnabled()) {
// do things...
}
```
#### Class/global instance Kaleidoscope_/Kaleidoscope renamed to kaleidoscope::Runtime_/kaleidoscope::Runtime
After the renaming, Kaleidoscope core should be using `kaleidoscope::Runtime`.
The former `Kaleidoscope` global symbol is to be used by sketches only - and
only to not diverge too much from the Arduino naming style.
The deprecated `Kaleidoscope_` class has been removed on **2020-06-16**.
#### Transition to linear indexing
Row/col based indexing was replaced by linear indexing throughout the whole firmware. A compatibility layer of functions was introduced that allows the firmware to remain backwards compatible, however, these functions are deprecated and will be removed in future versions of the firmware.
Also a new version of the onKeyswitchEvent-handler has been introduced.
The deprecated row/col based indexing APIs have been removed on **2020-06-16**.
### Removed on 2020-01-06
### EEPROMKeymap mode
#### EEPROMKeymap mode
The [EEPROM-Keymap](doc/plugin/EEPROM-Keymap.md) plugin had its `setup()` method changed, the formerly optional `method` argument is now obsolete and unused. It can be safely removed.
The [EEPROM-Keymap](plugins/EEPROM-Keymap.md) plugin had its `setup()` method changed, the formerly optional `method` argument is now obsolete and unused. It can be safely removed.
## keymaps array and KEYMAPS and KEYMAPS_STACKED macros
##### keymaps array and KEYMAPS and KEYMAPS_STACKED macros
The `keymaps` array has been replaced with a `keymaps_linear` array. This new array treats each layer as a simple one dimensional array of keys, rather than a two dimensional array of arrays of rows. At the same time, the `KEYMAPS` and `KEYMAPS_STACKED` macros that were previously defined in each hardware implmentation class have been replaced with `PER_KEY_DATA` and `PER_KEY_DATA_STACKED` macros in each hardware class. This change should be invisible to users, but will require changes by any plugin that accessed the 'keymaps' variable directly.
@ -578,13 +602,13 @@ Code like `key.raw = pgm_read_word(&(keymaps[layer][row][col])); return key;` sh
### Removed on 2019-01-18
### Removal of Layer.defaultLayer
#### Removal of Layer.defaultLayer
The `Layer.defaultLayer()` method has been deprecated, because it wasn't widely used, nor tested well, and needlessly complicated the layering logic. If one wants to set a default layer, which the keyboard switches to when booting up, `EEPROMSettings.default_layer()` may be of use.
`Layer.defaultLayer` has since been removed.
### More clarity in Layer method names
#### More clarity in Layer method names
A number of methods on the `Layer` object have been renamed, to make their intent clearer:

@ -165,11 +165,21 @@ namespace kaleidoscope {
namespace device {
namespace imaginary {
ATMEGA32U4_KEYBOARD(
Keypad, Caterina,
ROW_PIN_LIST({ PIN_D0, PIN_D1 }),
COL_PIN_LIST({ PIN_C0, PIN_C1 })
);
struct KeypadProps : kaleidoscope::device::ATmega32U4KeyboardProps {
struct KeyScannerProps : public kaleidoscope::driver::keyscanner::ATmegaProps {
static constexpr uint8_t matrix_rows = 2;
static constexpr uint8_t matrix_columns = 2;
typedef MatrixAddr<matrix_rows, matrix_columns> KeyAddr;
static constexpr uint8_t matrix_row_pins[matrix_rows] = {PIN_D0, PIN_D1};
static constexpr uint8_t matrix_col_pins[matrix_columns] = {PIN_C0, PIN_C1};
};
typedef kaleidoscope::driver::keyscanner::ATmega<KeyScannerProps> KeyScanner;
typedef kaleidoscope::driver::bootloader::avr::Caterina BootLoader;
static constexpr const char *short_name = "imaginary-keypad";
};
class Keypad: public kaleidoscope::device::ATmega32U4Keyboard<KeypadProps> {};
#define PER_KEY_DATA(dflt, \
R0C0, R0C1, \
@ -180,7 +190,7 @@ ATMEGA32U4_KEYBOARD(
}
}
typedef kaleidoscope::device::imaginary::Keypad Device;
EXPORT_DEVICE(kaleidoscope::device::imaginary::Keypad);
}
#endif
@ -193,11 +203,41 @@ typedef kaleidoscope::device::imaginary::Keypad Device;
#include <Kaleidoscope.h>
// Here, we set up aliases to the device's KeyScanner and KeyScannerProps in the
// global namespace within the scope of this file. We'll use these aliases to
// simplify some template initialization code below.
using KeyScannerProps = typename kaleidoscope::device::imaginary::KeypadProps::KeyScannerProps;
using KeyScanner = typename kaleidoscope::device::imaginary::KeypadProps::KeyScanner;
namespace kaleidoscope {
namespace device {
namespace imaginary {
AVR_KEYSCANNER_BOILERPLATE
// `KeyScannerProps` here refers to the alias set up above. We do not need to
// prefix the `matrix_rows` and `matrix_columns` names within the array
// declaration, because those are resolved within the context of the class, so
// the `matrix_rows` in `KeyScannerProps::matrix_row_pins[matrix_rows]` gets
// resolved as `KeyScannerProps::matrix_rows`.
const uint8_t KeyScannerProps::matrix_rows;
const uint8_t KeyScannerProps::matrix_columns;
constexpr uint8_t KeyScannerProps::matrix_row_pins[matrix_rows];
constexpr uint8_t KeyScannerProps::matrix_col_pins[matrix_columns];
// `KeyScanner` here refers to the alias set up above, just like in the
// `KeyScannerProps` case above.
template<> KeyScanner::row_state_t KeyScanner::matrix_state_[KeyScannerProps::matrix_rows] = {};
// We set up the TIMER1 interrupt vector here. Due to dependency reasons, this
// cannot be in a header-only driver, and must be placed here.
//
// Timer1 is responsible for setting a property on the KeyScanner, which will
// tell it to do a scan. We use this to make sure that scans happen at roughly
// the intervals we want. We do the scan outside of the interrupt scope for
// practical reasons: guarding every codepath against interrupts that can be
// reached from the scan is far too tedious, for very little gain.
ISR(TIMER1_OVF_vect) {
Runtime.device().keyScanner().do_scan_ = true;
}
}
}

@ -0,0 +1,64 @@
# Build and install the latest firmware for your keyboard
# Select your keyboard
1. Open the 'Tools' menu, click on 'Board' and then click on the name of your keyboard. In the screenshot, we picked 'Keyboardio Model 01'. (You may have to scroll through a long list of other boards to get there.)
![](images/arduino-setup/select-board-in-menu.png)
2. Open the 'Tools' menu, click on "Port > ". If your keyboard is not already selected, click on it to select it. (If there is only one option such as "COM3" try it, it's almost certainly the correct port.)
![](images/arduino-setup/select-port.png)
Next step: [Install the latest firmware on your keyboard](#Install-latest-firmware)
# <a name="Install-latest-firmware" />Install the latest default firmware on your keyboard
To load the firmware, open the Arduino IDE's "File" menu, and click on the "Examples" submenu.
If you're using a Keyboardio Model 01, Scroll down to 'Model01-Firmware':
![](images/arduino-setup/select-model-01-firmware.png)
If you're using another keyboard, you should find it under Examples -> Kaleidoscope -> Devices -> (Your keyboard maker) -> (Your keyboard)
After you pick your example sketch, Arduino wil open a new window showing the sketch's source code above a black message log section and a green status message bar at the bottom. The message log displays detailed information about what Arduino is doing.
_**Note:** We recommend that you install the default firmware at least once before you start to make changes. This gives you a chance to ensure that the firmware update process works._
# Build the firmware
Click the check mark icon below "File" to build your firmware.
![](images/arduino-setup/verify-model-01-firmware.png)
If the firmware builds successfully, Arduino reports "Done Compiling" in the green status bar.
![](images/arduino-setup/verify-ok.png)
If something goes wrong, the status bar turns orange and displays an error message. Additionally, there may be text in the black message log with more details about the error. At this point, it may be helpful to expand the message log so that you can see a bit more about what's going on.
![](images/arduino-setup/verify-failed.png)
If you see errors, refer to [Getting help](Getting-help) for troubleshooting tips and useful resources.
# Install the firmware
If your keyboard has a programming interlock key, you'll need to hold it down now. On the Keyboardio Model 01, this is the `Prog` key. On the Keyboardio Atreus, this is the `Esc` key.
Without releasing that key, click on the "right arrow" button in the sketch window menu bar. This starts the firmware installation process.
![](images/arduino-setup/press-prog.png)
![](images/arduino-setup/press-prog-atreus.png)
![](images/arduino-setup/upload-sketch.png)
If the process is successful, Arduino will tell you that in the status area. Some keyboards may also use LEDs to report their results. For example, the Model 01's LED's flash red across the board as the firmware is installed, and then the "LED" key glows blue.
On Windows, you may also see the message "the device Model 01 is undergoing additional configuration."
If you have any trouble flashing your keyboard's firmware, check to see if the issue is addressed on the [Troubleshooting Firmware Upload Issues](https://github.com/keyboardio/Kaleidoscope/wiki/Troubleshooting-Firmware-Upload-Issues)

@ -12,132 +12,131 @@ Our style guide is based on the [Google C++ style guide][goog:c++-guide] which w
## Table of Contents
* [Background](#background)
* [Goals of the Style Guide](#goals-of-the-style-guide)
* [Library Guidelines](#library-guidelines)
* [Header Files](#header-files)
* [Self-contained Headers](#self-contained-headers)
* [Header Guards](#header-guards)
* [Forward Declarations](#forward-declarations)
* [Inline Functions](#inline-functions)
* [Names and Order of Includes](#names-and-order-of-includes)
* [Scoping](#scoping)
* [Namespaces](#namespaces)
* [Unnamed Namespaces and Static Variables](#unnamed-namespaces-and-static-variables)
* [Nonmember, Static Member, and Global Functions](#nonmember-static-member-and-global-functions)
* [Local Variables](#local-variables)
* [Static and Global Variables](#static-and-global-variables)
* [Classes](#classes)
* [Doing Work in Constructors](#doing-work-in-constructors)
* [Implicit Conversions](#implicit-conversions)
* [Copyable and Movable Types](#copyable-and-movable-types)
* [Structs vs. Classes](#structs-vs-classes)
* [Inheritance](#inheritance)
* [Multiple Inheritance](#multiple-inheritance)
* [Interfaces](#interfaces)
* [Operator Overloading](#operator-overloading)
* [Access Control](#access-control)
* [Declaration Order](#declaration-order)
* [Functions](#functions)
* [Parameter Ordering](#parameter-ordering)
* [Write Short Functions](#write-short-functions)
* [Reference Arguments](#reference-arguments)
* [Function Overloading](#function-overloading)
* [Default Arguments](#default-arguments)
* [Trailing Return Type Syntax](#trailing-return-type-syntax)
* [Google-specific magic](#google-specific-magic)
* [Ownership and Smart Pointers](#ownership-and-smart-pointers)
* [cpplint](#cpplint)
* [Other C++ Features](#other-c-features)
* [Rvalue References](#rvalue-references)
* [Friends](#friends)
* [Exceptions](#exceptions)
* [Run-Time Type Information (RTTI)](#run-time-type-information-rtti)
* [Casting](#casting)
* [Streams](#streams)
* [Preincrement and Predecrement](#preincrement-and-predecrement)
* [Use of const](#use-of-const)
* [Where to put the const](#where-to-put-the-const)
* [Use of constexpr](#use-of-constexpr)
* [Integer Types](#integer-types)
* [On Unsigned Integers](#on-unsigned-integers)
* [Preprocessor Macros](#preprocessor-macros)
* [0 and nullptr/NULL](#0-and-nullptrnull)
* [sizeof](#sizeof)
* [auto](#auto)
* [Braced Initializer List](#braced-initializer-list)
* [Lambda expressions](#lambda-expressions)
* [Template metaprogramming](#template-metaprogramming)
* [C++11](#c11)
* [Nonstandard Extensions](#nonstandard-extensions)
* [Aliases](#aliases)
* [Naming](#naming)
* [General Naming Rules](#general-naming-rules)
* [File Names](#file-names)
* [Type Names](#type-names)
* [Variable Names](#variable-names)
* [Common Variable Names](#common-variable-names)
* [Class Data Members](#class-data-members)
* [Struct Data Members](#struct-data-members)
* [Constant Names](#constant-names)
* [Function Names](#function-names)
* [Namespace Names](#namespace-names)
* [Enumerator Names](#enumerator-names)
* [Macro Names](#macro-names)
* [Exceptions to Naming Rules](#exceptions-to-naming-rules)
* [Comments](#comments)
* [Comment Style](#comment-style)
* [File Comments](#file-comments)
* [Legal Notice and Author Line](#legal-notice-and-author-line)
* [File Contents](#file-contents)
* [Class Comments](#class-comments)
* [Function Comments](#function-comments)
* [Function Declarations](#function-declarations)
* [Function Definitions](#function-definitions)
* [Variable Comments](#variable-comments)
* [Class Data Member Comments](#class-data-member-comments)
* [Global Variable Comments](#global-variable-comments)
* [Implementation Comments](#implementation-comments)
* [Explanatory Comments](#explanatory-comments)
* [Line Comments](#line-comments)
* [Function Argument Comments](#function-argument-comments)
* [Dont's](#donts)
* [Punctuation, Spelling and Grammar](#punctuation-spelling-and-grammar)
* [TODO Comments](#todo-comments)
* [Deprecation Comments](#deprecation-comments)
* [Formatting](#formatting)
* [Line Length](#line-length)
* [Non-ASCII Characters](#non-ascii-characters)
* [Spaces vs. Tabs](#spaces-vs-tabs)
* [Function Declarations and Definitions](#function-declarations-and-definitions)
* [Formatting Lambda Expressions](#formatting-lambda-expressions)
* [Function Calls](#function-calls)
* [Braced Initializer List Format](#braced-initializer-list-format)
* [Conditionals](#conditionals)
* [Loops and Switch Statements](#loops-and-switch-statements)
* [Pointer and Reference Expressions](#pointer-and-reference-expressions)
* [Boolean Expressions](#boolean-expressions)
* [Return Values](#return-values)
* [Variable and Array Initialization](#variable-and-array-initialization)
* [Preprocessor Directives](#preprocessor-directives)
* [Class Format](#class-format)
* [Constructor Initializer Lists](#constructor-initializer-lists)
* [Namespace Formatting](#namespace-formatting)
* [Horizontal Whitespace](#horizontal-whitespace)
* [General](#general)
* [Loops and Conditionals](#loops-and-conditionals)
* [Operators](#operators)
* [Templates and Casts](#templates-and-casts)
* [Vertical Whitespace](#vertical-whitespace)
* [Exceptions to the Rules](#exceptions-to-the-rules)
* [Existing Non-conformant Code](#existing-non-conformant-code)
* [Parting Words](#parting-words)
- [Kaleidoscope C++ Coding Style](#kaleidoscope-c-coding-style)
- [Important warning](#important-warning)
- [Table of Contents](#table-of-contents)
- [Background](#background)
- [Goals of the Style Guide](#goals-of-the-style-guide)
- [Library Guidelines](#library-guidelines)
- [Header Files](#header-files)
- [Self-contained Headers](#self-contained-headers)
- [Header Guards](#header-guards)
- [Forward Declarations](#forward-declarations)
- [Inline Functions](#inline-functions)
- [Names and Order of Includes](#names-and-order-of-includes)
- [Scoping](#scoping)
- [Namespaces](#namespaces)
- [Unnamed Namespaces and Static Variables](#unnamed-namespaces-and-static-variables)
- [Nonmember, Static Member, and Global Functions](#nonmember-static-member-and-global-functions)
- [Local Variables](#local-variables)
- [Static and Global Variables](#static-and-global-variables)
- [Classes](#classes)
- [Doing Work in Constructors](#doing-work-in-constructors)
- [Implicit Conversions](#implicit-conversions)
- [Copyable and Movable Types](#copyable-and-movable-types)
- [Structs vs. Classes](#structs-vs-classes)
- [Inheritance](#inheritance)
- [Multiple Inheritance](#multiple-inheritance)
- [Interfaces](#interfaces)
- [Operator Overloading](#operator-overloading)
- [Access Control](#access-control)
- [Declaration Order](#declaration-order)
- [Functions](#functions)
- [Parameter Ordering](#parameter-ordering)
- [Write Short Functions](#write-short-functions)
- [Reference Arguments](#reference-arguments)
- [Function Overloading](#function-overloading)
- [Default Arguments](#default-arguments)
- [Trailing Return Type Syntax](#trailing-return-type-syntax)
- [Google-Specific Magic](#google-specific-magic)
- [Ownership and Smart Pointers](#ownership-and-smart-pointers)
- [cpplint](#cpplint)
- [Other C++ Features](#other-c-features)
- [Rvalue References](#rvalue-references)
- [Friends](#friends)
- [Exceptions](#exceptions)
- [Run-Time Type Information (RTTI)](#run-time-type-information-rtti)
- [Casting](#casting)
- [Streams](#streams)
- [Preincrement and Predecrement](#preincrement-and-predecrement)
- [Use of const](#use-of-const)
- [Where to put the const](#where-to-put-the-const)
- [Use of constexpr](#use-of-constexpr)
- [Integer Types](#integer-types)
- [On Unsigned Integers](#on-unsigned-integers)
- [Preprocessor Macros](#preprocessor-macros)
- [0 and nullptr/NULL](#0-and-nullptrnull)
- [sizeof](#sizeof)
- [auto](#auto)
- [Braced Initializer List](#braced-initializer-list)
- [Lambda expressions](#lambda-expressions)
- [Naming](#naming)
- [General Naming Rules](#general-naming-rules)
- [File Names](#file-names)
- [Type Names](#type-names)
- [Variable Names](#variable-names)
- [Common Variable Names](#common-variable-names)
- [Class Data Members](#class-data-members)
- [Struct Data Members](#struct-data-members)
- [Constant Names](#constant-names)
- [Function Names](#function-names)
- [Namespace Names](#namespace-names)
- [Enumerator Names](#enumerator-names)
- [Macro Names](#macro-names)
- [Exceptions to Naming Rules](#exceptions-to-naming-rules)
- [Comments](#comments)
- [Comment Style](#comment-style)
- [File Comments](#file-comments)
- [Legal Notice and Author Line](#legal-notice-and-author-line)
- [File Contents](#file-contents)
- [Class Comments](#class-comments)
- [Function Comments](#function-comments)
- [Function Declarations](#function-declarations)
- [Function Definitions](#function-definitions)
- [Variable Comments](#variable-comments)
- [Class Data Member Comments](#class-data-member-comments)
- [Global Variable Comments](#global-variable-comments)
- [Implementation Comments](#implementation-comments)
- [Explanatory Comments](#explanatory-comments)
- [Line Comments](#line-comments)
- [Function Argument Comments](#function-argument-comments)
- [Don'ts](#donts)
- [Punctuation, Spelling and Grammar](#punctuation-spelling-and-grammar)
- [TODO Comments](#todo-comments)
- [Deprecation Comments](#deprecation-comments)
- [Formatting](#formatting)
- [Line Length](#line-length)
- [Non-ASCII Characters](#non-ascii-characters)
- [Spaces vs. Tabs](#spaces-vs-tabs)
- [Function Declarations and Definitions](#function-declarations-and-definitions)
- [Formatting Lambda Expressions](#formatting-lambda-expressions)
- [Function Calls](#function-calls)
- [Braced Initializer List Format](#braced-initializer-list-format)
- [Conditionals](#conditionals)
- [Loops and Switch Statements](#loops-and-switch-statements)
- [Pointer and Reference Expressions](#pointer-and-reference-expressions)
- [Boolean Expressions](#boolean-expressions)
- [Return Values](#return-values)
- [Variable and Array Initialization](#variable-and-array-initialization)
- [Preprocessor Directives](#preprocessor-directives)
- [Class Format](#class-format)
- [Constructor Initializer Lists](#constructor-initializer-lists)
- [Namespace Formatting](#namespace-formatting)
- [Horizontal Whitespace](#horizontal-whitespace)
- [General](#general)
- [Loops and Conditionals](#loops-and-conditionals)
- [Operators](#operators)
- [Templates and Casts](#templates-and-casts)
- [Vertical Whitespace](#vertical-whitespace)
- [Exceptions to the Rules](#exceptions-to-the-rules)
- [Existing Non-conformant Code](#existing-non-conformant-code)
- [Parting Words](#parting-words)
## Background
<!-- TODO: Review this section, the Google-specifc wording was replaced with something more appropriate -->
C++ is the language of Arduino libraries, and as a consequence, in which Kaleidoscope was written in. As every C++ programmer knows, the language has many powerful features, but this power brings with it complexity, which in turn can make code more bug-prone and harder to read and maintain.
C++ is the language of Arduino libraries, and as a consequence, the language in which Kaleidoscope was written. As every C++ programmer knows, the language has many powerful features, but this power brings with it complexity, which in turn can make code more bug-prone and harder to read and to maintain.
The goal of this guide is to manage this complexity by describing in detail the dos and don'ts of writing C++ code. These rules exist to keep the code base manageable while still allowing coders to use C++ language features productively.
@ -157,7 +156,7 @@ The goals of the style guide as we currently see them are as follows:
<dt>Style rules should pull their weight</dt>
<dd>
The benefit of a style rule must be large enough to justify asking all of our engineers to remember it. The benefit is measured relative to the codebase we would get without the rule, so a rule against a very harmful practice may still have a small benefit if people are unlikely to do it anyway. This principle mostly explains the rules we don't have, rather than the rules we do: for example, `goto` contravenes many of the following principles, but is already vanishingly rare, so the Style Guide doesn't discuss it.
The benefit of a style rule must be large enough to justify asking all of our engineers to remember it. The benefit is measured relative to the codebase we would get without the rule, so a rule against a very harmful practice may still have a small benefit if people are unlikely to do it anyway. This principle mostly explains the rules we don't have, rather than the rules we do: for example, <code>goto</code> contravenes many of the following principles, but is already vanishingly rare, so the Style Guide doesn't discuss it.
</dd>
<!-- TODO: Review the Kaleidoscope/Arduino bits -->
@ -185,7 +184,7 @@ C++ has features that are more surprising or dangerous than one might think at a
<!-- TODO: Review the wording: changed to mention that our target are not necessarily programmers. -->
<dt>Avoid constructs that our average C++ programmer would find tricky or hard to maintain</dt>
<dd>
C++ has features that may not be generally appropriate because of the complexity they introduce to the code. In widely used code, it may be more acceptable to use trickier language constructs, because any benefits of more complex implementation are multiplied widely by usage, and the cost in understanding the complexity does not need to be paid again when working with new portions of the codebase. When in doubt, waivers to rules of this type can be sought by asking your project leads. This is specifically important for our codebase because code ownership and team membership changes over time: even if everyone that works with some piece of code currently understands it, such understanding is not guaranteed to hold a few years from now. Not to mention that our target audience are average people, not average C++ programmers.
C++ has features that may not be generally appropriate because of the complexity they introduce to the code. In widely used code, it may be more acceptable to use trickier language constructs, because any benefits of more complex implementation are multiplied widely by usage, and the cost in understanding the complexity does not need to be paid again when working with new portions of the codebase. When in doubt, waivers to rules of this type can be sought by asking [the Kaleidoscope maintainers](maintainers.md). This is specifically important for our codebase because code ownership changes over time: even if everyone that works with some piece of code currently understands it, such understanding is not guaranteed to hold a few years from now. Not to mention that our target audience are average people, not necessarily professional C++ programmers.
</dd>
<!-- TODO: Un-googlified... -->
@ -200,14 +199,17 @@ Performance optimizations can sometimes be necessary and appropriate, even when
</dl>
The intent of this document is to provide maximal guidance with reasonable restriction. As always, common sense and good taste should prevail. By this we specifically refer to the established conventions of the entire community (both Kaleidoscope and Arduino communities), not just your personal preferences or those of your team. Be skeptical about and reluctant to use clever or unusual constructs: the absence of a prohibition is not the same as a license to proceed. Use your judgment, and if you are unsure, please don't hesitate to ask, to get additional input.
The intent of this document is to provide maximal guidance with reasonable restriction. As always, common sense and good taste should prevail. By this we specifically refer to the established conventions of the entire community (both Kaleidoscope and Arduino communities), not just personal preferences. Be skeptical about and reluctant to use clever or unusual constructs: the absence of a prohibition is not the same as a license to proceed. Use your judgment, and if you are unsure, please don't hesitate to ask (e.g. on [Discourse][keyboardio:discourse] or on [Discord][keyboardio:discord]), to get additional input.
[keyboardio:discourse]: https://community.keyboard.io/
[keyboardio:discord]: https://keyboard.io/discord-invite
## Library Guidelines
<!-- TODO: This is a whole new section! -->
Before looking at the coding style guidelines, we must first talk about libraries. Every Kaleidoscope plugin is also an Arduino library. The core firmware is an Arduino library too. As such, libraries should follow the [Arduino library specification][arduino:library-spec] (revision 2.1 or later), with a few additional recommendations:
[arduino:library-spec]: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification
[arduino:library-spec]: https://arduino.github.io/arduino-cli/library-specification/
<dl>
<dt>Use Semantic Versioning for versioning</dt>
@ -222,7 +224,7 @@ It does not matter much what hardware the example is for, as long as there is on
<dt>Be mindful of the documentation</dt>
<dd>
Documenting the interfaces of the library, how to use it, its dependencies, in a way that is meaningful for a novice user is a very strong recommendation. The `README.md` in a library should target a novice audience. Would one want or need to document parts of the code that is only meaningful for more advanced programmers, do so in the code.
Documenting the interfaces of the library, how to use it, and its dependencies, in a way that is meaningful for a novice user is a very strong recommendation. The <code>README.md</code> in a library should target a novice audience. Should one want or need to document parts of the code that is only meaningful for more advanced programmers, do so in the code.
</dd>
<dt>Use the tools provided in Kaleidoscope-Plugin</dt>
@ -246,7 +248,7 @@ The following rules will guide you through the various pitfalls of using header
All header files should be self-contained. Users and refactoring tools should not have to adhere to special conditions to include the header. Specifically, a header should have [header guards](#header-guards) and include all other headers it needs.
Prefer placing the definitions for template and inline functions in the same file as their declarations. The definitions of these constructs must be included into every `.cpp` file that uses them, or the program may fail to link in some build configurations. If declarations and definitions are in different files, including the former should transitively include the latter. Do not move these definitions to separately included header files (`-inl.h`).
Prefer placing the definitions for template and inline functions in the same file as their declarations. The definitions of these constructs must be included into every `.cpp` file that uses them, or the program may fail to link in some build configurations. If declarations and definitions are in different files, including the former should transitively include the latter. Do not move these definitions to separately included header files (e.g. `-inl.h` files).
As an exception, a template that is explicitly instantiated for all relevant sets of template arguments, or that is a private implementation detail of a class, is allowed to be defined in the one and only `.cpp` file that instantiates the template.
@ -283,7 +285,7 @@ A *"forward declaration"* is a declaration of a class, function, or template wit
* When using a function declared in a header file, always `#include` that header.
* When using a class template, prefer to `#include` its header file.
Please see [Names and Order of Includes](#names-and-order-of-includes) for rules about when to #include a header.
Please see [Names and Order of Includes](#names-and-order-of-includes) for rules about when to `#include` a header.
### Inline Functions
@ -328,20 +330,20 @@ If there is more than one header, they should be listed as descendants of the pr
Having more than one level of subdirectories is not recommended.
In `dir/foo.cpp` or `dir/foo_test.cc`, whose main purpose is to implement or test the stuff in `dir2/foo2.h`, order your includes as follows:
In `dir/foo.cpp` or `dir/foo_test.cpp`, whose main purpose is to implement or test the stuff in `dir2/foo2.h`, order your includes as follows:
1. `dir2/foo2.h`
2. Arduino libraries.
3. Other libraries' `.h` files.
4. Your project's `.h` files.
With the preferred ordering, if `dir2/foo2.h` omits any necessary includes, the build of `dir/foo.cpp` or `dir/foo_test.cpp` will break. Thus, this rule ensures that build breaks show up first for the people working on these files, not for innocent people in other packages.
With the preferred ordering, if `dir2/foo2.h` omits any necessary includes, the build of `dir/foo.cpp` or `dir/foo_test.cpp` will break. Thus, this rule ensures that build breakages show up first for the people working on these files, not for innocent people in other packages.
`dir/foo.cc` and `dir2/foo2.h` are usually in the same directory (e.g. `Kaleidoscope/Something_test.cpp` and `Kaleidoscope/Something.h`), but may sometimes be in different directories too.
Within each section the includes should be ordered alphabetically.
You should include all the headers that define the symbols you rely upon, except in the unusual case of [forward declarations](#forward-declarations) . If you rely on symbols from `bar.h`, don't count on the fact that you included `foo.h` which (currently) includes `bar.h`: include `bar.h` yourself, unless `foo.h` explicitly demonstrates its intent to provide you the symbols of `bar.h`. However, any includes present in the related header do not need to be included again in the related `cc` (i.e., `foo.cc` can rely on `foo.h`'s includes).
You should include all the headers that define the symbols you rely upon, except in the unusual case of [forward declarations](#forward-declarations). If you rely on symbols from `bar.h`, don't count on the fact that you included `foo.h` which (currently) includes `bar.h`: include `bar.h` yourself, unless `foo.h` explicitly demonstrates its intent to provide you the symbols of `bar.h`. However, any includes present in the related header do not need to be included again in the related `cc` (i.e., `foo.cc` can rely on `foo.h`'s includes).
For example, the includes in `Kaleidoscope-Something/src/Kaleidoscope/Something.cpp` might look like this:
@ -362,11 +364,11 @@ Sometimes, system-specific code needs conditional includes. Such code can put co
#include "Kaleidoscope.h"
#if defined(ARDUINO_AVR_MODEL01)
#include "Kaleidoscope/Something-Model01.h"
#include "Kaleidoscope/Something-AVR-Model01.h"
#endif
#if defined(ARDUINO_AVR_SHORTCUT)
#include "Kaleidoscope/Something-Shortcut.h"
#include "Kaleidoscope/Something-AVR-Shortcut.h"
#endif
```
@ -414,7 +416,7 @@ The expressions `X::Y::foo()` and `X::foo()` are interchangeable. Inline namespa
**Cons**
Namespaces can be confusing, because they complicate the mechanics of figuring out what definition a name refers to.
Namespaces can be confusing, because they complicate the mechanics of figuring out to what definition a name refers.
Inline namespaces, in particular, can be confusing because names aren't actually restricted to the namespace where they are declared. They are only useful as part of some larger versioning policy.
@ -513,7 +515,7 @@ All declarations can be given internal linkage by placing them in unnamed namesp
**Decision**
Use of internal linkage in `.cc` files is encouraged for all code that does not need to be referenced elsewhere. Do not use internal linkage in `.h` files.
Use of internal linkage in `.cpp` files is encouraged for all code that does not need to be referenced elsewhere. Do not use internal linkage in `.h` files.
Format unnamed namespaces like named namespaces. In the terminating comment, leave the namespace name empty:
@ -638,7 +640,7 @@ One way to alleviate the destructor problem is to terminate the program by calli
As a result we only allow static variables to contain POD data. This rule completely disallows `std::vector` (use C arrays instead), or `string` (use `const char []`).
If you need a static or global variable of a class type, consider initializing a pointer (which will never be freed), from either your main() function or from pthread_once(). Note that this must be a raw pointer, not a "smart" pointer, since the smart pointer's destructor will have the order-of-destructor issue that we are trying to avoid.
If you need a static or global variable of a class type, consider initializing a pointer (which will never be freed), from either your `main()` function or from `pthread_once()`. Note that this must be a raw pointer, not a "smart" pointer, since the smart pointer's destructor will have the order-of-destructor issue that we are trying to avoid.
## Classes
@ -716,7 +718,7 @@ This kind of code isn't technically an implicit conversion, but the language tre
**Decision**
Type conversion operators, and constructors that are callable with a single argument, must be marked `explicit` in the class definition. As an exception, copy and move constructors should not be `explicit`, since they do not perform type conversion. Implicit conversions can sometimes be necessary and appropriate for types that are designed to transparently wrap other types. In that case, contact your project leads to request a waiver of this rule.
Type conversion operators, and constructors that are callable with a single argument, must be marked `explicit` in the class definition. As an exception, copy and move constructors should not be `explicit`, since they do not perform type conversion. Implicit conversions can sometimes be necessary and appropriate for types that are designed to transparently wrap other types. In that case, contact the [Kaleidoscope maintainers](maintainers.md) to request a waiver of this rule.
Constructors that cannot be called with a single argument should usually omit `explicit`. Constructors that take a single `std::initializer_list` parameter should also omit `explicit`, in order to support copy-initialization (e.g. `MyType m = {1, 2};`).
@ -785,7 +787,7 @@ MyClass& operator=(const MyClass&) = delete;
The `struct` and `class` keywords behave almost identically in C++. We add our own semantic meanings to each keyword, so you should use the appropriate keyword for the data-type you're defining.
`structs` should be used for passive objects that carry data, and may have associated constants, but lack any functionality other than access/setting the data members. The accessing/setting of fields is done by directly accessing the fields rather than through method invocations. Methods should not provide behavior but should only be used to set up the data members, e.g., constructor, destructor, `Initialize()`, `Reset()`, `Validate()`.
`struct`s should be used for passive objects that carry data, and may have associated constants, but lack any functionality other than access/setting the data members. The accessing/setting of fields is done by directly accessing the fields rather than through method invocations. Methods should not provide behavior but should only be used to set up the data members, e.g., constructor, destructor, `Initialize()`, `Reset()`, `Validate()`.
If more functionality is required, a `class` is more appropriate. If in doubt, make it a `class`.
@ -799,7 +801,7 @@ Note that member variables in structs and classes have [different naming rules](
**Definition**
When a sub-class inherits from a base class, it includes the definitions of all the data and operations that the parent base class defines. In practice, inheritance is used in two major ways in C++: implementation inheritance, in which actual code is inherited by the child, and [interface inheritance](#interfaces) , in which only method names are inherited.
When a sub-class inherits from a base class, it includes the definitions of all the data and operations that the base class defines. In practice, inheritance is used in two major ways in C++: implementation inheritance, in which actual code is inherited by the child, and [interface inheritance](#interfaces), in which only method names are inherited.
**Pros**
@ -2535,10 +2537,10 @@ auto x_plus_n = [&x](int n) -> int { return x + n; }
Short lambdas may be written inline as function arguments.
```c++
std::set<int> blacklist = {7, 8, 9};
std::set<int> skip_list = {7, 8, 9};
std::vector<int> digits = {3, 9, 1, 8, 4, 7, 1};
digits.erase(std::remove_if(digits.begin(), digits.end(), [&blacklist](int i) {
return blacklist.find(i) != blacklist.end();
digits.erase(std::remove_if(digits.begin(), digits.end(), [&skip_list](int i) {
return skip_list.find(i) != skip_list.end();
}),
digits.end());
```

@ -0,0 +1,11 @@
# Design philosophy
Kaleidoscope should, in order:
1) Work well as a keyboard
2) Be compatible with real hardware
3) Be compatible with the spec
4) Be easy to read and understand
5) Be easy to modify and customize
Our code indentation style is managed with 'make astyle.' For code we 'own', there should be an astyle target in the Makefile. For third party code we use and expect to update (ever), we try not to mess with the upstream house style.

@ -7,6 +7,10 @@ It is, as yet, incredibly incomplete.
Entries should be included in dictionary order. When describing an identifier of any kind from the codebase, it should be
written using identical capitalization to its use in the code and surrounded by backticks: `identifierName`
## Firmware Terminology
These terms commonly arise when discussing the firmware.
### Cycle
The `loop` method in one's sketch file is the heart of the firmware. It runs -
@ -40,3 +44,54 @@ A point where the core firmware calls [event handlers](#event-handler), allowing
An Arduino library prepared to work with Kaleidoscope. They implement methods
from the `kaleidoscope::Plugin` (usually a subset of them). See [event
handlers](#event-handler) above for a list of methods.
## Testing
These terms arise when discussing the testing framworks and related tests.
### Sim Harness
An abstraction used in testing to inject events into or invoke actions on the
simulated firmware. This abstraction comprises half of the interface to the
[test simulator](#test-simulator).
### Sim State
An abstraction used in testing to encapsulate, snapshot, and examine firmware
state. This abstraction comprises half of the interface to the [test
simulator](#test-simulator).
### Test
An indivial assertion or expectation that must hold for a [test
case](#test-case) to pass.
### Test Case
An indivual `TEST*` macro invocation. Its body consists of one or [tests](#test)
and optionally other code, e.g. to invoke the [test harness](#test-harness).
Note that gtest uses the non-standard term _Test_ for what we call a [Test
Case](#test-case).
### Test File
An individual file containing one or more [test suites](#test-suite).
### Test Fixture
A class comprising setup, teardown, and other code and common state to make
writing [test cases](#test-case) easieer. A fresh object of the fixture class
associated with a [test suite](#test-suite) is constructed for each run of each
[teset case](#test-case) in the [test suite](#test-suite).
### Test Simulator
An abstraction wrapping a virtual firmware build that allows performing
actions against the virtual firmware and reading state out of the virtual
firmware. The interface to the test simular is comprised of the [sim
harness](#sim-harness) and the [sim state](#sim-state).
### Test Suite
A collection of related [test cases](#test-case), optionally with an associated
[test fixture](#test-fixture).

@ -0,0 +1,9 @@
<!-- -*- mode: markdown; fill-column: 8192 -*- -->
# Kaleidoscope Maintainers
We consider pull requests to the Kaleidoscope GitHub repo.
- [obra](https://github.com/obra)
- [noseglasses](https://github.com/noseglasses)
- [algernon](https://github.com/algernon)

@ -0,0 +1,97 @@
# Release testing
Before a new release of Kaleidoscope, the following test process should be run through on all supported operating systems.
(As of August 2017, this whole thing really applies to Model01-Firmware, but we hope to generalize it to Kaleidoscope)
# Tested operating systems
* The latest stable Ubuntu Linux release running X11. (We _should_ eventually be testing both X11 and Wayland)
* The latest stable release of macOS
* An older Mac OS X release TBD. (There were major USB stack changes in 10.9 or so)
* Windows 10
* Windows 7
* The current release of ChromeOS
* A currentish android tablet that supports USB Host
* an iOS device (once we fix the usb connection issue to limit power draw)
# Test process
## Basic testing
1. Plug the keyboard in
1. Make sure the host OS doesn't throw an error
1. Make sure the LED in the top left doesn't glow red
1. Make sure the LED in the top-right corner of the left side breathes blue for ~10s
1. Bring up some sort of notepad app or text editor
## Basic testing, part 2
1. Test typing of shifted and unshifted letters and numbers with and without key repeat
1. Test typing of fn-shifted characters: []{}|\ with and without key repeat
1. Test that 'Any' key generates a random letter or number and that key repeat works
1. Test fn-hjkl to move the cursor
1. Test Fn-WASD to move the mouse
1. Test Fn-RFV for the three mouse buttons
1. Test Fn-BGTabEsc for mouse warp
1. Test that LeftFn+RightFn + hjkl move the cursor
1. Verify that leftfn+rightfn do not light up the numpad
## NKRO
1. Open the platform's native key event viewer
(If not available, visit https://www.microsoft.com/appliedsciences/KeyboardGhostingDemo.mspx in a browser)
1. Press as many keys as your fingers will let you
1. Verify that the keymap reports all the keys you're pressing
## Test media keys
1. Fn-Any: previous track
1. Fn-Y: next-track
1. Fn-Enter: play/pause
1. Fn-Butterfly: Windows 'menu' key
1. Fn-n: mute
1. Fn-m: volume down
1. Fn-,: volume up
## Test numlock
1. Tap "Num"
1. Verify that the numpad lights up red
1. Verify that the num key is breathing blue
1. Verify that numpad keys generate numbers
1. Tap the Num key
1. Verify that the numpad keys stop being lit up
1 Verify that 'jkl' don't generate numbers.
## Test LED Effects
1. Tap the LED key
1. Verify that there is a rainbow effect
1. Tap the LED key a few more times and verify that other LED effects show up
1. Verify that you can still type.
## Second connection
1. Unplug the keyboard
1. Plug the keyboard back in
1. Make sure you can still type
## Programming
1. If the OS has a way to show serial port devices, verify that the keyboard's serial port shows up.
1. If you can run stty, as you can on linux and macos, make sure you can tickle the serial port at 1200 bps.
Linux: stty -F /dev/ttyACM0 1200
Mac:
1. If you tickle the serial port without holding down the prog key, verify that the Prog key does not light up red
1. If you hold down the prog key before tickling the serial port, verify that the Prog key's LED lights up red.
1. Unplug the keyboard
1. While holding down prog, plug the keyboard in
1. Verify that the prog key is glowing red.
1. Unplug the keyboard
1. Plug the keyboard in
1. Verify that the prog key is not glowing red.
# If the current platform supports the Arduino IDE (Win/Lin/Mac)
1. use the Arduino IDE to reflash the current version of the software.
1. Verify that you can type a few keys
1. Verify that the LED key toggles between LED effects

@ -0,0 +1,56 @@
# Automated Testing
## Testing with gtest/gmock
Before feature requests or bug fixes can be merged into master, the folowing
steps should be taken:
- Create a new test suite named after the issue, e.g. `Issue840`.
- Add a test case named `Reproduces` that reproduces the bug. It should fail if
the bug is present and pass if the bug is fixed.
- Merge the proposed fix into a temporary testing branch.
- The reproduction test should fail.
- Add a test called "HasNotRegresed" that detects a potential regression.
It should pass with the fix and fail before the fix.
- Comment out and keep the `Reproduces` test case as documentation.
For an example, see keyboardio:Kaleidoscope/tests/issue_840.
### Adding a New Test Case
For general information on writing test with gtest/gmock see [gtest
docs](https://github.com/google/googletest/tree/master/googletest/docs) and
[gmock docs](https://github.com/google/googletest/tree/master/googlemock/docs).
1. Create a new test file, if appropriate.
1. Choose a new test suite name and create a new test fixture, if appropriate.
1. Write your test case.
The final include in any test file should be `#include
"testing/setup-googletest.h"` which should be followed by the macro
invocation `SETUP_GOOGLETEST()`. This will take care of including headers
commonly used in tests in addtion to gtest and gmock headers.
Any test fixtures should inherit from `VirtualDeviceTest` which wraps the test
sim APIs and provides common setup and teardown functionality. The appropriate
header is already imported by `setup-googletest.h`
### Test Infrastructure
If you need to modify or extend test infrastructure to support your use case,
it can currently be found under `keyboardio:Kaleidoscope/testing`.
### Style
TODO(obra): Fill out this section to your liking.
You can see samples of the desired test style in the [example tests](#examples).
### Examples
All existing tests are examples and may be found under
`keyboardio:Kaleidoscope/tests`.
## Testing with Aglais/Papilio
TODO(obra): Write (or delegate the writing of) this section.

@ -0,0 +1,99 @@
# Release testing
Before a new release of Kaleidoscope, the following test process should be run through on all supported operating systems.
Always run all of the [automated tests](automated-testing.md) to verify there are no regressions.
(As of August 2017, this whole thing really applies to Model01-Firmware, but we hope to generalize it to Kaleidoscope)
# Tested operating systems
* The latest stable Ubuntu Linux release running X11. (We _should_ eventually be testing both X11 and Wayland)
* The latest stable release of macOS
* An older Mac OS X release TBD. (There were major USB stack changes in 10.9 or so)
* Windows 10
* Windows 7
* The current release of ChromeOS
* A currentish android tablet that supports USB Host
* an iOS device (once we fix the usb connection issue to limit power draw)
# Test process
## Basic testing
1. Plug the keyboard in
1. Make sure the host OS doesn't throw an error
1. Make sure the LED in the top left doesn't glow red
1. Make sure the LED in the top-right corner of the left side breathes blue for ~10s
1. Bring up some sort of notepad app or text editor
## Basic testing, part 2
1. Test typing of shifted and unshifted letters and numbers with and without key repeat
1. Test typing of fn-shifted characters: []{}|\ with and without key repeat
1. Test that 'Any' key generates a random letter or number and that key repeat works
1. Test fn-hjkl to move the cursor
1. Test Fn-WASD to move the mouse
1. Test Fn-RFV for the three mouse buttons
1. Test Fn-BGTabEsc for mouse warp
1. Test that LeftFn+RightFn + hjkl move the cursor
1. Verify that leftfn+rightfn do not light up the numpad
## NKRO
1. Open the platform's native key event viewer
(If not available, visit https://www.microsoft.com/appliedsciences/KeyboardGhostingDemo.mspx in a browser)
1. Press as many keys as your fingers will let you
1. Verify that the keymap reports all the keys you're pressing
## Test media keys
1. Fn-Any: previous track
1. Fn-Y: next-track
1. Fn-Enter: play/pause
1. Fn-Butterfly: Windows 'menu' key
1. Fn-n: mute
1. Fn-m: volume down
1. Fn-,: volume up
## Test numlock
1. Tap "Num"
1. Verify that the numpad lights up red
1. Verify that the num key is breathing blue
1. Verify that numpad keys generate numbers
1. Tap the Num key
1. Verify that the numpad keys stop being lit up
1 Verify that 'jkl' don't generate numbers.
## Test LED Effects
1. Tap the LED key
1. Verify that there is a rainbow effect
1. Tap the LED key a few more times and verify that other LED effects show up
1. Verify that you can still type.
## Second connection
1. Unplug the keyboard
1. Plug the keyboard back in
1. Make sure you can still type
## Programming
1. If the OS has a way to show serial port devices, verify that the keyboard's serial port shows up.
1. If you can run stty, as you can on linux and macos, make sure you can tickle the serial port at 1200 bps.
Linux: stty -F /dev/ttyACM0 1200
Mac:
1. If you tickle the serial port without holding down the prog key, verify that the Prog key does not light up red
1. If you hold down the prog key before tickling the serial port, verify that the Prog key's LED lights up red.
1. Unplug the keyboard
1. While holding down prog, plug the keyboard in
1. Verify that the prog key is glowing red.
1. Unplug the keyboard
1. Plug the keyboard in
1. Verify that the prog key is not glowing red.
# If the current platform supports the Arduino IDE (Win/Lin/Mac)
1. use the Arduino IDE to reflash the current version of the software.
1. Verify that you can type a few keys
1. Verify that the LED key toggles between LED effects

@ -32,8 +32,8 @@ author = 'Keyboardio & Friends'
extensions = [
#'breathe',
#'exhale',
'recommonmark'
'recommonmark',
'sphinx_markdown_tables'
]
extensions.append('copy-examples')
@ -56,11 +56,11 @@ exhale_args = {
"rootFileTitle": "Kaleidoscope",
"doxygenStripFromPath": "..",
# Suggested optional arguments
"createTreeView": False,
"createTreeView": True,
# TIP: if using the sphinx-bootstrap-theme, you need
# "treeViewIsBootstrap": True,
"exhaleExecutesDoxygen": True,
"exhaleDoxygenStdin": "INPUT = ../src",
"exhaleUseDoxyfile": True,
"verboseBuild": True
}
@ -70,6 +70,10 @@ primary_domain = 'cpp'
# Tell sphinx what the pygments highlight language should be.
highlight_language = 'cpp'
cpp_id_attributes = ["aligned","packed","weak","always_inline","noinline","no-unroll-loops","__attribute__((optimize(3)))"]
cpp_paren_attributes = ["optimize","__aligned__","section","deprecated"]
source_suffix = {
'.rst': 'restructuredtext',
'.txt': 'restructuredtext',
@ -91,6 +95,22 @@ exclude_patterns = ['_build', '_sphinx', 'Thumbs.db', '.DS_Store', 'etc', 'requi
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme_options = {
'logo_only': False,
'display_version': True,
'prev_next_buttons_location': 'bottom',
'style_external_links': False,
'vcs_pageview_mode': '',
'style_nav_header_background': 'white',
# Toc options
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 8,
'includehidden': False,
'titles_only': True
}
#
# on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org

@ -0,0 +1,125 @@
# Core plugin overview
This is an annotated list of some of Kaleidoscope's most important core plugins. You may also want to consult the [automatically generated list of all plugins bundled with Kaleidoscope](../plugin_list).
You can find a list of hird-party plugins not distributed as part of Kaleidoscope at https://community.keyboard.io/c/programming/Discuss-Plugins-one-thread-per-plugin
## EEPROM-Keymap
[EEPROM-Keymap Documentation](../plugins/EEPROM-Keymap.md)
While keyboards usually ship with a keymap programmed in, to be able to change that keymap, without flashing new firmware, we need a way to place the keymap into a place we can update at run-time, and which persists across reboots. Fortunately, we have a bit of EEPROM on the keyboard, and can use it to store either the full keymap (and saving space in the firmware then), or store an overlay there. In the latter case, whenever there is a non-transparent key on the overlay, we will use that instead of the keyboard default.
In short, this plugin allows us to change our keymaps, without having to compile and flash new firmware. It does so through the use of the Focus plugin.
## Escape-OneShot
[Escape-OneShot Documentation](../plugins/Escape-OneShot.md)
Turn the Esc key into a special key, that can cancel any active OneShot effect - or act as the normal Esc key if none are active. For those times when one accidentally presses a one-shot key, or change their minds.
## KeyLogger
[KeyLogger Documentation](../plugins/KeyLogger.md)
The KeyLogger plugin, as the name suggests, implements a key logger for the Kaleidoscope firmware. It logs the row and column of every key press and release, along with the event, and the layer number, in a format that is reasonably easy to parse, to the Serial interface.
**A word of warning**: Having a key logger is as dangerous as it sounds. Anyone who can read the serial events from the keyboard, will know exactly what keys you press, and when. Unless you know what you are doing, and can secure your keyboard, do not enable this plugin.
## Leader
[Leader Documentation](../plugins/Leader.md)
Leader keys are a kind of key where when they are tapped, all following keys are swallowed, until the plugin finds a matching sequence in the dictionary, it times out, or fails to find any possibilities. When a sequence is found, the corresponding action is executed, but the processing still continues. If any key is pressed that is not the continuation of the existing sequence, processing aborts, and the key is handled normally.
This behaviour is best described with an example. Suppose we want a behaviour where ``LEAD u`` starts unicode input mode, and ``LEAD u h e a r t`` should result in a heart symbol being input, and we want ``LEAD u 0 0 e 9 SPC`` to input é, and any other hex code that follows ``LEAD u``, should be handled as-is, and passed to the host. Obviously, we can't have all of this in a dictionary.
So we put ``LEAD u`` and ``LEAD u h e a r t`` in the dictionary only. The first will start unicode input mode, the second will type in the magic sequence that results in the symbol, and then aborts the leader sequence processing. With this setup, if we type ``LEAD u 0``, then ``LEAD u`` will be handled first, and start unicode input mode. Then, at the 0, the plugin notices it is not part of any sequence, so aborts leader processing, and passes the key on as-is, and it ends up being sent to the host. Thus, we covered all the cases of our scenario!
## Macros
[Macros Documentation](../plugins/Macros.md)
Macros are a standard feature on many keyboards and powered ones are no exceptions. Macros are a way to have a single key-press do a whole lot of things under the hood: conventionally, macros play back a key sequence, but with Kaleidoscope, there is much more we can do. Nevertheless, playing back a sequence of events is still the primary use of macros.
Playing back a sequence means that when we press a macro key, we can have it play pretty much any sequence. It can type some text for us, or invoke a complicated shortcut - the possibilities are endless!
## MagicCombo
[MagicCombo Documentation](../plugins/MagicCombo.md)
The MagicCombo extension provides a way to perform custom actions when a particular set of keys are held down together. The functionality assigned to these keys are not changed, and the custom action triggers as long as all keys within the set are pressed. The order in which they were pressed do not matter.
This can be used to tie complex actions to key chords.
## OneShot
[OneShot Documentation](../plugins/OneShot.md)
One-shots are a new kind of behaviour for your standard modifier and momentary layer keys: instead of having to hold them while pressing other keys, they can be tapped and released, and will remain active until any other key is pressed. In short, they turn ``Shift, A`` into ``Shift+A``, and ``Fn, 1`` to ``Fn+1``. The main advantage is that this allows us to place the modifiers and layer keys to positions that would otherwise be awkward when chording. Nevertheless, they still act as normal when held, that behaviour is not lost.
Furthermore, if a one-shot key is tapped two times in quick succession, it becomes sticky, and remains active until disabled with a third tap. This can be useful when one needs to input a number of keys with the modifier or layer active, and still does not wish to hold the key down. If this feature is undesirable, unset the ``OneShot.double_tap_sticky property`` (see later).
To make multi-modifier, or multi-layer shortcuts possible, one-shot keys remain active if another one-shot of the same type is tapped, so ``Ctrl, Alt, b`` becomes ``Ctrl+Alt+b``, and ``L1, L2, c`` is turned into ``L1+L2+c``.
## Qukeys
[Qukeys Documentation](../plugins/Qukeys.md)
A Qukey is a key that has two possible values, usually a modifier and a printable character. The name is a play on the term "qubit" (short for "quantum bit") from quantum computing. The value produced depends on how long the key press lasts, and how it is used in combination with other keys (roughly speaking, whether the key is "tapped" or "held").
The _primary_ value (a printable character) of a Qukey is output if the key is "tapped" (i.e. quickly pressed and released). If it is held long enough, it will instead produce the Qukey's _alternate_ value (usually a modifier). It will also produce that alternate value if a subsequent key is tapped after the initial keypress of the Qukey, even if both keys are released before the time it takes to produce the alternate value on its own. This makes it feasible for most people to use Qukeys on home-row keys, without slowing down typing. In this configuration, it can become very comfortable to use modifier combinations, without needing to move one's hands from the home position at all.
Qukeys can be defined to produce any two keys, including other plugin keys and keys with modifier flags applied. For example, one could define a Qukey to produce ``Shift + 9`` when tapped, and a OneShot ``Ctrl`` when held.
It is also possible to use Qukeys like SpaceCadet (see below), by setting the primary value to a modifier, and the alternate value to a printable character (e.g. ``(``). In that case, the behavior is reversed, and the alternate value will only be used if the key is pressed and released without any rollover to a subsequent key press.
## ShapeShifter
[ShapeShifter Documentation](../plugins/ShapeShifter.md)
ShapeShifter is a plugin that makes it considerably easier to change what symbol is input when a key is pressed together with ``Shift``. If one wants to rearrange the symbols on the number row for example, without modifying the layout on the operating system side, this plugin is where one can turn to.
What it does, is very simple: if any key in its dictionary is found pressed while ``Shift`` is held, it will press another key instead of the one triggering the event. For example, if it sees ``Shift + 1`` pressed together, which normally results in a ``!``, it will press ``4`` instead of ``1``, inputting ``$``.
## SpaceCadet
[SpaceCadet Documentation](../plugins/SpaceCadet.md)
Space Cadet is a way to make it more convenient to input parens - those ``(`` and ``)`` things -, symbols that a lot of programming languages use frequently. If you are working with Lisp, you are using these all the time.
What it does, is that it turns your left and right ``Shift`` keys into parens if you tap and release them, without pressing any other key while holding them. Therefore, to input, say, ``(print foo)``, you don't need to press ``Shift``, hold it, and press ``9`` to get a ``(``, you simply press and release ``Shift``, and continue writing. You use it as if you had a dedicated key for parens!
But if you wish to write capital letters, you hold it, as usual, and you will not see any parens when you release it. You can also hold it for a longer time, and it still would act as a ``Shift``, without the parens inserted on release: this is useful when you want to augment some mouse action with ``Shift``, to select text, for example.
After getting used to the Space Cadet style of typing, you may wish to enable this sort of functionality on other keys, as well. Fortunately, the Space Cadet plugin is configurable and extensible to support adding symbols to other keys. Along with ``(`` on your left ``Shift`` key and ``)`` on your right ``Shift`` key, you may wish to add other such programming mainstays as ``{`` to your left-side ``cmd`` key, ``}`` to your right-side ``alt`` key, [ to your left ``Control`` key, and ``]`` to your right ``Control`` key. You can map the keys in whatever way you may wish to do, so feel free to experiment with different combinations and discover what works best for you!
## TapDance
[TapDance Documentation](../plugins/TapDance.md)
Tap-dance keys are general purpose, multi-use keys, which trigger a different action based on the number of times they were tapped in sequence. As an example to make this clearer, one can have a key that inputs ``A`` when tapped once, inputs ``B`` when tapped twice, and lights up the keyboard in Christmas colors when tapped a third time.
This behaviour is most useful in cases where we have a number of things we perform rarely, where tapping a single key repeatedly is not counter-productive. Such cases include - for example - multimedia forward / backward keys: forward on single tap, backward on double. Of course, one could use modifiers to achieve a similar effect, but that's two keys to use, this is only one. We can also hide some destructive functionality behind a number of taps: reset the keyboard after 4 taps, and light up LEDs in increasingly frightful colors until then.
How does it work?
To not interfere with normal typing, tap-dance keys have two ways to decide when to call an action: they either get interrupted, or they time out. Every time a tap-dance key is pressed, the timer resets, so one does not have to finish the whole tapping sequence within a short time limit. The tap-dance counter continues incrementing until one of these cases happen.
When a tap-dance key is pressed and released, and nothing is pressed on the keyboard until the timeout is reached, then the key will time out, and trigger an action. Which action, depends on the number of times it has been tapped up until this point.
When a tap-dance key is pressed and released, and another key is hit before the timer expires, then the tap-dance key will trigger an action first, perform it, and only then will the firmware continue handling the interrupting key press. This is to preserve the order of keys pressed.
In both of these cases, the ``tapDanceAction`` will be called, with ``tapDanceIndex`` set to the index of the tap-dance action (as set in the keymap), the ``tapCount``, and tapDanceAction set to either ``kaleidoscope::TapDance::Interrupt``, or ``kaleidoscope::TapDance::Timeout``. If we continue holding the key, then as long as it is held, the same function will be called with tapDanceAction set to ``kaleidoscope::TapDance::Hold``. When the key is released, after either an Interrupt or Timeout action was triggered, the function will be called with tapDanceAction set to ``kaleidoscope::TapDance::Release``.
These actions allow us to create sophisticated tap-dance setups, where one can tap a key twice and hold it, and have it repeat, for example.
There is one additional value the tapDanceAction parameter can ``take: kaleidoscope::TapDance::Tap``. It is called with this argument for each and every tap, even if no action is to be triggered yet. This is so that we can have a way to do some side-effects, like light up LEDs to show progress, and so on.
## TopsyTurvy
[TopsyTurvy Documentation](../plugins/TopsyTurvy.md)
TopsyTurvy is a plugin that inverts the behaviour of the Shift key for some selected keys. That is, if configured so, it will input ``!`` when pressing the ``1`` key without ``Shift``, but with the modifier pressed, it will input the original ``1`` symbol.

@ -0,0 +1,29 @@
# Using EEPROM
## Why Use EEPROM?
While we've done our best to make it easy to change how your keyboard works by changing your firmware & re-flashing it, sometimes it would be convenient to be able to make changes without having to go through that rigamarole.
Maybe you'd like to be able to use a GUI like [Chrysalis](https://github.com/keyboardio/Chrysalis) to configure your keyboard layout or LED themes, or maybe your sketch is getting very complicated and you're looking for a way to save program memory.
In either case, you'll want to use EEPROM to store your settings.
## What is EEPROM?
EEPROM stands for "Electronic Erasable Programmable Read-Only Memory" and is one of the three memory mediums your keyboard has.
The other two are RAM, which is used for variables when running your code, and program memory, which is used for storing the program, as well as some other select pieces of data (if you're curious, the bit in your sketch where it says `PROGMEM` indicates that a variable is being stored in program memory instead of RAM).
RAM we want to keep as free as we can, since running our code will need some RAM to work.
While we can put stuff in PROGMEM, your code itself will take up some room there, so it may be useful to store things elsewhere.
EEPROM provides us with another place to store things that can free up RAM and PROGMEM.
Additionally, by leveraging a few plugins, we can store configuration in EEPROM and allow a GUI tool on the connected computer to change settings on the keyboard!
## Move Settings to EEPROM
There are a few important Kaleidoscope plugins for putting settings in EEPROM:
<!-- - [Kaleidoscope-EEPROM-Keymap-Programmer][] - is this worth mentioning in this context? -->
- Kaleidoscope-Focus] - This plugin is what enables communication between your keyboard and programs running on your computer; all the following plugins require you to be using this if you want to be able to change your settings from the computer without re-flashing.
- Kaleidoscope-EEPROM-Settings - This is a plugin that doesn't do much by itself, but most of the other EEPROM plugins will need active to be able to make use of EEPROM storage.
- Kaleidoscope-EEPROM-Keymap - This plugin uses Focus and EEPROM-Settings to allow either overriding or fully replacing the programmed-in keymap without reflashing (by means of a program like Chrysalis running on your computer).
- Kaleidoscope-Colormap - This plugin allows you to use a computer-side program to set a (static -- i.e. the keys won't change colour over time) LED theme for each layer.
All these plugins have minimal installation that can be found in their respective READMEs.
After following the instructions for each and adding them together, you should be able to download a program that knows how to communicate with the keyboard (i.e. [Chrysalis](https://github.com/keyboardio/Chrysalis) and you can start customizing settings without having to do any more programming!

@ -0,0 +1,19 @@
# What can go on your keymap
Eventually there should be a helpful table here with good definitions for the common codes. In the meantime, you can check these files for all the codes the Keyboardio supports:
- Most of the common keyboard key codes are here:
[key_defs_keyboard.h](https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/key_defs_keyboard.h)
- Key codes for system tasks like shutting down, switching windows, and moving through menus are here:
[key_defs_sysctl.h](https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/key_defs_sysctl.h)
- A wide range of key codes for controlling consumer electronics, most of which are probably not relevant, are in this file:
[key_defs_consumerctl.h](https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/key_defs_consumerctl.h)
## In-keymap chorded keys
In addition, the keys in `key_defs_keyboard.h` can be augmented with modifier macros: `LCTRL()`, `LSHIFT()`, `LALT()`, `LGUI()` and `RALT()` to add chorded keys to your keymap. For example `LCTRL(LALT(Key_Delete))` can be used to add control-alt-delete as a single key to your keymap, should you wish. The innermost bracket must be of the standard format as taken from the above key definitions, and all other modifiers must be from the aforementioned list, and in that format. This does allow you to create single keys for multiple modifiers, e.g. `LCTRL(LALT(LSHIFT(Key_LeftGui)))`, when held, would have the effect of all left modifiers at once. These modifier macros only work for standard keys! When applied to any key provided by a plugin, they will have no effect.

@ -0,0 +1,37 @@
# Core LED Effects
This is the list of the stable LED effects in the core libraries.
<h4>LED-ActiveModColor</h4>
A very simple plugin, that lights up the LED in white under any active modifier, for the duration of its activity. Also supports one-shots.
<h4>Kaleidoscope-LEDEffects</h4>
The LEDEffects plugin provides a selection of LED effects, each of them fairly simple, simple enough to not need a plugin of their own. There are a number of different effects included in the package, all of them are available once including the header, and one's free to choose any number of them.
<h4>Kaleidoscope-LEDEffect-BootGreeting</h4>
If you want to have your keyboard signal when it turns on, but you don't want to use any more complicated LED modes, this plugin is for you. It will make the ``LEDEffectNext`` key on your keymap slowly breathe for about ten seconds after plugging the keyboard in (without blocking the normal functionality of the keyboard, of course).
<h4>Kaleidoscope-LEDEffect-Breathe</h4>
Provides a breathing effect for the keyboard. Breathe in, breathe out.
<h4>Kaleidoscope-LEDEffect-Chase</h4>
A simple LED effect where one color chases another across the keyboard and back, over and over again. Playful colors they are.
<h4>Kaleidoscope-LEDEffect-Rainbow</h4>
Two colorful rainbow effects are implemented by this plugin: one where the rainbow waves through the keys, and another where the LEDs breathe though the colors of a rainbow. The difference is that in the first case, we have all the rainbow colors on display, and it waves through the keyboard. In the second case, we have only one color at a time, for the whole board, and the color cycles through the rainbow's palette.
<h4>Kaleidoscope-LEDEffect-SolidColor</h4>
This plugin provides tools to build LED effects that set the entire keyboard to a single color. For show, and for backlighting purposes.
<h4>LED-Stalker</h4>
Demoed in the backer update, this adds an effect that stalks your keys: whenever a key is pressed, the LED under it lights up, and the slowly fades away once the key is released. This provides a kind of trailing effect.
There are two color schemes currently: Haunt, which is a white-ish, ghostly color that follows your fingers, and BlazingTrail, demoed in the video, which lights your keyboard on fire. It looks much better in real life.

@ -0,0 +1,35 @@
# Developing interdependent plugins
Say you have two Kaleidoscope plugins or, more general, two Arduino libraries `A` and `B`. Let's assume `B` depends on `A` in a sense that `B` references symbols (functions/variables) defined in `A`. Both libraries define header files `a_header.h` and `b_header.h` that specify their exported symbols.
The following sketch builds as expected.
```cpp
// my_sketch.ino
#include "b_header.h"
#include "a_header.h"
...
```
If the header appear in opposite order the linker will throw undefined symbol errors regarding missing symbols from `A`.
```cpp
// my_sketch.ino
#include "a_header.h"
#include "b_header.h"
...
```
The reason for this somewhat unexpected behavior is that the order of libraries' occurrence in the linker command line is crucial. The linker must see library `B` first to determine which symbols it needs to extract from `A`. If it encounters `A` first, it completely neglects its symbols as there are no references to it at that point.
To be on the safe side and only if the sketch does not reference symbols from `A` directly, it is better to include the headers in the following way.
```cpp
// header_b.h
#include "header_a.h"
...
```
```cpp
// my_sketch.ino
// Do not include a_header.h directly. It is already included by b_header.h.
#include "b_header.h"
...
```
Note: I did no thorough research on how Arduino internally establishes the linker command line, e.g. with respect to a recursive traversal of the include-tree. This means, I am not sure how the link command line order is generated when header files that are included by the main `.ino` do include other files that provide definitions of library symbols in different orders. There might be additional pitfalls when header includes are more complex given a larger project.

@ -6,8 +6,8 @@
All example sketches
====================
.. toctree::
:maxdepth: 2
:maxdepth: 8
:glob:
examples/**/*.ino
generated/examples/**/*.ino

@ -1,4 +1,4 @@
# Kaleidoscope-Hardware-ErgoDox
# ErgoDox EZ
This is a plugin for [Kaleidoscope][fw], that adds hardware support for the
ErgoDox. To be able to flash the firmware, one will need the [Teensy Loader

@ -0,0 +1,10 @@
# Keyboardio Atreus
This is a plugin for [Kaleidoscope][fw], that provides hardware support for
the [Keyboardio Atreus][kbio:atreus].
The default firmware sketch for the Atreus is [included with Kaleidoscope][sketch]
[fw]: https://github.com/keyboardio/Kaleidoscope
[sketch]: https://github.com/keyboardio/Kaleidoscope/blob/master/examples/Devices/Keyboardio/Atreus/Atreus.ino
[kbio:atreus]: https://shop.keyboard.io/

@ -1,7 +1,10 @@
# Kaleidoscope-Hardware-Model01
# Keyboardio Model 01
This is a plugin for [Kaleidoscope][fw], that adds hardware support for
the [Keyboardio Model01][kbdio:model01].
the [Keyboardio Model 01][kbio:model01].
The default firmware sketch for the Model 01 is [available on GitHub][sketch]
[fw]: https://github.com/keyboardio/Kaleidoscope
[kbdio:model01]: https://shop.keyboard.io/
[sketch]: https://github.com/keyboardio/Model01-Firmware/blob/master/Model01-Firmware.ino
[kbio:model01]: https://shop.keyboard.io/

@ -1,4 +1,4 @@
# Kaleidoscope-Hardware-OLKB-Planck
# OLKB Planck
This is a plugin for [Kaleidoscope][fw], that adds hardware support for the
[OLKB Planck][planck]. For now, this only supports variants with an ATMega32U4 MCU.

@ -1,4 +1,4 @@
# Kaleidoscope-Hardware-SOFTHRUF-Splitography
# SOFTHRUF Splitography
Hardware support for the [SOFTHRUF Splitography][splitography] Steno keyboard.

@ -1,4 +1,4 @@
# Kaleidoscope-Hardware-Technomancy-Atreus
# Technomancy Atreus
This is a plugin for [Kaleidoscope][fw], that adds hardware support for the
[Atreus][atreus]. Supports both the pre- and post-2016 variants with an A* MCU,

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
id="Layer_1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 150 150"
style="enable-background:new 0 0 150 150;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F05025;}
.st1{enable-background:new ;}
</style>
<g transform="translate(0,-958.61215)">
<path class="st0" d="M120.2,998.6c1,0,1.9,0.8,1.9,1.9v80.6c0,1-0.8,1.9-1.9,1.9H99.6c-1,0-1.9-0.8-1.9-1.9v-80.6
c0-1,0.8-1.9,1.9-1.9H120.2z M116.8,1010.4h-13.9c-1,0-1.9,0.8-1.9,1.9v6.4c0,1,0.8,1.9,1.9,1.9h13.9c1,0,1.9-0.8,1.9-1.9v-6.4
C118.7,1011.2,117.8,1010.4,116.8,1010.4z M116.8,1067.6h-13.9c-1,0-1.9,0.8-1.9,1.9v2.6c0,1,0.8,1.9,1.9,1.9h13.9
c1,0,1.9-0.8,1.9-1.9v-2.6C118.7,1068.4,117.8,1067.6,116.8,1067.6z"/>
<path class="st0" d="M92.1,998.6c1,0,1.9,0.8,1.9,1.9v80.6c0,1-0.8,1.9-1.9,1.9H71.4c-1,0-1.9-0.8-1.9-1.9v-80.6
c0-1,0.8-1.9,1.9-1.9H92.1z M88.7,1010.4H74.8c-1,0-1.9,0.8-1.9,1.9v6.4c0,1,0.8,1.9,1.9,1.9h13.9c1,0,1.9-0.8,1.9-1.9v-6.4
C90.6,1011.2,89.7,1010.4,88.7,1010.4z M88.7,1067.6H74.8c-1,0-1.9,0.8-1.9,1.9v2.6c0,1,0.8,1.9,1.9,1.9h13.9c1,0,1.9-0.8,1.9-1.9
v-2.6C90.6,1068.4,89.7,1067.6,88.7,1067.6z"/>
<path class="st0" d="M65.1,1027.5c1.1,0.2,1.8,1.1,1.6,2.2l-9.6,51.7c-0.2,1-1.2,1.7-2.3,1.5l-15.5-2.6c-1.1-0.2-1.8-1.1-1.6-2.2
l9.6-51.7c0.2-1,1.2-1.7,2.3-1.5L65.1,1027.5z M57.8,1034.8l-3.9-0.7c-1.1-0.2-2.1,0.5-2.3,1.5l-6.2,33.2c-0.2,1,0.5,2,1.6,2.2
l3.9,0.7c1.1,0.2,2.1-0.5,2.3-1.5l6.2-33.2C59.5,1036,58.8,1035,57.8,1034.8L57.8,1034.8z"/>
</g>
<text transform="matrix(1 0 0 1 25.75 159.5)" style="font-family:'HelveticaNeue-Bold'; font-size:5px;">Created by Gonzalo Bravo</text>
<text transform="matrix(1 0 0 1 25.75 164.5)" style="font-family:'HelveticaNeue-Bold'; font-size:5px;">from the Noun Project</text>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

@ -13,99 +13,86 @@ This package contains the "core" of Kaleidoscope and a number of [example firmwa
If you're just getting started with the Keyboardio Model 01, the [introductory docs are here](https://github.com/keyboardio/Kaleidoscope/wiki/Keyboardio-Model-01-Introduction) and the source for the basic firmware package is here: https://github.com/keyboardio/Model01-Firmware. It's probably a good idea to start there, learn how to modify your keymap and maybe turn some modules on or off, and then come back to the full repository when you have more complex changes in mind.
Installation and setup
======================
.. toctree::
:caption: Installation and setup
:maxdepth: 2
quick_start
setup_toolchain
build_default_firmware
For users
=========
Supported input devices
-----------------------
.. toctree::
:maxdepth: 2
:glob:
:caption: Customizing your firmware
:maxdepth: 1
:glob:
layers.md
keycodes.md
customization/**
plugin_list.rst
hardware-devices/*
Plugins
-------
.. toctree::
:maxdepth: 1
:glob:
:maxdepth: 2
:caption: Supported devices
:glob:
plugins/*
hardware-devices/**
For developers
==============
Understanding the codebase
--------------------------
.. toctree::
:caption: Understanding the codebase
:maxdepth: 1
:glob:
codebase/glossary.md
codebase/code-style.md
API Design docs
---------------
codebase/**
.. toctree::
:caption: API Design
:maxdepth: 1
:glob:
api-reference/*
api-reference/**
Device drivers
--------------
.. toctree::
:maxdepth: 1
:caption: Device Drivers
:glob:
drivers/**
What's new in v2.0
------------------
.. toctree::
:maxdepth: 2
:caption: Development tips
:glob:
development/**
NEWS.md
Upgrading from old versions
---------------------------
.. toctree::
:maxdepth: 1
:maxdepth: 2
:caption: Changes
NEWS.md
UPGRADING.md
For Everybody
=============
.. toctree::
:maxdepth: 0
:maxdepth: 1
:caption: Code of Conduct
code_of_conduct.md
WIP
===
.. toctree::
:caption: Docs that don't work yet
:maxdepth: 2
examples
about
api/library_root

@ -0,0 +1,10 @@
Bundled plugins
===============
.. toctree::
:caption: Bundled plugins
:maxdepth: 1
:glob:
plugins/*

@ -44,10 +44,10 @@ properties:
> The Hue of the ripple animation. If set, the light splashing across the
> keyboard will use this value instead of all colors of the rainbow.
>
> Setting it to the special value of `Wavepool.rainbow_hue` will cause the
> Setting it to the special value of `WavepoolEffect.rainbow_hue` will cause the
> plugin to use all colors again.
>
> Defaults to `Wavepool.rainbow_hue`.
> Defaults to `WavepoolEffect.rainbow_hue`.
## Dependencies

@ -39,7 +39,7 @@ static void leaderTX(uint8_t seq_index) {
Kaleidoscope.serialPort().println("leaderTX");
}
static const kaleidoscope::Leader::dictionary_t leader_dictionary[] PROGMEM =
static const kaleidoscope::plugin::Leader::dictionary_t leader_dictionary[] PROGMEM =
LEADER_DICT({LEADER_SEQ(LEAD(0), Key_A), leaderA},
{LEADER_SEQ(LEAD(0), Key_T, Key_X), leaderTX});
@ -68,7 +68,7 @@ The plugin provides the `Leader` object, with the following methods and properti
### `.dictionary`
> Set this property to the dictionary `Leader` should use. The dictionary is an
> array of `kaleidoscope::Leader::dictionary_t` elements. Each element is made
> array of `kaleidoscope::plugin::Leader::dictionary_t` elements. Each element is made
> up of two elements, the first being a list of keys, the second an action to
> perform when the sequence is found.i
>

@ -83,7 +83,9 @@ The plugin provides a `Macros` object, with the following methods and properties
> helper discussed below. This method will be used by the plugin to play back
> the result of the `macroAction()` method, but is used rarely otherwise.
>
> The `macro` argument must be a sequence created with the `MACRO()` helper!
> The `macro` argument must be a sequence created with the `MACRO()` helper! For example:
>
> Macros.play(MACRO(D(LeftControl), D(LeftAlt), D(Spacebar), U(LeftControl), U(LeftAlt), U(Spacebar)));
### `.type(strings...)`

@ -65,6 +65,6 @@ started with the plugin.
`RxCy` coordinates for a Model01:
![rxcy layout](../model01_coordinates.png)
![rxcy layout](../hardware-devices/keyboardio/model01/model01_coordinates.png)
[plugin:example]: ../../examples/Keystrokes/MagicCombo/MagicCombo.ino

@ -40,7 +40,7 @@ KALEIDOSCOPE_INIT_PLUGINS(Qukeys);
columns are left to right:
- For the Keyboardio Model 01, key coordinates refer to [this header
file](https://github.com/keyboardio/Kaleidoscope-Hardware-Model01/blob/f469015346535cb864a340bf8eb317d268943248/src/Kaleidoscope-Hardware-Model01.h#L267-L279).
file](https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/device/keyboardio/Model01.h#L167-L179).
```
QUKEYS(

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save