From 874852ad6d1938318627d5a0a09cce8ab111e9ca Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sun, 3 Feb 2019 17:05:44 -0800 Subject: [PATCH] Fixing single color animation save/load - Storage stack was not saving position - On Kira when changing the key colors, then changing the underlighting while the key colors would stay the same (due to no animations manipulating them) the animation stack would be emptied so the storage stack would not know how to get that color * clearactive replace type was added to only remove moving animations - Resolves Issue #312 - Do not waste a storage block if saving the same data - If the storage is completely empty, raise the cleared_block flag (to handle defaults correctly) - Reworked how defaults are generated for brightness, fade and animations --- Keyboards/Pipfile | 2 +- Lib/CMake/kll.cmake | 2 +- Lib/storage.c | 23 ++-- Macro/PixelMap/pixel.c | 192 +++++++++++++++++++++++--------- Macro/PixelMap/pixel.h | 13 ++- Scan/Devices/ISSILed/led_scan.c | 10 +- 6 files changed, 168 insertions(+), 74 deletions(-) diff --git a/Keyboards/Pipfile b/Keyboards/Pipfile index ddb746ad5..871719254 100644 --- a/Keyboards/Pipfile +++ b/Keyboards/Pipfile @@ -4,7 +4,7 @@ verify_ssl = true name = "pypi" [packages] -kll = "==0.5.7.5" +kll = "==0.5.7.6" [dev-packages] diff --git a/Lib/CMake/kll.cmake b/Lib/CMake/kll.cmake index 14f5b3a34..e27c01e2e 100644 --- a/Lib/CMake/kll.cmake +++ b/Lib/CMake/kll.cmake @@ -43,7 +43,7 @@ endif () message ( STATUS "Checking for kll" ) ### XXX XXX XXX - Remember to update Pipfile as well when you change the version! ### -set ( KLL_MIN_VERSION "0.5.7.5" ) +set ( KLL_MIN_VERSION "0.5.7.6" ) # 1) Check for environment variable if ( NOT DEFINED KLL_EXECUTABLE ) diff --git a/Lib/storage.c b/Lib/storage.c index 5fbf04e4b..7b2a3bbe2 100644 --- a/Lib/storage.c +++ b/Lib/storage.c @@ -1,6 +1,6 @@ /** * Copyright (c) 2012 Atmel Corporation. All rights reserved. - * Modified by Jacob Alexander 2018 + * Modified by Jacob Alexander 2018-2019 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -266,6 +266,12 @@ void storage_init() storage_buffer[i] = page_buffer[i + 449]; #endif } + + // If this is the first page, then set the cleared flag as no flash has been written + if ( page_walker == 0 ) + { + cleared_block = 1; + } } // If the block is within a page, go to previous block and fetch the data else @@ -350,6 +356,13 @@ uint8_t storage_write(uint8_t* data, uint16_t address, uint16_t size, uint8_t cl return 0; } + // Make sure this isn't the same data already set in flash + // If so, just exit, no need to wear the flash any further + if ( memcmp( storage_buffer, data, size ) == 0 ) + { + return 1; + } + // Set internal buffer to all 0xffs // This way it's possible to do partial writes to the page for ( int i = 0; i < STORAGE_FLASH_PAGE_SIZE; i++ ) @@ -482,16 +495,10 @@ int8_t storage_block_position() } // Returns 1 if storage has been cleared and will not have conflicts when changing the block size -// Or if there is no useful data in the non-volatile storage +// Or if there is no useful data in the non-volatile storage (i.e. completely empty, fresh erase) // storage_init() must be called first uint8_t storage_is_storage_cleared() { - // Check to see if this page is empty - if ( !find_cleared_block(storage_buffer) ) - { - return 1; - } - return cleared_block; } diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index 732892f22..45704b932 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2018 by Jacob Alexander +/* Copyright (C) 2015-2019 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 @@ -82,21 +82,25 @@ typedef enum PixelTest { PixelTest_XY_Roll = 33, } PixelTest; + + // ----- Variables ----- -#if Storage_Enable_define == 1 typedef struct { - uint8_t animation_indices[Pixel_AnimationStackSize]; + uint8_t index; + uint8_t pos; +} PixelConfigElem; + +typedef struct { + PixelConfigElem animations[Pixel_AnimationStackSize]; PixelPeriodConfig fade_periods[4][4]; } PixelConfig; -static PixelConfig defaults = { - .animation_indices = {[0 ... Pixel_AnimationStackSize-1] = 255}, //Todo, use some kll define - // .fade_periods initialized later -}; - static PixelConfig settings; +#if Storage_Enable_define == 1 +static PixelConfig defaults; + static StorageModule PixelStorage = { .name = "Pixel Map", .settings = &settings, @@ -758,6 +762,49 @@ uint8_t Pixel_addAnimation( AnimationStackElement *element, CapabilityState csta Pixel_clearAnimations(); break; + // Clear all current animations from stack before adding new animation + // Unless it's paused, and if it's paused do a replace if necessary + case AnimationReplaceType_ClearActive: + found = Pixel_lookupAnimation( element->index, 0 ); + // If found, modify stack element + if ( found ) + { + found->pos = element->pos; + found->subpos = element->subpos; + found->loops = element->loops; + found->pfunc = element->pfunc; + found->ffunc = element->ffunc; + found->framedelay = element->framedelay; + found->frameoption = element->frameoption; + found->replace = element->replace; + found->state = element->state; + return 0; + } + + // Iterate through stack, stopping animations that are not paused + // and ignoring the found animation + for ( uint16_t pos = 0; pos < Pixel_AnimationStack.size; pos++ ) + { + // Ignore found animation + if ( Pixel_AnimationStack.stack[pos] == found ) + { + continue; + } + + // Ignore paused animations (single will be paused on the next frame) + if ( + Pixel_AnimationStack.stack[pos]->state == AnimationPlayState_Pause || + Pixel_AnimationStack.stack[pos]->state == AnimationPlayState_Single + ) + { + continue; + } + + // Otherwise stop + Pixel_AnimationStack.stack[pos]->state = AnimationPlayState_Stop; + } + break; + default: break; } @@ -2016,13 +2063,9 @@ void Pixel_SecondaryProcessing_setup() // Each of the periods for ( uint8_t pr = 0; pr < 4; pr++ ) { - // Lookup period using index - uint8_t period_index = Pixel_LED_FadePeriod_Defaults[pf][pr]; - PixelPeriodConfig conf = Pixel_LED_FadePeriods[period_index]; - // Set period to profile - Pixel_pixel_fade_profile_entries[pf].conf[pr].start = conf.start; - Pixel_pixel_fade_profile_entries[pf].conf[pr].end = conf.end; + PixelPeriodConfig conf = settings.fade_periods[pf][pr]; + Pixel_pixel_fade_profile_entries[pf].conf[pr] = conf; } // Reset state @@ -2245,23 +2288,21 @@ void Pixel_setAnimationControl( AnimationControl control ) // Starting Animation setup void Pixel_initializeStartAnimations() { - // Iterate over starting animations - for ( uint32_t index = 0; index < Pixel_AnimationSettingsNum_KLL; index++ ) + // Animations + for ( uint8_t pos = 0; pos < Pixel_AnimationStackSize; pos++ ) { - // Check if a starting animation - if ( Pixel_AnimationSettings[ index ].state == AnimationPlayState_Start ) - { - // Default animations are noted by the TriggerMacro *trigger pointer being set to 1 - if ( (uintptr_t)(Pixel_AnimationSettings[ index ].trigger) == 1 ) + uint8_t index = settings.animations[pos].index; + if (index != 255) { + AnimationStackElement element = Pixel_AnimationSettings[ index ]; + + // Only update state if not already defined + if ( element.state == AnimationPlayState_Pause ) { - // Start animation - if ( Pixel_addDefaultAnimation( index ) == 0 ) - { - warn_msg("Failed to start starting animation index: "); - printInt32( index ); - print( NL ); - } + element.state = AnimationPlayState_Start; } + + element.pos = settings.animations[pos].pos; + Pixel_addAnimation( &element, CapabilityState_None ); } } } @@ -2649,14 +2690,58 @@ inline void Pixel_setup() // Register Pixel CLI dictionary CLI_registerDictionary( pixelCLIDict, pixelCLIDictName ); - // Register storage module + // Iterate over starting animations + uint8_t add_animations = 0; + for ( uint32_t index = 0; index < Pixel_AnimationSettingsNum_KLL; index++ ) + { + // Check if a starting animation + if ( Pixel_AnimationSettings[ index ].state == AnimationPlayState_Start ) + { + // Default animations are noted by the TriggerMacro *trigger pointer being set to 1 + if ( (uintptr_t)(Pixel_AnimationSettings[ index ].trigger) == 1 ) + { + // Add animation to the defaults stack +#if Storage_Enable_define == 1 + defaults.animations[add_animations].index = index; + defaults.animations[add_animations].pos = Pixel_AnimationSettings[index].pos; +#else + settings.animations[add_animations].index = index; + settings.animations[add_animations].pos = Pixel_AnimationSettings[index].pos; +#endif + add_animations++; + } + } + } + + // Fill in rest of stack + for ( uint8_t animation = add_animations; animation < Pixel_AnimationStackSize; animation++ ) + { +#if Storage_Enable_define == 1 + defaults.animations[animation].index = 255; + defaults.animations[animation].pos = 0; +#else + settings.animations[animation].index = 255; + settings.animations[animation].pos = 0; +#endif + } + + // Setup fade defaults + for ( uint8_t profile = 0; profile < 4; profile++ ) + { + for ( uint8_t config = 0; config < 4; config++ ) + { #if Storage_Enable_define == 1 - for (uint8_t profile=0; profile<4; profile++) { - for (uint8_t config=0; config<4; config++) { defaults.fade_periods[profile][config] = Pixel_LED_FadePeriods[Pixel_LED_FadePeriod_Defaults[profile][config]]; +#else + settings.fade_periods[profile][config] = + Pixel_LED_FadePeriods[Pixel_LED_FadePeriod_Defaults[profile][config]]; +#endif } } + + // Register storage module +#if Storage_Enable_define == 1 Storage_registerModule(&PixelStorage); #endif @@ -3201,27 +3286,13 @@ void cliFunc_rectDisp( char* args ) #if Storage_Enable_define == 1 -void Pixel_loadConfig() { - // Animations - for ( uint8_t pos = 0; pos < Pixel_AnimationStackSize; pos++ ) - { - uint8_t index = settings.animation_indices[pos]; - if (index != 255) { - AnimationStackElement element = Pixel_AnimationSettings[ index ]; - element.state = AnimationPlayState_Start; - Pixel_addAnimation( &element, CapabilityState_None ); - } - } +void Pixel_loadConfig() +{ + // Animation setup + Pixel_initializeStartAnimations(); // Fade periods - for (uint8_t profile=0; profile<4; profile++) - { - for (uint8_t config=0; config<4; config++) - { - PixelPeriodConfig period_config = settings.fade_periods[profile][config]; - Pixel_pixel_fade_profile_entries[profile].conf[config] = period_config; - } - } + Pixel_SecondaryProcessing_setup(); } void Pixel_saveConfig() { @@ -3230,9 +3301,20 @@ void Pixel_saveConfig() { { if (pos < Pixel_AnimationStack.size) { AnimationStackElement *elem = Pixel_AnimationStack.stack[pos]; - settings.animation_indices[pos] = elem->index; + settings.animations[pos].index = elem->index; + + // Save position, only if paused + if ( elem->state == AnimationPlayState_Pause ) + { + settings.animations[pos].pos = elem->pos - 1; + } + else + { + settings.animations[pos].pos = 0; + } } else { - settings.animation_indices[pos] = 255; + settings.animations[pos].index = 255; + settings.animations[pos].pos = 0; } } @@ -3253,12 +3335,15 @@ void Pixel_printConfig() { print(" \033[35mAnimations\033[0m" NL); for ( uint8_t pos = 0; pos < Pixel_AnimationStackSize; pos++ ) { - uint8_t index = settings.animation_indices[pos]; + uint8_t index = settings.animations[pos].index; + uint8_t fpos = settings.animations[pos].pos; if (index != 255) { print("AnimationStack.stack["); printInt8(pos); print("]->index = "); printInt8(index); + print("; pos = "); + printInt8(fpos); print(NL); } } @@ -3278,6 +3363,7 @@ void Pixel_printConfig() { printInt8(period.start); print(", "); printInt8(period.end); + print("}"); print(NL); } } diff --git a/Macro/PixelMap/pixel.h b/Macro/PixelMap/pixel.h index 829d22108..ac46ee874 100644 --- a/Macro/PixelMap/pixel.h +++ b/Macro/PixelMap/pixel.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2018 by Jacob Alexander +/* Copyright (C) 2015-2019 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 @@ -104,11 +104,12 @@ typedef enum PixelAddressType { // Animation Replace Type typedef enum AnimationReplaceType { - AnimationReplaceType_None = 0, // Don't replace (add new animation to stack if not full) - AnimationReplaceType_Basic = 1, // Replace only if the same trigger initiated - AnimationReplaceType_All = 2, // Replace no matter what trigger initiated - AnimationReplaceType_State = 3, // Using same trigger, start on Activate/Press, stop on Deactivate/Release - AnimationReplaceType_Clear = 4, // Clear all other animations before addi + AnimationReplaceType_None = 0, // Don't replace (add new animation to stack if not full) + AnimationReplaceType_Basic = 1, // Replace only if the same trigger initiated + AnimationReplaceType_All = 2, // Replace no matter what trigger initiated + AnimationReplaceType_State = 3, // Using same trigger, start on Activate/Press, stop on Deactivate/Release + AnimationReplaceType_Clear = 4, // Clear all other animations before adding + AnimationReplaceType_ClearActive = 5, // Clear all other animations before adding, except paused (replace those) } AnimationReplaceType; // Animation Play State diff --git a/Scan/Devices/ISSILed/led_scan.c b/Scan/Devices/ISSILed/led_scan.c index dfe8881fa..499f38eb9 100644 --- a/Scan/Devices/ISSILed/led_scan.c +++ b/Scan/Devices/ISSILed/led_scan.c @@ -213,18 +213,18 @@ CLIDict_Def( ledCLIDict, "ISSI LED Module Commands" ) = { { 0, 0, 0 } // Null entry for dictionary end }; -#if Storage_Enable_define == 1 // Storage Module typedef struct { uint8_t brightness; } LedConfig; +static LedConfig settings; + +#if Storage_Enable_define == 1 static LedConfig defaults = { .brightness = ISSI_Global_Brightness_define }; -static LedConfig settings; - static StorageModule LedStorage = { .name = "LED Scan", .settings = &settings, @@ -550,7 +550,7 @@ void LED_reset() } // Reset global brightness - LED_brightness = ISSI_Global_Brightness_define; + LED_brightness = settings.brightness; #if ISSI_Chip_31FL3733_define == 1 // Enable pull-up and pull-down anti-ghosting resistors @@ -1279,7 +1279,7 @@ void cliFunc_ledSet( char* args ) // Reset brightness if ( *arg1Ptr == '\0' ) { - LED_setBrightness( ISSI_Global_Brightness_define ); + LED_setBrightness( settings.brightness ); } else {