diff --git a/Bootloader/main.c b/Bootloader/main.c index aabaeeb..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 @@ -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,47 @@ 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 + #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 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 (;;) + { + usb_poll(); + + // Only check for swapping after delay + uint32_t wait_ms = systick_millis_count - last_ms; + if ( wait_ms < USBPortSwapDelay_ms + attempt * USBPortSwapIncrement_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); + attempt++; + } + } +#else for (;;) { usb_poll(); } +#endif } diff --git a/CMakeLists.txt b/CMakeLists.txt index f6c5ef1..ec9fb62 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" ) @@ -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 "MDErgo1" +set( ScanModule "MD1" CACHE STRING "Scan Module" ) ##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule 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..ea3d414 --- /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="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/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 de58ea0..a3aa211 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 dce9f17..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" ) @@ -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,71 +57,65 @@ 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 ) - 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 () + 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 () 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 ) - 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 () + # 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 () endif () #| Print list of layout sources used message ( STATUS "Detected Layout Files:" ) foreach ( filename ${KLL_DEPENDS} ) - message ( "${filename}" ) + message ( "${filename}" ) endforeach () @@ -139,21 +133,22 @@ 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 set ( SRCS ${SRCS} ${kll_outputname} ) - +else () +message ( AUTHOR_WARNING "Unknown Macro module, ignoring kll generation" ) endif () # PartialMap 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 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..09243ae --- /dev/null +++ b/Macro/PixelMap/pixel.c @@ -0,0 +1,2898 @@ +/* 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_aniAdd ( char* args ); +void cliFunc_aniDel ( char* args ); +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_Pixel_Test, +} 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 ), + { 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; + +// Animation Stack +AnimationStack Pixel_AnimationStack; + + + + +// ------------------------------- +// 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 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 128 // 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 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 +// const uint8_t _frame[] = { PixelMod, ... } +#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), +}; +const uint8_t testani_frame1[] = { + Pixel_ModRGB_(0, Set, 0, 0, 0), +}; +const uint8_t testani_frame2[] = { + 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, RGB_HalfRed), +}; + +const uint8_t rainbow_frame1[] = { + // Set 1 + Pixel_ModRGB(84, Set, RGB_Red), + + // Set 2 + 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, RGB_RedOrange), + + // Set 2 + 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, 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, ... } +const uint8_t *testani_frames[] = { + testani_frame0, + testani_frame1, + testani_frame2, +}; + + +// Rainbow frame index +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, ... } +const uint8_t **Pixel_Animations[] = { + testani_frames, + rainbow_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]; + else if ( channel < 576 ) return &Pixel_Buffers[3]; + + // Invalid channel, return first channel and display error + erro_msg("Invalid channel: "); + printHex( channel ); + print( NL ); + 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 ); + + // 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; + } +} + +// 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] ); + } +} + +// 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() +{ + // 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; + } + + // 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; + } + case PixelTest_Pixel_Test: + // 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++; + + if ( rainbow_pos > 33 ) + { + rainbow_pos = 0; + goto pixel_process_done; + } + + 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_Pixel_Test; // TODO Remove when better default available + //Pixel_testMode = PixelTest_Off; + + // Clear animation stack + Pixel_AnimationStack.size = 0; +} + + +// ----- 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; + + 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 ); // 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; + + case 't': + case 'T': + info_msg("Starting pixel test"); + Pixel_testMode = PixelTest_Pixel_Test; + 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 ) +{ + 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; + rainbow_pos = 0; + 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; +} + +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 new file mode 100644 index 0000000..41ad89a --- /dev/null +++ b/Macro/PixelMap/pixel.h @@ -0,0 +1,127 @@ +/* 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 . + */ + +#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; + + +// Animation modifiers +typedef enum AnimationModifier { + AnimationModifier_None = 0x00, + AnimationModifier_Fallthrough = 0x01, // Process lower animation first +} AnimationModifier; + + + +// ----- 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 +#define Pixel_MaxChannelPerPixel 3 // TODO Generate +typedef struct PixelElement { + uint8_t width; // Number of bits in a channel + uint8_t channels; // Number of channels + // Hardware indices for each channel + uint16_t indices[Pixel_MaxChannelPerPixel]; +} PixelElement; +#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 { + 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; + +// 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 ----- + +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/Output/pjrcUSB/arm/usb_dev.c b/Output/pjrcUSB/arm/usb_dev.c index c0e4566..48baa14 100644 --- a/Output/pjrcUSB/arm/usb_dev.c +++ b/Output/pjrcUSB/arm/usb_dev.c @@ -1286,6 +1286,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/Scan/ICPad/defaultMap.kll b/Scan/ICPad/defaultMap.kll new file mode 100644 index 0000000..fdf7b6d --- /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..3f20cd9 --- /dev/null +++ b/Scan/ICPad/scan_loop.c @@ -0,0 +1,113 @@ +/* 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 + * 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 +#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(); + + // Setup Pixel Map + Pixel_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(); + + // Prepare any LED events + Pixel_process(); + + // 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..fa39dec 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,26 @@ 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 + +# 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 @@ -43,6 +63,45 @@ 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 */ +"; + +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 @@ -60,6 +119,45 @@ 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 */ +"; + +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/ISSILed/exampleAPI.bash b/Scan/ISSILed/exampleAPI.bash index 7993c38..e6e2d10 100755 --- a/Scan/ISSILed/exampleAPI.bash +++ b/Scan/ISSILed/exampleAPI.bash @@ -33,5 +33,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/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 a091b86..ef7b716 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,352 +32,369 @@ #endif // Local Includes +#include "i2c.h" #include "led_scan.h" // ----- Defines ----- -#define I2C_TxBufferLength 300 -#define I2C_RxBufferLength 8 +// 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_BufferLength 144 +#define LED_EnableBufferLength 18 +#define LED_FrameBuffersMax 4 +#define LED_TotalChannels (LED_BufferLength * ISSI_Chips_define) -// TODO Needs to be defined per keyboard -#define LED_TotalChannels 144 +// 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 }, \ + } // ----- 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 { + uint16_t i2c_addr; + uint16_t reg_addr; + uint16_t buffer[LED_EnableBufferLength]; +} 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_ledReset ( char* args ); +void cliFunc_ledSpeed ( 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( 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( 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( i2cRecv ), CLIDict_Item( i2cSend ), CLIDict_Item( ledCtrl ), - CLIDict_Item( ledRPage ), - 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 }; +volatile LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; -// 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 ]; + 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 -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 }; + uint8_t LED_displayFPS; // Display fps to cli -LED_Buffer LED_pageBuffer; - -// 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 ----- -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() +void LED_zeroPages( uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) { - // 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 - // 400kHz -> 120 (0x85) @ 48 MHz F_BUS - 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 startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) -{ - // Page Setup - uint8_t pageSetup[] = { 0xE8, 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] = 0xE8; // 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 *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[] = { 0xE8, 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); - } -void LED_writeReg( uint8_t reg, uint8_t val, uint8_t page ) +// 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 ) { - // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, 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 - uint8_t writeData[] = { 0xE8, reg, val }; + uint16_t writeData[] = { 0, reg, val }; - // Setup page - while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) - delay(1); + // Write to all the registers + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + writeData[0] = LED_pageBuffer[ ch ].i2c_addr; - while ( I2C_Send( writeData, sizeof( writeData ), 0 ) == 0 ) + // 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); } -void LED_readPage( uint8_t len, uint8_t page ) +// Write address +void LED_writeReg( uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) { - // Software shutdown must be enabled to read registers - LED_writeReg( 0x0A, 0x00, 0x0B ); - // Page Setup - uint8_t pageSetup[] = { 0xE8, 0xFD, page }; + uint16_t pageSetup[] = { addr, 0xFD, page }; + + // Reg Write Setup + 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 ) / 2 ) == -1 ) + delay(1); + + // Delay until written + while ( i2c_busy() ) + delay(1); +} + +// Read address +// 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 + uint16_t pageSetup[] = { addr, 0xFD, page }; + + // Setup page + while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Register Setup - uint8_t regSetup[] = { 0xE8, 0x00 }; + uint16_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 ) / 2 ) == -1 ) + delay(1); - // Configure register - while ( I2C_Send( regSetup, sizeof( regSetup ), 0 ) == 0 ) - delay(1); + // Register Read Command + uint16_t regReadCmd[] = { addr | 0x1, I2C_READ }; + uint8_t recv_data; - // Register Read Command - uint8_t regReadCmd[] = { 0xE9 }; - - // Request single register byte - while ( I2C_Send( regReadCmd, sizeof( regReadCmd ), 1 ) == 0 ) - delay(1); - dbug_print("NEXT"); - } + // Request single register byte + while ( i2c_read( regReadCmd, sizeof( regReadCmd ) / 2, &recv_data ) == -1 ) + delay(1); // Disable software shutdown - LED_writeReg( 0x0A, 0x01, 0x0B ); + LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + + 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 ); + } + + // 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 ) + { + // 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 @@ -386,261 +404,119 @@ 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; + 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 + + // 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) - 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); - PORTB_PCR16 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); GPIOB_PSOR |= (1<<16); - // Clear LED Pages - LED_zeroPages( 0x00, 8, 0x00, 0xB4 ); // LED Registers + // 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 LEDs based upon mask - LED_sendPage( (uint8_t*)LED_ledEnableMask1, sizeof( LED_ledEnableMask1 ), 0 ); + // Enable PORTB interrupt + NVIC_ENABLE_IRQ( IRQ_PORTB ); - // Set default brightness - LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 0 ); - - // 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 ) - { - // Disable Software shutdown of ISSI chip - LED_writeReg( 0x0A, 0x01, 0x0B ); - } + // Reset LED sequencing + LED_reset(); } -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 +uint32_t LED_timePrev = 0; unsigned int LED_currentEvent = 0; -inline uint8_t LED_scan() +inline void LED_scan() { // Check for current change event if ( LED_currentEvent ) @@ -649,18 +525,96 @@ inline uint8_t LED_scan() if ( LED_currentEvent < 150 ) { // Enable Software shutdown of ISSI chip - LED_writeReg( 0x0A, 0x00, 0x0B ); + 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 - 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 ); + } } LED_currentEvent = 0; } - return 0; + // Check to see if frame buffers are ready to replenish + if ( LED_FrameBufferReset ) + { + LED_FrameBufferReset = 0; + // Delay, in order to synchronize chips + LED_FrameBufferStart = 1; + + // 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 + 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; + + // 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; + + 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(); } @@ -696,59 +650,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, (uint16_t*)&LED_pageBuffer[ ch ], sizeof( LED_Buffer ) / 2, 0 ); + } } uint8_t LED_control_timer = 0; @@ -861,8 +813,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 ); @@ -882,7 +834,7 @@ void cliFunc_i2cSend( char* args ) if ( *arg1Ptr == '|' ) { print("| "); - I2C_Send( buffer, bufferLen, 0 ); + i2c_send( buffer, bufferLen ); bufferLen = 0; continue; } @@ -897,95 +849,33 @@ 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 ) -{ - // 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 ); - - LED_readPage( 0x1, page ); - //LED_readPage( 0xB4, page ); + i2c_send( buffer, bufferLen ); } +/* void cliFunc_ledWPage( char* args ) { char* curArgs; 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 ); @@ -993,7 +883,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 ) @@ -1019,27 +909,73 @@ void cliFunc_ledWPage( char* args ) data[1]++; } } +*/ -void cliFunc_ledStart( char* args ) +void cliFunc_ledReset( 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 + + } + + // 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 - LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 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 + 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 ); + + // 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 ); + } + + + // Set refresh speed per ISSI chip + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + + // Default refresh speed - TxA + // T is typically 11ms + // A is 1 to 64 (where 0 is 64) + LED_writeReg( addr, 0x03, speed, 0x0B ); + } } void cliFunc_ledCtrl( char* args ) @@ -1079,3 +1015,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 545b8b9..75d7937 100644 --- a/Scan/ISSILed/led_scan.h +++ b/Scan/ISSILed/led_scan.h @@ -23,10 +23,18 @@ +// ----- Variables ----- + +extern uint8_t LED_FrameBuffersReady; + + + // ----- Functions ----- void LED_setup(); -uint8_t LED_scan(); +void LED_scan(); + +void LED_currentChange( unsigned int current ); void LED_currentChange( unsigned int current ); 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 3f9c632..2f95ca6 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,62 +39,248 @@ 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 + +# Default animation speed +ISSI_AnimationSpeed = 14; # 20 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 */ +"; + +# 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 */ +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 = " +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 = " +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 = " +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 = " +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 4e52706..898c1fe 100644 --- a/Scan/KType/scan_loop.c +++ b/Scan/KType/scan_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2016 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 @@ -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(); @@ -104,6 +118,7 @@ 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/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 7d8897b..cbb0e76 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -139,6 +139,10 @@ uint8_t Matrix_pin( GPIO_Pin gpio, Type type ) *GPIO_PDDR &= ~(1 << gpio.pin); // input, high Z state #endif *GPIO_PCOR |= (1 << gpio.pin); + #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 break; case Type_StrobeSetup: @@ -525,6 +529,10 @@ void Matrix_scan( uint16_t scanNum ) 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 ); } } 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..cf5a69e --- /dev/null +++ b/Scan/PortSwap/port_scan.c @@ -0,0 +1,207 @@ +/* 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; +} + + +// Signal from parent Scan Module that available current has changed +// current - mA +void Port_currentChange( unsigned int current ) +{ + // TODO - Power savings? +} + + + +// ----- 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..5d0fd2d --- /dev/null +++ b/Scan/PortSwap/port_scan.h @@ -0,0 +1,32 @@ +/* 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 . + */ + +#pragma once + +// ----- Includes ----- + +// Compiler Includes +#include + + + +// ----- Functions ----- + +void Port_setup(); +uint8_t Port_scan(); + +void Port_currentChange( unsigned int current ); // Called by Output Module + 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 +) + 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 1d87dfd..3aafdf1 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 ); diff --git a/Scan/WhiteFox/scan_loop.c b/Scan/WhiteFox/scan_loop.c index 56fa995..6b54a65 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();