diff options
Diffstat (limited to 'main')
| -rw-r--r-- | main/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | main/epd.c | 127 | ||||
| -rw-r--r-- | main/epd.h | 3 | ||||
| -rw-r--r-- | main/git_srht_cert.pem | 31 | ||||
| -rw-r--r-- | main/main.c | 421 | ||||
| -rw-r--r-- | main/util.c | 10 | ||||
| -rw-r--r-- | main/util.h | 6 | ||||
| -rw-r--r-- | main/wifi.c | 86 | ||||
| -rw-r--r-- | main/wifi.h | 6 |
9 files changed, 446 insertions, 246 deletions
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 81b367e..0bfb5fc 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "main.c" "epd.c" "util.c" +idf_component_register(SRCS "main.c" "epd.c" "wifi.c" EMBED_TXTFILES git_srht_cert.pem INCLUDE_DIRS ".") @@ -6,16 +6,16 @@ #include <driver/spi_master.h> #include <driver/gpio.h> + #include <esp_log.h> #include "epd.h" -#include "util.h" -#define EPD_SCREEN_WIDTH 800 -#define EPD_SCREEN_HEIGHT 480 +#define EPD_WIDTH 800 +#define EPD_HEIGHT 480 #define EPD_CS_PIN GPIO_NUM_5 -#define EPD_DC_PIN GPIO_NUM_15 +#define EPD_DC_PIN GPIO_NUM_16 #define EPD_RST_PIN GPIO_NUM_2 #define EPD_CLK_PIN GPIO_NUM_18 #define EPD_MOSI_PIN GPIO_NUM_23 @@ -25,11 +25,11 @@ static const char* TAG = "epd"; static spi_device_handle_t spi = NULL; -static uint8_t VOLTAGE_FRAME[] = { +static const uint8_t VOLTAGE_FRAME[] = { 0x6, 0x3F, 0x3F, 0x11, 0x24, 0x7, 0x17, }; -static uint8_t LUT_VCOM[] = { +static const uint8_t LUT_VCOM[] = { 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, @@ -39,7 +39,7 @@ static uint8_t LUT_VCOM[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; -static uint8_t LUT_WW[] = { +static const uint8_t LUT_WW[] = { 0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, @@ -49,7 +49,7 @@ static uint8_t LUT_WW[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; -static uint8_t LUT_BW[] = { +static const uint8_t LUT_BW[] = { 0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, @@ -59,7 +59,7 @@ static uint8_t LUT_BW[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; -static uint8_t LUT_WB[] = { +static const uint8_t LUT_WB[] = { 0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, @@ -69,7 +69,7 @@ static uint8_t LUT_WB[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; -static uint8_t LUT_BB[] = { +static const uint8_t LUT_BB[] = { 0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, @@ -91,10 +91,11 @@ static void send_cmd(uint8_t cmd) memset(&t, 0, sizeof(t)); t.length = 8; - t.tx_buffer = &cmd; + t.tx_data[0] = cmd; t.user = (void*)0; + t.flags = SPI_TRANS_USE_TXDATA; - ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &t)); + spi_device_polling_transmit(spi, &t); } static void send_data(uint8_t data) @@ -103,10 +104,11 @@ static void send_data(uint8_t data) memset(&t, 0, sizeof(t)); t.length = 8; - t.tx_buffer = &data; + t.tx_data[0] = data; t.user = (void*)1; + t.flags = SPI_TRANS_USE_TXDATA; - ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &t)); + spi_device_polling_transmit(spi, &t); } static inline void wait_until_idle(void) @@ -118,30 +120,29 @@ static inline void wait_until_idle(void) do { send_cmd(0x71); busy = gpio_get_level(EPD_BUSY_PIN); - } while(busy == 0); + } while (busy == 0); ESP_LOGI(TAG, "ready"); - delay_ms(20); + vTaskDelay((TickType_t) 20 / portTICK_PERIOD_MS); } static inline void reset(void) { - ESP_ERROR_CHECK(gpio_set_level(EPD_RST_PIN, 1)); - delay_ms(200); + gpio_set_level(EPD_RST_PIN, 1); + vTaskDelay((TickType_t) 200 / portTICK_PERIOD_MS); - ESP_ERROR_CHECK(gpio_set_level(EPD_RST_PIN, 0)); - delay_ms(2); + gpio_set_level(EPD_RST_PIN, 0); + vTaskDelay((TickType_t) 2 / portTICK_PERIOD_MS); - ESP_ERROR_CHECK(gpio_set_level(EPD_RST_PIN, 1)); - delay_ms(200); + gpio_set_level(EPD_RST_PIN, 1); + vTaskDelay((TickType_t) 200 / portTICK_PERIOD_MS); } static inline void config_lut(uint8_t cmd, const uint8_t *lut) { - uint8_t i; - send_cmd(cmd); - for(i = 0; i < 42; i++) + + for (int i = 0; i < 42; i++) send_data(lut[i]); } @@ -155,11 +156,12 @@ static inline void gpio_init(void) }; ESP_ERROR_CHECK(gpio_config(&io_cfg)); + ESP_ERROR_CHECK(gpio_set_direction(EPD_DC_PIN, GPIO_MODE_OUTPUT)); ESP_ERROR_CHECK(gpio_set_direction(EPD_RST_PIN, GPIO_MODE_OUTPUT)); ESP_ERROR_CHECK(gpio_set_direction(EPD_BUSY_PIN, GPIO_MODE_INPUT)); - delay_ms(500); + vTaskDelay((TickType_t) 1000 / portTICK_PERIOD_MS); } static void spi_init(void) @@ -170,25 +172,23 @@ static void spi_init(void) .sclk_io_num = EPD_CLK_PIN, .quadwp_io_num = -1, .quadhd_io_num = -1, - .max_transfer_sz = 8 + .max_transfer_sz = EPD_WIDTH * EPD_HEIGHT }; - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, - &bus_cfg, - SPI_DMA_CH_AUTO)); + ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO)); spi_device_interface_config_t dev_cfg = { .clock_speed_hz = 10 * 1000 * 1000, .mode = 0, .spics_io_num = EPD_CS_PIN, - .queue_size = 1, + .queue_size = 3, .pre_cb = spi_pre_cb_handler }; ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &dev_cfg, &spi)); } -void epd_init(void) +void epd_init() { spi_init(); gpio_init(); @@ -216,7 +216,7 @@ void epd_init(void) send_data(*(VOLTAGE_FRAME + 0)); send_cmd(0x04); - delay_ms(100); + vTaskDelay((TickType_t) 100 / portTICK_PERIOD_MS); wait_until_idle(); send_cmd(0x00); @@ -254,55 +254,66 @@ void epd_init(void) static inline void refresh() { send_cmd(0x12); - delay_ms(100); - + vTaskDelay((TickType_t) 100 / portTICK_PERIOD_MS); wait_until_idle(); } void epd_clear(void) { - uint16_t i, width, height; - - width = (EPD_SCREEN_WIDTH % 8 == 0) ? - (EPD_SCREEN_WIDTH / 8 ) : - (EPD_SCREEN_WIDTH / 8 + 1); - height = EPD_SCREEN_HEIGHT; + int height = EPD_HEIGHT; + int width = (EPD_WIDTH % 8 == 0) ? (EPD_WIDTH / 8 ) : (EPD_WIDTH / 8 + 1); send_cmd(0x10); - for(i = 0; i < height * width; i++) + for(int i = 0; i < height * width; i++) send_data(0x00); send_cmd(0x13); - for(i = 0; i < height * width; i++) + for(int i = 0; i < height * width; i++) send_data(0x00); refresh(); } -void epd_draw(const uint8_t pb[48000]) +void epd_draw_async(const uint8_t *buf, size_t n) +{ + static spi_transaction_t t[3]; + + memset(&t[0], 0, sizeof(t[0])); + t[0].length = 8; + t[0].tx_data[0] = 0x13; + t[0].user = (void*) 0; + t[0].flags = SPI_TRANS_USE_TXDATA; + + memset(&t[1], 0, sizeof(t[1])); + t[1].length = 8 * n; + t[1].tx_buffer = buf; + t[1].user = (void*) 1; + + memset(&t[2], 0, sizeof(t[2])); + t[2].length = 8; + t[2].tx_data[0] = 0x12; + t[2].user = (void*) 0; + t[2].flags = SPI_TRANS_USE_TXDATA; + + for (int i = 0; i < 3; i++) + spi_device_queue_trans(spi, &t[i], portMAX_DELAY); +} + +void epd_draw_await(void) { - uint32_t i, j, width, height; + esp_err_t rc; + spi_transaction_t *t; - width = (EPD_SCREEN_WIDTH % 8 == 0) ? - (EPD_SCREEN_WIDTH / 8 ) : - (EPD_SCREEN_WIDTH / 8 + 1); - height = EPD_SCREEN_HEIGHT; - - send_cmd(0x13); - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) - send_data(~pb[i * width + j]); + for (int i = 0; i < 3; i++) { + rc = spi_device_get_trans_result(spi, &t, portMAX_DELAY); + assert(rc == ESP_OK); } - - refresh(); } void epd_sleep(void) { send_cmd(0x02); - wait_until_idle(); - send_cmd(0x07); send_data(0xA5); } @@ -3,7 +3,8 @@ void epd_init(void); void epd_clear(void); -void epd_draw(const uint8_t pb[48000]); +void epd_draw_async(const uint8_t *buf, size_t n); +void epd_draw_await(void); void epd_sleep(void); #endif /* EPD_H */ diff --git a/main/git_srht_cert.pem b/main/git_srht_cert.pem new file mode 100644 index 0000000..123d192 --- /dev/null +++ b/main/git_srht_cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC +ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL +wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D +LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK +4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5 +bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y +sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ +Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4 +FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc +SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql +PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND +TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1 +c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx ++tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB +ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu +b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E +U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu +MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC +5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW +9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG +WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O +he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC +Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5 +-----END CERTIFICATE----- diff --git a/main/main.c b/main/main.c index a679855..577ac00 100644 --- a/main/main.c +++ b/main/main.c @@ -2,107 +2,158 @@ #include <freertos/event_groups.h> #include <freertos/task.h> #include <freertos/queue.h> +#include <freertos/semphr.h> #include <esp_log.h> -#include <esp_log.h> #include <esp_netif.h> #include <esp_system.h> -#include <esp_wifi.h> #include <esp_tls.h> #include <esp_http_client.h> +#include <esp_sleep.h> +#include <esp_wifi.h> #include <nvs_flash.h> #include <sys/param.h> #include <driver/gpio.h> +#include <driver/rtc_io.h> #include "epd.h" -#include "util.h" +#include "wifi.h" #define PAGE_LEN 3 #define PAGE_SIZE 48000 +#define IO_SLEEP_PIN GPIO_NUM_15 #define IO_PAGE_PREV GPIO_NUM_21 #define IO_PAGE_NEXT GPIO_NUM_22 #define IO_INTR_FLAG_DEFAULT 0 -#define WIFI_SSID CONFIG_ESP_WIFI_SSID -#define WIFI_PASSWORD CONFIG_ESP_WIFI_PASSWORD -#define WIFI_MAX_RETRY CONFIG_ESP_MAXIMUM_RETRY +#define EBM_ARCH_URL CONFIG_EBM_ARCH_URL -#define WIFI_CONNECTED_BIT BIT0 -#define WIFI_ERROR_BIT BIT1 - -#define HTTP_URL_BASE CONFIG_HTTP_BASE_URL -#define HTTP_URL_SUFFIX ".ebm" +#define MUTEX_TIMEOUT ((TickType_t) 5000 / portTICK_PERIOD_MS) extern const char git_srht_cert_pem_start[] asm("_binary_git_srht_cert_pem_start"); extern const char git_srht_cert_pem_end[] asm("_binary_git_srht_cert_pem_end"); static const char* TAG = "app"; -static size_t page_num = 0; -static uint8_t *pages[PAGE_LEN]; +static SemaphoreHandle_t mutex; -static int http_get_page(size_t page_n, char buf[PAGE_SIZE]) -{ - int rc; - char *url; - esp_http_client_handle_t client; +static RTC_NOINIT_ATTR size_t c_page_num; +static RTC_NOINIT_ATTR size_t n_page_num; +static RTC_NOINIT_ATTR size_t p_page_num; - rc = 0; - url = NULL; - client = NULL; +static uint8_t *pages[PAGE_LEN]; - int url_len = strlen(HTTP_URL_BASE) + - snprintf(NULL, 0,"%02d", page_n) + - strlen(HTTP_URL_SUFFIX) + 1; +static QueueHandle_t http_evt_queue; +static esp_http_client_handle_t http_client; - if ((url = malloc(sizeof(char) * url_len)) == NULL) { - ESP_LOGE(TAG, "malloc() failed for URL"); - goto exit; +struct http_user_data { + char *res_buf; + int *res_len; +}; + +static esp_err_t http_evt_handler(esp_http_client_event_t *evt) +{ + static int read_len; + + switch(evt->event_id) { + case HTTP_EVENT_ON_HEADER: + ESP_LOGI(TAG, "received header, key=%s, value=%s", + evt->header_key, + evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + int copy_len = 0; + struct http_user_data *user_data = (struct http_user_data *) evt->user_data; + + if (user_data && user_data->res_buf) { + copy_len = MIN(evt->data_len, (PAGE_SIZE - read_len)); + if (copy_len) { + memcpy(user_data->res_buf + read_len, evt->data, copy_len); + read_len += copy_len; + ESP_LOGD(TAG, "download progress = %d", read_len); + *user_data->res_len = read_len; + } + } + break; + case HTTP_EVENT_ON_FINISH: + read_len = 0; + break; + case HTTP_EVENT_DISCONNECTED: + int mbedtls_err = 0; + esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t) evt->data, + &mbedtls_err, + NULL); + if (err != 0) { + ESP_LOGE(TAG, "disconnected, last esp error code: 0x%x", err); + ESP_LOGI(TAG, "disconnected, last mbedtls failure: 0x%x", mbedtls_err); + } + read_len = 0; + break; + default: + break; } + return ESP_OK; +} - snprintf(url, url_len, "%s%02d%s", HTTP_URL_BASE, page_n, - HTTP_URL_SUFFIX); +static int http_get_page(size_t page_n, char buf[PAGE_SIZE]) +{ + struct http_user_data user_data; + + int res_len = 0; + int r0 = ((page_n - 1) * PAGE_SIZE); + int rn = page_n * PAGE_SIZE - 1; + int rh_buflen = snprintf(NULL, 0, "bytes=%d-%d", r0, rn) + 1; - ESP_LOGI(TAG, "downloading, URL = %s", url); + char *rh_buf = malloc(sizeof(char) * rh_buflen); - esp_http_client_config_t config = { - .url = url, - .timeout_ms = 5000, - .disable_auto_redirect = true, - .max_authorization_retries = -1, - .cert_pem = git_srht_cert_pem_start - }; + if (rh_buf) { + snprintf(rh_buf, rh_buflen, "bytes=%d-%d", r0, rn); + esp_http_client_set_header(http_client, "Range", rh_buf); - client = esp_http_client_init(&config); + user_data.res_len = &res_len; + user_data.res_buf = buf; + esp_http_client_set_user_data(http_client, &user_data); - esp_err_t err = esp_http_client_open(client, 0); - if (err != ESP_OK) { - ESP_LOGE(TAG, "HTTP connection error: %s", esp_err_to_name(err)); - goto exit; - } + esp_http_client_perform(http_client); - esp_http_client_fetch_headers(client); - - int read_len = esp_http_client_read(client, buf, PAGE_SIZE); - if (read_len <= 0) { - ESP_LOGE(TAG, "HTTP response read error"); - goto exit; - } + ESP_LOGI(TAG, "HTTP status = %d, content length = %d", + esp_http_client_get_status_code(http_client), + res_len); - ESP_LOGI(TAG, "HTTP response status = %d, content length = %" PRId64, - esp_http_client_get_status_code(client), - esp_http_client_get_content_length(client)); + free(rh_buf); + } - rc = read_len == PAGE_SIZE; + return res_len == PAGE_SIZE; +} -exit: - free(url); - esp_http_client_close(client); - esp_http_client_cleanup(client); +struct page_info { + size_t page_num; + uint8_t *page_buf; +}; - return rc; +static void http_task(void* arg) +{ + struct page_info pg; + + for (;;) { + if (xQueueReceive(http_evt_queue, &pg, portMAX_DELAY)) { + if (http_get_page(pg.page_num, (char *) pg.page_buf)) { + if (xSemaphoreTake(mutex, MUTEX_TIMEOUT) == pdTRUE) { + if (pg.page_num > c_page_num) + n_page_num = pg.page_num; + else if (pg.page_num < c_page_num) + p_page_num = pg.page_num; + xSemaphoreGive(mutex); + } else { + ESP_LOGE(TAG, "failed to acquire mutex"); + } + } else { + ESP_LOGE(TAG, "page fetch error"); + } + } + } } static QueueHandle_t gpio_evt_queue = NULL; @@ -110,30 +161,72 @@ static QueueHandle_t gpio_evt_queue = NULL; static void gpio_task(void* arg) { uint32_t io_num; + struct page_info pg; - for(;;) { - if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { + for (;;) { + if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { if (io_num == IO_PAGE_NEXT) { - page_num++; - epd_draw(pages[page_num % PAGE_LEN]); - if(!http_get_page(page_num + 2, - (char *) pages[(page_num + 1) % PAGE_LEN])) { - page_num--; + if (xSemaphoreTake(mutex, MUTEX_TIMEOUT) == pdTRUE) { + if (c_page_num < n_page_num) { + c_page_num++; + + pg.page_num = c_page_num + 2; + pg.page_buf = pages[(c_page_num + 1) % PAGE_LEN]; + + xSemaphoreGive(mutex); + + xQueueSend(http_evt_queue, &pg, portMAX_DELAY); + + epd_draw_async(pages[c_page_num % PAGE_LEN], PAGE_SIZE); + epd_draw_await(); + } else { + xSemaphoreGive(mutex); + ESP_LOGI(TAG, "page not ready"); + } + } else { + ESP_LOGE(TAG, "failed to acquire mutex"); } - } - else if (io_num == IO_PAGE_PREV && page_num > 0) { - page_num--; - epd_draw(pages[page_num % PAGE_LEN]); - if(!http_get_page(page_num + 1, - (char *) pages[(page_num - 1) % PAGE_LEN])) { - page_num++; + } else if (io_num == IO_PAGE_PREV && c_page_num > 0) { + if (xSemaphoreTake(mutex, MUTEX_TIMEOUT) == pdTRUE) { + if (c_page_num > p_page_num) { + c_page_num--; + + pg.page_num = c_page_num + 1; + pg.page_buf = pages[(c_page_num - 1) % PAGE_LEN]; + + xSemaphoreGive(mutex); + + xQueueSend(http_evt_queue, &pg, portMAX_DELAY); + + epd_draw_async(pages[c_page_num % PAGE_LEN], PAGE_SIZE); + epd_draw_await(); + } else { + xSemaphoreGive(mutex); + ESP_LOGI(TAG, "page not ready"); + } + } else { + ESP_LOGE(TAG, "failed to acquire mutex"); } + } else if (io_num == IO_SLEEP_PIN) { + epd_clear(); + epd_sleep(); + + esp_wifi_stop(); + + rtc_gpio_init(IO_SLEEP_PIN); + rtc_gpio_pullup_dis(IO_SLEEP_PIN); + rtc_gpio_pulldown_en(IO_SLEEP_PIN); + + esp_sleep_enable_ext0_wakeup(IO_SLEEP_PIN, 1); + + esp_deep_sleep_start(); + } else { + vTaskDelay((TickType_t) 500 / portTICK_PERIOD_MS); } - else - delay_ms(500); gpio_intr_enable(IO_PAGE_NEXT); gpio_intr_enable(IO_PAGE_PREV); + gpio_intr_enable(IO_SLEEP_PIN); } } } @@ -142,131 +235,119 @@ static void gpio_isr_handler(void *arg) { gpio_intr_disable(IO_PAGE_PREV); gpio_intr_disable(IO_PAGE_NEXT); + gpio_intr_disable(IO_SLEEP_PIN); uint32_t gpio_num = (uint32_t) arg; - xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); + if (gpio_num != IO_SLEEP_PIN) + xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); + else + xQueueSendToFrontFromISR(gpio_evt_queue, &gpio_num, NULL); } -static int wifi_retry_num = 0; -static EventGroupHandle_t wifi_evt_group; - -static void wifi_evt_handler(void *arg, - esp_event_base_t eb, int32_t id, - void *data) +void app_main(void) { - if (eb == WIFI_EVENT && id == WIFI_EVENT_STA_DISCONNECTED) { - if (wifi_retry_num < WIFI_MAX_RETRY) { - esp_wifi_connect(); - wifi_retry_num++; - ESP_LOGI(TAG, "trying to connect to AP..."); - } else { - ESP_LOGE(TAG,"connection to AP failed"); - xEventGroupSetBits(wifi_evt_group, WIFI_ERROR_BIT); - } - } else if (eb == IP_EVENT && id == IP_EVENT_STA_GOT_IP) { - ip_event_got_ip_t* evt = (ip_event_got_ip_t*) data; - ESP_LOGI(TAG, "connected to AP with ip:" IPSTR, IP2STR(&evt->ip_info.ip)); - wifi_retry_num = 0; - xEventGroupSetBits(wifi_evt_group, WIFI_CONNECTED_BIT); + if (esp_reset_reason() != ESP_RST_DEEPSLEEP) { + p_page_num = 0; + c_page_num = 0; + n_page_num = 0; } -} - -static inline void wifi_connect(void) -{ - wifi_evt_group = xEventGroupCreate(); - esp_netif_create_default_wifi_sta(); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - - esp_event_handler_instance_t any_id; - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, - ESP_EVENT_ANY_ID, - &wifi_evt_handler, - NULL, - &any_id)); - - esp_event_handler_instance_t got_ip; - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, - IP_EVENT_STA_GOT_IP, - &wifi_evt_handler, - NULL, - &got_ip)); - - wifi_config_t wifi_config = { - .sta = { - .ssid = WIFI_SSID, - .password = WIFI_PASSWORD, - .threshold.authmode = WIFI_AUTH_WPA2_PSK - }, - }; - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - - ESP_ERROR_CHECK(esp_wifi_start()); - ESP_ERROR_CHECK(esp_wifi_connect()); - - xEventGroupWaitBits(wifi_evt_group, - WIFI_CONNECTED_BIT | WIFI_ERROR_BIT, - pdFALSE, - pdFALSE, - portMAX_DELAY); - ESP_LOGI(TAG, "wifi station initialized"); -} - -void app_main(void) -{ - esp_err_t rc = nvs_flash_init(); - if (rc == ESP_ERR_NVS_NO_FREE_PAGES || rc == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ESP_ERROR_CHECK(nvs_flash_init()); + mutex = xSemaphoreCreateMutex(); + if (mutex == NULL) { + ESP_LOGE(TAG, "xSemaphoreCreateMutex() failed"); + return; } ESP_ERROR_CHECK(esp_event_loop_create_default()); - ESP_ERROR_CHECK(esp_netif_init()); + + ESP_ERROR_CHECK(rtc_gpio_deinit(IO_SLEEP_PIN)); gpio_config_t io_cfg = { - .pin_bit_mask = ((1ULL << IO_PAGE_PREV) | (1ULL << IO_PAGE_NEXT)), + .pin_bit_mask = ((1ULL << IO_PAGE_PREV) | + (1ULL << IO_PAGE_NEXT | + (1ULL << IO_SLEEP_PIN))), .mode = GPIO_MODE_INPUT, .pull_up_en = true, .intr_type = GPIO_INTR_NEGEDGE }; ESP_ERROR_CHECK(gpio_config(&io_cfg)); + ESP_ERROR_CHECK(gpio_set_pull_mode(IO_SLEEP_PIN, GPIO_PULLDOWN_ONLY)); + ESP_ERROR_CHECK(gpio_set_intr_type(IO_SLEEP_PIN, GPIO_INTR_POSEDGE)); + + ESP_ERROR_CHECK(gpio_install_isr_service(IO_INTR_FLAG_DEFAULT)); + + ESP_ERROR_CHECK(gpio_isr_handler_add(IO_SLEEP_PIN, + gpio_isr_handler, + (void *) IO_SLEEP_PIN)); gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); - xTaskCreate(gpio_task, "gpio_task", 4096, NULL, 10, NULL); + xTaskCreatePinnedToCore(gpio_task, "gpio_task", 4096, NULL, 10, NULL, 0); + + esp_err_t rc = nvs_flash_init(); + if (rc == ESP_ERR_NVS_NO_FREE_PAGES || rc == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ESP_ERROR_CHECK(nvs_flash_init()); + } - ESP_ERROR_CHECK(gpio_set_direction(IO_PAGE_PREV, GPIO_MODE_INPUT)); - ESP_ERROR_CHECK(gpio_set_direction(IO_PAGE_NEXT, GPIO_MODE_INPUT)); + ESP_ERROR_CHECK(esp_netif_init()); wifi_connect(); - epd_init(); - epd_clear(); - delay_ms(500); + pages[0] = heap_caps_malloc(sizeof(uint8_t) * PAGE_SIZE, MALLOC_CAP_DMA); + pages[1] = heap_caps_malloc(sizeof(uint8_t) * PAGE_SIZE, MALLOC_CAP_DMA); + pages[2] = heap_caps_malloc(sizeof(uint8_t) * PAGE_SIZE, MALLOC_CAP_DMA); - pages[0] = malloc(sizeof(uint8_t) * PAGE_SIZE); - pages[1] = malloc(sizeof(uint8_t) * PAGE_SIZE); - pages[2] = malloc(sizeof(uint8_t) * PAGE_SIZE); + int http_rc; if (pages[0] && pages[1] && pages[2]) { - if (http_get_page(page_num + 1, - (char *) pages[page_num % PAGE_LEN])) { - epd_draw(pages[page_num % PAGE_LEN]); - if (!http_get_page(page_num + 2, - (char *) pages[(page_num + 1) % PAGE_LEN])) { - page_num = -1; - } + epd_init(); + + esp_http_client_config_t http_client_cfg = { + .url = EBM_ARCH_URL, + .is_async = false, + .timeout_ms = 5000, + .disable_auto_redirect = true, + .event_handler = http_evt_handler, + .cert_pem = git_srht_cert_pem_start + }; + + http_client = esp_http_client_init(&http_client_cfg); + esp_http_client_set_header(http_client, "Accept", "application/octet-stream"); + + char *c_page_buf = (char *) pages[c_page_num % PAGE_LEN]; + http_rc = http_get_page(c_page_num + 1, c_page_buf); + if (!http_rc) { + ESP_LOGE(TAG, "failed to download the first page"); + return; + } - gpio_install_isr_service(IO_INTR_FLAG_DEFAULT); - gpio_isr_handler_add(IO_PAGE_PREV, gpio_isr_handler, (void *) IO_PAGE_PREV); - gpio_isr_handler_add(IO_PAGE_NEXT, gpio_isr_handler, (void *) IO_PAGE_NEXT); + epd_draw_async(pages[c_page_num % PAGE_LEN], PAGE_SIZE); - ESP_LOGI(TAG, "GPIO for user input initialized"); + if (c_page_num > 0) { + char *p_page_buf = (char *) pages[(c_page_num - 1) % PAGE_LEN]; + http_rc = http_get_page(c_page_num, p_page_buf); + p_page_num = http_rc ? c_page_num - 1 : c_page_num; } + + char *n_page_buf = (char *) pages[(c_page_num) + 1 % PAGE_LEN]; + http_rc = http_get_page(c_page_num + 2, n_page_buf); + n_page_num = http_rc ? c_page_num + 1 : c_page_num; + + epd_draw_await(); + + http_evt_queue = xQueueCreate(10, sizeof(struct page_info)); + xTaskCreatePinnedToCore(http_task, "http_task", 4096, NULL, 10, NULL, 1); + + ESP_ERROR_CHECK(gpio_isr_handler_add(IO_PAGE_PREV, + gpio_isr_handler, + (void *) IO_PAGE_PREV)); + + ESP_ERROR_CHECK(gpio_isr_handler_add(IO_PAGE_NEXT, + gpio_isr_handler, + (void *) IO_PAGE_NEXT)); + + ESP_LOGI(TAG, "enabled GPIO for user input"); } else { ESP_LOGE(TAG, "malloc() failed for pages"); } diff --git a/main/util.c b/main/util.c deleted file mode 100644 index d2b6f22..0000000 --- a/main/util.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <freertos/FreeRTOS.h> -#include <freertos/task.h> - -#include "util.h" - -void delay_ms(unsigned int t) -{ - vTaskDelay((TickType_t) t / portTICK_PERIOD_MS); -} - diff --git a/main/util.h b/main/util.h deleted file mode 100644 index 7156c8f..0000000 --- a/main/util.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef EPD_UTIL_H -#define EPD_UTIL_H - -void delay_ms(unsigned int t); - -#endif /* EPD_UTIL_H */ diff --git a/main/wifi.c b/main/wifi.c new file mode 100644 index 0000000..5024df9 --- /dev/null +++ b/main/wifi.c @@ -0,0 +1,86 @@ +#include <freertos/FreeRTOS.h> +#include <freertos/event_groups.h> +#include <freertos/task.h> + +#include <esp_log.h> +#include <esp_wifi.h> + +#include "wifi.h" + +#define WIFI_SSID CONFIG_ESP_WIFI_SSID +#define WIFI_PASSWORD CONFIG_ESP_WIFI_PASSWORD +#define WIFI_MAX_RETRY CONFIG_ESP_MAXIMUM_RETRY + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_ERROR_BIT BIT1 + +static const char* TAG = "wifi"; + +static int wifi_retry_num = 0; +static EventGroupHandle_t wifi_evt_group; + +static void wifi_evt_handler(void *arg, + esp_event_base_t eb, int32_t id, + void *data) +{ + if (eb == WIFI_EVENT && id == WIFI_EVENT_STA_DISCONNECTED) { + if (wifi_retry_num < WIFI_MAX_RETRY) { + esp_wifi_connect(); + wifi_retry_num++; + ESP_LOGI(TAG, "trying to connect to AP..."); + } else { + ESP_LOGE(TAG,"connection to AP failed"); + xEventGroupSetBits(wifi_evt_group, WIFI_ERROR_BIT); + } + } else if (eb == IP_EVENT && id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* evt = (ip_event_got_ip_t*) data; + ESP_LOGI(TAG, "connected to AP with ip:" IPSTR, IP2STR(&evt->ip_info.ip)); + wifi_retry_num = 0; + xEventGroupSetBits(wifi_evt_group, WIFI_CONNECTED_BIT); + } +} + +void wifi_connect(void) +{ + wifi_evt_group = xEventGroupCreate(); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t any_id; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &wifi_evt_handler, + NULL, + &any_id)); + + esp_event_handler_instance_t got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &wifi_evt_handler, + NULL, + &got_ip)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = WIFI_SSID, + .password = WIFI_PASSWORD, + .threshold.authmode = WIFI_AUTH_WPA2_PSK + }, + }; + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + + ESP_ERROR_CHECK(esp_wifi_start()); + ESP_ERROR_CHECK(esp_wifi_connect()); + + xEventGroupWaitBits(wifi_evt_group, + WIFI_CONNECTED_BIT | WIFI_ERROR_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + ESP_LOGI(TAG, "wifi station initialized"); +} diff --git a/main/wifi.h b/main/wifi.h new file mode 100644 index 0000000..eca5248 --- /dev/null +++ b/main/wifi.h @@ -0,0 +1,6 @@ +#ifndef EPD_WIFI_H +#define EPD_WIFI_H + +void wifi_connect(void); + +#endif /* EPD_WIFI_H */ |
