commit 3e66c236cc4b0e2bd0da551147de473c933fd488 Author: cfif Date: Mon Jun 2 13:26:40 2025 +0300 Init diff --git a/Inc/UserInputButtonWatcher.h b/Inc/UserInputButtonWatcher.h new file mode 100644 index 0000000..90ba32d --- /dev/null +++ b/Inc/UserInputButtonWatcher.h @@ -0,0 +1,76 @@ +// +// Created by xemon on 16.11.22. +// + +#ifndef UVEOS_ON_NATION_USERINPUTWATCHBUTTON_H +#define UVEOS_ON_NATION_USERINPUTWATCHBUTTON_H + +#include +#include "stdbool.h" +#include "stdint.h" + +#include "GpioPinInterface.h" +#include "UserInputButtonEvent.h" +#include "UserButtonsInterface.h" +#include "Adcs.h" + +typedef struct { + void *env; + + bool (*getState)(); +} tUserInputCustomSwitch; + +typedef struct { + tGpioPin pin; + + tUserInputCustomSwitch custom; + bool isCustom; + bool kostil; + bool state; + uint32_t begin; + uint32_t previousBegin; + bool fired; + uint16_t buttonId; + uint16_t buttonPressTime; + uint32_t beginTime; +} tUserInputButtonWatch; + +typedef struct { + tUserInputButtonWatch *watches; + uint16_t watchesLimit; + uint16_t watchesCount; + uint32_t minimalDuration; + osMessageQueueId_t eventsOutQueue; + +} tUserInputButtonWatcher; + +void UserInputButtonWatcher_Init( + tUserInputButtonWatcher *env, + tUserInputButtonWatch *watchesMem, + uint16_t watchesLimit, + size_t eventsQueueLength +); + +#define UserInputButtonWatcher_InitStatic(ENV, MEM, LEN) UserInputButtonWatcher_Init(ENV, MEM , sizeof(MEM)/sizeof(tUserInputButtonWatch),LEN) + +bool UserInputButtonWatcher_Add(tUserInputButtonWatcher *env, tGpioPin pin, uint16_t id); + +bool UserInputButtonWatcher_AddAdc(tUserInputButtonWatcher *env, tAdc adc, uint16_t id); + +bool UserInputButtonWatcher_CustomGetter(tUserInputButtonWatcher *env,tAdc adc,uint16_t id); + +bool UserInputButtonWatcher_AddCustom( + tUserInputButtonWatcher *env, void *customEnv, bool (*customGetter)(), uint16_t id +); + +void UserInputButtonWatcher_Check(tUserInputButtonWatcher *env); + +void UserInputButtonWatcher_Clear(tUserInputButtonWatcher *env); + +void UserInputButtonWatcher_SimulateButton(tUserInputButtonWatcher *env, uint16_t butId); + +bool UserInputButtonWatcher_GetNext(tUserInputButtonWatcher *env, tUserInputButtonEvent *next, uint32_t timeout); + +tUserButtonsInterface UserInputButtonWatcher_GetInterface(tUserInputButtonWatcher *env); + +#endif //UVEOS_ON_NATION_USERINPUTWATCHBUTTON_H diff --git a/Src/UserInputButtonWatcher.c b/Src/UserInputButtonWatcher.c new file mode 100644 index 0000000..19d8880 --- /dev/null +++ b/Src/UserInputButtonWatcher.c @@ -0,0 +1,156 @@ +#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 \ No newline at end of file diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..8c30893 --- /dev/null +++ b/modular.json @@ -0,0 +1,22 @@ +{ + "dep": [ + { + "type": "git", + "provider": "Smart_Components_Aurus", + "repo": "UserInputEvent" + }, + { + "type": "git", + "provider": "Smart_Components_Aurus", + "repo": "UserButtonsInterface" + } + ], + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file