From ff0c45ec8f9eeccd3349e088974efdd23f334631 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Thu, 12 Nov 2015 22:21:32 +1300 Subject: [PATCH 01/30] Initial support for the ICPad - Basic support for up to 4 ISSI chips (and partial support for 16 chip configurations) - Initial USB mux support * Required USB re-init procedure - Initial interconnect mux support * Required some state reset commands --- Keyboards/README.markdown | 1 + Keyboards/icpad.bash | 72 +++++++ Output/pjrcUSB/arm/usb_dev.c | 3 + README.markdown | 2 +- Scan/ICPad/defaultMap.kll | 169 ++++++++++++++++ Scan/ICPad/matrix.h | 56 ++++++ Scan/ICPad/pinout | 114 +++++++++++ Scan/ICPad/scan_loop.c | 106 ++++++++++ Scan/ICPad/scan_loop.h | 40 ++++ Scan/ICPad/setup.cmake | 33 +++ Scan/ISSILed/capabilities.kll | 32 ++- Scan/ISSILed/exampleAPI.bash | 5 +- Scan/ISSILed/led_scan.c | 320 ++++++++++++++++++++---------- Scan/MatrixARM/matrix_scan.c | 1 - Scan/UARTConnect/capabilities.kll | 2 +- Scan/UARTConnect/connect_scan.h | 1 + 16 files changed, 845 insertions(+), 112 deletions(-) create mode 100755 Keyboards/icpad.bash create mode 100644 Scan/ICPad/defaultMap.kll create mode 100644 Scan/ICPad/matrix.h create mode 100644 Scan/ICPad/pinout create mode 100644 Scan/ICPad/scan_loop.c create mode 100644 Scan/ICPad/scan_loop.h create mode 100644 Scan/ICPad/setup.cmake diff --git a/Keyboards/README.markdown b/Keyboards/README.markdown index 9240c18..857e3a9 100644 --- a/Keyboards/README.markdown +++ b/Keyboards/README.markdown @@ -28,6 +28,7 @@ Projects -------- * infinity.bash (Infinity Keyboard 2014/10/15) +* icpad.bash (Soon?) * ergodox.bash (Infinity Ergodox 2015/08/15) * template.bash (Example template for new keyboards) * whitefox.bash (Soon?) diff --git a/Keyboards/icpad.bash b/Keyboards/icpad.bash new file mode 100755 index 0000000..de299fd --- /dev/null +++ b/Keyboards/icpad.bash @@ -0,0 +1,72 @@ +#!/bin/bash +# This is a build script template +# These build scripts are just a convenience for configuring your keyboard (less daunting than CMake) +# Jacob Alexander 2015 + + + +################# +# Configuration # +################# + +# Feel free to change the variables in this section to configure your keyboard + +BuildPath="ICPad" + +## KLL Configuration ## + +# Generally shouldn't be changed, this will affect every layer +BaseMap="defaultMap" + +# This is the default layer of the keyboard +# NOTE: To combine kll files into a single layout, separate them by spaces +# e.g. DefaultMap="mylayout mylayoutmod" +DefaultMap="stdFuncMap" + +# This is where you set the additional layers +# NOTE: Indexing starts at 1 +# NOTE: Each new layer is another array entry +# e.g. PartialMaps[1]="layer1 layer1mod" +# PartialMaps[2]="layer2" +# PartialMaps[3]="layer3" +PartialMaps[1]="" + + + +########################## +# Advanced Configuration # +########################## + +# Don't change the variables in this section unless you know what you're doing +# These are useful for completely custom keyboards +# NOTE: Changing any of these variables will require a force build to compile correctly + +# Keyboard Module Configuration +ScanModule="ICPad" +MacroModule="PartialMap" +OutputModule="pjrcUSB" +DebugModule="full" + +# Microcontroller +Chip="mk20dx256vlh7" + +# Compiler Selection +Compiler="gcc" + + + +######################## +# Bash Library Include # +######################## + +# Shouldn't need to touch this section + +# Check if the library can be found +if [ ! -f cmake.bash ]; then + echo "ERROR: Cannot find 'cmake.bash'" + exit 1 +fi + +# Load the library +source cmake.bash + diff --git a/Output/pjrcUSB/arm/usb_dev.c b/Output/pjrcUSB/arm/usb_dev.c index 782f3ac..174fe8d 100644 --- a/Output/pjrcUSB/arm/usb_dev.c +++ b/Output/pjrcUSB/arm/usb_dev.c @@ -1176,6 +1176,9 @@ uint8_t usb_init() print("USB INIT"NL); #endif + // Unset usb configuration + usb_configuration = 0; + // Clear out endpoints table for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) { diff --git a/README.markdown b/README.markdown index 7039d59..f020072 100644 --- a/README.markdown +++ b/README.markdown @@ -38,7 +38,7 @@ Supported Microcontrollers * Teensy 2.0 (Partial) * Teensy 2.0++ -* Teensy 3.0 +* Teesny 3.0 * Teensy 3.1 * mk20dx128vlf5 * mk20dx256vlh7 diff --git a/Scan/ICPad/defaultMap.kll b/Scan/ICPad/defaultMap.kll new file mode 100644 index 0000000..c558967 --- /dev/null +++ b/Scan/ICPad/defaultMap.kll @@ -0,0 +1,169 @@ +Name = ICPad; +Version = 0.1; +Author = "HaaTa (Jacob Alexander) 2015"; +KLL = 0.3d; + +# Modified Date +Date = 2015-10-21; + + +S0x00 : U"Esc"; +S0x01 : U"1"; +S0x02 : U"2"; +S0x03 : U"3"; +S0x04 : U"4"; +S0x05 : U"5"; +S0x06 : U"6"; +S0x07 : U"7"; +S0x08 : U"8"; +S0x09 : U"9"; +S0x0A : U"0"; +S0x0B : U"Minus"; +S0x0C : U"Equal"; +S0x0D : U"Hash"; +S0x0E : U"Backspace"; +S0x0F : U"BackTick"; +S0x10 : U"Tab"; +S0x11 : U"Q"; +S0x12 : U"W"; +S0x13 : U"E"; +S0x14 : U"R"; +S0x15 : U"T"; +S0x16 : U"Y"; +S0x17 : U"U"; +S0x18 : U"I"; +S0x19 : U"O"; +S0x1A : U"P"; +S0x1B : U"LBrace"; +S0x1C : U"RBrace"; +S0x1D : U"Backslash"; +S0x1E : U"Delete"; +S0x1F : U"CapsLock"; +S0x20 : U"A"; +S0x21 : U"S"; +S0x22 : U"D"; +S0x23 : U"F"; +S0x24 : U"G"; +S0x25 : U"H"; +S0x26 : U"J"; +S0x27 : U"K"; +S0x28 : U"L"; +S0x29 : U"Semicolon"; +S0x2A : U"Quote"; +S0x2B : U"App"; +S0x2C : U"Enter"; +S0x2D : U"PageUp"; +S0x2E : U"LShift"; +S0x2F : U"ISO Slash"; +S0x30 : U"Z"; +S0x31 : U"X"; +S0x32 : U"C"; +S0x33 : U"V"; +S0x34 : U"B"; +S0x35 : U"N"; +S0x36 : U"M"; +S0x37 : U"Comma"; +S0x38 : U"Period"; +S0x39 : U"Slash"; +S0x3A : U"RShift"; +S0x3B : U"Up"; +S0x3C : U"PageDown"; +S0x3D : U"Ctrl"; +S0x3E : U"Function1"; +S0x3F : U"LAlt"; +S0x40 : U"Space"; +S0x41 : U"RAlt"; +S0x42 : U"Gui"; +S0x43 : U"Menu"; +S0x44 : U"Left"; +S0x45 : U"Down"; +S0x46 : U"Right"; + + +# Defines available to the ICPad Scan Module + +# Available ISSI Chips +ISSI_Chips = 2; + +# LED Default Enable Mask Override +# +# Each LED is represented by a single bit +# See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details +ISSILedMask1 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFE, 0xFE, /* C2-1 -> C2-16 */ + 0xFE, 0xFE, /* C3-1 -> C3-16 */ + 0x06, 0x06, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x60, 0x60, /* C6-1 -> C6-16 */ + 0x7F, 0x7F, /* C7-1 -> C7-16 */ + 0x7F, 0x7F, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedMask2 = " + 0xFF, 0x00, /* C1-1 -> C1-16 */ + 0xFE, 0x00, /* C2-1 -> C2-16 */ + 0xFE, 0x00, /* C3-1 -> C3-16 */ + 0x06, 0x00, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x00, 0x00, /* C6-1 -> C6-16 */ + 0x0F, 0x00, /* C7-1 -> C7-16 */ + 0x0F, 0x00, /* C8-1 -> C8-16 */ + 0x0F, 0x00, /* C9-1 -> C9-16 */ +"; + + +# LED Brightness Override +# +# Each LED channel supports 256 levels (8-bit control) +# By default, LEDs are set to 0 brightness +ISSILedBrightness1 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness2 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +"; + +# Misc +ISSILedBrightness1 = " +0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, /* C1-1 -> C1-16 */ +0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, /* C2-1 -> C2-16 */ +0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, /* C3-1 -> C3-16 */ +0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, /* C6-1 -> C6-16 */ +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, /* C7-1 -> C7-16 */ +0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, /* C8-1 -> C8-16 */ +0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness2 = " +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +0x00, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +0x00, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +"; + diff --git a/Scan/ICPad/matrix.h b/Scan/ICPad/matrix.h new file mode 100644 index 0000000..f2037e0 --- /dev/null +++ b/Scan/ICPad/matrix.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Project Includes +#include + + + +// ----- Matrix Definition ----- + +// Freescale ARM MK20's support GPIO PTA, PTB, PTC, PTD and PTE 0..31 +// Not all chips have access to all of these pins (most don't have 160 pins :P) +// +// NOTE: +// Before using a pin, make sure it supports being a GPIO *and* doesn't have a default pull-up/pull-down +// Checking this is completely on the ownness of the user + +// MDErgo1 +// +// Column (Strobe) - 9 Total +// PTB2,3,18,19 +// PTC0,9..11 +// PTD0 +// +// Rows (Sense) - 5 Total +// PTD1,4..7 + +// Define Rows (Sense) and Columns (Strobes) +GPIO_Pin Matrix_cols[] = { gpio(B,2), gpio(B,3), gpio(B,18), gpio(B,19), gpio(C,0), gpio(C,8), gpio(C,9), gpio(C,10), gpio(C,11) }; +GPIO_Pin Matrix_rows[] = { gpio(D,0), gpio(D,1), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7), gpio(C,1), gpio(C,2) }; + +// Define type of scan matrix +Config Matrix_type = Config_Pulldown; + diff --git a/Scan/ICPad/pinout b/Scan/ICPad/pinout new file mode 100644 index 0000000..96db34c --- /dev/null +++ b/Scan/ICPad/pinout @@ -0,0 +1,114 @@ +Pin Usage +========= + +mk20dx256vlh7 + + ---- +|Keys| + ---- + +* Strobe (Columns) + +PTB2 +PTB3 +PTB18 +PTB19 +PTC0 +PTC8 +PTC9 +PTC10 +PTC11 + +* Sense (Rows) + +PTD0 +PTD1 +PTD4 +PTD5 +PTD6 +PTD7 +PTC1 +PTC2 + + + ----- +|Clock| + ----- + +PTA18 <-> PTA19 + + + --- +|I2C| + --- + +* IS31FL3731C + +PTB0 - SCL0 (add header pin, label as SCL0) +PTB1 - SDA0 (add header pin, label as SDA0) +PTB17 - INTB Chip 1 +PTB16 - SDB (tied to all Chips, hardware shutdown) + + + + --- +|DAC| + --- + +DAC0 (N/C) + + + ---- +|UART| + ---- + +* Comm - For bi-directional communication between halves + +PTA1 - RX0 (Master Side) +PTA2 - TX0 (Master Side) + +PTE1 - RX1 (Slave Side) +PTE0 - TX1 (Slave Side) + +PTD2 - RX2 (UART Debug Header) +PTD3 - TX2 (UART Debug Header) + + + ----- +|Debug| + ----- + +* SWD - (Main reflash header) + +PTA0 (Pull-down) +PTA3 (Pull-up) + +* LEDs + +PTA5 (LED only for PCB, not Teensy) + +* UARTs + +PTD2 - RX2 (UART Debug Header, label as RX2) +PTD3 - TX2 (UART Debug Header, label as TX2) + + + ------ +|Unused| + ------ + +* GPIO + +PTA4 +PTA12 +PTA13 +PTC3 +PTC4 +PTC5 +PTC6 +PTC7 + +* Analog + +TODO + diff --git a/Scan/ICPad/scan_loop.c b/Scan/ICPad/scan_loop.c new file mode 100644 index 0000000..c1db646 --- /dev/null +++ b/Scan/ICPad/scan_loop.c @@ -0,0 +1,106 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Local Includes +#include "scan_loop.h" + + + +// ----- Function Declarations ----- + +// ----- Variables ----- + +// Number of scans since the last USB send +uint16_t Scan_scanCount = 0; + + + +// ----- Functions ----- + +// Setup +inline void Scan_setup() +{ + // Setup Port Swap module + Port_setup(); + + // Setup UART Connect, if Output_Available, this is the master node + Connect_setup( Output_Available ); + + // Setup GPIO pins for matrix scanning + Matrix_setup(); + + // Setup ISSI chip to control the leds + LED_setup(); + + // Reset scan count + Scan_scanCount = 0; +} + + +// Main Detection Loop +inline uint8_t Scan_loop() +{ + // Port Swap detection + Port_scan(); + + // Scan Matrix + Matrix_scan( Scan_scanCount++ ); + + // Process any interconnect commands + Connect_scan(); + + // Process any LED events + LED_scan(); + + return 0; +} + + +// Signal from Macro Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithMacro( uint8_t sentKeys ) +{ +} + + +// Signal from Output Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithOutput( uint8_t sentKeys ) +{ + // Reset scan loop indicator (resets each key debounce state) + // TODO should this occur after USB send or Macro processing? + Scan_scanCount = 0; +} + diff --git a/Scan/ICPad/scan_loop.h b/Scan/ICPad/scan_loop.h new file mode 100644 index 0000000..17a06fc --- /dev/null +++ b/Scan/ICPad/scan_loop.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Compiler Includes +#include + + + +// ----- Functions ----- + +// Functions to be called by main.c +void Scan_setup( void ); +uint8_t Scan_loop( void ); + +// Call-backs +void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module +void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module + diff --git a/Scan/ICPad/setup.cmake b/Scan/ICPad/setup.cmake new file mode 100644 index 0000000..5696ccd --- /dev/null +++ b/Scan/ICPad/setup.cmake @@ -0,0 +1,33 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2015 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Required Sub-modules +# +AddModule ( Scan ISSILed ) +AddModule ( Scan MatrixARM ) +AddModule ( Scan PortSwap ) +AddModule ( Scan UARTConnect ) + + +### +# Module C files +# +set ( Module_SRCS + scan_loop.c +) + + +### +# Compiler Family Compatibility +# +set ( ModuleCompatibility + arm +) + diff --git a/Scan/ISSILed/capabilities.kll b/Scan/ISSILed/capabilities.kll index 6ecd4f6..77cb864 100644 --- a/Scan/ISSILed/capabilities.kll +++ b/Scan/ISSILed/capabilities.kll @@ -1,7 +1,7 @@ Name = ISSILedCapabilities; Version = 0.2; Author = "HaaTa (Jacob Alexander) 2015"; -KLL = 0.3c; +KLL = 0.3d; # Modified Date Date = 2015-10-09; @@ -24,6 +24,10 @@ ledControl => LED_control_capability( mode : 1, amount : 1, index : 2 ); # Defines available to the ISSILed sub-module +# Available ISSI Chips +ISSI_Chips => ISSI_Chips_define; +ISSI_Chips = 1; # 1 by default + # LED Default Enable Mask # # By default, all LEDs are enabled @@ -43,6 +47,19 @@ ISSILedMask1 = " 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; +ISSILedMask2 => ISSILedMask2_define; +ISSILedMask2 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFF, 0xFF, /* C2-1 -> C2-16 */ + 0xFF, 0xFF, /* C3-1 -> C3-16 */ + 0xFF, 0xFF, /* C4-1 -> C4-16 */ + 0xFF, 0xFF, /* C5-1 -> C5-16 */ + 0xFF, 0xFF, /* C6-1 -> C6-16 */ + 0xFF, 0xFF, /* C7-1 -> C7-16 */ + 0xFF, 0xFF, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + # LED Default Brightness # # By default, all LEDs are set to max brightness @@ -60,6 +77,19 @@ ISSILedBrightness1 = " 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; +ISSILedBrightness2 => ISSILedBrightness2_define; +ISSILedBrightness2 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + # Example starting from 0 brightness to 0x8F ISSILedBrightness_example = " 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ diff --git a/Scan/ISSILed/exampleAPI.bash b/Scan/ISSILed/exampleAPI.bash index 5d66c37..a54dd0f 100755 --- a/Scan/ISSILed/exampleAPI.bash +++ b/Scan/ISSILed/exampleAPI.bash @@ -27,5 +27,8 @@ printf "\r" > $SERIALPORT # Page 0x0A is used for configuration # See the datasheet for full details http://www.issi.com/WW/pdf/31FL3731C.pdf sleep 0.1 -printf "ledWPage 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT +printf "ledWPage 0xE8 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 1 +printf "ledWPage 0xEA 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 2 +printf "ledWPage 0xEC 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 3 +printf "ledWPage 0xEE 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 4 diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index 8a92b76..6a639a1 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -37,13 +37,53 @@ // ----- Defines ----- +// Increase buffer sizes for RGB +#ifdef ISSI_RGB_define +#define I2C_TxBufferLength 600 +#define I2C_RxBufferLength 16 +#else #define I2C_TxBufferLength 300 #define I2C_RxBufferLength 8 +#endif -#define LED_BufferLength 144 +#define LED_BufferLength 144 +#define LED_EnableBufferLength 18 -// TODO Needs to be defined per keyboard -#define LED_TotalChannels 144 +#define LED_TotalChannels (144 * ISSI_Chips_define) + +// ISSI Addresses +// IS31FL3731 (max 4 channels per bus) +#if 1 +#define ISSI_Ch1 0xE8 +#define ISSI_Ch2 0xEA +#define ISSI_Ch3 0xEC +#define ISSI_Ch4 0xEE + +// IS31FL3732 (max 16 channels per bus) +#else +#define ISSI_Ch1 0xB0 +#define ISSI_Ch2 0xB2 +#define ISSI_Ch3 0xB4 +#define ISSI_Ch4 0xB6 +#endif + + + +// ----- Macros ----- + +#define LED_MaskDefine(ch) \ + { \ + ISSI_Ch##ch, /* I2C address */ \ + 0x00, /* Starting register address */ \ + { ISSILedMask##ch##_define }, \ + } + +#define LED_BrightnessDefine(ch) \ + { \ + ISSI_Ch##ch, /* I2C address */ \ + 0x24, /* Starting register address */ \ + { ISSILedBrightness##ch##_define }, \ + } @@ -63,6 +103,12 @@ typedef struct LED_Buffer { uint8_t buffer[LED_BufferLength]; } LED_Buffer; +typedef struct LED_EnableBuffer { + uint8_t i2c_addr; + uint8_t reg_addr; + uint8_t buffer[LED_EnableBufferLength]; +} LED_EnableBuffer; + // ----- Function Declarations ----- @@ -93,7 +139,7 @@ CLIDict_Entry( ledCtrl, "Basic LED control. Args: []" CLIDict_Entry( ledRPage, "Read the given register page." ); CLIDict_Entry( ledStart, "Disable software shutdown." ); CLIDict_Entry( ledTest, "Test out the led pages." ); -CLIDict_Entry( ledWPage, "Write to given register page starting at address. i.e. 0x2 0x24 0xF0 0x12" ); +CLIDict_Entry( ledWPage, "Write to given register page starting at address. i.e. 0xE8 0x2 0x24 0xF0 0x12" ); CLIDict_Entry( ledZero, "Zero out LED register pages (non-configuration)." ); CLIDict_Def( ledCLIDict, "ISSI LED Module Commands" ) = { @@ -118,23 +164,42 @@ volatile uint8_t I2C_RxBufferPtr[ I2C_TxBufferLength ]; volatile I2C_Buffer I2C_TxBuffer = { 0, 0, 0, I2C_TxBufferLength, (uint8_t*)I2C_TxBufferPtr }; volatile I2C_Buffer I2C_RxBuffer = { 0, 0, 0, I2C_RxBufferLength, (uint8_t*)I2C_RxBufferPtr }; -LED_Buffer LED_pageBuffer; +LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; -// A bit mask determining which LEDs are enabled in the ISSI chip -const uint8_t LED_ledEnableMask1[] = { - 0xE8, // I2C address - 0x00, // Starting register address - ISSILedMask1_define +// Enable mask and default brightness for ISSI chip channel +const LED_EnableBuffer LED_ledEnableMask[ISSI_Chips_define] = { + LED_MaskDefine( 1 ), +#if ISSI_Chips_define >= 2 + LED_MaskDefine( 2 ), +#endif +#if ISSI_Chips_define >= 3 + LED_MaskDefine( 3 ), +#endif +#if ISSI_Chips_define >= 4 + LED_MaskDefine( 4 ), +#endif }; // Default LED brightness -const uint8_t LED_defaultBrightness1[] = { - 0xE8, // I2C address - 0x24, // Starting register address - ISSILedBrightness1_define +const LED_Buffer LED_defaultBrightness[ISSI_Chips_define] = { + LED_BrightnessDefine( 1 ), +#if ISSI_Chips_define >= 2 + LED_BrightnessDefine( 2 ), +#endif +#if ISSI_Chips_define >= 3 + LED_BrightnessDefine( 3 ), +#endif +#if ISSI_Chips_define >= 4 + LED_BrightnessDefine( 4 ), +#endif }; +#if ISSI_Chips_define >= 5 +#error "Invalid number of ISSI Chips" +#endif + + // ----- Interrupt Functions ----- @@ -274,7 +339,10 @@ inline void I2C_setup() PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); // SCL Frequency Divider - // 400kHz -> 120 (0x85) @ 48 MHz F_BUS + // 1.8 MBaud (likely higher than spec) + // 0x85 -> 36 MHz / (4 * 5) = 1.8 MBaud + // 0x80 => mul(4) + // 0x05 => ICL(5) I2C0_F = 0x85; I2C0_FLT = 4; I2C0_C1 = I2C_C1_IICEN; @@ -284,14 +352,14 @@ inline void I2C_setup() NVIC_ENABLE_IRQ( IRQ_I2C0 ); } -void LED_zeroPages( uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) +void LED_zeroPages( uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) { // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, 0x00 }; + uint8_t pageSetup[] = { addr, 0xFD, 0x00 }; // Max length of a page + chip id + reg start uint8_t fullPage[ 0xB4 + 2 ] = { 0 }; // Max size of page - fullPage[0] = 0xE8; // Set chip id + fullPage[0] = addr; // Set chip id fullPage[1] = startReg; // Set start reg // Iterate through given pages, zero'ing out the given register regions @@ -310,10 +378,10 @@ void LED_zeroPages( uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8 } } -void LED_sendPage( uint8_t *buffer, uint8_t len, uint8_t page ) +void LED_sendPage( uint8_t addr, uint8_t *buffer, uint8_t len, uint8_t page ) { // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, page }; + uint8_t pageSetup[] = { addr, 0xFD, page }; // Setup page while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) @@ -325,58 +393,55 @@ void LED_sendPage( uint8_t *buffer, uint8_t len, uint8_t page ) } -void LED_writeReg( uint8_t reg, uint8_t val, uint8_t page ) +// Write address +void LED_writeReg( uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) { // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, page }; + uint8_t pageSetup[] = { addr, 0xFD, page }; // Reg Write Setup - uint8_t writeData[] = { 0xE8, reg, val }; + uint8_t writeData[] = { addr, reg, val }; // Setup page while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) delay(1); + // Write register while ( I2C_Send( writeData, sizeof( writeData ), 0 ) == 0 ) delay(1); } -void LED_readPage( uint8_t len, uint8_t page ) +// Read address +void LED_readReg( uint8_t addr, uint8_t reg, uint8_t page ) { // Software shutdown must be enabled to read registers - LED_writeReg( 0x0A, 0x00, 0x0B ); + LED_writeReg( addr, 0x0A, 0x00, 0x0B ); // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, page }; + uint8_t pageSetup[] = { addr, 0xFD, page }; // Setup page while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) delay(1); // Register Setup - uint8_t regSetup[] = { 0xE8, 0x00 }; + uint8_t regSetup[] = { addr, reg }; - // Read each register in the page - for ( uint8_t reg = 0; reg < len; reg++ ) - { - // Update register to read - regSetup[1] = reg; + // Configure register + while ( I2C_Send( regSetup, sizeof( regSetup ), 0 ) == 0 ) + delay(1); - // Configure register - while ( I2C_Send( regSetup, sizeof( regSetup ), 0 ) == 0 ) - delay(1); + // Register Read Command + uint8_t regReadCmd[] = { addr | 0x1 }; - // Register Read Command - uint8_t regReadCmd[] = { 0xE9 }; + // Request single register byte + while ( I2C_Send( regReadCmd, sizeof( regReadCmd ), 1 ) == 0 ) + delay(1); - // Request single register byte - while ( I2C_Send( regReadCmd, sizeof( regReadCmd ), 1 ) == 0 ) - delay(1); - dbug_print("NEXT"); - } + // TODO get byte from buffer // Disable software shutdown - LED_writeReg( 0x0A, 0x01, 0x0B ); + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); } // Setup @@ -388,9 +453,29 @@ inline void LED_setup() // Initialize I2C I2C_setup(); + // Setup LED_pageBuffer addresses and brightness section + LED_pageBuffer[0].i2c_addr = ISSI_Ch1; + LED_pageBuffer[0].reg_addr = 0x24; +#if ISSI_Chips_define >= 2 + LED_pageBuffer[1].i2c_addr = ISSI_Ch2; + LED_pageBuffer[1].reg_addr = 0x24; +#endif +#if ISSI_Chips_define >= 3 + LED_pageBuffer[2].i2c_addr = ISSI_Ch3; + LED_pageBuffer[2].reg_addr = 0x24; +#endif +#if ISSI_Chips_define >= 4 + LED_pageBuffer[3].i2c_addr = ISSI_Ch4; + LED_pageBuffer[3].reg_addr = 0x24; +#endif + // Zero out Frame Registers // This needs to be done before disabling the hardware shutdown (or the leds will do undefined things) - LED_zeroPages( 0x0B, 1, 0x00, 0x0C ); // Control Registers + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_zeroPages( addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers + } // Disable Hardware shutdown of ISSI chip (pull high) GPIOB_PDDR |= (1<<16); @@ -398,16 +483,22 @@ inline void LED_setup() GPIOB_PSOR |= (1<<16); // Clear LED Pages - LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers - // Enable LEDs based upon mask - LED_sendPage( (uint8_t*)LED_ledEnableMask1, sizeof( LED_ledEnableMask1 ), 0 ); - // Set default brightness - LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 0 ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers + LED_sendPage( addr, (uint8_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ), 0 ); + LED_sendPage( addr, (uint8_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); + } // Disable Software shutdown of ISSI chip - LED_writeReg( 0x0A, 0x01, 0x0B ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + } } @@ -635,11 +726,6 @@ uint8_t I2C_Send( uint8_t *data, uint8_t sendLen, uint8_t recvLen ) // LED State processing loop inline uint8_t LED_scan() { - - // I2C Busy - // S & I2C_S_BUSY - //I2C_S_BUSY - return 0; } @@ -667,59 +753,57 @@ typedef struct LedControl { void LED_control( LedControl *control ) { - // Only send if we've completed all other transactions - /* - if ( I2C_TxBuffer.sequencePos > 0 ) - return; - */ - // Configure based upon the given mode - // TODO Perhaps do gamma adjustment? - switch ( control->mode ) + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - case LedControlMode_brightness_decrease: - // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ control->index ] -= control->amount; - break; - - case LedControlMode_brightness_increase: - // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ control->index ] += control->amount; - break; - - case LedControlMode_brightness_set: - LED_pageBuffer.buffer[ control->index ] = control->amount; - break; - - case LedControlMode_brightness_decrease_all: - for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + // TODO Perhaps do gamma adjustment? + switch ( control->mode ) { + case LedControlMode_brightness_decrease: // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ channel ] -= control->amount; - } - break; + LED_pageBuffer[ ch ].buffer[ control->index ] -= control->amount; + break; - case LedControlMode_brightness_increase_all: - for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) - { + case LedControlMode_brightness_increase: // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ channel ] += control->amount; - } - break; + LED_pageBuffer[ ch ].buffer[ control->index ] += control->amount; + break; - case LedControlMode_brightness_set_all: - for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) - { - LED_pageBuffer.buffer[ channel ] = control->amount; + case LedControlMode_brightness_set: + LED_pageBuffer[ ch ].buffer[ control->index ] = control->amount; + break; + + case LedControlMode_brightness_decrease_all: + for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + { + // Don't worry about rolling over, the cycle is quick + LED_pageBuffer[ ch ].buffer[ channel ] -= control->amount; + } + break; + + case LedControlMode_brightness_increase_all: + for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + { + // Don't worry about rolling over, the cycle is quick + LED_pageBuffer[ ch ].buffer[ channel ] += control->amount; + } + break; + + case LedControlMode_brightness_set_all: + for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + { + LED_pageBuffer[ ch ].buffer[ channel ] = control->amount; + } + break; } - break; } // Sync LED buffer with ISSI chip buffer // TODO Support multiple frames - LED_pageBuffer.i2c_addr = 0xE8; // Chip 1 - LED_pageBuffer.reg_addr = 0x24; // Brightness section - LED_sendPage( (uint8_t*)&LED_pageBuffer, sizeof( LED_Buffer ), 0 ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_sendPage( LED_pageBuffer[ ch ].i2c_addr, (uint8_t*)&LED_pageBuffer[ ch ], sizeof( LED_Buffer ), 0 ); + } } uint8_t LED_control_timer = 0; @@ -922,6 +1006,7 @@ void cliFunc_i2cRecv( char* args ) // TODO Currently not working correctly void cliFunc_ledRPage( char* args ) { + /* TODO Use readReg command instead // Parse number from argument // NOTE: Only first argument is used char* arg1Ptr; @@ -939,8 +1024,9 @@ void cliFunc_ledRPage( char* args ) // No \r\n by default after the command is entered print( NL ); - LED_readPage( 0x1, page ); - //LED_readPage( 0xB4, page ); + // TODO, multi-channel + LED_readPage( ISSI_Ch1, 0xB4, page ); + */ } void cliFunc_ledWPage( char* args ) @@ -949,14 +1035,23 @@ void cliFunc_ledWPage( char* args ) char* arg1Ptr; char* arg2Ptr = args; - // First process page and starting address + // First specify the write address curArgs = arg2Ptr; CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); // Stop processing args if no more are found if ( *arg1Ptr == '\0' ) return; - uint8_t page[] = { 0xE8, 0xFD, numToInt( arg1Ptr ) }; + uint8_t addr = numToInt( arg1Ptr ); + + // Next process page and starting address + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + return; + uint8_t page[] = { addr, 0xFD, numToInt( arg1Ptr ) }; curArgs = arg2Ptr; CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); @@ -964,7 +1059,7 @@ void cliFunc_ledWPage( char* args ) // Stop processing args if no more are found if ( *arg1Ptr == '\0' ) return; - uint8_t data[] = { 0xE8, numToInt( arg1Ptr ), 0 }; + uint8_t data[] = { addr, numToInt( arg1Ptr ), 0 }; // Set the register page while ( I2C_Send( page, sizeof( page ), 0 ) == 0 ) @@ -994,23 +1089,34 @@ void cliFunc_ledWPage( char* args ) void cliFunc_ledStart( char* args ) { print( NL ); // No \r\n by default after the command is entered - LED_zeroPages( 0x0B, 1, 0x00, 0x0C ); // Control Registers - //LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers - LED_writeReg( 0x0A, 0x01, 0x0B ); - LED_sendPage( (uint8_t*)LED_ledEnableMask1, sizeof( LED_ledEnableMask1 ), 0 ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_zeroPages( LED_ledEnableMask[ ch ].i2c_addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers + //LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers + LED_writeReg( LED_ledEnableMask[ ch ].i2c_addr, 0x0A, 0x01, 0x0B ); + LED_sendPage( LED_ledEnableMask[ ch ].i2c_addr, (uint8_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ), 0 ); + } } void cliFunc_ledTest( char* args ) { print( NL ); // No \r\n by default after the command is entered - LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 0 ); + + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_sendPage( LED_defaultBrightness[ ch ].i2c_addr, (uint8_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); + } } void cliFunc_ledZero( char* args ) { print( NL ); // No \r\n by default after the command is entered - LED_zeroPages( 0x00, 8, 0x24, 0xB4 ); // Only PWMs + + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_zeroPages( LED_defaultBrightness[ ch ].i2c_addr, 0x00, 8, 0x24, 0xB4 ); // Only PWMs + } } void cliFunc_ledCtrl( char* args ) diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index a9018df..8463b26 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -196,7 +196,6 @@ void Matrix_setup() print( NL ); info_msg("Max Keys: "); printHex( Matrix_maxKeys ); - print( NL ); // Clear out Debounce Array for ( uint8_t item = 0; item < Matrix_maxKeys; item++ ) diff --git a/Scan/UARTConnect/capabilities.kll b/Scan/UARTConnect/capabilities.kll index bab1b61..67aafe0 100644 --- a/Scan/UARTConnect/capabilities.kll +++ b/Scan/UARTConnect/capabilities.kll @@ -26,7 +26,7 @@ UARTConnectBaudFine => UARTConnectBaudFine_define; # Thus baud setting = 26 # NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet # Baud fine setting = 0x02 -UARTConnectBaud = 1; # 4.5 Mbpsa @ 72 MHz +UARTConnectBaud = 1; # 4.5 Mbps @ 72 MHz UARTConnectBaudFine = 0x0; #UARTConnectBaud = 39; # 115385 bps @ 72 MHz (close to 115200) diff --git a/Scan/UARTConnect/connect_scan.h b/Scan/UARTConnect/connect_scan.h index cdd7ed0..389dce7 100644 --- a/Scan/UARTConnect/connect_scan.h +++ b/Scan/UARTConnect/connect_scan.h @@ -163,6 +163,7 @@ extern uint8_t Connect_master; // Set if master void Connect_setup( uint8_t master ); void Connect_scan(); +void Connect_reset(); void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes ); void Connect_send_RemoteCapability( uint8_t id, uint8_t capabilityIndex, uint8_t state, uint8_t stateType, uint8_t numArgs, uint8_t *args ); From a25aa8451331eaa696ee3676bdeac63b64e45c87 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Thu, 12 Nov 2015 22:21:32 +1300 Subject: [PATCH 02/30] Initial support for the ICPad - Basic support for up to 4 ISSI chips (and partial support for 16 chip configurations) - Initial USB mux support * Required USB re-init procedure - Initial interconnect mux support * Required some state reset commands --- Keyboards/README.markdown | 1 + Keyboards/icpad.bash | 72 +++++++ Output/pjrcUSB/arm/usb_dev.c | 3 + README.markdown | 2 +- Scan/ICPad/defaultMap.kll | 169 ++++++++++++++++ Scan/ICPad/matrix.h | 56 ++++++ Scan/ICPad/pinout | 114 +++++++++++ Scan/ICPad/scan_loop.c | 106 ++++++++++ Scan/ICPad/scan_loop.h | 40 ++++ Scan/ICPad/setup.cmake | 33 +++ Scan/ISSILed/capabilities.kll | 32 ++- Scan/ISSILed/exampleAPI.bash | 5 +- Scan/ISSILed/led_scan.c | 320 ++++++++++++++++++++---------- Scan/MatrixARM/matrix_scan.c | 1 - Scan/UARTConnect/capabilities.kll | 2 +- Scan/UARTConnect/connect_scan.h | 1 + 16 files changed, 845 insertions(+), 112 deletions(-) create mode 100755 Keyboards/icpad.bash create mode 100644 Scan/ICPad/defaultMap.kll create mode 100644 Scan/ICPad/matrix.h create mode 100644 Scan/ICPad/pinout create mode 100644 Scan/ICPad/scan_loop.c create mode 100644 Scan/ICPad/scan_loop.h create mode 100644 Scan/ICPad/setup.cmake diff --git a/Keyboards/README.markdown b/Keyboards/README.markdown index 9240c18..857e3a9 100644 --- a/Keyboards/README.markdown +++ b/Keyboards/README.markdown @@ -28,6 +28,7 @@ Projects -------- * infinity.bash (Infinity Keyboard 2014/10/15) +* icpad.bash (Soon?) * ergodox.bash (Infinity Ergodox 2015/08/15) * template.bash (Example template for new keyboards) * whitefox.bash (Soon?) diff --git a/Keyboards/icpad.bash b/Keyboards/icpad.bash new file mode 100755 index 0000000..de299fd --- /dev/null +++ b/Keyboards/icpad.bash @@ -0,0 +1,72 @@ +#!/bin/bash +# This is a build script template +# These build scripts are just a convenience for configuring your keyboard (less daunting than CMake) +# Jacob Alexander 2015 + + + +################# +# Configuration # +################# + +# Feel free to change the variables in this section to configure your keyboard + +BuildPath="ICPad" + +## KLL Configuration ## + +# Generally shouldn't be changed, this will affect every layer +BaseMap="defaultMap" + +# This is the default layer of the keyboard +# NOTE: To combine kll files into a single layout, separate them by spaces +# e.g. DefaultMap="mylayout mylayoutmod" +DefaultMap="stdFuncMap" + +# This is where you set the additional layers +# NOTE: Indexing starts at 1 +# NOTE: Each new layer is another array entry +# e.g. PartialMaps[1]="layer1 layer1mod" +# PartialMaps[2]="layer2" +# PartialMaps[3]="layer3" +PartialMaps[1]="" + + + +########################## +# Advanced Configuration # +########################## + +# Don't change the variables in this section unless you know what you're doing +# These are useful for completely custom keyboards +# NOTE: Changing any of these variables will require a force build to compile correctly + +# Keyboard Module Configuration +ScanModule="ICPad" +MacroModule="PartialMap" +OutputModule="pjrcUSB" +DebugModule="full" + +# Microcontroller +Chip="mk20dx256vlh7" + +# Compiler Selection +Compiler="gcc" + + + +######################## +# Bash Library Include # +######################## + +# Shouldn't need to touch this section + +# Check if the library can be found +if [ ! -f cmake.bash ]; then + echo "ERROR: Cannot find 'cmake.bash'" + exit 1 +fi + +# Load the library +source cmake.bash + diff --git a/Output/pjrcUSB/arm/usb_dev.c b/Output/pjrcUSB/arm/usb_dev.c index 782f3ac..174fe8d 100644 --- a/Output/pjrcUSB/arm/usb_dev.c +++ b/Output/pjrcUSB/arm/usb_dev.c @@ -1176,6 +1176,9 @@ uint8_t usb_init() print("USB INIT"NL); #endif + // Unset usb configuration + usb_configuration = 0; + // Clear out endpoints table for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) { diff --git a/README.markdown b/README.markdown index 7039d59..f020072 100644 --- a/README.markdown +++ b/README.markdown @@ -38,7 +38,7 @@ Supported Microcontrollers * Teensy 2.0 (Partial) * Teensy 2.0++ -* Teensy 3.0 +* Teesny 3.0 * Teensy 3.1 * mk20dx128vlf5 * mk20dx256vlh7 diff --git a/Scan/ICPad/defaultMap.kll b/Scan/ICPad/defaultMap.kll new file mode 100644 index 0000000..c558967 --- /dev/null +++ b/Scan/ICPad/defaultMap.kll @@ -0,0 +1,169 @@ +Name = ICPad; +Version = 0.1; +Author = "HaaTa (Jacob Alexander) 2015"; +KLL = 0.3d; + +# Modified Date +Date = 2015-10-21; + + +S0x00 : U"Esc"; +S0x01 : U"1"; +S0x02 : U"2"; +S0x03 : U"3"; +S0x04 : U"4"; +S0x05 : U"5"; +S0x06 : U"6"; +S0x07 : U"7"; +S0x08 : U"8"; +S0x09 : U"9"; +S0x0A : U"0"; +S0x0B : U"Minus"; +S0x0C : U"Equal"; +S0x0D : U"Hash"; +S0x0E : U"Backspace"; +S0x0F : U"BackTick"; +S0x10 : U"Tab"; +S0x11 : U"Q"; +S0x12 : U"W"; +S0x13 : U"E"; +S0x14 : U"R"; +S0x15 : U"T"; +S0x16 : U"Y"; +S0x17 : U"U"; +S0x18 : U"I"; +S0x19 : U"O"; +S0x1A : U"P"; +S0x1B : U"LBrace"; +S0x1C : U"RBrace"; +S0x1D : U"Backslash"; +S0x1E : U"Delete"; +S0x1F : U"CapsLock"; +S0x20 : U"A"; +S0x21 : U"S"; +S0x22 : U"D"; +S0x23 : U"F"; +S0x24 : U"G"; +S0x25 : U"H"; +S0x26 : U"J"; +S0x27 : U"K"; +S0x28 : U"L"; +S0x29 : U"Semicolon"; +S0x2A : U"Quote"; +S0x2B : U"App"; +S0x2C : U"Enter"; +S0x2D : U"PageUp"; +S0x2E : U"LShift"; +S0x2F : U"ISO Slash"; +S0x30 : U"Z"; +S0x31 : U"X"; +S0x32 : U"C"; +S0x33 : U"V"; +S0x34 : U"B"; +S0x35 : U"N"; +S0x36 : U"M"; +S0x37 : U"Comma"; +S0x38 : U"Period"; +S0x39 : U"Slash"; +S0x3A : U"RShift"; +S0x3B : U"Up"; +S0x3C : U"PageDown"; +S0x3D : U"Ctrl"; +S0x3E : U"Function1"; +S0x3F : U"LAlt"; +S0x40 : U"Space"; +S0x41 : U"RAlt"; +S0x42 : U"Gui"; +S0x43 : U"Menu"; +S0x44 : U"Left"; +S0x45 : U"Down"; +S0x46 : U"Right"; + + +# Defines available to the ICPad Scan Module + +# Available ISSI Chips +ISSI_Chips = 2; + +# LED Default Enable Mask Override +# +# Each LED is represented by a single bit +# See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details +ISSILedMask1 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFE, 0xFE, /* C2-1 -> C2-16 */ + 0xFE, 0xFE, /* C3-1 -> C3-16 */ + 0x06, 0x06, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x60, 0x60, /* C6-1 -> C6-16 */ + 0x7F, 0x7F, /* C7-1 -> C7-16 */ + 0x7F, 0x7F, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedMask2 = " + 0xFF, 0x00, /* C1-1 -> C1-16 */ + 0xFE, 0x00, /* C2-1 -> C2-16 */ + 0xFE, 0x00, /* C3-1 -> C3-16 */ + 0x06, 0x00, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x00, 0x00, /* C6-1 -> C6-16 */ + 0x0F, 0x00, /* C7-1 -> C7-16 */ + 0x0F, 0x00, /* C8-1 -> C8-16 */ + 0x0F, 0x00, /* C9-1 -> C9-16 */ +"; + + +# LED Brightness Override +# +# Each LED channel supports 256 levels (8-bit control) +# By default, LEDs are set to 0 brightness +ISSILedBrightness1 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness2 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +"; + +# Misc +ISSILedBrightness1 = " +0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, /* C1-1 -> C1-16 */ +0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, /* C2-1 -> C2-16 */ +0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, /* C3-1 -> C3-16 */ +0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, /* C6-1 -> C6-16 */ +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, /* C7-1 -> C7-16 */ +0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, /* C8-1 -> C8-16 */ +0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness2 = " +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +0x00, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +0x00, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +"; + diff --git a/Scan/ICPad/matrix.h b/Scan/ICPad/matrix.h new file mode 100644 index 0000000..f2037e0 --- /dev/null +++ b/Scan/ICPad/matrix.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Project Includes +#include + + + +// ----- Matrix Definition ----- + +// Freescale ARM MK20's support GPIO PTA, PTB, PTC, PTD and PTE 0..31 +// Not all chips have access to all of these pins (most don't have 160 pins :P) +// +// NOTE: +// Before using a pin, make sure it supports being a GPIO *and* doesn't have a default pull-up/pull-down +// Checking this is completely on the ownness of the user + +// MDErgo1 +// +// Column (Strobe) - 9 Total +// PTB2,3,18,19 +// PTC0,9..11 +// PTD0 +// +// Rows (Sense) - 5 Total +// PTD1,4..7 + +// Define Rows (Sense) and Columns (Strobes) +GPIO_Pin Matrix_cols[] = { gpio(B,2), gpio(B,3), gpio(B,18), gpio(B,19), gpio(C,0), gpio(C,8), gpio(C,9), gpio(C,10), gpio(C,11) }; +GPIO_Pin Matrix_rows[] = { gpio(D,0), gpio(D,1), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7), gpio(C,1), gpio(C,2) }; + +// Define type of scan matrix +Config Matrix_type = Config_Pulldown; + diff --git a/Scan/ICPad/pinout b/Scan/ICPad/pinout new file mode 100644 index 0000000..96db34c --- /dev/null +++ b/Scan/ICPad/pinout @@ -0,0 +1,114 @@ +Pin Usage +========= + +mk20dx256vlh7 + + ---- +|Keys| + ---- + +* Strobe (Columns) + +PTB2 +PTB3 +PTB18 +PTB19 +PTC0 +PTC8 +PTC9 +PTC10 +PTC11 + +* Sense (Rows) + +PTD0 +PTD1 +PTD4 +PTD5 +PTD6 +PTD7 +PTC1 +PTC2 + + + ----- +|Clock| + ----- + +PTA18 <-> PTA19 + + + --- +|I2C| + --- + +* IS31FL3731C + +PTB0 - SCL0 (add header pin, label as SCL0) +PTB1 - SDA0 (add header pin, label as SDA0) +PTB17 - INTB Chip 1 +PTB16 - SDB (tied to all Chips, hardware shutdown) + + + + --- +|DAC| + --- + +DAC0 (N/C) + + + ---- +|UART| + ---- + +* Comm - For bi-directional communication between halves + +PTA1 - RX0 (Master Side) +PTA2 - TX0 (Master Side) + +PTE1 - RX1 (Slave Side) +PTE0 - TX1 (Slave Side) + +PTD2 - RX2 (UART Debug Header) +PTD3 - TX2 (UART Debug Header) + + + ----- +|Debug| + ----- + +* SWD - (Main reflash header) + +PTA0 (Pull-down) +PTA3 (Pull-up) + +* LEDs + +PTA5 (LED only for PCB, not Teensy) + +* UARTs + +PTD2 - RX2 (UART Debug Header, label as RX2) +PTD3 - TX2 (UART Debug Header, label as TX2) + + + ------ +|Unused| + ------ + +* GPIO + +PTA4 +PTA12 +PTA13 +PTC3 +PTC4 +PTC5 +PTC6 +PTC7 + +* Analog + +TODO + diff --git a/Scan/ICPad/scan_loop.c b/Scan/ICPad/scan_loop.c new file mode 100644 index 0000000..c1db646 --- /dev/null +++ b/Scan/ICPad/scan_loop.c @@ -0,0 +1,106 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Local Includes +#include "scan_loop.h" + + + +// ----- Function Declarations ----- + +// ----- Variables ----- + +// Number of scans since the last USB send +uint16_t Scan_scanCount = 0; + + + +// ----- Functions ----- + +// Setup +inline void Scan_setup() +{ + // Setup Port Swap module + Port_setup(); + + // Setup UART Connect, if Output_Available, this is the master node + Connect_setup( Output_Available ); + + // Setup GPIO pins for matrix scanning + Matrix_setup(); + + // Setup ISSI chip to control the leds + LED_setup(); + + // Reset scan count + Scan_scanCount = 0; +} + + +// Main Detection Loop +inline uint8_t Scan_loop() +{ + // Port Swap detection + Port_scan(); + + // Scan Matrix + Matrix_scan( Scan_scanCount++ ); + + // Process any interconnect commands + Connect_scan(); + + // Process any LED events + LED_scan(); + + return 0; +} + + +// Signal from Macro Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithMacro( uint8_t sentKeys ) +{ +} + + +// Signal from Output Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithOutput( uint8_t sentKeys ) +{ + // Reset scan loop indicator (resets each key debounce state) + // TODO should this occur after USB send or Macro processing? + Scan_scanCount = 0; +} + diff --git a/Scan/ICPad/scan_loop.h b/Scan/ICPad/scan_loop.h new file mode 100644 index 0000000..17a06fc --- /dev/null +++ b/Scan/ICPad/scan_loop.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Compiler Includes +#include + + + +// ----- Functions ----- + +// Functions to be called by main.c +void Scan_setup( void ); +uint8_t Scan_loop( void ); + +// Call-backs +void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module +void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module + diff --git a/Scan/ICPad/setup.cmake b/Scan/ICPad/setup.cmake new file mode 100644 index 0000000..5696ccd --- /dev/null +++ b/Scan/ICPad/setup.cmake @@ -0,0 +1,33 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2015 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Required Sub-modules +# +AddModule ( Scan ISSILed ) +AddModule ( Scan MatrixARM ) +AddModule ( Scan PortSwap ) +AddModule ( Scan UARTConnect ) + + +### +# Module C files +# +set ( Module_SRCS + scan_loop.c +) + + +### +# Compiler Family Compatibility +# +set ( ModuleCompatibility + arm +) + diff --git a/Scan/ISSILed/capabilities.kll b/Scan/ISSILed/capabilities.kll index 6ecd4f6..77cb864 100644 --- a/Scan/ISSILed/capabilities.kll +++ b/Scan/ISSILed/capabilities.kll @@ -1,7 +1,7 @@ Name = ISSILedCapabilities; Version = 0.2; Author = "HaaTa (Jacob Alexander) 2015"; -KLL = 0.3c; +KLL = 0.3d; # Modified Date Date = 2015-10-09; @@ -24,6 +24,10 @@ ledControl => LED_control_capability( mode : 1, amount : 1, index : 2 ); # Defines available to the ISSILed sub-module +# Available ISSI Chips +ISSI_Chips => ISSI_Chips_define; +ISSI_Chips = 1; # 1 by default + # LED Default Enable Mask # # By default, all LEDs are enabled @@ -43,6 +47,19 @@ ISSILedMask1 = " 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; +ISSILedMask2 => ISSILedMask2_define; +ISSILedMask2 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFF, 0xFF, /* C2-1 -> C2-16 */ + 0xFF, 0xFF, /* C3-1 -> C3-16 */ + 0xFF, 0xFF, /* C4-1 -> C4-16 */ + 0xFF, 0xFF, /* C5-1 -> C5-16 */ + 0xFF, 0xFF, /* C6-1 -> C6-16 */ + 0xFF, 0xFF, /* C7-1 -> C7-16 */ + 0xFF, 0xFF, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + # LED Default Brightness # # By default, all LEDs are set to max brightness @@ -60,6 +77,19 @@ ISSILedBrightness1 = " 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; +ISSILedBrightness2 => ISSILedBrightness2_define; +ISSILedBrightness2 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + # Example starting from 0 brightness to 0x8F ISSILedBrightness_example = " 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ diff --git a/Scan/ISSILed/exampleAPI.bash b/Scan/ISSILed/exampleAPI.bash index 5d66c37..a54dd0f 100755 --- a/Scan/ISSILed/exampleAPI.bash +++ b/Scan/ISSILed/exampleAPI.bash @@ -27,5 +27,8 @@ printf "\r" > $SERIALPORT # Page 0x0A is used for configuration # See the datasheet for full details http://www.issi.com/WW/pdf/31FL3731C.pdf sleep 0.1 -printf "ledWPage 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT +printf "ledWPage 0xE8 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 1 +printf "ledWPage 0xEA 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 2 +printf "ledWPage 0xEC 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 3 +printf "ledWPage 0xEE 0x00 0x24 0x10 0x20 0x30 0x40 0x50\r" > $SERIALPORT # Channel 4 diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index 8a92b76..6a639a1 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -37,13 +37,53 @@ // ----- Defines ----- +// Increase buffer sizes for RGB +#ifdef ISSI_RGB_define +#define I2C_TxBufferLength 600 +#define I2C_RxBufferLength 16 +#else #define I2C_TxBufferLength 300 #define I2C_RxBufferLength 8 +#endif -#define LED_BufferLength 144 +#define LED_BufferLength 144 +#define LED_EnableBufferLength 18 -// TODO Needs to be defined per keyboard -#define LED_TotalChannels 144 +#define LED_TotalChannels (144 * ISSI_Chips_define) + +// ISSI Addresses +// IS31FL3731 (max 4 channels per bus) +#if 1 +#define ISSI_Ch1 0xE8 +#define ISSI_Ch2 0xEA +#define ISSI_Ch3 0xEC +#define ISSI_Ch4 0xEE + +// IS31FL3732 (max 16 channels per bus) +#else +#define ISSI_Ch1 0xB0 +#define ISSI_Ch2 0xB2 +#define ISSI_Ch3 0xB4 +#define ISSI_Ch4 0xB6 +#endif + + + +// ----- Macros ----- + +#define LED_MaskDefine(ch) \ + { \ + ISSI_Ch##ch, /* I2C address */ \ + 0x00, /* Starting register address */ \ + { ISSILedMask##ch##_define }, \ + } + +#define LED_BrightnessDefine(ch) \ + { \ + ISSI_Ch##ch, /* I2C address */ \ + 0x24, /* Starting register address */ \ + { ISSILedBrightness##ch##_define }, \ + } @@ -63,6 +103,12 @@ typedef struct LED_Buffer { uint8_t buffer[LED_BufferLength]; } LED_Buffer; +typedef struct LED_EnableBuffer { + uint8_t i2c_addr; + uint8_t reg_addr; + uint8_t buffer[LED_EnableBufferLength]; +} LED_EnableBuffer; + // ----- Function Declarations ----- @@ -93,7 +139,7 @@ CLIDict_Entry( ledCtrl, "Basic LED control. Args: []" CLIDict_Entry( ledRPage, "Read the given register page." ); CLIDict_Entry( ledStart, "Disable software shutdown." ); CLIDict_Entry( ledTest, "Test out the led pages." ); -CLIDict_Entry( ledWPage, "Write to given register page starting at address. i.e. 0x2 0x24 0xF0 0x12" ); +CLIDict_Entry( ledWPage, "Write to given register page starting at address. i.e. 0xE8 0x2 0x24 0xF0 0x12" ); CLIDict_Entry( ledZero, "Zero out LED register pages (non-configuration)." ); CLIDict_Def( ledCLIDict, "ISSI LED Module Commands" ) = { @@ -118,23 +164,42 @@ volatile uint8_t I2C_RxBufferPtr[ I2C_TxBufferLength ]; volatile I2C_Buffer I2C_TxBuffer = { 0, 0, 0, I2C_TxBufferLength, (uint8_t*)I2C_TxBufferPtr }; volatile I2C_Buffer I2C_RxBuffer = { 0, 0, 0, I2C_RxBufferLength, (uint8_t*)I2C_RxBufferPtr }; -LED_Buffer LED_pageBuffer; +LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; -// A bit mask determining which LEDs are enabled in the ISSI chip -const uint8_t LED_ledEnableMask1[] = { - 0xE8, // I2C address - 0x00, // Starting register address - ISSILedMask1_define +// Enable mask and default brightness for ISSI chip channel +const LED_EnableBuffer LED_ledEnableMask[ISSI_Chips_define] = { + LED_MaskDefine( 1 ), +#if ISSI_Chips_define >= 2 + LED_MaskDefine( 2 ), +#endif +#if ISSI_Chips_define >= 3 + LED_MaskDefine( 3 ), +#endif +#if ISSI_Chips_define >= 4 + LED_MaskDefine( 4 ), +#endif }; // Default LED brightness -const uint8_t LED_defaultBrightness1[] = { - 0xE8, // I2C address - 0x24, // Starting register address - ISSILedBrightness1_define +const LED_Buffer LED_defaultBrightness[ISSI_Chips_define] = { + LED_BrightnessDefine( 1 ), +#if ISSI_Chips_define >= 2 + LED_BrightnessDefine( 2 ), +#endif +#if ISSI_Chips_define >= 3 + LED_BrightnessDefine( 3 ), +#endif +#if ISSI_Chips_define >= 4 + LED_BrightnessDefine( 4 ), +#endif }; +#if ISSI_Chips_define >= 5 +#error "Invalid number of ISSI Chips" +#endif + + // ----- Interrupt Functions ----- @@ -274,7 +339,10 @@ inline void I2C_setup() PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); // SCL Frequency Divider - // 400kHz -> 120 (0x85) @ 48 MHz F_BUS + // 1.8 MBaud (likely higher than spec) + // 0x85 -> 36 MHz / (4 * 5) = 1.8 MBaud + // 0x80 => mul(4) + // 0x05 => ICL(5) I2C0_F = 0x85; I2C0_FLT = 4; I2C0_C1 = I2C_C1_IICEN; @@ -284,14 +352,14 @@ inline void I2C_setup() NVIC_ENABLE_IRQ( IRQ_I2C0 ); } -void LED_zeroPages( uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) +void LED_zeroPages( uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) { // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, 0x00 }; + uint8_t pageSetup[] = { addr, 0xFD, 0x00 }; // Max length of a page + chip id + reg start uint8_t fullPage[ 0xB4 + 2 ] = { 0 }; // Max size of page - fullPage[0] = 0xE8; // Set chip id + fullPage[0] = addr; // Set chip id fullPage[1] = startReg; // Set start reg // Iterate through given pages, zero'ing out the given register regions @@ -310,10 +378,10 @@ void LED_zeroPages( uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8 } } -void LED_sendPage( uint8_t *buffer, uint8_t len, uint8_t page ) +void LED_sendPage( uint8_t addr, uint8_t *buffer, uint8_t len, uint8_t page ) { // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, page }; + uint8_t pageSetup[] = { addr, 0xFD, page }; // Setup page while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) @@ -325,58 +393,55 @@ void LED_sendPage( uint8_t *buffer, uint8_t len, uint8_t page ) } -void LED_writeReg( uint8_t reg, uint8_t val, uint8_t page ) +// Write address +void LED_writeReg( uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) { // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, page }; + uint8_t pageSetup[] = { addr, 0xFD, page }; // Reg Write Setup - uint8_t writeData[] = { 0xE8, reg, val }; + uint8_t writeData[] = { addr, reg, val }; // Setup page while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) delay(1); + // Write register while ( I2C_Send( writeData, sizeof( writeData ), 0 ) == 0 ) delay(1); } -void LED_readPage( uint8_t len, uint8_t page ) +// Read address +void LED_readReg( uint8_t addr, uint8_t reg, uint8_t page ) { // Software shutdown must be enabled to read registers - LED_writeReg( 0x0A, 0x00, 0x0B ); + LED_writeReg( addr, 0x0A, 0x00, 0x0B ); // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, page }; + uint8_t pageSetup[] = { addr, 0xFD, page }; // Setup page while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) delay(1); // Register Setup - uint8_t regSetup[] = { 0xE8, 0x00 }; + uint8_t regSetup[] = { addr, reg }; - // Read each register in the page - for ( uint8_t reg = 0; reg < len; reg++ ) - { - // Update register to read - regSetup[1] = reg; + // Configure register + while ( I2C_Send( regSetup, sizeof( regSetup ), 0 ) == 0 ) + delay(1); - // Configure register - while ( I2C_Send( regSetup, sizeof( regSetup ), 0 ) == 0 ) - delay(1); + // Register Read Command + uint8_t regReadCmd[] = { addr | 0x1 }; - // Register Read Command - uint8_t regReadCmd[] = { 0xE9 }; + // Request single register byte + while ( I2C_Send( regReadCmd, sizeof( regReadCmd ), 1 ) == 0 ) + delay(1); - // Request single register byte - while ( I2C_Send( regReadCmd, sizeof( regReadCmd ), 1 ) == 0 ) - delay(1); - dbug_print("NEXT"); - } + // TODO get byte from buffer // Disable software shutdown - LED_writeReg( 0x0A, 0x01, 0x0B ); + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); } // Setup @@ -388,9 +453,29 @@ inline void LED_setup() // Initialize I2C I2C_setup(); + // Setup LED_pageBuffer addresses and brightness section + LED_pageBuffer[0].i2c_addr = ISSI_Ch1; + LED_pageBuffer[0].reg_addr = 0x24; +#if ISSI_Chips_define >= 2 + LED_pageBuffer[1].i2c_addr = ISSI_Ch2; + LED_pageBuffer[1].reg_addr = 0x24; +#endif +#if ISSI_Chips_define >= 3 + LED_pageBuffer[2].i2c_addr = ISSI_Ch3; + LED_pageBuffer[2].reg_addr = 0x24; +#endif +#if ISSI_Chips_define >= 4 + LED_pageBuffer[3].i2c_addr = ISSI_Ch4; + LED_pageBuffer[3].reg_addr = 0x24; +#endif + // Zero out Frame Registers // This needs to be done before disabling the hardware shutdown (or the leds will do undefined things) - LED_zeroPages( 0x0B, 1, 0x00, 0x0C ); // Control Registers + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_zeroPages( addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers + } // Disable Hardware shutdown of ISSI chip (pull high) GPIOB_PDDR |= (1<<16); @@ -398,16 +483,22 @@ inline void LED_setup() GPIOB_PSOR |= (1<<16); // Clear LED Pages - LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers - // Enable LEDs based upon mask - LED_sendPage( (uint8_t*)LED_ledEnableMask1, sizeof( LED_ledEnableMask1 ), 0 ); - // Set default brightness - LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 0 ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers + LED_sendPage( addr, (uint8_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ), 0 ); + LED_sendPage( addr, (uint8_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); + } // Disable Software shutdown of ISSI chip - LED_writeReg( 0x0A, 0x01, 0x0B ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + } } @@ -635,11 +726,6 @@ uint8_t I2C_Send( uint8_t *data, uint8_t sendLen, uint8_t recvLen ) // LED State processing loop inline uint8_t LED_scan() { - - // I2C Busy - // S & I2C_S_BUSY - //I2C_S_BUSY - return 0; } @@ -667,59 +753,57 @@ typedef struct LedControl { void LED_control( LedControl *control ) { - // Only send if we've completed all other transactions - /* - if ( I2C_TxBuffer.sequencePos > 0 ) - return; - */ - // Configure based upon the given mode - // TODO Perhaps do gamma adjustment? - switch ( control->mode ) + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - case LedControlMode_brightness_decrease: - // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ control->index ] -= control->amount; - break; - - case LedControlMode_brightness_increase: - // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ control->index ] += control->amount; - break; - - case LedControlMode_brightness_set: - LED_pageBuffer.buffer[ control->index ] = control->amount; - break; - - case LedControlMode_brightness_decrease_all: - for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + // TODO Perhaps do gamma adjustment? + switch ( control->mode ) { + case LedControlMode_brightness_decrease: // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ channel ] -= control->amount; - } - break; + LED_pageBuffer[ ch ].buffer[ control->index ] -= control->amount; + break; - case LedControlMode_brightness_increase_all: - for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) - { + case LedControlMode_brightness_increase: // Don't worry about rolling over, the cycle is quick - LED_pageBuffer.buffer[ channel ] += control->amount; - } - break; + LED_pageBuffer[ ch ].buffer[ control->index ] += control->amount; + break; - case LedControlMode_brightness_set_all: - for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) - { - LED_pageBuffer.buffer[ channel ] = control->amount; + case LedControlMode_brightness_set: + LED_pageBuffer[ ch ].buffer[ control->index ] = control->amount; + break; + + case LedControlMode_brightness_decrease_all: + for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + { + // Don't worry about rolling over, the cycle is quick + LED_pageBuffer[ ch ].buffer[ channel ] -= control->amount; + } + break; + + case LedControlMode_brightness_increase_all: + for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + { + // Don't worry about rolling over, the cycle is quick + LED_pageBuffer[ ch ].buffer[ channel ] += control->amount; + } + break; + + case LedControlMode_brightness_set_all: + for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ ) + { + LED_pageBuffer[ ch ].buffer[ channel ] = control->amount; + } + break; } - break; } // Sync LED buffer with ISSI chip buffer // TODO Support multiple frames - LED_pageBuffer.i2c_addr = 0xE8; // Chip 1 - LED_pageBuffer.reg_addr = 0x24; // Brightness section - LED_sendPage( (uint8_t*)&LED_pageBuffer, sizeof( LED_Buffer ), 0 ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_sendPage( LED_pageBuffer[ ch ].i2c_addr, (uint8_t*)&LED_pageBuffer[ ch ], sizeof( LED_Buffer ), 0 ); + } } uint8_t LED_control_timer = 0; @@ -922,6 +1006,7 @@ void cliFunc_i2cRecv( char* args ) // TODO Currently not working correctly void cliFunc_ledRPage( char* args ) { + /* TODO Use readReg command instead // Parse number from argument // NOTE: Only first argument is used char* arg1Ptr; @@ -939,8 +1024,9 @@ void cliFunc_ledRPage( char* args ) // No \r\n by default after the command is entered print( NL ); - LED_readPage( 0x1, page ); - //LED_readPage( 0xB4, page ); + // TODO, multi-channel + LED_readPage( ISSI_Ch1, 0xB4, page ); + */ } void cliFunc_ledWPage( char* args ) @@ -949,14 +1035,23 @@ void cliFunc_ledWPage( char* args ) char* arg1Ptr; char* arg2Ptr = args; - // First process page and starting address + // First specify the write address curArgs = arg2Ptr; CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); // Stop processing args if no more are found if ( *arg1Ptr == '\0' ) return; - uint8_t page[] = { 0xE8, 0xFD, numToInt( arg1Ptr ) }; + uint8_t addr = numToInt( arg1Ptr ); + + // Next process page and starting address + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + return; + uint8_t page[] = { addr, 0xFD, numToInt( arg1Ptr ) }; curArgs = arg2Ptr; CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); @@ -964,7 +1059,7 @@ void cliFunc_ledWPage( char* args ) // Stop processing args if no more are found if ( *arg1Ptr == '\0' ) return; - uint8_t data[] = { 0xE8, numToInt( arg1Ptr ), 0 }; + uint8_t data[] = { addr, numToInt( arg1Ptr ), 0 }; // Set the register page while ( I2C_Send( page, sizeof( page ), 0 ) == 0 ) @@ -994,23 +1089,34 @@ void cliFunc_ledWPage( char* args ) void cliFunc_ledStart( char* args ) { print( NL ); // No \r\n by default after the command is entered - LED_zeroPages( 0x0B, 1, 0x00, 0x0C ); // Control Registers - //LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers - LED_writeReg( 0x0A, 0x01, 0x0B ); - LED_sendPage( (uint8_t*)LED_ledEnableMask1, sizeof( LED_ledEnableMask1 ), 0 ); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_zeroPages( LED_ledEnableMask[ ch ].i2c_addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers + //LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers + LED_writeReg( LED_ledEnableMask[ ch ].i2c_addr, 0x0A, 0x01, 0x0B ); + LED_sendPage( LED_ledEnableMask[ ch ].i2c_addr, (uint8_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ), 0 ); + } } void cliFunc_ledTest( char* args ) { print( NL ); // No \r\n by default after the command is entered - LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 0 ); + + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_sendPage( LED_defaultBrightness[ ch ].i2c_addr, (uint8_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); + } } void cliFunc_ledZero( char* args ) { print( NL ); // No \r\n by default after the command is entered - LED_zeroPages( 0x00, 8, 0x24, 0xB4 ); // Only PWMs + + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_zeroPages( LED_defaultBrightness[ ch ].i2c_addr, 0x00, 8, 0x24, 0xB4 ); // Only PWMs + } } void cliFunc_ledCtrl( char* args ) diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index a9018df..8463b26 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -196,7 +196,6 @@ void Matrix_setup() print( NL ); info_msg("Max Keys: "); printHex( Matrix_maxKeys ); - print( NL ); // Clear out Debounce Array for ( uint8_t item = 0; item < Matrix_maxKeys; item++ ) diff --git a/Scan/UARTConnect/capabilities.kll b/Scan/UARTConnect/capabilities.kll index bab1b61..67aafe0 100644 --- a/Scan/UARTConnect/capabilities.kll +++ b/Scan/UARTConnect/capabilities.kll @@ -26,7 +26,7 @@ UARTConnectBaudFine => UARTConnectBaudFine_define; # Thus baud setting = 26 # NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet # Baud fine setting = 0x02 -UARTConnectBaud = 1; # 4.5 Mbpsa @ 72 MHz +UARTConnectBaud = 1; # 4.5 Mbps @ 72 MHz UARTConnectBaudFine = 0x0; #UARTConnectBaud = 39; # 115385 bps @ 72 MHz (close to 115200) diff --git a/Scan/UARTConnect/connect_scan.h b/Scan/UARTConnect/connect_scan.h index cdd7ed0..389dce7 100644 --- a/Scan/UARTConnect/connect_scan.h +++ b/Scan/UARTConnect/connect_scan.h @@ -163,6 +163,7 @@ extern uint8_t Connect_master; // Set if master void Connect_setup( uint8_t master ); void Connect_scan(); +void Connect_reset(); void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes ); void Connect_send_RemoteCapability( uint8_t id, uint8_t capabilityIndex, uint8_t state, uint8_t stateType, uint8_t numArgs, uint8_t *args ); From 571c7ad35a9675c9c8f083e9ddc745f288724bae Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sat, 12 Dec 2015 14:37:05 -0800 Subject: [PATCH 03/30] Adding USB port swapping (when supported) to the bootloader - Every 1000 ms, if no USB connection detected, swap to the other USB port --- Bootloader/main.c | 42 ++++++++++++++++++++++++++++++++++++++++++ Lib/mk20dx.c | 4 ++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Bootloader/main.c b/Bootloader/main.c index aabaeeb..124e82d 100644 --- a/Bootloader/main.c +++ b/Bootloader/main.c @@ -17,12 +17,17 @@ // ----- Includes ----- +// Project Includes +#include + // Local Includes #include "mchck.h" #include "dfu.desc.h" #include "debug.h" +#include "usb-internal.h" + // ----- Variables ----- @@ -173,6 +178,9 @@ static struct dfu_ctx dfu_ctx; void init_usb_bootloader( int config ) { dfu_init( setup_read, setup_write, finish_write, &dfu_ctx ); + + // Make sure SysTick counter is disabled + SYST_CSR = 0; } void main() @@ -224,9 +232,43 @@ void main() flash_prepare_flashing(); usb_init( &dfu_device ); + +#if defined(_mk20dx256vlh7_) // Kiibohd-dfu + // PTA13 - USB Swap + // Start, disabled + GPIOA_PDDR |= (1<<13); + PORTA_PCR13 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + GPIOA_PCOR |= (1<<13); + + #define USBPortSwapDelay_ms 1000 + // For keyboards with dual usb ports, doesn't do anything on keyboards without them + // If a USB connection is not detected in 2 seconds, switch to the other port to see if it's plugged in there + uint32_t last_ms = systick_millis_count; + for (;;) + { + usb_poll(); + + // Only check for swapping after delay + uint32_t wait_ms = systick_millis_count - last_ms; + if ( wait_ms < USBPortSwapDelay_ms ) + { + continue; + } + + last_ms = systick_millis_count; + + // USB not initialized, attempt to swap + if ( usb.state != USBD_STATE_ADDRESS ) + { + print("USB not initializing, port swapping (if supported)"); + GPIOA_PTOR |= (1<<13); + } + } +#else for (;;) { usb_poll(); } +#endif } diff --git a/Lib/mk20dx.c b/Lib/mk20dx.c index ec6908c..e8b77f8 100644 --- a/Lib/mk20dx.c +++ b/Lib/mk20dx.c @@ -527,7 +527,7 @@ void ResetHandler() // Also checking for ARM lock-up signal (invalid firmware image) // RCM_SRS1 & 0x02 if ( // PIN (External Reset Pin/Switch) - RCM_SRS0 & 0x40 + RCM_SRS0 & 0x40 // WDOG (Watchdog timeout) || RCM_SRS0 & 0x20 // LOCKUP (ARM Core LOCKUP event) @@ -690,11 +690,11 @@ void ResetHandler() #endif -#if !defined(_bootloader_) // Initialize the SysTick counter SYST_RVR = (F_CPU / 1000) - 1; SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE; +#if !defined(_bootloader_) __enable_irq(); #else // Disable Watchdog for bootloader From 415a0aab52e4bd213f891af6ecf357ce126408f9 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sat, 12 Dec 2015 15:16:57 -0800 Subject: [PATCH 04/30] Adding automatic port swapping to ICPad - Works the same as the bootloader variant, waits 1000 ms before attempting to swap Only swaps if USB not already intialized If USB never initializes, will swap forever TODO - Stop swapping if UARTConnect detected and initialized --- Scan/MatrixARM/matrix_scan.c | 1 + Scan/PortSwap/capabilities.kll | 14 +++ Scan/PortSwap/port_scan.c | 199 +++++++++++++++++++++++++++++++++ Scan/PortSwap/port_scan.h | 30 +++++ Scan/PortSwap/setup.cmake | 30 +++++ 5 files changed, 274 insertions(+) create mode 100644 Scan/PortSwap/capabilities.kll create mode 100644 Scan/PortSwap/port_scan.c create mode 100644 Scan/PortSwap/port_scan.h create mode 100644 Scan/PortSwap/setup.cmake diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index 8463b26..a9018df 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -196,6 +196,7 @@ void Matrix_setup() print( NL ); info_msg("Max Keys: "); printHex( Matrix_maxKeys ); + print( NL ); // Clear out Debounce Array for ( uint8_t item = 0; item < Matrix_maxKeys; item++ ) diff --git a/Scan/PortSwap/capabilities.kll b/Scan/PortSwap/capabilities.kll new file mode 100644 index 0000000..347f39b --- /dev/null +++ b/Scan/PortSwap/capabilities.kll @@ -0,0 +1,14 @@ +Name = PortSwapCapabilities; +Version = 0.1; +Author = "HaaTa (Jacob Alexander) 2015"; +KLL = 0.3d; + +# Modified Date +Date = 2015-10-23; + +# Cross interconnect pins, required for complex cabling arrangements +portCross => Port_cross_capability(); + +# Capability to swap the USB port mapping +portSwap => Port_swap_capability(); + diff --git a/Scan/PortSwap/port_scan.c b/Scan/PortSwap/port_scan.c new file mode 100644 index 0000000..40efc9a --- /dev/null +++ b/Scan/PortSwap/port_scan.c @@ -0,0 +1,199 @@ +/* Copyright (C) 2015 by Jacob Alexander + * + * This file 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, either version 3 of the License, or + * (at your option) any later version. + * + * This file 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 file. If not, see . + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include +#include + +// USB Includes +#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) +#include +#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) +#include +#endif + +// Interconnect Includes +#include + +// Local Includes +#include "port_scan.h" + + + +// ----- Defines ----- + + + +// ----- Structs ----- + + + +// ----- Function Declarations ----- + +// CLI Functions +void cliFunc_portCross( char* args ); +void cliFunc_portSwap ( char* args ); + + + +// ----- Variables ----- + +uint32_t Port_lastcheck_ms; + +// Scan Module command dictionary +CLIDict_Entry( portCross, "Cross interconnect pins." ); +CLIDict_Entry( portSwap, "Swap USB ports manually, forces usb and interconnect to re-negotiate if necessary." ); + +CLIDict_Def( portCLIDict, "Port Swap Module Commands" ) = { + CLIDict_Item( portCross ), + CLIDict_Item( portSwap ), + { 0, 0, 0 } // Null entry for dictionary end +}; + + + +// ----- Functions ----- + +void Port_swap() +{ + info_print("USB Port Swap"); + + // PTA13 - USB Swap + GPIOA_PTOR |= (1<<13); + + // Re-initialize usb + // Call usb_configured() to check if usb is ready + usb_init(); +} + +void Port_cross() +{ + info_print("Interconnect Line Cross"); + + // PTA12 - UART Tx/Rx cross-over + GPIOA_PTOR |= (1<<12); + + // Reset interconnects + Connect_reset(); +} + +// Setup +inline void Port_setup() +{ + // Register Scan CLI dictionary + CLI_registerDictionary( portCLIDict, portCLIDictName ); + + // PTA12 - UART Tx/Rx cross-over + // Start, disabled + GPIOA_PDDR |= (1<<12); + PORTA_PCR12 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + GPIOA_PCOR |= (1<<12); + + // PTA13 - USB Swap + // Start, disabled + GPIOA_PDDR |= (1<<13); + PORTA_PCR13 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + GPIOA_PCOR |= (1<<13); + + // Starting point for automatic port swapping + Port_lastcheck_ms = systick_millis_count; +} + +// Port State processing loop +inline uint8_t Port_scan() +{ + // TODO Add in interconnect line cross + + #define USBPortSwapDelay_ms 1000 + // Wait 1000 ms before checking + // Only check for swapping after delay + uint32_t wait_ms = systick_millis_count - Port_lastcheck_ms; + if ( wait_ms > USBPortSwapDelay_ms ) + { + // Update timeout + Port_lastcheck_ms = systick_millis_count; + + // USB not initialized, attempt to swap + if ( !usb_configured() ) + { + Port_swap(); + } + } + + return 0; +} + + + +// ----- Capabilities ----- + +void Port_swap_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("Port_swap_capability()"); + return; + } + + // Only only release + // TODO Analog + if ( state != 0x03 ) + return; + + Port_swap(); +} + +void Port_cross_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("Port_cross_capability()"); + return; + } + + // Only only release + // TODO Analog + if ( state != 0x03 ) + return; + + Port_cross(); +} + + + +// ----- CLI Command Functions ----- + +void cliFunc_portSwap( char* args ) +{ + print( NL ); + Port_swap(); +} + +void cliFunc_portCross( char* args ) +{ + print( NL ); + Port_cross(); +} + diff --git a/Scan/PortSwap/port_scan.h b/Scan/PortSwap/port_scan.h new file mode 100644 index 0000000..0e6cb2f --- /dev/null +++ b/Scan/PortSwap/port_scan.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2015 by Jacob Alexander + * + * This file 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, either version 3 of the License, or + * (at your option) any later version. + * + * This file 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 file. If not, see . + */ + +#pragma once + +// ----- Includes ----- + +// Compiler Includes +#include + + + +// ----- Functions ----- + +void Port_setup(); +uint8_t Port_scan(); + diff --git a/Scan/PortSwap/setup.cmake b/Scan/PortSwap/setup.cmake new file mode 100644 index 0000000..035377a --- /dev/null +++ b/Scan/PortSwap/setup.cmake @@ -0,0 +1,30 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2015 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Sub-module flag, cannot be included stand-alone +# +set ( SubModule 1 ) + + +### +# Module C files +# +set ( Module_SRCS + port_scan.c +) + + +### +# Compiler Family Compatibility +# +set ( ModuleCompatibility + arm +) + From f501a0e196d0ef9b20e74fba5a93bf3e262b95f7 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Mon, 21 Dec 2015 15:15:20 -0800 Subject: [PATCH 05/30] Adding support for 4 ISSI chips --- Scan/ISSILed/capabilities.kll | 52 +++++++++++ Scan/KType/defaultMap.kll | 165 ++++++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) diff --git a/Scan/ISSILed/capabilities.kll b/Scan/ISSILed/capabilities.kll index 77cb864..6aaad88 100644 --- a/Scan/ISSILed/capabilities.kll +++ b/Scan/ISSILed/capabilities.kll @@ -60,6 +60,32 @@ ISSILedMask2 = " 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; +ISSILedMask3 => ISSILedMask3_define; +ISSILedMask3 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFF, 0xFF, /* C2-1 -> C2-16 */ + 0xFF, 0xFF, /* C3-1 -> C3-16 */ + 0xFF, 0xFF, /* C4-1 -> C4-16 */ + 0xFF, 0xFF, /* C5-1 -> C5-16 */ + 0xFF, 0xFF, /* C6-1 -> C6-16 */ + 0xFF, 0xFF, /* C7-1 -> C7-16 */ + 0xFF, 0xFF, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedMask4 => ISSILedMask4_define; +ISSILedMask4 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFF, 0xFF, /* C2-1 -> C2-16 */ + 0xFF, 0xFF, /* C3-1 -> C3-16 */ + 0xFF, 0xFF, /* C4-1 -> C4-16 */ + 0xFF, 0xFF, /* C5-1 -> C5-16 */ + 0xFF, 0xFF, /* C6-1 -> C6-16 */ + 0xFF, 0xFF, /* C7-1 -> C7-16 */ + 0xFF, 0xFF, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + # LED Default Brightness # # By default, all LEDs are set to max brightness @@ -90,6 +116,32 @@ ISSILedBrightness2 = " 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; +ISSILedBrightness3 => ISSILedBrightness3_define; +ISSILedBrightness3 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness4 => ISSILedBrightness4_define; +ISSILedBrightness4 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + # Example starting from 0 brightness to 0x8F ISSILedBrightness_example = " 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ diff --git a/Scan/KType/defaultMap.kll b/Scan/KType/defaultMap.kll index 3f9c632..ea4e3c9 100644 --- a/Scan/KType/defaultMap.kll +++ b/Scan/KType/defaultMap.kll @@ -95,3 +95,168 @@ S0x54 : U"Left"; S0x55 : U"Down"; S0x56 : U"Right"; +# Available ISSI Chips +ISSI_Chips = 4; # 1 by default + +# LED Default Enable Mask +# +# By default, all LEDs are enabled +# However, this may cause issuse with some led matrices, so it is recommended to disable unused positions +# Each LED is represented by a single bit +# See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details +ISSILedMask1 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFE, 0xFE, /* C2-1 -> C2-16 */ + 0xFE, 0xFE, /* C3-1 -> C3-16 */ + 0x06, 0x06, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x60, 0x60, /* C6-1 -> C6-16 */ + 0x7F, 0x7F, /* C7-1 -> C7-16 */ + 0x7F, 0x7F, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedMask2 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFE, 0xFE, /* C2-1 -> C2-16 */ + 0xFE, 0xFE, /* C3-1 -> C3-16 */ + 0x06, 0x06, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x60, 0x60, /* C6-1 -> C6-16 */ + 0x7F, 0x7F, /* C7-1 -> C7-16 */ + 0x7F, 0x7F, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedMask3 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFE, 0xFE, /* C2-1 -> C2-16 */ + 0xFE, 0xFE, /* C3-1 -> C3-16 */ + 0x06, 0x06, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x60, 0x60, /* C6-1 -> C6-16 */ + 0x7F, 0x7F, /* C7-1 -> C7-16 */ + 0x7F, 0x7F, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +ISSILedMask4 = " + 0xFF, 0xFF, /* C1-1 -> C1-16 */ + 0xFE, 0xFE, /* C2-1 -> C2-16 */ + 0xFE, 0xFE, /* C3-1 -> C3-16 */ + 0x06, 0x06, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x60, 0x60, /* C6-1 -> C6-16 */ + 0x7F, 0x7F, /* C7-1 -> C7-16 */ + 0x7F, 0x7F, /* C8-1 -> C8-16 */ + 0xFF, 0xFF, /* C9-1 -> C9-16 */ +"; + +#ISSILedMask4 = " +# 0x00, 0x00, /* C1-1 -> C1-16 */ +# 0x00, 0x00, /* C2-1 -> C2-16 */ +# 0x00, 0x00, /* C3-1 -> C3-16 */ +# 0x00, 0x00, /* C4-1 -> C4-16 */ +# 0x00, 0x00, /* C5-1 -> C5-16 */ +# 0x00, 0x00, /* C6-1 -> C6-16 */ +# 0x00, 0x00, /* C7-1 -> C7-16 */ +# 0x00, 0x00, /* C8-1 -> C8-16 */ +# 0x00, 0x00, /* C9-1 -> C9-16 */ +#"; + +ISSILedBrightness1 = " +0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ +0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* C2-1 -> C2-16 */ +0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, /* C3-1 -> C3-16 */ +0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, /* C4-1 -> C4-16 */ +0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* C5-1 -> C5-16 */ +0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, /* C6-1 -> C6-16 */ +0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, /* C7-1 -> C7-16 */ +0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, /* C8-1 -> C8-16 */ +0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness2 = " +0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ +0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* C2-1 -> C2-16 */ +0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, /* C3-1 -> C3-16 */ +0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, /* C4-1 -> C4-16 */ +0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* C5-1 -> C5-16 */ +0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, /* C6-1 -> C6-16 */ +0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, /* C7-1 -> C7-16 */ +0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, /* C8-1 -> C8-16 */ +0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness3 = " +0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ +0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* C2-1 -> C2-16 */ +0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, /* C3-1 -> C3-16 */ +0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, /* C4-1 -> C4-16 */ +0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* C5-1 -> C5-16 */ +0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, /* C6-1 -> C6-16 */ +0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, /* C7-1 -> C7-16 */ +0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, /* C8-1 -> C8-16 */ +0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness4 = " +0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ +0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* C2-1 -> C2-16 */ +0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, /* C3-1 -> C3-16 */ +0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, /* C4-1 -> C4-16 */ +0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* C5-1 -> C5-16 */ +0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, /* C6-1 -> C6-16 */ +0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, /* C7-1 -> C7-16 */ +0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, /* C8-1 -> C8-16 */ +0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness1 = " +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness2 = " +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness3 = " +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +"; + +ISSILedBrightness4 = " +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +"; + From 1e47c7abc201e221ec07dca6fed53608902527a9 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sun, 3 Jan 2016 10:21:10 -0800 Subject: [PATCH 06/30] Initial LED Animiation Support - Added port swapping to KType - Added initial KType default keymappings - Initial PixelMap animiation framework - Swapped in new i2c library for ISSILed --- Keyboards/icpad.bash | 2 +- Keyboards/ktype.bash | 72 +++ Lib/CMake/build.cmake | 2 +- Lib/CMake/kll.cmake | 5 +- Scan/ICPad/defaultMap.kll | 44 +- Scan/ICPad/scan_loop.c | 9 +- Scan/ISSILed/capabilities.kll | 16 + Scan/ISSILed/i2c.c | 313 ++++++++++++ Scan/ISSILed/i2c.h | 115 +++++ Scan/ISSILed/led_scan.c | 926 +++++++++++++++------------------- Scan/ISSILed/led_scan.h | 8 +- Scan/ISSILed/setup.cmake | 1 + Scan/KType/defaultMap.kll | 238 +++++---- Scan/KType/matrix.h | 14 +- Scan/KType/scan_loop.c | 16 +- Scan/KType/setup.cmake | 1 + Scan/MatrixARM/matrix_scan.c | 1 - Scan/WhiteFox/defaultMap.kll | 25 +- Scan/WhiteFox/scan_loop.c | 7 + 19 files changed, 1148 insertions(+), 667 deletions(-) create mode 100755 Keyboards/ktype.bash create mode 100644 Scan/ISSILed/i2c.c create mode 100644 Scan/ISSILed/i2c.h diff --git a/Keyboards/icpad.bash b/Keyboards/icpad.bash index de299fd..ea3d414 100755 --- a/Keyboards/icpad.bash +++ b/Keyboards/icpad.bash @@ -43,7 +43,7 @@ PartialMaps[1]="" # Keyboard Module Configuration ScanModule="ICPad" -MacroModule="PartialMap" +MacroModule="PixelMap" OutputModule="pjrcUSB" DebugModule="full" diff --git a/Keyboards/ktype.bash b/Keyboards/ktype.bash new file mode 100755 index 0000000..500a037 --- /dev/null +++ b/Keyboards/ktype.bash @@ -0,0 +1,72 @@ +#!/bin/bash +# This is a build script template +# These build scripts are just a convenience for configuring your keyboard (less daunting than CMake) +# Jacob Alexander 2015 + + + +################# +# Configuration # +################# + +# Feel free to change the variables in this section to configure your keyboard + +BuildPath="KType" + +## KLL Configuration ## + +# Generally shouldn't be changed, this will affect every layer +BaseMap="defaultMap" + +# This is the default layer of the keyboard +# NOTE: To combine kll files into a single layout, separate them by spaces +# e.g. DefaultMap="mylayout mylayoutmod" +DefaultMap="stdFuncMap" + +# This is where you set the additional layers +# NOTE: Indexing starts at 1 +# NOTE: Each new layer is another array entry +# e.g. PartialMaps[1]="layer1 layer1mod" +# PartialMaps[2]="layer2" +# PartialMaps[3]="layer3" +PartialMaps[1]="" + + + +########################## +# Advanced Configuration # +########################## + +# Don't change the variables in this section unless you know what you're doing +# These are useful for completely custom keyboards +# NOTE: Changing any of these variables will require a force build to compile correctly + +# Keyboard Module Configuration +ScanModule="KType" +MacroModule="PixelMap" +OutputModule="pjrcUSB" +DebugModule="full" + +# Microcontroller +Chip="mk20dx256vlh7" + +# Compiler Selection +Compiler="gcc" + + + +######################## +# Bash Library Include # +######################## + +# Shouldn't need to touch this section + +# Check if the library can be found +if [ ! -f cmake.bash ]; then + echo "ERROR: Cannot find 'cmake.bash'" + exit 1 +fi + +# Load the library +source cmake.bash + diff --git a/Lib/CMake/build.cmake b/Lib/CMake/build.cmake index b3209bf..4cdf8b8 100644 --- a/Lib/CMake/build.cmake +++ b/Lib/CMake/build.cmake @@ -24,7 +24,7 @@ endif () #| Create the .ELF file set( TARGET_ELF ${TARGET}.elf ) -add_executable( ${TARGET_ELF} ${SRCS} generatedKeymap.h ) +add_executable( ${TARGET_ELF} ${SRCS} generatedKeymap.h kll_defs.h ) #| .ELF Properties diff --git a/Lib/CMake/kll.cmake b/Lib/CMake/kll.cmake index 36802e4..0f5b580 100644 --- a/Lib/CMake/kll.cmake +++ b/Lib/CMake/kll.cmake @@ -11,7 +11,7 @@ # Check if KLL compiler is needed # -if ( "${MacroModule}" STREQUAL "PartialMap" ) +if ( "${MacroModule}" STREQUAL "PartialMap" OR "${MacroModule}" STREQUAL "PixelMap" ) @@ -148,6 +148,7 @@ add_custom_target ( kll_regen set ( SRCS ${SRCS} ${kll_outputname} ) - +else () +message ( AUTHOR_WARNING "Unknown Macro module, ignoring kll generation" ) endif () # PartialMap diff --git a/Scan/ICPad/defaultMap.kll b/Scan/ICPad/defaultMap.kll index c558967..fdf7b6d 100644 --- a/Scan/ICPad/defaultMap.kll +++ b/Scan/ICPad/defaultMap.kll @@ -143,27 +143,27 @@ ISSILedBrightness2 = " "; # Misc -ISSILedBrightness1 = " -0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, /* C1-1 -> C1-16 */ -0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, /* C2-1 -> C2-16 */ -0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, /* C3-1 -> C3-16 */ -0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, /* C6-1 -> C6-16 */ -0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, /* C7-1 -> C7-16 */ -0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, /* C8-1 -> C8-16 */ -0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, /* C9-1 -> C9-16 */ -"; +#ISSILedBrightness1 = " +#0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, /* C1-1 -> C1-16 */ +#0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, /* C2-1 -> C2-16 */ +#0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, /* C3-1 -> C3-16 */ +#0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, /* C6-1 -> C6-16 */ +#0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, /* C7-1 -> C7-16 */ +#0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, /* C8-1 -> C8-16 */ +#0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, /* C9-1 -> C9-16 */ +#"; -ISSILedBrightness2 = " -0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ -0x00, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ -0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ -0x00, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ -0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ -0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ -0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ -"; +#ISSILedBrightness2 = " +#0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +#0x00, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +#0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +#0x00, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +#0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +#0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +#0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +#"; diff --git a/Scan/ICPad/scan_loop.c b/Scan/ICPad/scan_loop.c index c1db646..3f20cd9 100644 --- a/Scan/ICPad/scan_loop.c +++ b/Scan/ICPad/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2015 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,7 @@ #include #include #include +#include // Local Includes #include "scan_loop.h" @@ -66,6 +67,9 @@ inline void Scan_setup() // Setup ISSI chip to control the leds LED_setup(); + // Setup Pixel Map + Pixel_setup(); + // Reset scan count Scan_scanCount = 0; } @@ -83,6 +87,9 @@ inline uint8_t Scan_loop() // Process any interconnect commands Connect_scan(); + // Prepare any LED events + Pixel_process(); + // Process any LED events LED_scan(); diff --git a/Scan/ISSILed/capabilities.kll b/Scan/ISSILed/capabilities.kll index 6aaad88..fa39dec 100644 --- a/Scan/ISSILed/capabilities.kll +++ b/Scan/ISSILed/capabilities.kll @@ -28,6 +28,22 @@ ledControl => LED_control_capability( mode : 1, amount : 1, index : 2 ); ISSI_Chips => ISSI_Chips_define; ISSI_Chips = 1; # 1 by default +# Default animation speed +# Can be set from 0 to 63 (A) +# Formula is TxA (T is approx 11ms) +# 0 - 1.4 fps (represents 64) +# 1 - 90 fps +# 2 - 45 fps +# 3 - 30 fps +# 4 - 22 fps +# etc. +# For a 400 kHz I2C, with a single chip, updating all 144 channels, generally 30 fps is the max for continuous animations +# Each additional chip consumes more bandwidth +# 20 - 4.5 fps - Slow, but should always work without glitches +# See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details +ISSI_AnimationSpeed => ISSI_AnimationSpeed_define; +ISSI_AnimationSpeed = 20; # 20 by default + # LED Default Enable Mask # # By default, all LEDs are enabled diff --git a/Scan/ISSILed/i2c.c b/Scan/ISSILed/i2c.c new file mode 100644 index 0000000..f690e61 --- /dev/null +++ b/Scan/ISSILed/i2c.c @@ -0,0 +1,313 @@ +/* + * Copyright ( C ) 2014 Jan Rychter + * Modifications ( C ) 2015 Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files ( the "Software" ), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// ----- Includes ---- + +// Compiler Includes +#include + +// Project Includes +#include + +// Local Includes +#include "i2c.h" + + + +// ----- Variables ----- + +volatile I2C_Channel i2c_channels[1]; + + + +// ----- Functions ----- + +inline void i2c_setup( ) +{ + // Enable I2C internal clock + SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0 + + // External pull-up resistor + PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); + PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); + + // SCL Frequency Divider + // 1.8 MBaud ( likely higher than spec ) + // 0x82 -> 36 MHz / (4 * 3) = 2.25 MBaud + // 0x80 => mul(4) + // 0x05 => ICL(5) + I2C0_F = 0x84; + I2C0_FLT = 4; + I2C0_C1 = I2C_C1_IICEN; + I2C0_C2 = I2C_C2_HDRS; // High drive select + + // Enable I2C Interrupt + NVIC_ENABLE_IRQ( IRQ_I2C0 ); +} + +uint8_t i2c_busy() +{ + volatile I2C_Channel *channel = &( i2c_channels[0] ); + if ( channel->status == I2C_BUSY ) + { + return 1; + } + + return 0; +} + + +// These are here for readability and correspond to bit 0 of the address byte. +#define I2C_WRITING 0 +#define I2C_READING 1 + +int32_t i2c_send_sequence( + uint16_t *sequence, + uint32_t sequence_length, + uint8_t *received_data, + void ( *callback_fn )( void* ), + void *user_data +) { + volatile I2C_Channel *channel = &( i2c_channels[0] ); + int32_t result = 0; + uint8_t status; + + if ( channel->status == I2C_BUSY ) + { + return -1; + } + + // Debug + /* + for ( uint8_t c = 0; c < sequence_length; c++ ) + { + printHex( sequence[c] ); + print(" "); + } + print(NL); + */ + + channel->sequence = sequence; + channel->sequence_end = sequence + sequence_length; + channel->received_data = received_data; + channel->status = I2C_BUSY; + channel->txrx = I2C_WRITING; + channel->callback_fn = callback_fn; + channel->user_data = user_data; + + // reads_ahead does not need to be initialized + + // Acknowledge the interrupt request, just in case + I2C0_S |= I2C_S_IICIF; + I2C0_C1 = ( I2C_C1_IICEN | I2C_C1_IICIE ); + + // Generate a start condition and prepare for transmitting. + I2C0_C1 |= ( I2C_C1_MST | I2C_C1_TX ); + + status = I2C0_S; + if ( status & I2C_S_ARBL ) + { + warn_print("Arbitration lost"); + result = -1; + goto i2c_send_sequence_cleanup; + } + + // Write the first (address) byte. + I2C0_D = *channel->sequence++; + + // Everything is OK. + return result; + +i2c_send_sequence_cleanup: + I2C0_C1 &= ~( I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX ); + channel->status = I2C_ERROR; + return result; +} + + +void i2c0_isr() +{ + volatile I2C_Channel* channel = &i2c_channels[0]; + uint8_t element; + uint8_t status; + + status = I2C0_S; + + // Acknowledge the interrupt request + I2C0_S |= I2C_S_IICIF; + + // Arbitration problem + if ( status & I2C_S_ARBL ) + { + warn_print("Arbitration error"); + I2C0_S |= I2C_S_ARBL; + goto i2c_isr_error; + } + + if ( channel->txrx == I2C_READING ) + { + + switch( channel->reads_ahead ) + { + // All the reads in the sequence have been processed ( but note that the final data register read still needs to + // be done below! Now, the next thing is either a restart or the end of a sequence. In any case, we need to + // switch to TX mode, either to generate a repeated start condition, or to avoid triggering another I2C read + // when reading the contents of the data register. + case 0: + I2C0_C1 |= I2C_C1_TX; + + // Perform the final data register read now that it's safe to do so. + *channel->received_data++ = I2C0_D; + + // Do we have a repeated start? + if ( ( channel->sequence < channel->sequence_end ) && ( *channel->sequence == I2C_RESTART ) ) + { + + // Generate a repeated start condition. + I2C0_C1 |= I2C_C1_RSTA; + + // A restart is processed immediately, so we need to get a new element from our sequence. This is safe, because + // a sequence cannot end with a RESTART: there has to be something after it. Note that the only thing that can + // come after a restart is an address write. + channel->txrx = I2C_WRITING; + channel->sequence++; + element = *channel->sequence; + I2C0_D = element; + } + else + { + goto i2c_isr_stop; + } + break; + + case 1: + // do not ACK the final read + I2C0_C1 |= I2C_C1_TXAK; + *channel->received_data++ = I2C0_D; + break; + + default: + *channel->received_data++ = I2C0_D; + break; + } + + channel->reads_ahead--; + + } + // channel->txrx == I2C_WRITING + else + { + // First, check if we are at the end of a sequence. + if ( channel->sequence == channel->sequence_end ) + goto i2c_isr_stop; + + // We received a NACK. Generate a STOP condition and abort. + if ( status & I2C_S_RXAK ) + { + warn_print("NACK Received"); + goto i2c_isr_error; + } + + // check next thing in our sequence + element = *channel->sequence; + + // Do we have a restart? If so, generate repeated start and make sure TX is on. + if ( element == I2C_RESTART ) + { + I2C0_C1 |= I2C_C1_RSTA | I2C_C1_TX; + + // A restart is processed immediately, so we need to get a new element from our sequence. + // This is safe, because a sequence cannot end with a RESTART: there has to be something after it. + channel->sequence++; + element = *channel->sequence; + + // Note that the only thing that can come after a restart is a write. + I2C0_D = element; + } + else + { + if ( element == I2C_READ ) { + channel->txrx = I2C_READING; + // How many reads do we have ahead of us ( not including this one )? + // For reads we need to know the segment length to correctly plan NACK transmissions. + // We already know about one read + channel->reads_ahead = 1; + while ( + ( ( channel->sequence + channel->reads_ahead ) < channel->sequence_end ) && + ( *( channel->sequence + channel->reads_ahead ) == I2C_READ ) + ) { + channel->reads_ahead++; + } + + // Switch to RX mode. + I2C0_C1 &= ~I2C_C1_TX; + + // do not ACK the final read + if ( channel->reads_ahead == 1 ) + { + I2C0_C1 |= I2C_C1_TXAK; + } + // ACK all but the final read + else + { + I2C0_C1 &= ~( I2C_C1_TXAK ); + } + + // Dummy read comes first, note that this is not valid data! + // This only triggers a read, actual data will come in the next interrupt call and overwrite this. + // This is why we do not increment the received_data pointer. + *channel->received_data = I2C0_D; + channel->reads_ahead--; + } + // Not a restart, not a read, must be a write. + else + { + I2C0_D = element; + } + } + } + + channel->sequence++; + return; + +i2c_isr_stop: + // Generate STOP ( set MST=0 ), switch to RX mode, and disable further interrupts. + I2C0_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE | I2C_C1_TXAK ); + channel->status = I2C_AVAILABLE; + + // Call the user-supplied callback function upon successful completion (if it exists). + if ( channel->callback_fn ) + { + // Delay 10 microseconds before starting linked function + delayMicroseconds(10); + ( *channel->callback_fn )( channel->user_data ); + } + return; + +i2c_isr_error: + // Generate STOP and disable further interrupts. + I2C0_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE ); + channel->status = I2C_ERROR; + return; +} + diff --git a/Scan/ISSILed/i2c.h b/Scan/ISSILed/i2c.h new file mode 100644 index 0000000..1a0ff07 --- /dev/null +++ b/Scan/ISSILed/i2c.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2014 Jan Rychter + * Modifications (C) 2015 Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*/ + +#pragma once + +// ----- Includes ---- + +// Compiler Includes +#include + + + +// ----- Defines ----- + +// Channel status definitions. These are not enumerated, as I want them to be uint8_t. +#define I2C_AVAILABLE 0 +#define I2C_BUSY 1 +#define I2C_ERROR 2 + + +#define I2C_RESTART 1<<8 +#define I2C_READ 2<<8 + + + +// ----- Structs ----- + +typedef struct { + uint16_t *sequence; + uint16_t *sequence_end; + uint8_t *received_data; + void (*callback_fn)(void*); + void *user_data; + uint8_t reads_ahead; + uint8_t status; + uint8_t txrx; +} I2C_Channel; + + + +// ----- Variables ----- + +extern volatile I2C_Channel i2c_channels[1]; + + + +// ----- Functions ----- + +/* + * I2C Module Setup - Channel 0 only + */ + +void i2c_setup(); + + +/* + * Sends a command/data sequence that can include restarts, writes and reads. Every transmission begins with a START, + * and ends with a STOP so you do not have to specify that. + * + * sequence is the I2C operation sequence that should be performed. It can include any number of writes, restarts and + * reads. Note that the sequence is composed of uint16_t, not uint8_t. This is because we have to support out-of-band + * signalling of I2C_RESTART and I2C_READ operations, while still passing through 8-bit data. + * + * sequence_length is the number of sequence elements (not bytes). Sequences of arbitrary length are supported. The + * minimum sequence length is (rather obviously) 2. + * + * received_data should point to a buffer that can hold as many bytes as there are I2C_READ operations in the + * sequence. If there are no reads, 0 can be passed, as this parameter will not be used. + * + * callback_fn is a pointer to a function that will get called upon successful completion of the entire sequence. If 0 is + * supplied, no function will be called. Note that the function will be called fron an interrupt handler, so it should do + * the absolute minimum possible (such as enqueue an event to be processed later, set a flag, exit sleep mode, etc.) + * + * user_data is a pointer that will be passed to the callback_fn. + */ + +int32_t i2c_send_sequence( + uint16_t *sequence, + uint32_t sequence_length, + uint8_t *received_data, + void (*callback_fn)(void*), + void *user_data +); + +/* + * Convenience macros + */ +#define i2c_send(seq, seq_len) i2c_send_sequence( seq, seq_len, 0, 0, 0 ) +#define i2c_read(seq, seq_len, rec) i2c_send_sequence( seq, seq_len, rec, 0, 0 ) + +/* + * Check if busy + */ +uint8_t i2c_busy(); + diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index 6a639a1..e04067a 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -24,6 +24,7 @@ #include #include #include +#include // Interconnect module if compiled in #if defined(ConnectEnabled_define) @@ -31,25 +32,23 @@ #endif // Local Includes +#include "i2c.h" #include "led_scan.h" // ----- Defines ----- -// Increase buffer sizes for RGB -#ifdef ISSI_RGB_define -#define I2C_TxBufferLength 600 -#define I2C_RxBufferLength 16 -#else -#define I2C_TxBufferLength 300 -#define I2C_RxBufferLength 8 -#endif - +// TODO Make this a kll define +// I2C transfers are more efficient if all 144 don't have to be updated +// (and most implementations don't use all the channels) +// Ergodox tested @ 83fps /w 38 +// Whitefox tested @ 45fps /w 71 #define LED_BufferLength 144 -#define LED_EnableBufferLength 18 -#define LED_TotalChannels (144 * ISSI_Chips_define) +#define LED_EnableBufferLength 18 +#define LED_FrameBuffersMax 4 +#define LED_TotalChannels (LED_BufferLength * ISSI_Chips_define) // ISSI Addresses // IS31FL3731 (max 4 channels per bus) @@ -89,24 +88,16 @@ // ----- Structs ----- -typedef struct I2C_Buffer { - uint16_t head; - uint16_t tail; - uint8_t sequencePos; - uint16_t size; - uint8_t *buffer; -} I2C_Buffer; - typedef struct LED_Buffer { - uint8_t i2c_addr; - uint8_t reg_addr; - uint8_t buffer[LED_BufferLength]; + uint16_t i2c_addr; + uint16_t reg_addr; + uint16_t buffer[LED_BufferLength]; } LED_Buffer; typedef struct LED_EnableBuffer { - uint8_t i2c_addr; - uint8_t reg_addr; - uint8_t buffer[LED_EnableBufferLength]; + uint16_t i2c_addr; + uint16_t reg_addr; + uint16_t buffer[LED_EnableBufferLength]; } LED_EnableBuffer; @@ -114,39 +105,31 @@ typedef struct LED_EnableBuffer { // ----- Function Declarations ----- // CLI Functions -void cliFunc_i2cRecv ( char* args ); -void cliFunc_i2cSend ( char* args ); -void cliFunc_ledCtrl ( char* args ); -void cliFunc_ledRPage( char* args ); -void cliFunc_ledStart( char* args ); -void cliFunc_ledTest ( char* args ); -void cliFunc_ledWPage( char* args ); -void cliFunc_ledZero ( char* args ); - -uint8_t I2C_TxBufferPop(); -void I2C_BufferPush( uint8_t byte, I2C_Buffer *buffer ); -uint16_t I2C_BufferLen( I2C_Buffer *buffer ); -uint8_t I2C_Send( uint8_t *data, uint8_t sendLen, uint8_t recvLen ); +void cliFunc_i2cSend ( char* args ); +void cliFunc_ledCtrl ( char* args ); +void cliFunc_ledNFrame( char* args ); +void cliFunc_ledStart ( char* args ); +void cliFunc_ledTest ( char* args ); +void cliFunc_ledWPage ( char* args ); +void cliFunc_ledZero ( char* args ); // ----- Variables ----- // Scan Module command dictionary -CLIDict_Entry( i2cRecv, "Send I2C sequence of bytes and expect a reply of 1 byte on the last sequence." NL "\t\tUse |'s to split sequences with a stop." ); CLIDict_Entry( i2cSend, "Send I2C sequence of bytes. Use |'s to split sequences with a stop." ); CLIDict_Entry( ledCtrl, "Basic LED control. Args: []" ); -CLIDict_Entry( ledRPage, "Read the given register page." ); +CLIDict_Entry( ledNFrame, "Increment led frame." ); CLIDict_Entry( ledStart, "Disable software shutdown." ); CLIDict_Entry( ledTest, "Test out the led pages." ); CLIDict_Entry( ledWPage, "Write to given register page starting at address. i.e. 0xE8 0x2 0x24 0xF0 0x12" ); CLIDict_Entry( ledZero, "Zero out LED register pages (non-configuration)." ); CLIDict_Def( ledCLIDict, "ISSI LED Module Commands" ) = { - CLIDict_Item( i2cRecv ), CLIDict_Item( i2cSend ), CLIDict_Item( ledCtrl ), - CLIDict_Item( ledRPage ), + CLIDict_Item( ledNFrame ), CLIDict_Item( ledStart ), CLIDict_Item( ledTest ), CLIDict_Item( ledWPage ), @@ -155,17 +138,13 @@ CLIDict_Def( ledCLIDict, "ISSI LED Module Commands" ) = { }; - -// Before sending the sequence, I2C_TxBuffer_CurLen is assigned and as each byte is sent, it is decremented -// Once I2C_TxBuffer_CurLen reaches zero, a STOP on the I2C bus is sent -volatile uint8_t I2C_TxBufferPtr[ I2C_TxBufferLength ]; -volatile uint8_t I2C_RxBufferPtr[ I2C_TxBufferLength ]; - -volatile I2C_Buffer I2C_TxBuffer = { 0, 0, 0, I2C_TxBufferLength, (uint8_t*)I2C_TxBufferPtr }; -volatile I2C_Buffer I2C_RxBuffer = { 0, 0, 0, I2C_RxBufferLength, (uint8_t*)I2C_RxBufferPtr }; - LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; + uint8_t LED_FrameBuffersReady; // Starts at maximum, reset on interrupt from ISSI +volatile uint8_t LED_FrameBufferReset; // INTB interrupt received, reset available buffer count when ready + uint8_t LED_FrameBufferPage; // Current page of the buffer + uint8_t LED_FrameBufferStart; // Whether or not a start signal can be sent + // Enable mask and default brightness for ISSI chip channel const LED_EnableBuffer LED_ledEnableMask[ISSI_Chips_define] = { LED_MaskDefine( 1 ), @@ -203,245 +182,130 @@ const LED_Buffer LED_defaultBrightness[ISSI_Chips_define] = { // ----- Interrupt Functions ----- -void i2c0_isr() +void portb_isr() { - cli(); // Disable Interrupts - - uint8_t status = I2C0_S; // Read I2C Bus status - - // Master Mode Transmit - if ( I2C0_C1 & I2C_C1_TX ) + // Check for ISSI INTB IRQ + if ( PORTB_ISFR & (1 << 17) ) { - // Check current use of the I2C bus - // Currently sending data - if ( I2C_TxBuffer.sequencePos > 0 ) - { - // Make sure slave sent an ACK - if ( status & I2C_S_RXAK ) - { - // NACK Detected, disable interrupt - erro_print("I2C NAK detected..."); - I2C0_C1 = I2C_C1_IICEN; + // Set frame buffer replenish condition + LED_FrameBufferReset = 1; - // Abort Tx Buffer - I2C_TxBuffer.head = 0; - I2C_TxBuffer.tail = 0; - I2C_TxBuffer.sequencePos = 0; - } - else - { - // Transmit byte - I2C0_D = I2C_TxBufferPop(); - } - } - // Receiving data - else if ( I2C_RxBuffer.sequencePos > 0 ) - { - // Master Receive, addr sent - if ( status & I2C_S_ARBL ) - { - // Arbitration Lost - erro_print("Arbitration lost..."); - // TODO Abort Rx - - I2C0_C1 = I2C_C1_IICEN; - I2C0_S = I2C_S_ARBL | I2C_S_IICIF; // Clear ARBL flag and interrupt - } - if ( status & I2C_S_RXAK ) - { - // Slave Address NACK Detected, disable interrupt - erro_print("Slave Address I2C NAK detected..."); - // TODO Abort Rx - - I2C0_C1 = I2C_C1_IICEN; - } - else - { - dbug_msg("Attempting to read byte - "); - printHex( I2C_RxBuffer.sequencePos ); - print( NL ); - I2C0_C1 = I2C_RxBuffer.sequencePos == 1 - ? I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TXAK // Single byte read - : I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST; // Multi-byte read - } - } - else - { - /* - dbug_msg("STOP - "); - printHex( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) ); - print(NL); - */ - - // Delay around STOP to make sure it actually happens... - delayMicroseconds( 1 ); - I2C0_C1 = I2C_C1_IICEN; // Send STOP - delayMicroseconds( 7 ); - - // If there is another sequence, start sending - if ( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) < I2C_TxBuffer.size ) - { - // Clear status flags - I2C0_S = I2C_S_IICIF | I2C_S_ARBL; - - // Wait...till the master dies - while ( I2C0_S & I2C_S_BUSY ); - - // Enable I2C interrupt - I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX; - - // Transmit byte - I2C0_D = I2C_TxBufferPop(); - } - } + // Clear IRQ + PORTB_ISFR |= (1 << 17); } - // Master Mode Receive - else - { - // XXX Do we need to handle 2nd last byte? - //I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TXAK; // No STOP, Rx, NAK on recv - - // Last byte - if ( I2C_TxBuffer.sequencePos <= 1 ) - { - // Change to Tx mode - I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; - - // Grab last byte - I2C_BufferPush( I2C0_D, (I2C_Buffer*)&I2C_RxBuffer ); - - delayMicroseconds( 1 ); // Should be enough time before issuing the stop - I2C0_C1 = I2C_C1_IICEN; // Send STOP - } - else - { - // Retrieve data - I2C_BufferPush( I2C0_D, (I2C_Buffer*)&I2C_RxBuffer ); - } - } - - I2C0_S = I2C_S_IICIF; // Clear interrupt - - sei(); // Re-enable Interrupts } // ----- Functions ----- -inline void I2C_setup() -{ - // Enable I2C internal clock - SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0 - - // External pull-up resistor - PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); - PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); - - // SCL Frequency Divider - // 1.8 MBaud (likely higher than spec) - // 0x85 -> 36 MHz / (4 * 5) = 1.8 MBaud - // 0x80 => mul(4) - // 0x05 => ICL(5) - I2C0_F = 0x85; - I2C0_FLT = 4; - I2C0_C1 = I2C_C1_IICEN; - I2C0_C2 = I2C_C2_HDRS; // High drive select - - // Enable I2C Interrupt - NVIC_ENABLE_IRQ( IRQ_I2C0 ); -} - void LED_zeroPages( uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) { - // Page Setup - uint8_t pageSetup[] = { addr, 0xFD, 0x00 }; - + // Clear Page // Max length of a page + chip id + reg start - uint8_t fullPage[ 0xB4 + 2 ] = { 0 }; // Max size of page - fullPage[0] = addr; // Set chip id - fullPage[1] = startReg; // Set start reg + uint16_t clearPage[2 + 0xB4] = { 0 }; + clearPage[0] = addr; + clearPage[1] = startReg; // Iterate through given pages, zero'ing out the given register regions for ( uint8_t page = startPage; page < startPage + numPages; page++ ) { - // Set page - pageSetup[2] = page; + // Page Setup + uint16_t pageSetup[] = { addr, 0xFD, page }; // Setup page - while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) + while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Zero out page - while ( I2C_Send( fullPage, endReg - startReg + 2, 0 ) == 0 ) + while ( i2c_send( clearPage, 2 + endReg - startReg ) == -1 ) delay(1); } + + // Wait until finished zero'ing + while ( i2c_busy() ) + delay(1); } -void LED_sendPage( uint8_t addr, uint8_t *buffer, uint8_t len, uint8_t page ) +void LED_sendPage( uint8_t addr, uint16_t *buffer, uint32_t len, uint8_t page ) { + /* + info_msg("I2C Send Page Addr: "); + printHex( addr ); + print(" Len: "); + printHex( len ); + print(" Page: "); + printHex( page ); + print( NL ); + */ + // Page Setup - uint8_t pageSetup[] = { addr, 0xFD, page }; + uint16_t pageSetup[] = { addr, 0xFD, page }; // Setup page - while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) + while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Write page to I2C Tx Buffer - while ( I2C_Send( buffer, len, 0 ) == 0 ) + while ( i2c_send( buffer, len ) == -1 ) delay(1); - } // Write address void LED_writeReg( uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) { // Page Setup - uint8_t pageSetup[] = { addr, 0xFD, page }; + uint16_t pageSetup[] = { addr, 0xFD, page }; // Reg Write Setup - uint8_t writeData[] = { addr, reg, val }; + uint16_t writeData[] = { addr, reg, val }; // Setup page - while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) + while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Write register - while ( I2C_Send( writeData, sizeof( writeData ), 0 ) == 0 ) + while ( i2c_send( writeData, sizeof( writeData ) / 2 ) == -1 ) + delay(1); + + // Delay until written + while ( i2c_busy() ) delay(1); } // Read address -void LED_readReg( uint8_t addr, uint8_t reg, uint8_t page ) +// TODO Not working? +uint8_t LED_readReg( uint8_t addr, uint8_t reg, uint8_t page ) { // Software shutdown must be enabled to read registers LED_writeReg( addr, 0x0A, 0x00, 0x0B ); // Page Setup - uint8_t pageSetup[] = { addr, 0xFD, page }; + uint16_t pageSetup[] = { addr, 0xFD, page }; // Setup page - while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) + while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Register Setup - uint8_t regSetup[] = { addr, reg }; + uint16_t regSetup[] = { addr, reg }; // Configure register - while ( I2C_Send( regSetup, sizeof( regSetup ), 0 ) == 0 ) + while ( i2c_send( regSetup, sizeof( regSetup ) / 2 ) == -1 ) delay(1); // Register Read Command - uint8_t regReadCmd[] = { addr | 0x1 }; + uint16_t regReadCmd[] = { addr | 0x1, I2C_READ }; + uint8_t recv_data; // Request single register byte - while ( I2C_Send( regReadCmd, sizeof( regReadCmd ), 1 ) == 0 ) + while ( i2c_read( regReadCmd, sizeof( regReadCmd ) / 2, &recv_data ) == -1 ) delay(1); - // TODO get byte from buffer - // Disable software shutdown LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + + return recv_data; } // Setup @@ -451,7 +315,7 @@ inline void LED_setup() CLI_registerDictionary( ledCLIDict, ledCLIDictName ); // Initialize I2C - I2C_setup(); + i2c_setup(); // Setup LED_pageBuffer addresses and brightness section LED_pageBuffer[0].i2c_addr = ISSI_Ch1; @@ -469,6 +333,11 @@ inline void LED_setup() LED_pageBuffer[3].reg_addr = 0x24; #endif + // Enable Hardware shutdown (pull low) + GPIOB_PDDR |= (1<<16); + PORTB_PCR16 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + GPIOB_PCOR |= (1<<16); + // Zero out Frame Registers // This needs to be done before disabling the hardware shutdown (or the leds will do undefined things) for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) @@ -478,19 +347,60 @@ inline void LED_setup() } // Disable Hardware shutdown of ISSI chip (pull high) - GPIOB_PDDR |= (1<<16); - PORTB_PCR16 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); GPIOB_PSOR |= (1<<16); + // Prepare pin to read INTB interrupt of ISSI chip (Active Low) + // Enable interrupt to detect falling edge + // Uses external pullup resistor + GPIOB_PDDR |= ~(1<<17); + PORTB_PCR17 = PORT_PCR_IRQC(0xA) | PORT_PCR_PFE | PORT_PCR_MUX(1); + LED_FrameBufferReset = 0; // Clear frame buffer reset condition for ISSI + + // Enable PORTB interrupt + NVIC_ENABLE_IRQ( IRQ_PORTB ); + + // Reset frame buffer used count + LED_FrameBuffersReady = LED_FrameBuffersMax; + + // Starting page for the buffers + LED_FrameBufferPage = 4; + + // Initially do not allow autoplay to restart + LED_FrameBufferStart = 0; + // Clear LED Pages // Enable LEDs based upon mask - // Set default brightness for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers - LED_sendPage( addr, (uint8_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ), 0 ); - LED_sendPage( addr, (uint8_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); + + // For each page + for ( uint8_t pg = 0; pg < LED_FrameBuffersMax * 2; pg++ ) + { + LED_sendPage( + addr, + (uint16_t*)&LED_ledEnableMask[ ch ], + sizeof( LED_EnableBuffer ) / 2, + pg + ); + } + } + + // Setup ISSI auto frame play, but do not start yet + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + // CNS 1 loop, FNS 4 frames - 0x14 + LED_writeReg( addr, 0x02, 0x14, 0x0B ); + + // Default refresh speed - TxA + // T is typically 11ms + // A is 1 to 64 (where 0 is 64) + LED_writeReg( addr, 0x03, ISSI_AnimationSpeed_define, 0x0B ); + + // Set MODE to Auto Frame Play + LED_writeReg( addr, 0x00, 0x08, 0x0B ); } // Disable Software shutdown of ISSI chip @@ -502,231 +412,143 @@ inline void LED_setup() } -inline uint8_t I2C_BufferCopy( uint8_t *data, uint8_t sendLen, uint8_t recvLen, I2C_Buffer *buffer ) +// LED Linked Send +// Call-back for i2c write when updating led display +uint8_t LED_chipSend; +void LED_linkedSend() { - uint8_t reTurn = 0; - - // If sendLen is greater than buffer fail right away - if ( sendLen > buffer->size ) - return 0; - - // Calculate new tail to determine if buffer has enough space - // The first element specifies the expected number of bytes from the slave (+1) - // The second element in the new buffer is the length of the buffer sequence (+1) - uint16_t newTail = buffer->tail + sendLen + 2; - if ( newTail >= buffer->size ) - newTail -= buffer->size; - - if ( I2C_BufferLen( buffer ) < sendLen + 2 ) - return 0; - -/* - print("|"); - printHex( sendLen + 2 ); - print("|"); - printHex( *tail ); - print("@"); - printHex( newTail ); - print("@"); -*/ - - // If buffer is clean, return 1, otherwise 2 - reTurn = buffer->head == buffer->tail ? 1 : 2; - - // Add to buffer, already know there is enough room (simplifies adding logic) - uint8_t bufferHeaderPos = 0; - for ( uint16_t c = 0; c < sendLen; c++ ) + // Check if we've updated all the ISSI chips for this frame + if ( LED_chipSend >= ISSI_Chips_define ) { - // Add data to buffer - switch ( bufferHeaderPos ) + // Increment the buffer page + // And reset if necessary + if ( ++LED_FrameBufferPage >= LED_FrameBuffersMax * 2 ) { - case 0: - buffer->buffer[ buffer->tail ] = recvLen; - bufferHeaderPos++; - c--; - break; - - case 1: - buffer->buffer[ buffer->tail ] = sendLen; - bufferHeaderPos++; - c--; - break; - - default: - buffer->buffer[ buffer->tail ] = data[ c ]; - break; + LED_FrameBufferPage = 0; } - // Check for wrap-around case - if ( buffer->tail + 1 >= buffer->size ) - { - buffer->tail = 0; - } - // Normal case - else - { - buffer->tail++; - } - } - - return reTurn; -} - - -inline uint16_t I2C_BufferLen( I2C_Buffer *buffer ) -{ - // Tail >= Head - if ( buffer->tail >= buffer->head ) - return buffer->head + buffer->size - buffer->tail; - - // Head > Tail - return buffer->head - buffer->tail; -} - - -void I2C_BufferPush( uint8_t byte, I2C_Buffer *buffer ) -{ - dbug_msg("DATA: "); - printHex( byte ); - - // Make sure buffer isn't full - if ( buffer->tail + 1 == buffer->head || ( buffer->head > buffer->tail && buffer->tail + 1 - buffer->size == buffer->head ) ) - { - warn_msg("I2C_BufferPush failed, buffer full: "); - printHex( byte ); - print( NL ); + // Now ready to update the frame buffer + Pixel_FrameState = FrameState_Update; return; } - // Check for wrap-around case - if ( buffer->tail + 1 >= buffer->size ) - { - buffer->tail = 0; - } - // Normal case - else - { - buffer->tail++; - } - - // Add byte to buffer - buffer->buffer[ buffer->tail ] = byte; -} - - -uint8_t I2C_TxBufferPop() -{ - // Return 0xFF if no buffer left (do not rely on this) - if ( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) >= I2C_TxBuffer.size ) - { - erro_msg("No buffer to pop an entry from... "); - printHex( I2C_TxBuffer.head ); - print(" "); - printHex( I2C_TxBuffer.tail ); - print(" "); - printHex( I2C_TxBuffer.sequencePos ); - print(NL); - return 0xFF; - } - - // If there is currently no sequence being sent, the first entry in the RingBuffer is the length - if ( I2C_TxBuffer.sequencePos == 0 ) - { - I2C_TxBuffer.sequencePos = 0xFF; // So this doesn't become an infinite loop - I2C_RxBuffer.sequencePos = I2C_TxBufferPop(); - I2C_TxBuffer.sequencePos = I2C_TxBufferPop(); - } - - uint8_t data = I2C_TxBuffer.buffer[ I2C_TxBuffer.head ]; - - // Prune head - I2C_TxBuffer.head++; - - // Wrap-around case - if ( I2C_TxBuffer.head >= I2C_TxBuffer.size ) - I2C_TxBuffer.head = 0; - - // Decrement buffer sequence (until next stop will be sent) - I2C_TxBuffer.sequencePos--; + // Update ISSI Frame State + Pixel_FrameState = FrameState_Sending; + // Debug /* - dbug_msg("Popping: "); - printHex( data ); - print(" "); - printHex( I2C_TxBuffer.head ); - print(" "); - printHex( I2C_TxBuffer.tail ); - print(" "); - printHex( I2C_TxBuffer.sequencePos ); - print(NL); - */ - return data; -} - - -uint8_t I2C_Send( uint8_t *data, uint8_t sendLen, uint8_t recvLen ) -{ - // Check head and tail pointers - // If full, return 0 - // If empty, start up I2C Master Tx - // If buffer is non-empty and non-full, just append to the buffer - switch ( I2C_BufferCopy( data, sendLen, recvLen, (I2C_Buffer*)&I2C_TxBuffer ) ) + dbug_msg("Linked Send: chip("); + printHex( LED_chipSend ); + print(") frame("); + printHex( LED_FrameBufferPage ); + print(") addr("); + printHex( LED_pageBuffer[0].i2c_addr ); + print(") reg("); + printHex( LED_pageBuffer[0].reg_addr ); + print(") len("); + printHex( sizeof( LED_Buffer ) / 2 ); + print(") data[]" NL "("); + for ( uint8_t c = 0; c < 9; c++ ) + //for ( uint8_t c = 0; c < sizeof( LED_Buffer ) / 2 - 2; c++ ) { - // Not enough buffer space... - case 0: - /* - erro_msg("Not enough Tx buffer space... "); - printHex( I2C_TxBuffer.head ); - print(":"); - printHex( I2C_TxBuffer.tail ); - print("+"); - printHex( sendLen ); - print("|"); - printHex( I2C_TxBuffer.size ); - print( NL ); - */ - return 0; - - // Empty buffer, initialize I2C - case 1: - // Clear status flags - I2C0_S = I2C_S_IICIF | I2C_S_ARBL; - - // Check to see if we already have control of the bus - if ( I2C0_C1 & I2C_C1_MST ) - { - // Already the master (ah yeah), send a repeated start - I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX; - } - // Otherwise, seize control - else - { - // Wait...till the master dies - while ( I2C0_S & I2C_S_BUSY ); - - // Now we're the master (ah yisss), get ready to send stuffs - I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; - } - - // Enable I2C interrupt - I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX; - - // Depending on what type of transfer, the first byte is configured for R or W - I2C0_D = I2C_TxBufferPop(); - - return 1; + printHex( LED_pageBuffer[0].buffer[c] ); + print(" "); } + print(")" NL); + */ - // Dirty buffer, I2C already initialized - return 2; + // Send, and recursively call this function when finished + while ( i2c_send_sequence( + (uint16_t*)&LED_pageBuffer[ LED_chipSend ], + sizeof( LED_Buffer ) / 2, + 0, + LED_linkedSend, + 0 + ) == -1 ) + delay(1); + + // Increment chip position + LED_chipSend++; } - // LED State processing loop -inline uint8_t LED_scan() +uint32_t LED_timePrev = 0; +inline void LED_scan() { - return 0; + // Check to see if frame buffers are ready to replenish + if ( LED_FrameBufferReset ) + { + LED_FrameBufferReset = 0; + LED_FrameBufferStart = 1; + + // Debug Status + dbug_msg("4frames/"); + printInt32( systick_millis_count - LED_timePrev ); + LED_timePrev = systick_millis_count; + print("ms" NL); + } + + // Make sure there are buffers available + if ( LED_FrameBuffersReady == 0 ) + { + // Only start if we haven't already + // And if we've finished updating the buffers + if ( !LED_FrameBufferStart || Pixel_FrameState == FrameState_Sending ) + return; + + // Buffers are now full, start signal can be sent + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + + // Start Auto Frame Play on either frame 1 or 5 + uint8_t frame = LED_FrameBufferPage == 0 ? 4 : 0; + LED_writeReg( addr, 0x00, 0x08 | frame, 0x0B ); + } + + LED_FrameBufferStart = 0; + LED_FrameBuffersReady = LED_FrameBuffersMax; + + return; + } + /* + else + { + dbug_msg(":/ - Start("); + printHex( LED_FrameBufferStart ); + print(") BuffersReady("); + printHex( LED_FrameBuffersReady ); + print(") State("); + printHex( Pixel_FrameState ); + print(")"NL); + } + */ + + // Only send frame to ISSI chip if buffers are ready + if ( Pixel_FrameState != FrameState_Ready ) + return; + + LED_FrameBuffersReady--; + + // Set the page of all the ISSI chips + // This way we can easily link the buffers to send the brightnesses in the background + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + // Page Setup + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + uint16_t pageSetup[] = { addr, 0xFD, LED_FrameBufferPage }; + + // Send each update + while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + delay(1); + } + + // Send current set of buffers + // Uses interrupts to send to all the ISSI chips + // Pixel_FrameState will be updated when complete + LED_chipSend = 0; // Start with chip 0 + LED_linkedSend(); } @@ -802,7 +624,7 @@ void LED_control( LedControl *control ) // TODO Support multiple frames for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - LED_sendPage( LED_pageBuffer[ ch ].i2c_addr, (uint8_t*)&LED_pageBuffer[ ch ], sizeof( LED_Buffer ), 0 ); + LED_sendPage( LED_pageBuffer[ ch ].i2c_addr, (uint16_t*)&LED_pageBuffer[ ch ], sizeof( LED_Buffer ) / 2, 0 ); } } @@ -916,8 +738,8 @@ void cliFunc_i2cSend( char* args ) // Buffer used after interpretting the args, will be sent to I2C functions // NOTE: Limited to 8 bytes currently (can be increased if necessary #define i2cSend_BuffLenMax 8 - uint8_t buffer[ i2cSend_BuffLenMax ]; - uint8_t bufferLen = 0; + uint16_t buffer[ i2cSend_BuffLenMax ]; + uint8_t bufferLen = 0; // No \r\n by default after the command is entered print( NL ); @@ -937,7 +759,7 @@ void cliFunc_i2cSend( char* args ) if ( *arg1Ptr == '|' ) { print("| "); - I2C_Send( buffer, bufferLen, 0 ); + i2c_send( buffer, bufferLen ); bufferLen = 0; continue; } @@ -952,85 +774,12 @@ void cliFunc_i2cSend( char* args ) print( NL ); - I2C_Send( buffer, bufferLen, 0 ); -} - -void cliFunc_i2cRecv( char* args ) -{ - char* curArgs; - char* arg1Ptr; - char* arg2Ptr = args; - - // Buffer used after interpretting the args, will be sent to I2C functions - // NOTE: Limited to 8 bytes currently (can be increased if necessary - #define i2cSend_BuffLenMax 8 - uint8_t buffer[ i2cSend_BuffLenMax ]; - uint8_t bufferLen = 0; - - // No \r\n by default after the command is entered - print( NL ); - info_msg("Sending: "); - - // Parse args until a \0 is found - while ( bufferLen < i2cSend_BuffLenMax ) - { - curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list - CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); - - // Stop processing args if no more are found - if ( *arg1Ptr == '\0' ) - break; - - // If | is found, end sequence and start new one - if ( *arg1Ptr == '|' ) - { - print("| "); - I2C_Send( buffer, bufferLen, 0 ); - bufferLen = 0; - continue; - } - - // Interpret the argument - buffer[ bufferLen++ ] = (uint8_t)numToInt( arg1Ptr ); - - // Print out the arg - dPrint( arg1Ptr ); - print(" "); - } - - print( NL ); - - I2C_Send( buffer, bufferLen, 1 ); // Only 1 byte is ever read at a time with the ISSI chip -} - -// TODO Currently not working correctly -void cliFunc_ledRPage( char* args ) -{ - /* TODO Use readReg command instead - // Parse number from argument - // NOTE: Only first argument is used - char* arg1Ptr; - char* arg2Ptr; - CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); - - // Default to 0 if no argument is given - uint8_t page = 0; - - if ( arg1Ptr[0] != '\0' ) - { - page = (uint8_t)numToInt( arg1Ptr ); - } - - // No \r\n by default after the command is entered - print( NL ); - - // TODO, multi-channel - LED_readPage( ISSI_Ch1, 0xB4, page ); - */ + i2c_send( buffer, bufferLen ); } void cliFunc_ledWPage( char* args ) { + /* char* curArgs; char* arg1Ptr; char* arg2Ptr = args; @@ -1084,6 +833,7 @@ void cliFunc_ledWPage( char* args ) // Increment address data[1]++; } + */ } void cliFunc_ledStart( char* args ) @@ -1095,7 +845,7 @@ void cliFunc_ledStart( char* args ) LED_zeroPages( LED_ledEnableMask[ ch ].i2c_addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers //LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers LED_writeReg( LED_ledEnableMask[ ch ].i2c_addr, 0x0A, 0x01, 0x0B ); - LED_sendPage( LED_ledEnableMask[ ch ].i2c_addr, (uint8_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ), 0 ); + LED_sendPage( LED_ledEnableMask[ ch ].i2c_addr, (uint16_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ) / 2, 0 ); } } @@ -1103,10 +853,120 @@ void cliFunc_ledTest( char* args ) { print( NL ); // No \r\n by default after the command is entered + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; + uint8_t speed = ISSI_AnimationSpeed_define; + + // Process speed argument if given + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr != '\0' ) + speed = numToInt( arg1Ptr ); + + + // TODO REMOVEME for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - LED_sendPage( LED_defaultBrightness[ ch ].i2c_addr, (uint8_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + // CNS 1 loop, FNS 4 frames - 0x14 + //LED_writeReg( addr, 0x02, 0x14, 0x0B ); + + // Default refresh speed - TxA + // T is typically 11ms + // A is 1 to 64 (where 0 is 64) + LED_writeReg( addr, 0x03, speed, 0x0B ); + + // Set MODE to Auto Frame Play + // Set FS to 5, this is to train the IRQ on the ISSI for the processing loop + // The first 4 frames are blank, we fill the last 4 + // Clear the interrupt, and the movie display starts at frame 5 + //LED_writeReg( addr, 0x00, 0x0C, 0x0B ); } + return; + + // Zero out Frame Registers + // This needs to be done before disabling the hardware shutdown (or the leds will do undefined things) + info_print("LED - Zeroing out all pages"); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_zeroPages( addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers + LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers + } + + // Clear LED Pages + // Enable LEDs based upon mask + info_print("LED - Setting LED enable mask"); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + //for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + + // For each page + for ( uint8_t pg = 0; pg < LED_FrameBuffersMax * 2; pg++ ) + { + LED_sendPage( + addr, + (uint16_t*)&LED_ledEnableMask[ ch ], + sizeof( LED_EnableBuffer ) / 2, + pg + ); + } + } + + // Setup ISSI auto frame play, but do not start yet + /* + info_print("LED - Enabling 8 frame 3 loop auto play"); + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + // CNS 3 loops, FNS all frames - 0x30 + LED_writeReg( addr, 0x02, 0x30, 0x0B ); + + // Default refresh speed - TxA + // T is typically 11ms + // A is 1 to 64 (where 0 is 64) + LED_writeReg( addr, 0x03, speed, 0x0B ); + + // Set MODE to Auto Frame Play + // Set FS to frame 1 + //LED_writeReg( addr, 0x00, 0x08, 0x0B ); + } + */ + + // Load frame data + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + + // Load each page with a different led enabled + uint16_t data[] = { + addr, 0xFD, 0x00, + }; + while( i2c_send( data, sizeof( data ) / 2 ) == -1 ) + delay( 1 ); + data[1] = 0x24; + data[2] = 0xFF; + while( i2c_send( data, sizeof( data ) / 2 ) == -1 ) + delay( 1 ); + } + + // Disable Software shutdown of ISSI chip + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + } + +/* + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_sendPage( LED_defaultBrightness[ ch ].i2c_addr, (uint16_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); + } +*/ } void cliFunc_ledZero( char* args ) @@ -1115,6 +975,7 @@ void cliFunc_ledZero( char* args ) for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { + LED_zeroPages( LED_defaultBrightness[ ch ].i2c_addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers LED_zeroPages( LED_defaultBrightness[ ch ].i2c_addr, 0x00, 8, 0x24, 0xB4 ); // Only PWMs } } @@ -1156,3 +1017,44 @@ void cliFunc_ledCtrl( char* args ) LED_control( &control ); } +void cliFunc_ledNFrame( char* args ) +{ + // TODO REMOVEME + LED_FrameBufferStart = 1; + return; + /* + LED_FrameBufferReset = 0; + LED_FrameBuffersReady = LED_FrameBuffersMax; + LED_FrameBufferStart = 1; + */ + //LED_FrameBuffersReady++; + //LED_FrameBufferStart = 1; + //uint8_t addr = LED_pageBuffer[ 0 ].i2c_addr; + //LED_writeReg( addr, 0x00, 0x08, 0x0B ); + + //LED_FrameBuffersReady--; + + // Iterate over available buffers + // Each pass can only send one buffer (per chip) + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + // XXX It is more efficient to only send positions that are used + // However, this may actually have more addressing overhead + // For simplicity, just sending the full 144 positions per ISSI chip + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_sendPage( + addr, + (uint16_t*)&LED_pageBuffer[ ch ], + sizeof( LED_Buffer ) / 2, + LED_FrameBufferPage + ); + } + + // Increment the buffer page + // And reset if necessary + if ( ++LED_FrameBufferPage >= LED_FrameBuffersMax * 2 ) + { + LED_FrameBufferPage = 0; + } +} + diff --git a/Scan/ISSILed/led_scan.h b/Scan/ISSILed/led_scan.h index 71d8e80..b89531e 100644 --- a/Scan/ISSILed/led_scan.h +++ b/Scan/ISSILed/led_scan.h @@ -23,8 +23,14 @@ +// ----- Variables ----- + +extern uint8_t LED_FrameBuffersReady; + + + // ----- Functions ----- void LED_setup(); -uint8_t LED_scan(); +void LED_scan(); diff --git a/Scan/ISSILed/setup.cmake b/Scan/ISSILed/setup.cmake index c2cef01..ecd88d9 100644 --- a/Scan/ISSILed/setup.cmake +++ b/Scan/ISSILed/setup.cmake @@ -17,6 +17,7 @@ set ( SubModule 1 ) # Module C files # set ( Module_SRCS + i2c.c led_scan.c ) diff --git a/Scan/KType/defaultMap.kll b/Scan/KType/defaultMap.kll index ea4e3c9..8917a50 100644 --- a/Scan/KType/defaultMap.kll +++ b/Scan/KType/defaultMap.kll @@ -4,9 +4,10 @@ Author = "HaaTa (Jacob Alexander) 2015"; KLL = 0.3c; # Modified Date -Date = 2015-09-29; +Date = 2016-01-03; +# Function Row S0x00 : U"Esc"; S0x01 : U"F1"; S0x02 : U"F2"; @@ -23,6 +24,8 @@ S0x0C : U"F12"; S0x0D : U"PrintScreen"; S0x0E : U"ScrollLock"; S0x0F : U"Pause"; + +# Number Row S0x10 : U"Backtick"; S0x11 : U"1"; S0x12 : U"2"; @@ -36,67 +39,87 @@ S0x19 : U"9"; S0x1A : U"0"; S0x1B : U"Minus"; S0x1C : U"Equals"; -S0x1D : U"Backspace"; -S0x1E : U"Insert"; -S0x1F : U"Home"; -S0x20 : U"PageUp"; -S0x21 : U"Tab"; -S0x22 : U"Q"; -S0x23 : U"W"; -S0x24 : U"E"; -S0x25 : U"R"; -S0x26 : U"T"; -S0x27 : U"Y"; -S0x28 : U"U"; -S0x29 : U"I"; -S0x2A : U"O"; -S0x2B : U"P"; -S0x2C : U"LBrace"; -S0x2D : U"RBrace"; -S0x2E : U"Backslash"; -S0x2F : U"Delete"; -S0x30 : U"End"; -S0x31 : U"PageDown"; -S0x32 : U"CapsLock"; -S0x33 : U"A"; -S0x34 : U"S"; -S0x35 : U"D"; -S0x36 : U"F"; -S0x37 : U"G"; -S0x38 : U"H"; -S0x39 : U"J"; -S0x3A : U"K"; -S0x3B : U"L"; -S0x3C : U"Semicolon"; -S0x3D : U"Quote"; -S0x3E : U"Enter"; -S0x3F : U"LShift"; -S0x40 : U"Z"; -S0x41 : U"X"; -S0x42 : U"C"; -S0x43 : U"V"; -S0x44 : U"B"; -S0x45 : U"N"; -S0x46 : U"M"; -S0x47 : U"Comma"; -S0x48 : U"Period"; -S0x49 : U"Slash"; -S0x4A : U"RShift"; -S0x4B : U"Up"; -S0x4C : U"LCtrl"; -S0x4D : U"LGui"; -S0x4E : U"LAlt"; -S0x4F : U"Space"; -S0x50 : U"RAlt"; -S0x51 : U"RGui"; -S0x52 : U"Menu"; -S0x53 : U"RCtrl"; -S0x54 : U"Left"; -S0x55 : U"Down"; -S0x56 : U"Right"; +S0x1D : U"Hash"; +S0x1E : U"Backspace"; +S0x1F : U"Backspace"; # ISO Backspace +S0x20 : U"Insert"; +S0x21 : U"Home"; +S0x22 : U"PageUp"; + +# Top Alphabet Row +S0x23 : U"Tab"; +S0x24 : U"Q"; +S0x25 : U"W"; +S0x26 : U"E"; +S0x27 : U"R"; +S0x28 : U"T"; +S0x29 : U"Y"; +S0x2A : U"U"; +S0x2B : U"I"; +S0x2C : U"O"; +S0x2D : U"P"; +S0x2E : U"LBrace"; +S0x2F : U"RBrace"; +S0x30 : U"Backslash"; +S0x31 : U"Enter"; # ISO Enter +S0x32 : U"Delete"; +S0x33 : U"End"; +S0x34 : U"End"; + +# Middle Alphabet Row +S0x35 : U"CapsLock"; +S0x36 : U"A"; +S0x37 : U"S"; +S0x38 : U"D"; +S0x39 : U"F"; +S0x3A : U"G"; +S0x3B : U"H"; +S0x3C : U"J"; +S0x3D : U"K"; +S0x3E : U"L"; +S0x3F : U"Semicolon"; +S0x40 : U"Quote"; +S0x41 : U"Backslash"; # ISO Backslash +S0x42 : U"Enter"; + +# Bottom Alphabet Row +S0x43 : U"LShift"; +S0x44 : U"LShift"; +S0x45 : U"ISO/"; +S0x46 : U"Z"; +S0x47 : U"X"; +S0x48 : U"C"; +S0x49 : U"V"; +S0x4A : U"B"; +S0x4B : U"N"; +S0x4C : U"M"; +S0x4D : U"Comma"; +S0x4E : U"Period"; +S0x4F : U"Slash"; +S0x50 : U"RShift"; # HHKB RShift +S0x51 : U"RShift"; +S0x52 : U"Function1"; +S0x53 : U"Up"; + +# Modifier Row +S0x54 : U"LCtrl"; +S0x55 : U"LGui"; +S0x56 : U"LAlt"; +S0x57 : U"Space"; +S0x58 : U"RAlt"; +S0x59 : U"RGui"; +S0x5A : U"Menu"; +S0x5B : U"RCtrl"; +S0x5C : U"Left"; +S0x5D : U"Down"; +S0x5E : U"Right"; + # Available ISSI Chips -ISSI_Chips = 4; # 1 by default +ISSI_Chips = 3; # 1 by default + +# Default animation speed +ISSI_AnimationSpeed = 14; # 20 by default # LED Default Enable Mask # @@ -152,17 +175,18 @@ ISSILedMask4 = " 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; -#ISSILedMask4 = " -# 0x00, 0x00, /* C1-1 -> C1-16 */ -# 0x00, 0x00, /* C2-1 -> C2-16 */ -# 0x00, 0x00, /* C3-1 -> C3-16 */ -# 0x00, 0x00, /* C4-1 -> C4-16 */ -# 0x00, 0x00, /* C5-1 -> C5-16 */ -# 0x00, 0x00, /* C6-1 -> C6-16 */ -# 0x00, 0x00, /* C7-1 -> C7-16 */ -# 0x00, 0x00, /* C8-1 -> C8-16 */ -# 0x00, 0x00, /* C9-1 -> C9-16 */ -#"; +# Disabled for now +ISSILedMask4 = " + 0x00, 0x00, /* C1-1 -> C1-16 */ + 0x00, 0x00, /* C2-1 -> C2-16 */ + 0x00, 0x00, /* C3-1 -> C3-16 */ + 0x00, 0x00, /* C4-1 -> C4-16 */ + 0x00, 0x00, /* C5-1 -> C5-16 */ + 0x00, 0x00, /* C6-1 -> C6-16 */ + 0x00, 0x00, /* C7-1 -> C7-16 */ + 0x00, 0x00, /* C8-1 -> C8-16 */ + 0x00, 0x00, /* C9-1 -> C9-16 */ +"; ISSILedBrightness1 = " 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ @@ -213,50 +237,50 @@ ISSILedBrightness4 = " "; ISSILedBrightness1 = " -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; ISSILedBrightness2 = " -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; ISSILedBrightness3 = " -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; ISSILedBrightness4 = " -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C1-1 -> C1-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C2-1 -> C2-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C3-1 -> C3-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C4-1 -> C4-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C5-1 -> C5-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C6-1 -> C6-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C7-1 -> C7-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C8-1 -> C8-16 */ -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* C9-1 -> C9-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; diff --git a/Scan/KType/matrix.h b/Scan/KType/matrix.h index 912a700..8835d5e 100644 --- a/Scan/KType/matrix.h +++ b/Scan/KType/matrix.h @@ -37,20 +37,20 @@ // Before using a pin, make sure it supports being a GPIO *and* doesn't have a default pull-up/pull-down // Checking this is completely on the ownness of the user -// MDErgo1 +// KType // -// Column (Strobe) - 9 Total +// Column (Strobe) - 10 Total // PTB2,3,18,19 -// PTC0,9..11 +// PTC0,8..11 // PTD0 // -// Rows (Sense) - 5 Total +// Rows (Sense) - 10 Total // PTD1,4..7 +// PTC1..5 // Define Rows (Sense) and Columns (Strobes) -// TODO -GPIO_Pin Matrix_cols[] = { gpio(B,2), gpio(B,3), gpio(B,18), gpio(B,19), gpio(C,0), gpio(C,8), gpio(C,9), gpio(C,10), gpio(C,11) }; -GPIO_Pin Matrix_rows[] = { gpio(D,0), gpio(D,1), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7), gpio(C,1), gpio(C,2) }; +GPIO_Pin Matrix_cols[] = { gpio(B,2), gpio(B,3), gpio(B,18), gpio(B,19), gpio(C,0), gpio(C,8), gpio(C,9), gpio(C,10), gpio(C,11), gpio(D,0) }; +GPIO_Pin Matrix_rows[] = { gpio(D,1), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7), gpio(C,1), gpio(C,2), gpio(C,3), gpio(C,4), gpio(C,5) }; // Define type of scan matrix Config Matrix_type = Config_Pulldown; diff --git a/Scan/KType/scan_loop.c b/Scan/KType/scan_loop.c index 7999853..3f20cd9 100644 --- a/Scan/KType/scan_loop.c +++ b/Scan/KType/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2015 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +33,8 @@ #include #include #include +#include +#include // Local Includes #include "scan_loop.h" @@ -53,6 +55,9 @@ uint16_t Scan_scanCount = 0; // Setup inline void Scan_setup() { + // Setup Port Swap module + Port_setup(); + // Setup UART Connect, if Output_Available, this is the master node Connect_setup( Output_Available ); @@ -62,6 +67,9 @@ inline void Scan_setup() // Setup ISSI chip to control the leds LED_setup(); + // Setup Pixel Map + Pixel_setup(); + // Reset scan count Scan_scanCount = 0; } @@ -70,12 +78,18 @@ inline void Scan_setup() // Main Detection Loop inline uint8_t Scan_loop() { + // Port Swap detection + Port_scan(); + // Scan Matrix Matrix_scan( Scan_scanCount++ ); // Process any interconnect commands Connect_scan(); + // Prepare any LED events + Pixel_process(); + // Process any LED events LED_scan(); diff --git a/Scan/KType/setup.cmake b/Scan/KType/setup.cmake index 50aef79..5696ccd 100644 --- a/Scan/KType/setup.cmake +++ b/Scan/KType/setup.cmake @@ -12,6 +12,7 @@ # AddModule ( Scan ISSILed ) AddModule ( Scan MatrixARM ) +AddModule ( Scan PortSwap ) AddModule ( Scan UARTConnect ) diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index a9018df..8463b26 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -196,7 +196,6 @@ void Matrix_setup() print( NL ); info_msg("Max Keys: "); printHex( Matrix_maxKeys ); - print( NL ); // Clear out Debounce Array for ( uint8_t item = 0; item < Matrix_maxKeys; item++ ) diff --git a/Scan/WhiteFox/defaultMap.kll b/Scan/WhiteFox/defaultMap.kll index 798a0c7..e692d7b 100644 --- a/Scan/WhiteFox/defaultMap.kll +++ b/Scan/WhiteFox/defaultMap.kll @@ -82,6 +82,9 @@ S0x46 : U"Right"; # Defines available to the WhiteFox Scan Module +# Default animation speed +ISSI_AnimationSpeed = 3; # 20 by default + # LED Default Enable Mask Override # # Each LED is represented by a single bit @@ -115,15 +118,15 @@ ISSILedBrightness1 = " "; # Full brightness example -#ISSILedBrightness1 = " -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ -#0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ -#"; +ISSILedBrightness1 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +"; diff --git a/Scan/WhiteFox/scan_loop.c b/Scan/WhiteFox/scan_loop.c index 16cefa2..cac143b 100644 --- a/Scan/WhiteFox/scan_loop.c +++ b/Scan/WhiteFox/scan_loop.c @@ -32,6 +32,7 @@ #include #include #include +#include // Local Includes #include "scan_loop.h" @@ -58,6 +59,9 @@ inline void Scan_setup() // Setup ISSI chip to control the leds LED_setup(); + // Setup Pixel Map + Pixel_setup(); + // Reset scan count Scan_scanCount = 0; } @@ -69,6 +73,9 @@ inline uint8_t Scan_loop() // Scan Matrix Matrix_scan( Scan_scanCount++ ); + // Prepare any LED events + Pixel_process(); + // Process any LED events LED_scan(); From 9ed526deb669d793a2bd5a53d094f4cfbe17425c Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sun, 3 Jan 2016 16:16:41 -0800 Subject: [PATCH 07/30] Adding PixelMap - Includes basic (led) channel testing tools - Currently hard-coded, needs kll integration before this can be used in general --- Macro/PixelMap/capabilities.kll | 9 + Macro/PixelMap/pixel.c | 358 ++++++++++++++++++++++++++++++++ Macro/PixelMap/pixel.h | 102 +++++++++ Macro/PixelMap/setup.cmake | 31 +++ Scan/ISSILed/led_scan.c | 334 +++++++++++++---------------- Scan/MatrixARM/matrix_scan.c | 1 + 6 files changed, 646 insertions(+), 189 deletions(-) create mode 100644 Macro/PixelMap/capabilities.kll create mode 100644 Macro/PixelMap/pixel.c create mode 100644 Macro/PixelMap/pixel.h create mode 100644 Macro/PixelMap/setup.cmake diff --git a/Macro/PixelMap/capabilities.kll b/Macro/PixelMap/capabilities.kll new file mode 100644 index 0000000..3d5202d --- /dev/null +++ b/Macro/PixelMap/capabilities.kll @@ -0,0 +1,9 @@ +Name = PartialMapCapabilities; +Version = 0.1; +Author = "HaaTa (Jacob Alexander) 2015"; +KLL = 0.5; + +# Modified Date +Date = 2015-12-19; + + diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c new file mode 100644 index 0000000..4d188fa --- /dev/null +++ b/Macro/PixelMap/pixel.c @@ -0,0 +1,358 @@ +/* Copyright (C) 2015-2016 by Jacob Alexander + * + * This file 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, either version 3 of the License, or + * (at your option) any later version. + * + * This file 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 file. If not, see . + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include +#include + +// Local Includes +#include "pixel.h" + + + +// ----- Function Declarations ----- + +void cliFunc_chanTest ( char* args ); +void cliFunc_pixelList ( char* args ); +void cliFunc_pixelTest ( char* args ); + + + +// ----- Enums ----- + +typedef enum PixelTest { + PixelTest_Off = 0, // Disabled + PixelTest_Chan_All, // Enable all positions + PixelTest_Chan_Roll, // Iterate over all positions + PixelTest_Pixel_All, // Enable all positions + PixelTest_Pixel_Roll, // Iterate over all positions +} PixelTest; + + + +// ----- Variables ----- + +// Macro Module command dictionary +CLIDict_Entry( chanTest, "Channel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop" ); +CLIDict_Entry( pixelList, "Prints out pixel:channel mappings." ); +CLIDict_Entry( pixelTest, "Pixel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop" ); + +CLIDict_Def( pixelCLIDict, "Pixel Module Commands" ) = { + CLIDict_Item( chanTest ), + CLIDict_Item( pixelList ), + CLIDict_Item( pixelTest ), + { 0, 0, 0 } // Null entry for dictionary end +}; + +// Debug states +PixelTest Pixel_testMode; +uint16_t Pixel_testPos; + +// Frame State +// Indicates to pixel and output modules current state of the buffer +FrameState Pixel_FrameState; + + + + +// ------------------------------- +// TODO This part is generated +// ------------------------------- + +// TODO Generate list of buffers and pointers from kll +#define LED_BufferLength 144 +typedef struct LED_Buffer { + uint16_t i2c_addr; + uint16_t reg_addr; + uint16_t buffer[LED_BufferLength]; +} LED_Buffer; +extern LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; + + +// Buffer list +#define Pixel_BuffersLen 3 +#define Pixel_TotalChannels 432 +PixelBuf Pixel_Buffers[] = { + PixelBufElem( LED_BufferLength, 16, 0, LED_pageBuffer[0].buffer ), + PixelBufElem( LED_BufferLength, 16, 144, LED_pageBuffer[1].buffer ), + PixelBufElem( LED_BufferLength, 16, 288, LED_pageBuffer[2].buffer ), +}; + + +// Pixel Mapping +uint8_t Pixel_Mapping[] = { + Pixel_RGBChannel(0,1,2), + // TODO +}; + +// Frame of led changes +// const uint8_t _frame[] = { PixelMod, ... } +#define Pixel_ModRGB(pixel,type,r,g,b) pixel, PixelChange_##type, 1, r, g, b +const uint8_t testani_frame0[] = { + Pixel_ModRGB(0, Set, 30, 70, 120), +}; +const uint8_t testani_frame1[] = { + Pixel_ModRGB(0, Set, 0, 0, 0), +}; +const uint8_t testani_frame2[] = { + Pixel_ModRGB(0, Set, 60, 90, 140), +}; + +// Index of frames for animations +// uint8_t *_frames[] = { _frame, ... } +const uint8_t *testani_frames[] = { + testani_frame0, + testani_frame1, + testani_frame2, +}; + +// Index of animations +// uint8_t *Pixel_Animations[] = { _frames, ... } +const uint8_t **Pixel_Animations[] = { + testani_frames, +}; + +// ------------------------------- +// TODO GENERATED END +// ------------------------------- + + + +// ----- Capabilities ----- + + + +// ----- Functions ----- + +PixelBuf Pixel_bufferMap( uint16_t channel ) +{ + // TODO Generate + if ( channel < 144 ) return Pixel_Buffers[0]; + else if ( channel < 288 ) return Pixel_Buffers[1]; + else if ( channel < 432 ) return Pixel_Buffers[2]; + + // Invalid channel, return first channel and display error + erro_msg("Invalid channel: "); + printHex( channel ); + print( NL ); + return Pixel_Buffers[0]; +} + +void Pixel_channelToggle( uint16_t channel ) +{ + // Determine which buffer we are in + PixelBuf pixbuf = Pixel_bufferMap( channel ); + + // Toggle channel accordingly + switch ( pixbuf.width ) + { + // Invalid width, default to 8 + default: + warn_msg("Unknown width, using 8: "); + printInt8( pixbuf.width ); + print(" Ch: "); + printHex( channel ); + print( NL ); + // Falls through on purpose + + // 8bit width + case 8: + PixelBuf8( pixbuf, channel ) ^= 128; + break; + + // 16bit width + case 16: + PixelBuf16( pixbuf, channel ) ^= 128; + break; + } +} + +// Pixel Procesing Loop +inline void Pixel_process() +{ + // Only update frame when ready + if ( Pixel_FrameState != FrameState_Update ) + return; + + // First check if we are in a test mode + switch ( Pixel_testMode ) + { + // Toggle current position, then increment + case PixelTest_Chan_Roll: + // Toggle channel + Pixel_channelToggle( Pixel_testPos ); + + // Increment channel + Pixel_testPos++; + if ( Pixel_testPos >= Pixel_TotalChannels ) + Pixel_testPos = 0; + + goto pixel_process_done; + + // Blink all channels + case PixelTest_Chan_All: + { + uint16_t ch; + + // Only update 50 positions at a time + for ( ch = Pixel_testPos; ch < Pixel_testPos + 50 && ch < Pixel_TotalChannels; ch++ ) + { + // Toggle channel + Pixel_channelToggle( ch ); + } + + Pixel_testPos = ch; + + // Only signal frame update after all pixels complete + if ( Pixel_testPos >= Pixel_TotalChannels ) + { + Pixel_testPos = 0; + goto pixel_process_done; + } + + return; + } + + default: + break; + } + + +pixel_process_done: + // Frame is now ready to send + Pixel_FrameState = FrameState_Ready; +} + + +inline void Pixel_setup() +{ + // Register Pixel CLI dictionary + CLI_registerDictionary( pixelCLIDict, pixelCLIDictName ); + + // Set frame state to update + Pixel_FrameState = FrameState_Update; + + // Disable test modes by default, start at position 0 + Pixel_testMode = PixelTest_Off; +} + + +// ----- CLI Command Functions ----- + +void cliFunc_pixelList( char* args ) +{ + print( NL ); // No \r\n by default after the command is entered + + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; + + // Process speed argument if given + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Check for special args + switch ( *arg1Ptr ) + { + case 'b': + case 'B': + info_msg("Buffer List"); + + // List all buffers + for ( uint8_t buf = 0; buf < Pixel_BuffersLen; buf++ ) + { + print( NL "\t" ); + printInt8( buf ); + print(":"); + printHex32( (uint32_t)(Pixel_Buffers[ buf ].data) ); + print(":width("); + printInt8( Pixel_Buffers[ buf ].width ); + print("):size("); + printInt8( Pixel_Buffers[ buf ].size ); + print(")"); + } + break; + } +} + +void cliFunc_pixelTest( char* args ) +{ + print( NL ); +} + +void cliFunc_chanTest( char* args ) +{ + print( NL ); // No \r\n by default after the command is entered + + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; + + // Process speed argument if given + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Check for special args + switch ( *arg1Ptr ) + { + case 'a': + case 'A': + info_msg("All channel test"); + Pixel_testPos = 0; + Pixel_testMode = PixelTest_Chan_All; + return; + + case 'r': + case 'R': + info_msg("Channel roll test"); + Pixel_testPos = 0; + Pixel_testMode = PixelTest_Chan_Roll; + return; + + case 's': + case 'S': + info_msg("Stopping channel test"); + Pixel_testMode = PixelTest_Off; + return; + } + + // Check for specific position + if ( *arg1Ptr != '\0' ) + { + Pixel_testPos = numToInt( arg1Ptr ); + } + else + { + info_msg("Channel: "); + printInt16( Pixel_testPos ); + } + + // Toggle channel + Pixel_channelToggle( Pixel_testPos ); + + // Increment channel + Pixel_testPos++; + if ( Pixel_testPos >= Pixel_TotalChannels ) + Pixel_testPos = 0; +} + diff --git a/Macro/PixelMap/pixel.h b/Macro/PixelMap/pixel.h new file mode 100644 index 0000000..c629782 --- /dev/null +++ b/Macro/PixelMap/pixel.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2015 by Jacob Alexander + * + * This file 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, either version 3 of the License, or + * (at your option) any later version. + * + * This file 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 file. If not, see . + */ + +#pragma once + +// ----- Includes ----- + +// Compiler Includes +#include + + + +// ----- Enums ----- + +typedef enum FrameState { + FrameState_Ready, // Buffers have been updated and are ready to send + FrameState_Sending, // Buffers are currently being sent, do not change + FrameState_Update, // Buffers need to be updated to latest frame +} FrameState; + +// Pixel Change Storage +// - Store only the change of the pixel +// - Change is a value (size of the pixel) +// - Contiguous sets of pixel changes can be stored for maximized packing (with the same width) +// - Each value has a corresponding operator +// * Add +// * Subtract +// * Left shift +// * Right shift +// * Set +// * Add no-rollover +// * Subtract no-rollover +typedef enum PixelChange { + PixelChange_Set = 0, // + PixelChange_Add, // + + PixelChange_Subtract, // - + PixelChange_NoRoll_Add, // +: + PixelChange_NoRoll_Subtract, // -: + PixelChange_LeftShift, // << + PixelChange_RightShift, // >> +} PixelChange; + + + +// ----- Structs ----- + +// Element of array of buffers pointers +typedef struct PixelBuf { + uint8_t size; // Number of elements + uint8_t width; // Width of each element + uint16_t offset; // Subtraction offset from absolute channel + void *data; // Pointer to start of buffer +} PixelBuf; +#define PixelBufElem(len,width,offset,ptr) { len, width, offset, (void*)ptr } +#define PixelBuf8(pixbuf, ch) ( ((uint8_t*) (pixbuf.data))[ ch - pixbuf.offset ] ) +#define PixelBuf16(pixbuf, ch) ( ((uint16_t*)(pixbuf.data))[ ch - pixbuf.offset ] ) + + +// Individual Pixel element +typedef struct PixelElement { + uint8_t width; // Number of bits in a channel + uint8_t channels; // Number of channels + uint16_t indices[0]; // Hardware indices for each channel +} PixelElement; +#define s2b(num) (num >> 8), (num & 0xFF) +#define Pixel_RGBChannel(r,g,b) 8, 3, s2b(r), s2b(g), s2b(b) +#define Pixel_8bitChannel(c) 8, 1, s2b(c) + + +typedef struct PixelMod { + uint16_t pixel; // Pixel index + PixelChange change; // Change to apply to pixel + uint8_t contiguousPixels; // # of contiguous pixels to apply same changes too + uint8_t data[0]; // Data size depends on PixelElement definition +} PixelMod; + + + +// ----- Variables ----- + +extern FrameState Pixel_FrameState; + + + +// ----- Functions ----- + +void Pixel_process(); +void Pixel_setup(); + diff --git a/Macro/PixelMap/setup.cmake b/Macro/PixelMap/setup.cmake new file mode 100644 index 0000000..158ffa5 --- /dev/null +++ b/Macro/PixelMap/setup.cmake @@ -0,0 +1,31 @@ +###| CMake Kiibohd Controller Macro Module |### +# +# Written by Jacob Alexander in 2015 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Required Sub-modules +# +AddModule ( Macro PartialMap ) + + + +### +# Module C files +# +set ( Module_SRCS + pixel.c +) + + +### +# Compiler Family Compatibility +# +set ( ModuleCompatibility + arm +) + diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index e04067a..25ecc31 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -107,11 +107,8 @@ typedef struct LED_EnableBuffer { // CLI Functions void cliFunc_i2cSend ( char* args ); void cliFunc_ledCtrl ( char* args ); -void cliFunc_ledNFrame( char* args ); -void cliFunc_ledStart ( char* args ); -void cliFunc_ledTest ( char* args ); -void cliFunc_ledWPage ( char* args ); -void cliFunc_ledZero ( char* args ); +void cliFunc_ledReset ( char* args ); +void cliFunc_ledSpeed ( char* args ); @@ -120,31 +117,27 @@ void cliFunc_ledZero ( char* args ); // Scan Module command dictionary CLIDict_Entry( i2cSend, "Send I2C sequence of bytes. Use |'s to split sequences with a stop." ); CLIDict_Entry( ledCtrl, "Basic LED control. Args: []" ); -CLIDict_Entry( ledNFrame, "Increment led frame." ); -CLIDict_Entry( ledStart, "Disable software shutdown." ); -CLIDict_Entry( ledTest, "Test out the led pages." ); -CLIDict_Entry( ledWPage, "Write to given register page starting at address. i.e. 0xE8 0x2 0x24 0xF0 0x12" ); -CLIDict_Entry( ledZero, "Zero out LED register pages (non-configuration)." ); +CLIDict_Entry( ledReset, "Reset ISSI chips." ); +CLIDict_Entry( ledSpeed, "ISSI frame rate 0-63, 1 is fastest. f - display fps" ); CLIDict_Def( ledCLIDict, "ISSI LED Module Commands" ) = { CLIDict_Item( i2cSend ), CLIDict_Item( ledCtrl ), - CLIDict_Item( ledNFrame ), - CLIDict_Item( ledStart ), - CLIDict_Item( ledTest ), - CLIDict_Item( ledWPage ), - CLIDict_Item( ledZero ), + CLIDict_Item( ledReset ), + CLIDict_Item( ledSpeed ), { 0, 0, 0 } // Null entry for dictionary end }; -LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; +volatile LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; uint8_t LED_FrameBuffersReady; // Starts at maximum, reset on interrupt from ISSI volatile uint8_t LED_FrameBufferReset; // INTB interrupt received, reset available buffer count when ready uint8_t LED_FrameBufferPage; // Current page of the buffer uint8_t LED_FrameBufferStart; // Whether or not a start signal can be sent + uint8_t LED_displayFPS; // Display fps to cli + // Enable mask and default brightness for ISSI chip channel const LED_EnableBuffer LED_ledEnableMask[ISSI_Chips_define] = { LED_MaskDefine( 1 ), @@ -251,6 +244,39 @@ void LED_sendPage( uint8_t addr, uint16_t *buffer, uint32_t len, uint8_t page ) delay(1); } +// Write register on all ISSI chips +// Prepare pages first, then attempt write register with a minimal delay between chips +void LED_syncReg( uint8_t reg, uint8_t val, uint8_t page ) +{ + uint16_t pageSetup[] = { 0, 0xFD, page }; + + // Setup each of the pages + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + pageSetup[0] = LED_pageBuffer[ ch ].i2c_addr; + + while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + delay(1); + } + + // Reg Write Setup + uint16_t writeData[] = { 0, reg, val }; + + // Write to all the registers + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + writeData[0] = LED_pageBuffer[ ch ].i2c_addr; + + // Delay very little to help with synchronization + while ( i2c_send( writeData, sizeof( writeData ) / 2 ) == -1 ) + delayMicroseconds(10); + } + + // Delay until written + while ( i2c_busy() ) + delay(1); +} + // Write address void LED_writeReg( uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) { @@ -308,6 +334,63 @@ uint8_t LED_readReg( uint8_t addr, uint8_t reg, uint8_t page ) return recv_data; } +void LED_reset() +{ + // Reset frame buffer used count + LED_FrameBuffersReady = LED_FrameBuffersMax; + + // Starting page for the buffers + LED_FrameBufferPage = 4; + + // Initially do not allow autoplay to restart + LED_FrameBufferStart = 0; + + // Disable FPS by default + LED_displayFPS = 0; + + // Clear LED Pages + // Enable LEDs based upon mask + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers + + // For each page + for ( uint8_t pg = 0; pg < LED_FrameBuffersMax * 2; pg++ ) + { + LED_sendPage( + addr, + (uint16_t*)&LED_ledEnableMask[ ch ], + sizeof( LED_EnableBuffer ) / 2, + pg + ); + } + } + + // Setup ISSI auto frame play, but do not start yet + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + // CNS 1 loop, FNS 4 frames - 0x14 + LED_writeReg( addr, 0x02, 0x14, 0x0B ); + + // Default refresh speed - TxA + // T is typically 11ms + // A is 1 to 64 (where 0 is 64) + LED_writeReg( addr, 0x03, ISSI_AnimationSpeed_define, 0x0B ); + + // Set MODE to Auto Frame Play + LED_writeReg( addr, 0x00, 0x08, 0x0B ); + } + + // Disable Software shutdown of ISSI chip + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + } +} + // Setup inline void LED_setup() { @@ -359,56 +442,8 @@ inline void LED_setup() // Enable PORTB interrupt NVIC_ENABLE_IRQ( IRQ_PORTB ); - // Reset frame buffer used count - LED_FrameBuffersReady = LED_FrameBuffersMax; - - // Starting page for the buffers - LED_FrameBufferPage = 4; - - // Initially do not allow autoplay to restart - LED_FrameBufferStart = 0; - - // Clear LED Pages - // Enable LEDs based upon mask - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers - - // For each page - for ( uint8_t pg = 0; pg < LED_FrameBuffersMax * 2; pg++ ) - { - LED_sendPage( - addr, - (uint16_t*)&LED_ledEnableMask[ ch ], - sizeof( LED_EnableBuffer ) / 2, - pg - ); - } - } - - // Setup ISSI auto frame play, but do not start yet - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - // CNS 1 loop, FNS 4 frames - 0x14 - LED_writeReg( addr, 0x02, 0x14, 0x0B ); - - // Default refresh speed - TxA - // T is typically 11ms - // A is 1 to 64 (where 0 is 64) - LED_writeReg( addr, 0x03, ISSI_AnimationSpeed_define, 0x0B ); - - // Set MODE to Auto Frame Play - LED_writeReg( addr, 0x00, 0x08, 0x0B ); - } - - // Disable Software shutdown of ISSI chip - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_writeReg( addr, 0x0A, 0x01, 0x0B ); - } + // Reset LED sequencing + LED_reset(); } @@ -480,13 +515,17 @@ inline void LED_scan() if ( LED_FrameBufferReset ) { LED_FrameBufferReset = 0; + // Delay, in order to synchronize chips LED_FrameBufferStart = 1; - // Debug Status - dbug_msg("4frames/"); - printInt32( systick_millis_count - LED_timePrev ); - LED_timePrev = systick_millis_count; - print("ms" NL); + // FPS Display + if ( LED_displayFPS ) + { + dbug_msg("4frames/"); + printInt32( systick_millis_count - LED_timePrev ); + LED_timePrev = systick_millis_count; + print( "ms" NL ); + } } // Make sure there are buffers available @@ -497,15 +536,9 @@ inline void LED_scan() if ( !LED_FrameBufferStart || Pixel_FrameState == FrameState_Sending ) return; - // Buffers are now full, start signal can be sent - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - - // Start Auto Frame Play on either frame 1 or 5 - uint8_t frame = LED_FrameBufferPage == 0 ? 4 : 0; - LED_writeReg( addr, 0x00, 0x08 | frame, 0x0B ); - } + // Start Auto Frame Play on either frame 1 or 5 + uint8_t frame = LED_FrameBufferPage == 0 ? 4 : 0; + LED_syncReg( 0x00, 0x08 | frame, 0x0B ); LED_FrameBufferStart = 0; LED_FrameBuffersReady = LED_FrameBuffersMax; @@ -777,9 +810,9 @@ void cliFunc_i2cSend( char* args ) i2c_send( buffer, bufferLen ); } +/* void cliFunc_ledWPage( char* args ) { - /* char* curArgs; char* arg1Ptr; char* arg2Ptr = args; @@ -833,23 +866,29 @@ void cliFunc_ledWPage( char* args ) // Increment address data[1]++; } - */ } +*/ -void cliFunc_ledStart( char* args ) +void cliFunc_ledReset( char* args ) { print( NL ); // No \r\n by default after the command is entered for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { LED_zeroPages( LED_ledEnableMask[ ch ].i2c_addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers - //LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers - LED_writeReg( LED_ledEnableMask[ ch ].i2c_addr, 0x0A, 0x01, 0x0B ); - LED_sendPage( LED_ledEnableMask[ ch ].i2c_addr, (uint16_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ) / 2, 0 ); + } + + // Clear buffers + for ( uint8_t buf = 0; buf < ISSI_Chips_define; buf++ ) + { + memset( (void*)LED_pageBuffer[ buf ].buffer, 0, LED_BufferLength * 2 ); + } + + LED_reset(); } -void cliFunc_ledTest( char* args ) +void cliFunc_ledSpeed( char* args ) { print( NL ); // No \r\n by default after the command is entered @@ -862,121 +901,38 @@ void cliFunc_ledTest( char* args ) curArgs = arg2Ptr; CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + // Check if f argument was given + switch ( *arg1Ptr ) + { + case 'f': + case 'F': + info_msg("FPS Toggle"); + LED_displayFPS = !LED_displayFPS; + return; + } + // Stop processing args if no more are found if ( *arg1Ptr != '\0' ) + { speed = numToInt( arg1Ptr ); + } + // Default to default speed + else + { + info_msg("Setting default speed: "); + printInt8( speed ); + } - // TODO REMOVEME + // Set refresh speed per ISSI chip for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - // CNS 1 loop, FNS 4 frames - 0x14 - //LED_writeReg( addr, 0x02, 0x14, 0x0B ); // Default refresh speed - TxA // T is typically 11ms // A is 1 to 64 (where 0 is 64) LED_writeReg( addr, 0x03, speed, 0x0B ); - - // Set MODE to Auto Frame Play - // Set FS to 5, this is to train the IRQ on the ISSI for the processing loop - // The first 4 frames are blank, we fill the last 4 - // Clear the interrupt, and the movie display starts at frame 5 - //LED_writeReg( addr, 0x00, 0x0C, 0x0B ); - } - return; - - // Zero out Frame Registers - // This needs to be done before disabling the hardware shutdown (or the leds will do undefined things) - info_print("LED - Zeroing out all pages"); - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_zeroPages( addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers - LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers - } - - // Clear LED Pages - // Enable LEDs based upon mask - info_print("LED - Setting LED enable mask"); - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - //for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - - // For each page - for ( uint8_t pg = 0; pg < LED_FrameBuffersMax * 2; pg++ ) - { - LED_sendPage( - addr, - (uint16_t*)&LED_ledEnableMask[ ch ], - sizeof( LED_EnableBuffer ) / 2, - pg - ); - } - } - - // Setup ISSI auto frame play, but do not start yet - /* - info_print("LED - Enabling 8 frame 3 loop auto play"); - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - // CNS 3 loops, FNS all frames - 0x30 - LED_writeReg( addr, 0x02, 0x30, 0x0B ); - - // Default refresh speed - TxA - // T is typically 11ms - // A is 1 to 64 (where 0 is 64) - LED_writeReg( addr, 0x03, speed, 0x0B ); - - // Set MODE to Auto Frame Play - // Set FS to frame 1 - //LED_writeReg( addr, 0x00, 0x08, 0x0B ); - } - */ - - // Load frame data - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - - // Load each page with a different led enabled - uint16_t data[] = { - addr, 0xFD, 0x00, - }; - while( i2c_send( data, sizeof( data ) / 2 ) == -1 ) - delay( 1 ); - data[1] = 0x24; - data[2] = 0xFF; - while( i2c_send( data, sizeof( data ) / 2 ) == -1 ) - delay( 1 ); - } - - // Disable Software shutdown of ISSI chip - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_writeReg( addr, 0x0A, 0x01, 0x0B ); - } - -/* - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - LED_sendPage( LED_defaultBrightness[ ch ].i2c_addr, (uint16_t*)&LED_defaultBrightness[ ch ], sizeof( LED_Buffer ), 0 ); - } -*/ -} - -void cliFunc_ledZero( char* args ) -{ - print( NL ); // No \r\n by default after the command is entered - - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) - { - LED_zeroPages( LED_defaultBrightness[ ch ].i2c_addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers - LED_zeroPages( LED_defaultBrightness[ ch ].i2c_addr, 0x00, 8, 0x24, 0xB4 ); // Only PWMs } } diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index 8463b26..a9018df 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -196,6 +196,7 @@ void Matrix_setup() print( NL ); info_msg("Max Keys: "); printHex( Matrix_maxKeys ); + print( NL ); // Clear out Debounce Array for ( uint8_t item = 0; item < Matrix_maxKeys; item++ ) From b30f8f5e97cd6c094796d359b8559d05e20471df Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sun, 3 Jan 2016 18:37:22 -0800 Subject: [PATCH 08/30] Initial (non-kll) pixel mappings for KType - Includes pixel testing functions --- Macro/PixelMap/pixel.c | 244 +++++++++++++++++++++++++++++++++++++++- Macro/PixelMap/pixel.h | 12 +- Scan/ISSILed/led_scan.c | 2 +- 3 files changed, 248 insertions(+), 10 deletions(-) diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index 4d188fa..4f56a29 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -100,9 +100,116 @@ PixelBuf Pixel_Buffers[] = { // Pixel Mapping -uint8_t Pixel_Mapping[] = { - Pixel_RGBChannel(0,1,2), - // TODO +#define Pixel_TotalPixels 95 // TODO Generate +PixelElement Pixel_Mapping[] = { + // Function Row (1-16) + Pixel_RGBChannel(0,33,49), // 1 + Pixel_RGBChannel(1,17,50), // 2 + Pixel_RGBChannel(2,18,34), // 3 + Pixel_RGBChannel(3,19,35), // 4 + Pixel_RGBChannel(4,20,36), // 5 + Pixel_RGBChannel(5,21,37), // 6 + Pixel_RGBChannel(6,22,38), // 7 + Pixel_RGBChannel(7,23,39), // 8 + Pixel_RGBChannel(128,112,96), // 9 + Pixel_RGBChannel(129,113,97), // 10 + Pixel_RGBChannel(130,114,98), // 11 + Pixel_RGBChannel(131,115,99), // 12 + Pixel_RGBChannel(132,116,100), // 13 + Pixel_RGBChannel(133,117,101), // 14 + Pixel_RGBChannel(134,118,85), // 15 + Pixel_RGBChannel(135,102,86), // 16 + + // Number Row (17-35) + Pixel_RGBChannel(8,41,57), // 17 + Pixel_RGBChannel(9,25,58), // 18 + Pixel_RGBChannel(10,26,42), // 19 + Pixel_RGBChannel(11,27,43), // 20 + Pixel_RGBChannel(12,28,44), // 21 + Pixel_RGBChannel(13,29,45), // 22 + Pixel_RGBChannel(14,30,46), // 23 + Pixel_RGBChannel(15,31,47), // 24 + Pixel_RGBChannel(136,120,104), // 25 + Pixel_RGBChannel(137,121,105), // 26 + Pixel_RGBChannel(138,122,106), // 27 + Pixel_RGBChannel(139,123,107), // 28 + Pixel_RGBChannel(140,124,108), // 29 + Pixel_RGBChannel(141,125,109), // 30 + Pixel_RGBChannel(142,126,93), // 31 + Pixel_RGBChannel(143,110,94), // 32 + Pixel_RGBChannel(144,177,193), // 33 + Pixel_RGBChannel(145,161,194), // 34 + Pixel_RGBChannel(146,162,178), // 35 + + // Top Alpha Row (36-53) + Pixel_RGBChannel(147,163,179), // 36 + Pixel_RGBChannel(148,164,180), // 37 + Pixel_RGBChannel(149,165,181), // 38 + Pixel_RGBChannel(150,166,182), // 39 + Pixel_RGBChannel(151,167,183), // 40 + Pixel_RGBChannel(272,256,240), // 41 + Pixel_RGBChannel(273,257,241), // 42 + Pixel_RGBChannel(274,258,242), // 43 + Pixel_RGBChannel(275,259,243), // 44 + Pixel_RGBChannel(276,260,244), // 45 + Pixel_RGBChannel(277,261,245), // 46 + Pixel_RGBChannel(278,262,229), // 47 + Pixel_RGBChannel(279,246,230), // 48 + Pixel_RGBChannel(152,185,201), // 49 + Pixel_RGBChannel(153,169,202), // 50 + Pixel_RGBChannel(154,170,186), // 51 + Pixel_RGBChannel(155,171,187), // 52 + Pixel_RGBChannel(156,172,188), // 53 + + // Mid Alpha Row (54-67) + Pixel_RGBChannel(157,173,189), // 54 + Pixel_RGBChannel(158,174,190), // 55 + Pixel_RGBChannel(159,175,191), // 56 + Pixel_RGBChannel(280,264,248), // 57 + Pixel_RGBChannel(281,265,249), // 58 + Pixel_RGBChannel(282,266,250), // 59 + Pixel_RGBChannel(283,267,251), // 60 + Pixel_RGBChannel(284,268,252), // 61 + Pixel_RGBChannel(285,269,253), // 62 + Pixel_RGBChannel(286,270,237), // 63 + Pixel_RGBChannel(287,254,238), // 64 + Pixel_RGBChannel(288,321,337), // 65 + Pixel_RGBChannel(289,305,338), // 66 + Pixel_RGBChannel(290,306,322), // 67 + + // Low Alpha Row (68-84) + Pixel_RGBChannel(291,307,323), // 68 + Pixel_RGBChannel(292,308,324), // 69 + Pixel_RGBChannel(293,309,325), // 70 + Pixel_RGBChannel(294,310,326), // 71 + Pixel_RGBChannel(295,311,327), // 72 + Pixel_RGBChannel(416,400,384), // 73 + Pixel_RGBChannel(417,401,385), // 74 + Pixel_RGBChannel(418,402,386), // 75 + Pixel_RGBChannel(419,403,387), // 76 + Pixel_RGBChannel(420,404,388), // 77 + Pixel_RGBChannel(421,405,389), // 78 + Pixel_RGBChannel(422,406,373), // 79 + Pixel_RGBChannel(423,390,374), // 80 + Pixel_RGBChannel(296,329,345), // 81 + Pixel_RGBChannel(297,313,346), // 82 + Pixel_RGBChannel(298,314,330), // 83 + Pixel_RGBChannel(299,315,331), // 84 + + // Mod Row (85-95) + Pixel_RGBChannel(300,316,332), // 85 + Pixel_RGBChannel(301,317,333), // 86 + Pixel_RGBChannel(302,318,334), // 87 + Pixel_RGBChannel(303,319,335), // 88 + Pixel_RGBChannel(424,408,392), // 89 + Pixel_RGBChannel(425,409,393), // 90 + Pixel_RGBChannel(426,410,394), // 91 + Pixel_RGBChannel(427,411,395), // 92 + Pixel_RGBChannel(428,412,396), // 93 + Pixel_RGBChannel(429,413,397), // 94 + Pixel_RGBChannel(430,414,381), // 95 + + // Underlighting - TODO }; // Frame of led changes @@ -158,6 +265,7 @@ PixelBuf Pixel_bufferMap( uint16_t channel ) return Pixel_Buffers[0]; } +// Toggle the given channel void Pixel_channelToggle( uint16_t channel ) { // Determine which buffer we are in @@ -187,6 +295,16 @@ void Pixel_channelToggle( uint16_t channel ) } } +// Toggle given pixel elementt +void Pixel_pixelToggle( PixelElement *elem ) +{ + // Toggle each of the channels of the pixel + for ( uint8_t ch = 0; ch < elem->channels; ch++ ) + { + Pixel_channelToggle( elem->indices[ch] ); + } +} + // Pixel Procesing Loop inline void Pixel_process() { @@ -233,6 +351,42 @@ inline void Pixel_process() return; } + // Toggle current position, then increment + case PixelTest_Pixel_Roll: + // Toggle channel + Pixel_pixelToggle( &Pixel_Mapping[ Pixel_testPos ] ); + + // Increment channel + Pixel_testPos++; + if ( Pixel_testPos >= Pixel_TotalPixels ) + Pixel_testPos = 0; + + goto pixel_process_done; + + + case PixelTest_Pixel_All: + { + uint16_t px; + + // Only update 10 positions at a time + for ( px = Pixel_testPos; px < Pixel_testPos + 50 && px < Pixel_TotalPixels; px++ ) + { + // Toggle channel + Pixel_pixelToggle( &Pixel_Mapping[ px ] ); + } + + Pixel_testPos = px; + + // Only signal frame update after all pixels complete + if ( Pixel_testPos >= Pixel_TotalPixels ) + { + Pixel_testPos = 0; + goto pixel_process_done; + } + + return; + } + default: break; } @@ -292,12 +446,94 @@ void cliFunc_pixelList( char* args ) print(")"); } break; + + default: + info_msg("Pixel List - [,...]:..."); + + // List all pixels + for ( uint16_t pixel = 0; pixel < Pixel_TotalPixels; pixel++ ) + { + // NL occaisionally + if ( pixel % 5 == 0 ) + print( NL ); + + PixelElement *elem = (PixelElement*)&Pixel_Mapping[ pixel ]; + + printHex_op( pixel, 2 ); + print(":"); + printInt8( elem->width ); + print("["); + + // Display each of the channels + printHex_op( elem->indices[0], 2 ); + for ( uint8_t ch = 1; ch < elem->channels; ch++ ) + { + print(","); + printHex_op( elem->indices[ch], 2 ); + } + + print("]"); + print(" "); + } + + break; } } void cliFunc_pixelTest( char* args ) { - print( NL ); + print( NL ); // No \r\n by default after the command is entered + + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; + + // Process speed argument if given + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Check for special args + switch ( *arg1Ptr ) + { + case 'a': + case 'A': + info_msg("All pixel test"); + Pixel_testPos = 0; + Pixel_testMode = PixelTest_Pixel_All; + return; + + case 'r': + case 'R': + info_msg("Pixel roll test"); + Pixel_testPos = 0; + Pixel_testMode = PixelTest_Pixel_Roll; + return; + + case 's': + case 'S': + info_msg("Stopping pixel test"); + Pixel_testMode = PixelTest_Off; + return; + } + + // Check for specific position + if ( *arg1Ptr != '\0' ) + { + Pixel_testPos = numToInt( arg1Ptr ); + } + else + { + info_msg("Pixel: "); + printInt16( Pixel_testPos ); + } + + // Toggle channel + Pixel_pixelToggle( &Pixel_Mapping[ Pixel_testPos ] ); + + // Increment channel + Pixel_testPos++; + if ( Pixel_testPos >= Pixel_TotalPixels ) + Pixel_testPos = 0; } void cliFunc_chanTest( char* args ) diff --git a/Macro/PixelMap/pixel.h b/Macro/PixelMap/pixel.h index c629782..784b30b 100644 --- a/Macro/PixelMap/pixel.h +++ b/Macro/PixelMap/pixel.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 by Jacob Alexander +/* Copyright (C) 2015-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -70,14 +70,16 @@ typedef struct PixelBuf { // Individual Pixel element +#define Pixel_MaxChannelPerPixel 3 // TODO Generate typedef struct PixelElement { uint8_t width; // Number of bits in a channel uint8_t channels; // Number of channels - uint16_t indices[0]; // Hardware indices for each channel + // Hardware indices for each channel + uint16_t indices[Pixel_MaxChannelPerPixel]; } PixelElement; -#define s2b(num) (num >> 8), (num & 0xFF) -#define Pixel_RGBChannel(r,g,b) 8, 3, s2b(r), s2b(g), s2b(b) -#define Pixel_8bitChannel(c) 8, 1, s2b(c) +#define Pixel_RGBChannel(r,g,b) { 8, 3, { r, g, b } } +// TODO generate macro based on max channels +//#define Pixel_8bitChannel(c) { 8, 1, { c } } typedef struct PixelMod { diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index 25ecc31..6de94e8 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From ad1ea632e49c00f74a2dd1561c99c844bcd2c851 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sun, 3 Jan 2016 23:45:13 -0800 Subject: [PATCH 09/30] Initial code for Animation stack --- Macro/PixelMap/pixel.c | 88 ++++++++++++++++++++++++++++++++++++++++++ Macro/PixelMap/pixel.h | 27 ++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index 4f56a29..d120b2a 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -32,6 +32,8 @@ // ----- Function Declarations ----- +void cliFunc_aniAdd ( char* args ); +void cliFunc_aniDel ( char* args ); void cliFunc_chanTest ( char* args ); void cliFunc_pixelList ( char* args ); void cliFunc_pixelTest ( char* args ); @@ -53,11 +55,15 @@ typedef enum PixelTest { // ----- Variables ----- // Macro Module command dictionary +CLIDict_Entry( aniAdd, "Add the given animation id to the stack" ); +CLIDict_Entry( aniDel, "Remove the given stack index animation" ); CLIDict_Entry( chanTest, "Channel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop" ); CLIDict_Entry( pixelList, "Prints out pixel:channel mappings." ); CLIDict_Entry( pixelTest, "Pixel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop" ); CLIDict_Def( pixelCLIDict, "Pixel Module Commands" ) = { + CLIDict_Item( aniAdd ), + CLIDict_Item( aniDel ), CLIDict_Item( chanTest ), CLIDict_Item( pixelList ), CLIDict_Item( pixelTest ), @@ -72,6 +78,9 @@ uint16_t Pixel_testPos; // Indicates to pixel and output modules current state of the buffer FrameState Pixel_FrameState; +// Animation Stack +AnimationStack Pixel_AnimationStack; + @@ -225,6 +234,47 @@ const uint8_t testani_frame2[] = { Pixel_ModRGB(0, Set, 60, 90, 140), }; + + +// Rainbow Animation - Hardcoded +const uint8_t rainbow_frame0[] = { + // Set 1 + Pixel_ModRGB(84, Set, 127,0,255), +}; + +const uint8_t rainbow_frame1[] = { + // Set 1 + Pixel_ModRGB(84, Set, 127,0,255), + + // Set 2 + Pixel_ModRGB(16, Set, 127,0,255), + Pixel_ModRGB(35, Set, 127,0,255), + Pixel_ModRGB(53, Set, 127,0,255), + Pixel_ModRGB(68, Set, 127,0,255), + Pixel_ModRGB(85, Set, 127,0,255), +}; + +const uint8_t rainbow_frame2[] = { + // Set 1 + Pixel_ModRGB(84, Set, 127,0,255), + + // Set 2 + Pixel_ModRGB(16, Set, 127,0,255), + Pixel_ModRGB(35, Set, 127,0,255), + Pixel_ModRGB(53, Set, 127,0,255), + Pixel_ModRGB(68, Set, 127,0,255), + Pixel_ModRGB(85, Set, 127,0,255), + + // Set 3 + Pixel_ModRGB(0, Set, 127,0,255), + Pixel_ModRGB(17, Set, 127,0,255), + Pixel_ModRGB(36, Set, 127,0,255), + Pixel_ModRGB(54, Set, 127,0,255), + Pixel_ModRGB(70, Set, 127,0,255), + Pixel_ModRGB(86, Set, 127,0,255), +}; + + // Index of frames for animations // uint8_t *_frames[] = { _frame, ... } const uint8_t *testani_frames[] = { @@ -233,10 +283,20 @@ const uint8_t *testani_frames[] = { testani_frame2, }; + +// Rainbow frame index +const uint8_t *rainbow_frames[] = { + rainbow_frame0, + rainbow_frame1, + rainbow_frame2, +}; + + // Index of animations // uint8_t *Pixel_Animations[] = { _frames, ... } const uint8_t **Pixel_Animations[] = { testani_frames, + rainbow_frames, }; // ------------------------------- @@ -391,6 +451,9 @@ inline void Pixel_process() break; } + // Start from the top of the Animation Stack + // TODO + pixel_process_done: // Frame is now ready to send @@ -408,6 +471,9 @@ inline void Pixel_setup() // Disable test modes by default, start at position 0 Pixel_testMode = PixelTest_Off; + + // Clear animation stack + Pixel_AnimationStack.size = 0; } @@ -592,3 +658,25 @@ void cliFunc_chanTest( char* args ) Pixel_testPos = 0; } +void cliFunc_aniAdd( char* args ) +{ + print( NL ); // No \r\n by default after the command is entered + + // TODO + uint16_t index = Pixel_AnimationStack.size; + Pixel_AnimationStack.stack[index].index = 1; + Pixel_AnimationStack.stack[index].pos = 1; + Pixel_AnimationStack.stack[index].loops = 1; + Pixel_AnimationStack.stack[index].divider = 0; + Pixel_AnimationStack.stack[index].modifier = AnimationModifier_None; + Pixel_AnimationStack.size++; +} + +void cliFunc_aniDel( char* args ) +{ + print( NL ); // No \r\n by default after the command is entered + + // TODO + Pixel_AnimationStack.size--; +} + diff --git a/Macro/PixelMap/pixel.h b/Macro/PixelMap/pixel.h index 784b30b..5acc46b 100644 --- a/Macro/PixelMap/pixel.h +++ b/Macro/PixelMap/pixel.h @@ -44,7 +44,7 @@ typedef enum FrameState { // * Add no-rollover // * Subtract no-rollover typedef enum PixelChange { - PixelChange_Set = 0, // + PixelChange_Set = 0, // = PixelChange_Add, // + PixelChange_Subtract, // - PixelChange_NoRoll_Add, // +: @@ -54,6 +54,13 @@ typedef enum PixelChange { } PixelChange; +// Animation modifiers +typedef enum AnimationModifier { + AnimationModifier_None = 0x00, + AnimationModifier_Fallthrough = 0x01, // Process lower animation first +} AnimationModifier; + + // ----- Structs ----- @@ -74,7 +81,7 @@ typedef struct PixelBuf { typedef struct PixelElement { uint8_t width; // Number of bits in a channel uint8_t channels; // Number of channels - // Hardware indices for each channel + // Hardware indices for each channel uint16_t indices[Pixel_MaxChannelPerPixel]; } PixelElement; #define Pixel_RGBChannel(r,g,b) { 8, 3, { r, g, b } } @@ -89,6 +96,22 @@ typedef struct PixelMod { uint8_t data[0]; // Data size depends on PixelElement definition } PixelMod; +// Animation stack element +typedef struct AnimationElement { + uint16_t index; // Animation id + uint16_t pos; // Current frame + uint8_t loops; // # of loops to run animation, 0 indicates infinite + uint8_t divider; // # of times to repeat each frame + AnimationModifier modifier; // Modifier applied to the entire animation +} AnimationElement; + +// Animation stack +#define Pixel_AnimationStackSize 16 +typedef struct AnimationStack { + uint16_t size; + AnimationElement stack[Pixel_AnimationStackSize]; +} AnimationStack; + // ----- Variables ----- From 922885d749a550c9fa1147c696fcaf234a6c5e68 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Tue, 5 Jan 2016 04:04:11 -0800 Subject: [PATCH 10/30] Basic hard-coded KType rainbow demo --- Macro/PixelMap/pixel.c | 2256 +++++++++++++++++++++++++++++++++++++++- Macro/PixelMap/pixel.h | 4 +- 2 files changed, 2227 insertions(+), 33 deletions(-) diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index d120b2a..98b213b 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -48,6 +48,7 @@ typedef enum PixelTest { PixelTest_Chan_Roll, // Iterate over all positions PixelTest_Pixel_All, // Enable all positions PixelTest_Pixel_Roll, // Iterate over all positions + PixelTest_Pixel_Test, } PixelTest; @@ -223,57 +224,2109 @@ PixelElement Pixel_Mapping[] = { // Frame of led changes // const uint8_t _frame[] = { PixelMod, ... } -#define Pixel_ModRGB(pixel,type,r,g,b) pixel, PixelChange_##type, 1, r, g, b +#define s2bs(n) (n & 0xFF), (n >> 8) +#define Pixel_ModRGB(pixel,type,color) s2bs(pixel), PixelChange_##type, 1, color +#define Pixel_ModRGB_(pixel,type,r,g,b) pixel, PixelChange_##type, 1, r, g, b const uint8_t testani_frame0[] = { - Pixel_ModRGB(0, Set, 30, 70, 120), + Pixel_ModRGB_(0, Set, 30, 70, 120), }; const uint8_t testani_frame1[] = { - Pixel_ModRGB(0, Set, 0, 0, 0), + Pixel_ModRGB_(0, Set, 0, 0, 0), }; const uint8_t testani_frame2[] = { - Pixel_ModRGB(0, Set, 60, 90, 140), + Pixel_ModRGB_(0, Set, 60, 90, 140), }; +// Temp convenience colours +#define RGB_HalfRed 127,0,0 +#define RGB_Red 255,0,0 +#define RGB_RedOrange 255,64,0 +#define RGB_Orange 255,127,0 +#define RGB_OrangeYellow 255,191,0 +#define RGB_Yellow 255,255,0 +#define RGB_YellowGreen 127,255,0 +#define RGB_Green 0,255,0 +#define RGB_GreenBlue 0,127,127 +#define RGB_Blue 0,0,255 +#define RGB_BlueIndigo 38,0,193 +#define RGB_Indigo 75,0,130 +#define RGB_IndigoViolet 101,0,193 +#define RGB_Violet 127,0,255 +#define RGB_HalfViolet 64,0,127 +#define RGB_White 255,255,255 +#define RGB_Black 0,0,0 // Rainbow Animation - Hardcoded const uint8_t rainbow_frame0[] = { // Set 1 - Pixel_ModRGB(84, Set, 127,0,255), + Pixel_ModRGB(84, Set, RGB_HalfRed), }; const uint8_t rainbow_frame1[] = { // Set 1 - Pixel_ModRGB(84, Set, 127,0,255), + Pixel_ModRGB(84, Set, RGB_Red), // Set 2 - Pixel_ModRGB(16, Set, 127,0,255), - Pixel_ModRGB(35, Set, 127,0,255), - Pixel_ModRGB(53, Set, 127,0,255), - Pixel_ModRGB(68, Set, 127,0,255), - Pixel_ModRGB(85, Set, 127,0,255), + Pixel_ModRGB(16, Set, RGB_HalfRed), + Pixel_ModRGB(35, Set, RGB_HalfRed), + Pixel_ModRGB(53, Set, RGB_HalfRed), + Pixel_ModRGB(68, Set, RGB_HalfRed), + Pixel_ModRGB(85, Set, RGB_HalfRed), }; const uint8_t rainbow_frame2[] = { // Set 1 - Pixel_ModRGB(84, Set, 127,0,255), + Pixel_ModRGB(84, Set, RGB_RedOrange), // Set 2 - Pixel_ModRGB(16, Set, 127,0,255), - Pixel_ModRGB(35, Set, 127,0,255), - Pixel_ModRGB(53, Set, 127,0,255), - Pixel_ModRGB(68, Set, 127,0,255), - Pixel_ModRGB(85, Set, 127,0,255), + Pixel_ModRGB(16, Set, RGB_Red), + Pixel_ModRGB(35, Set, RGB_Red), + Pixel_ModRGB(53, Set, RGB_Red), + Pixel_ModRGB(68, Set, RGB_Red), + Pixel_ModRGB(85, Set, RGB_Red), // Set 3 - Pixel_ModRGB(0, Set, 127,0,255), - Pixel_ModRGB(17, Set, 127,0,255), - Pixel_ModRGB(36, Set, 127,0,255), - Pixel_ModRGB(54, Set, 127,0,255), - Pixel_ModRGB(70, Set, 127,0,255), - Pixel_ModRGB(86, Set, 127,0,255), + Pixel_ModRGB(0, Set, RGB_HalfRed), + Pixel_ModRGB(17, Set, RGB_HalfRed), + Pixel_ModRGB(36, Set, RGB_HalfRed), + Pixel_ModRGB(54, Set, RGB_HalfRed), + Pixel_ModRGB(70, Set, RGB_HalfRed), + Pixel_ModRGB(86, Set, RGB_HalfRed), }; +const uint8_t rainbow_frame3[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Orange), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_RedOrange), + Pixel_ModRGB(35, Set, RGB_RedOrange), + Pixel_ModRGB(53, Set, RGB_RedOrange), + Pixel_ModRGB(68, Set, RGB_RedOrange), + Pixel_ModRGB(85, Set, RGB_RedOrange), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_Red), + Pixel_ModRGB(17, Set, RGB_Red), + Pixel_ModRGB(36, Set, RGB_Red), + Pixel_ModRGB(54, Set, RGB_Red), + Pixel_ModRGB(70, Set, RGB_Red), + Pixel_ModRGB(86, Set, RGB_Red), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_HalfRed), + Pixel_ModRGB(37, Set, RGB_HalfRed), + Pixel_ModRGB(55, Set, RGB_HalfRed), + Pixel_ModRGB(71, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame4[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_OrangeYellow), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_Orange), + Pixel_ModRGB(35, Set, RGB_Orange), + Pixel_ModRGB(53, Set, RGB_Orange), + Pixel_ModRGB(68, Set, RGB_Orange), + Pixel_ModRGB(85, Set, RGB_Orange), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_RedOrange), + Pixel_ModRGB(17, Set, RGB_RedOrange), + Pixel_ModRGB(36, Set, RGB_RedOrange), + Pixel_ModRGB(54, Set, RGB_RedOrange), + Pixel_ModRGB(70, Set, RGB_RedOrange), + Pixel_ModRGB(86, Set, RGB_RedOrange), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_Red), + Pixel_ModRGB(37, Set, RGB_Red), + Pixel_ModRGB(55, Set, RGB_Red), + Pixel_ModRGB(71, Set, RGB_Red), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_HalfRed), + Pixel_ModRGB(19, Set, RGB_HalfRed), + Pixel_ModRGB(38, Set, RGB_HalfRed), + Pixel_ModRGB(56, Set, RGB_HalfRed), + Pixel_ModRGB(72, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame5[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Yellow), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_OrangeYellow), + Pixel_ModRGB(35, Set, RGB_OrangeYellow), + Pixel_ModRGB(53, Set, RGB_OrangeYellow), + Pixel_ModRGB(68, Set, RGB_OrangeYellow), + Pixel_ModRGB(85, Set, RGB_OrangeYellow), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_Orange), + Pixel_ModRGB(17, Set, RGB_Orange), + Pixel_ModRGB(36, Set, RGB_Orange), + Pixel_ModRGB(54, Set, RGB_Orange), + Pixel_ModRGB(70, Set, RGB_Orange), + Pixel_ModRGB(86, Set, RGB_Orange), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_RedOrange), + Pixel_ModRGB(37, Set, RGB_RedOrange), + Pixel_ModRGB(55, Set, RGB_RedOrange), + Pixel_ModRGB(71, Set, RGB_RedOrange), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_Red), + Pixel_ModRGB(19, Set, RGB_Red), + Pixel_ModRGB(38, Set, RGB_Red), + Pixel_ModRGB(56, Set, RGB_Red), + Pixel_ModRGB(72, Set, RGB_Red), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_HalfRed), + Pixel_ModRGB(20, Set, RGB_HalfRed), + Pixel_ModRGB(39, Set, RGB_HalfRed), + Pixel_ModRGB(57, Set, RGB_HalfRed), + Pixel_ModRGB(73, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame6[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_YellowGreen), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_Yellow), + Pixel_ModRGB(35, Set, RGB_Yellow), + Pixel_ModRGB(53, Set, RGB_Yellow), + Pixel_ModRGB(68, Set, RGB_Yellow), + Pixel_ModRGB(85, Set, RGB_Yellow), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_OrangeYellow), + Pixel_ModRGB(17, Set, RGB_OrangeYellow), + Pixel_ModRGB(36, Set, RGB_OrangeYellow), + Pixel_ModRGB(54, Set, RGB_OrangeYellow), + Pixel_ModRGB(70, Set, RGB_OrangeYellow), + Pixel_ModRGB(86, Set, RGB_OrangeYellow), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_Orange), + Pixel_ModRGB(37, Set, RGB_Orange), + Pixel_ModRGB(55, Set, RGB_Orange), + Pixel_ModRGB(71, Set, RGB_Orange), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_RedOrange), + Pixel_ModRGB(19, Set, RGB_RedOrange), + Pixel_ModRGB(38, Set, RGB_RedOrange), + Pixel_ModRGB(56, Set, RGB_RedOrange), + Pixel_ModRGB(72, Set, RGB_RedOrange), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_Red), + Pixel_ModRGB(20, Set, RGB_Red), + Pixel_ModRGB(39, Set, RGB_Red), + Pixel_ModRGB(57, Set, RGB_Red), + Pixel_ModRGB(73, Set, RGB_Red), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_HalfRed), + Pixel_ModRGB(21, Set, RGB_HalfRed), + Pixel_ModRGB(40, Set, RGB_HalfRed), + Pixel_ModRGB(58, Set, RGB_HalfRed), + Pixel_ModRGB(74, Set, RGB_HalfRed), + Pixel_ModRGB(87, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame7[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Green), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_YellowGreen), + Pixel_ModRGB(35, Set, RGB_YellowGreen), + Pixel_ModRGB(53, Set, RGB_YellowGreen), + Pixel_ModRGB(68, Set, RGB_YellowGreen), + Pixel_ModRGB(85, Set, RGB_YellowGreen), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_Yellow), + Pixel_ModRGB(17, Set, RGB_Yellow), + Pixel_ModRGB(36, Set, RGB_Yellow), + Pixel_ModRGB(54, Set, RGB_Yellow), + Pixel_ModRGB(70, Set, RGB_Yellow), + Pixel_ModRGB(86, Set, RGB_Yellow), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_OrangeYellow), + Pixel_ModRGB(37, Set, RGB_OrangeYellow), + Pixel_ModRGB(55, Set, RGB_OrangeYellow), + Pixel_ModRGB(71, Set, RGB_OrangeYellow), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_Orange), + Pixel_ModRGB(19, Set, RGB_Orange), + Pixel_ModRGB(38, Set, RGB_Orange), + Pixel_ModRGB(56, Set, RGB_Orange), + Pixel_ModRGB(72, Set, RGB_Orange), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_RedOrange), + Pixel_ModRGB(20, Set, RGB_RedOrange), + Pixel_ModRGB(39, Set, RGB_RedOrange), + Pixel_ModRGB(57, Set, RGB_RedOrange), + Pixel_ModRGB(73, Set, RGB_RedOrange), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_Red), + Pixel_ModRGB(21, Set, RGB_Red), + Pixel_ModRGB(40, Set, RGB_Red), + Pixel_ModRGB(58, Set, RGB_Red), + Pixel_ModRGB(74, Set, RGB_Red), + Pixel_ModRGB(87, Set, RGB_Red), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_HalfRed), + Pixel_ModRGB(22, Set, RGB_HalfRed), + Pixel_ModRGB(41, Set, RGB_HalfRed), + Pixel_ModRGB(59, Set, RGB_HalfRed), + Pixel_ModRGB(75, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame8[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_GreenBlue), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_Green), + Pixel_ModRGB(35, Set, RGB_Green), + Pixel_ModRGB(53, Set, RGB_Green), + Pixel_ModRGB(68, Set, RGB_Green), + Pixel_ModRGB(85, Set, RGB_Green), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_YellowGreen), + Pixel_ModRGB(17, Set, RGB_YellowGreen), + Pixel_ModRGB(36, Set, RGB_YellowGreen), + Pixel_ModRGB(54, Set, RGB_YellowGreen), + Pixel_ModRGB(70, Set, RGB_YellowGreen), + Pixel_ModRGB(86, Set, RGB_YellowGreen), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_Yellow), + Pixel_ModRGB(37, Set, RGB_Yellow), + Pixel_ModRGB(55, Set, RGB_Yellow), + Pixel_ModRGB(71, Set, RGB_Yellow), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_OrangeYellow), + Pixel_ModRGB(19, Set, RGB_OrangeYellow), + Pixel_ModRGB(38, Set, RGB_OrangeYellow), + Pixel_ModRGB(56, Set, RGB_OrangeYellow), + Pixel_ModRGB(72, Set, RGB_OrangeYellow), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_Orange), + Pixel_ModRGB(20, Set, RGB_Orange), + Pixel_ModRGB(39, Set, RGB_Orange), + Pixel_ModRGB(57, Set, RGB_Orange), + Pixel_ModRGB(73, Set, RGB_Orange), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_RedOrange), + Pixel_ModRGB(21, Set, RGB_RedOrange), + Pixel_ModRGB(40, Set, RGB_RedOrange), + Pixel_ModRGB(58, Set, RGB_RedOrange), + Pixel_ModRGB(74, Set, RGB_RedOrange), + Pixel_ModRGB(87, Set, RGB_RedOrange), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_Red), + Pixel_ModRGB(22, Set, RGB_Red), + Pixel_ModRGB(41, Set, RGB_Red), + Pixel_ModRGB(59, Set, RGB_Red), + Pixel_ModRGB(75, Set, RGB_Red), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_HalfRed), + Pixel_ModRGB(23, Set, RGB_HalfRed), + Pixel_ModRGB(42, Set, RGB_HalfRed), + Pixel_ModRGB(60, Set, RGB_HalfRed), + Pixel_ModRGB(76, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame9[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Blue), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_GreenBlue), + Pixel_ModRGB(35, Set, RGB_GreenBlue), + Pixel_ModRGB(53, Set, RGB_GreenBlue), + Pixel_ModRGB(68, Set, RGB_GreenBlue), + Pixel_ModRGB(85, Set, RGB_GreenBlue), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_Green), + Pixel_ModRGB(17, Set, RGB_Green), + Pixel_ModRGB(36, Set, RGB_Green), + Pixel_ModRGB(54, Set, RGB_Green), + Pixel_ModRGB(70, Set, RGB_Green), + Pixel_ModRGB(86, Set, RGB_Green), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_YellowGreen), + Pixel_ModRGB(37, Set, RGB_YellowGreen), + Pixel_ModRGB(55, Set, RGB_YellowGreen), + Pixel_ModRGB(71, Set, RGB_YellowGreen), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_Yellow), + Pixel_ModRGB(19, Set, RGB_Yellow), + Pixel_ModRGB(38, Set, RGB_Yellow), + Pixel_ModRGB(56, Set, RGB_Yellow), + Pixel_ModRGB(72, Set, RGB_Yellow), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_OrangeYellow), + Pixel_ModRGB(20, Set, RGB_OrangeYellow), + Pixel_ModRGB(39, Set, RGB_OrangeYellow), + Pixel_ModRGB(57, Set, RGB_OrangeYellow), + Pixel_ModRGB(73, Set, RGB_OrangeYellow), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_Orange), + Pixel_ModRGB(21, Set, RGB_Orange), + Pixel_ModRGB(40, Set, RGB_Orange), + Pixel_ModRGB(58, Set, RGB_Orange), + Pixel_ModRGB(74, Set, RGB_Orange), + Pixel_ModRGB(87, Set, RGB_Orange), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_RedOrange), + Pixel_ModRGB(22, Set, RGB_RedOrange), + Pixel_ModRGB(41, Set, RGB_RedOrange), + Pixel_ModRGB(59, Set, RGB_RedOrange), + Pixel_ModRGB(75, Set, RGB_RedOrange), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_Red), + Pixel_ModRGB(23, Set, RGB_Red), + Pixel_ModRGB(42, Set, RGB_Red), + Pixel_ModRGB(60, Set, RGB_Red), + Pixel_ModRGB(76, Set, RGB_Red), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_HalfRed), + Pixel_ModRGB(24, Set, RGB_HalfRed), + Pixel_ModRGB(43, Set, RGB_HalfRed), + Pixel_ModRGB(61, Set, RGB_HalfRed), + Pixel_ModRGB(77, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame10[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_BlueIndigo), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_Blue), + Pixel_ModRGB(35, Set, RGB_Blue), + Pixel_ModRGB(53, Set, RGB_Blue), + Pixel_ModRGB(68, Set, RGB_Blue), + Pixel_ModRGB(85, Set, RGB_Blue), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_GreenBlue), + Pixel_ModRGB(17, Set, RGB_GreenBlue), + Pixel_ModRGB(36, Set, RGB_GreenBlue), + Pixel_ModRGB(54, Set, RGB_GreenBlue), + Pixel_ModRGB(70, Set, RGB_GreenBlue), + Pixel_ModRGB(86, Set, RGB_GreenBlue), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_Green), + Pixel_ModRGB(37, Set, RGB_Green), + Pixel_ModRGB(55, Set, RGB_Green), + Pixel_ModRGB(71, Set, RGB_Green), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_YellowGreen), + Pixel_ModRGB(19, Set, RGB_YellowGreen), + Pixel_ModRGB(38, Set, RGB_YellowGreen), + Pixel_ModRGB(56, Set, RGB_YellowGreen), + Pixel_ModRGB(72, Set, RGB_YellowGreen), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_Yellow), + Pixel_ModRGB(20, Set, RGB_Yellow), + Pixel_ModRGB(39, Set, RGB_Yellow), + Pixel_ModRGB(57, Set, RGB_Yellow), + Pixel_ModRGB(73, Set, RGB_Yellow), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_OrangeYellow), + Pixel_ModRGB(21, Set, RGB_OrangeYellow), + Pixel_ModRGB(40, Set, RGB_OrangeYellow), + Pixel_ModRGB(58, Set, RGB_OrangeYellow), + Pixel_ModRGB(74, Set, RGB_OrangeYellow), + Pixel_ModRGB(87, Set, RGB_OrangeYellow), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_Orange), + Pixel_ModRGB(22, Set, RGB_Orange), + Pixel_ModRGB(41, Set, RGB_Orange), + Pixel_ModRGB(59, Set, RGB_Orange), + Pixel_ModRGB(75, Set, RGB_Orange), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_RedOrange), + Pixel_ModRGB(23, Set, RGB_RedOrange), + Pixel_ModRGB(42, Set, RGB_RedOrange), + Pixel_ModRGB(60, Set, RGB_RedOrange), + Pixel_ModRGB(76, Set, RGB_RedOrange), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_Red), + Pixel_ModRGB(24, Set, RGB_Red), + Pixel_ModRGB(43, Set, RGB_Red), + Pixel_ModRGB(61, Set, RGB_Red), + Pixel_ModRGB(77, Set, RGB_Red), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_HalfRed), + Pixel_ModRGB(25, Set, RGB_HalfRed), + Pixel_ModRGB(44, Set, RGB_HalfRed), + Pixel_ModRGB(62, Set, RGB_HalfRed), + Pixel_ModRGB(78, Set, RGB_HalfRed), + Pixel_ModRGB(88, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame11[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Indigo), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_BlueIndigo), + Pixel_ModRGB(35, Set, RGB_BlueIndigo), + Pixel_ModRGB(53, Set, RGB_BlueIndigo), + Pixel_ModRGB(68, Set, RGB_BlueIndigo), + Pixel_ModRGB(85, Set, RGB_BlueIndigo), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_Blue), + Pixel_ModRGB(17, Set, RGB_Blue), + Pixel_ModRGB(36, Set, RGB_Blue), + Pixel_ModRGB(54, Set, RGB_Blue), + Pixel_ModRGB(70, Set, RGB_Blue), + Pixel_ModRGB(86, Set, RGB_Blue), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_GreenBlue), + Pixel_ModRGB(37, Set, RGB_GreenBlue), + Pixel_ModRGB(55, Set, RGB_GreenBlue), + Pixel_ModRGB(71, Set, RGB_GreenBlue), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_Green), + Pixel_ModRGB(19, Set, RGB_Green), + Pixel_ModRGB(38, Set, RGB_Green), + Pixel_ModRGB(56, Set, RGB_Green), + Pixel_ModRGB(72, Set, RGB_Green), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_YellowGreen), + Pixel_ModRGB(20, Set, RGB_YellowGreen), + Pixel_ModRGB(39, Set, RGB_YellowGreen), + Pixel_ModRGB(57, Set, RGB_YellowGreen), + Pixel_ModRGB(73, Set, RGB_YellowGreen), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_Yellow), + Pixel_ModRGB(21, Set, RGB_Yellow), + Pixel_ModRGB(40, Set, RGB_Yellow), + Pixel_ModRGB(58, Set, RGB_Yellow), + Pixel_ModRGB(74, Set, RGB_Yellow), + Pixel_ModRGB(87, Set, RGB_Yellow), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_OrangeYellow), + Pixel_ModRGB(22, Set, RGB_OrangeYellow), + Pixel_ModRGB(41, Set, RGB_OrangeYellow), + Pixel_ModRGB(59, Set, RGB_OrangeYellow), + Pixel_ModRGB(75, Set, RGB_OrangeYellow), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_Orange), + Pixel_ModRGB(23, Set, RGB_Orange), + Pixel_ModRGB(42, Set, RGB_Orange), + Pixel_ModRGB(60, Set, RGB_Orange), + Pixel_ModRGB(76, Set, RGB_Orange), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_RedOrange), + Pixel_ModRGB(24, Set, RGB_RedOrange), + Pixel_ModRGB(43, Set, RGB_RedOrange), + Pixel_ModRGB(61, Set, RGB_RedOrange), + Pixel_ModRGB(77, Set, RGB_RedOrange), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_Red), + Pixel_ModRGB(25, Set, RGB_Red), + Pixel_ModRGB(44, Set, RGB_Red), + Pixel_ModRGB(62, Set, RGB_Red), + Pixel_ModRGB(78, Set, RGB_Red), + Pixel_ModRGB(88, Set, RGB_Red), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_HalfRed), + Pixel_ModRGB(26, Set, RGB_HalfRed), + Pixel_ModRGB(45, Set, RGB_HalfRed), + Pixel_ModRGB(63, Set, RGB_HalfRed), + Pixel_ModRGB(79, Set, RGB_HalfRed), + Pixel_ModRGB(89, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame12[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_IndigoViolet), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_Indigo), + Pixel_ModRGB(35, Set, RGB_Indigo), + Pixel_ModRGB(53, Set, RGB_Indigo), + Pixel_ModRGB(68, Set, RGB_Indigo), + Pixel_ModRGB(85, Set, RGB_Indigo), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_BlueIndigo), + Pixel_ModRGB(17, Set, RGB_BlueIndigo), + Pixel_ModRGB(36, Set, RGB_BlueIndigo), + Pixel_ModRGB(54, Set, RGB_BlueIndigo), + Pixel_ModRGB(70, Set, RGB_BlueIndigo), + Pixel_ModRGB(86, Set, RGB_BlueIndigo), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_Blue), + Pixel_ModRGB(37, Set, RGB_Blue), + Pixel_ModRGB(55, Set, RGB_Blue), + Pixel_ModRGB(71, Set, RGB_Blue), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_GreenBlue), + Pixel_ModRGB(19, Set, RGB_GreenBlue), + Pixel_ModRGB(38, Set, RGB_GreenBlue), + Pixel_ModRGB(56, Set, RGB_GreenBlue), + Pixel_ModRGB(72, Set, RGB_GreenBlue), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_Green), + Pixel_ModRGB(20, Set, RGB_Green), + Pixel_ModRGB(39, Set, RGB_Green), + Pixel_ModRGB(57, Set, RGB_Green), + Pixel_ModRGB(73, Set, RGB_Green), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_YellowGreen), + Pixel_ModRGB(21, Set, RGB_YellowGreen), + Pixel_ModRGB(40, Set, RGB_YellowGreen), + Pixel_ModRGB(58, Set, RGB_YellowGreen), + Pixel_ModRGB(74, Set, RGB_YellowGreen), + Pixel_ModRGB(87, Set, RGB_YellowGreen), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_Yellow), + Pixel_ModRGB(22, Set, RGB_Yellow), + Pixel_ModRGB(41, Set, RGB_Yellow), + Pixel_ModRGB(59, Set, RGB_Yellow), + Pixel_ModRGB(75, Set, RGB_Yellow), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_OrangeYellow), + Pixel_ModRGB(23, Set, RGB_OrangeYellow), + Pixel_ModRGB(42, Set, RGB_OrangeYellow), + Pixel_ModRGB(60, Set, RGB_OrangeYellow), + Pixel_ModRGB(76, Set, RGB_OrangeYellow), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_Orange), + Pixel_ModRGB(24, Set, RGB_Orange), + Pixel_ModRGB(43, Set, RGB_Orange), + Pixel_ModRGB(61, Set, RGB_Orange), + Pixel_ModRGB(77, Set, RGB_Orange), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_RedOrange), + Pixel_ModRGB(25, Set, RGB_RedOrange), + Pixel_ModRGB(44, Set, RGB_RedOrange), + Pixel_ModRGB(62, Set, RGB_RedOrange), + Pixel_ModRGB(78, Set, RGB_RedOrange), + Pixel_ModRGB(88, Set, RGB_RedOrange), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_Red), + Pixel_ModRGB(26, Set, RGB_Red), + Pixel_ModRGB(45, Set, RGB_Red), + Pixel_ModRGB(63, Set, RGB_Red), + Pixel_ModRGB(79, Set, RGB_Red), + Pixel_ModRGB(89, Set, RGB_Red), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_HalfRed), + Pixel_ModRGB(27, Set, RGB_HalfRed), + Pixel_ModRGB(46, Set, RGB_HalfRed), + Pixel_ModRGB(64, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame13[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Violet), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_IndigoViolet), + Pixel_ModRGB(35, Set, RGB_IndigoViolet), + Pixel_ModRGB(53, Set, RGB_IndigoViolet), + Pixel_ModRGB(68, Set, RGB_IndigoViolet), + Pixel_ModRGB(85, Set, RGB_IndigoViolet), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_Indigo), + Pixel_ModRGB(17, Set, RGB_Indigo), + Pixel_ModRGB(36, Set, RGB_Indigo), + Pixel_ModRGB(54, Set, RGB_Indigo), + Pixel_ModRGB(70, Set, RGB_Indigo), + Pixel_ModRGB(86, Set, RGB_Indigo), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_BlueIndigo), + Pixel_ModRGB(37, Set, RGB_BlueIndigo), + Pixel_ModRGB(55, Set, RGB_BlueIndigo), + Pixel_ModRGB(71, Set, RGB_BlueIndigo), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_Blue), + Pixel_ModRGB(19, Set, RGB_Blue), + Pixel_ModRGB(38, Set, RGB_Blue), + Pixel_ModRGB(56, Set, RGB_Blue), + Pixel_ModRGB(72, Set, RGB_Blue), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_GreenBlue), + Pixel_ModRGB(20, Set, RGB_GreenBlue), + Pixel_ModRGB(39, Set, RGB_GreenBlue), + Pixel_ModRGB(57, Set, RGB_GreenBlue), + Pixel_ModRGB(73, Set, RGB_GreenBlue), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_Green), + Pixel_ModRGB(21, Set, RGB_Green), + Pixel_ModRGB(40, Set, RGB_Green), + Pixel_ModRGB(58, Set, RGB_Green), + Pixel_ModRGB(74, Set, RGB_Green), + Pixel_ModRGB(87, Set, RGB_Green), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_YellowGreen), + Pixel_ModRGB(22, Set, RGB_YellowGreen), + Pixel_ModRGB(41, Set, RGB_YellowGreen), + Pixel_ModRGB(59, Set, RGB_YellowGreen), + Pixel_ModRGB(75, Set, RGB_YellowGreen), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_Yellow), + Pixel_ModRGB(23, Set, RGB_Yellow), + Pixel_ModRGB(42, Set, RGB_Yellow), + Pixel_ModRGB(60, Set, RGB_Yellow), + Pixel_ModRGB(76, Set, RGB_Yellow), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_OrangeYellow), + Pixel_ModRGB(24, Set, RGB_OrangeYellow), + Pixel_ModRGB(43, Set, RGB_OrangeYellow), + Pixel_ModRGB(61, Set, RGB_OrangeYellow), + Pixel_ModRGB(77, Set, RGB_OrangeYellow), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_Orange), + Pixel_ModRGB(25, Set, RGB_Orange), + Pixel_ModRGB(44, Set, RGB_Orange), + Pixel_ModRGB(62, Set, RGB_Orange), + Pixel_ModRGB(78, Set, RGB_Orange), + Pixel_ModRGB(88, Set, RGB_Orange), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_RedOrange), + Pixel_ModRGB(26, Set, RGB_RedOrange), + Pixel_ModRGB(45, Set, RGB_RedOrange), + Pixel_ModRGB(63, Set, RGB_RedOrange), + Pixel_ModRGB(79, Set, RGB_RedOrange), + Pixel_ModRGB(89, Set, RGB_RedOrange), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_Red), + Pixel_ModRGB(27, Set, RGB_Red), + Pixel_ModRGB(46, Set, RGB_Red), + Pixel_ModRGB(64, Set, RGB_Red), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_HalfRed), + Pixel_ModRGB(28, Set, RGB_HalfRed), + Pixel_ModRGB(47, Set, RGB_HalfRed), + Pixel_ModRGB(90, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame14[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_HalfViolet), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_Violet), + Pixel_ModRGB(35, Set, RGB_Violet), + Pixel_ModRGB(53, Set, RGB_Violet), + Pixel_ModRGB(68, Set, RGB_Violet), + Pixel_ModRGB(85, Set, RGB_Violet), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_IndigoViolet), + Pixel_ModRGB(17, Set, RGB_IndigoViolet), + Pixel_ModRGB(36, Set, RGB_IndigoViolet), + Pixel_ModRGB(54, Set, RGB_IndigoViolet), + Pixel_ModRGB(70, Set, RGB_IndigoViolet), + Pixel_ModRGB(86, Set, RGB_IndigoViolet), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_Indigo), + Pixel_ModRGB(37, Set, RGB_Indigo), + Pixel_ModRGB(55, Set, RGB_Indigo), + Pixel_ModRGB(71, Set, RGB_Indigo), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_BlueIndigo), + Pixel_ModRGB(19, Set, RGB_BlueIndigo), + Pixel_ModRGB(38, Set, RGB_BlueIndigo), + Pixel_ModRGB(56, Set, RGB_BlueIndigo), + Pixel_ModRGB(72, Set, RGB_BlueIndigo), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_Blue), + Pixel_ModRGB(20, Set, RGB_Blue), + Pixel_ModRGB(39, Set, RGB_Blue), + Pixel_ModRGB(57, Set, RGB_Blue), + Pixel_ModRGB(73, Set, RGB_Blue), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_GreenBlue), + Pixel_ModRGB(21, Set, RGB_GreenBlue), + Pixel_ModRGB(40, Set, RGB_GreenBlue), + Pixel_ModRGB(58, Set, RGB_GreenBlue), + Pixel_ModRGB(74, Set, RGB_GreenBlue), + Pixel_ModRGB(87, Set, RGB_GreenBlue), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_Green), + Pixel_ModRGB(22, Set, RGB_Green), + Pixel_ModRGB(41, Set, RGB_Green), + Pixel_ModRGB(59, Set, RGB_Green), + Pixel_ModRGB(75, Set, RGB_Green), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_YellowGreen), + Pixel_ModRGB(23, Set, RGB_YellowGreen), + Pixel_ModRGB(42, Set, RGB_YellowGreen), + Pixel_ModRGB(60, Set, RGB_YellowGreen), + Pixel_ModRGB(76, Set, RGB_YellowGreen), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_Yellow), + Pixel_ModRGB(24, Set, RGB_Yellow), + Pixel_ModRGB(43, Set, RGB_Yellow), + Pixel_ModRGB(61, Set, RGB_Yellow), + Pixel_ModRGB(77, Set, RGB_Yellow), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_OrangeYellow), + Pixel_ModRGB(25, Set, RGB_OrangeYellow), + Pixel_ModRGB(44, Set, RGB_OrangeYellow), + Pixel_ModRGB(62, Set, RGB_OrangeYellow), + Pixel_ModRGB(78, Set, RGB_OrangeYellow), + Pixel_ModRGB(88, Set, RGB_OrangeYellow), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_Orange), + Pixel_ModRGB(26, Set, RGB_Orange), + Pixel_ModRGB(45, Set, RGB_Orange), + Pixel_ModRGB(63, Set, RGB_Orange), + Pixel_ModRGB(79, Set, RGB_Orange), + Pixel_ModRGB(89, Set, RGB_Orange), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_RedOrange), + Pixel_ModRGB(27, Set, RGB_RedOrange), + Pixel_ModRGB(46, Set, RGB_RedOrange), + Pixel_ModRGB(64, Set, RGB_RedOrange), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_Red), + Pixel_ModRGB(28, Set, RGB_Red), + Pixel_ModRGB(47, Set, RGB_Red), + Pixel_ModRGB(90, Set, RGB_Red), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_HalfRed), + Pixel_ModRGB(30, Set, RGB_HalfRed), + Pixel_ModRGB(66, Set, RGB_HalfRed), + Pixel_ModRGB(81, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame15[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Black), + + // Set 2 + Pixel_ModRGB(16, Set, RGB_HalfViolet), + Pixel_ModRGB(35, Set, RGB_HalfViolet), + Pixel_ModRGB(53, Set, RGB_HalfViolet), + Pixel_ModRGB(68, Set, RGB_HalfViolet), + Pixel_ModRGB(85, Set, RGB_HalfViolet), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_Violet), + Pixel_ModRGB(17, Set, RGB_Violet), + Pixel_ModRGB(36, Set, RGB_Violet), + Pixel_ModRGB(54, Set, RGB_Violet), + Pixel_ModRGB(70, Set, RGB_Violet), + Pixel_ModRGB(86, Set, RGB_Violet), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_IndigoViolet), + Pixel_ModRGB(37, Set, RGB_IndigoViolet), + Pixel_ModRGB(55, Set, RGB_IndigoViolet), + Pixel_ModRGB(71, Set, RGB_IndigoViolet), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_Indigo), + Pixel_ModRGB(19, Set, RGB_Indigo), + Pixel_ModRGB(38, Set, RGB_Indigo), + Pixel_ModRGB(56, Set, RGB_Indigo), + Pixel_ModRGB(72, Set, RGB_Indigo), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_BlueIndigo), + Pixel_ModRGB(20, Set, RGB_BlueIndigo), + Pixel_ModRGB(39, Set, RGB_BlueIndigo), + Pixel_ModRGB(57, Set, RGB_BlueIndigo), + Pixel_ModRGB(73, Set, RGB_BlueIndigo), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_Blue), + Pixel_ModRGB(21, Set, RGB_Blue), + Pixel_ModRGB(40, Set, RGB_Blue), + Pixel_ModRGB(58, Set, RGB_Blue), + Pixel_ModRGB(74, Set, RGB_Blue), + Pixel_ModRGB(87, Set, RGB_Blue), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_GreenBlue), + Pixel_ModRGB(22, Set, RGB_GreenBlue), + Pixel_ModRGB(41, Set, RGB_GreenBlue), + Pixel_ModRGB(59, Set, RGB_GreenBlue), + Pixel_ModRGB(75, Set, RGB_GreenBlue), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_Green), + Pixel_ModRGB(23, Set, RGB_Green), + Pixel_ModRGB(42, Set, RGB_Green), + Pixel_ModRGB(60, Set, RGB_Green), + Pixel_ModRGB(76, Set, RGB_Green), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_YellowGreen), + Pixel_ModRGB(24, Set, RGB_YellowGreen), + Pixel_ModRGB(43, Set, RGB_YellowGreen), + Pixel_ModRGB(61, Set, RGB_YellowGreen), + Pixel_ModRGB(77, Set, RGB_YellowGreen), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_Yellow), + Pixel_ModRGB(25, Set, RGB_Yellow), + Pixel_ModRGB(44, Set, RGB_Yellow), + Pixel_ModRGB(62, Set, RGB_Yellow), + Pixel_ModRGB(78, Set, RGB_Yellow), + Pixel_ModRGB(88, Set, RGB_Yellow), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_OrangeYellow), + Pixel_ModRGB(26, Set, RGB_OrangeYellow), + Pixel_ModRGB(45, Set, RGB_OrangeYellow), + Pixel_ModRGB(63, Set, RGB_OrangeYellow), + Pixel_ModRGB(79, Set, RGB_OrangeYellow), + Pixel_ModRGB(89, Set, RGB_OrangeYellow), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_Orange), + Pixel_ModRGB(27, Set, RGB_Orange), + Pixel_ModRGB(46, Set, RGB_Orange), + Pixel_ModRGB(64, Set, RGB_Orange), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_RedOrange), + Pixel_ModRGB(28, Set, RGB_RedOrange), + Pixel_ModRGB(47, Set, RGB_RedOrange), + Pixel_ModRGB(90, Set, RGB_RedOrange), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_Red), + Pixel_ModRGB(30, Set, RGB_Red), + Pixel_ModRGB(66, Set, RGB_Red), + Pixel_ModRGB(81, Set, RGB_Red), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_HalfRed), + Pixel_ModRGB(48, Set, RGB_HalfRed), + Pixel_ModRGB(91, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame16[] = { + // Set 2 + Pixel_ModRGB(16, Set, RGB_Black), + Pixel_ModRGB(35, Set, RGB_Black), + Pixel_ModRGB(53, Set, RGB_Black), + Pixel_ModRGB(68, Set, RGB_Black), + Pixel_ModRGB(85, Set, RGB_Black), + + // Set 3 + Pixel_ModRGB(0, Set, RGB_HalfViolet), + Pixel_ModRGB(17, Set, RGB_HalfViolet), + Pixel_ModRGB(36, Set, RGB_HalfViolet), + Pixel_ModRGB(54, Set, RGB_HalfViolet), + Pixel_ModRGB(70, Set, RGB_HalfViolet), + Pixel_ModRGB(86, Set, RGB_HalfViolet), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_Violet), + Pixel_ModRGB(37, Set, RGB_Violet), + Pixel_ModRGB(55, Set, RGB_Violet), + Pixel_ModRGB(71, Set, RGB_Violet), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_IndigoViolet), + Pixel_ModRGB(19, Set, RGB_IndigoViolet), + Pixel_ModRGB(38, Set, RGB_IndigoViolet), + Pixel_ModRGB(56, Set, RGB_IndigoViolet), + Pixel_ModRGB(72, Set, RGB_IndigoViolet), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_Indigo), + Pixel_ModRGB(20, Set, RGB_Indigo), + Pixel_ModRGB(39, Set, RGB_Indigo), + Pixel_ModRGB(57, Set, RGB_Indigo), + Pixel_ModRGB(73, Set, RGB_Indigo), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_BlueIndigo), + Pixel_ModRGB(21, Set, RGB_BlueIndigo), + Pixel_ModRGB(40, Set, RGB_BlueIndigo), + Pixel_ModRGB(58, Set, RGB_BlueIndigo), + Pixel_ModRGB(74, Set, RGB_BlueIndigo), + Pixel_ModRGB(87, Set, RGB_BlueIndigo), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_Blue), + Pixel_ModRGB(22, Set, RGB_Blue), + Pixel_ModRGB(41, Set, RGB_Blue), + Pixel_ModRGB(59, Set, RGB_Blue), + Pixel_ModRGB(75, Set, RGB_Blue), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_GreenBlue), + Pixel_ModRGB(23, Set, RGB_GreenBlue), + Pixel_ModRGB(42, Set, RGB_GreenBlue), + Pixel_ModRGB(60, Set, RGB_GreenBlue), + Pixel_ModRGB(76, Set, RGB_GreenBlue), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_Green), + Pixel_ModRGB(24, Set, RGB_Green), + Pixel_ModRGB(43, Set, RGB_Green), + Pixel_ModRGB(61, Set, RGB_Green), + Pixel_ModRGB(77, Set, RGB_Green), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_YellowGreen), + Pixel_ModRGB(25, Set, RGB_YellowGreen), + Pixel_ModRGB(44, Set, RGB_YellowGreen), + Pixel_ModRGB(62, Set, RGB_YellowGreen), + Pixel_ModRGB(78, Set, RGB_YellowGreen), + Pixel_ModRGB(88, Set, RGB_YellowGreen), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_Yellow), + Pixel_ModRGB(26, Set, RGB_Yellow), + Pixel_ModRGB(45, Set, RGB_Yellow), + Pixel_ModRGB(63, Set, RGB_Yellow), + Pixel_ModRGB(79, Set, RGB_Yellow), + Pixel_ModRGB(89, Set, RGB_Yellow), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_OrangeYellow), + Pixel_ModRGB(27, Set, RGB_OrangeYellow), + Pixel_ModRGB(46, Set, RGB_OrangeYellow), + Pixel_ModRGB(64, Set, RGB_OrangeYellow), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_Orange), + Pixel_ModRGB(28, Set, RGB_Orange), + Pixel_ModRGB(47, Set, RGB_Orange), + Pixel_ModRGB(90, Set, RGB_Orange), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_RedOrange), + Pixel_ModRGB(30, Set, RGB_RedOrange), + Pixel_ModRGB(66, Set, RGB_RedOrange), + Pixel_ModRGB(81, Set, RGB_RedOrange), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_Red), + Pixel_ModRGB(48, Set, RGB_Red), + Pixel_ModRGB(91, Set, RGB_Red), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_HalfRed), + Pixel_ModRGB(32, Set, RGB_HalfRed), + Pixel_ModRGB(50, Set, RGB_HalfRed), + Pixel_ModRGB(92, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame17[] = { + // Set 3 + Pixel_ModRGB(0, Set, RGB_Black), + Pixel_ModRGB(17, Set, RGB_Black), + Pixel_ModRGB(36, Set, RGB_Black), + Pixel_ModRGB(54, Set, RGB_Black), + Pixel_ModRGB(70, Set, RGB_Black), + Pixel_ModRGB(86, Set, RGB_Black), + + // Set 4 + Pixel_ModRGB(18, Set, RGB_HalfViolet), + Pixel_ModRGB(37, Set, RGB_HalfViolet), + Pixel_ModRGB(55, Set, RGB_HalfViolet), + Pixel_ModRGB(71, Set, RGB_HalfViolet), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_Violet), + Pixel_ModRGB(19, Set, RGB_Violet), + Pixel_ModRGB(38, Set, RGB_Violet), + Pixel_ModRGB(56, Set, RGB_Violet), + Pixel_ModRGB(72, Set, RGB_Violet), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_IndigoViolet), + Pixel_ModRGB(20, Set, RGB_IndigoViolet), + Pixel_ModRGB(39, Set, RGB_IndigoViolet), + Pixel_ModRGB(57, Set, RGB_IndigoViolet), + Pixel_ModRGB(73, Set, RGB_IndigoViolet), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_Indigo), + Pixel_ModRGB(21, Set, RGB_Indigo), + Pixel_ModRGB(40, Set, RGB_Indigo), + Pixel_ModRGB(58, Set, RGB_Indigo), + Pixel_ModRGB(74, Set, RGB_Indigo), + Pixel_ModRGB(87, Set, RGB_Indigo), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_BlueIndigo), + Pixel_ModRGB(22, Set, RGB_BlueIndigo), + Pixel_ModRGB(41, Set, RGB_BlueIndigo), + Pixel_ModRGB(59, Set, RGB_BlueIndigo), + Pixel_ModRGB(75, Set, RGB_BlueIndigo), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_Blue), + Pixel_ModRGB(23, Set, RGB_Blue), + Pixel_ModRGB(42, Set, RGB_Blue), + Pixel_ModRGB(60, Set, RGB_Blue), + Pixel_ModRGB(76, Set, RGB_Blue), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_GreenBlue), + Pixel_ModRGB(24, Set, RGB_GreenBlue), + Pixel_ModRGB(43, Set, RGB_GreenBlue), + Pixel_ModRGB(61, Set, RGB_GreenBlue), + Pixel_ModRGB(77, Set, RGB_GreenBlue), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_Green), + Pixel_ModRGB(25, Set, RGB_Green), + Pixel_ModRGB(44, Set, RGB_Green), + Pixel_ModRGB(62, Set, RGB_Green), + Pixel_ModRGB(78, Set, RGB_Green), + Pixel_ModRGB(88, Set, RGB_Green), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_YellowGreen), + Pixel_ModRGB(26, Set, RGB_YellowGreen), + Pixel_ModRGB(45, Set, RGB_YellowGreen), + Pixel_ModRGB(63, Set, RGB_YellowGreen), + Pixel_ModRGB(79, Set, RGB_YellowGreen), + Pixel_ModRGB(89, Set, RGB_YellowGreen), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_Yellow), + Pixel_ModRGB(27, Set, RGB_Yellow), + Pixel_ModRGB(46, Set, RGB_Yellow), + Pixel_ModRGB(64, Set, RGB_Yellow), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_OrangeYellow), + Pixel_ModRGB(28, Set, RGB_OrangeYellow), + Pixel_ModRGB(47, Set, RGB_OrangeYellow), + Pixel_ModRGB(90, Set, RGB_OrangeYellow), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_Orange), + Pixel_ModRGB(30, Set, RGB_Orange), + Pixel_ModRGB(66, Set, RGB_Orange), + Pixel_ModRGB(81, Set, RGB_Orange), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_RedOrange), + Pixel_ModRGB(48, Set, RGB_RedOrange), + Pixel_ModRGB(91, Set, RGB_RedOrange), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_Red), + Pixel_ModRGB(32, Set, RGB_Red), + Pixel_ModRGB(50, Set, RGB_Red), + Pixel_ModRGB(92, Set, RGB_Red), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_HalfRed), + Pixel_ModRGB(33, Set, RGB_HalfRed), + Pixel_ModRGB(51, Set, RGB_HalfRed), + Pixel_ModRGB(83, Set, RGB_HalfRed), + Pixel_ModRGB(93, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame18[] = { + // Set 4 + Pixel_ModRGB(18, Set, RGB_Black), + Pixel_ModRGB(37, Set, RGB_Black), + Pixel_ModRGB(55, Set, RGB_Black), + Pixel_ModRGB(71, Set, RGB_Black), + + // Set 5 + Pixel_ModRGB(1, Set, RGB_HalfViolet), + Pixel_ModRGB(19, Set, RGB_HalfViolet), + Pixel_ModRGB(38, Set, RGB_HalfViolet), + Pixel_ModRGB(56, Set, RGB_HalfViolet), + Pixel_ModRGB(72, Set, RGB_HalfViolet), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_Violet), + Pixel_ModRGB(20, Set, RGB_Violet), + Pixel_ModRGB(39, Set, RGB_Violet), + Pixel_ModRGB(57, Set, RGB_Violet), + Pixel_ModRGB(73, Set, RGB_Violet), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_IndigoViolet), + Pixel_ModRGB(21, Set, RGB_IndigoViolet), + Pixel_ModRGB(40, Set, RGB_IndigoViolet), + Pixel_ModRGB(58, Set, RGB_IndigoViolet), + Pixel_ModRGB(74, Set, RGB_IndigoViolet), + Pixel_ModRGB(87, Set, RGB_IndigoViolet), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_Indigo), + Pixel_ModRGB(22, Set, RGB_Indigo), + Pixel_ModRGB(41, Set, RGB_Indigo), + Pixel_ModRGB(59, Set, RGB_Indigo), + Pixel_ModRGB(75, Set, RGB_Indigo), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_BlueIndigo), + Pixel_ModRGB(23, Set, RGB_BlueIndigo), + Pixel_ModRGB(42, Set, RGB_BlueIndigo), + Pixel_ModRGB(60, Set, RGB_BlueIndigo), + Pixel_ModRGB(76, Set, RGB_BlueIndigo), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_Blue), + Pixel_ModRGB(24, Set, RGB_Blue), + Pixel_ModRGB(43, Set, RGB_Blue), + Pixel_ModRGB(61, Set, RGB_Blue), + Pixel_ModRGB(77, Set, RGB_Blue), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_GreenBlue), + Pixel_ModRGB(25, Set, RGB_GreenBlue), + Pixel_ModRGB(44, Set, RGB_GreenBlue), + Pixel_ModRGB(62, Set, RGB_GreenBlue), + Pixel_ModRGB(78, Set, RGB_GreenBlue), + Pixel_ModRGB(88, Set, RGB_GreenBlue), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_Green), + Pixel_ModRGB(26, Set, RGB_Green), + Pixel_ModRGB(45, Set, RGB_Green), + Pixel_ModRGB(63, Set, RGB_Green), + Pixel_ModRGB(79, Set, RGB_Green), + Pixel_ModRGB(89, Set, RGB_Green), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_YellowGreen), + Pixel_ModRGB(27, Set, RGB_YellowGreen), + Pixel_ModRGB(46, Set, RGB_YellowGreen), + Pixel_ModRGB(64, Set, RGB_YellowGreen), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_Yellow), + Pixel_ModRGB(28, Set, RGB_Yellow), + Pixel_ModRGB(47, Set, RGB_Yellow), + Pixel_ModRGB(90, Set, RGB_Yellow), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_OrangeYellow), + Pixel_ModRGB(30, Set, RGB_OrangeYellow), + Pixel_ModRGB(66, Set, RGB_OrangeYellow), + Pixel_ModRGB(81, Set, RGB_OrangeYellow), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_Orange), + Pixel_ModRGB(48, Set, RGB_Orange), + Pixel_ModRGB(91, Set, RGB_Orange), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_RedOrange), + Pixel_ModRGB(32, Set, RGB_RedOrange), + Pixel_ModRGB(50, Set, RGB_RedOrange), + Pixel_ModRGB(92, Set, RGB_RedOrange), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_Red), + Pixel_ModRGB(33, Set, RGB_Red), + Pixel_ModRGB(51, Set, RGB_Red), + Pixel_ModRGB(83, Set, RGB_Red), + Pixel_ModRGB(93, Set, RGB_Red), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_HalfRed), + Pixel_ModRGB(34, Set, RGB_HalfRed), + Pixel_ModRGB(52, Set, RGB_HalfRed), + Pixel_ModRGB(94, Set, RGB_HalfRed), +}; + +const uint8_t rainbow_frame19[] = { + // Set 5 + Pixel_ModRGB(1, Set, RGB_Black), + Pixel_ModRGB(19, Set, RGB_Black), + Pixel_ModRGB(38, Set, RGB_Black), + Pixel_ModRGB(56, Set, RGB_Black), + Pixel_ModRGB(72, Set, RGB_Black), + + // Set 6 + Pixel_ModRGB(2, Set, RGB_HalfViolet), + Pixel_ModRGB(20, Set, RGB_HalfViolet), + Pixel_ModRGB(39, Set, RGB_HalfViolet), + Pixel_ModRGB(57, Set, RGB_HalfViolet), + Pixel_ModRGB(73, Set, RGB_HalfViolet), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_Violet), + Pixel_ModRGB(21, Set, RGB_Violet), + Pixel_ModRGB(40, Set, RGB_Violet), + Pixel_ModRGB(58, Set, RGB_Violet), + Pixel_ModRGB(74, Set, RGB_Violet), + Pixel_ModRGB(87, Set, RGB_Violet), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_IndigoViolet), + Pixel_ModRGB(22, Set, RGB_IndigoViolet), + Pixel_ModRGB(41, Set, RGB_IndigoViolet), + Pixel_ModRGB(59, Set, RGB_IndigoViolet), + Pixel_ModRGB(75, Set, RGB_IndigoViolet), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_Indigo), + Pixel_ModRGB(23, Set, RGB_Indigo), + Pixel_ModRGB(42, Set, RGB_Indigo), + Pixel_ModRGB(60, Set, RGB_Indigo), + Pixel_ModRGB(76, Set, RGB_Indigo), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_BlueIndigo), + Pixel_ModRGB(24, Set, RGB_BlueIndigo), + Pixel_ModRGB(43, Set, RGB_BlueIndigo), + Pixel_ModRGB(61, Set, RGB_BlueIndigo), + Pixel_ModRGB(77, Set, RGB_BlueIndigo), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_Blue), + Pixel_ModRGB(25, Set, RGB_Blue), + Pixel_ModRGB(44, Set, RGB_Blue), + Pixel_ModRGB(62, Set, RGB_Blue), + Pixel_ModRGB(78, Set, RGB_Blue), + Pixel_ModRGB(88, Set, RGB_Blue), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_GreenBlue), + Pixel_ModRGB(26, Set, RGB_GreenBlue), + Pixel_ModRGB(45, Set, RGB_GreenBlue), + Pixel_ModRGB(63, Set, RGB_GreenBlue), + Pixel_ModRGB(79, Set, RGB_GreenBlue), + Pixel_ModRGB(89, Set, RGB_GreenBlue), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_Green), + Pixel_ModRGB(27, Set, RGB_Green), + Pixel_ModRGB(46, Set, RGB_Green), + Pixel_ModRGB(64, Set, RGB_Green), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_YellowGreen), + Pixel_ModRGB(28, Set, RGB_YellowGreen), + Pixel_ModRGB(47, Set, RGB_YellowGreen), + Pixel_ModRGB(90, Set, RGB_YellowGreen), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_Yellow), + Pixel_ModRGB(30, Set, RGB_Yellow), + Pixel_ModRGB(66, Set, RGB_Yellow), + Pixel_ModRGB(81, Set, RGB_Yellow), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_OrangeYellow), + Pixel_ModRGB(48, Set, RGB_OrangeYellow), + Pixel_ModRGB(91, Set, RGB_OrangeYellow), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_Orange), + Pixel_ModRGB(32, Set, RGB_Orange), + Pixel_ModRGB(50, Set, RGB_Orange), + Pixel_ModRGB(92, Set, RGB_Orange), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_RedOrange), + Pixel_ModRGB(33, Set, RGB_RedOrange), + Pixel_ModRGB(51, Set, RGB_RedOrange), + Pixel_ModRGB(83, Set, RGB_RedOrange), + Pixel_ModRGB(93, Set, RGB_RedOrange), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_Red), + Pixel_ModRGB(34, Set, RGB_Red), + Pixel_ModRGB(52, Set, RGB_Red), + Pixel_ModRGB(94, Set, RGB_Red), +}; + +const uint8_t rainbow_frame20[] = { + // Set 6 + Pixel_ModRGB(2, Set, RGB_Black), + Pixel_ModRGB(20, Set, RGB_Black), + Pixel_ModRGB(39, Set, RGB_Black), + Pixel_ModRGB(57, Set, RGB_Black), + Pixel_ModRGB(73, Set, RGB_Black), + + // Set 7 + Pixel_ModRGB(3, Set, RGB_HalfViolet), + Pixel_ModRGB(21, Set, RGB_HalfViolet), + Pixel_ModRGB(40, Set, RGB_HalfViolet), + Pixel_ModRGB(58, Set, RGB_HalfViolet), + Pixel_ModRGB(74, Set, RGB_HalfViolet), + Pixel_ModRGB(87, Set, RGB_HalfViolet), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_Violet), + Pixel_ModRGB(22, Set, RGB_Violet), + Pixel_ModRGB(41, Set, RGB_Violet), + Pixel_ModRGB(59, Set, RGB_Violet), + Pixel_ModRGB(75, Set, RGB_Violet), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_IndigoViolet), + Pixel_ModRGB(23, Set, RGB_IndigoViolet), + Pixel_ModRGB(42, Set, RGB_IndigoViolet), + Pixel_ModRGB(60, Set, RGB_IndigoViolet), + Pixel_ModRGB(76, Set, RGB_IndigoViolet), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_Indigo), + Pixel_ModRGB(24, Set, RGB_Indigo), + Pixel_ModRGB(43, Set, RGB_Indigo), + Pixel_ModRGB(61, Set, RGB_Indigo), + Pixel_ModRGB(77, Set, RGB_Indigo), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_BlueIndigo), + Pixel_ModRGB(25, Set, RGB_BlueIndigo), + Pixel_ModRGB(44, Set, RGB_BlueIndigo), + Pixel_ModRGB(62, Set, RGB_BlueIndigo), + Pixel_ModRGB(78, Set, RGB_BlueIndigo), + Pixel_ModRGB(88, Set, RGB_BlueIndigo), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_Blue), + Pixel_ModRGB(26, Set, RGB_Blue), + Pixel_ModRGB(45, Set, RGB_Blue), + Pixel_ModRGB(63, Set, RGB_Blue), + Pixel_ModRGB(79, Set, RGB_Blue), + Pixel_ModRGB(89, Set, RGB_Blue), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_GreenBlue), + Pixel_ModRGB(27, Set, RGB_GreenBlue), + Pixel_ModRGB(46, Set, RGB_GreenBlue), + Pixel_ModRGB(64, Set, RGB_GreenBlue), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_Green), + Pixel_ModRGB(28, Set, RGB_Green), + Pixel_ModRGB(47, Set, RGB_Green), + Pixel_ModRGB(90, Set, RGB_Green), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_YellowGreen), + Pixel_ModRGB(30, Set, RGB_YellowGreen), + Pixel_ModRGB(66, Set, RGB_YellowGreen), + Pixel_ModRGB(81, Set, RGB_YellowGreen), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_Yellow), + Pixel_ModRGB(48, Set, RGB_Yellow), + Pixel_ModRGB(91, Set, RGB_Yellow), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_OrangeYellow), + Pixel_ModRGB(32, Set, RGB_OrangeYellow), + Pixel_ModRGB(50, Set, RGB_OrangeYellow), + Pixel_ModRGB(92, Set, RGB_OrangeYellow), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_Orange), + Pixel_ModRGB(33, Set, RGB_Orange), + Pixel_ModRGB(51, Set, RGB_Orange), + Pixel_ModRGB(83, Set, RGB_Orange), + Pixel_ModRGB(93, Set, RGB_Orange), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_RedOrange), + Pixel_ModRGB(34, Set, RGB_RedOrange), + Pixel_ModRGB(52, Set, RGB_RedOrange), + Pixel_ModRGB(94, Set, RGB_RedOrange), +}; + +const uint8_t rainbow_frame21[] = { + // Set 7 + Pixel_ModRGB(3, Set, RGB_Black), + Pixel_ModRGB(21, Set, RGB_Black), + Pixel_ModRGB(40, Set, RGB_Black), + Pixel_ModRGB(58, Set, RGB_Black), + Pixel_ModRGB(74, Set, RGB_Black), + Pixel_ModRGB(87, Set, RGB_Black), + + // Set 8 + Pixel_ModRGB(4, Set, RGB_HalfViolet), + Pixel_ModRGB(22, Set, RGB_HalfViolet), + Pixel_ModRGB(41, Set, RGB_HalfViolet), + Pixel_ModRGB(59, Set, RGB_HalfViolet), + Pixel_ModRGB(75, Set, RGB_HalfViolet), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_Violet), + Pixel_ModRGB(23, Set, RGB_Violet), + Pixel_ModRGB(42, Set, RGB_Violet), + Pixel_ModRGB(60, Set, RGB_Violet), + Pixel_ModRGB(76, Set, RGB_Violet), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_IndigoViolet), + Pixel_ModRGB(24, Set, RGB_IndigoViolet), + Pixel_ModRGB(43, Set, RGB_IndigoViolet), + Pixel_ModRGB(61, Set, RGB_IndigoViolet), + Pixel_ModRGB(77, Set, RGB_IndigoViolet), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_Indigo), + Pixel_ModRGB(25, Set, RGB_Indigo), + Pixel_ModRGB(44, Set, RGB_Indigo), + Pixel_ModRGB(62, Set, RGB_Indigo), + Pixel_ModRGB(78, Set, RGB_Indigo), + Pixel_ModRGB(88, Set, RGB_Indigo), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_BlueIndigo), + Pixel_ModRGB(26, Set, RGB_BlueIndigo), + Pixel_ModRGB(45, Set, RGB_BlueIndigo), + Pixel_ModRGB(63, Set, RGB_BlueIndigo), + Pixel_ModRGB(79, Set, RGB_BlueIndigo), + Pixel_ModRGB(89, Set, RGB_BlueIndigo), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_Blue), + Pixel_ModRGB(27, Set, RGB_Blue), + Pixel_ModRGB(46, Set, RGB_Blue), + Pixel_ModRGB(64, Set, RGB_Blue), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_GreenBlue), + Pixel_ModRGB(28, Set, RGB_GreenBlue), + Pixel_ModRGB(47, Set, RGB_GreenBlue), + Pixel_ModRGB(90, Set, RGB_GreenBlue), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_Green), + Pixel_ModRGB(30, Set, RGB_Green), + Pixel_ModRGB(66, Set, RGB_Green), + Pixel_ModRGB(81, Set, RGB_Green), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_YellowGreen), + Pixel_ModRGB(48, Set, RGB_YellowGreen), + Pixel_ModRGB(91, Set, RGB_YellowGreen), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_Yellow), + Pixel_ModRGB(32, Set, RGB_Yellow), + Pixel_ModRGB(50, Set, RGB_Yellow), + Pixel_ModRGB(92, Set, RGB_Yellow), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_OrangeYellow), + Pixel_ModRGB(33, Set, RGB_OrangeYellow), + Pixel_ModRGB(51, Set, RGB_OrangeYellow), + Pixel_ModRGB(83, Set, RGB_OrangeYellow), + Pixel_ModRGB(93, Set, RGB_OrangeYellow), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_Orange), + Pixel_ModRGB(34, Set, RGB_Orange), + Pixel_ModRGB(52, Set, RGB_Orange), + Pixel_ModRGB(94, Set, RGB_Orange), +}; + +const uint8_t rainbow_frame22[] = { + // Set 8 + Pixel_ModRGB(4, Set, RGB_Black), + Pixel_ModRGB(22, Set, RGB_Black), + Pixel_ModRGB(41, Set, RGB_Black), + Pixel_ModRGB(59, Set, RGB_Black), + Pixel_ModRGB(75, Set, RGB_Black), + + // Set 9 + Pixel_ModRGB(5, Set, RGB_HalfViolet), + Pixel_ModRGB(23, Set, RGB_HalfViolet), + Pixel_ModRGB(42, Set, RGB_HalfViolet), + Pixel_ModRGB(60, Set, RGB_HalfViolet), + Pixel_ModRGB(76, Set, RGB_HalfViolet), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_Violet), + Pixel_ModRGB(24, Set, RGB_Violet), + Pixel_ModRGB(43, Set, RGB_Violet), + Pixel_ModRGB(61, Set, RGB_Violet), + Pixel_ModRGB(77, Set, RGB_Violet), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_IndigoViolet), + Pixel_ModRGB(25, Set, RGB_IndigoViolet), + Pixel_ModRGB(44, Set, RGB_IndigoViolet), + Pixel_ModRGB(62, Set, RGB_IndigoViolet), + Pixel_ModRGB(78, Set, RGB_IndigoViolet), + Pixel_ModRGB(88, Set, RGB_IndigoViolet), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_Indigo), + Pixel_ModRGB(26, Set, RGB_Indigo), + Pixel_ModRGB(45, Set, RGB_Indigo), + Pixel_ModRGB(63, Set, RGB_Indigo), + Pixel_ModRGB(79, Set, RGB_Indigo), + Pixel_ModRGB(89, Set, RGB_Indigo), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_BlueIndigo), + Pixel_ModRGB(27, Set, RGB_BlueIndigo), + Pixel_ModRGB(46, Set, RGB_BlueIndigo), + Pixel_ModRGB(64, Set, RGB_BlueIndigo), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_Blue), + Pixel_ModRGB(28, Set, RGB_Blue), + Pixel_ModRGB(47, Set, RGB_Blue), + Pixel_ModRGB(90, Set, RGB_Blue), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_GreenBlue), + Pixel_ModRGB(30, Set, RGB_GreenBlue), + Pixel_ModRGB(66, Set, RGB_GreenBlue), + Pixel_ModRGB(81, Set, RGB_GreenBlue), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_Green), + Pixel_ModRGB(48, Set, RGB_Green), + Pixel_ModRGB(91, Set, RGB_Green), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_YellowGreen), + Pixel_ModRGB(32, Set, RGB_YellowGreen), + Pixel_ModRGB(50, Set, RGB_YellowGreen), + Pixel_ModRGB(92, Set, RGB_YellowGreen), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_Yellow), + Pixel_ModRGB(33, Set, RGB_Yellow), + Pixel_ModRGB(51, Set, RGB_Yellow), + Pixel_ModRGB(83, Set, RGB_Yellow), + Pixel_ModRGB(93, Set, RGB_Yellow), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_OrangeYellow), + Pixel_ModRGB(34, Set, RGB_OrangeYellow), + Pixel_ModRGB(52, Set, RGB_OrangeYellow), + Pixel_ModRGB(94, Set, RGB_OrangeYellow), +}; + +const uint8_t rainbow_frame23[] = { + // Set 9 + Pixel_ModRGB(5, Set, RGB_Black), + Pixel_ModRGB(23, Set, RGB_Black), + Pixel_ModRGB(42, Set, RGB_Black), + Pixel_ModRGB(60, Set, RGB_Black), + Pixel_ModRGB(76, Set, RGB_Black), + + // Set 10 + Pixel_ModRGB(6, Set, RGB_HalfViolet), + Pixel_ModRGB(24, Set, RGB_HalfViolet), + Pixel_ModRGB(43, Set, RGB_HalfViolet), + Pixel_ModRGB(61, Set, RGB_HalfViolet), + Pixel_ModRGB(77, Set, RGB_HalfViolet), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_Violet), + Pixel_ModRGB(25, Set, RGB_Violet), + Pixel_ModRGB(44, Set, RGB_Violet), + Pixel_ModRGB(62, Set, RGB_Violet), + Pixel_ModRGB(78, Set, RGB_Violet), + Pixel_ModRGB(88, Set, RGB_Violet), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_IndigoViolet), + Pixel_ModRGB(26, Set, RGB_IndigoViolet), + Pixel_ModRGB(45, Set, RGB_IndigoViolet), + Pixel_ModRGB(63, Set, RGB_IndigoViolet), + Pixel_ModRGB(79, Set, RGB_IndigoViolet), + Pixel_ModRGB(89, Set, RGB_IndigoViolet), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_Indigo), + Pixel_ModRGB(27, Set, RGB_Indigo), + Pixel_ModRGB(46, Set, RGB_Indigo), + Pixel_ModRGB(64, Set, RGB_Indigo), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_BlueIndigo), + Pixel_ModRGB(28, Set, RGB_BlueIndigo), + Pixel_ModRGB(47, Set, RGB_BlueIndigo), + Pixel_ModRGB(90, Set, RGB_BlueIndigo), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_Blue), + Pixel_ModRGB(30, Set, RGB_Blue), + Pixel_ModRGB(66, Set, RGB_Blue), + Pixel_ModRGB(81, Set, RGB_Blue), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_GreenBlue), + Pixel_ModRGB(48, Set, RGB_GreenBlue), + Pixel_ModRGB(91, Set, RGB_GreenBlue), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_Green), + Pixel_ModRGB(32, Set, RGB_Green), + Pixel_ModRGB(50, Set, RGB_Green), + Pixel_ModRGB(92, Set, RGB_Green), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_YellowGreen), + Pixel_ModRGB(33, Set, RGB_YellowGreen), + Pixel_ModRGB(51, Set, RGB_YellowGreen), + Pixel_ModRGB(83, Set, RGB_YellowGreen), + Pixel_ModRGB(93, Set, RGB_YellowGreen), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_Yellow), + Pixel_ModRGB(34, Set, RGB_Yellow), + Pixel_ModRGB(52, Set, RGB_Yellow), + Pixel_ModRGB(94, Set, RGB_Yellow), +}; + +const uint8_t rainbow_frame24[] = { + // Set 10 + Pixel_ModRGB(6, Set, RGB_Black), + Pixel_ModRGB(24, Set, RGB_Black), + Pixel_ModRGB(43, Set, RGB_Black), + Pixel_ModRGB(61, Set, RGB_Black), + Pixel_ModRGB(77, Set, RGB_Black), + + // Set 11 + Pixel_ModRGB(7, Set, RGB_HalfViolet), + Pixel_ModRGB(25, Set, RGB_HalfViolet), + Pixel_ModRGB(44, Set, RGB_HalfViolet), + Pixel_ModRGB(62, Set, RGB_HalfViolet), + Pixel_ModRGB(78, Set, RGB_HalfViolet), + Pixel_ModRGB(88, Set, RGB_HalfViolet), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_Violet), + Pixel_ModRGB(26, Set, RGB_Violet), + Pixel_ModRGB(45, Set, RGB_Violet), + Pixel_ModRGB(63, Set, RGB_Violet), + Pixel_ModRGB(79, Set, RGB_Violet), + Pixel_ModRGB(89, Set, RGB_Violet), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_IndigoViolet), + Pixel_ModRGB(27, Set, RGB_IndigoViolet), + Pixel_ModRGB(46, Set, RGB_IndigoViolet), + Pixel_ModRGB(64, Set, RGB_IndigoViolet), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_Indigo), + Pixel_ModRGB(28, Set, RGB_Indigo), + Pixel_ModRGB(47, Set, RGB_Indigo), + Pixel_ModRGB(90, Set, RGB_Indigo), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_BlueIndigo), + Pixel_ModRGB(30, Set, RGB_BlueIndigo), + Pixel_ModRGB(66, Set, RGB_BlueIndigo), + Pixel_ModRGB(81, Set, RGB_BlueIndigo), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_Blue), + Pixel_ModRGB(48, Set, RGB_Blue), + Pixel_ModRGB(91, Set, RGB_Blue), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_GreenBlue), + Pixel_ModRGB(32, Set, RGB_GreenBlue), + Pixel_ModRGB(50, Set, RGB_GreenBlue), + Pixel_ModRGB(92, Set, RGB_GreenBlue), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_Green), + Pixel_ModRGB(33, Set, RGB_Green), + Pixel_ModRGB(51, Set, RGB_Green), + Pixel_ModRGB(83, Set, RGB_Green), + Pixel_ModRGB(93, Set, RGB_Green), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_YellowGreen), + Pixel_ModRGB(34, Set, RGB_YellowGreen), + Pixel_ModRGB(52, Set, RGB_YellowGreen), + Pixel_ModRGB(94, Set, RGB_YellowGreen), +}; + +const uint8_t rainbow_frame25[] = { + // Set 11 + Pixel_ModRGB(7, Set, RGB_Black), + Pixel_ModRGB(25, Set, RGB_Black), + Pixel_ModRGB(44, Set, RGB_Black), + Pixel_ModRGB(62, Set, RGB_Black), + Pixel_ModRGB(78, Set, RGB_Black), + Pixel_ModRGB(88, Set, RGB_Black), + + // Set 12 + Pixel_ModRGB(8, Set, RGB_HalfViolet), + Pixel_ModRGB(26, Set, RGB_HalfViolet), + Pixel_ModRGB(45, Set, RGB_HalfViolet), + Pixel_ModRGB(63, Set, RGB_HalfViolet), + Pixel_ModRGB(79, Set, RGB_HalfViolet), + Pixel_ModRGB(89, Set, RGB_HalfViolet), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_Violet), + Pixel_ModRGB(27, Set, RGB_Violet), + Pixel_ModRGB(46, Set, RGB_Violet), + Pixel_ModRGB(64, Set, RGB_Violet), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_IndigoViolet), + Pixel_ModRGB(28, Set, RGB_IndigoViolet), + Pixel_ModRGB(47, Set, RGB_IndigoViolet), + Pixel_ModRGB(90, Set, RGB_IndigoViolet), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_Indigo), + Pixel_ModRGB(30, Set, RGB_Indigo), + Pixel_ModRGB(66, Set, RGB_Indigo), + Pixel_ModRGB(81, Set, RGB_Indigo), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_BlueIndigo), + Pixel_ModRGB(48, Set, RGB_BlueIndigo), + Pixel_ModRGB(91, Set, RGB_BlueIndigo), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_Blue), + Pixel_ModRGB(32, Set, RGB_Blue), + Pixel_ModRGB(50, Set, RGB_Blue), + Pixel_ModRGB(92, Set, RGB_Blue), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_GreenBlue), + Pixel_ModRGB(33, Set, RGB_GreenBlue), + Pixel_ModRGB(51, Set, RGB_GreenBlue), + Pixel_ModRGB(83, Set, RGB_GreenBlue), + Pixel_ModRGB(93, Set, RGB_GreenBlue), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_Green), + Pixel_ModRGB(34, Set, RGB_Green), + Pixel_ModRGB(52, Set, RGB_Green), + Pixel_ModRGB(94, Set, RGB_Green), +}; + +const uint8_t rainbow_frame26[] = { + // Set 12 + Pixel_ModRGB(8, Set, RGB_Black), + Pixel_ModRGB(26, Set, RGB_Black), + Pixel_ModRGB(45, Set, RGB_Black), + Pixel_ModRGB(63, Set, RGB_Black), + Pixel_ModRGB(79, Set, RGB_Black), + Pixel_ModRGB(89, Set, RGB_Black), + + // Set 13 + Pixel_ModRGB(9, Set, RGB_HalfViolet), + Pixel_ModRGB(27, Set, RGB_HalfViolet), + Pixel_ModRGB(46, Set, RGB_HalfViolet), + Pixel_ModRGB(64, Set, RGB_HalfViolet), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_Violet), + Pixel_ModRGB(28, Set, RGB_Violet), + Pixel_ModRGB(47, Set, RGB_Violet), + Pixel_ModRGB(90, Set, RGB_Violet), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_IndigoViolet), + Pixel_ModRGB(30, Set, RGB_IndigoViolet), + Pixel_ModRGB(66, Set, RGB_IndigoViolet), + Pixel_ModRGB(81, Set, RGB_IndigoViolet), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_Indigo), + Pixel_ModRGB(48, Set, RGB_Indigo), + Pixel_ModRGB(91, Set, RGB_Indigo), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_BlueIndigo), + Pixel_ModRGB(32, Set, RGB_BlueIndigo), + Pixel_ModRGB(50, Set, RGB_BlueIndigo), + Pixel_ModRGB(92, Set, RGB_BlueIndigo), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_Blue), + Pixel_ModRGB(33, Set, RGB_Blue), + Pixel_ModRGB(51, Set, RGB_Blue), + Pixel_ModRGB(83, Set, RGB_Blue), + Pixel_ModRGB(93, Set, RGB_Blue), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_GreenBlue), + Pixel_ModRGB(34, Set, RGB_GreenBlue), + Pixel_ModRGB(52, Set, RGB_GreenBlue), + Pixel_ModRGB(94, Set, RGB_GreenBlue), +}; + +const uint8_t rainbow_frame27[] = { + // Set 13 + Pixel_ModRGB(9, Set, RGB_Black), + Pixel_ModRGB(27, Set, RGB_Black), + Pixel_ModRGB(46, Set, RGB_Black), + Pixel_ModRGB(64, Set, RGB_Black), + + // Set 14 + Pixel_ModRGB(10, Set, RGB_HalfViolet), + Pixel_ModRGB(28, Set, RGB_HalfViolet), + Pixel_ModRGB(47, Set, RGB_HalfViolet), + Pixel_ModRGB(90, Set, RGB_HalfViolet), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_Violet), + Pixel_ModRGB(30, Set, RGB_Violet), + Pixel_ModRGB(66, Set, RGB_Violet), + Pixel_ModRGB(81, Set, RGB_Violet), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_IndigoViolet), + Pixel_ModRGB(48, Set, RGB_IndigoViolet), + Pixel_ModRGB(91, Set, RGB_IndigoViolet), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_Indigo), + Pixel_ModRGB(32, Set, RGB_Indigo), + Pixel_ModRGB(50, Set, RGB_Indigo), + Pixel_ModRGB(92, Set, RGB_Indigo), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_BlueIndigo), + Pixel_ModRGB(33, Set, RGB_BlueIndigo), + Pixel_ModRGB(51, Set, RGB_BlueIndigo), + Pixel_ModRGB(83, Set, RGB_BlueIndigo), + Pixel_ModRGB(93, Set, RGB_BlueIndigo), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_Blue), + Pixel_ModRGB(34, Set, RGB_Blue), + Pixel_ModRGB(52, Set, RGB_Blue), + Pixel_ModRGB(94, Set, RGB_Blue), +}; + +const uint8_t rainbow_frame28[] = { + // Set 14 + Pixel_ModRGB(10, Set, RGB_Black), + Pixel_ModRGB(28, Set, RGB_Black), + Pixel_ModRGB(47, Set, RGB_Black), + Pixel_ModRGB(90, Set, RGB_Black), + + // Set 15 + Pixel_ModRGB(11, Set, RGB_HalfViolet), + Pixel_ModRGB(30, Set, RGB_HalfViolet), + Pixel_ModRGB(66, Set, RGB_HalfViolet), + Pixel_ModRGB(81, Set, RGB_HalfViolet), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_Violet), + Pixel_ModRGB(48, Set, RGB_Violet), + Pixel_ModRGB(91, Set, RGB_Violet), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_IndigoViolet), + Pixel_ModRGB(32, Set, RGB_IndigoViolet), + Pixel_ModRGB(50, Set, RGB_IndigoViolet), + Pixel_ModRGB(92, Set, RGB_IndigoViolet), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_Indigo), + Pixel_ModRGB(33, Set, RGB_Indigo), + Pixel_ModRGB(51, Set, RGB_Indigo), + Pixel_ModRGB(83, Set, RGB_Indigo), + Pixel_ModRGB(93, Set, RGB_Indigo), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_BlueIndigo), + Pixel_ModRGB(34, Set, RGB_BlueIndigo), + Pixel_ModRGB(52, Set, RGB_BlueIndigo), + Pixel_ModRGB(94, Set, RGB_BlueIndigo), +}; + +const uint8_t rainbow_frame29[] = { + // Set 15 + Pixel_ModRGB(11, Set, RGB_Black), + Pixel_ModRGB(30, Set, RGB_Black), + Pixel_ModRGB(66, Set, RGB_Black), + Pixel_ModRGB(81, Set, RGB_Black), + + // Set 16 + Pixel_ModRGB(12, Set, RGB_HalfViolet), + Pixel_ModRGB(48, Set, RGB_HalfViolet), + Pixel_ModRGB(91, Set, RGB_HalfViolet), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_Violet), + Pixel_ModRGB(32, Set, RGB_Violet), + Pixel_ModRGB(50, Set, RGB_Violet), + Pixel_ModRGB(92, Set, RGB_Violet), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_IndigoViolet), + Pixel_ModRGB(33, Set, RGB_IndigoViolet), + Pixel_ModRGB(51, Set, RGB_IndigoViolet), + Pixel_ModRGB(83, Set, RGB_IndigoViolet), + Pixel_ModRGB(93, Set, RGB_IndigoViolet), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_Indigo), + Pixel_ModRGB(34, Set, RGB_Indigo), + Pixel_ModRGB(52, Set, RGB_Indigo), + Pixel_ModRGB(94, Set, RGB_Indigo), +}; + +const uint8_t rainbow_frame30[] = { + // Set 16 + Pixel_ModRGB(12, Set, RGB_Black), + Pixel_ModRGB(48, Set, RGB_Black), + Pixel_ModRGB(91, Set, RGB_Black), + + // Set 17 + Pixel_ModRGB(13, Set, RGB_HalfViolet), + Pixel_ModRGB(32, Set, RGB_HalfViolet), + Pixel_ModRGB(50, Set, RGB_HalfViolet), + Pixel_ModRGB(92, Set, RGB_HalfViolet), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_Violet), + Pixel_ModRGB(33, Set, RGB_Violet), + Pixel_ModRGB(51, Set, RGB_Violet), + Pixel_ModRGB(83, Set, RGB_Violet), + Pixel_ModRGB(93, Set, RGB_Violet), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_IndigoViolet), + Pixel_ModRGB(34, Set, RGB_IndigoViolet), + Pixel_ModRGB(52, Set, RGB_IndigoViolet), + Pixel_ModRGB(94, Set, RGB_IndigoViolet), +}; + +const uint8_t rainbow_frame31[] = { + // Set 17 + Pixel_ModRGB(13, Set, RGB_Black), + Pixel_ModRGB(32, Set, RGB_Black), + Pixel_ModRGB(50, Set, RGB_Black), + Pixel_ModRGB(92, Set, RGB_Black), + + // Set 18 + Pixel_ModRGB(14, Set, RGB_HalfViolet), + Pixel_ModRGB(33, Set, RGB_HalfViolet), + Pixel_ModRGB(51, Set, RGB_HalfViolet), + Pixel_ModRGB(83, Set, RGB_HalfViolet), + Pixel_ModRGB(93, Set, RGB_HalfViolet), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_Violet), + Pixel_ModRGB(34, Set, RGB_Violet), + Pixel_ModRGB(52, Set, RGB_Violet), + Pixel_ModRGB(94, Set, RGB_Violet), +}; + +const uint8_t rainbow_frame32[] = { + // Set 18 + Pixel_ModRGB(14, Set, RGB_Black), + Pixel_ModRGB(33, Set, RGB_Black), + Pixel_ModRGB(51, Set, RGB_Black), + Pixel_ModRGB(83, Set, RGB_Black), + Pixel_ModRGB(93, Set, RGB_Black), + + // Set 19 + Pixel_ModRGB(15, Set, RGB_HalfViolet), + Pixel_ModRGB(34, Set, RGB_HalfViolet), + Pixel_ModRGB(52, Set, RGB_HalfViolet), + Pixel_ModRGB(94, Set, RGB_HalfViolet), +}; + +const uint8_t rainbow_frame33[] = { + // Set 19 + Pixel_ModRGB(15, Set, RGB_Black), + Pixel_ModRGB(34, Set, RGB_Black), + Pixel_ModRGB(52, Set, RGB_Black), + Pixel_ModRGB(94, Set, RGB_Black), +}; + + // Index of frames for animations // uint8_t *_frames[] = { _frame, ... } @@ -289,8 +2342,79 @@ const uint8_t *rainbow_frames[] = { rainbow_frame0, rainbow_frame1, rainbow_frame2, + rainbow_frame3, + rainbow_frame4, + rainbow_frame5, + rainbow_frame6, + rainbow_frame7, + rainbow_frame8, + rainbow_frame9, + rainbow_frame10, + rainbow_frame11, + rainbow_frame12, + rainbow_frame13, + rainbow_frame14, + rainbow_frame15, + rainbow_frame16, + rainbow_frame17, + rainbow_frame18, + rainbow_frame19, + rainbow_frame20, + rainbow_frame21, + rainbow_frame22, + rainbow_frame23, + rainbow_frame24, + rainbow_frame25, + rainbow_frame26, + rainbow_frame27, + rainbow_frame28, + rainbow_frame29, + rainbow_frame30, + rainbow_frame31, + rainbow_frame32, + rainbow_frame33, }; +const uint16_t rainbow_framesizes[] = { + sizeof( rainbow_frame0 ), + sizeof( rainbow_frame1 ), + sizeof( rainbow_frame2 ), + sizeof( rainbow_frame3 ), + sizeof( rainbow_frame4 ), + sizeof( rainbow_frame5 ), + sizeof( rainbow_frame6 ), + sizeof( rainbow_frame7 ), + sizeof( rainbow_frame8 ), + sizeof( rainbow_frame9 ), + sizeof( rainbow_frame10 ), + sizeof( rainbow_frame11 ), + sizeof( rainbow_frame12 ), + sizeof( rainbow_frame13 ), + sizeof( rainbow_frame14 ), + sizeof( rainbow_frame15 ), + sizeof( rainbow_frame16 ), + sizeof( rainbow_frame17 ), + sizeof( rainbow_frame18 ), + sizeof( rainbow_frame19 ), + sizeof( rainbow_frame20 ), + sizeof( rainbow_frame21 ), + sizeof( rainbow_frame22 ), + sizeof( rainbow_frame23 ), + sizeof( rainbow_frame24 ), + sizeof( rainbow_frame25 ), + sizeof( rainbow_frame26 ), + sizeof( rainbow_frame27 ), + sizeof( rainbow_frame28 ), + sizeof( rainbow_frame29 ), + sizeof( rainbow_frame30 ), + sizeof( rainbow_frame31 ), + sizeof( rainbow_frame32 ), + sizeof( rainbow_frame33 ), +}; + +// XXX Temp +uint16_t rainbow_pos = 0; + // Index of animations // uint8_t *Pixel_Animations[] = { _frames, ... } @@ -311,33 +2435,33 @@ const uint8_t **Pixel_Animations[] = { // ----- Functions ----- -PixelBuf Pixel_bufferMap( uint16_t channel ) +PixelBuf *Pixel_bufferMap( uint16_t channel ) { // TODO Generate - if ( channel < 144 ) return Pixel_Buffers[0]; - else if ( channel < 288 ) return Pixel_Buffers[1]; - else if ( channel < 432 ) return Pixel_Buffers[2]; + if ( channel < 144 ) return &Pixel_Buffers[0]; + else if ( channel < 288 ) return &Pixel_Buffers[1]; + else if ( channel < 432 ) return &Pixel_Buffers[2]; // Invalid channel, return first channel and display error erro_msg("Invalid channel: "); printHex( channel ); print( NL ); - return Pixel_Buffers[0]; + return &Pixel_Buffers[0]; } // Toggle the given channel void Pixel_channelToggle( uint16_t channel ) { // Determine which buffer we are in - PixelBuf pixbuf = Pixel_bufferMap( channel ); + PixelBuf *pixbuf = Pixel_bufferMap( channel ); // Toggle channel accordingly - switch ( pixbuf.width ) + switch ( pixbuf->width ) { // Invalid width, default to 8 default: warn_msg("Unknown width, using 8: "); - printInt8( pixbuf.width ); + printInt8( pixbuf->width ); print(" Ch: "); printHex( channel ); print( NL ); @@ -365,6 +2489,47 @@ void Pixel_pixelToggle( PixelElement *elem ) } } +// Process each pixel in the frame +// TODO Handle non-8bit channel widths +void Pixel_pixelProcess( const uint8_t *frame, uint16_t size ) +{ + // Map each pixel modification then apply change accordingly + for ( uint16_t pos = 0; pos < size; pos += sizeof( PixelMod ) ) + { + // Map pixel + PixelMod *mod = (PixelMod*)&frame[pos]; + PixelElement *elem = &Pixel_Mapping[mod->pixel]; + PixelBuf *pixbuf; + + // Lookup number of channels in pixel + uint8_t channels = elem->channels; + + // Apply operation to each channel of the pixel + for ( uint8_t ch = 0; ch < channels; ch++ ) + { + uint16_t ch_pos = elem->indices[ch]; + + // Operation + switch ( mod->change ) + { + case PixelChange_Set: // = + // Determine which buffer we are in + pixbuf = Pixel_bufferMap( ch_pos ); + PixelBuf16( pixbuf, ch_pos ) = mod->data[ch]; + break; + + default: + warn_print("Unimplemented pixel modifier"); + break; + } + } + + // Skip extra channels + // TODO account for non-8bit widths + pos += channels; + } +} + // Pixel Procesing Loop inline void Pixel_process() { @@ -446,6 +2611,18 @@ inline void Pixel_process() return; } + case PixelTest_Pixel_Test: + // Start from the top of the Animation Stack + // TODO + dbug_print("YSSS"); + // XXX Temp - Play rainbow + Pixel_pixelProcess( rainbow_frames[rainbow_pos], rainbow_framesizes[rainbow_pos] ); + rainbow_pos++; + Pixel_testMode = PixelTest_Off; + + if ( rainbow_pos >= sizeof( rainbow_frames ) ) + rainbow_pos = 0; + goto pixel_process_done; default: break; @@ -454,6 +2631,16 @@ inline void Pixel_process() // Start from the top of the Animation Stack // TODO + // XXX Temp - Play rainbow + Pixel_pixelProcess( rainbow_frames[rainbow_pos], rainbow_framesizes[rainbow_pos] ); + rainbow_pos++; + Pixel_testMode = PixelTest_Off; + + if ( rainbow_pos >= sizeof( rainbow_framesizes ) / 2 ) + { + rainbow_pos = 0; + } + pixel_process_done: // Frame is now ready to send @@ -580,6 +2767,12 @@ void cliFunc_pixelTest( char* args ) info_msg("Stopping pixel test"); Pixel_testMode = PixelTest_Off; return; + + case 't': + case 'T': + info_msg("Starting pixel test"); + Pixel_testMode = PixelTest_Pixel_Test; + return; } // Check for specific position @@ -635,6 +2828,7 @@ void cliFunc_chanTest( char* args ) case 'S': info_msg("Stopping channel test"); Pixel_testMode = PixelTest_Off; + rainbow_pos = 0; return; } diff --git a/Macro/PixelMap/pixel.h b/Macro/PixelMap/pixel.h index 5acc46b..41ad89a 100644 --- a/Macro/PixelMap/pixel.h +++ b/Macro/PixelMap/pixel.h @@ -72,8 +72,8 @@ typedef struct PixelBuf { void *data; // Pointer to start of buffer } PixelBuf; #define PixelBufElem(len,width,offset,ptr) { len, width, offset, (void*)ptr } -#define PixelBuf8(pixbuf, ch) ( ((uint8_t*) (pixbuf.data))[ ch - pixbuf.offset ] ) -#define PixelBuf16(pixbuf, ch) ( ((uint16_t*)(pixbuf.data))[ ch - pixbuf.offset ] ) +#define PixelBuf8(pixbuf, ch) ( ((uint8_t*) (pixbuf->data))[ ch - pixbuf->offset ] ) +#define PixelBuf16(pixbuf, ch) ( ((uint16_t*)(pixbuf->data))[ ch - pixbuf->offset ] ) // Individual Pixel element From 077d781cf191a1b0c31910b471c939109dbd9f99 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Wed, 13 Jan 2016 14:50:45 -0800 Subject: [PATCH 11/30] Disabling rainbow by default --- Macro/PixelMap/pixel.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index 98b213b..067f93a 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -2620,9 +2620,11 @@ inline void Pixel_process() rainbow_pos++; Pixel_testMode = PixelTest_Off; - if ( rainbow_pos >= sizeof( rainbow_frames ) ) + if ( rainbow_pos >= sizeof( rainbow_frames ) / 2 ) + { rainbow_pos = 0; goto pixel_process_done; + } default: break; @@ -2631,6 +2633,7 @@ inline void Pixel_process() // Start from the top of the Animation Stack // TODO + /* // XXX Temp - Play rainbow Pixel_pixelProcess( rainbow_frames[rainbow_pos], rainbow_framesizes[rainbow_pos] ); rainbow_pos++; @@ -2640,6 +2643,7 @@ inline void Pixel_process() { rainbow_pos = 0; } + */ pixel_process_done: From 5c442e043416b361316d8b075e89d2c509f35a0f Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Wed, 13 Jan 2016 15:03:29 -0800 Subject: [PATCH 12/30] Adding comment for the Teensy 3.2 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f14bbd..dcb0c94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ set( CHIP # "at90usb1286" # Teensy++ 2.0 (avr) # "mk20dx128" # Teensy 3.0 (arm) "mk20dx128vlf5" # McHCK mk20dx128vlf5 -# "mk20dx256" # Teensy 3.1 (arm) +# "mk20dx256" # Teensy 3.1,3.2 (arm) # "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 CACHE STRING "Microcontroller Chip" ) From 6cea31c463a6644f50a84a34ac0046321c9a61cc Mon Sep 17 00:00:00 2001 From: Dan McGregor Date: Mon, 10 Aug 2015 14:49:46 -0600 Subject: [PATCH 13/30] Start removing select Linux-isms bash might not be in /bin. Don't expect it there. --- Bootloader/Scripts/easyMode.bash | 2 +- Bootloader/Scripts/generateManufacturingImage.bash | 2 +- Bootloader/Scripts/ledTest.bash | 2 +- Bootloader/Scripts/swdLoad.bash | 2 +- Keyboards/cmake.bash | 2 +- Keyboards/ergodox.bash | 2 +- Keyboards/infinity.bash | 2 +- Keyboards/template.bash | 2 +- Keyboards/whitefox.bash | 2 +- Lib/CMake/sizeCalculator | 2 +- Lib/CMake/writer | 2 +- LoadFile/load.dfu | 2 +- LoadFile/load.teensy | 2 +- LoadFile/winload.teensy | 2 +- Scan/ISSILed/exampleAPI.bash | 2 +- Scan/STLcd/exampleAPI.bash | 2 +- buildall.bash | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Bootloader/Scripts/easyMode.bash b/Bootloader/Scripts/easyMode.bash index 65b4848..ece0b53 100644 --- a/Bootloader/Scripts/easyMode.bash +++ b/Bootloader/Scripts/easyMode.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Just in case there was an extra ledTest.bash (don't care if error) rm /dev/ttyACM0 diff --git a/Bootloader/Scripts/generateManufacturingImage.bash b/Bootloader/Scripts/generateManufacturingImage.bash index ef46e2d..455e570 100755 --- a/Bootloader/Scripts/generateManufacturingImage.bash +++ b/Bootloader/Scripts/generateManufacturingImage.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Combines a given bootloader image and firmware image into a single firmware binary # Manufacturing deliverable diff --git a/Bootloader/Scripts/ledTest.bash b/Bootloader/Scripts/ledTest.bash index 07aa9d8..9c8565f 100644 --- a/Bootloader/Scripts/ledTest.bash +++ b/Bootloader/Scripts/ledTest.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash printf "led\r" > /dev/ttyACM0 diff --git a/Bootloader/Scripts/swdLoad.bash b/Bootloader/Scripts/swdLoad.bash index 12b1e9b..6c333bf 100755 --- a/Bootloader/Scripts/swdLoad.bash +++ b/Bootloader/Scripts/swdLoad.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Loads firmware image using an SWD Flasher # Uses MCHCK ruby flasher toolchain # NOTE: Only tested with a buspirate on Linux diff --git a/Keyboards/cmake.bash b/Keyboards/cmake.bash index 3a1b6e4..9587abe 100644 --- a/Keyboards/cmake.bash +++ b/Keyboards/cmake.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This is bash lib file for the convenience build scripts # Don't call this script directly # Jacob Alexander 2015 diff --git a/Keyboards/ergodox.bash b/Keyboards/ergodox.bash index b07eb16..85f85a2 100755 --- a/Keyboards/ergodox.bash +++ b/Keyboards/ergodox.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This is a build script template # These build scripts are just a convenience for configuring your keyboard (less daunting than CMake) # Jacob Alexander 2015 diff --git a/Keyboards/infinity.bash b/Keyboards/infinity.bash index bc3c0ac..b790dd5 100755 --- a/Keyboards/infinity.bash +++ b/Keyboards/infinity.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This is a build script template # These build scripts are just a convenience for configuring your keyboard (less daunting than CMake) # Jacob Alexander 2015 diff --git a/Keyboards/template.bash b/Keyboards/template.bash index b1e876f..c522726 100755 --- a/Keyboards/template.bash +++ b/Keyboards/template.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This is a build script template # These build scripts are just a convenience for configuring your keyboard (less daunting than CMake) # Jacob Alexander 2015 diff --git a/Keyboards/whitefox.bash b/Keyboards/whitefox.bash index c5ff835..049986a 100755 --- a/Keyboards/whitefox.bash +++ b/Keyboards/whitefox.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This is a build script template # These build scripts are just a convenience for configuring your keyboard (less daunting than CMake) # Jacob Alexander 2015 diff --git a/Lib/CMake/sizeCalculator b/Lib/CMake/sizeCalculator index affb163..b0ab2e6 100755 --- a/Lib/CMake/sizeCalculator +++ b/Lib/CMake/sizeCalculator @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #| Jacob Alexander 2014 #| Arg List #| 1 - size binary (e.g. avr-size) diff --git a/Lib/CMake/writer b/Lib/CMake/writer index 23f94dd..a5eb27b 100755 --- a/Lib/CMake/writer +++ b/Lib/CMake/writer @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #| Jacob Alexander 2014 #| Arg List #| 1 - File to write to (e.g. final_chip) diff --git a/LoadFile/load.dfu b/LoadFile/load.dfu index d99c5e6..5c7719c 100755 --- a/LoadFile/load.dfu +++ b/LoadFile/load.dfu @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Convenience script for loading firmware onto a dfu type device # By default, initiates dfu-util diff --git a/LoadFile/load.teensy b/LoadFile/load.teensy index 751a97f..b86dd11 100755 --- a/LoadFile/load.teensy +++ b/LoadFile/load.teensy @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Convenience script for loading firmware onto a teensy type device # By default, initiates teensy-load-cli diff --git a/LoadFile/winload.teensy b/LoadFile/winload.teensy index 1d86daf..4928197 100755 --- a/LoadFile/winload.teensy +++ b/LoadFile/winload.teensy @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Convenience script for loading firmware onto a teensy type device # By default, initiates teensy-load-cli diff --git a/Scan/ISSILed/exampleAPI.bash b/Scan/ISSILed/exampleAPI.bash index f821b7f..e6e2d10 100755 --- a/Scan/ISSILed/exampleAPI.bash +++ b/Scan/ISSILed/exampleAPI.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # ISSILed # Virtual Serial Port API Example # Jacob Alexander 2015 diff --git a/Scan/STLcd/exampleAPI.bash b/Scan/STLcd/exampleAPI.bash index dfce9d1..ae470b3 100755 --- a/Scan/STLcd/exampleAPI.bash +++ b/Scan/STLcd/exampleAPI.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # STLcd # Virtual Serial Port API Example # Jacob Alexander 2015 diff --git a/buildall.bash b/buildall.bash index dd3a7cc..4f5aaa9 100755 --- a/buildall.bash +++ b/buildall.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash ###| Builder Script |### # # Builds all permutations of modules From c5cba9818e231189bdbda3feb26e98108a24aa16 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Wed, 13 Jan 2016 15:04:45 -0800 Subject: [PATCH 14/30] Updating README for Teensy 3.2 support --- README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.markdown b/README.markdown index f020072..9e0d5c4 100644 --- a/README.markdown +++ b/README.markdown @@ -38,8 +38,8 @@ Supported Microcontrollers * Teensy 2.0 (Partial) * Teensy 2.0++ -* Teesny 3.0 -* Teensy 3.1 +* Teensy 3.0 +* Teensy 3.1/3.2 * mk20dx128vlf5 * mk20dx256vlh7 From eedfb3ac2581d860cba66abb94e5d3a3c2cd9d52 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Wed, 27 Jan 2016 20:41:15 -0800 Subject: [PATCH 15/30] Setting WhiteFox LEDs as defaulting to on --- Scan/WhiteFox/defaultMap.kll | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/Scan/WhiteFox/defaultMap.kll b/Scan/WhiteFox/defaultMap.kll index e692d7b..6a4e641 100644 --- a/Scan/WhiteFox/defaultMap.kll +++ b/Scan/WhiteFox/defaultMap.kll @@ -82,9 +82,6 @@ S0x46 : U"Right"; # Defines available to the WhiteFox Scan Module -# Default animation speed -ISSI_AnimationSpeed = 3; # 20 by default - # LED Default Enable Mask Override # # Each LED is represented by a single bit @@ -105,17 +102,17 @@ ISSILedMask1 = " # # Each LED channel supports 256 levels (8-bit control) # By default, LEDs are set to 0 brightness -ISSILedBrightness1 = " -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ -"; +#ISSILedBrightness1 = " +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +#"; # Full brightness example ISSILedBrightness1 = " From abe3bd68c821cabe65b183d32b1fc971a88d0fea Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sat, 6 Feb 2016 18:06:37 -0800 Subject: [PATCH 16/30] Initial code for MD1_1 - IC60 /w Single color LEDs - Requires a different matrix configuration so it's incompatible with the old IC60 layout --- Scan/MD1_1/defaultMap.kll | 134 ++++++++++++++++++++++++++++++ Scan/MD1_1/matrix.h | 56 +++++++++++++ Scan/MD1_1/pinout | 93 +++++++++++++++++++++ Scan/MD1_1/scan_loop.c | 168 ++++++++++++++++++++++++++++++++++++++ Scan/MD1_1/scan_loop.h | 48 +++++++++++ Scan/MD1_1/setup.cmake | 33 ++++++++ 6 files changed, 532 insertions(+) create mode 100644 Scan/MD1_1/defaultMap.kll create mode 100644 Scan/MD1_1/matrix.h create mode 100644 Scan/MD1_1/pinout create mode 100644 Scan/MD1_1/scan_loop.c create mode 100644 Scan/MD1_1/scan_loop.h create mode 100644 Scan/MD1_1/setup.cmake diff --git a/Scan/MD1_1/defaultMap.kll b/Scan/MD1_1/defaultMap.kll new file mode 100644 index 0000000..df51d82 --- /dev/null +++ b/Scan/MD1_1/defaultMap.kll @@ -0,0 +1,134 @@ +Name = MD1_1; +Version = 0.3d; +Author = "HaaTa (Jacob Alexander) 2014-2016"; +KLL = 0.3c; + +# Modified Date +Date = 2016-02-06; + + +S0x00 : U"Esc"; +S0x01 : U"1"; +S0x02 : U"2"; +S0x03 : U"3"; +S0x04 : U"4"; +S0x05 : U"5"; +S0x06 : U"6"; +S0x07 : U"7"; +S0x08 : U"8"; +S0x09 : U"9"; +S0x0A : U"0"; +S0x0B : U"Minus"; +S0x0C : U"Equal"; +S0x0D : U"Backslash"; +S0x0E : U"Backtick"; +S0x0F : U"Tab"; +S0x10 : U"Q"; +S0x11 : U"W"; +S0x12 : U"E"; +S0x13 : U"R"; +S0x14 : U"T"; +S0x15 : U"Y"; +S0x16 : U"U"; +S0x17 : U"I"; +S0x18 : U"O"; +S0x19 : U"P"; +S0x1A : U"LBrace"; +S0x1B : U"RBrace"; +S0x1C : U"Backspace"; +S0x1D : U"Ctrl"; +S0x1E : U"A"; +S0x1F : U"S"; +S0x20 : U"D"; +S0x21 : U"F"; +S0x22 : U"G"; +S0x23 : U"H"; +S0x24 : U"J"; +S0x25 : U"K"; +S0x26 : U"L"; +S0x27 : U"Semicolon"; +S0x28 : U"Quote"; +S0x29 : U"Enter"; +S0x2A : U"LShift"; +S0x2B : U"Z"; +S0x2C : U"X"; +S0x2D : U"C"; +S0x2E : U"V"; +S0x2F : U"B"; +S0x30 : U"N"; +S0x31 : U"M"; +S0x32 : U"Comma"; +S0x33 : U"Period"; +S0x34 : U"Slash"; +S0x35 : U"RShift"; +S0x36 : U"Function1"; # Fun key +S0x37 : U"Function2"; # Left Blank Key +S0x38 : U"LAlt"; +S0x39 : U"LGui"; +S0x3A : U"Space"; +S0x3B : U"RGui"; +S0x3C : U"RAlt"; +S0x3D : U"Function3"; # Right Blank Key 1 +S0x3E : U"Function4"; # Right Blank Key 2 + + +# Custom Action Examples + +# Example capability, prints to cli +action1 => CustomAction_action1_capability(); # No arguments + +# Blocks given USB Code, must be used with blockLink +# Simple example, supports only blocking a single key at a time +# Keys must be specified using numbers see Macro/PartialMap/usb_hid.h +blockHold => CustomAction_blockHold_capability( usbCode : 1 ); # Single 8-bit argument +blockKey => CustomAction_blockKey_capability( usbCode : 1 ); + + + +# Defines available to the MD1_1 Scan Module + +# LED Default Enable Mask Override +# +# Each LED is represented by a single bit +# See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details +ISSILedMask1 = " + 0xFF, 0x00, /* C1-1 -> C1-16 */ + 0xFF, 0x00, /* C2-1 -> C2-16 */ + 0xFF, 0x00, /* C3-1 -> C3-16 */ + 0xFF, 0x00, /* C4-1 -> C4-16 */ + 0xFF, 0x00, /* C5-1 -> C5-16 */ + 0xFF, 0x00, /* C6-1 -> C6-16 */ + 0xFF, 0x00, /* C7-1 -> C7-16 */ + 0x7F, 0x00, /* C8-1 -> C8-16 */ + 0x00, 0x00, /* C9-1 -> C9-16 */ +"; + +# LED Brightness Override +# +# Each LED channel supports 256 levels (8-bit control) +# By default, LEDs are set to 0 brightness +#ISSILedBrightness1 = " +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +#0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +#"; + +# Full brightness example +ISSILedBrightness1 = " +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C3-1 -> C3-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C4-1 -> C4-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C5-1 -> C5-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C6-1 -> C6-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C7-1 -> C7-16 */ +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C8-1 -> C8-16 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C9-1 -> C9-16 */ +"; + diff --git a/Scan/MD1_1/matrix.h b/Scan/MD1_1/matrix.h new file mode 100644 index 0000000..ca33a52 --- /dev/null +++ b/Scan/MD1_1/matrix.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2014-2016 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Project Includes +#include + + + +// ----- Matrix Definition ----- + +// Freescale ARM MK20's support GPIO PTA, PTB, PTC, PTD and PTE 0..31 +// Not all chips have access to all of these pins (most don't have 160 pins :P) +// +// NOTE: +// Before using a pin, make sure it supports being a GPIO *and* doesn't have a default pull-up/pull-down +// Checking this is completely on the ownness of the user + +// MD1 +// +// Columns (Strobe) +// PTB0..3,16,17 +// PTC4,5 +// PTD0 +// +// Rows (Sense) +// PTD1..7 + +// Define Rows (Sense) and Columns (Strobes) +GPIO_Pin Matrix_cols[] = { gpio(C,0), gpio(C,1), gpio(C,2), gpio(C,3), gpio(C,4), gpio(C,5), gpio(C,6), gpio(C,7), gpio(D,0) }; +GPIO_Pin Matrix_rows[] = { gpio(D,1), gpio(D,2), gpio(D,3), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7) }; + +// Define type of scan matrix +Config Matrix_type = Config_Pulldown; + diff --git a/Scan/MD1_1/pinout b/Scan/MD1_1/pinout new file mode 100644 index 0000000..4b40fe9 --- /dev/null +++ b/Scan/MD1_1/pinout @@ -0,0 +1,93 @@ +Pin Usage +========= + +mk20dx128vlf5 + + ---- +|Keys| + ---- + +* Strobe (Columns) + +TODO + + +* Sense (Rows) + +PTD1 +PTD2 +PTD3 +PTD4 +PTD5 +PTD6 +PTD7 + + + --- +|I2C| + --- + +* IS31FL3731C + +PTB0 - SCL0 (add header pin, label as SCL0) +PTB1 - SDA0 (add header pin, label as SDA0) +PTB17 - INTB Chip 1 +PTB16 - SDB (tied to all Chips, hardware shutdown) + + + ----- +|Debug| + ----- + +* SWD + +PTA0 (Pull-down) +PTA3 (Pull-up) + +* LEDs + +PTA19 (LED only for PCB, not McHCK) (XTAL) + +* UARTs + +PTA1 - RX0 +PTA2 - TX0 + +* Tag Connect + +1 - Vdd +5 +2 - PTA3 / SWD_IO +3 - Vss / Gnd +4 - PTA0 / SWD_CLK +5 - +5V +6 - PTA2 / TRACE_SWO +7 - N/C +8 - PTA1 / JTAG_TDI +9 - N/C +10 - Reset_b + + + ------ +|Unused| + ------ + +* GPIO + +PTA1 (Not broken out on PCB, available on McHCK) (Pull-up) +PTA2 (") +PTA4 (Pull-up) +PTA18 (EXTAL) + +PTC0 +PTC1 +PTC2 +PTC3 +PTC6 +PTC7 + +* Analog + +ADC0_DP0 +ADC0_DM0 + + diff --git a/Scan/MD1_1/scan_loop.c b/Scan/MD1_1/scan_loop.c new file mode 100644 index 0000000..74218a0 --- /dev/null +++ b/Scan/MD1_1/scan_loop.c @@ -0,0 +1,168 @@ +/* Copyright (C) 2014,2016 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include +#include +#include +#include +#include + +// Local Includes +#include "scan_loop.h" + + + +// ----- Function Declarations ----- + +// ----- Variables ----- + +// Number of scans since the last USB send +uint16_t Scan_scanCount = 0; + + + +// ----- Functions ----- + +// Setup +inline void Scan_setup() +{ + // Setup GPIO pins for matrix scanning + Matrix_setup(); + + // Setup ISSI chip to control the leds + LED_setup(); + + // Reset scan count + Scan_scanCount = 0; +} + + +// Main Detection Loop +inline uint8_t Scan_loop() +{ + Matrix_scan( Scan_scanCount++ ); + + // Process any LED events + LED_scan(); + + return 0; +} + + +// Signal from Macro Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithMacro( uint8_t sentKeys ) +{ +} + + +// Signal from Output Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithOutput( uint8_t sentKeys ) +{ + // Reset scan loop indicator (resets each key debounce state) + // TODO should this occur after USB send or Macro processing? + Scan_scanCount = 0; +} + + + +// ----- Capabilities ----- + +// Custom capability examples +// Refer to kll.h in Macros/PartialMap for state and stateType information +void CustomAction_action1_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + // XXX This is required for debug cli to give you a list of capabilities + if ( stateType == 0xFF && state == 0xFF ) + { + print("CustomAction_action1_capability()"); + return; + } + + // Prints Action1 info message to the debug cli + info_print("Action1"); +} + +uint8_t CustomAction_blockHold_storage = 0; +void CustomAction_blockHold_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("CustomAction_blockHold_capability(usbCode)"); + return; + } + + // Retrieve 8-bit argument + uint8_t key = args[0]; + + // We only care about normal keys + if ( stateType == 0x00 ) + { + // Block given key if we're in the "Press" or "Hold" state + if ( ( state == 0x01 || state == 0x02 ) + && CustomAction_blockHold_storage == 0 ) + { + CustomAction_blockHold_storage = key; + info_msg("Blocking Key: "); + printHex( key ); + print( NL ); + } + // Release if in the "Off" or "Release" state and we're blocking + else if ( ( state == 0x00 || state == 0x03 ) + && key == CustomAction_blockHold_storage ) + { + info_msg("Unblocking Key: "); + printHex( CustomAction_blockHold_storage ); + print( NL ); + CustomAction_blockHold_storage = 0; + } + } +} + +void CustomAction_blockKey_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("CustomAction_blockKey_capability(usbCode)"); + return; + } + + // Retrieve 8-bit argument + uint8_t key = args[0]; + + // If key is not blocked, process + if ( key != CustomAction_blockHold_storage ) + { + extern void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ); + Output_usbCodeSend_capability( state, stateType, &key ); + } +} + diff --git a/Scan/MD1_1/scan_loop.h b/Scan/MD1_1/scan_loop.h new file mode 100644 index 0000000..0c89838 --- /dev/null +++ b/Scan/MD1_1/scan_loop.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Compiler Includes +#include + + + +// ----- Functions ----- + +// Functions to be called by main.c +void Scan_setup( void ); +uint8_t Scan_loop( void ); + +// Call-backs +void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module +void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module + + +// ----- Capabilities ----- + +// Example capabilities +void CustomAction_action1_capability( uint8_t state, uint8_t stateType, uint8_t *args ); +void CustomAction_blockHold_capability( uint8_t state, uint8_t stateType, uint8_t *args ); +void CustomAction_blockKey_capability( uint8_t state, uint8_t stateType, uint8_t *args ); + diff --git a/Scan/MD1_1/setup.cmake b/Scan/MD1_1/setup.cmake new file mode 100644 index 0000000..5ca7607 --- /dev/null +++ b/Scan/MD1_1/setup.cmake @@ -0,0 +1,33 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2014,2016 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Required Submodules +# + +AddModule ( Scan ISSILed ) +AddModule ( Scan MatrixARM ) + + +### +# Module C files +# + +set ( Module_SRCS + scan_loop.c +) + + +### +# Compiler Family Compatibility +# +set ( ModuleCompatibility + arm +) + From ce38bdadf35ff585fd6e1d8de31ae76ec5ba0ab2 Mon Sep 17 00:00:00 2001 From: "Ryan S. Brown" Date: Sat, 6 Feb 2016 21:06:08 -0500 Subject: [PATCH 17/30] Ensure directories can only be made with printable characters In situations where `ls` colors directories incorrectly, the `$module` variable contains unprintable characters. This causes directories to be impossible to `cd` into normally, and is generally a pain. --- buildall.bash | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buildall.bash b/buildall.bash index 4f5aaa9..a8c393b 100755 --- a/buildall.bash +++ b/buildall.bash @@ -31,7 +31,8 @@ main() { # Create permutation directories # Then run cmake, and run each build permutation # Keeping track of how many builds failed/passed - for module in $scanModules; do + for mod in $scanModules; do + module=$(tr -dc "[:print:]" <<< "$mod") # Create directory, but do not error if it exists already mkdir -p build/$module cd build/$module From ab9d10f22bcf23fc5525c409c0c4e155e0fbaca6 Mon Sep 17 00:00:00 2001 From: Kevin Frei Date: Sat, 2 Jan 2016 17:43:05 -0800 Subject: [PATCH 18/30] Fix a handful of infinite loops that occur if you have more than 254 macros --- Macro/PartialMap/macro.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Macro/PartialMap/macro.c b/Macro/PartialMap/macro.c index e861f0e..dc51751 100644 --- a/Macro/PartialMap/macro.c +++ b/Macro/PartialMap/macro.c @@ -135,7 +135,7 @@ uint16_t macroStepCounter = 0; // Key Trigger List Buffer and Layer Cache // The layer cache is set on press only, hold and release events refer to the value set on press TriggerGuide macroTriggerListBuffer[ MaxScanCode ]; -uint8_t macroTriggerListBufferSize = 0; +var_uint_t macroTriggerListBufferSize = 0; var_uint_t macroTriggerListLayerCache[ MaxScanCode ]; // Pending Trigger Macro Index List @@ -557,7 +557,7 @@ inline void Macro_interconnectAdd( void *trigger_ptr ) // Add trigger to the Interconnect Cache // During each processing loop, a scancode may be re-added depending on it's state - for ( uint8_t c = 0; c < macroInterconnectCacheSize; c++ ) + for ( var_uint_t c = 0; c < macroInterconnectCacheSize; c++ ) { // Check if the same ScanCode if ( macroInterconnectCache[ c ].scanCode == trigger->scanCode ) @@ -699,7 +699,7 @@ inline void Macro_appendResultMacroToPendingList( const TriggerMacro *triggerMac uint8_t scanCode = ((TriggerGuide*)&triggerMacro->guide[ pos - TriggerGuideSize ])->scanCode; // Lookup scanCode in buffer list for the current state and stateType - for ( uint8_t keyIndex = 0; keyIndex < macroTriggerListBufferSize; keyIndex++ ) + for ( var_uint_t keyIndex = 0; keyIndex < macroTriggerListBufferSize; keyIndex++ ) { if ( macroTriggerListBuffer[ keyIndex ].scanCode == scanCode ) { @@ -905,7 +905,7 @@ TriggerMacroEval Macro_evalTriggerMacro( var_uint_t triggerMacroIndex ) TriggerMacroVote vote = TriggerMacroVote_Invalid; // Iterate through the key buffer, comparing to each key in the combo - for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ ) + for ( var_uint_t key = 0; key < macroTriggerListBufferSize; key++ ) { // Lookup key information TriggerGuide *keyInfo = ¯oTriggerListBuffer[ key ]; @@ -1065,7 +1065,7 @@ inline ResultMacroEval Macro_evalResultMacro( var_uint_t resultMacroIndex ) inline void Macro_updateTriggerMacroPendingList() { // Iterate over the macroTriggerListBuffer to add any new Trigger Macros to the pending list - for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ ) + for ( var_uint_t key = 0; key < macroTriggerListBufferSize; key++ ) { // TODO LED States // TODO Analog Switches @@ -1586,7 +1586,7 @@ void cliFunc_macroList( char* args ) info_msg("Pending Key Events: "); printInt16( (uint16_t)macroTriggerListBufferSize ); print(" : "); - for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ ) + for ( var_uint_t key = 0; key < macroTriggerListBufferSize; key++ ) { printHex( macroTriggerListBuffer[ key ].scanCode ); print(" "); From 2abfedec22165ab47479b1e849dd484bf9064165 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sat, 20 Feb 2016 13:27:49 -0800 Subject: [PATCH 19/30] Debug code for interconnect cable debugging --- Scan/UARTConnect/connect_scan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Scan/UARTConnect/connect_scan.c b/Scan/UARTConnect/connect_scan.c index 1d08777..55f6619 100644 --- a/Scan/UARTConnect/connect_scan.c +++ b/Scan/UARTConnect/connect_scan.c @@ -1139,6 +1139,7 @@ void Connect_scan() } // Limit how often we do cable checks + //uint32_t time_compare = 0x007; // Used for debugging cables -HaaTa uint32_t time_compare = 0x7FF; // Must be all 1's, 0x3FF is valid, 0x4FF is not uint32_t current_time = systick_millis_count; if ( Connect_lastCheck != current_time From 585c0aae17ce2ee3b9e3992ad8e2e650323092f5 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Mon, 8 Feb 2016 08:28:38 -0800 Subject: [PATCH 20/30] Update README.markdown --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 9e0d5c4..a7802f9 100644 --- a/README.markdown +++ b/README.markdown @@ -84,6 +84,7 @@ Contact If you really need to get a hold of HaaTa, email is best: `haata@kiibohd.com` IRC is likely faster though. +`#input.club@irc.freenode.net` `#geekhack@irc.freenode.net` `#deskthority@irc.freenode.net` From bba3ec86098ce552f01415b158e46148422b8a04 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Thu, 11 Feb 2016 22:56:25 -0800 Subject: [PATCH 21/30] Changed name from MD1_1 to MD1.1 --- Scan/{MD1_1 => MD1.1}/defaultMap.kll | 2 +- Scan/{MD1_1 => MD1.1}/matrix.h | 0 Scan/{MD1_1 => MD1.1}/pinout | 0 Scan/{MD1_1 => MD1.1}/scan_loop.c | 0 Scan/{MD1_1 => MD1.1}/scan_loop.h | 0 Scan/{MD1_1 => MD1.1}/setup.cmake | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename Scan/{MD1_1 => MD1.1}/defaultMap.kll (99%) rename Scan/{MD1_1 => MD1.1}/matrix.h (100%) rename Scan/{MD1_1 => MD1.1}/pinout (100%) rename Scan/{MD1_1 => MD1.1}/scan_loop.c (100%) rename Scan/{MD1_1 => MD1.1}/scan_loop.h (100%) rename Scan/{MD1_1 => MD1.1}/setup.cmake (100%) diff --git a/Scan/MD1_1/defaultMap.kll b/Scan/MD1.1/defaultMap.kll similarity index 99% rename from Scan/MD1_1/defaultMap.kll rename to Scan/MD1.1/defaultMap.kll index df51d82..f60a4ed 100644 --- a/Scan/MD1_1/defaultMap.kll +++ b/Scan/MD1.1/defaultMap.kll @@ -1,4 +1,4 @@ -Name = MD1_1; +Name = MD1.1; Version = 0.3d; Author = "HaaTa (Jacob Alexander) 2014-2016"; KLL = 0.3c; diff --git a/Scan/MD1_1/matrix.h b/Scan/MD1.1/matrix.h similarity index 100% rename from Scan/MD1_1/matrix.h rename to Scan/MD1.1/matrix.h diff --git a/Scan/MD1_1/pinout b/Scan/MD1.1/pinout similarity index 100% rename from Scan/MD1_1/pinout rename to Scan/MD1.1/pinout diff --git a/Scan/MD1_1/scan_loop.c b/Scan/MD1.1/scan_loop.c similarity index 100% rename from Scan/MD1_1/scan_loop.c rename to Scan/MD1.1/scan_loop.c diff --git a/Scan/MD1_1/scan_loop.h b/Scan/MD1.1/scan_loop.h similarity index 100% rename from Scan/MD1_1/scan_loop.h rename to Scan/MD1.1/scan_loop.h diff --git a/Scan/MD1_1/setup.cmake b/Scan/MD1.1/setup.cmake similarity index 100% rename from Scan/MD1_1/setup.cmake rename to Scan/MD1.1/setup.cmake From 953d5a407b7d7c3ea543dd524be3f352e35dd695 Mon Sep 17 00:00:00 2001 From: CryHam Date: Fri, 19 Feb 2016 18:10:25 +0100 Subject: [PATCH 22/30] Added support for ghosting matrices and code for elimination. To use define GHOST in matrix.h, see example in Scan/CK3 --- Scan/CK3/defaultMap.kll | 85 +++++++++++++++ Scan/CK3/matrix.h | 53 +++++++++ Scan/CK3/pinout | 88 +++++++++++++++ Scan/CK3/prototype.kll | 73 +++++++++++++ Scan/CK3/scan_loop.c | 204 +++++++++++++++++++++++++++++++++++ Scan/CK3/scan_loop.h | 48 +++++++++ Scan/CK3/setup.cmake | 32 ++++++ Scan/MatrixARM/matrix_scan.c | 120 ++++++++++++++++++++- Scan/MatrixARM/matrix_scan.h | 10 ++ 9 files changed, 712 insertions(+), 1 deletion(-) create mode 100644 Scan/CK3/defaultMap.kll create mode 100644 Scan/CK3/matrix.h create mode 100644 Scan/CK3/pinout create mode 100644 Scan/CK3/prototype.kll create mode 100644 Scan/CK3/scan_loop.c create mode 100644 Scan/CK3/scan_loop.h create mode 100644 Scan/CK3/setup.cmake diff --git a/Scan/CK3/defaultMap.kll b/Scan/CK3/defaultMap.kll new file mode 100644 index 0000000..d821d95 --- /dev/null +++ b/Scan/CK3/defaultMap.kll @@ -0,0 +1,85 @@ +Name = CK3; +Version = 0.3; +Author = "Crystal Hammer 2016"; +KLL = 0.3c; + +# Modified Date +Date = 2016-02-19; + + +S0x00 : U"Esc"; +S0x01 : U"1"; +S0x02 : U"2"; +S0x03 : U"3"; +S0x04 : U"4"; +S0x05 : U"5"; +S0x06 : U"6"; +S0x07 : U"7"; +S0x08 : U"8"; +S0x09 : U"9"; +S0x0A : U"0"; +S0x0B : U"Minus"; +S0x0C : U"Equal"; +S0x0D : U"Backslash"; +S0x0E : U"Backtick"; +S0x0F : U"Tab"; +S0x10 : U"Q"; +S0x11 : U"W"; +S0x12 : U"E"; +S0x13 : U"R"; +S0x14 : U"T"; +S0x15 : U"Y"; +S0x16 : U"U"; +S0x17 : U"I"; +S0x18 : U"O"; +S0x19 : U"P"; +S0x1A : U"LBrace"; +S0x1B : U"RBrace"; +S0x1C : U"Backspace"; +S0x1D : U"Ctrl"; +S0x1E : U"A"; +S0x1F : U"S"; +S0x20 : U"D"; +S0x21 : U"F"; +S0x22 : U"G"; +S0x23 : U"H"; +S0x24 : U"J"; +S0x25 : U"K"; +S0x26 : U"L"; +S0x27 : U"Semicolon"; +S0x28 : U"Quote"; +S0x29 : U"Enter"; +S0x2A : U"LShift"; +S0x2B : U"Z"; +S0x2C : U"X"; +S0x2D : U"C"; +S0x2E : U"V"; +S0x2F : U"B"; +S0x30 : U"N"; +S0x31 : U"M"; +S0x32 : U"Comma"; +S0x33 : U"Period"; +S0x34 : U"Slash"; +S0x35 : U"RShift"; +S0x36 : U"Function1"; # Fun key +S0x37 : U"Function2"; # Left Blank Key +S0x38 : U"LAlt"; +S0x39 : U"LGui"; +S0x3A : U"Space"; +S0x3B : U"RGui"; +S0x3C : U"RAlt"; +S0x3D : U"Function3"; # Right Blank Key 1 +S0x3E : U"Function4"; # Right Blank Key 2 + + +# Custom Action Examples + +# Example capability, prints to cli +action1 => CustomAction_action1_capability(); # No arguments + +# Blocks given USB Code, must be used with blockLink +# Simple example, supports only blocking a single key at a time +# Keys must be specified using numbers see Macro/PartialMap/usb_hid.h +blockHold => CustomAction_blockHold_capability( usbCode : 1 ); # Single 8-bit argument +blockKey => CustomAction_blockKey_capability( usbCode : 1 ); + diff --git a/Scan/CK3/matrix.h b/Scan/CK3/matrix.h new file mode 100644 index 0000000..28bd3b0 --- /dev/null +++ b/Scan/CK3/matrix.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Project Includes +#include + + + +// ----- Matrix Definition ----- + +// Freescale ARM MK20's support GPIO PTA, PTB, PTC, PTD and PTE 0..31 +// Not all chips have access to all of these pins (most don't have 160 pins :P) +// +// NOTE: +// Before using a pin, make sure it supports being a GPIO *and* doesn't have a default pull-up/pull-down +// Checking this is completely on the ownness of the user + +// +// Columns (Strobe) // PTB0..3,16,17 PTC4,5 PTD0 +// Rows (Sense) // PTD1..7 + +// Define Rows (Sense) and Columns (Strobes) +GPIO_Pin Matrix_cols[] = { gpio(B,0), gpio(B,1), gpio(B,2), gpio(B,3), gpio(B,16), gpio(B,17), gpio(C,4), gpio(C,6), gpio(D,0) }; +GPIO_Pin Matrix_rows[] = { gpio(D,1), gpio(D,2), gpio(D,3), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7) }; + +// Define type of scan matrix +Config Matrix_type = Config_Pulldown; + + +// define this if your matrix has ghosting (i.e. regular keyboard without diodes) +#define GHOST diff --git a/Scan/CK3/pinout b/Scan/CK3/pinout new file mode 100644 index 0000000..a72c0e6 --- /dev/null +++ b/Scan/CK3/pinout @@ -0,0 +1,88 @@ +Pin Usage +========= + +mk20dx128vlf5 + + ---- +|Keys| + ---- + +* Strobe (Columns) + +PTB0 +PTB1 +PTB2 +PTB3 +PTB16 +PTB17 +PTC4 +PTC5 +PTD0 + + +* Sense (Rows) + +PTD1 +PTD2 +PTD3 +PTD4 +PTD5 +PTD6 +PTD7 + + + ----- +|Debug| + ----- + +* SWD + +PTA0 (Pull-down) +PTA3 (Pull-up) + +* LEDs + +PTA19 (LED only for PCB, not McHCK) (XTAL) + +* UARTs + +PTA1 - RX0 +PTA2 - TX0 + +* Tag Connect + +1 - Vdd +5 +2 - PTA3 / SWD_IO +3 - Vss / Gnd +4 - PTA0 / SWD_CLK +5 - +5V +6 - PTA2 / TRACE_SWO +7 - N/C +8 - PTA1 / JTAG_TDI +9 - N/C +10 - Reset_b + + + ------ +|Unused| + ------ + +* GPIO + +PTA1 (Not broken out on PCB, available on McHCK) (Pull-up) +PTA2 (") +PTA4 (Pull-up) +PTA18 (EXTAL) + +PTC0 +PTC1 +PTC2 +PTC3 +PTC6 +PTC7 + +* Analog + +ADC0_DP0 +ADC0_DM0 + diff --git a/Scan/CK3/prototype.kll b/Scan/CK3/prototype.kll new file mode 100644 index 0000000..64fe862 --- /dev/null +++ b/Scan/CK3/prototype.kll @@ -0,0 +1,73 @@ +Name = MD1; +Version = 0.2; +Author = "HaaTa (Jacob Alexander) 2014"; +KLL = 0.3; + +# Modified Date +Date = 2014-09-14; + + +S0x00 : U"Esc"; +S0x01 : U"1"; +S0x02 : U"2"; +S0x03 : U"3"; +S0x04 : U"4"; +S0x05 : U"5"; +S0x06 : U"6"; +S0x07 : U"7"; +S0x08 : U"8"; +S0x09 : U"9"; +S0x0A : U"0"; +S0x0B : U"Minus"; +S0x0C : U"Equal"; +S0x0D : U"Backslash"; +S0x0E : U"Tab"; +S0x0F : U"Q"; +S0x10 : U"W"; +S0x11 : U"E"; +S0x12 : U"R"; +S0x13 : U"T"; +S0x14 : U"Y"; +S0x15 : U"U"; +S0x16 : U"I"; +S0x17 : U"O"; +S0x18 : U"P"; +S0x19 : U"LBrace"; +S0x1A : U"RBrace"; +S0x1B : U"Backspace"; +S0x1C : U"Ctrl"; +S0x1D : U"A"; +S0x1E : U"S"; +S0x1F : U"D"; +S0x20 : U"F"; +S0x21 : U"G"; +S0x22 : U"H"; +S0x23 : U"J"; +S0x24 : U"K"; +S0x25 : U"L"; +S0x26 : U"Semicolon"; +S0x27 : U"Quote"; +S0x28 : U"Enter"; +S0x29 : U"LShift"; +S0x2A : U"Z"; +S0x2B : U"X"; +S0x2C : U"C"; +S0x2D : U"V"; +S0x2E : U"B"; +S0x2F : U"N"; +S0x30 : U"M"; +S0x31 : U"Comma"; +S0x32 : U"Period"; +S0x33 : U"Slash"; +S0x34 : U"RShift"; +S0x35 : U"Function1"; # Fun key +S0x36 : U"Function2"; # Left Blank Key +S0x37 : U"LAlt"; +S0x38 : U"LGui"; +S0x39 : U"Space"; +S0x3A : U"RGui"; +S0x3B : U"RAlt"; +S0x3C : U"Function3"; # Right Blank Key 1 +S0x3D : U"Function4"; # Right Blank Key 2 +S0x3E : U"BackTick"; + diff --git a/Scan/CK3/scan_loop.c b/Scan/CK3/scan_loop.c new file mode 100644 index 0000000..22d43c2 --- /dev/null +++ b/Scan/CK3/scan_loop.c @@ -0,0 +1,204 @@ +/* Copyright (C) 2014 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include +#include +#include + +// Local Includes +#include "scan_loop.h" + + + +// ----- Function Declarations ----- + +// CLI Functions +void cliFunc_echo( char* args ); + + + +// ----- Variables ----- + +// Scan Module command dictionary +CLIDict_Entry( echo, "Example command, echos the arguments." ); + +CLIDict_Def( scanCLIDict, "Scan Module Commands" ) = { + CLIDict_Item( echo ), + { 0, 0, 0 } // Null entry for dictionary end +}; + +// Number of scans since the last USB send +uint16_t Scan_scanCount = 0; + + + +// ----- Functions ----- + +// Setup +inline void Scan_setup() +{ + // Register Scan CLI dictionary + CLI_registerDictionary( scanCLIDict, scanCLIDictName ); + + // Setup GPIO pins for matrix scanning + Matrix_setup(); + + // Reset scan count + Scan_scanCount = 0; +} + + +// Main Detection Loop +inline uint8_t Scan_loop() +{ + Matrix_scan( Scan_scanCount++ ); + + return 0; +} + + +// Signal from Macro Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithMacro( uint8_t sentKeys ) +{ +} + + +// Signal from Output Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithOutput( uint8_t sentKeys ) +{ + // Reset scan loop indicator (resets each key debounce state) + // TODO should this occur after USB send or Macro processing? + Scan_scanCount = 0; +} + + + +// ----- Capabilities ----- + +// Custom capability examples +// Refer to kll.h in Macros/PartialMap for state and stateType information +void CustomAction_action1_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + // XXX This is required for debug cli to give you a list of capabilities + if ( stateType == 0xFF && state == 0xFF ) + { + print("CustomAction_action1_capability()"); + return; + } + + // Prints Action1 info message to the debug cli + info_print("Action1"); +} + +uint8_t CustomAction_blockHold_storage = 0; +void CustomAction_blockHold_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("CustomAction_blockHold_capability(usbCode)"); + return; + } + + // Retrieve 8-bit argument + uint8_t key = args[0]; + + // We only care about normal keys + if ( stateType == 0x00 ) + { + // Block given key if we're in the "Press" or "Hold" state + if ( ( state == 0x01 || state == 0x02 ) + && CustomAction_blockHold_storage == 0 ) + { + CustomAction_blockHold_storage = key; + info_msg("Blocking Key: "); + printHex( key ); + print( NL ); + } + // Release if in the "Off" or "Release" state and we're blocking + else if ( ( state == 0x00 || state == 0x03 ) + && key == CustomAction_blockHold_storage ) + { + info_msg("Unblocking Key: "); + printHex( CustomAction_blockHold_storage ); + print( NL ); + CustomAction_blockHold_storage = 0; + } + } +} + +void CustomAction_blockKey_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("CustomAction_blockKey_capability(usbCode)"); + return; + } + + // Retrieve 8-bit argument + uint8_t key = args[0]; + + // If key is not blocked, process + if ( key != CustomAction_blockHold_storage ) + { + extern void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ); + Output_usbCodeSend_capability( state, stateType, &key ); + } +} + + + +// ----- CLI Command Functions ----- + +// XXX Just an example command showing how to parse arguments (more complex than generally needed) +void cliFunc_echo( char* args ) +{ + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; + + // Parse args until a \0 is found + while ( 1 ) + { + print( NL ); // No \r\n by default after the command is entered + + curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + break; + + // Print out the arg + dPrint( arg1Ptr ); + } +} + diff --git a/Scan/CK3/scan_loop.h b/Scan/CK3/scan_loop.h new file mode 100644 index 0000000..0c89838 --- /dev/null +++ b/Scan/CK3/scan_loop.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2014-2015 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// ----- Includes ----- + +// Compiler Includes +#include + + + +// ----- Functions ----- + +// Functions to be called by main.c +void Scan_setup( void ); +uint8_t Scan_loop( void ); + +// Call-backs +void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module +void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module + + +// ----- Capabilities ----- + +// Example capabilities +void CustomAction_action1_capability( uint8_t state, uint8_t stateType, uint8_t *args ); +void CustomAction_blockHold_capability( uint8_t state, uint8_t stateType, uint8_t *args ); +void CustomAction_blockKey_capability( uint8_t state, uint8_t stateType, uint8_t *args ); + diff --git a/Scan/CK3/setup.cmake b/Scan/CK3/setup.cmake new file mode 100644 index 0000000..d40a338 --- /dev/null +++ b/Scan/CK3/setup.cmake @@ -0,0 +1,32 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2014 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Required Submodules +# + +AddModule ( Scan MatrixARM ) + + +### +# Module C files +# + +set ( Module_SRCS + scan_loop.c +) + + +### +# Compiler Family Compatibility +# +set ( ModuleCompatibility + arm +) + diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index a9018df..03a4148 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -70,6 +70,15 @@ CLIDict_Def( matrixCLIDict, "Matrix Module Commands" ) = { // Debounce Array KeyState Matrix_scanArray[ Matrix_colsNum * Matrix_rowsNum ]; +// Ghost Arrays +#ifdef GHOST +KeyGhost Matrix_ghostArray[ Matrix_colsNum * Matrix_rowsNum ]; + +uint8_t col_use[Matrix_colsNum], row_use[Matrix_rowsNum]; // used count +uint8_t col_ghost[Matrix_colsNum], row_ghost[Matrix_rowsNum]; // marked as having ghost if 1 +#endif + + // Matrix debug flag - If set to 1, for each keypress the scan code is displayed in hex // If set to 2, for each key state change, the scan code is displayed along with the state uint8_t matrixDebugMode = 0; @@ -111,10 +120,17 @@ uint8_t Matrix_pin( GPIO_Pin gpio, Type type ) { case Type_StrobeOn: *GPIO_PSOR |= (1 << gpio.pin); + #ifdef GHOST + *GPIO_PDDR |= (1 << gpio.pin); // output + #endif break; case Type_StrobeOff: *GPIO_PCOR |= (1 << gpio.pin); + #ifdef GHOST + // Ghosting martix needs to put not used (off) strobes in high impedance state + *GPIO_PDDR &= ~(1 << gpio.pin); // input, high Z state + #endif break; case Type_StrobeSetup: @@ -206,6 +222,11 @@ void Matrix_setup() Matrix_scanArray[ item ].activeCount = 0; Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state Matrix_scanArray[ item ].prevDecisionTime = 0; + #ifdef GHOST + Matrix_ghostArray[ item ].prev = KeyState_Off; + Matrix_ghostArray[ item ].cur = KeyState_Off; + Matrix_ghostArray[ item ].saved = KeyState_Off; + #endif } // Clear scan stats counters @@ -372,12 +393,14 @@ void Matrix_scan( uint16_t scanNum ) erro_print("Matrix scan bug!! Report me!"); break; } - + // Update decision time state->prevDecisionTime = currentTime; // Send keystate to macro module + #ifndef GHOST Macro_keyState( key, state->curState ); + #endif // Matrix Debug, only if there is a state change if ( matrixDebugMode && state->curState != state->prevState ) @@ -403,6 +426,101 @@ void Matrix_scan( uint16_t scanNum ) Matrix_pin( Matrix_cols[ strobe ], Type_StrobeOff ); } + + // Matrix ghosting check and elimination + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +#ifdef GHOST + // strobe = column, sense = row + + // Count (rows) use for columns + //print("C "); + for ( uint8_t col = 0; col < Matrix_colsNum; col++ ) + { + uint8_t used = 0; + for ( uint8_t row = 0; row < Matrix_rowsNum; row++ ) + { + uint8_t key = Matrix_colsNum * row + col; + KeyState *state = &Matrix_scanArray[ key ]; + if ( keyOn(state->curState) ) + used++; + } + //printInt8(used); + col_use[col] = used; + col_ghost[col] = 0; // clear + } + + // Count (columns) use for rows + //print(" R "); + for ( uint8_t row = 0; row < Matrix_rowsNum; row++ ) + { + uint8_t used = 0; + for ( uint8_t col = 0; col < Matrix_colsNum; col++ ) + { + uint8_t key = Matrix_colsNum * row + col; + KeyState *state = &Matrix_scanArray[ key ]; + if ( keyOn(state->curState) ) + used++; + } + //printInt8(used); + row_use[row] = used; + row_ghost[row] = 0; // clear + } + + // Check if matrix has ghost + // Happens when key is pressed and some other key is pressed in same row and another in same column + //print(" G "); + for ( uint8_t col = 0; col < Matrix_colsNum; col++ ) + { + for ( uint8_t row = 0; row < Matrix_rowsNum; row++ ) + { + uint8_t key = Matrix_colsNum * row + col; + KeyState *state = &Matrix_scanArray[ key ]; + if ( keyOn(state->curState) && col_use[col] >= 2 && row_use[row] >= 2 ) + { + // mark col and row as having ghost + col_ghost[col] = 1; + row_ghost[row] = 1; + //print(" "); printInt8(col); print(","); printInt8(row); + } + } + } + //print( NL ); + + // Send keys + for ( uint8_t col = 0; col < Matrix_colsNum; col++ ) + { + for ( uint8_t row = 0; row < Matrix_rowsNum; row++ ) + { + uint8_t key = Matrix_colsNum * row + col; + KeyState *state = &Matrix_scanArray[ key ]; + KeyGhost *st = &Matrix_ghostArray[ key ]; + + // col or row is ghosting (crossed) + uint8_t ghost = (col_ghost[col] > 0 || row_ghost[row] > 0) ? 1 : 0; + + st->prev = st->cur; // previous + // save state if no ghost or outside ghosted area + if ( ghost == 0 ) + st->saved = state->curState; // save state if no ghost + // final + // use saved state if ghosting, or current if not + st->cur = ghost > 0 ? st->saved : state->curState; + + // Send keystate to macro module + KeyPosition k = !st->cur + ? (!st->prev ? KeyState_Off : KeyState_Release) + : ( st->prev ? KeyState_Hold : KeyState_Press); + //if (!st->cur && !st->prev) k = KeyState_Off; else + //if ( st->cur && st->prev) k = KeyState_Hold; else + //if ( st->cur && !st->prev) k = KeyState_Press; else + //if (!st->cur && st->prev) k = KeyState_Release; + Macro_keyState( key, k ); + } + } +#endif + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + // State Table Output Debug if ( matrixDebugStateCounter > 0 ) { diff --git a/Scan/MatrixARM/matrix_scan.h b/Scan/MatrixARM/matrix_scan.h index 810e6d9..ce09bf1 100644 --- a/Scan/MatrixARM/matrix_scan.h +++ b/Scan/MatrixARM/matrix_scan.h @@ -139,6 +139,16 @@ typedef struct KeyState { uint8_t prevDecisionTime; } __attribute__((packed)) KeyState; +// Ghost Element, after ghost detection/cancelation +typedef struct KeyGhost { + KeyPosition prev; + KeyPosition cur; + KeyPosition saved; // state before ghosting +} __attribute__((packed)) KeyGhost; + +// utility +inline uint8_t keyOn(/*KeyPosition*/uint8_t st) +{ return (st == KeyState_Press || st == KeyState_Hold) ? 1 : 0; } // ----- Functions ----- From 7f7c0e8873f2ec761810786dffe022eb7e25de90 Mon Sep 17 00:00:00 2001 From: CryHam Date: Sat, 20 Feb 2016 08:33:39 +0100 Subject: [PATCH 23/30] Minor styling fixes. Renamed define to GHOSTING_MATRIX. Deleted unused files from CK3. --- Scan/CK3/matrix.h | 5 +- Scan/CK3/pinout | 88 ------------------------------------ Scan/CK3/prototype.kll | 73 ------------------------------ Scan/MatrixARM/matrix_scan.c | 14 +++--- Scan/MatrixARM/matrix_scan.h | 6 ++- 5 files changed, 14 insertions(+), 172 deletions(-) delete mode 100644 Scan/CK3/pinout delete mode 100644 Scan/CK3/prototype.kll diff --git a/Scan/CK3/matrix.h b/Scan/CK3/matrix.h index 28bd3b0..1a2be2e 100644 --- a/Scan/CK3/matrix.h +++ b/Scan/CK3/matrix.h @@ -49,5 +49,6 @@ GPIO_Pin Matrix_rows[] = { gpio(D,1), gpio(D,2), gpio(D,3), gpio(D,4), gpio(D,5) Config Matrix_type = Config_Pulldown; -// define this if your matrix has ghosting (i.e. regular keyboard without diodes) -#define GHOST +// Define this if your matrix has ghosting (i.e. regular keyboard without diodes) +// this will enable the anti-ghosting code +#define GHOSTING_MATRIX diff --git a/Scan/CK3/pinout b/Scan/CK3/pinout deleted file mode 100644 index a72c0e6..0000000 --- a/Scan/CK3/pinout +++ /dev/null @@ -1,88 +0,0 @@ -Pin Usage -========= - -mk20dx128vlf5 - - ---- -|Keys| - ---- - -* Strobe (Columns) - -PTB0 -PTB1 -PTB2 -PTB3 -PTB16 -PTB17 -PTC4 -PTC5 -PTD0 - - -* Sense (Rows) - -PTD1 -PTD2 -PTD3 -PTD4 -PTD5 -PTD6 -PTD7 - - - ----- -|Debug| - ----- - -* SWD - -PTA0 (Pull-down) -PTA3 (Pull-up) - -* LEDs - -PTA19 (LED only for PCB, not McHCK) (XTAL) - -* UARTs - -PTA1 - RX0 -PTA2 - TX0 - -* Tag Connect - -1 - Vdd +5 -2 - PTA3 / SWD_IO -3 - Vss / Gnd -4 - PTA0 / SWD_CLK -5 - +5V -6 - PTA2 / TRACE_SWO -7 - N/C -8 - PTA1 / JTAG_TDI -9 - N/C -10 - Reset_b - - - ------ -|Unused| - ------ - -* GPIO - -PTA1 (Not broken out on PCB, available on McHCK) (Pull-up) -PTA2 (") -PTA4 (Pull-up) -PTA18 (EXTAL) - -PTC0 -PTC1 -PTC2 -PTC3 -PTC6 -PTC7 - -* Analog - -ADC0_DP0 -ADC0_DM0 - diff --git a/Scan/CK3/prototype.kll b/Scan/CK3/prototype.kll deleted file mode 100644 index 64fe862..0000000 --- a/Scan/CK3/prototype.kll +++ /dev/null @@ -1,73 +0,0 @@ -Name = MD1; -Version = 0.2; -Author = "HaaTa (Jacob Alexander) 2014"; -KLL = 0.3; - -# Modified Date -Date = 2014-09-14; - - -S0x00 : U"Esc"; -S0x01 : U"1"; -S0x02 : U"2"; -S0x03 : U"3"; -S0x04 : U"4"; -S0x05 : U"5"; -S0x06 : U"6"; -S0x07 : U"7"; -S0x08 : U"8"; -S0x09 : U"9"; -S0x0A : U"0"; -S0x0B : U"Minus"; -S0x0C : U"Equal"; -S0x0D : U"Backslash"; -S0x0E : U"Tab"; -S0x0F : U"Q"; -S0x10 : U"W"; -S0x11 : U"E"; -S0x12 : U"R"; -S0x13 : U"T"; -S0x14 : U"Y"; -S0x15 : U"U"; -S0x16 : U"I"; -S0x17 : U"O"; -S0x18 : U"P"; -S0x19 : U"LBrace"; -S0x1A : U"RBrace"; -S0x1B : U"Backspace"; -S0x1C : U"Ctrl"; -S0x1D : U"A"; -S0x1E : U"S"; -S0x1F : U"D"; -S0x20 : U"F"; -S0x21 : U"G"; -S0x22 : U"H"; -S0x23 : U"J"; -S0x24 : U"K"; -S0x25 : U"L"; -S0x26 : U"Semicolon"; -S0x27 : U"Quote"; -S0x28 : U"Enter"; -S0x29 : U"LShift"; -S0x2A : U"Z"; -S0x2B : U"X"; -S0x2C : U"C"; -S0x2D : U"V"; -S0x2E : U"B"; -S0x2F : U"N"; -S0x30 : U"M"; -S0x31 : U"Comma"; -S0x32 : U"Period"; -S0x33 : U"Slash"; -S0x34 : U"RShift"; -S0x35 : U"Function1"; # Fun key -S0x36 : U"Function2"; # Left Blank Key -S0x37 : U"LAlt"; -S0x38 : U"LGui"; -S0x39 : U"Space"; -S0x3A : U"RGui"; -S0x3B : U"RAlt"; -S0x3C : U"Function3"; # Right Blank Key 1 -S0x3D : U"Function4"; # Right Blank Key 2 -S0x3E : U"BackTick"; - diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index 03a4148..90343fe 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -71,7 +71,7 @@ CLIDict_Def( matrixCLIDict, "Matrix Module Commands" ) = { KeyState Matrix_scanArray[ Matrix_colsNum * Matrix_rowsNum ]; // Ghost Arrays -#ifdef GHOST +#ifdef GHOSTING_MATRIX KeyGhost Matrix_ghostArray[ Matrix_colsNum * Matrix_rowsNum ]; uint8_t col_use[Matrix_colsNum], row_use[Matrix_rowsNum]; // used count @@ -120,14 +120,14 @@ uint8_t Matrix_pin( GPIO_Pin gpio, Type type ) { case Type_StrobeOn: *GPIO_PSOR |= (1 << gpio.pin); - #ifdef GHOST + #ifdef GHOSTING_MATRIX *GPIO_PDDR |= (1 << gpio.pin); // output #endif break; case Type_StrobeOff: *GPIO_PCOR |= (1 << gpio.pin); - #ifdef GHOST + #ifdef GHOSTING_MATRIX // Ghosting martix needs to put not used (off) strobes in high impedance state *GPIO_PDDR &= ~(1 << gpio.pin); // input, high Z state #endif @@ -222,7 +222,7 @@ void Matrix_setup() Matrix_scanArray[ item ].activeCount = 0; Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state Matrix_scanArray[ item ].prevDecisionTime = 0; - #ifdef GHOST + #ifdef GHOSTING_MATRIX Matrix_ghostArray[ item ].prev = KeyState_Off; Matrix_ghostArray[ item ].cur = KeyState_Off; Matrix_ghostArray[ item ].saved = KeyState_Off; @@ -393,12 +393,12 @@ void Matrix_scan( uint16_t scanNum ) erro_print("Matrix scan bug!! Report me!"); break; } - + // Update decision time state->prevDecisionTime = currentTime; // Send keystate to macro module - #ifndef GHOST + #ifndef GHOSTING_MATRIX Macro_keyState( key, state->curState ); #endif @@ -429,7 +429,7 @@ void Matrix_scan( uint16_t scanNum ) // Matrix ghosting check and elimination // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -#ifdef GHOST +#ifdef GHOSTING_MATRIX // strobe = column, sense = row // Count (rows) use for columns diff --git a/Scan/MatrixARM/matrix_scan.h b/Scan/MatrixARM/matrix_scan.h index ce09bf1..8b9cee7 100644 --- a/Scan/MatrixARM/matrix_scan.h +++ b/Scan/MatrixARM/matrix_scan.h @@ -146,9 +146,11 @@ typedef struct KeyGhost { KeyPosition saved; // state before ghosting } __attribute__((packed)) KeyGhost; -// utility +// utility inline uint8_t keyOn(/*KeyPosition*/uint8_t st) -{ return (st == KeyState_Press || st == KeyState_Hold) ? 1 : 0; } +{ + return (st == KeyState_Press || st == KeyState_Hold) ? 1 : 0; +} // ----- Functions ----- From 5ceecce0428a89e1d0d374869e22cfa9a3de6da4 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Tue, 23 Feb 2016 14:35:08 -0800 Subject: [PATCH 24/30] As per request of original author, updating license to MIT --- Scan/DPH/scan_loop.c | 29 +++++++++++++++++------------ Scan/DPH/scan_loop.h | 25 +++++++++++++++---------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/Scan/DPH/scan_loop.c b/Scan/DPH/scan_loop.c index 1a0176c..5d8d832 100644 --- a/Scan/DPH/scan_loop.c +++ b/Scan/DPH/scan_loop.c @@ -1,18 +1,23 @@ -/* Copyright (C) 2011-2013 by Joseph Makuch - * Additions by Jacob Alexander (2013-2014) +/* Copyright (C) 2011-2013 by Joseph Makuch (jmakuch+f@gmail.com) + * Additions by Jacob Alexander (2013-2014) (haata@kiibohd.com) * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * This library 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 - * Lesser General Public License for more details. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. */ // ----- Includes ----- diff --git a/Scan/DPH/scan_loop.h b/Scan/DPH/scan_loop.h index 83a9a1b..234b959 100644 --- a/Scan/DPH/scan_loop.h +++ b/Scan/DPH/scan_loop.h @@ -1,17 +1,22 @@ /* Copyright (C) 2013-2015 by Jacob Alexander * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * This library 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 - * Lesser General Public License for more details. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. */ #pragma once From 62ba0c558bcb34e5560e6c311760927054e82038 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Thu, 25 Feb 2016 23:24:14 -0800 Subject: [PATCH 25/30] Fixing default pixel test mode to use rainbox --- Macro/PixelMap/pixel.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index 067f93a..f44bddd 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -2614,13 +2614,11 @@ inline void Pixel_process() case PixelTest_Pixel_Test: // Start from the top of the Animation Stack // TODO - dbug_print("YSSS"); // XXX Temp - Play rainbow Pixel_pixelProcess( rainbow_frames[rainbow_pos], rainbow_framesizes[rainbow_pos] ); rainbow_pos++; - Pixel_testMode = PixelTest_Off; - if ( rainbow_pos >= sizeof( rainbow_frames ) / 2 ) + if ( rainbow_pos > 33 ) { rainbow_pos = 0; goto pixel_process_done; @@ -2630,22 +2628,6 @@ inline void Pixel_process() break; } - // Start from the top of the Animation Stack - // TODO - - /* - // XXX Temp - Play rainbow - Pixel_pixelProcess( rainbow_frames[rainbow_pos], rainbow_framesizes[rainbow_pos] ); - rainbow_pos++; - Pixel_testMode = PixelTest_Off; - - if ( rainbow_pos >= sizeof( rainbow_framesizes ) / 2 ) - { - rainbow_pos = 0; - } - */ - - pixel_process_done: // Frame is now ready to send Pixel_FrameState = FrameState_Ready; @@ -2661,7 +2643,8 @@ inline void Pixel_setup() Pixel_FrameState = FrameState_Update; // Disable test modes by default, start at position 0 - Pixel_testMode = PixelTest_Off; + Pixel_testMode = PixelTest_Pixel_Test; // TODO Remove when better default available + //Pixel_testMode = PixelTest_Off; // Clear animation stack Pixel_AnimationStack.size = 0; From aaae9bc0f25dce3984392b2c71987ddaa7b2f108 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sun, 21 Feb 2016 19:56:52 -0800 Subject: [PATCH 26/30] Adding dynamic USB power support - Each scan module now has a current change callback which passes the available current as a parameter - No longer attempts to use the max 500 mA immediately, starts with 100 mA then goes to 500 mA after enumeration - If enumeration fails due to bMaxPower of 500 mA, then attempt again at 100 mA (might also be possible to go even lower to 20 mA in certain cases) - Now working with the Apple Ipad (no over-power messages) - Fixed Wake-up behaviour on Apple Ipad (and likely other iOS devices) - More effecient set_feature/clear_feature handling (device handler) - Initial power handling via Interconnect (still needs work to get it more dynamic) --- Bootloader/dfu.desc.c | 4 +- Bootloader/main.c | 10 ++- Output/pjrcUSB/arm/usb_desc.c | 6 +- Output/pjrcUSB/arm/usb_desc.h | 4 +- Output/pjrcUSB/arm/usb_dev.c | 121 ++++++++++++++++++++++++++++++-- Output/pjrcUSB/arm/usb_dev.h | 1 + Output/pjrcUSB/output_com.c | 80 ++++++++++++++++++++- Output/pjrcUSB/output_com.h | 10 ++- Output/usbMuxUart/output_com.c | 80 ++++++++++++++++++++- Scan/ISSILed/led_scan.c | 50 +++++++++++-- Scan/ISSILed/led_scan.h | 4 +- Scan/KType/scan_loop.c | 14 +++- Scan/KType/scan_loop.h | 8 ++- Scan/MD1.1/scan_loop.c | 12 +++- Scan/MD1.1/scan_loop.h | 4 +- Scan/MD1/scan_loop.c | 11 ++- Scan/MD1/scan_loop.h | 4 +- Scan/MDErgo1/scan_loop.c | 14 +++- Scan/MDErgo1/scan_loop.h | 8 ++- Scan/MatrixARM/matrix_scan.c | 25 ++++--- Scan/MatrixARM/matrix_scan.h | 4 +- Scan/PortSwap/port_scan.c | 8 +++ Scan/PortSwap/port_scan.h | 4 +- Scan/STLcd/lcd_scan.c | 10 ++- Scan/STLcd/lcd_scan.h | 4 +- Scan/UARTConnect/connect_scan.c | 31 +++++++- Scan/UARTConnect/connect_scan.h | 4 +- Scan/WhiteFox/scan_loop.c | 12 +++- Scan/WhiteFox/scan_loop.h | 4 +- 29 files changed, 503 insertions(+), 48 deletions(-) diff --git a/Bootloader/dfu.desc.c b/Bootloader/dfu.desc.c index dc11fef..a0ce1f8 100644 --- a/Bootloader/dfu.desc.c +++ b/Bootloader/dfu.desc.c @@ -1,5 +1,5 @@ // Originally Generated from MCHCK Toolkit -/* Copyright (c) Jacob Alexander 2014-2015 +/* Copyright (c) Jacob Alexander 2014-2016 * * 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 @@ -38,7 +38,7 @@ static const struct usb_config_1 usb_config_1 = { .bConfigurationValue = 1, .iConfiguration = 0, .one = 1, - .bMaxPower = 100 + .bMaxPower = 50 }, .usb_function_0 = { .iface = { diff --git a/Bootloader/main.c b/Bootloader/main.c index 124e82d..d939775 100644 --- a/Bootloader/main.c +++ b/Bootloader/main.c @@ -1,5 +1,5 @@ /* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>. - * Modifications by Jacob Alexander 2014-2015 + * Modifications by Jacob Alexander 2014-2016 * * 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 @@ -241,8 +241,11 @@ void main() GPIOA_PCOR |= (1<<13); #define USBPortSwapDelay_ms 1000 + #define USBPortSwapIncrement_ms 100 // For keyboards with dual usb ports, doesn't do anything on keyboards without them - // If a USB connection is not detected in 2 seconds, switch to the other port to see if it's plugged in there + // If a USB connection is not detected in 1 second, switch to the other port to see if it's plugged in there + // Incremement the delay by 100 ms each attempt, just in case the device is slow + uint32_t attempt = 0; uint32_t last_ms = systick_millis_count; for (;;) { @@ -250,7 +253,7 @@ void main() // Only check for swapping after delay uint32_t wait_ms = systick_millis_count - last_ms; - if ( wait_ms < USBPortSwapDelay_ms ) + if ( wait_ms < USBPortSwapDelay_ms + attempt * USBPortSwapIncrement_ms ) { continue; } @@ -262,6 +265,7 @@ void main() { print("USB not initializing, port swapping (if supported)"); GPIOA_PTOR |= (1<<13); + attempt++; } } #else diff --git a/Output/pjrcUSB/arm/usb_desc.c b/Output/pjrcUSB/arm/usb_desc.c index b7cb735..1d9a939 100644 --- a/Output/pjrcUSB/arm/usb_desc.c +++ b/Output/pjrcUSB/arm/usb_desc.c @@ -1,7 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. - * Modified by Jacob Alexander (2013-2015) + * Modified by Jacob Alexander (2013-2016) * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -451,7 +451,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { 1, // bConfigurationValue 0, // iConfiguration 0xA0, // bmAttributes - 250, // bMaxPower + 250, // bMaxPower - Entry Index 8 // --- Keyboard HID --- Boot Mode Keyboard Interface // - 9 bytes - @@ -695,6 +695,8 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { SYS_CTRL_INTERVAL, // bInterval }; +uint8_t *usb_bMaxPower = &config_descriptor[8]; + // ----- String Descriptors ----- diff --git a/Output/pjrcUSB/arm/usb_desc.h b/Output/pjrcUSB/arm/usb_desc.h index 33c6589..0e769a1 100644 --- a/Output/pjrcUSB/arm/usb_desc.h +++ b/Output/pjrcUSB/arm/usb_desc.h @@ -1,7 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. - * Modified by Jacob Alexander (2013-2015) + * Modified by Jacob Alexander (2013-2016) * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -137,3 +137,5 @@ extern const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS]; extern const usb_descriptor_list_t usb_descriptor_list[]; +extern uint8_t *usb_bMaxPower; + diff --git a/Output/pjrcUSB/arm/usb_dev.c b/Output/pjrcUSB/arm/usb_dev.c index 174fe8d..48baa14 100644 --- a/Output/pjrcUSB/arm/usb_dev.c +++ b/Output/pjrcUSB/arm/usb_dev.c @@ -1,7 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. - * Modifications by Jacob Alexander (2013-2015) + * Modifications by Jacob Alexander (2013-2016) * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -168,6 +168,9 @@ volatile uint8_t usb_reboot_timer = 0; static uint8_t reply_buffer[8]; +static uint8_t power_neg_delay; +static uint32_t power_neg_time; + // ----- Functions ----- @@ -188,6 +191,34 @@ static void endpoint0_transmit( const void *data, uint32_t len ) ep0_tx_bdt_bank ^= 1; } +// Used to check any USB state changes that may not have a proper interrupt +// Called once per scan loop, should take minimal processing time or it may affect other modules +void usb_device_check() +{ + // Check to see if we're still waiting for the next USB request after Get Configuration Descriptor + // If still waiting, restart the USB initialization with a lower power requirement + if ( power_neg_delay ) + { + // Check if 100 ms has elapsed + if ( systick_millis_count - power_neg_time > 100 ) + { + // Update bMaxPower + // The value set is in increments of 2 mA + // So 50 * 2 mA = 100 mA + // XXX Currently only transitions to 100 mA + // It may be possible to transition down again to 20 mA + *usb_bMaxPower = 50; + + // Re-initialize USB + power_neg_delay = 0; + usb_configuration = 0; // Clear USB configuration if we have one + USB0_CONTROL = 0; // Disable D+ Pullup to simulate disconnect + delay(10); // Delay is necessary to simulate disconnect + usb_init(); + } + } +} + static void usb_setup() { const uint8_t *data = NULL; @@ -199,6 +230,13 @@ static void usb_setup() const uint8_t *cfg; int i; + // If another request is made, disable the power negotiation check + // See GET_DESCRIPTOR - Configuration + if ( power_neg_delay ) + { + power_neg_delay = 0; + } + switch ( setup.wRequestAndType ) { case 0x0500: // SET_ADDRESS @@ -212,6 +250,10 @@ static void usb_setup() Output_Available = usb_configuration; reg = &USB0_ENDPT1; cfg = usb_endpoint_config_table; + + // Now configured so we can utilize bMaxPower now + Output_update_usb_current( *usb_bMaxPower * 2 ); + // clear all BDT entries, free any allocated memory... for ( i = 4; i < ( NUM_ENDPOINTS + 1) * 4; i++ ) { @@ -324,9 +366,27 @@ static void usb_setup() goto send; case 0x0100: // CLEAR_FEATURE (device) + switch ( setup.wValue ) + { + // CLEAR_FEATURE(DEVICE_REMOTE_WAKEUP) + // See SET_FEATURE(DEVICE_REMOTE_WAKEUP) for details + case 0x1: + goto send; + } + + warn_msg("SET_FEATURE - Device wValue("); + printHex( setup.wValue ); + print( ")" NL ); + endpoint0_stall(); + return; + case 0x0101: // CLEAR_FEATURE (interface) // TODO: Currently ignoring, perhaps useful? -HaaTa - warn_print("CLEAR_FEATURE - Device/Interface"); + warn_msg("CLEAR_FEATURE - Interface wValue("); + printHex( setup.wValue ); + print(") wIndex("); + printHex( setup.wIndex ); + print( ")" NL ); endpoint0_stall(); return; @@ -342,9 +402,30 @@ static void usb_setup() goto send; case 0x0300: // SET_FEATURE (device) + switch ( setup.wValue ) + { + // SET_FEATURE(DEVICE_REMOTE_WAKEUP) + // XXX: Only used to confirm Remote Wake + // Used on Mac OSX and Windows not on Linux + // Good post on the behaviour: + // http://community.silabs.com/t5/8-bit-MCU/Remote-wakeup-HID/m-p/74957#M30802 + case 0x1: + goto send; + } + + warn_msg("SET_FEATURE - Device wValue("); + printHex( setup.wValue ); + print( ")" NL ); + endpoint0_stall(); + return; + case 0x0301: // SET_FEATURE (interface) // TODO: Currently ignoring, perhaps useful? -HaaTa - warn_print("SET_FEATURE - Device/Interface"); + warn_msg("SET_FEATURE - Interface wValue("); + printHex( setup.wValue ); + print(") wIndex("); + printHex( setup.wIndex ); + print( ")" NL ); endpoint0_stall(); return; @@ -385,6 +466,27 @@ static void usb_setup() { datalen = list->length; } + + // XXX Power negotiation hack -HaaTa + // Some devices such as the Apple Ipad do not support bMaxPower greater than 100 mA + // However, there is no provision in the basic USB 2.0 stack for power negotiation + // To get around this: + // * Attempt to set bMaxPower to 500 mA first + // * If more than 100 ms passes since retrieving a Get Configuration Descriptor + // (Descriptor with bMaxPower in it) + // * Change usb_bMaxPower to 50 (100 mA) + // * Restart the USB init process + // According to notes online, it says that some Apple devices can only do 20 mA + // However, in my testing this hasn't been the case + // (you can also draw as much current as you want if you just lie in the descriptor :P) + // If this becomes an issue we can use this hack a second time to negotiate down to 20 mA + // (which should be fine for just the mcu) + if ( setup.wValue == 0x0200 && setup.wIndex == 0x0 ) + { + power_neg_delay = 1; + power_neg_time = systick_millis_count; + } + #if UART_DEBUG print("Desc found, "); printHex32( (uint32_t)data ); @@ -862,6 +964,11 @@ void usb_rx_memory( usb_packet_t *packet ) void usb_tx( uint32_t endpoint, usb_packet_t *packet ) { + // Since we are transmitting data, USB will be brought out of sleep/suspend + // if it's in that state + // Use the currently set descriptor value + Output_update_usb_current( *usb_bMaxPower * 2 ); + bdt_t *b = &table[ index( endpoint, TX, EVEN ) ]; uint8_t next; @@ -1161,9 +1268,12 @@ restart: USB0_ISTAT = USB_ISTAT_ERROR; } + // USB Host signalling device to enter 'sleep' state + // The USB Module triggers this interrupt when it detects the bus has been idle for 3 ms if ( (status & USB_ISTAT_SLEEP /* 10 */ ) ) { - //serial_print("sleep\n"); + info_print("Host has requested USB sleep/suspend state"); + Output_update_usb_current( 100 ); // Set to 100 mA USB0_ISTAT = USB_ISTAT_SLEEP; } } @@ -1223,6 +1333,9 @@ uint8_t usb_init() // enable d+ pullup USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; + // Do not check for power negotiation delay until Get Configuration Descriptor + power_neg_delay = 0; + return 1; } diff --git a/Output/pjrcUSB/arm/usb_dev.h b/Output/pjrcUSB/arm/usb_dev.h index 0f445de..827f843 100644 --- a/Output/pjrcUSB/arm/usb_dev.h +++ b/Output/pjrcUSB/arm/usb_dev.h @@ -81,6 +81,7 @@ static inline uint32_t usb_rx_byte_count(uint32_t endpoint) } void usb_device_reload(); +void usb_device_check(); extern void usb_serial_flush_callback(); diff --git a/Output/pjrcUSB/output_com.c b/Output/pjrcUSB/output_com.c index 2e97e42..b18bbdb 100644 --- a/Output/pjrcUSB/output_com.c +++ b/Output/pjrcUSB/output_com.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2015 by Jacob Alexander +/* Copyright (C) 2011-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -137,6 +137,14 @@ volatile uint8_t Output_Available = 0; // 1 - Debug enabled uint8_t Output_DebugMode = 0; +// mA - Set by outside module if not using USB (i.e. Interconnect) +// Generally set to 100 mA (low power) or 500 mA (high power) +uint16_t Output_ExtCurrent_Available = 0; + +// mA - Set by USB module (if exists) +// Initially 100 mA, but may be negotiated higher (e.g. 500 mA) +uint16_t Output_USBCurrent_Available = 0; + // ----- Capabilities ----- @@ -535,6 +543,10 @@ inline void Output_setup() // USB Data Send inline void Output_send() { + // USB status checks + // Non-standard USB state manipulation, usually does nothing + usb_device_check(); + // Boot Mode Only, unset stale keys if ( USBKeys_Protocol == 0 ) for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) @@ -614,6 +626,72 @@ inline void Output_softReset() } +// Update USB current (mA) +// Triggers power change event +void Output_update_usb_current( unsigned int current ) +{ + // Only signal if changed + if ( current == Output_USBCurrent_Available ) + return; + + // Update USB current + Output_USBCurrent_Available = current; + + unsigned int total_current = Output_current_available(); + info_msg("USB Available Current Changed. Total Available: "); + printInt32( total_current ); + print(" mA" NL); + + // Send new total current to the Scan Modules + Scan_currentChange( Output_current_available() ); +} + + +// Update external current (mA) +// Triggers power change event +void Output_update_external_current( unsigned int current ) +{ + // Only signal if changed + if ( current == Output_ExtCurrent_Available ) + return; + + // Update external current + Output_ExtCurrent_Available = current; + + unsigned int total_current = Output_current_available(); + info_msg("External Available Current Changed. Total Available: "); + printInt32( total_current ); + print(" mA" NL); + + // Send new total current to the Scan Modules + Scan_currentChange( Output_current_available() ); +} + + +// Power/Current Available +unsigned int Output_current_available() +{ + unsigned int total_current = 0; + + // Check for USB current source + total_current += Output_USBCurrent_Available; + + // Check for external current source + total_current += Output_ExtCurrent_Available; + + // XXX If the total available current is still 0 + // Set to 100 mA, which is generally a safe assumption at startup + // before we've been able to determine actual available current + if ( total_current == 0 ) + { + total_current = 100; + } + + return total_current; +} + + + // ----- CLI Command Functions ----- void cliFunc_kbdProtocol( char* args ) diff --git a/Output/pjrcUSB/output_com.h b/Output/pjrcUSB/output_com.h index c82ed98..2448683 100644 --- a/Output/pjrcUSB/output_com.h +++ b/Output/pjrcUSB/output_com.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013-2015 by Jacob Alexander +/* Copyright (C) 2013-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -82,6 +82,8 @@ extern volatile uint8_t Output_Available; // 0 - Output module not fully functi extern uint8_t Output_DebugMode; // 0 - Debug disabled, 1 - Debug enabled +extern uint16_t Output_ExtCurrent_Available; // mA - Set by outside module if not using USB (i.e. Interconnect) + // ----- Functions ----- @@ -97,6 +99,12 @@ void Output_softReset(); // Relies on USB serial module unsigned int Output_availablechar(); +// Returns the total mA available (total, if used in a chain, each device will have to use a slice of it) +unsigned int Output_current_available(); + +void Output_update_external_current( unsigned int current ); +void Output_update_usb_current( unsigned int current ); + int Output_getchar(); int Output_putchar( char c ); int Output_putstr( char* str ); diff --git a/Output/usbMuxUart/output_com.c b/Output/usbMuxUart/output_com.c index 44c5b49..55c9553 100644 --- a/Output/usbMuxUart/output_com.c +++ b/Output/usbMuxUart/output_com.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -143,6 +143,14 @@ volatile uint8_t Output_Available = 0; // 1 - Debug enabled uint8_t Output_DebugMode = 0; +// mA - Set by outside module if not using USB (i.e. Interconnect) +// Generally set to 100 mA (low power) or 500 mA (high power) +uint16_t Output_ExtCurrent_Available = 0; + +// mA - Set by USB module (if exists) +// Initially 100 mA, but may be negotiated higher (e.g. 500 mA) +uint16_t Output_USBCurrent_Available = 0; + // ----- Capabilities ----- @@ -544,6 +552,10 @@ inline void Output_setup() // USB Data Send inline void Output_send() { + // USB status checks + // Non-standard USB state manipulation, usually does nothing + usb_device_check(); + // Boot Mode Only, unset stale keys if ( USBKeys_Protocol == 0 ) for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) @@ -641,6 +653,72 @@ inline void Output_softReset() } +// Update USB current (mA) +// Triggers power change event +void Output_update_usb_current( unsigned int current ) +{ + // Only signal if changed + if ( current == Output_USBCurrent_Available ) + return; + + // Update USB current + Output_USBCurrent_Available = current; + + unsigned int total_current = Output_current_available(); + info_msg("USB Available Current Changed. Total Available: "); + printInt32( total_current ); + print(" mA" NL); + + // Send new total current to the Scan Modules + Scan_currentChange( Output_current_available() ); +} + + +// Update external current (mA) +// Triggers power change event +void Output_update_external_current( unsigned int current ) +{ + // Only signal if changed + if ( current == Output_ExtCurrent_Available ) + return; + + // Update external current + Output_ExtCurrent_Available = current; + + unsigned int total_current = Output_current_available(); + info_msg("External Available Current Changed. Total Available: "); + printInt32( total_current ); + print(" mA" NL); + + // Send new total current to the Scan Modules + Scan_currentChange( Output_current_available() ); +} + + +// Power/Current Available +unsigned int Output_current_available() +{ + unsigned int total_current = 0; + + // Check for USB current source + total_current += Output_USBCurrent_Available; + + // Check for external current source + total_current += Output_ExtCurrent_Available; + + // XXX If the total available current is still 0 + // Set to 100 mA, which is generally a safe assumption at startup + // before we've been able to determine actual available current + if ( total_current == 0 ) + { + total_current = 100; + } + + return total_current; +} + + + // ----- CLI Command Functions ----- void cliFunc_kbdProtocol( char* args ) diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index 6de94e8..ef7b716 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -383,11 +383,17 @@ void LED_reset() LED_writeReg( addr, 0x00, 0x08, 0x0B ); } - // Disable Software shutdown of ISSI chip - for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + // Do not disable software shutdown of ISSI chip unless current is high enough + // Require at least 150 mA + // May be enabled/disabled at a later time + if ( Output_current_available() >= 150 ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + // Disable Software shutdown of ISSI chip + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + } } } @@ -509,8 +515,35 @@ void LED_linkedSend() // LED State processing loop uint32_t LED_timePrev = 0; +unsigned int LED_currentEvent = 0; inline void LED_scan() { + // Check for current change event + if ( LED_currentEvent ) + { + // TODO dim LEDs in low power mode instead of shutting off + if ( LED_currentEvent < 150 ) + { + // Enable Software shutdown of ISSI chip + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_writeReg( addr, 0x0A, 0x00, 0x0B ); + } + } + else + { + // Disable Software shutdown of ISSI chip + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + } + } + + LED_currentEvent = 0; + } + // Check to see if frame buffers are ready to replenish if ( LED_FrameBufferReset ) { @@ -585,6 +618,15 @@ inline void LED_scan() } +// Called by parent Scan Module whenver the available current has changed +// current - mA +void LED_currentChange( unsigned int current ) +{ + // Delay action till next LED scan loop (as this callback sometimes occurs during interrupt requests) + LED_currentEvent = current; +} + + // ----- Capabilities ----- diff --git a/Scan/ISSILed/led_scan.h b/Scan/ISSILed/led_scan.h index b89531e..7352e72 100644 --- a/Scan/ISSILed/led_scan.h +++ b/Scan/ISSILed/led_scan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,3 +34,5 @@ extern uint8_t LED_FrameBuffersReady; void LED_setup(); void LED_scan(); +void LED_currentChange( unsigned int current ); + diff --git a/Scan/KType/scan_loop.c b/Scan/KType/scan_loop.c index 3f20cd9..898c1fe 100644 --- a/Scan/KType/scan_loop.c +++ b/Scan/KType/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 by Jacob Alexander +/* Copyright (C) 2015-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -111,3 +111,15 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) Scan_scanCount = 0; } + +// Signal from the Output Module that the available current has changed +// current - mA +void Scan_currentChange( unsigned int current ) +{ + // Indicate to all submodules current change + Connect_currentChange( current ); + Port_currentChange( current ); + Matrix_currentChange( current ); + LED_currentChange( current ); +} + diff --git a/Scan/KType/scan_loop.h b/Scan/KType/scan_loop.h index 17a06fc..b18a0ca 100644 --- a/Scan/KType/scan_loop.h +++ b/Scan/KType/scan_loop.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,10 +31,12 @@ // ----- Functions ----- // Functions to be called by main.c -void Scan_setup( void ); -uint8_t Scan_loop( void ); +void Scan_setup(); +uint8_t Scan_loop(); // Call-backs void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module +void Scan_currentChange( unsigned int current ); // Called by Output Module + diff --git a/Scan/MD1.1/scan_loop.c b/Scan/MD1.1/scan_loop.c index 74218a0..3b2bad1 100644 --- a/Scan/MD1.1/scan_loop.c +++ b/Scan/MD1.1/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014,2016 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -90,6 +90,16 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) } +// Signal from the Output Module that the available current has changed +// current - mA +void Scan_currentChange( unsigned int current ) +{ + // Indicate to all submodules current change + Matrix_currentChange( current ); + LED_currentChange( current ); +} + + // ----- Capabilities ----- diff --git a/Scan/MD1.1/scan_loop.h b/Scan/MD1.1/scan_loop.h index 0c89838..339ede5 100644 --- a/Scan/MD1.1/scan_loop.h +++ b/Scan/MD1.1/scan_loop.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,6 +38,8 @@ uint8_t Scan_loop( void ); void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module +void Scan_currentChange( unsigned int current ); // Called by Output Module + // ----- Capabilities ----- diff --git a/Scan/MD1/scan_loop.c b/Scan/MD1/scan_loop.c index 22d43c2..d9348e1 100644 --- a/Scan/MD1/scan_loop.c +++ b/Scan/MD1/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -175,6 +175,15 @@ void CustomAction_blockKey_capability( uint8_t state, uint8_t stateType, uint8_t } +// Signal from the Output Module that the available current has changed +// current - mA +void Scan_currentChange( unsigned int current ) +{ + // Indicate to all submodules current change + Matrix_currentChange( current ); +} + + // ----- CLI Command Functions ----- diff --git a/Scan/MD1/scan_loop.h b/Scan/MD1/scan_loop.h index 0c89838..339ede5 100644 --- a/Scan/MD1/scan_loop.h +++ b/Scan/MD1/scan_loop.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,6 +38,8 @@ uint8_t Scan_loop( void ); void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module +void Scan_currentChange( unsigned int current ); // Called by Output Module + // ----- Capabilities ----- diff --git a/Scan/MDErgo1/scan_loop.c b/Scan/MDErgo1/scan_loop.c index d5e97e5..e80119b 100644 --- a/Scan/MDErgo1/scan_loop.c +++ b/Scan/MDErgo1/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -102,3 +102,15 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) Scan_scanCount = 0; } + +// Signal from the Output Module that the available current has changed +// current - mA +void Scan_currentChange( unsigned int current ) +{ + // Indicate to all submodules current change + Connect_currentChange( current ); + Matrix_currentChange( current ); + LED_currentChange( current ); + LCD_currentChange( current ); +} + diff --git a/Scan/MDErgo1/scan_loop.h b/Scan/MDErgo1/scan_loop.h index 17a06fc..b18a0ca 100644 --- a/Scan/MDErgo1/scan_loop.h +++ b/Scan/MDErgo1/scan_loop.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,10 +31,12 @@ // ----- Functions ----- // Functions to be called by main.c -void Scan_setup( void ); -uint8_t Scan_loop( void ); +void Scan_setup(); +uint8_t Scan_loop(); // Call-backs void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module +void Scan_currentChange( unsigned int current ); // Called by Output Module + diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index 90343fe..017161d 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -428,7 +428,7 @@ void Matrix_scan( uint16_t scanNum ) // Matrix ghosting check and elimination - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #ifdef GHOSTING_MATRIX // strobe = column, sense = row @@ -465,7 +465,7 @@ void Matrix_scan( uint16_t scanNum ) row_use[row] = used; row_ghost[row] = 0; // clear } - + // Check if matrix has ghost // Happens when key is pressed and some other key is pressed in same row and another in same column //print(" G "); @@ -494,10 +494,10 @@ void Matrix_scan( uint16_t scanNum ) uint8_t key = Matrix_colsNum * row + col; KeyState *state = &Matrix_scanArray[ key ]; KeyGhost *st = &Matrix_ghostArray[ key ]; - + // col or row is ghosting (crossed) uint8_t ghost = (col_ghost[col] > 0 || row_ghost[row] > 0) ? 1 : 0; - + st->prev = st->cur; // previous // save state if no ghost or outside ghosted area if ( ghost == 0 ) @@ -505,9 +505,9 @@ void Matrix_scan( uint16_t scanNum ) // final // use saved state if ghosting, or current if not st->cur = ghost > 0 ? st->saved : state->curState; - + // Send keystate to macro module - KeyPosition k = !st->cur + KeyPosition k = !st->cur ? (!st->prev ? KeyState_Off : KeyState_Release) : ( st->prev ? KeyState_Hold : KeyState_Press); //if (!st->cur && !st->prev) k = KeyState_Off; else @@ -518,7 +518,7 @@ void Matrix_scan( uint16_t scanNum ) } } #endif - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // State Table Output Debug @@ -567,6 +567,15 @@ void Matrix_scan( uint16_t scanNum ) } +// Called by parent scan module whenever the available current changes +// current - mA +void Matrix_currentChange( unsigned int current ) +{ + // TODO - Any potential power savings? +} + + + // ----- CLI Command Functions ----- void cliFunc_matrixDebug ( char* args ) diff --git a/Scan/MatrixARM/matrix_scan.h b/Scan/MatrixARM/matrix_scan.h index 8b9cee7..3a8f0e2 100644 --- a/Scan/MatrixARM/matrix_scan.h +++ b/Scan/MatrixARM/matrix_scan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -158,3 +158,5 @@ inline uint8_t keyOn(/*KeyPosition*/uint8_t st) void Matrix_setup(); void Matrix_scan( uint16_t scanNum ); +void Matrix_currentChange( unsigned int current ); + diff --git a/Scan/PortSwap/port_scan.c b/Scan/PortSwap/port_scan.c index 40efc9a..cf5a69e 100644 --- a/Scan/PortSwap/port_scan.c +++ b/Scan/PortSwap/port_scan.c @@ -144,6 +144,14 @@ inline uint8_t Port_scan() } +// Signal from parent Scan Module that available current has changed +// current - mA +void Port_currentChange( unsigned int current ) +{ + // TODO - Power savings? +} + + // ----- Capabilities ----- diff --git a/Scan/PortSwap/port_scan.h b/Scan/PortSwap/port_scan.h index 0e6cb2f..5d0fd2d 100644 --- a/Scan/PortSwap/port_scan.h +++ b/Scan/PortSwap/port_scan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 by Jacob Alexander +/* Copyright (C) 2015-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,3 +28,5 @@ void Port_setup(); uint8_t Port_scan(); +void Port_currentChange( unsigned int current ); // Called by Output Module + diff --git a/Scan/STLcd/lcd_scan.c b/Scan/STLcd/lcd_scan.c index c4bf080..1dd9126 100644 --- a/Scan/STLcd/lcd_scan.c +++ b/Scan/STLcd/lcd_scan.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 by Jacob Alexander +/* Copyright (C) 2015-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -346,6 +346,14 @@ inline uint8_t LCD_scan() } +// Signal from parent Scan Module that available current has changed +// current - mA +void LCD_currentChange( unsigned int current ) +{ + // TODO - Power savings? +} + + // ----- Capabilities ----- diff --git a/Scan/STLcd/lcd_scan.h b/Scan/STLcd/lcd_scan.h index 36884a2..096107b 100644 --- a/Scan/STLcd/lcd_scan.h +++ b/Scan/STLcd/lcd_scan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 by Jacob Alexander +/* Copyright (C) 2015-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,3 +28,5 @@ void LCD_setup(); uint8_t LCD_scan(); +void LCD_currentChange( unsigned int current ); + diff --git a/Scan/UARTConnect/connect_scan.c b/Scan/UARTConnect/connect_scan.c index 55f6619..4c56c3c 100644 --- a/Scan/UARTConnect/connect_scan.c +++ b/Scan/UARTConnect/connect_scan.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -470,6 +470,14 @@ uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8 } else { + // Lower current requirement during errors + // USB minimum + // Only if this is not the master node + if ( Connect_id != 0 ) + { + Output_update_external_current( 100 ); + } + Connect_cableFaultsMaster++; Connect_cableOkMaster = 0; print(" Master "); @@ -489,6 +497,12 @@ uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8 } else { + // If we already have an Id, then set max current again + if ( Connect_id != 255 && Connect_id != 0 ) + { + // TODO reset to original negotiated current + Output_update_external_current( 500 ); + } Connect_cableChecksMaster++; } } @@ -560,6 +574,14 @@ uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint // Send reponse back to master Connect_send_IdReport( id ); + // Node now enumerated, set external power to USB Max + // Only set if this is not the master node + // TODO Determine power slice for each node as part of protocol + if ( Connect_id != 0 ) + { + Output_update_external_current( 500 ); + } + // Propogate next Id if the connection is ok if ( Connect_cableOkSlave ) { @@ -1177,6 +1199,13 @@ void Connect_scan() } +// Called by parent Scan module whenever the available current changes +void Connect_currentChange( unsigned int current ) +{ + // TODO - Any potential power saving here? +} + + // ----- CLI Command Functions ----- diff --git a/Scan/UARTConnect/connect_scan.h b/Scan/UARTConnect/connect_scan.h index 389dce7..3aafdf1 100644 --- a/Scan/UARTConnect/connect_scan.h +++ b/Scan/UARTConnect/connect_scan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -168,3 +168,5 @@ void Connect_reset(); void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes ); void Connect_send_RemoteCapability( uint8_t id, uint8_t capabilityIndex, uint8_t state, uint8_t stateType, uint8_t numArgs, uint8_t *args ); +void Connect_currentChange( unsigned int current ); + diff --git a/Scan/WhiteFox/scan_loop.c b/Scan/WhiteFox/scan_loop.c index cac143b..6b54a65 100644 --- a/Scan/WhiteFox/scan_loop.c +++ b/Scan/WhiteFox/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -97,3 +97,13 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) Scan_scanCount = 0; } + +// Signal from the Output Module that the available current has changed +// current - mA +void Scan_currentChange( unsigned int current ) +{ + // Indicate to all submodules current change + Matrix_currentChange( current ); + LED_currentChange( current ); +} + diff --git a/Scan/WhiteFox/scan_loop.h b/Scan/WhiteFox/scan_loop.h index 17a06fc..9e9a8f1 100644 --- a/Scan/WhiteFox/scan_loop.h +++ b/Scan/WhiteFox/scan_loop.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,3 +38,5 @@ uint8_t Scan_loop( void ); void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module +void Scan_currentChange( unsigned int current ); // Called by Output Module + From 2a745b59c0c5facfda490b26146c18f4726607bb Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Mon, 25 Apr 2016 23:26:27 -0700 Subject: [PATCH 27/30] Adding hard-coded underlighting support for KType - Adds 32 channels of RGB leds - Increases buffer pages to 4 - Increases max channels to 576 --- Macro/PixelMap/pixel.c | 43 +++++++++++++++++++++++++++++++++++---- Scan/KType/defaultMap.kll | 24 +++++++++++----------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index f44bddd..09243ae 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -100,17 +100,18 @@ extern LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; // Buffer list -#define Pixel_BuffersLen 3 -#define Pixel_TotalChannels 432 +#define Pixel_BuffersLen 4 +#define Pixel_TotalChannels 576 PixelBuf Pixel_Buffers[] = { PixelBufElem( LED_BufferLength, 16, 0, LED_pageBuffer[0].buffer ), PixelBufElem( LED_BufferLength, 16, 144, LED_pageBuffer[1].buffer ), PixelBufElem( LED_BufferLength, 16, 288, LED_pageBuffer[2].buffer ), + PixelBufElem( LED_BufferLength, 16, 432, LED_pageBuffer[3].buffer ), }; // Pixel Mapping -#define Pixel_TotalPixels 95 // TODO Generate +#define Pixel_TotalPixels 128 // TODO Generate PixelElement Pixel_Mapping[] = { // Function Row (1-16) Pixel_RGBChannel(0,33,49), // 1 @@ -219,7 +220,40 @@ PixelElement Pixel_Mapping[] = { Pixel_RGBChannel(429,413,397), // 94 Pixel_RGBChannel(430,414,381), // 95 - // Underlighting - TODO + // Underlighting + // TODO Deal with missing channel 96 here + Pixel_RGBChannel(432,465,481), // 97 + Pixel_RGBChannel(433,449,482), // 98 + Pixel_RGBChannel(434,450,466), // 99 + Pixel_RGBChannel(435,451,467), // 100 + Pixel_RGBChannel(436,452,468), // 101 + Pixel_RGBChannel(437,453,469), // 102 + Pixel_RGBChannel(438,454,470), // 103 + Pixel_RGBChannel(439,455,471), // 104 + Pixel_RGBChannel(560,544,528), // 105 + Pixel_RGBChannel(561,545,529), // 106 + Pixel_RGBChannel(562,546,530), // 107 + Pixel_RGBChannel(563,547,531), // 108 + Pixel_RGBChannel(564,548,532), // 109 + Pixel_RGBChannel(565,549,533), // 110 + Pixel_RGBChannel(566,550,517), // 111 + Pixel_RGBChannel(567,534,518), // 112 + Pixel_RGBChannel(440,473,489), // 113 + Pixel_RGBChannel(441,457,490), // 114 + Pixel_RGBChannel(442,458,474), // 115 + Pixel_RGBChannel(443,459,475), // 116 + Pixel_RGBChannel(444,460,476), // 117 + Pixel_RGBChannel(445,461,477), // 118 + Pixel_RGBChannel(446,462,478), // 119 + Pixel_RGBChannel(447,463,479), // 120 + Pixel_RGBChannel(568,552,536), // 121 + Pixel_RGBChannel(569,553,537), // 122 + Pixel_RGBChannel(570,554,538), // 123 + Pixel_RGBChannel(571,555,539), // 124 + Pixel_RGBChannel(572,556,540), // 125 + Pixel_RGBChannel(573,557,541), // 126 + Pixel_RGBChannel(574,558,525), // 127 + Pixel_RGBChannel(575,542,526), // 128 }; // Frame of led changes @@ -2441,6 +2475,7 @@ PixelBuf *Pixel_bufferMap( uint16_t channel ) if ( channel < 144 ) return &Pixel_Buffers[0]; else if ( channel < 288 ) return &Pixel_Buffers[1]; else if ( channel < 432 ) return &Pixel_Buffers[2]; + else if ( channel < 576 ) return &Pixel_Buffers[3]; // Invalid channel, return first channel and display error erro_msg("Invalid channel: "); diff --git a/Scan/KType/defaultMap.kll b/Scan/KType/defaultMap.kll index 8917a50..2f95ca6 100644 --- a/Scan/KType/defaultMap.kll +++ b/Scan/KType/defaultMap.kll @@ -116,7 +116,7 @@ S0x5E : U"Right"; # Available ISSI Chips -ISSI_Chips = 3; # 1 by default +ISSI_Chips = 4; # 1 by default # Default animation speed ISSI_AnimationSpeed = 14; # 20 by default @@ -176,17 +176,17 @@ ISSILedMask4 = " "; # Disabled for now -ISSILedMask4 = " - 0x00, 0x00, /* C1-1 -> C1-16 */ - 0x00, 0x00, /* C2-1 -> C2-16 */ - 0x00, 0x00, /* C3-1 -> C3-16 */ - 0x00, 0x00, /* C4-1 -> C4-16 */ - 0x00, 0x00, /* C5-1 -> C5-16 */ - 0x00, 0x00, /* C6-1 -> C6-16 */ - 0x00, 0x00, /* C7-1 -> C7-16 */ - 0x00, 0x00, /* C8-1 -> C8-16 */ - 0x00, 0x00, /* C9-1 -> C9-16 */ -"; +#ISSILedMask4 = " +# 0x00, 0x00, /* C1-1 -> C1-16 */ +# 0x00, 0x00, /* C2-1 -> C2-16 */ +# 0x00, 0x00, /* C3-1 -> C3-16 */ +# 0x00, 0x00, /* C4-1 -> C4-16 */ +# 0x00, 0x00, /* C5-1 -> C5-16 */ +# 0x00, 0x00, /* C6-1 -> C6-16 */ +# 0x00, 0x00, /* C7-1 -> C7-16 */ +# 0x00, 0x00, /* C8-1 -> C8-16 */ +# 0x00, 0x00, /* C9-1 -> C9-16 */ +#"; ISSILedBrightness1 = " 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ From 0ffd8739789b2c87b41aea0666f2028bd7e807f8 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 30 Apr 2016 10:32:19 -0700 Subject: [PATCH 28/30] Change the target chip --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec9fb62..e1d4f4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,9 +22,9 @@ set( CHIP # "at90usb646" # Teensy++ 1.0 (avr) # "at90usb1286" # Teensy++ 2.0 (avr) # "mk20dx128" # Teensy 3.0 (arm) - "mk20dx128vlf5" # McHCK mk20dx128vlf5 +# "mk20dx128vlf5" # McHCK mk20dx128vlf5 # "mk20dx256" # Teensy 3.1,3.2 (arm) -# "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 + "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 CACHE STRING "Microcontroller Chip" ) From ccfe28a1d756fa4cec4aa3c316ad51f29b25db7a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 30 Apr 2016 11:01:56 -0700 Subject: [PATCH 29/30] Use MDErgo1 for the Scan Module --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1d4f4b..f6c5ef1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ include( initialize ) #| Please look at the {Scan,Macro,Output,Debug} for information on the modules and how to create new ones ##| Deals with acquiring the keypress information and turning it into a key index -set( ScanModule "MD1" +set( ScanModule "MDErgo1" CACHE STRING "Scan Module" ) ##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule From 1585940b80f6ea709547d685daae3f3bd6fc040b Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 30 Apr 2016 13:22:39 -0700 Subject: [PATCH 30/30] Add Layouts directory to the search path for BaseMap and PartialMap Oh. And reformat part of the file because tabs are of the devil. --- Lib/CMake/kll.cmake | 130 +++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 62 deletions(-) diff --git a/Lib/CMake/kll.cmake b/Lib/CMake/kll.cmake index 36802e4..dce9f17 100644 --- a/Lib/CMake/kll.cmake +++ b/Lib/CMake/kll.cmake @@ -20,22 +20,22 @@ if ( "${MacroModule}" STREQUAL "PartialMap" ) # if ( NOT EXISTS "${PROJECT_SOURCE_DIR}/kll/kll.py" ) - message ( STATUS "Downloading latest kll version:" ) + message ( STATUS "Downloading latest kll version:" ) - # Make sure git is available - find_package ( Git REQUIRED ) + # Make sure git is available + find_package ( Git REQUIRED ) - # Clone kll git repo - execute_process ( COMMAND ${GIT_EXECUTABLE} clone https://github.com/kiibohd/kll.git - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - ) + # Clone kll git repo + execute_process ( COMMAND ${GIT_EXECUTABLE} clone https://github.com/kiibohd/kll.git + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + ) elseif ( REFRESH_KLL ) # Otherwise attempt to update the repo - message ( STATUS "Checking for latest kll version:" ) + message ( STATUS "Checking for latest kll version:" ) - # Clone kll git repo - execute_process ( COMMAND ${GIT_EXECUTABLE} pull --rebase - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/kll - ) + # Clone kll git repo + execute_process ( COMMAND ${GIT_EXECUTABLE} pull --rebase + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/kll + ) endif () # kll/kll.py exists @@ -48,8 +48,8 @@ endif () # kll/kll.py exists #| Add each of the detected capabilities.kll foreach ( filename ${ScanModule_KLL} ${MacroModule_KLL} ${OutputModule_KLL} ${DebugModule_KLL} ) - set ( BaseMap_Args ${BaseMap_Args} ${filename} ) - set ( KLL_DEPENDS ${KLL_DEPENDS} ${filename} ) + set ( BaseMap_Args ${BaseMap_Args} ${filename} ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${filename} ) endforeach () #| If set BaseMap cannot be found, use default map @@ -57,65 +57,71 @@ set ( pathname "${PROJECT_SOURCE_DIR}/${ScanModulePath}" ) string ( REPLACE " " ";" MAP_LIST ${BaseMap} ) # Change spaces to semicolons foreach ( MAP ${MAP_LIST} ) - # Only check the Scan Module for BaseMap .kll files, default to defaultMap.kll - if ( NOT EXISTS ${pathname}/${MAP}.kll ) - set ( BaseMap_Args ${BaseMap_Args} ${pathname}/defaultMap.kll ) - set ( KLL_DEPENDS ${KLL_DEPENDS} ${pathname}/defaultMap.kll ) - elseif ( EXISTS "${pathname}/${MAP}.kll" ) - set ( BaseMap_Args ${BaseMap_Args} ${pathname}/${MAP}.kll ) - set ( KLL_DEPENDS ${KLL_DEPENDS} ${pathname}/${MAP}.kll ) - else () - message ( FATAL " Could not find '${MAP}.kll' BaseMap in Scan module directory" ) - endif () + # Only check the Scan Module for BaseMap .kll files, default to defaultMap.kll + if ( NOT EXISTS ${pathname}/${MAP}.kll ) + set ( BaseMap_Args ${BaseMap_Args} ${pathname}/defaultMap.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${pathname}/defaultMap.kll ) + elseif ( EXISTS "${pathname}/${MAP}.kll" ) + set ( BaseMap_Args ${BaseMap_Args} ${pathname}/${MAP}.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${pathname}/${MAP}.kll ) + else () + message ( FATAL " Could not find '${MAP}.kll' BaseMap in Scan module directory" ) + endif () endforeach () #| Configure DefaultMap if specified if ( NOT "${DefaultMap}" STREQUAL "" ) - set ( DefaultMap_Args -d ) + set ( DefaultMap_Args -d ) - string ( REPLACE " " ";" MAP_LIST ${DefaultMap} ) # Change spaces to semicolons - foreach ( MAP ${MAP_LIST} ) - # Check if kll file is in build directory, otherwise default to layout directory - if ( EXISTS "${PROJECT_BINARY_DIR}/${MAP}.kll" ) - set ( DefaultMap_Args ${DefaultMap_Args} ${MAP}.kll ) - set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_BINARY_DIR}/${MAP}.kll ) - elseif ( EXISTS "${PROJECT_SOURCE_DIR}/kll/layouts/${MAP}.kll" ) - set ( DefaultMap_Args ${DefaultMap_Args} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP}.kll ) - set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP}.kll ) - else () - message ( FATAL " Could not find '${MAP}.kll' DefaultMap" ) - endif () - endforeach () + string ( REPLACE " " ";" MAP_LIST ${DefaultMap} ) # Change spaces to semicolons + foreach ( MAP ${MAP_LIST} ) + # Check if kll file is in build directory, otherwise default to layout directory + if ( EXISTS "${PROJECT_BINARY_DIR}/${MAP}.kll" ) + set ( DefaultMap_Args ${DefaultMap_Args} ${MAP}.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_BINARY_DIR}/${MAP}.kll ) + elseif ( EXISTS "${PROJECT_SOURCE_DIR}/kll/layouts/${MAP}.kll" ) + set ( DefaultMap_Args ${DefaultMap_Args} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP}.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP}.kll ) + elseif ( EXISTS "${PROJECT_SOURCE_DIR}/Layouts/${MAP}.kll" ) + set ( PartialMap_Args ${PartialMap_Args} ${PROJECT_SOURCE_DIR}/Layouts/${MAP}.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_SOURCE_DIR}/Layouts/${MAP}.kll ) + else () + message ( FATAL " Could not find '${MAP}.kll' DefaultMap" ) + endif () + endforeach () endif () #| Configure PartialMaps if specified if ( NOT "${PartialMaps}" STREQUAL "" ) - # For each partial layer - foreach ( MAP ${PartialMaps} ) - set ( PartialMap_Args ${PartialMap_Args} -p ) + # For each partial layer + foreach ( MAP ${PartialMaps} ) + set ( PartialMap_Args ${PartialMap_Args} -p ) - # Combine each layer - string ( REPLACE " " ";" MAP_LIST ${MAP} ) # Change spaces to semicolons - foreach ( MAP_PART ${MAP_LIST} ) - # Check if kll file is in build directory, otherwise default to layout directory - if ( EXISTS "${PROJECT_BINARY_DIR}/${MAP_PART}.kll" ) - set ( PartialMap_Args ${PartialMap_Args} ${MAP_PART}.kll ) - set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_BINARY_DIR}/${MAP_PART}.kll ) - elseif ( EXISTS "${PROJECT_SOURCE_DIR}/kll/layouts/${MAP_PART}.kll" ) - set ( PartialMap_Args ${PartialMap_Args} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP_PART}.kll ) - set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP_PART}.kll ) - else () - message ( FATAL " Could not find '${MAP_PART}.kll' PartialMap" ) - endif () - endforeach () - endforeach () + # Combine each layer + string ( REPLACE " " ";" MAP_LIST ${MAP} ) # Change spaces to semicolons + foreach ( MAP_PART ${MAP_LIST} ) + # Check if kll file is in build directory, otherwise default to layout directory + if ( EXISTS "${PROJECT_BINARY_DIR}/${MAP_PART}.kll" ) + set ( PartialMap_Args ${PartialMap_Args} ${MAP_PART}.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_BINARY_DIR}/${MAP_PART}.kll ) + elseif ( EXISTS "${PROJECT_SOURCE_DIR}/kll/layouts/${MAP_PART}.kll" ) + set ( PartialMap_Args ${PartialMap_Args} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP_PART}.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_SOURCE_DIR}/kll/layouts/${MAP_PART}.kll ) + elseif ( EXISTS "${PROJECT_SOURCE_DIR}/Layouts/${MAP_PART}.kll" ) + set ( PartialMap_Args ${PartialMap_Args} ${PROJECT_SOURCE_DIR}/Layouts/${MAP_PART}.kll ) + set ( KLL_DEPENDS ${KLL_DEPENDS} ${PROJECT_SOURCE_DIR}/Layouts/${MAP_PART}.kll ) + else () + message ( FATAL " Could not find '${MAP_PART}.kll' PartialMap" ) + endif () + endforeach () + endforeach () endif () #| Print list of layout sources used message ( STATUS "Detected Layout Files:" ) foreach ( filename ${KLL_DEPENDS} ) - message ( "${filename}" ) + message ( "${filename}" ) endforeach () @@ -133,15 +139,15 @@ set ( kll_output --outputs ${kll_outputname} ) #| KLL Cmd set ( kll_cmd ${PROJECT_SOURCE_DIR}/kll/kll.py ${BaseMap_Args} ${DefaultMap_Args} ${PartialMap_Args} ${kll_backend} ${kll_template} ${kll_output} ) add_custom_command ( OUTPUT ${kll_outputname} - COMMAND ${kll_cmd} - DEPENDS ${KLL_DEPENDS} - COMMENT "Generating KLL Layout" + COMMAND ${kll_cmd} + DEPENDS ${KLL_DEPENDS} + COMMENT "Generating KLL Layout" ) #| KLL Regen Convenience Target add_custom_target ( kll_regen - COMMAND ${kll_cmd} - COMMENT "Re-generating KLL Layout" + COMMAND ${kll_cmd} + COMMENT "Re-generating KLL Layout" ) #| Append generated file to required sources so it becomes a dependency in the main build