From 01309286013d37312464ed8a7f60fae27c462c92 Mon Sep 17 00:00:00 2001
From: Manuel Bl <10954524+manuelbl@users.noreply.github.com>
Date: Tue, 28 Sep 2021 22:38:05 +0200
Subject: [PATCH] Fix ttn_wait_for_idle for MAC cmd processing

---
 .../{shutdown => deep_sleep}/CMakeLists.txt   |   4 +-
 .../main/CMakeLists.txt                       |   0
 .../{shutdown => deep_sleep}/main/main.cpp    | 125 ++++++++----------
 examples/deep_sleep_in_c/main/main.c          |  11 ++
 src/hal/hal_esp32.c                           |   7 +-
 src/ttn.c                                     |   5 +-
 6 files changed, 78 insertions(+), 74 deletions(-)
 rename examples/{shutdown => deep_sleep}/CMakeLists.txt (79%)
 rename examples/{shutdown => deep_sleep}/main/CMakeLists.txt (100%)
 rename examples/{shutdown => deep_sleep}/main/main.cpp (61%)

diff --git a/examples/shutdown/CMakeLists.txt b/examples/deep_sleep/CMakeLists.txt
similarity index 79%
rename from examples/shutdown/CMakeLists.txt
rename to examples/deep_sleep/CMakeLists.txt
index 4e4be0a..7c07596 100644
--- a/examples/shutdown/CMakeLists.txt
+++ b/examples/deep_sleep/CMakeLists.txt
@@ -5,4 +5,6 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 # e.g. list(APPEND EXTRA_COMPONENT_DIRS "/Users/me/Documents/ttn-esp32")
 list(APPEND EXTRA_COMPONENT_DIRS "../..")
 
-project(shutdown)
+#add_definitions(-DLMIC_ENABLE_event_logging=1)
+
+project(deep_sleep)
diff --git a/examples/shutdown/main/CMakeLists.txt b/examples/deep_sleep/main/CMakeLists.txt
similarity index 100%
rename from examples/shutdown/main/CMakeLists.txt
rename to examples/deep_sleep/main/CMakeLists.txt
diff --git a/examples/shutdown/main/main.cpp b/examples/deep_sleep/main/main.cpp
similarity index 61%
rename from examples/shutdown/main/main.cpp
rename to examples/deep_sleep/main/main.cpp
index 69a93b5..09a6e0f 100644
--- a/examples/shutdown/main/main.cpp
+++ b/examples/deep_sleep/main/main.cpp
@@ -1,23 +1,23 @@
 /*******************************************************************************
- * 
+ *
  * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
- * 
- * Copyright (c) 2018 Manuel Bleichenbacher
- * 
+ *
+ * Copyright (c) 2021 Manuel Bleichenbacher
+ *
  * Licensed under MIT License
  * https://opensource.org/licenses/MIT
  *
- * Sample program showing how to send and receive messages.
+ * Sample program sending messages and going to deep sleep in-between.
  *******************************************************************************/
 
-#include "freertos/FreeRTOS.h"
-#include "esp_event.h"
 #include "driver/gpio.h"
+#include "esp_event.h"
+#include "esp_sleep.h"
+#include "freertos/FreeRTOS.h"
 #include "nvs_flash.h"
 
 #include "TheThingsNetwork.h"
 
-
 // NOTE:
 // The LoRaWAN frequency and the radio chip must be configured by running 'idf.py menuconfig'.
 // Go to Components / The Things Network, select the appropriate values and save.
@@ -32,71 +32,24 @@ const char *devEui = "????????????????";
 // AppKey
 const char *appKey = "????????????????????????????????";
 
-
 // Pins and other resources
-#define TTN_SPI_HOST      HSPI_HOST
-#define TTN_SPI_DMA_CHAN  1
-#define TTN_PIN_SPI_SCLK  5
-#define TTN_PIN_SPI_MOSI  27
-#define TTN_PIN_SPI_MISO  19
-#define TTN_PIN_NSS       18
-#define TTN_PIN_RXTX      TTN_NOT_CONNECTED
-#define TTN_PIN_RST       14
-#define TTN_PIN_DIO0      26
-#define TTN_PIN_DIO1      35
+#define TTN_SPI_HOST HSPI_HOST
+#define TTN_SPI_DMA_CHAN 1
+#define TTN_PIN_SPI_SCLK 5
+#define TTN_PIN_SPI_MOSI 27
+#define TTN_PIN_SPI_MISO 19
+#define TTN_PIN_NSS 18
+#define TTN_PIN_RXTX TTN_NOT_CONNECTED
+#define TTN_PIN_RST 14
+#define TTN_PIN_DIO0 26
+#define TTN_PIN_DIO1 35
 
 static TheThingsNetwork ttn;
 
-const unsigned TX_INTERVAL = 30;
+const unsigned TX_INTERVAL = 60;
 static uint8_t msgData[] = "Hello, world";
 
