diff --git a/include/TheThingsNetwork.h b/include/TheThingsNetwork.h index 8d996cc..f3bd4ec 100644 --- a/include/TheThingsNetwork.h +++ b/include/TheThingsNetwork.h @@ -615,6 +615,17 @@ class TheThingsNetwork ttn_prepare_for_deep_sleep(); } + /** + * @brief Waits until the TTN device is idle. + * + * If the TTN device is idle, the ESP32 can go into deep sleep mode + * or be powered off without disrupting an on-going communication. + */ + void waitForIdle() + { + ttn_wait_for_idle(); + } + /** * @brief Returns the minimum duration the TTN device is busy. * diff --git a/include/ttn.h b/include/ttn.h index cba5406..7d2fed2 100644 --- a/include/ttn.h +++ b/include/ttn.h @@ -583,6 +583,14 @@ extern "C" */ void ttn_prepare_for_deep_sleep(void); + /** + * @brief Waits until the TTN device is idle. + * + * If the TTN device is idle, the ESP32 can go into deep sleep mode + * or be powered off without disrupting an on-going communication. + */ + void ttn_wait_for_idle(void); + /** * @brief Returns the minimum duration the TTN device will be busy. * @@ -599,7 +607,7 @@ extern "C" * * @return busy duration (in FreeRTOS ticks) */ - TickType_t ttn_busy_duration(); + TickType_t ttn_busy_duration(void); /** * @brief Stops all activies. diff --git a/src/hal/hal_esp32.c b/src/hal/hal_esp32.c index efb2b88..7ca13fa 100755 --- a/src/hal/hal_esp32.c +++ b/src/hal/hal_esp32.c @@ -35,6 +35,7 @@ typedef enum { + WAIT_KIND_NONE = 0, WAIT_KIND_CHECK_IO, WAIT_KIND_WAIT_FOR_ANY_EVENT, WAIT_KIND_WAIT_FOR_TIMER @@ -74,6 +75,7 @@ static SemaphoreHandle_t mutex; static esp_timer_handle_t timer; static int64_t next_alarm; static volatile bool run_background_task; +static volatile wait_kind_e current_wait_kind; // ----------------------------------------------------------------------------- @@ -331,7 +333,9 @@ bool wait(wait_kind_e wait_kind) TickType_t ticks_to_wait = wait_kind == WAIT_KIND_CHECK_IO ? 0 : portMAX_DELAY; while (true) { + current_wait_kind = wait_kind; uint32_t bits = ulTaskNotifyTake(pdTRUE, ticks_to_wait); + current_wait_kind = WAIT_KIND_NONE; if (bits == 0) return false; @@ -366,6 +370,22 @@ bool wait(wait_kind_e wait_kind) } } +TickType_t hal_esp32_get_timer_duration(void) +{ + wait_kind_e wait_kind = current_wait_kind; + int64_t alarm_time = next_alarm; + + if (wait_kind == WAIT_KIND_NONE || wait_kind == WAIT_KIND_CHECK_IO) + return 1; // busy, not waiting + + if (alarm_time != 0) + return pdMS_TO_TICKS((alarm_time - esp_timer_get_time() + 999) / 1000); + + + return 0; // waiting indefinitely +} + + // Gets current time in LMIC ticks u4_t IRAM_ATTR hal_ticks(void) { diff --git a/src/hal/hal_esp32.h b/src/hal/hal_esp32.h index 4278071..936ff0a 100644 --- a/src/hal/hal_esp32.h +++ b/src/hal/hal_esp32.h @@ -33,6 +33,8 @@ void hal_esp32_leave_critical_section(void); void hal_esp32_set_rssi_cal(int8_t rssi_cal); +TickType_t hal_esp32_get_timer_duration(void); + #ifdef __cplusplus } diff --git a/src/ttn.c b/src/ttn.c index 695a208..30aaff7 100644 --- a/src/ttn.c +++ b/src/ttn.c @@ -305,6 +305,30 @@ bool ttn_is_provisioned(void) return ttn_provisioning_have_keys(); } +void ttn_wait_for_idle(void) +{ + while (true) + { + TickType_t ticks_to_wait = ttn_busy_duration(); + if (ticks_to_wait == 0) + return; + vTaskDelay(ticks_to_wait); + } +} + +TickType_t ttn_busy_duration(void) +{ + TickType_t duration = hal_esp32_get_timer_duration(); + if (duration != 0) + return duration; // busy or timer scheduled + + if (current_rx_tx_window != TTN_WINDOW_IDLE) + return pdMS_TO_TICKS(100); // within TX/RX window + + return 0; // idle +} + + void ttn_set_rssi_cal(int8_t rssi_cal) { hal_esp32_set_rssi_cal(rssi_cal);