UserInputWatchButtons/Src/UserInputButtonWatcher.c

156 lines
4.4 KiB
C

#include "UserInputButtonWatcher.h"
#include "SystemDelayInterface.h"
#pragma GCC push_options
#pragma GCC optimize ("O0")
void UserInputButtonWatcher_Init(
tUserInputButtonWatcher *env,
tUserInputButtonWatch *watchesMem,
uint16_t watchesLimit,
size_t eventsQueueLength
) {
env->minimalDuration = 50;
env->eventsOutQueue = osMessageQueueNew(eventsQueueLength, sizeof(tUserInputButtonEvent), NULL);
env->watchesCount = 0;
env->watches->beginTime = 0;
env->watches->kostil = false;
env->watches = watchesMem;
env->watchesLimit = watchesLimit;
}
bool UserInputButtonWatcher_Add(
tUserInputButtonWatcher *env,
tGpioPin pin,
uint16_t id
) {
if (env->watchesCount >= env->watchesLimit) {
return false;
}
tUserInputButtonWatch *next = env->watches + env->watchesCount;
*next = (tUserInputButtonWatch) {
.begin=osKernelGetTickCount(),
.state= GpioPinGet(&pin),
.pin = pin,
.fired = true,
.buttonId = id,
.custom = (tUserInputCustomSwitch) {
.env = NULL,
.getState = NULL,
}
};
++env->watchesCount;
return true;
}
bool UserInputButtonWatcher_AddCustom(
tUserInputButtonWatcher *env,
void *customEnv,
bool (*customGetter)(),
uint16_t id
) {
if (env->watchesCount >= env->watchesLimit) {
return false;
}
tUserInputButtonWatch *next = env->watches + env->watchesCount;
*next = (tUserInputButtonWatch) {
.begin=osKernelGetTickCount(),
.state= customGetter(customEnv),
.fired = true,
.buttonId = id,
.custom = (tUserInputCustomSwitch) {
.env = customEnv,
.getState = customGetter,
}
};
++env->watchesCount;
return true;
}
void UserInputButtonWatcher_CheckButton(tUserInputButtonWatcher *env, tUserInputButtonWatch *watch, uint32_t NOW) {
bool current = false;
if (watch->custom.getState) {
current = watch->custom.getState(watch->custom.env);
} else {
current = GpioPinGet(&watch->pin);
}
if (watch->state != current) {
if (watch->fired) {
watch->previousBegin = watch->begin;
watch->state = current;
watch->begin = NOW;
watch->fired = false;
} else {
watch->begin = watch->previousBegin;
watch->state = current;
watch->fired = true;
}
}
if (!watch->fired) {
uint32_t currentDuration = NOW - watch->begin;
currentDuration = currentDuration + 60;
if (currentDuration > env->minimalDuration) {
tUserInputButtonEvent event = {
.buttonId =watch->buttonId,
.duration = watch->begin - watch->previousBegin,
.action = watch->state == false ? USER_INPUT_BUTTON_ACTION_RAISE
: USER_INPUT_BUTTON_ACTION_FALL
};
watch->fired = true;
osMessageQueuePut(env->eventsOutQueue, &event, 0U, 100U);
}
}
}
void UserInputButtonWatcher_SimulateButton(tUserInputButtonWatcher *env, uint16_t butId) {
tUserInputButtonEvent event = {
.buttonId = butId,
.duration = 1000,
.action = USER_INPUT_BUTTON_ACTION_RAISE
};
osMessageQueuePut(env->eventsOutQueue, &event, 0U, 100U);
}
void UserInputButtonWatcher_Check(tUserInputButtonWatcher *env) {
uint32_t NOW = osKernelGetTickCount();
for (uint16_t watchIdx = 0; watchIdx < env->watchesCount; ++watchIdx) {
UserInputButtonWatcher_CheckButton(env, env->watches + watchIdx, NOW);
}
}
void UserInputButtonWatcher_Clear(tUserInputButtonWatcher *env) {
osMessageQueueReset(env->eventsOutQueue);
}
bool UserInputButtonWatcher_GetNext(tUserInputButtonWatcher *env, tUserInputButtonEvent *next, uint32_t timeout) {
return osMessageQueueGet(env->eventsOutQueue, next, 0, timeout) == osOK;
}
tUserButtonsInterface UserInputButtonWatcher_GetInterface(tUserInputButtonWatcher *env) {
tUserButtonsInterface result = {
.env = env,
.clear = (userButtonsCall) UserInputButtonWatcher_Clear,
.getNextEvent = (userButtonsNextEventCall) UserInputButtonWatcher_GetNext
};
return result;
}
#pragma GCC pop_options