#include "IR_CMD_Handler.h" #include "IR.h" #include "SimpleTimer.h" #include "ShiftReg.h" #include "Print.h" #define IR_Timeout 137 #define ResetInputProgerss_Timeout 2500 #define InitialRepeatTime 100 // Начальный интервал времени между вызовами функции при удержании #define MinRepeatTime 30 // Минимально допустимый интервал времени между вызовами функции при удержании #define HoldTime 500 // Время, необходимое для определения удержания #define RepeatDecay 10 // Шаг уменьшения времени между вызовами функции при удержании #define NULL_NumberParam 0xFFFF //extern unsigned char IR_Command; //extern unsigned char IR_Address; extern unsigned char IRStatus; IRData data; IRData old_data; uint32_t IR_Timeout_timer = 0; uint8_t dataHandled_flag = 0; uint32_t inputInProgerss_timer = 0; uint8_t inputInProgerss = 0; uint8_t digitInputInProgerss = 0; uint8_t inputDigit = 0; // left = 0 to right uint16_t inputParam = NULL_NumberParam; uint32_t holdStartTime = 0; // Время начала удержания uint32_t lastRepeatTime = 0; // Последнее время повторного вызова функции uint32_t currentRepeatTime = InitialRepeatTime; // Текущее значение интервала между вызовами функции void IR_Home_Process(); void IR_ParamEnter(); void IR_CMD_Clear(); void (*InputHandler)(void) = IR_Home_Process; void NullFunc(){}; void (*onParamEnter)() = NullFunc; void (*onHoldRepeat)() = NullFunc; // Указатель на функцию, вызываемую при удержании void paramEnter(void(*onEnter_)()){ InputHandler = IR_ParamEnter; onParamEnter = onEnter_; } // Установка функции для вызова при удержании void setHoldRepeatHandler(void (*handler)()) { onHoldRepeat = handler; } void IR_CMD_Handler() { // timeout tick if (dataHandled_flag && (millis() - IR_Timeout_timer > IR_Timeout)) { dataHandled_flag = 0; } if (inputInProgerss && (millis() - inputInProgerss_timer > ResetInputProgerss_Timeout)) { IR_CMD_Clear(); } // cmd handler if (IR_Available()) { data = getIRData(); IR_Timeout_timer = millis(); // works once per button press if (memcmp(&data, &old_data, sizeof(IRData)) != 0 || !dataHandled_flag) { dataHandled_flag = 1; if (IR_Address == 0x01) { onHoldRepeat = NullFunc; InputHandler(); inputInProgerss = 1; inputInProgerss_timer = millis(); holdStartTime = millis(); // Запоминаем время начала удержания lastRepeatTime = holdStartTime; // Инициализируем таймер повторного вызова currentRepeatTime = InitialRepeatTime; // Сбрасываем интервал повторного вызова } memcpy(&old_data, &data, sizeof(IRData)); } else { // Проверка на удержание кнопки if (millis() - holdStartTime > HoldTime) { // Если кнопка удерживается дольше HoldTime if (millis() - lastRepeatTime > currentRepeatTime) { // Если прошло достаточно времени для повторного вызова lastRepeatTime = millis(); // Обновляем время последнего вызова onHoldRepeat(); // Вызываем функцию при удержании // Уменьшаем интервал до минимального значения if (currentRepeatTime > MinRepeatTime) { currentRepeatTime -= RepeatDecay; if (currentRepeatTime < MinRepeatTime) { currentRepeatTime = MinRepeatTime; } } } } } IR_Timeout_timer = millis(); ClearIRStatus(); } } void IR_CMD_Clear() { InputHandler = IR_Home_Process; inputDigit = 0; inputInProgerss = 0; digitInputInProgerss = 0; inputParam = NULL_NumberParam; // SetShiftReg_inline(0, 0xff, 0); } void IR_ParamEnter() { // SetShiftReg_inline(0x03, 0, 0); if (0 <= data.command && data.command <= 9) { if (digitInputInProgerss) { inputParam = inputParam * 10; // dec shift << 1 inputParam += (data.command + 1) % 10; // SetShiftReg_inline(0xF0, 0, 0); } else { inputParam = (data.command + 1) % 10; } digitInputInProgerss = 1; } else { digitInputInProgerss = 0; switch (data.command) { case IR_ENTER: if(inputParam != NULL_NumberParam){ print("Enter: "); printNumber(inputParam); // SetShiftReg_inline(0, 0, inputParam); onParamEnter(); } inputParam = NULL_NumberParam; digitInputInProgerss = 0; break; default: IR_Home_Process(); break; } } }