23#include "src/modes/include/default_config.hpp"
47 static constexpr auto from(
const uint8_t* arr)
49 ActiveIndexTy index = {arr[0], arr[1], arr[2], arr[3]};
52 static constexpr auto from(
const std::array<uint8_t, 4>& arr) {
return ActiveIndexTy::from(arr.data()); }
56template<
typename Config>
struct RampHandlerTy
58 using ConfigTy = Config;
59 static constexpr uint32_t startPeriod = Config::rampStartPeriodMs;
63 RampHandlerTy(uint32_t stepSpeed,
bool rampSaturates = Config::defaultRampSaturates) :
64 stepSpeed {stepSpeed},
66 lastTimeMeasured {1000},
68 animEffect {Config::defaultCustomRampAnimEffect},
69 animChoice {Config::defaultCustomRampAnimChoice}
73 void LMBD_INLINE reset()
76 stepSpeed = Config::defaultCustomRampStepSpeedMs;
78 animEffect = Config::defaultCustomRampAnimEffect;
79 animChoice = Config::defaultCustomRampAnimChoice;
82 void LMBD_INLINE update_ramp(uint8_t rampValue, uint32_t holdTime,
auto callback)
85 if (holdTime < lastTimeMeasured)
87 lastTimeMeasured = holdTime;
89 if (holdTime < startPeriod)
92 isForward = !isForward;
105 uint32_t lastCounter = lastTimeMeasured / stepSpeed;
106 uint32_t nextCounter = holdTime / stepSpeed;
107 if (nextCounter <= lastCounter)
111 for (uint32_t I = 0; I < nextCounter - lastCounter; ++I)
114 if (isForward && (!rampSaturates || rampValue < 255))
118 if (!isForward && (!rampSaturates || rampValue > 0))
125 lastTimeMeasured = holdTime;
132 uint32_t lastTimeMeasured;
139template<
typename Config,
typename AllGroups, u
int8_t h
iddenGroupsCount>
struct ModeManagerTy
141 using SelfTy = ModeManagerTy<Config, AllGroups, hiddenGroupsCount>;
142 using ConfigTy = Config;
143 using AllGroupsTy = AllGroups;
144 using AllStatesTy = details::StateTyFrom<AllGroups>;
147 static constexpr uint8_t nbGroupsTotal {std::tuple_size_v<AllGroupsTy>};
148 static constexpr uint8_t hiddenGroupCount = hiddenGroupsCount;
150 static_assert(nbGroupsTotal >= hiddenGroupsCount,
"Manager cannot operate without accessible groups");
153 static constexpr uint8_t nbAccessibleGroups = nbGroupsTotal - hiddenGroupsCount;
156 static_assert(nbGroupsTotal <= 15,
"Maximum of 15 groups has been exceeded.");
158 template<u
int8_t Idx>
using GroupAt = std::tuple_element_t<Idx, AllGroupsTy>;
161 using HasAnyGroup = details::anyOf<AllGroupsTy>;
162 static constexpr bool hasSunsetAnimation = HasAnyGroup::hasSunsetAnimation;
163 static constexpr bool hasBrightCallback = HasAnyGroup::hasBrightCallback;
164 static constexpr bool requireUserThread = HasAnyGroup::requireUserThread;
165 static constexpr bool hasCustomRamp = HasAnyGroup::hasCustomRamp;
166 static constexpr bool hasSystemCallbacks = hasCustomRamp || HasAnyGroup::hasSystemCallbacks;
167 static constexpr bool hasButtonCustomUI = HasAnyGroup::hasButtonCustomUI;
170 using EveryModeBool = details::asTableFor<AllGroupsTy>;
171 static constexpr auto everySunsetCallback = EveryModeBool::everySunsetCallback;
172 static constexpr auto everyBrightCallback = EveryModeBool::everyBrightCallback;
173 static constexpr auto everyRequireUserThread = EveryModeBool::everyRequireUserThread;
174 static constexpr auto everyCustomRamp = EveryModeBool::everyCustomRamp;
175 static constexpr auto everySystemCallbacks = EveryModeBool::everySystemCallbacks;
176 static constexpr auto everyButtonCustomUI = EveryModeBool::everyButtonCustomUI;
179 ModeManagerTy(hardware::LampTy& lamp) : activeIndex {ActiveIndexTy::from(Config::initialActiveIndex)}, lamp {lamp} {}
181 ModeManagerTy() =
delete;
182 ModeManagerTy(
const ModeManagerTy&) =
delete;
183 ModeManagerTy& operator=(
const ModeManagerTy&) =
delete;
186 auto get_context() {
return ContextTy<SelfTy, SelfTy>(*
this); }
189 template<
typename CallBack>
static void LMBD_INLINE dispatch_group(
auto& ctx, CallBack&& cb)
191 uint8_t groupId = ctx.get_active_group(nbGroupsTotal);
193 details::unroll<nbGroupsTotal>([&](
auto Idx) LMBD_INLINE {
202 template<
bool systemCallbacksOnly,
typename CallBack>
static void LMBD_INLINE foreach_group(
auto& ctx, CallBack&& cb)
204 if constexpr (systemCallbacksOnly)
206 details::unroll<nbGroupsTotal>([&](
auto Idx) LMBD_INLINE {
207 using GroupHere = GroupAt<Idx>;
208 constexpr bool hasCallbacks = GroupHere::hasSystemCallbacks;
210 if constexpr (hasCallbacks)
218 details::unroll<nbGroupsTotal>([&](
auto Idx) LMBD_INLINE {
229 enum class Store : uint16_t
239 static constexpr uint32_t storeId = modes::store::derivateStoreId<modes::store::hash(
"ManagerStoreId"), AllGroupsTy>;
256 std::array<ActiveIndexTy, maxFavoriteCount>
favorites = {};
264 ActiveIndexTy::from({0, 2, 80, 0}),
266 ActiveIndexTy::from({0, 2, 165, 0}),
268 ActiveIndexTy::from({0, 2, 0, 0}),
270 ActiveIndexTy::from({0, 0, 0, 0}),
272 ActiveIndexTy::from({0, 0, 128, 0}),
274 ActiveIndexTy::from({0, 0, 255, 0}),
282 static_assert(
maxFavoriteCount < 16,
"Maximum of 15 favorite as been exceeded");
298 RampHandlerTy<Config>
rampHandler = {Config::defaultCustomRampStepSpeedMs};
337 auto& self = ctx.state;
338 self.rampHandler.reset();
339 self.clearStripOnModeChange = Config::defaultClearStripOnModeChange;
345 auto& self = ctx.state;
346 if (self.clearStripOnModeChange)
354 template<
typename Group> StateTyOf<Group>* LMBD_INLINE getStateGroupOf()
356 using StateTy = StateTyOf<Group>;
357 using OptionalTy = std::optional<StateTy>;
359 StateTy* substate =
nullptr;
360 details::unroll<nbGroupsTotal>([&](
auto Idx) LMBD_INLINE {
361 using GroupHere = GroupAt<Idx>;
362 constexpr bool IsHere = std::is_same_v<GroupHere, Group>;
364 if constexpr (IsHere)
366 OptionalTy& opt = std::get<OptionalTy>(state.groupStates);
367 if (!opt.has_value())
372 StateTy& stateHere = *opt;
373 substate = &stateHere;
376 assert(substate !=
nullptr &&
"this should not have compiled at all!");
378 static_assert(details::ModeBelongsTo<Group, AllGroups>);
383 template<
typename Mode> StateTyOf<Mode>& LMBD_INLINE getStateOf()
385 using TargetStateTy = StateTyOf<Mode>;
388 if constexpr (std::is_same_v<TargetStateTy, NoState>)
394 else if constexpr (std::is_same_v<TargetStateTy, StateTy>)
400 else if constexpr (details::GroupBelongsTo<Mode, AllGroups>)
402 TargetStateTy* substate = getStateGroupOf<Mode>();
404 if (substate ==
nullptr)
406 substate = (TargetStateTy*)&placeholder;
407 assert(
false &&
"this code should be unreachable, but is it?");
414 static_assert(details::ModeExists<Mode, AllGroups>);
417 TargetStateTy* substate =
nullptr;
419 details::unroll<nbGroupsTotal>([&](
auto Idx) LMBD_INLINE {
420 using Group = GroupAt<Idx>;
421 using AllModes =
typename Group::AllModesTy;
422 if constexpr (details::ModeBelongsTo<Mode, AllModes>)
424 substate = Group::template getStateOf<Mode>(*
this);
427 assert(substate !=
nullptr &&
"this should not have compiled at all!");
429 if (substate ==
nullptr)
431 substate = (TargetStateTy*)&placeholder;
432 assert(
false &&
"this code should be unreachable, but is it?");
443 static constexpr bool isGroupManager =
true;
444 static constexpr bool isModeManager =
true;
447 static void next_group(
auto& ctx)
450 uint8_t groupIdBefore = ctx.get_active_group(nbAccessibleGroups);
451 ctx.set_active_group(groupIdBefore + 1, nbAccessibleGroups);
455 static void next_mode(
auto& ctx)
457 dispatch_group(ctx, [](
auto group) {
463 static void jump_to_new_active_index(
auto& ctx,
const ActiveIndexTy& newActiveIndex)
466 ctx.set_active_group(newActiveIndex.groupIndex, nbGroupsTotal);
467 ctx.set_active_mode(newActiveIndex.modeIndex);
469 ctx.modeManager.activeIndex.customIndex = newActiveIndex.customIndex;
470 ctx.modeManager.activeIndex.rampIndex = newActiveIndex.rampIndex;
473 if (ctx.modeManager.activeIndex.rawIndex != newActiveIndex.rawIndex)
475 ctx.modeManager.activeIndex = newActiveIndex;
476 custom_ramp_update(ctx, ctx.get_active_custom_ramp());
487 static bool jump_to_favorite(
auto& ctx, uint8_t which_one,
bool shouldSaveLastActiveIndex)
490 if (ctx.state.usedFavoriteCount <= 0)
494 which_one = (which_one % ctx.state.usedFavoriteCount);
495 ctx.state.lastFavoriteStep = which_one;
498 if (shouldSaveLastActiveIndex)
500 ctx.state.beforeFavoriteActiveIndex = ctx.modeManager.activeIndex;
503 if (which_one >= ctx.state.maxFavoriteCount)
506 const auto targetFavorite = ctx.state.favorites[which_one];
508 jump_to_new_active_index(ctx, targetFavorite);
512 display_favorite_number_ramp(ctx, which_one, ctx.state.usedFavoriteCount,
true, 1000);
518 ctx.state.isInFavoriteMockGroup =
true;
526 static bool exit_favorite_group(
auto& ctx, ActiveIndexTy newActiveIndex)
528 if (not ctx.state.isInFavoriteMockGroup)
531#ifdef LMBD_SIMULATION
532 fprintf(stderr,
"Exit fake favorite group\n");
535 ctx.state.isInFavoriteMockGroup =
false;
537 jump_to_new_active_index(ctx, newActiveIndex);
551 static bool set_favorite_now(
auto& ctx, uint8_t which_one = 0)
554 if (which_one != ctx.state.maxFavoriteCount && which_one == ctx.state.usedFavoriteCount)
557 ctx.state.usedFavoriteCount = std::min<uint8_t>(ctx.state.usedFavoriteCount + 1, ctx.state.maxFavoriteCount);
560 if (which_one < ctx.state.maxFavoriteCount)
562 ctx.state.favorites[which_one] = ctx.modeManager.activeIndex;
573 static bool delete_favorite_now(
auto& ctx)
576 const auto which_one = ctx.state.lastFavoriteStep;
577 if (ctx.state.usedFavoriteCount > 0 and which_one < ctx.state.maxFavoriteCount)
579 ctx.state.usedFavoriteCount -= 1;
581 for (uint8_t i = which_one; i < ctx.state.maxFavoriteCount - 1; ++i)
584 ctx.state.favorites[i] = ctx.state.favorites[i + 1];
587 if (ctx.state.usedFavoriteCount > 0)
589 jump_to_favorite(ctx, which_one,
false);
594 exit_favorite_group(ctx, ctx.state.beforeFavoriteActiveIndex);
606 static void handle_scroll_modes(
auto& ctx, uint32_t holdDuration)
608 auto& scrollHandler = ctx.state.scrollHandler;
609 scrollHandler.isForward =
false;
611 static constexpr uint32_t scrollActivationTiming = 750;
612 if (holdDuration <= scrollActivationTiming)
615 overlay_animate_ramp(
616 ctx, holdDuration, scrollActivationTiming, colors::PaletteGradient<colors::White, colors::Cyan>);
620 scrollHandler.update_ramp(128, holdDuration, [&](uint8_t rampValue) {
621 uint8_t modeIndex = ctx.get_active_mode();
622 uint8_t groupIndex = ctx.get_active_group();
623 uint8_t modeCount = ctx.get_modes_count();
625 ctx.state.isLastScrollAGroupChange =
false;
634 ctx.set_active_mode(modeIndex - 1, modeCount);
640 ctx.state.isLastScrollAGroupChange =
true;
645 ctx.set_active_group(groupIndex - 1, nbAccessibleGroups);
652 ctx.set_active_group(nbAccessibleGroups - 1, nbAccessibleGroups);
656 modeCount = ctx.get_modes_count();
657 ctx.set_active_mode(modeCount - 1, modeCount);
666 if (modeIndex + 1 < modeCount)
674 ctx.state.isLastScrollAGroupChange =
true;
676 if (groupIndex + 1 < nbAccessibleGroups)
684 ctx.set_active_group(0, nbAccessibleGroups);
688 ctx.set_active_mode(0, modeCount);
699 static void enter_hidden_group(
auto& ctx, uint8_t index)
701 assert(index < hiddenGroupsCount);
702 ctx.set_active_group(nbAccessibleGroups + index, nbGroupsTotal);
706 static bool overlay_animate_ramp(
707 auto& ctx,
float holdDuration,
float stepSize,
const colors::PaletteTy& palette,
const uint32_t timeout = 0)
710 const uint32_t stepProgress = floor((holdDuration * 256.0) / stepSize);
711 return overlay_animate_ramp(ctx, stepProgress % 256, palette);
713 static bool overlay_animate_ramp(
auto& ctx,
716 const uint32_t timeout = 0)
738 return (progress >= 250);
742 static void overlay_animate_dot(
auto& ctx,
747 const uint32_t timeout = 0)
766 static uint8_t get_modes_count(
auto& ctx)
769 dispatch_group(ctx, [&](
auto group) {
770 value =
decltype(group)::LocalModeTy::nbModes;
776 static void enter_group(
auto& ctx,
const uint8_t value)
779 assert(value < nbGroupsTotal);
781 auto manager = ctx.modeManager.get_context();
784 ctx.modeManager.quit_mode(manager);
787 ctx.modeManager.activeIndex.groupIndex = value;
789 ctx.modeManager.activeIndex.modeIndex = ctx.state.lastModeMemory[value];
792 ctx.modeManager.enter_mode(manager);
796 static void quit_group(
auto& ctx)
799 uint8_t modeIdBefore = ctx.get_active_mode();
802 auto keyModeMemory = ctx.template storageFor<Store::modeMemory>(ctx.state.lastModeMemory);
805 uint8_t groupIdBefore = ctx.get_active_group(nbGroupsTotal);
806 ctx.state.lastModeMemory[groupIdBefore] = modeIdBefore;
810 static void enter_mode(
auto& ctx)
812 ctx.state.before_enter_mode(ctx);
815 dispatch_group(ctx, [](
auto group) {
819 ctx.state.after_enter_mode(ctx);
823 static void quit_mode(
auto& ctx)
825 dispatch_group(ctx, [](
auto group) {
835 static void loop(
auto& ctx)
838 if (ctx.state.isFavoritePending > 0)
840 ctx.state.isFavoritePending -= 1;
842 if (ctx.state.isFavoritePending == 0 && ctx.state.whichFavoritePending <= ctx.state.usedFavoriteCount)
844 if (ctx.set_favorite_now(ctx.state.whichFavoritePending))
852 if (ctx.state.isFavoriteDeletePending > 0)
854 ctx.state.isFavoriteDeletePending -= 1;
857 if (ctx.state.isFavoriteDeletePending == 0)
859 ctx.delete_favorite_now();
864 if (ctx.state.isSunsetTimingPending > 0)
866 ctx.state.isSunsetTimingPending -= 1;
867 if (ctx.state.isSunsetTimingPending == 0)
876 if (ctx.lamp.config.skipFirstLedsForEffect > 0)
878 ctx.lamp.config.skipFirstLedsForEffect -= 1;
881 if (ctx.state.skipNextFrameEffect > 0)
883 ctx.state.skipNextFrameEffect -= 1;
886 if (ctx.state.skipNextFrameEffect == 0)
888 ctx.lamp.restoreBrightness();
893 ctx.lamp.refresh_tick_value();
896 dispatch_group(ctx, [](
auto group) {
901 overlay.display_update(ctx);
909 static void sunset_update(
auto& ctx,
float progress)
911 dispatch_group(ctx, [&](
auto group) {
912 group.sunset_update(progress);
923 dispatch_group(ctx, [&](
auto group) {
924 group.brightness_update(brightness);
932 ctx.lamp.refresh_tick_value();
934 foreach_group<true>(ctx, [](
auto group) {
935 group.power_on_sequence();
939 if (ctx.state.isInFavoriteMockGroup and jump_to_favorite(ctx, ctx.state.lastFavoriteStep,
false))
946 uint8_t groupIdBefore = ctx.get_active_group(nbGroupsTotal);
947 ctx.set_active_group(groupIdBefore);
954 foreach_group<true>(ctx, [](
auto group) {
955 group.power_off_sequence();
966 ctx.template storageSaveOnly<Store::lastActive>(ctx.modeManager.activeIndex);
969 ctx.template storageSaveOnly<Store::usedFavoriteCount>(ctx.modeManager.state.usedFavoriteCount);
970 ctx.template storageSaveOnly<Store::favoriteModes>(ctx.modeManager.state.favorites);
971 ctx.template storageSaveOnly<Store::lastUsedFavorite>(ctx.modeManager.state.lastFavoriteStep);
972 ctx.template storageSaveOnly<Store::isInFavoriteGroup>(ctx.state.isInFavoriteMockGroup);
973 ctx.template storageSaveOnly<Store::modeMemory>(ctx.state.lastModeMemory);
975 foreach_group<not hasCustomRamp>(ctx, [&ctx](
auto group) {
976 if constexpr (group.hasCustomRamp)
978 using StoreHere =
typename decltype(group)::StoreEnum;
979 group.template storageSaveOnly<StoreHere::rampMemory>(group.state.customRampMemory);
980 group.template storageSaveOnly<StoreHere::indexMemory>(group.state.customIndexMemory);
983 group.write_parameters();
994 using LocalStore = details::LocalStoreOf<
decltype(ctx)>;
995 LocalStore::template migrateStoreIfNeeded<storeId>();
998 ctx.template storageLoadOnly<Store::lastActive>(ctx.modeManager.activeIndex,
999 ActiveIndexTy::from(Config::initialActiveIndex));
1004 ctx.template storageLoadOnly<Store::usedFavoriteCount>(ctx.modeManager.state.usedFavoriteCount,
1005 ctx.modeManager.state.defaultFavoriteCount_indexable);
1006 ctx.template storageLoadOnly<Store::favoriteModes>(ctx.state.favorites,
1007 ctx.modeManager.state.defaultFavorites_indexable);
1012 ctx.template storageLoadOnly<Store::usedFavoriteCount>(ctx.modeManager.state.usedFavoriteCount,
1013 ctx.modeManager.state.defaultFavoriteCount_simple);
1014 ctx.template storageLoadOnly<Store::favoriteModes>(ctx.state.favorites,
1015 ctx.modeManager.state.defaultFavorites_simple);
1018 ctx.template storageLoadOnly<Store::lastUsedFavorite>(ctx.modeManager.state.lastFavoriteStep);
1019 ctx.template storageLoadOnly<Store::isInFavoriteGroup>(ctx.state.isInFavoriteMockGroup);
1020 ctx.template storageLoadOnly<Store::modeMemory>(ctx.state.lastModeMemory);
1023 foreach_group<not hasCustomRamp>(ctx, [&ctx](
auto group) {
1024 using LocalStore = details::LocalStoreOf<
decltype(group)>;
1025 LocalStore::template migrateStoreIfNeeded<storeId>();
1027 if constexpr (group.hasCustomRamp)
1029 using StoreHere =
typename LocalStore::EnumTy;
1031 group.template storageLoadOnly<StoreHere::rampMemory>(group.state.customRampMemory,
1032 group.template get_custom_ramp_default_value());
1033 group.template storageLoadOnly<StoreHere::indexMemory>(group.state.customIndexMemory);
1036 group.read_parameters();
1043 dispatch_group(ctx, [](
auto group) {
1044 group.user_thread();
1054 static void custom_ramp_update(
auto& ctx, uint8_t rampValue, uint32_t timeout = 0)
1056 uint8_t groupId = ctx.get_active_group();
1057 uint8_t modeId = ctx.get_active_mode();
1059 if (ctx.everyCustomRamp[groupId][modeId] && ctx.state.rampHandler.animEffect)
1061 switch (ctx.state.rampHandler.animChoice)
1073 dispatch_group(ctx, [&](
auto group) {
1074 group.custom_ramp_update(rampValue);
1079 static bool custom_click(
auto& ctx, uint8_t nbClick)
1081 bool retVal =
false;
1082 dispatch_group(ctx, [&](
auto group) {
1083 retVal = group.custom_click(nbClick);
1089 static bool custom_hold(
auto& ctx, uint8_t nbClickAndHold,
bool isEndOfHoldEvent, uint32_t holdDuration)
1091 bool retVal =
false;
1092 dispatch_group(ctx, [&](
auto group) {
1093 retVal = group.custom_hold(nbClickAndHold, isEndOfHoldEvent, holdDuration);
1110 static void display_favorite_number_ramp(
auto& ctx,
1111 const uint8_t favoriteIndex,
1112 const uint8_t maxFavoriteIndex,
1113 const bool display =
false,
1114 const uint32_t timeout = 0)
1116 const uint8_t maxPixelDisplay = std::min<uint8_t>(ctx.state.maxFavoriteCount, maxFavoriteIndex);
1117 for (uint8_t i = 0; i < maxPixelDisplay; ++i)
1119 const bool shouldDisplay = (display and i <= favoriteIndex);
1120 overlay_animate_dot(
1121 ctx, i, i, shouldDisplay ? 255 : 0, colors::PaletteGradient<colors::Black, colors::Cyan>, timeout);
1125 static uint8_t get_number_of_allowed_favorites(
auto& ctx)
1129 return ctx.state.usedFavoriteCount + ((ctx.state.usedFavoriteCount < ctx.state.maxFavoriteCount) ? 1 : 0);
1136 template<
bool displayFavoriteNumber = true>
1137 static void set_current_mode_as_favorite(
auto& ctx, uint8_t favoriteIndex, uint32_t displayTimeout_s = 0)
1139 const uint8_t numberOfFavoriteSet = get_number_of_allowed_favorites(ctx);
1140 if (favoriteIndex >= numberOfFavoriteSet)
1143 "Cannot set a favorite at index %d, max index must be less than %d", favoriteIndex, numberOfFavoriteSet);
1148 if constexpr (displayFavoriteNumber)
1151 display_favorite_number_ramp(
1152 ctx, favoriteIndex, numberOfFavoriteSet, favoriteIndex < numberOfFavoriteSet, displayTimeout_s);
1156 ctx.state.isFavoritePending = 10;
1157 ctx.state.whichFavoritePending = favoriteIndex;
1166 template<
bool displayFavoriteNumber = true>
1167 static void animate_favorite_pick(
auto& ctx,
float holdDuration,
float stepSize)
1169 const uint8_t numberOfFavoriteSet = get_number_of_allowed_favorites(ctx);
1172 uint32_t stepCount = numberOfFavoriteSet + floor(holdDuration / stepSize);
1173 stepCount = stepCount % (numberOfFavoriteSet + 1);
1176 if (stepCount >= numberOfFavoriteSet)
1179 ctx.state.isFavoritePending = 0;
1182 if (holdDuration <= 2 * stepSize)
1184 overlay_animate_ramp(ctx, holdDuration, stepSize, colors::PaletteGradient<colors::White, colors::Cyan>);
1190 overlay_animate_ramp(ctx, holdDuration, stepSize, colors::PaletteGradient<colors::Green, colors::White>);
1193 set_current_mode_as_favorite<displayFavoriteNumber>(ctx, stepCount);
1203 template<
bool displayFavoriteNumber = true>
1204 static void animate_favorite_delete(
auto& ctx,
float holdDuration,
float stepSize)
1207 if (ctx.state.usedFavoriteCount <= 0)
1210 ctx.state.isInDeleteFavorite =
true;
1212 uint32_t stepCount = floor(holdDuration / stepSize);
1213 stepCount = stepCount % 2;
1217 if (overlay_animate_ramp(ctx, holdDuration, stepSize, colors::PaletteGradient<colors::Orange, colors::Red>))
1220 ctx.state.isFavoriteDeletePending = 2;
1225 ctx.state.isFavoriteDeletePending = 0;
1229 if constexpr (displayFavoriteNumber)
1232 display_favorite_number_ramp(ctx, ctx.state.lastFavoriteStep, ctx.state.usedFavoriteCount,
true);
1243 ActiveIndexTy activeIndex;
1246 hardware::LampTy& lamp;
1249 inline static draw::overlay::Manager<> overlay;
1257 NoState placeholder;
1267 ModeManagerTy<ManagerConfig, std::tuple<Groups...>, 0>;
1296 ModeManagerTy<ManagerConfig, std::tuple<Groups...>, hiddenGroupCnt>;
Handle the main alerts behavior.
Define assertions helpers.
void raise(const Type type)
Raise an alert.
Definition: alerts.cpp:878
ContextTy and associated definitions.
Filesystem interaction tools.
Define the main led strip interaction object.
void lampda_print(const char *format,...)
C linkage to print functions.
Definition: text_out.cpp:227
AlertManager_t manager
Instanciation of the AlertManager.
Definition: alerts.cpp:29
void add_time_minutes(const uint8_t time_minutes)
add some time to the sunset timer. Limited in the range [1; 10] minutes. If the timer is not started ...
Definition: sunset_timer.cpp:170
static constexpr PaletteTy PaletteBlackBodyColors
Black body radiation, with the high end changed to be nicer.
Definition: palettes.hpp:396
std::array< uint32_t, 16 > PaletteTy
Palette types.
Definition: palettes.hpp:18
static constexpr PaletteTy PaletteRainbowColors
HSV Rainbow.
Definition: palettes.hpp:360
@ DOT
Display a pixel dot.
@ indexable
Equivalent to LMBD_LAMP_TYPE__INDEXABLE.
@ simple
Equivalent to LMBD_LAMP_TYPE__SIMPLE.
static void clear_stored()
Force clear the stored parameters.
Definition: keystore.hpp:75
Contains basic interface types to implement custom user modes.
Definition: control_fixed_modes.hpp:12
ModeManagerTy< ManagerConfig, std::tuple< Groups... >, hiddenGroupCnt > ManagerFoHiddenConfig
Same as modes::ManagerFor but with custom defaults, and additional hidden groups.
Definition: manager_type.hpp:1296
ModeManagerTy< DefaultManagerConfig, std::tuple< Groups... >, hiddenGroupCnt > ManagerForHiddenGroups
Group together several mode groups defined through modes::GroupFor. Will use the last hiddenGroupCnt ...
Definition: manager_type.hpp:1289
ModeManagerTy< ManagerConfig, std::tuple< Groups... >, 0 > ManagerForConfig
Same as modes::ManagerFor but with custom defaults.
Definition: manager_type.hpp:1267
@ rampSaturates
(bool) Mode saturates on custom ramp, or else wrap?
ModeManagerTy< DefaultManagerConfig, std::tuple< Groups... >, 0 > ManagerFor
Group together several mode groups defined through modes::GroupFor.
Definition: manager_type.hpp:1277
static auto context_as(auto &ctx)
Bind provided context to another modes::BasicMode.
Definition: context_type.hpp:25
void brightness_update(const brightness_t brightness)
Called when the system changes the LED strip brightness.
Definition: default_behavior.hpp:59
void user_thread()
Called at each tick of the secondary thread.
Definition: default_behavior.hpp:206
void read_parameters()
Called when system wants to read parameters from filesystem.
Definition: default_behavior.hpp:96
void power_on_sequence()
Called when the system powers on (must be non blocking function!)
Definition: default_behavior.hpp:34
void write_parameters()
Called when system wants to write parameters to filesystem.
Definition: default_behavior.hpp:90
void power_off_sequence()
Called when the system powers off (must be non blocking function!)
Definition: default_behavior.hpp:45
void loop()
Called at each tick of the main loop.
Definition: default_behavior.hpp:186
uint16_t brightness_t
Define the type of the brightness parameters.
Definition: constants.h:147
GlobalSimStateTy state
Store the global simulation state.
Definition: simulator_state.cpp:7
Default manager configuration, enables you to customize defaults.
Definition: default_config.hpp:42
Definition: manager_type.hpp:246
RampHandlerTy< Config > scrollHandler
Ramp handlers: mode scroll ramp.
Definition: manager_type.hpp:300
static constexpr uint8_t defaultFavoriteCount_simple
By default, the system will have X favorites.
Definition: manager_type.hpp:278
static constexpr std::array< ActiveIndexTy, maxFavoriteCount > defaultFavorites_indexable
The default favorites are defined below :
Definition: manager_type.hpp:262
bool clearStripOnModeChange
Should clear the strip before switching mode.
Definition: manager_type.hpp:302
RampHandlerTy< Config > rampHandler
Ramp handlers: custom ramp (or "color ramp")
Definition: manager_type.hpp:298
bool isInFavoriteMockGroup
Indicates that we are in the fake favorite page.
Definition: manager_type.hpp:290
static constexpr uint8_t defaultFavoriteCount_indexable
By default, the system will have X favorites.
Definition: manager_type.hpp:260
uint8_t lastFavoriteStep
last used favorite index
Definition: manager_type.hpp:289
AllStatesTy groupStates
All group states, containing all modes individual states.
Definition: manager_type.hpp:248
uint8_t isFavoriteDeletePending
indicate that the deletion of a favorite in in process
Definition: manager_type.hpp:288
ActiveIndexTy beforeFavoriteActiveIndex
store the index we need to go to when quitting the favorite page
Definition: manager_type.hpp:291
static constexpr std::array< ActiveIndexTy, maxFavoriteCount > defaultFavorites_simple
The default favorites are defined below :
Definition: manager_type.hpp:280
uint8_t usedFavoriteCount
number of favorite set by user [0, maxFavoriteCount]
Definition: manager_type.hpp:257
bool isLastScrollAGroupChange
last mode change in scroll changed group
Definition: manager_type.hpp:294
uint8_t whichFavoritePending
indicates the favorite currently selected
Definition: manager_type.hpp:286
uint32_t lastScrollStopped
keep track of the last scrool release time
Definition: manager_type.hpp:295
static void LMBD_INLINE before_enter_mode(auto &ctx)
configuration-related actions done before entering mode
Definition: manager_type.hpp:335
uint8_t isSunsetTimingPending
Indicates that a sunset timer ramp is active.
Definition: manager_type.hpp:292
void reset()
Reset the stored variable states.
Definition: manager_type.hpp:308
std::array< ActiveIndexTy, maxFavoriteCount > favorites
Store the active index of every favorite.
Definition: manager_type.hpp:256
uint8_t skipNextFrameEffect
should the next .loop() mode be skipped?
Definition: manager_type.hpp:305
std::array< uint8_t, nbGroupsTotal > lastModeMemory
When switching group, remember which mode was on last time we visited it.
Definition: manager_type.hpp:251
static constexpr uint8_t maxFavoriteCount
Maximum allowed favorite count.
Definition: manager_type.hpp:254
static void LMBD_INLINE after_enter_mode(auto &ctx)
configuration-related actions done after mode entering
Definition: manager_type.hpp:343
uint8_t isFavoritePending
indicate that the addition of a favorite in in process
Definition: manager_type.hpp:285
bool isInDeleteFavorite
indicates that we are in a favorite deletion process
Definition: manager_type.hpp:287
Logic of the sunset time, eg the system auto stops after a set delay.