15 profileSlots[profileIndex] = std::move(profile);
21 if (profileIndex <
MAX_PROFILES && profileSlots[profileIndex])
23 return profileSlots[profileIndex]->getAction(button);
30 if (profileIndex <
MAX_PROFILES && profileSlots[profileIndex])
32 return profileSlots[profileIndex].get();
40 uint8_t next = currentProfile;
41 for (uint8_t i = 0; i < numProfiles; i++)
43 int temp = (next + 1) % numProfiles;
44 next =
static_cast<uint8_t
>(temp);
45 if (profileSlots[next])
50 currentProfile = next;
51 postSwitchBlink =
true;
56 return currentProfile;
67void ProfileManager::updateLEDs()
77 if (numProfiles <= numLeds)
80 for (uint8_t i = 0; i < numLeds && i < static_cast<uint8_t>(selectLeds.size()); i++)
82 selectLeds[i]->setState(i == currentProfile);
88 auto bits =
static_cast<uint8_t
>(currentProfile + 1);
89 for (uint8_t i = 0; i < numLeds && i < static_cast<uint8_t>(selectLeds.size()); i++)
91 selectLeds[i]->setState((bits & (1U << i)) != 0);
98 if (! postSwitchBlink)
106 blinkStartTime = now;
107 for (
auto* led : selectLeds)
114 uint32_t elapsed = now - blinkStartTime;
115 auto phase =
static_cast<uint8_t
>(elapsed / BLINK_INTERVAL);
117 if (phase == blinkPhase)
123 uint8_t totalHalfCycles = BLINK_COUNT * 2;
124 if (phase >= totalHalfCycles)
126 postSwitchBlink =
false;
131 bool on = (phase % 2 == 0);
132 for (
auto* led : selectLeds)
140 if (profileIndex <
MAX_PROFILES && profileSlots[profileIndex])
142 currentProfile = profileIndex;
151 for (uint8_t i = 0; i < numProfiles; i++)
159 postSwitchBlink =
false;
165 if (profileIndex <
MAX_PROFILES && profileSlots[profileIndex])
167 return profileSlots[profileIndex]->getName();
169 static const std::string emptyString;
175 for (
const auto& slot : profileSlots)
183 const Action* action = slot->getAction(b);
204 return "SendMediaKey";
206 return "SerialOutput";
Base class for all pedal actions.
virtual bool isInProgress() const
Returns true if the action is currently in progress (e.g.
ProfileManager(std::vector< ILEDController * > leds)
bool hasActiveDelayedAction() const
Returns true if any DelayedAction across all profiles is currently running.
const std::string & getProfileName(uint8_t profileIndex) const
const Profile * getProfile(uint8_t profileIndex) const
static constexpr uint8_t MAX_PROFILES
2^6 − 1 (6 select LEDs max)
Action * getAction(uint8_t profileIndex, uint8_t button) const
static const char * getActionTypeString(Action::Type actionType)
void resetToFirstProfile()
Reset to the first populated slot (or slot 0 if all empty)
void setCurrentProfile(uint8_t profileIndex)
Directly set the current profile without triggering blink feedback.
void update(uint32_t now)
Drive timed LED behaviour — call every loop iteration.
uint8_t switchProfile()
Advance to the next populated profile slot and trigger blink feedback.
void addProfile(uint8_t profileIndex, std::unique_ptr< Profile > profile)
Represents a single button configuration profile.
static constexpr uint8_t MAX_BUTTONS
Maximum buttons per profile (A–Z)
const HardwareConfig hardwareConfig
Global hardware configuration instance.
std::vector< ILEDController * > selectLeds
uint8_t numSelectLeds
Profile-select LEDs wired; caps profiles at 2^n − 1.
uint8_t numProfiles
Number of active profiles (1..MAX_PROFILES)