#include <Arduino.h>
#include <LiquidCrystal_I2C.h>


#define RE_CLK (14)
#define RE_DT (12)
#define RE_SW (13)
#define NUM_INFO_PAGE (4)
#define NUM_SETTING_PAGE (4)
#define RELAY_PIN (25)

LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 16, 2);


TaskHandle_t RotaryRollHandles[NUM_INFO_PAGE];
TaskHandle_t RotaryClickHandles;
TimerHandle_t timer;

volatile int8_t display = (NUM_INFO_PAGE - 1);
volatile bool SETTING_MODE = false;


void IRAM_ATTR rotaryRollISR() {
  int8_t step = digitalRead(RE_DT) ? 1 : -1;
  display = (NUM_INFO_PAGE + display + step) % NUM_INFO_PAGE;

  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  vTaskNotifyGiveFromISR(RotaryRollHandles[display], &xHigherPriorityTaskWoken);
  if (xHigherPriorityTaskWoken) {
    portYIELD_FROM_ISR();
  }
}

void IRAM_ATTR rotaryClickISR() {

  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  vTaskNotifyGiveFromISR(RotaryClickHandles, &xHigherPriorityTaskWoken);
  if (xHigherPriorityTaskWoken) {
    portYIELD_FROM_ISR();
  }
}

void TaskRotaryRoll(void *param) {
  uint8_t id = (uint8_t)(uint32_t)param;

  for (;;) {
    if (ulTaskNotifyTake(pdTRUE, portMAX_DELAY)) {
      if (xTimerIsTimerActive(timer)) {
        xTimerReset(timer, 0);
      }
      vTaskDelay(100 / portTICK_PERIOD_MS);
    }
  }
}

void TaskRotaryClick(void *param) {

  for (;;) {
    if (ulTaskNotifyTake(pdTRUE, portMAX_DELAY)) {
      SETTING_MODE = true;
      if (xTimerIsTimerActive(timer)) {
        xTimerReset(timer, 0);
      } else {
        // Start the timer if it's not already running
        xTimerStart(timer, 0);
      }
    }
  }
}

void timer_callback(TimerHandle_t xTimer) {
    SETTING_MODE = false;
    xTimerStop(timer, 0);
}

void TaskDisplayOnLCD(void *param) {

  for (;;) {
    LCD.clear();
    LCD.setCursor(0, 0);
    if(SETTING_MODE){
      LCD.println("SETTING");
    } else{
      char result[50];
      sprintf(result, "Info Page : %d", display);
      LCD.println(result);
    }
    vTaskDelay(30 / portTICK_PERIOD_MS);
  }
}

void TaskRelayControl(void *param) {

  for (;;) {
    digitalWrite(RELAY_PIN, HIGH);
    vTaskDelay(30 / portTICK_PERIOD_MS);
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(RE_CLK, INPUT_PULLUP);
  pinMode(RE_DT, INPUT_PULLUP);
  pinMode(RE_SW, INPUT_PULLUP);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);

  LCD.init();
  LCD.backlight();
  LCD.clear();
  LCD.setCursor(0, 0);
  timer = xTimerCreate("Timer", 5000 / portTICK_PERIOD_MS, pdTRUE, 0, timer_callback);


  attachInterrupt(digitalPinToInterrupt(RE_CLK), rotaryRollISR, FALLING);
  attachInterrupt(digitalPinToInterrupt(RE_SW), rotaryClickISR, FALLING);
  for (uint8_t i = 0; i < NUM_INFO_PAGE; i++) {
    xTaskCreate(TaskRotaryRoll, "task", 2048, (void *)(uint32_t)i, tskIDLE_PRIORITY+1, &RotaryRollHandles[i]);
  }
  xTaskCreate(TaskRotaryClick, "Setting Mode Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1, &RotaryClickHandles);
  xTaskCreate(TaskDisplayOnLCD, "DisplayOnLCD", 2048, NULL, tskIDLE_PRIORITY+1, NULL);
}

void loop() {}
$abcdeabcde151015202530354045505560fghijfghij
$abcdeabcde151015202530354045505560fghijfghij
NOCOMNCVCCGNDINLED1PWRRelay Module