summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2020-05-17 04:03:16 +0200
committerUros Majstorovic <majstor@majstor.org>2020-05-17 04:03:16 +0200
commit5d157b4f7ecea4793c9da5c33a890d4ea4afc545 (patch)
tree6309b33a6d8e5f6beb068e59e001e66c9f677d2a
parent1cafcbd398fa0e5a4afb1ade33ecf21694cde235 (diff)
power management implemented; net protocol change
-rw-r--r--code/esp32/components/eos/at_cmd.c (renamed from code/esp32/components/eos/at_urc.c)73
-rw-r--r--code/esp32/components/eos/cell.c2
-rw-r--r--code/esp32/components/eos/cell_modem.c277
-rw-r--r--code/esp32/components/eos/cell_pcm.c4
-rw-r--r--code/esp32/components/eos/include/at_cmd.h (renamed from code/esp32/components/eos/include/at_urc.h)4
-rw-r--r--code/esp32/components/eos/include/cell.h17
-rw-r--r--code/esp32/components/eos/include/eos.h9
-rw-r--r--code/esp32/components/eos/include/net.h13
-rw-r--r--code/esp32/components/eos/include/power.h13
-rw-r--r--code/esp32/components/eos/net.c190
-rw-r--r--code/esp32/components/eos/power.c257
-rwxr-xr-xcode/esp32/components/eos/wifi.c8
-rw-r--r--code/esp32/main/app_main.c7
13 files changed, 689 insertions, 185 deletions
diff --git a/code/esp32/components/eos/at_urc.c b/code/esp32/components/eos/at_cmd.c
index b362d6f..ea31485 100644
--- a/code/esp32/components/eos/at_urc.c
+++ b/code/esp32/components/eos/at_cmd.c
@@ -3,9 +3,14 @@
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
+#include <esp_log.h>
#include "eos.h"
-#include "at_urc.h"
+
+#include "cell.h"
+#include "at_cmd.h"
+
+static const char *TAG = "EOS ATCMD";
typedef struct ATURCItem {
regex_t re;
@@ -22,6 +27,15 @@ static ATURCList urc_list;
static ATURCItem *urc_curr;
static SemaphoreHandle_t mutex;
+static char at_buf[128];
+
+void at_init(void) {
+ memset(&urc_list, 0, sizeof(ATURCList));
+
+ mutex = xSemaphoreCreateBinary();
+ xSemaphoreGive(mutex);
+}
+
int at_urc_process(char *urc) {
regmatch_t match[AT_SIZE_NMATCH];
at_urc_cb_t cb = NULL;
@@ -58,18 +72,18 @@ int at_urc_process(char *urc) {
}
int at_urc_insert(char *pattern, at_urc_cb_t cb, int flags) {
- int r = EOS_OK;
+ int r;
+ int rv = EOS_OK;
if (strlen(pattern) >= AT_SIZE_PATTERN) return EOS_ERR;
- r = regcomp(&urc_list.item[urc_list.len].re, pattern, flags);
- if (r) return EOS_ERR;
-
xSemaphoreTake(mutex, portMAX_DELAY);
- if (urc_list.len == AT_SIZE_URC_LIST) r = EOS_ERR_FULL;
+ r = regcomp(&urc_list.item[urc_list.len].re, pattern, flags);
+ if (r) rv = EOS_ERR;
- if (!r) {
+ if (!rv && (urc_list.len == AT_SIZE_URC_LIST)) rv = EOS_ERR_FULL;
+ if (!rv) {
strcpy(urc_list.item[urc_list.len].pattern, pattern);
urc_list.item[urc_list.len].cb = cb;
urc_list.len++;
@@ -77,12 +91,12 @@ int at_urc_insert(char *pattern, at_urc_cb_t cb, int flags) {
xSemaphoreGive(mutex);
- return r;
+ return rv;
}
int at_urc_delete(char *pattern) {
int i;
- int r = EOS_ERR_NOTFOUND;
+ int rv = EOS_ERR_NOTFOUND;
xSemaphoreTake(mutex, portMAX_DELAY);
@@ -90,6 +104,7 @@ int at_urc_delete(char *pattern) {
if ((strcmp(pattern, urc_list.item[i].pattern) == 0)) {
if (i != urc_list.len - 1) memmove(&urc_list.item[i], &urc_list.item[i + 1], (urc_list.len - i - 1) * sizeof(ATURCItem));
urc_list.len--;
+ memset(&urc_list.item[urc_list.len], 0, sizeof(ATURCItem));
if (urc_curr) {
if (urc_curr == &urc_list.item[i]) {
urc_curr = NULL;
@@ -97,13 +112,47 @@ int at_urc_delete(char *pattern) {
urc_curr--;
}
}
-
- r = EOS_OK;
+ rv = EOS_OK;
break;
}
}
xSemaphoreGive(mutex);
- return r;
+ return rv;
+}
+
+int at_expect(char *str_ok, char *str_err, uint32_t timeout) {
+ int r;
+ int rv;
+ regex_t re_ok;
+ regex_t re_err;
+ uint32_t e = 0;
+ uint64_t t_start = esp_timer_get_time();
+
+ if (str_ok) {
+ rv = regcomp(&re_ok, str_ok, REG_EXTENDED | REG_NOSUB);
+ if (rv) return EOS_ERR;
+ }
+
+ if (str_err) {
+ rv = regcomp(&re_err, str_err, REG_EXTENDED | REG_NOSUB);
+ if (rv) return EOS_ERR;
+ }
+
+ do {
+ rv = eos_modem_readln(at_buf, sizeof(at_buf), timeout - e);
+ if (rv) return rv;
+
+ if (at_buf[0] == '\0') continue;
+
+ if (str_ok && (regexec(&re_ok, at_buf, 0, NULL, 0) == 0)) return 1;
+ if (str_err && (regexec(&re_err, at_buf, 0, NULL, 0) == 0)) return 0;
+
+ r = at_urc_process(at_buf);
+ if (!r) ESP_LOGD(TAG, "expect unhandled URC: %s", at_buf);
+
+ e = (uint32_t)(esp_timer_get_time() - t_start) / 1000;
+ if (e >= timeout) return EOS_ERR_TIMEOUT;
+ } while (1);
}
diff --git a/code/esp32/components/eos/cell.c b/code/esp32/components/eos/cell.c
index 138a4e4..2da1450 100644
--- a/code/esp32/components/eos/cell.c
+++ b/code/esp32/components/eos/cell.c
@@ -14,7 +14,7 @@ static void cell_handler(unsigned char _mtype, unsigned char *buffer, uint16_t s
switch (mtype) {
case EOS_CELL_MTYPE_DATA:
- eos_modem_write(buffer+1, size-1);
+ if (eos_modem_get_mode() == EOS_CELL_UART_MODE_RELAY) eos_modem_write(buffer+1, size-1);
break;
case EOS_CELL_MTYPE_DATA_START:
cell_mode = eos_modem_get_mode();
diff --git a/code/esp32/components/eos/cell_modem.c b/code/esp32/components/eos/cell_modem.c
index 79e8e86..589f1d8 100644
--- a/code/esp32/components/eos/cell_modem.c
+++ b/code/esp32/components/eos/cell_modem.c
@@ -13,13 +13,12 @@
#include "eos.h"
#include "net.h"
-#include "at_urc.h"
-#include "cell.h"
+#include "power.h"
-// XXX: Modem init, reconnect on failure
+#include "at_cmd.h"
+#include "cell.h"
-#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
-#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
+// XXX: PPP reconnect on failure
#define UART_SIZE_BUF 1024
#define UART_SIZE_URC_BUF 128
@@ -29,16 +28,22 @@
#define UART_GPIO_DTR 32
#define UART_GPIO_RI 35
-static QueueHandle_t uart_queue;
-static QueueHandle_t uart_ri_queue;
+#define MODEM_ETYPE_INIT 1
+#define MODEM_ETYPE_RI 2
+
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
static const char *TAG = "EOS MODEM";
static SemaphoreHandle_t mutex;
-static char at_resp[128];
+static QueueHandle_t modem_queue;
+static QueueHandle_t uart_queue;
+
static char uart_buf[UART_SIZE_URC_BUF];
static unsigned int uart_buf_len;
+
static uint8_t uart_mode = EOS_CELL_UART_MODE_NONE;
static SemaphoreHandle_t uart_mutex;
@@ -54,6 +59,10 @@ typedef enum {
UART_EEVT_MODE = UART_EVENT_MAX
} uart_eevt_type_t;
+typedef struct {
+ uint8_t type;
+} modem_event_t;
+
static void modem_atcmd_read(size_t bsize);
static void uart_data_read(uint8_t mode) {
@@ -105,7 +114,7 @@ static void uart_event_task(void *pvParameters) {
while (1) {
/* Waiting for UART event.
*/
- if (xQueueReceive(uart_queue, (void *)&event, (portTickType)portMAX_DELAY)) {
+ if (xQueueReceive(uart_queue, &event, portMAX_DELAY)) {
switch (event.type) {
case UART_DATA:
/* Event of UART receiving data
@@ -139,26 +148,66 @@ static void uart_event_task(void *pvParameters) {
vTaskDelete(NULL);
}
-static void uart_ri_event_task(void *pvParameters) {
- int level;
+static void IRAM_ATTR uart_ri_isr_handler(void *arg) {
+ modem_event_t evt;
- while (1) {
- if (xQueueReceive(uart_ri_queue, (void *)&level, (portTickType)portMAX_DELAY) && (level == 0)) {
- uint64_t t_start = esp_timer_get_time();
- if (xQueueReceive(uart_ri_queue, (void *)&level, 200 / portTICK_RATE_MS) && (level == 1)) {
- uint64_t t_end = esp_timer_get_time();
- ESP_LOGI(TAG, "URC:%u", (uint32_t)(t_end - t_start));
- } else {
- ESP_LOGI(TAG, "RING");
+ evt.type = MODEM_ETYPE_RI;
+ xQueueSendFromISR(modem_queue, &evt, NULL);
+}
+
+static int modem_atcmd_init(void) {
+ unsigned char *buf;
+ int echo_on = 0;
+ int tries = 3;
+ int r;
+ int rv = EOS_OK;
+
+ rv = eos_modem_take(1000);
+ if (rv) return rv;
+
+ do {
+ eos_modem_write("AT\r", 3);
+ r = at_expect("^AT", "^OK", 1000);
+ if (r >= 0) {
+ echo_on = r;
+ if (echo_on) {
+ r = at_expect("^OK", NULL, 1000);
}
+ break;
}
+ tries--;
+ } while (tries);
+
+ if (tries == 0) {
+ eos_modem_give();
+ return EOS_ERR_TIMEOUT;
}
- vTaskDelete(NULL);
-}
-static void IRAM_ATTR uart_ri_isr_handler(void *arg) {
- int level = gpio_get_level(UART_GPIO_RI);
- xQueueSendFromISR(uart_ri_queue, &level, NULL);
+ if (echo_on) {
+ eos_modem_write("AT&F\r", 5);
+ r = at_expect("^AT&F", NULL, 1000);
+ r = at_expect("^OK", NULL, 1000);
+ } else {
+ r = eos_modem_write("AT&F\r", 5);
+ r = at_expect("^OK", NULL, 1000);
+
+ }
+ eos_modem_write("ATE0\r", 5);
+ r = at_expect("^ATE0", NULL, 1000);
+ r = at_expect("^OK", "^ERROR", 1000);
+
+ eos_modem_write("AT+CSCLK=1\r", 11);
+ r = at_expect("^OK", "^ERROR", 1000);
+ eos_modem_write("AT+CFGRI=1\r", 11);
+ r = at_expect("^OK", "^ERROR", 1000);
+
+ buf = eos_net_alloc();
+ buf[0] = EOS_CELL_MTYPE_READY;
+ eos_net_send(EOS_NET_MTYPE_CELL, buf, 1, 0);
+
+ eos_modem_give();
+
+ return EOS_OK;
}
static void modem_atcmd_read(size_t bsize) {
@@ -175,8 +224,13 @@ static void modem_atcmd_read(size_t bsize) {
while ((ln_end = strchr(ln_next, '\n'))) {
ln_end--;
if ((ln_end > ln_begin) && (*ln_end == '\r')) {
+ int r;
+
*ln_end = '\0';
- at_urc_process(ln_begin);
+ r = at_urc_process(ln_begin);
+ if (!r) {
+ ESP_LOGD(TAG, "unhandled URC: %s", ln_begin);
+ }
}
ln_next = ln_end + 2;
ln_begin = ln_next;
@@ -191,12 +245,54 @@ static void modem_atcmd_read(size_t bsize) {
} while (rd != bsize);
}
+int modem_urc_init_handler(char *urc, regmatch_t *m) {
+ modem_event_t evt;
+
+ evt.type = MODEM_ETYPE_INIT;
+ xQueueSend(modem_queue, &evt, portMAX_DELAY);
+
+ return AT_URC_OK;
+}
+
static void modem_set_mode(uint8_t mode) {
uart_event_t evt;
evt.type = UART_EEVT_MODE;
evt.size = mode;
- xQueueSend(uart_queue, (void *)&evt, portMAX_DELAY);
+ xQueueSend(uart_queue, &evt, portMAX_DELAY);
+}
+
+static void modem_event_task(void *pvParameters) {
+ modem_event_t evt;
+
+ while (1) {
+ if (xQueueReceive(modem_queue, &evt, portMAX_DELAY)) {
+ switch (evt.type) {
+ case MODEM_ETYPE_INIT:
+ modem_atcmd_init();
+ break;
+
+ case MODEM_ETYPE_RI:
+ ESP_LOGI(TAG, "URC from RI");
+ break;
+
+ default:
+ break;
+ }
+
+ /* Obsolete!!!
+ uint64_t t_start = esp_timer_get_time();
+ if (xQueueReceive(modem_queue, &level, 200 / portTICK_RATE_MS) && (level == 1)) {
+ uint64_t t_end = esp_timer_get_time();
+ ESP_LOGI(TAG, "URC:%u", (uint32_t)(t_end - t_start));
+ } else {
+ ESP_LOGI(TAG, "RING");
+ }
+ */
+
+ }
+ }
+ vTaskDelete(NULL);
}
static char *memstr(char *mem, size_t size, char *str) {
@@ -296,15 +392,14 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
}
}
-static int ppp_pause(void) {
+static int ppp_pause(uint32_t timeout, uint8_t retries) {
int done = 0;
int len = 0;
- int ret = EOS_OK;
+ int rv = EOS_OK;
char *ok_str = NULL;
uint64_t t_start;
- uint32_t timeout = 500;
- uint8_t retries = 1;
+ timeout += 1000;
xSemaphoreTake(ppp_mutex, portMAX_DELAY);
eos_modem_flush();
vTaskDelay(1000 / portTICK_PERIOD_MS);
@@ -336,11 +431,11 @@ static int ppp_pause(void) {
}
if (timeout && !done && ((uint32_t)((esp_timer_get_time() - t_start) / 1000) > timeout)) {
if (!retries) {
- ret = EOS_ERR_TIMEOUT;
- done = 1;
modem_set_mode(EOS_CELL_UART_MODE_PPP);
xSemaphoreGive(uart_mutex);
xSemaphoreGive(ppp_mutex);
+ rv = EOS_ERR_TIMEOUT;
+ done = 1;
} else {
retries--;
eos_modem_write("+++", 3);
@@ -349,7 +444,7 @@ static int ppp_pause(void) {
}
} while (!done);
- return ret;
+ return rv;
}
static int ppp_resume(void) {
@@ -357,7 +452,7 @@ static int ppp_resume(void) {
int rv = EOS_OK;
eos_modem_write("ATO\r", 4);
- r = eos_modem_resp("^CONNECT", "^(ERROR|NO CARRIER)", 1000);
+ r = at_expect("^CONNECT", "^(ERROR|NO CARRIER)", 1000);
if (r <= 0) rv = EOS_ERR;
modem_set_mode(EOS_CELL_UART_MODE_PPP);
@@ -375,10 +470,14 @@ static int ppp_setup(void) {
if ((cmd_len < 0) || (cmd_len >= sizeof(cmd))) return EOS_ERR;
modem_set_mode(EOS_CELL_UART_MODE_NONE);
- xSemaphoreTake(uart_mutex, portMAX_DELAY);
+ r = xSemaphoreTake(uart_mutex, 1000 / portTICK_PERIOD_MS);
+ if (r == pdFALSE) {
+ modem_set_mode(uart_mode);
+ return EOS_ERR_TIMEOUT;
+ }
eos_modem_write(cmd, cmd_len);
- r = eos_modem_resp("^OK", "^ERROR", 1000);
+ r = at_expect("^OK", "^ERROR", 1000);
if (r <= 0) {
modem_set_mode(uart_mode);
xSemaphoreGive(uart_mutex);
@@ -386,7 +485,7 @@ static int ppp_setup(void) {
}
eos_modem_write("AT+CGDATA=\"PPP\",1\r", 18);
- r = eos_modem_resp("^CONNECT", "^(ERROR|\\+CME ERROR|NO CARRIER)", 1000);
+ r = at_expect("^CONNECT", "^(ERROR|\\+CME ERROR|NO CARRIER)", 1000);
if (r <= 0) {
modem_set_mode(uart_mode);
xSemaphoreGive(uart_mutex);
@@ -410,11 +509,11 @@ static int ppp_disconnect(void) {
pppapi_close(ppp_handle, 0);
- rv = ppp_pause();
+ rv = ppp_pause(1000, 2);
if (rv) return rv;
eos_modem_write("ATH\r", 4);
- eos_modem_resp("^OK", NULL, 1000);
+ at_expect("^OK", NULL, 1000);
xSemaphoreGive(uart_mutex);
xSemaphoreGive(ppp_mutex);
@@ -448,7 +547,7 @@ void eos_modem_init(void) {
gpio_config(&io_conf);
gpio_set_level(UART_GPIO_DTR, 0);
- io_conf.intr_type = GPIO_PIN_INTR_ANYEDGE;
+ io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = ((uint64_t)1 << UART_GPIO_RI);
io_conf.pull_up_en = 0;
@@ -464,12 +563,16 @@ void eos_modem_init(void) {
ppp_mutex = xSemaphoreCreateBinary();
xSemaphoreGive(ppp_mutex);
- uart_ri_queue = xQueueCreate(4, sizeof(int));
- // Create a task to handle uart event from ISR
+ modem_queue = xQueueCreate(4, sizeof(modem_event_t));
xTaskCreate(uart_event_task, "uart_event", EOS_TASK_SSIZE_UART, NULL, EOS_TASK_PRIORITY_UART, NULL);
- xTaskCreate(uart_ri_event_task, "uart_ri_event", EOS_TASK_SSIZE_UART_RI, NULL, EOS_TASK_PRIORITY_UART_RI, NULL);
+ xTaskCreate(modem_event_task, "modem_event", EOS_TASK_SSIZE_MODEM, NULL, EOS_TASK_PRIORITY_MODEM, NULL);
gpio_isr_handler_add(UART_GPIO_RI, uart_ri_isr_handler, NULL);
+
+ at_init();
+ at_urc_insert("^PB DONE", modem_urc_init_handler, REG_EXTENDED);
+ eos_modem_set_mode(EOS_CELL_UART_MODE_ATCMD);
+
ESP_LOGI(TAG, "INIT");
}
@@ -488,10 +591,11 @@ size_t eos_modem_read(void *data, size_t size, uint32_t timeout) {
int eos_modem_readln(char *buf, size_t buf_size, uint32_t timeout) {
int done = 0;
int len = 0;
- int ret = EOS_OK;
+ int rv = EOS_OK;
char *ln_end = NULL;
uint64_t t_start = esp_timer_get_time();
+ uart_buf[uart_buf_len] = '\0';
ln_end = strchr(uart_buf, '\n');
do {
@@ -506,12 +610,13 @@ int eos_modem_readln(char *buf, size_t buf_size, uint32_t timeout) {
if (ln_end) {
ln_end--;
if ((ln_end >= uart_buf) && (*ln_end == '\r')) {
- if (buf_size > ln_end - uart_buf) {
- memcpy(buf, uart_buf, ln_end - uart_buf);
- buf[ln_end - uart_buf] = '\0';
- ret = EOS_OK;
- } else {
- ret = EOS_ERR;
+ if (buf) {
+ if (buf_size > ln_end - uart_buf) {
+ memcpy(buf, uart_buf, ln_end - uart_buf);
+ buf[ln_end - uart_buf] = '\0';
+ } else {
+ rv = EOS_ERR;
+ }
}
done = 1;
}
@@ -524,40 +629,12 @@ int eos_modem_readln(char *buf, size_t buf_size, uint32_t timeout) {
uart_buf_len = sizeof(uart_buf) / 2;
}
if (timeout && !done && ((uint32_t)((esp_timer_get_time() - t_start) / 1000) > timeout)) {
- ret = EOS_ERR_TIMEOUT;
+ rv = EOS_ERR_TIMEOUT;
done = 1;
}
} while (!done);
- return ret;
-}
-
-int eos_modem_resp(char *ok_str, char *err_str, uint32_t timeout) {
- int rv;
- regex_t re;
- uint32_t e = 0;
- uint64_t t_start = esp_timer_get_time();
-
- do {
- rv = eos_modem_readln(at_resp, sizeof(at_resp), timeout - e);
- if (rv) return EOS_ERR;
-
- if (ok_str) {
- rv = regcomp(&re, ok_str, REG_EXTENDED | REG_NOSUB);
- if (rv) return EOS_ERR;
- if (regexec(&re, at_resp, 0, NULL, 0) == 0) return 1;
- }
-
- if (err_str) {
- rv = regcomp(&re, err_str, REG_EXTENDED | REG_NOSUB);
- if (rv) return EOS_ERR;
- if (regexec(&re, at_resp, 0, NULL, 0) == 0) return 0;
- }
-
- at_urc_process(at_resp);
- e = (uint32_t)(esp_timer_get_time() - t_start) / 1000;
- if (e >= timeout) return EOS_ERR;
- } while (1);
+ return rv;
}
uint8_t eos_modem_get_mode(void) {
@@ -590,22 +667,32 @@ int eos_modem_set_mode(uint8_t mode) {
return rv;
}
-int eos_modem_take(void) {
+int eos_modem_take(uint32_t timeout) {
int rv = EOS_OK;
xSemaphoreTake(mutex, portMAX_DELAY);
if (uart_mode == EOS_CELL_UART_MODE_PPP) {
- rv = ppp_pause();
+ rv = ppp_pause(timeout, 0);
} else {
+ int r;
+
modem_set_mode(EOS_CELL_UART_MODE_NONE);
- xSemaphoreTake(uart_mutex, portMAX_DELAY);
+ r = xSemaphoreTake(uart_mutex, timeout ? timeout / portTICK_PERIOD_MS : portMAX_DELAY);
+ if (r == pdFALSE) {
+ modem_set_mode(uart_mode);
+ rv = EOS_ERR_TIMEOUT;
+ }
}
+
+ if (rv) xSemaphoreGive(mutex);
+
return rv;
}
void eos_modem_give(void) {
if (uart_mode == EOS_CELL_UART_MODE_PPP) {
- ppp_resume();
+ int rv = ppp_resume();
+ if (rv) ESP_LOGW(TAG, "PPP resume failed");
} else {
modem_set_mode(uart_mode);
xSemaphoreGive(uart_mutex);
@@ -614,11 +701,31 @@ void eos_modem_give(void) {
}
void eos_modem_sleep(void) {
+ int r;
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ modem_set_mode(EOS_CELL_UART_MODE_NONE);
+ r = xSemaphoreTake(uart_mutex, 1000 / portTICK_PERIOD_MS);
+ if (r == pdFALSE) {
+ ESP_LOGE(TAG, "Obtaining mutex before sleep failed");
+ }
gpio_set_level(UART_GPIO_DTR, 1);
}
-void eos_modem_wake(void) {
+void eos_modem_wake(uint8_t source) {
+ if (source == EOS_PWR_WAKE_UART) {
+ modem_event_t evt;
+
+ evt.type = MODEM_ETYPE_RI;
+ xQueueSend(modem_queue, &evt, portMAX_DELAY);
+ }
+ gpio_set_intr_type(UART_GPIO_RI, GPIO_INTR_NEGEDGE);
+ gpio_isr_handler_add(UART_GPIO_RI, uart_ri_isr_handler, NULL);
+
gpio_set_level(UART_GPIO_DTR, 0);
+ modem_set_mode(uart_mode);
+ xSemaphoreGive(uart_mutex);
+ xSemaphoreGive(mutex);
}
void eos_ppp_set_apn(char *apn) {
diff --git a/code/esp32/components/eos/cell_pcm.c b/code/esp32/components/eos/cell_pcm.c
index 9ee6b63..c1419b8 100644
--- a/code/esp32/components/eos/cell_pcm.c
+++ b/code/esp32/components/eos/cell_pcm.c
@@ -54,7 +54,7 @@ static void i2s_event_task(void *pvParameters) {
while (1) {
// Waiting for I2S event.
- if (xQueueReceive(i2s_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
+ if (xQueueReceive(i2s_queue, &event, portMAX_DELAY)) {
switch (event.type) {
case I2S_EVENT_RX_DONE:
// Event of I2S receiving data
@@ -248,7 +248,7 @@ void eos_pcm_start(void) {
xSemaphoreGive(mutex);
evt.type = I2S_EVENT_MAX; /* my type */
- xQueueSend(i2s_queue, (void *)&evt, portMAX_DELAY);
+ xQueueSend(i2s_queue, &evt, portMAX_DELAY);
i2s_zero_dma_buffer(I2S_NUM_0);
i2s_start(I2S_NUM_0);
}
diff --git a/code/esp32/components/eos/include/at_urc.h b/code/esp32/components/eos/include/at_cmd.h
index 9a4c641..ca46e23 100644
--- a/code/esp32/components/eos/include/at_urc.h
+++ b/code/esp32/components/eos/include/at_cmd.h
@@ -12,6 +12,8 @@
typedef int (*at_urc_cb_t) (char *, regmatch_t[]);
+void at_init(void);
int at_urc_process(char *urc);
int at_urc_insert(char *pattern, at_urc_cb_t cb, int flags);
-int at_urc_delete(char *pattern); \ No newline at end of file
+int at_urc_delete(char *pattern);
+int at_expect(char *str_ok, char *str_err, uint32_t timeout); \ No newline at end of file
diff --git a/code/esp32/components/eos/include/cell.h b/code/esp32/components/eos/include/cell.h
index 3a9e955..17847ce 100644
--- a/code/esp32/components/eos/include/cell.h
+++ b/code/esp32/components/eos/include/cell.h
@@ -1,13 +1,14 @@
#include <sys/types.h>
-#define EOS_CELL_MTYPE_DATA 0
-#define EOS_CELL_MTYPE_AUDIO 1
+#define EOS_CELL_MTYPE_READY 0
+#define EOS_CELL_MTYPE_DATA 1
+#define EOS_CELL_MTYPE_AUDIO 2
-#define EOS_CELL_MTYPE_DATA_START 2
-#define EOS_CELL_MTYPE_DATA_STOP 3
+#define EOS_CELL_MTYPE_DATA_START 4
+#define EOS_CELL_MTYPE_DATA_STOP 5
-#define EOS_CELL_MTYPE_AUDIO_START 4
-#define EOS_CELL_MTYPE_AUDIO_STOP 5
+#define EOS_CELL_MTYPE_AUDIO_START 6
+#define EOS_CELL_MTYPE_AUDIO_STOP 7
#define EOS_CELL_UART_MODE_NONE 0
#define EOS_CELL_UART_MODE_ATCMD 1
@@ -31,11 +32,11 @@ int eos_modem_resp(char *ok_str, char *err_str, uint32_t timeout);
uint8_t eos_modem_get_mode(void);
int eos_modem_set_mode(uint8_t mode);
-int eos_modem_take(void);
+int eos_modem_take(uint32_t timeout);
void eos_modem_give(void);
void eos_modem_sleep(void);
-void eos_modem_wake(void);
+void eos_modem_wake(uint8_t source);
void eos_ppp_set_apn(char *apn);
void eos_ppp_set_auth(char *user, char *pass);
diff --git a/code/esp32/components/eos/include/eos.h b/code/esp32/components/eos/include/eos.h
index 87ac9f3..0e660fb 100644
--- a/code/esp32/components/eos/include/eos.h
+++ b/code/esp32/components/eos/include/eos.h
@@ -1,22 +1,23 @@
#define EOS_OK 0
#define EOS_ERR -1
#define EOS_ERR_TIMEOUT -2
+#define EOS_ERR_BUSY -3
#define EOS_ERR_FULL -10
#define EOS_ERR_EMPTY -11
#define EOS_ERR_NOTFOUND -12
-#define EOS_ERR_BUSY -13
#define EOS_TASK_PRIORITY_UART 1
-#define EOS_TASK_PRIORITY_UART_RI 1
+#define EOS_TASK_PRIORITY_MODEM 1
#define EOS_TASK_PRIORITY_I2S 1
#define EOS_TASK_PRIORITY_NET_XCHG 1
#define EOS_TASK_PRIORITY_UDP_RCVR 1
+#define EOS_TASK_PRIORITY_PWR 1
#define EOS_TASK_SSIZE_UART 4096
-#define EOS_TASK_SSIZE_UART_RI 4096
+#define EOS_TASK_SSIZE_MODEM 4096
#define EOS_TASK_SSIZE_I2S 4096
#define EOS_TASK_SSIZE_NET_XCHG 8192
#define EOS_TASK_SSIZE_UDP_RCVR 4096
-
+#define EOS_TASK_SSIZE_PWR 4096
diff --git a/code/esp32/components/eos/include/net.h b/code/esp32/components/eos/include/net.h
index df1bd0d..818776e 100644
--- a/code/esp32/components/eos/include/net.h
+++ b/code/esp32/components/eos/include/net.h
@@ -1,7 +1,10 @@
#include <stdint.h>
+/* common */
+#define EOS_NET_SIZE_BUF 1500
+
#define EOS_NET_MTYPE_SOCK 1
-#define EOS_NET_MTYPE_AUDIO 2
+#define EOS_NET_MTYPE_POWER 4
#define EOS_NET_MTYPE_WIFI 5
#define EOS_NET_MTYPE_CELL 6
@@ -10,9 +13,9 @@
#define EOS_NET_MAX_MTYPE 8
-#define EOS_NET_MTYPE_FLAG_ONEW 0x10
+#define EOS_NET_MTYPE_FLAG_ONEW 0x80
-#define EOS_NET_SIZE_BUF 1500
+/* esp32 specific */
#define EOS_NET_SIZE_BUFQ 4
#define EOS_NET_SIZE_SNDQ 4
@@ -25,4 +28,6 @@ void eos_net_init(void);
unsigned char *eos_net_alloc(void);
void eos_net_free(unsigned char *buf);
int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len, uint8_t flags);
-void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler); \ No newline at end of file
+void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler);
+void eos_net_sleep_done(void);
+void eos_net_wake(uint8_t source);
diff --git a/code/esp32/components/eos/include/power.h b/code/esp32/components/eos/include/power.h
new file mode 100644
index 0000000..3f44507
--- /dev/null
+++ b/code/esp32/components/eos/include/power.h
@@ -0,0 +1,13 @@
+#include <stdint.h>
+
+#define EOS_PWR_MTYPE_BUTTON 0
+
+#define EOS_PWR_WAKE_BTN 1
+#define EOS_PWR_WAKE_NET 2
+#define EOS_PWR_WAKE_MSG 3
+#define EOS_PWR_WAKE_UART 4
+
+void eos_power_init(void);
+void eos_power_sleep(void);
+void eos_power_wake(uint8_t source);
+void eos_power_1v8rdy(void); \ No newline at end of file
diff --git a/code/esp32/components/eos/net.c b/code/esp32/components/eos/net.c
index 4eb4983..c5be1bf 100644
--- a/code/esp32/components/eos/net.c
+++ b/code/esp32/components/eos/net.c
@@ -15,6 +15,7 @@
#include "eos.h"
#include "msgq.h"
+#include "power.h"
#include "net.h"
#define SPI_GPIO_RTS 22
@@ -24,6 +25,10 @@
#define SPI_GPIO_SCLK 18
#define SPI_GPIO_CS 5
+#define SPI_SIZE_BUF (EOS_NET_SIZE_BUF + 8)
+
+static volatile char net_sleep;
+
static EOSBufQ net_buf_q;
static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ];
@@ -32,40 +37,74 @@ static EOSMsgItem net_sndq_array[EOS_NET_SIZE_SNDQ];
static SemaphoreHandle_t mutex;
static SemaphoreHandle_t semaph;
-
+static TaskHandle_t net_xchg_task_handle;
static const char *TAG = "EOS NET";
static eos_net_fptr_t mtype_handler[EOS_NET_MAX_MTYPE];
static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) {
- ESP_LOGE(TAG, "NET RECV: bad handler: %d", mtype);
+ ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len);
+}
+
+// Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high.
+static void _post_setup_cb(spi_slave_transaction_t *trans) {
+ gpio_set_level(SPI_GPIO_CTS, 1);
+}
+
+// Called after transaction is sent/received. We use this to set the handshake line low.
+static void _post_trans_cb(spi_slave_transaction_t *trans) {
+ gpio_set_level(SPI_GPIO_CTS, 0);
}
static void net_xchg_task(void *pvParameters) {
int repeat = 0;
+ int wake = 0;
unsigned char mtype = 0;
unsigned char *buffer;
uint16_t len;
uint8_t flags;
- unsigned char *buf_send = heap_caps_malloc(EOS_NET_SIZE_BUF, MALLOC_CAP_DMA);
- unsigned char *buf_recv = heap_caps_malloc(EOS_NET_SIZE_BUF, MALLOC_CAP_DMA);
+ unsigned char *buf_send = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA);
+ unsigned char *buf_recv = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA);
+ esp_err_t ret;
+ spi_slave_transaction_t spi_tr;
- spi_slave_transaction_t t;
- memset(&t, 0, sizeof(t));
+ //Configuration for the SPI bus
+ spi_bus_config_t spi_bus_cfg = {
+ .mosi_io_num = SPI_GPIO_MOSI,
+ .miso_io_num = SPI_GPIO_MISO,
+ .sclk_io_num = SPI_GPIO_SCLK
+ };
- t.length = EOS_NET_SIZE_BUF*8;
- t.tx_buffer = buf_send;
- t.rx_buffer = buf_recv;
- for (;;) {
+ //Configuration for the SPI slave interface
+ spi_slave_interface_config_t spi_slave_cfg = {
+ .mode = 0,
+ .spics_io_num = SPI_GPIO_CS,
+ .queue_size = 2,
+ .flags = 0,
+ .post_setup_cb = _post_setup_cb,
+ .post_trans_cb = _post_trans_cb
+ };
+
+ //Initialize SPI slave interface
+ ret = spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1);
+ assert(ret == ESP_OK);
+
+ memset(&spi_tr, 0, sizeof(spi_tr));
+ spi_tr.length = SPI_SIZE_BUF * 8;
+ spi_tr.tx_buffer = buf_send;
+ spi_tr.rx_buffer = buf_recv;
+
+ while (1) {
if (!repeat) {
xSemaphoreTake(mutex, portMAX_DELAY);
eos_msgq_pop(&net_send_q, &mtype, &buffer, &len, &flags);
if (mtype) {
- buf_send[0] = ((mtype << 3) | (len >> 8)) & 0xFF;
- buf_send[1] = len & 0xFF;
+ buf_send[0] = mtype;
+ buf_send[1] = len >> 8;
+ buf_send[2] = len & 0xFF;
if (buffer) {
- memcpy(buf_send + 2, buffer, len);
+ memcpy(buf_send + 3, buffer, len);
if (flags & EOS_NET_FLAG_BFREE) {
free(buffer);
} else {
@@ -77,46 +116,69 @@ static void net_xchg_task(void *pvParameters) {
gpio_set_level(SPI_GPIO_RTS, 0);
buf_send[0] = 0;
buf_send[1] = 0;
+ buf_send[2] = 0;
}
xSemaphoreGive(mutex);
}
-
- memset(buf_recv, 0, EOS_NET_SIZE_BUF);
- spi_slave_transmit(HSPI_HOST, &t, portMAX_DELAY);
- // ESP_LOGI(TAG, "RECV:%d", (buf_recv[0] >> 3));
repeat = 0;
- if (buf_recv[0] != 0) {
- mtype = (buf_recv[0] >> 3);
- len = ((buf_recv[0] & 0x07) << 8);
- len |= buf_recv[1];
- buffer = buf_recv + 2;
- if (mtype & EOS_NET_MTYPE_FLAG_ONEW) {
- mtype &= ~EOS_NET_MTYPE_FLAG_ONEW;
- if (buf_send[0]) repeat = 1;
- }
- if (mtype <= EOS_NET_MAX_MTYPE) {
- mtype_handler[mtype-1](mtype, buffer, len);
- } else {
- bad_handler(mtype, buffer, len);
- }
+
+ buf_recv[0] = 0;
+ buf_recv[1] = 0;
+ buf_recv[2] = 0;
+ spi_slave_transmit(VSPI_HOST, &spi_tr, portMAX_DELAY);
+ // ESP_LOGD(TAG, "RECV:%d", buf_recv[0]);
+
+ if (wake) {
+ eos_power_1v8rdy();
+ wake = 0;
}
- }
-}
+ if (buf_recv[0] == 0x00) continue;
+ if (buf_recv[0] == 0xFF) { // Sleep req
+ if (buf_send[0] == 0) {
+ int abort = 0;
-// Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high.
-static void _post_setup_cb(spi_slave_transaction_t *trans) {
- gpio_set_level(SPI_GPIO_CTS, 1);
-}
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ net_sleep = 1;
+ if (eos_msgq_len(&net_send_q)) abort = 1;
+ xSemaphoreGive(mutex);
-// Called after transaction is sent/received. We use this to set the handshake line low.
-static void _post_trans_cb(spi_slave_transaction_t *trans) {
- gpio_set_level(SPI_GPIO_CTS, 0);
+ spi_slave_free(VSPI_HOST);
+
+ eos_power_sleep();
+ if (abort) eos_power_wake(EOS_PWR_WAKE_MSG);
+
+ vTaskSuspend(NULL);
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ net_sleep = 0;
+ xSemaphoreGive(mutex);
+
+ wake = 1;
+ repeat = 1;
+ spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1);
+ }
+ continue;
+ }
+ mtype = buf_recv[0];
+ len = (uint16_t)buf_recv[1] << 8;
+ len |= (uint16_t)buf_recv[2] & 0xFF;
+ buffer = buf_recv + 3;
+ if (mtype & EOS_NET_MTYPE_FLAG_ONEW) {
+ mtype &= ~EOS_NET_MTYPE_FLAG_ONEW;
+ if (buf_send[0]) repeat = 1;
+ }
+ if (mtype <= EOS_NET_MAX_MTYPE) {
+ mtype_handler[mtype-1](mtype, buffer, len);
+ } else {
+ bad_handler(mtype, buffer, len);
+ }
+ }
+ vTaskDelete(NULL);
}
void eos_net_init(void) {
int i;
- esp_err_t ret;
// Configuration for the handshake lines
gpio_config_t io_conf;
@@ -137,27 +199,6 @@ void eos_net_init(void) {
gpio_config(&io_conf);
gpio_set_level(SPI_GPIO_RTS, 0);
- //Configuration for the SPI bus
- spi_bus_config_t buscfg = {
- .mosi_io_num = SPI_GPIO_MOSI,
- .miso_io_num = SPI_GPIO_MISO,
- .sclk_io_num = SPI_GPIO_SCLK
- };
-
- //Configuration for the SPI slave interface
- spi_slave_interface_config_t slvcfg = {
- .mode = 0,
- .spics_io_num = SPI_GPIO_CS,
- .queue_size = 2,
- .flags = 0,
- .post_setup_cb = _post_setup_cb,
- .post_trans_cb = _post_trans_cb
- };
-
- //Initialize SPI slave interface
- ret=spi_slave_initialize(HSPI_HOST, &buscfg, &slvcfg, 1);
- assert(ret==ESP_OK);
-
eos_msgq_init(&net_send_q, net_sndq_array, EOS_NET_SIZE_SNDQ);
eos_bufq_init(&net_buf_q, net_bufq_array, EOS_NET_SIZE_BUFQ);
for (i=0; i<EOS_NET_SIZE_BUFQ; i++) {
@@ -171,7 +212,7 @@ void eos_net_init(void) {
semaph = xSemaphoreCreateCounting(EOS_NET_SIZE_BUFQ, EOS_NET_SIZE_BUFQ);
mutex = xSemaphoreCreateBinary();
xSemaphoreGive(mutex);
- xTaskCreate(&net_xchg_task, "net_xchg", EOS_TASK_SSIZE_NET_XCHG, NULL, EOS_TASK_PRIORITY_NET_XCHG, NULL);
+ xTaskCreate(&net_xchg_task, "net_xchg", EOS_TASK_SSIZE_NET_XCHG, NULL, EOS_TASK_PRIORITY_NET_XCHG, &net_xchg_task_handle);
ESP_LOGI(TAG, "INIT");
}
@@ -194,10 +235,11 @@ void eos_net_free(unsigned char *buf) {
}
int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len, uint8_t flags) {
- int rv;
+ int rv, sleep;
if (flags & EOS_NET_FLAG_BCOPY) xSemaphoreTake(semaph, portMAX_DELAY);
xSemaphoreTake(mutex, portMAX_DELAY);
+ sleep = net_sleep;
gpio_set_level(SPI_GPIO_RTS, 1);
if (flags & EOS_NET_FLAG_BCOPY) {
unsigned char *b = eos_bufq_pop(&net_buf_q);
@@ -207,6 +249,8 @@ int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len, uint8
rv = eos_msgq_push(&net_send_q, mtype, buffer, len, flags);
xSemaphoreGive(mutex);
+ if (sleep) eos_power_wake(EOS_PWR_WAKE_MSG);
+
return rv;
}
@@ -214,3 +258,21 @@ void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler) {
mtype_handler[mtype-1] = handler;
}
+void eos_net_sleep_done(void) {
+ gpio_set_level(SPI_GPIO_CTS, 1);
+ vTaskDelay(200 / portTICK_PERIOD_MS);
+ gpio_set_level(SPI_GPIO_CTS, 0);
+}
+
+void eos_net_wake(uint8_t source) {
+ int sleep;
+
+ do {
+ vTaskResume(net_xchg_task_handle);
+ vTaskDelay(10 / portTICK_PERIOD_MS);
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ sleep = net_sleep;
+ xSemaphoreGive(mutex);
+ } while (sleep);
+}
diff --git a/code/esp32/components/eos/power.c b/code/esp32/components/eos/power.c
new file mode 100644
index 0000000..6d55a10
--- /dev/null
+++ b/code/esp32/components/eos/power.c
@@ -0,0 +1,257 @@
+#include <stdlib.h>
+
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>
+#include <freertos/queue.h>
+#include <driver/gpio.h>
+#include <esp_sleep.h>
+#include <esp_pm.h>
+#include <esp_log.h>
+
+#include "eos.h"
+#include "net.h"
+#include "cell.h"
+#include "power.h"
+
+#define POWER_GPIO_BTN 0
+#define POWER_GPIO_NET 5
+#define POWER_GPIO_UART 35
+
+#define POWER_ETYPE_BTN 1
+#define POWER_ETYPE_SLEEP 2
+#define POWER_ETYPE_WAKE 3
+#define POWER_ETYPE_1V8RDY 4
+
+typedef struct {
+ uint8_t type;
+ union {
+ uint8_t source;
+ uint8_t level;
+ };
+} power_event_t;
+
+static esp_pm_lock_handle_t power_lock_cpu_freq;
+static esp_pm_lock_handle_t power_lock_apb_freq;
+static esp_pm_lock_handle_t power_lock_no_sleep;
+
+static const char *TAG = "EOS POWER";
+
+static QueueHandle_t power_queue;
+
+static void IRAM_ATTR btn_handler(void *arg) {
+ power_event_t evt;
+
+ evt.type = POWER_ETYPE_BTN;
+ evt.level = gpio_get_level(POWER_GPIO_BTN);
+ xQueueSendFromISR(power_queue, &evt, NULL);
+}
+
+static void IRAM_ATTR btn_wake_handler(void *arg) {
+ power_event_t evt;
+
+ gpio_intr_disable(POWER_GPIO_BTN);
+
+ evt.type = POWER_ETYPE_WAKE;
+ evt.source = EOS_PWR_WAKE_BTN;
+ xQueueSendFromISR(power_queue, &evt, NULL);
+
+}
+
+static void IRAM_ATTR net_wake_handler(void *arg) {
+ power_event_t evt;
+
+ gpio_intr_disable(POWER_GPIO_NET);
+
+ evt.type = POWER_ETYPE_WAKE;
+ evt.source = EOS_PWR_WAKE_NET;
+ xQueueSendFromISR(power_queue, &evt, NULL);
+}
+
+static void IRAM_ATTR uart_wake_handler(void *arg) {
+ power_event_t evt;
+
+ gpio_intr_disable(POWER_GPIO_UART);
+
+ evt.type = POWER_ETYPE_WAKE;
+ evt.source = EOS_PWR_WAKE_UART;
+ xQueueSendFromISR(power_queue, &evt, NULL);
+}
+
+void power_sleep(void) {
+ gpio_config_t io_conf;
+
+ eos_modem_sleep();
+
+ io_conf.intr_type = GPIO_INTR_DISABLE;
+ io_conf.mode = GPIO_MODE_INPUT;
+ io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_NET);
+ io_conf.pull_up_en = 0;
+ io_conf.pull_down_en = 0;
+ gpio_config(&io_conf);
+
+ gpio_isr_handler_add(POWER_GPIO_BTN, btn_wake_handler, NULL);
+ gpio_isr_handler_add(POWER_GPIO_NET, net_wake_handler, NULL);
+ gpio_isr_handler_add(POWER_GPIO_UART, uart_wake_handler, NULL);
+
+ gpio_wakeup_enable(POWER_GPIO_BTN, GPIO_INTR_LOW_LEVEL);
+ gpio_wakeup_enable(POWER_GPIO_NET, GPIO_INTR_LOW_LEVEL);
+ gpio_wakeup_enable(POWER_GPIO_UART, GPIO_INTR_LOW_LEVEL);
+
+ eos_net_sleep_done();
+
+ ESP_LOGD(TAG, "SLEEP");
+
+ esp_pm_lock_release(power_lock_apb_freq);
+ esp_pm_lock_release(power_lock_no_sleep);
+}
+
+void power_wake_stage1(uint8_t source) {
+ gpio_config_t io_conf;
+
+ esp_pm_lock_acquire(power_lock_apb_freq);
+ esp_pm_lock_acquire(power_lock_no_sleep);
+
+ gpio_wakeup_disable(POWER_GPIO_BTN);
+ gpio_wakeup_disable(POWER_GPIO_NET);
+ gpio_wakeup_disable(POWER_GPIO_UART);
+
+ gpio_isr_handler_remove(POWER_GPIO_NET);
+ io_conf.intr_type = GPIO_INTR_DISABLE;
+ io_conf.mode = GPIO_MODE_DISABLE;
+ io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_NET);
+ io_conf.pull_up_en = 0;
+ io_conf.pull_down_en = 0;
+ gpio_config(&io_conf);
+
+ gpio_intr_disable(POWER_GPIO_BTN);
+ if ((source != EOS_PWR_WAKE_BTN) && (source != EOS_PWR_WAKE_NET)) {
+ gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_OUTPUT);
+ gpio_set_level(POWER_GPIO_BTN, 0);
+ vTaskDelay(200 / portTICK_PERIOD_MS);
+ gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_INPUT);
+ }
+ eos_net_wake(source);
+}
+
+void power_wake_stage2(uint8_t source) {
+ eos_modem_wake(source);
+
+ gpio_set_intr_type(POWER_GPIO_BTN, GPIO_INTR_ANYEDGE);
+ gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL);
+
+ ESP_LOGD(TAG, "WAKE");
+}
+
+static void power_event_task(void *pvParameters) {
+ unsigned char *buf;
+ power_event_t evt;
+ uint8_t source = 0;
+ int sleep = 0;
+
+ while (1) {
+ if (xQueueReceive(power_queue, &evt, portMAX_DELAY)) {
+ switch (evt.type) {
+ case POWER_ETYPE_SLEEP:
+ if (!sleep) {
+ power_sleep();
+ sleep = 1;
+ }
+ break;
+
+ case POWER_ETYPE_WAKE:
+ if (sleep) {
+ source = evt.source;
+ power_wake_stage1(source);
+ }
+ break;
+
+ case POWER_ETYPE_1V8RDY:
+ if (sleep && source) {
+ power_wake_stage2(source);
+ sleep = 0;
+ source = 0;
+ }
+ break;
+
+ case POWER_ETYPE_BTN:
+ buf = eos_net_alloc();
+ buf[0] = EOS_PWR_MTYPE_BUTTON;
+ buf[1] = evt.level;
+ eos_net_send(EOS_NET_MTYPE_POWER, buf, 2, 0);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ vTaskDelete(NULL);
+}
+
+void eos_power_init(void) {
+ esp_err_t ret;
+ gpio_config_t io_conf;
+ esp_pm_config_esp32_t pwr_conf;
+
+ io_conf.intr_type = GPIO_INTR_ANYEDGE;
+ io_conf.mode = GPIO_MODE_INPUT;
+ io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_BTN);
+ io_conf.pull_up_en = 1;
+ io_conf.pull_down_en = 0;
+ gpio_config(&io_conf);
+ gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL);
+
+ ret = esp_sleep_enable_gpio_wakeup();
+ assert(ret == ESP_OK);
+
+ ret = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, NULL, &power_lock_cpu_freq);
+ assert(ret == ESP_OK);
+ ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, NULL, &power_lock_apb_freq);
+ assert(ret == ESP_OK);
+ ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, NULL, &power_lock_no_sleep);
+ assert(ret == ESP_OK);
+
+ ret = esp_pm_lock_acquire(power_lock_cpu_freq);
+ assert(ret == ESP_OK);
+ ret = esp_pm_lock_acquire(power_lock_apb_freq);
+ assert(ret == ESP_OK);
+ ret = esp_pm_lock_acquire(power_lock_no_sleep);
+ assert(ret == ESP_OK);
+
+ pwr_conf.max_freq_mhz = 160;
+ pwr_conf.min_freq_mhz = 80;
+ pwr_conf.light_sleep_enable = 1;
+
+ ret = esp_pm_configure(&pwr_conf);
+ assert(ret == ESP_OK);
+
+ power_queue = xQueueCreate(4, sizeof(power_event_t));
+ xTaskCreate(power_event_task, "power_event", EOS_TASK_SSIZE_PWR, NULL, EOS_TASK_PRIORITY_PWR, NULL);
+ ESP_LOGI(TAG, "INIT");
+}
+
+void eos_power_sleep(void) {
+ power_event_t evt;
+
+ evt.type = POWER_ETYPE_SLEEP;
+ evt.source = 0;
+ xQueueSend(power_queue, &evt, portMAX_DELAY);
+}
+
+void eos_power_wake(uint8_t source) {
+ power_event_t evt;
+
+ evt.type = POWER_ETYPE_WAKE;
+ evt.source = source;
+
+ xQueueSend(power_queue, &evt, portMAX_DELAY);
+}
+
+void eos_power_1v8rdy(void) {
+ power_event_t evt;
+
+ evt.type = POWER_ETYPE_1V8RDY;
+ evt.source = 0;
+
+ xQueueSend(power_queue, &evt, portMAX_DELAY);
+}
diff --git a/code/esp32/components/eos/wifi.c b/code/esp32/components/eos/wifi.c
index 31aefea..3dd90ba 100755
--- a/code/esp32/components/eos/wifi.c
+++ b/code/esp32/components/eos/wifi.c
@@ -16,7 +16,7 @@
#include "net.h"
#include "wifi.h"
-// XXX: No DHCP server
+// XXX: WiFi fail due to no DHCP server
#define WIFI_MAX_SCAN_RECORDS 20
#define WIFI_MAX_CONNECT_ATTEMPTS 3
@@ -45,7 +45,7 @@ static uint8_t wifi_action;
static uint8_t wifi_state;
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) {
- esp_err_t ret;
+ esp_err_t ret = ESP_OK;
char _disconnect;
uint8_t _action, _state;
unsigned char *rbuf;
@@ -188,6 +188,9 @@ void eos_wifi_init(void) {
ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config);
assert(ret == ESP_OK);
+ ret = esp_wifi_stop();
+ assert(ret == ESP_OK);
+
mutex = xSemaphoreCreateBinary();
xSemaphoreGive(mutex);
@@ -260,7 +263,6 @@ int eos_wifi_connect(void) {
if (rv) return rv;
-
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config);
if (_wifi_state == WIFI_STATE_STOPPED) {
diff --git a/code/esp32/main/app_main.c b/code/esp32/main/app_main.c
index 4a277cf..bd2e3e1 100644
--- a/code/esp32/main/app_main.c
+++ b/code/esp32/main/app_main.c
@@ -6,14 +6,17 @@
#include "_net.h"
#include "wifi.h"
#include "sock.h"
+#include "power.h"
#include "bq25895.h"
+#define ESP_INTR_FLAG_DEFAULT 0
+
// Main application
void app_main() {
tcpip_adapter_init();
eos_pcm_init();
- gpio_install_isr_service(0);
+ gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
eos_modem_init();
eos_net_init();
@@ -21,6 +24,8 @@ void app_main() {
eos_wifi_init();
eos_sock_init();
+ eos_power_init();
+
eos_i2c_init();
eos_bq25895_set_ilim();
}