-bool join()
-{
-    printf("Joining...\n");
-    if (ttn.join())
-    {
-        printf("Joined.\n");
-        return true;
-    }
-    else
-    {
-        printf("Join failed. Goodbye\n");
-        return false;
-    }
-}
-
-
-void sendMessages(void* pvParameter)
-{
-    while (1) {
-
-        // Send 2 messages
-        for (int i = 0; i < 2; i++)
-        {
-            printf("Sending message...\n");
-            TTNResponseCode res = ttn.transmitMessage(msgData, sizeof(msgData) - 1);
-            printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n");
-
-            vTaskDelay(TX_INTERVAL * pdMS_TO_TICKS(1000));
-        }
-
-        // shutdown
-        ttn.shutdown();
-
-        // go to sleep
-        printf("Sleeping for 30s...\n");
-        vTaskDelay(pdMS_TO_TICKS(30000));
-
-        // startup
-        ttn.startup();
-
-        // join again
-        if (!join())
-            return;
-    }
-}
-
-void messageReceived(const uint8_t* message, size_t length, ttn_port_t port)
+void messageReceived(const uint8_t *message, size_t length, ttn_port_t port)
 {
     printf("Message of %d bytes received on port %d:", length, port);
     for (int i = 0; i < length; i++)
@@ -110,7 +63,7 @@ extern "C" void app_main(void)
     // Initialize the GPIO ISR handler service
     err = gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
     ESP_ERROR_CHECK(err);
-    
+
     // Initialize the NVS (non-volatile storage) for saving and restoring the keys
     err = nvs_flash_init();
     ESP_ERROR_CHECK(err);
@@ -132,10 +85,42 @@ extern "C" void app_main(void)
     // The below line can be commented after the first run as the data is saved in NVS
     ttn.provision(devEui, appEui, appKey);
 
+    // Register callback for received messages
     ttn.onMessage(messageReceived);
 
-    if (join())
+    //    ttn.setAdrEnabled(false);
+    //    ttn.setDataRate(kTTNDataRate_US915_SF7);
+    //    ttn.setMaxTxPower(14);
+
+    if (ttn.resumeAfterDeepSleep())
     {
-        xTaskCreate(sendMessages, "send_messages", 1024 * 4, (void* )0, 3, nullptr);
+        printf("Resumed from deep sleep.\n");
     }
+    else
+    {
+        printf("Joining...\n");
+        if (ttn.join())
+        {
+            printf("Joined.\n");
+        }
+        else
+        {
+            printf("Join failed. Goodbye\n");
+            return;
+        }
+    }
+
+    printf("Sending message...\n");
+    TTNResponseCode res = ttn.transmitMessage(msgData, sizeof(msgData) - 1);
+    printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n");
+
+    // Wait until TTN communication is idle and save state
+    ttn.waitForIdle();
+    ttn.prepareForDeepSleep();
+
+    // Schedule wake up
+    esp_sleep_enable_timer_wakeup(TX_INTERVAL * 1000000LL);
+
+    printf("Going to deep sleep...\n");
+    esp_deep_sleep_start();
 }
diff --git a/examples/deep_sleep_in_c/main/main.c b/examples/deep_sleep_in_c/main/main.c
index 43e9949..0c1e80f 100644
--- a/examples/deep_sleep_in_c/main/main.c
+++ b/examples/deep_sleep_in_c/main/main.c
@@ -49,6 +49,14 @@ const char *appKey = "????????????????????????????????";
 static uint8_t msgData[] = "Hello, world";
 
 
+void messageReceived(const uint8_t* message, size_t length, ttn_port_t port)
+{
+    printf("Message of %d bytes received on port %d:", length, port);
+    for (int i = 0; i < length; i++)
+        printf(" %02x", message[i]);
+    printf("\n");
+}
+
 void app_main(void)
 {
     esp_err_t err;
@@ -80,6 +88,9 @@ void app_main(void)
     // The below line can be commented after the first run as the data is saved in NVS
     ttn_provision(devEui, appEui, appKey);
 
+    // Register callback for received messages
+    ttn_on_message(messageReceived);
+
     // ttn_set_adr_enabled(false);
     // ttn_set_data_rate(TTN_DR_US915_SF7);
     // ttn_set_max_tx_pow(14);
diff --git a/src/hal/hal_esp32.c b/src/hal/hal_esp32.c
index 7972ea1..bc4d362 100755
--- a/src/hal/hal_esp32.c
+++ b/src/hal/hal_esp32.c
@@ -391,7 +391,12 @@ TickType_t hal_esp32_get_timer_duration(void)
         return 1; // busy, not waiting
 
     if (alarm_time != 0)
-        return pdMS_TO_TICKS((alarm_time - get_current_time() + 999) / 1000);
+    {
+        TickType_t dur = pdMS_TO_TICKS((alarm_time - get_current_time() + 999) / 1000);
+        if (dur > pdMS_TO_TICKS(30000))
+            dur = pdMS_TO_TICKS(200);
+        return dur;
+    }
 
 
     return 0; // waiting indefinitely
diff --git a/src/ttn.c b/src/ttn.c
index d6a7e4d..bf1790e 100644
--- a/src/ttn.c
+++ b/src/ttn.c
@@ -337,6 +337,7 @@ bool ttn_is_provisioned(void)
 void ttn_prepare_for_deep_sleep(void)
 {
     ttn_rtc_save();
+    stop();
 }
 
 
@@ -357,8 +358,8 @@ TickType_t ttn_busy_duration(void)
     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
+    if ((LMIC.opmode & (OP_JOINING | OP_TXDATA | OP_POLL | OP_TXRXPEND)) != 0)
+        return pdMS_TO_TICKS(100); // pending action
 
     return 0; // idle
 }