From 97e9e68d35044b378cca547bf59fed707e9bd4ef Mon Sep 17 00:00:00 2001 From: RnD1 Date: Fri, 17 Apr 2026 11:34:49 +0900 Subject: [PATCH] ZCD optimizations --- BLEScan.cpp | 9 +++ ConnectWiFi.cpp | 2 +- HermitCrab.h | 2 +- HermitCrab.ino | 95 +++++++++++----------- NTC_10K.cpp | 6 +- OTA.cpp | 2 +- Setup.cpp | 12 ++- Task0.ino | 4 +- UI.cpp | 6 +- WiFiHost.cpp | 7 +- zcd.cpp | 207 ++++++++++++++++++++++++++++++++++-------------- 11 files changed, 230 insertions(+), 122 deletions(-) diff --git a/BLEScan.cpp b/BLEScan.cpp index ec49e5f..6b5a708 100644 --- a/BLEScan.cpp +++ b/BLEScan.cpp @@ -1,3 +1,12 @@ +// ==================================================================== +// +// Tuya 1 MAC: 38:1F:8D:77:73:34 +// Tuya 1 MAC: 38:1F:8D:CB:ED:78 +// Xiami MAC: A4:C1:38:E7:58:CF +// +// ==================================================================== + + #include #include #include diff --git a/ConnectWiFi.cpp b/ConnectWiFi.cpp index 8480caa..0d1359a 100644 --- a/ConnectWiFi.cpp +++ b/ConnectWiFi.cpp @@ -59,7 +59,7 @@ void checkWiFi(unsigned long tickMillis) { // Connecting if (bConnecting) { if (tickMillis - lastAttempt < 60000) { - // give 30 seconds for connection try + // give 60 seconds for connection try return; } diff --git a/HermitCrab.h b/HermitCrab.h index 28c10e7..fda4aed 100644 --- a/HermitCrab.h +++ b/HermitCrab.h @@ -239,5 +239,5 @@ extern bool bShowSensor; extern const char *COMPANY_NAME; extern const char *SERVICE_NAME; extern const char *HC__VERSION; - +extern volatile uint32_t g_millis; #endif diff --git a/HermitCrab.ino b/HermitCrab.ino index 2ee9b75..451bed0 100644 --- a/HermitCrab.ino +++ b/HermitCrab.ino @@ -10,6 +10,7 @@ #include "OTA.h" #include "UI.h" #include "BLEScan.h" +#include "hal/timer_ll.h" #if defined(ESP32) #include "esp_wifi.h" @@ -20,6 +21,8 @@ STATUS_TYPE status; // Time volatile unsigned short g_nYear, g_nMonth, g_nDay, g_nHour, g_nMinute, g_nSecond; +volatile uint32_t g_millis = 0l; +extern timg_dev_t *tg1; // Environment bool bShowSensor = false; @@ -44,14 +47,14 @@ void controlLightDuty(); // // ================================================================================== MY_IRAM_ATTR void loop() { - static unsigned long lastTickSecond = 0; - static uint8_t lastSecond = -1; - unsigned long tickMillis = millis(); - unsigned long tickSecond = tickMillis / 1000; + static unsigned long lastTickSecond = 0; + static uint8_t lastSecond = -1; + g_millis = (uint32_t)timer_ll_get_counter_value(tg1, 1); + unsigned long tickMillis = g_millis; + unsigned long tickSecond = tickMillis / 1000; - - // Un-Conditional Loop - { + // Un-Conditional Loop + { //ESP_LOGI(TAG_MAIN,"Checking WiFi2"); //checkWiFi(tickMillis); @@ -60,59 +63,59 @@ MY_IRAM_ATTR void loop() { // UI Button Check ui.loopButton(tickMillis); - } + } - // Every Second - if (tickSecond != lastTickSecond) - { - // Time and ZCD - setZCD(); - setTime(); + // Every Second + if (tickSecond != lastTickSecond) + { + // Time and ZCD + setZCD(); + setTime(); - // Temperature and Humidity - readSensors(); - //ble.loop(tickMillis); + // Temperature and Humidity + readSensors(); + //ble.loop(tickMillis); - // Fan, Motor, Light Duties - controlFanDuty(); - controlMotorDuty(); - controlLightDuty(); + // Fan, Motor, Light Duties + controlFanDuty(); + controlMotorDuty(); + controlLightDuty(); - // Add to History - every minutes - if (g_nSecond == 0 && lastSecond != g_nSecond) { - history.add(status); - } - lastSecond = g_nSecond; + // Add to History - every minutes + if (g_nSecond == 0 && lastSecond != g_nSecond) { + history.add(status); + } + lastSecond = g_nSecond; - // Every 10 Second - switch(tickSecond % 10) { + // Every 10 Second + switch(tickSecond % 10) { case 1: // Every 5 second - xx:xx-x7 - if (bShowSensor) { + if (bShowSensor) { ESP_LOGI(TAG_MAIN, "%s\n", printStatus(tickSecond, true)); - } - break; + } + break; case 2: // AC1 - controlAC1(status.nTemp1, tickSecond); - break; + controlAC1(status.nTemp1, tickSecond); + break; case 3: // AC2 - controlAC2(status.nTemp1, tickSecond); - break; + controlAC2(status.nTemp1, tickSecond); + break; case 4: // Mist - controlMist(status.nHumid1, tickSecond); - break; + controlMist(status.nHumid1, tickSecond); + break; case 5: // Fan Control - controlFan(status.nTemp1, tickSecond); - break; + controlFan(status.nTemp1, tickSecond); + break; case 6: // Motor Control - controlMotor(g_nHour, g_nMinute, tickSecond); - break; + controlMotor(g_nHour, g_nMinute, tickSecond); + break; case 7: // Light Control - controlLight(g_nHour, g_nMinute, tickSecond); - break; + controlLight(g_nHour, g_nMinute, tickSecond); + break; default: - break; - } - lastTickSecond = tickSecond; + break; + } + lastTickSecond = tickSecond; } yield(); } diff --git a/NTC_10K.cpp b/NTC_10K.cpp index a4b6fdd..5a8b4aa 100644 --- a/NTC_10K.cpp +++ b/NTC_10K.cpp @@ -69,7 +69,7 @@ void NTC_10K::setup(bool bNegativePolarity) { _vRef = 3.3f; _RESO = 4095; m_nTemp = -9999; - m_fTemp = -9999.0; + m_fTemp = -9999.0f; m_fLastTemp = 0.0f; pinMode(PIN_NTC, INPUT); // Set PIN_NTC as input @@ -125,8 +125,8 @@ void NTC_10K::readSensor() { if (m_fTemp < -5000.0f) { m_fTemp = currentInstantTemp; } else { - // 0.01f Alpha: The 5°C PWM noise now only moves the buffer by 0.05°C per hit. - const float alpha = 0.05f; + // 0.005f Alpha: The 5°C PWM noise now only moves the buffer by 0.05°C per hit. + const float alpha = 0.005f; m_fTemp = (currentInstantTemp * alpha) + (m_fTemp * (1.0f - alpha)); } diff --git a/OTA.cpp b/OTA.cpp index 6fa3fa3..6065aa9 100644 --- a/OTA.cpp +++ b/OTA.cpp @@ -17,7 +17,7 @@ // OTA // // ============================================================== -const char *HC__VERSION = "20260415001"; +const char *HC__VERSION = "20260416002"; #define UPDATE_PORT ((uint16_t) 443) const char *url = "visionsoft.kr"; const char *uri = "/sc/pages/firmware_download.php"; diff --git a/Setup.cpp b/Setup.cpp index ecd8e26..1ad34ad 100644 --- a/Setup.cpp +++ b/Setup.cpp @@ -12,6 +12,7 @@ #include "BLEScan.h" #include #include "esp_coexist.h" +#include "hal/timer_ll.h" #define TAG_SETUP "TAG_SETUP" // Task handle @@ -22,6 +23,7 @@ bool g_bWiFiHasBeenConnected = false; extern STATUS_TYPE status; extern CHistory history; +extern timg_dev_t *tg1; void setupConfig(); void setupStatus(); @@ -35,6 +37,14 @@ void setup_BLE(); void scanI2C(); void setup() { + timer_ll_set_clock_prescale(tg1, 1, 80000); + timer_ll_set_count_direction(tg1, 1, GPTIMER_COUNT_UP); + tg1->hw_timer[1].loadhi.val = 0UL; + tg1->hw_timer[1].loadlo.val = 0UL; + tg1->hw_timer[1].load.val = 1UL; + timer_ll_enable_alarm(tg1, 1, false); // No ISR needed for watchdog + timer_ll_enable_counter(tg1, 1, true); + // put your setup code here, to run once: #ifdef DEBUG Serial.begin(115200); @@ -171,7 +181,7 @@ void setupPostWiFi(bool bBoot = false) { DPRINTLN(" Trying OTA"); ui.message(2, (char *) "Update check..."); checkOTA(true); - ui.message(2, (char *) "Update check...OK!"); + ui.message(2, (char *) "Update OK!"); DPRINTLN(" OTA Process completed!"); DPRINTLN("===============================\n"); } else { diff --git a/Task0.ino b/Task0.ino index 49b7903..d009d87 100644 --- a/Task0.ino +++ b/Task0.ino @@ -25,7 +25,7 @@ MY_IRAM_ATTR void core0Task(void *pvParameters) { ESP_LOGI(TAG_TASK0,"Core 0 Task Started"); DPRINTLN("Core 0 Task Started"); wl_status_t lastWiFiStatus = WL_DISCONNECTED; - unsigned long tickMillis = millis(); + unsigned long tickMillis = g_millis; unsigned long tickSecond; uint8_t slot; uint8_t lastSlot = 255; @@ -36,7 +36,7 @@ MY_IRAM_ATTR void core0Task(void *pvParameters) { while (true) { esp_task_wdt_reset(); - tickMillis = millis(); + tickMillis = g_millis; tickSecond = tickMillis / 1000; slot = (tickMillis % 1000) / 50; diff --git a/UI.cpp b/UI.cpp index 601e008..8f1554e 100644 --- a/UI.cpp +++ b/UI.cpp @@ -1135,18 +1135,18 @@ void CUI::checkButtonStates(unsigned long currentMillis) { // ISR for the Set button handling ARDUINO_ISR_ATTR void buttonSetISR() { // Record the time of the button interrupt and set a flag - ui.buttonSetChangeTime = millis(); + ui.buttonSetChangeTime = g_millis; ui.bButtonSetChanged = true; // Flag for main loop to process } // ISR for the Up button handling ARDUINO_ISR_ATTR void buttonUpISR() { - ui.buttonUpChangeTime = millis(); + ui.buttonUpChangeTime = g_millis; ui.bButtonUpChanged = true; // Flag for main loop to process } // ISR for the Down button handling ARDUINO_ISR_ATTR void buttonDownISR() { - ui.buttonDownChangeTime = millis(); + ui.buttonDownChangeTime = g_millis; ui.bButtonDownChanged = true; // Flag for main loop to process } \ No newline at end of file diff --git a/WiFiHost.cpp b/WiFiHost.cpp index 1cf9ecf..9e3382b 100644 --- a/WiFiHost.cpp +++ b/WiFiHost.cpp @@ -81,12 +81,12 @@ void CWiFiHost::Setup() //sockfd = -1; //connectStartTime = 0; //isConnecting = false; - + // Operation m_nMode = MODE_WAITING; m_bHelloSent = false; m_bSendHistoryPending = false; - + m_nLastReceivedTime = m_nLastHeartBeatSentTime = m_nLastUDPBroadcastTime = millis(); @@ -121,7 +121,6 @@ void CWiFiHost::Setup() // Server wifiServer.begin(SERVER_PORT, 1); //wifiExternal.begin(m_nPublicPort, 1); - m_nLastReceivedTime = millis(); m_bClientConnected = false; // UDP @@ -398,7 +397,7 @@ void CWiFiHost::ProcessPacket(TCP_PACKET& pkt) { // System case CMD_HEARTBEAT: - m_nLastReceivedTime = millis(); + m_nLastReceivedTime = g_millis; //ESP_LOGI(TAG_WIFI_HOST,"H"); break; case CMD_HELLO: diff --git a/zcd.cpp b/zcd.cpp index ed3c17a..a6fe3a8 100644 --- a/zcd.cpp +++ b/zcd.cpp @@ -6,11 +6,43 @@ #include #include +#include "hal/timer_ll.h" +#include "hal/timer_types.h" +#include "driver/timer.h" // Needed for timer_isr_register + +// Assuming tg0 is defined as: timg_dev_t *tg0 = &TIMG0; +timg_dev_t *tg0 = &TIMERG0; +timg_dev_t *tg1 = &TIMERG1; + +#define SET_TIMER_1(duty) do { \ + timer_ll_enable_counter(tg0, 0, false); \ + tg0->hw_timer[0].loadhi.val = 0; \ + tg0->hw_timer[0].loadlo.val = 0; \ + tg0->hw_timer[0].load.val = 1; \ + timer_ll_set_alarm_value(tg0, 0, duty); \ + timer_ll_enable_alarm(tg0, 0, true); \ + timer_ll_enable_counter(tg0, 0, true); \ +} while(0) + +#define SET_TIMER_2(duty) do { \ + timer_ll_enable_counter(tg0, 1, false); \ + tg0->hw_timer[1].loadhi.val = 0; \ + tg0->hw_timer[1].loadlo.val = 0; \ + tg0->hw_timer[1].load.val = 1; \ + timer_ll_set_alarm_value(tg0, 1, duty); \ + timer_ll_enable_alarm(tg0, 1, true); \ + timer_ll_enable_counter(tg0, 1, true); \ +} while(0) + + #define TAG_ZCD "ZCD" // Constants #define EFFECTIVE_POWER 0.86 #define LEADING_TIME_RATIO 0.06 +#define PHASE_CONTROL 0 +#define ZCD_CONTROL 1 + // ESP32 Clock Constants const uint32_t AC_CYCLE_TIME_CLOCKS = 8333; // Half cycle of 60Hz AC in clock cycles const uint32_t EFFECTIVE_HALF_CYCLE = EFFECTIVE_POWER * AC_CYCLE_TIME_CLOCKS; // Effective half cycle in clock cycles @@ -23,9 +55,31 @@ volatile uint32_t dutyHeater2; // Calculated timerZCD count for TRIAC firing volatile uint8_t zcdACCount; volatile uint8_t zcdLoadCount; +volatile uint8_t ac1ControlMode = PHASE_CONTROL; +volatile uint8_t ac2ControlMode = PHASE_CONTROL; + +volatile uint8_t fireStatusTimer1 = 0; +volatile uint8_t fireStatusTimer2 = 0; + + hw_timer_t *timerHeater1; hw_timer_t *timerHeater2; +const char fireTable[9][8] { {0, 0, 0, 0, 0, 0, 0, 0}, // 0 - 0% + {1, 0, 0, 0, 0, 0, 0, 0}, // 1 - 12.5% + {1, 0, 0, 0, 1, 0, 0, 0}, // 2 - 25% + {1, 0, 0, 1, 0, 0, 1, 0}, // 3 - 37.5% + {1, 0, 1, 0, 1, 0, 1, 0}, // 4 - 50% + {1, 1, 0, 1, 1, 0, 1, 0}, // 5 - 62.5% + {1, 1, 1, 0, 1, 1, 1, 0}, // 6 - 75% + {1, 1, 1, 1, 1, 1, 1, 0}, // 7 - 87.5% + {1, 1, 1, 1, 1, 1, 1, 1}}; // 8 - 100% +uint8_t seqStep = 0; +uint8_t dutyAC1 = 0; +uint8_t dutyAC2 = 0; + +void setAC1ControlMode(uint8_t mode) { ac1ControlMode = mode; } +void setAC2ControlMode(uint8_t mode) { ac2ControlMode = mode; } short getHeater1Duty() { if (dutyHeater1 == 0) return 0; @@ -41,25 +95,29 @@ short getHeater2Duty() { // Function to set the duty based on percentage (0 to 10000) ARDUINO_ISR_ATTR void setHeater1Duty(short duty) { - if (duty <= 0) { - dutyHeater1 = 0; // If 0% duty, no pulse (turn off TRIAC) - } else if (duty >= 10000) { - // 100% duty corresponds to the leading pulse + full effective half cycle - dutyHeater1 = LEADING_PULSE_COUNT; + if (ac1ControlMode == ZCD_CONTROL) { + dutyAC1 = (uint8_t)((duty + 10000/16)/1250); } else { - // Map duty to power ratio (0 to 1) - float powerRatio = (float) duty / 10000.0f; + if (duty <= 0) { + dutyHeater1 = 0; // If 0% duty, no pulse (turn off TRIAC) + } else if (duty >= 10000) { + // 100% duty corresponds to the leading pulse + full effective half cycle + dutyHeater1 = LEADING_PULSE_COUNT; + } else { + // Map duty to power ratio (0 to 1) + float powerRatio = (float) duty / 10000.0f; - // Calculate the angle in radians using the inverse cosine directly - float angleRadians = acosf(1.0f - 2.0f * powerRatio); + // Calculate the angle in radians using the inverse cosine directly + float angleRadians = acosf(1.0f - 2.0f * powerRatio); - // Convert angle to time delay (in clock cycles) - // Normalized angle (0 to PI) maps to half-cycle (0 to EFFECTIVE_HALF_CYCLE) - uint32_t pulseCount = (angleRadians / M_PI) * EFFECTIVE_HALF_CYCLE; + // Convert angle to time delay (in clock cycles) + // Normalized angle (0 to PI) maps to half-cycle (0 to EFFECTIVE_HALF_CYCLE) + uint32_t pulseCount = (angleRadians / M_PI) * EFFECTIVE_HALF_CYCLE; - dutyHeater1 = LEADING_PULSE_COUNT + EFFECTIVE_HALF_CYCLE - pulseCount; + dutyHeater1 = LEADING_PULSE_COUNT + EFFECTIVE_HALF_CYCLE - pulseCount; + } } - + uint32_t nDuty = duty * PWM_FULL / 10000; ledcWrite(PIN_LED_HEATER1, PWM_FULL - nDuty); ESP_LOGD(TAG_ZCD,"Set Duty: %.2f%%, Timer Count: %u clock cycles", duty, dutyHeater1); @@ -103,55 +161,76 @@ ARDUINO_ISR_ATTR void setHeater2Duty(short duty) { } -void ARDUINO_ISR_ATTR onTimer1() { - digitalWrite(PIN_HEATER1, HIGH); // Fire TRIAC - delayMicroseconds(10); // Short pulse to trigger TRIAC - digitalWrite(PIN_HEATER1, LOW); // Turn off TRIAC trigger +void ARDUINO_ISR_ATTR onTimer1(void *) { + if (fireStatusTimer1) { + REG_WRITE(GPIO_OUT1_W1TC_REG, (1UL << (PIN_HEATER1 - 32))); // Clear (Low) + } else { + REG_WRITE(GPIO_OUT1_W1TS_REG, (1UL << (PIN_HEATER1 - 32))); // Set (High) + fireStatusTimer1 = 1; + SET_TIMER_1(8); // 8 us + } } -void ARDUINO_ISR_ATTR onTimer2() { - digitalWrite(PIN_HEATER2, HIGH); // Fire TRIAC - delayMicroseconds(10); // Short pulse to trigger TRIAC - digitalWrite(PIN_HEATER2, LOW); // Turn off TRIAC trigger +void ARDUINO_ISR_ATTR onTimer2(void *) { + if (fireStatusTimer2) { + REG_WRITE(GPIO_OUT1_W1TC_REG, (1UL << (PIN_HEATER2 - 32))); // Clear (Low) + } else { + REG_WRITE(GPIO_OUT1_W1TS_REG, (1UL << (PIN_HEATER2 - 32))); // Set (High) + fireStatusTimer2 = 1; + SET_TIMER_2(8); // 8 us + } } + // Zero-Cross Detection Interrupt Service Routine void ARDUINO_ISR_ATTR zcdACISR() { - uint32_t clock = micros(); - static uint32_t lastClock = 0l; - - if (clock - lastClock < 8000) - return; - lastClock = clock; + // 1. Check the dedicated Watchdog Timer (Group 1) + uint32_t elapsed = timer_ll_get_counter_value(tg1, 0); + if (elapsed < 8000) return; // Reject noise based on absolute time since last ZCD + tg1->hw_timer[0].loadhi.val = 0UL; + tg1->hw_timer[0].loadlo.val = 0UL; + tg1->hw_timer[0].load.val = 1UL; zcdACCount++; + fireStatusTimer1 = 0; + fireStatusTimer2 = 0; // Heater 1 - if (dutyHeater1 == MAX_PULSE_COUNT) { - onTimer1(); - } - else if (dutyHeater1 >= LEADING_PULSE_COUNT && dutyHeater1 < MAX_PULSE_COUNT) { - // Stop the timer, configure new alarm, then explicitly start - timerStop(timerHeater1); // Stop any existing timer action - timerWrite(timerHeater1, 0); // Reset counter to 0 - timerAlarm(timerHeater1, dutyHeater1, false, 0); // Set alarm with updated duty - timerStart(timerHeater1); // Start the timer explicitly + if (ac1ControlMode == ZCD_CONTROL) { + if (fireTable[dutyAC1][seqStep]) { + onTimer1(NULL); + } + } else { + if (dutyHeater1 >= LEADING_PULSE_COUNT && dutyHeater1 < MAX_PULSE_COUNT) { + // Stop the timer, configure new alarm, then explicitly start + SET_TIMER_1(dutyHeater1); // Set alarm with updated duty + } + else if (dutyHeater1 == MAX_PULSE_COUNT) { + onTimer1(NULL); + } } + // Heater 2 - if (dutyHeater2 == MAX_PULSE_COUNT) { - onTimer2(); + if (ac2ControlMode == ZCD_CONTROL) { + if (fireTable[dutyAC2][seqStep]) { + onTimer2(NULL); + } } - else if (dutyHeater2 >= LEADING_PULSE_COUNT && dutyHeater2 < MAX_PULSE_COUNT) { - // Stop the timer, configure new alarm, then explicitly start - timerStop(timerHeater2); // Stop any existing timer action - timerWrite(timerHeater2, 0); // Reset counter to 0 - timerAlarm(timerHeater2, dutyHeater2, false, 0); // Set alarm with updated duty - timerStart(timerHeater2); // Start the timer explicitly + else { + if (dutyHeater2 >= LEADING_PULSE_COUNT && dutyHeater2 < MAX_PULSE_COUNT) { + // Stop the timer, configure new alarm, then explicitly start + SET_TIMER_2(dutyHeater2); // Set alarm with updated duty + } + else if (dutyHeater2 == MAX_PULSE_COUNT) { + onTimer2(NULL); + } } + + seqStep = ++seqStep & 0x07; } void ARDUINO_ISR_ATTR zcdLoadISR() { - zcdLoadCount++; + ++zcdLoadCount; } void setupZCD() { @@ -166,20 +245,28 @@ void setupZCD() { zcdLoadCount = 0; timerHeater1 = NULL; - attachInterrupt(PIN_ZCD_AC, zcdACISR, CHANGE); // Attach zero-cross detection ISR - attachInterrupt(PIN_ZCD_LOAD, zcdLoadISR, CHANGE); // Attach zero-cross detection ISR + // --- 1. Basic Hardware Config for TG0 (Heaters) --- + // Timer 0 + timer_ll_set_clock_prescale(tg0, 0, 80); + timer_ll_set_count_direction(tg0, 0, GPTIMER_COUNT_UP); + timer_ll_enable_alarm(tg0, 0, true); + + // Timer 1 + timer_ll_set_clock_prescale(tg0, 1, 80); + timer_ll_set_count_direction(tg0, 1, GPTIMER_COUNT_UP); + timer_ll_enable_alarm(tg0, 1, true); - // Initialize and configure the timer - if ((timerHeater1 = timerBegin(1000000)) != NULL) { - timerAttachInterrupt(timerHeater1, &onTimer1); // Attach TRIAC firing routine - timerStop(timerHeater1); // Ensure timer is stopped initially - timerStart(timerHeater1); // Explicitly start the timer after setup + // --- 2. Manual ISR Registration --- + // ESP_INTR_FLAG_IRAM ensures the ISR stays in IRAM for fast context switching. + timer_isr_register((timer_group_t)0, (timer_idx_t)0, onTimer1, NULL, ESP_INTR_FLAG_IRAM, NULL); + timer_isr_register((timer_group_t)0, (timer_idx_t)1, onTimer2, NULL, ESP_INTR_FLAG_IRAM, NULL); - } - - if ((timerHeater2 = timerBegin(1000000)) != NULL) { - timerAttachInterrupt(timerHeater2, &onTimer2); // Attach TRIAC firing routine - timerStop(timerHeater2); // Ensure timer is stopped initially - timerStart(timerHeater2); // Explicitly start the timer after setup - } + // --- 3. Hardware Config for TG1 (Watchdog) --- + timer_ll_set_clock_prescale(tg1, 0, 80000); + timer_ll_set_count_direction(tg1, 0, GPTIMER_COUNT_UP); + tg1->hw_timer[0].loadhi.val = 0UL; + tg1->hw_timer[0].loadlo.val = 0UL; + tg1->hw_timer[0].load.val = 1UL; + timer_ll_enable_alarm(tg1, 0, false); // No ISR needed for watchdog + timer_ll_enable_counter(tg1, 0, true); } \ No newline at end of file