Compare commits

..

No commits in common. "master" and "00c2d28ea7865d1cf2a9d36875c5e7080343e29d" have entirely different histories.

23 changed files with 85 additions and 4467 deletions

View File

@ -1,14 +1,32 @@
# _ESP32 S2 Cal Demo_
# _Sample project_
This is a demo project for a certain ESP32-S2 board.
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## How to create 4-indexed(2bit) image files
Use imagemagick and `bin2c` utility from CUDA toolchain
This is the simplest buildable example. The example is used by command `idf.py create-project`
that copies the project to user specified path and set it's name. For more information follow the [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project)
```bash
# Create an indexed image from any input file
magick 57852730_p0_4indexed.png -depth 2 57852730_p0_4indexed.gray
# Convert the image to C array
bin2c 57852730_p0_4indexed.gray > 57852730_p0_4indexed.c
```
## How to use example
We encourage the users to use the example as a template for the new projects.
A recommended way is to follow the instructions on a [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project).
## Example folder contents
The project **sample_project** contains one source file in C language [main.c](main/main.c). The file is located in folder [main](main).
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt`
files that provide set of directives and instructions describing the project's source files and targets
(executable, library, or both).
Below is short explanation of remaining files in the project folder.
```
├── CMakeLists.txt
├── main
│   ├── CMakeLists.txt
│   └── main.c
└── README.md This is the file you are currently reading
```
Additionally, the sample project contains Makefile and component.mk files, used for the legacy Make based build system.
They are not used or needed when building with CMake and idf.py.

View File

@ -6,14 +6,9 @@ idf_component_register(SRCS
"app_lib_i2c_system.c"
"app_lib_bat_impl.c"
"app_lib_epd_impl.c"
"app_lib_wifi_impl.c"
"app_lib_fs_impl.c"
"app_lib_pm_impl.c"
"lib/gdew042t2_epd.c"
"lib/ltc2941_battery.c"
"lib/sht35_dht.c"
"assets/pixiv_82311703_p0_4indexed.c"
"assets/pixiv_57852730_p0_4indexed.c"
INCLUDE_DIRS
"."
"./lib"

View File

@ -1,105 +0,0 @@
menu "Application Specific Configuration"
config APP_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) to connect to.
config APP_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) to use.
config APP_WIFI_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
config APP_WIFI_LISTEN_INTERVAL
int "WiFi listen interval"
default 3
help
Interval for station to listen to beacon from AP. The unit of listen interval is one beacon interval.
For example, if beacon interval is 100 ms and listen interval is 3, the interval for station to listen
to beacon is 300 ms.
choice APP_POWER_SAVE_MODE
prompt "power save mode"
default APP_POWER_SAVE_MIN_MODEM
help
Power save mode for the esp32 to use. Modem sleep mode includes minimum and maximum power save modes.
In minimum power save mode, station wakes up every DTIM to receive beacon. Broadcast data will not be
lost because it is transmitted after DTIM. However, it can not save much more power if DTIM is short
for DTIM is determined by AP.
In maximum power save mode, station wakes up every listen interval to receive beacon. Broadcast data
may be lost because station may be in sleep state at DTIM time. If listen interval is longer, more power
is saved but broadcast data is more easy to lose.
config APP_POWER_SAVE_NONE
bool "none"
config APP_POWER_SAVE_MIN_MODEM
bool "minimum modem"
config APP_POWER_SAVE_MAX_MODEM
bool "maximum modem"
endchoice
choice APP_MAX_CPU_FREQ
prompt "Maximum CPU frequency"
default APP_MAX_CPU_FREQ_80
depends on PM_ENABLE
help
Maximum CPU frequency to use for dynamic frequency scaling.
config APP_MAX_CPU_FREQ_80
bool "80 MHz"
config APP_MAX_CPU_FREQ_160
bool "160 MHz"
config APP_MAX_CPU_FREQ_240
bool "240 MHz"
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
endchoice
config APP_MAX_CPU_FREQ_MHZ
int
default 80 if APP_MAX_CPU_FREQ_80
default 160 if APP_MAX_CPU_FREQ_160
default 240 if APP_MAX_CPU_FREQ_240
choice APP_MIN_CPU_FREQ
prompt "Minimum CPU frequency"
default APP_MIN_CPU_FREQ_10M
depends on PM_ENABLE
help
Minimum CPU frequency to use for dynamic frequency scaling.
Should be set to XTAL frequency or XTAL frequency divided by integer.
config APP_MIN_CPU_FREQ_40M
bool "40 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_20M
bool "20 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_10M
bool "10 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_26M
bool "26 MHz (use with 26MHz XTAL)"
depends on ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_13M
bool "13 MHz (use with 26MHz XTAL)"
depends on ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO
endchoice
config APP_MIN_CPU_FREQ_MHZ
int
default 40 if APP_MIN_CPU_FREQ_40M
default 20 if APP_MIN_CPU_FREQ_20M
default 10 if APP_MIN_CPU_FREQ_10M
default 26 if APP_MIN_CPU_FREQ_26M
default 13 if APP_MIN_CPU_FREQ_13M
endmenu

View File

@ -1,5 +1,3 @@
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -7,7 +5,7 @@
#include "app_lib_epd_impl.h"
#define MAXIMUM_XFER_SIZE 4000
#define MAXIMUM_XFER_SIZE 400 * 300 / 8 // FULL fb.
#define MAX_BUSY_POLL_COUNT 10
static void _spi_pre_transfere_callback(spi_transaction_t *txn) {
@ -43,12 +41,11 @@ void app_lib_epd_impl_init(app_lib_epd_impl_t *impl) {
};
spi_device_interface_config_t interface_config = {
.clock_speed_hz = 16 * 1000 * 1000,
.clock_speed_hz = 8 * 1000 * 1000,
.mode = 0,
.spics_io_num = BOARD_EPD_SPI_CS_PIN,
.queue_size = 7,
.pre_cb = _spi_pre_transfere_callback,
.flags = SPI_DEVICE_HALFDUPLEX,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
@ -62,20 +59,6 @@ gd_epd_042_ret_t app_lib_epd_impl_reset(app_lib_epd_impl_t *impl) {
vTaskDelay(10);
gpio_set_level(BOARD_EPD_RES_PIN, 1);
vTaskDelay(10);
gpio_set_level(BOARD_EPD_RES_PIN, 0);
vTaskDelay(10);
gpio_set_level(BOARD_EPD_RES_PIN, 1);
vTaskDelay(10);
gpio_set_level(BOARD_EPD_RES_PIN, 0);
vTaskDelay(10);
gpio_set_level(BOARD_EPD_RES_PIN, 1);
vTaskDelay(10);
return EPD_OK;
}
gd_epd_042_ret_t app_lib_epd_delay_ms(app_lib_epd_impl_t *impl, uint32_t ms) {
vTaskDelay(pdMS_TO_TICKS(ms));
return EPD_OK;
}
@ -92,9 +75,8 @@ gd_epd_042_ret_t app_lib_epd_impl_write_cmd(app_lib_epd_impl_t *impl, uint8_t *c
if(ret != ESP_OK) return EPD_ERR;
if(len > 1) {
txn.length = 8 * (len - 1);
txn.length = 8 * len - 1;
txn.tx_buffer = &cmd[1];
txn.user = (void *)1;
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
if(ret != ESP_OK) return EPD_ERR;
@ -105,36 +87,15 @@ gd_epd_042_ret_t app_lib_epd_impl_write_cmd(app_lib_epd_impl_t *impl, uint8_t *c
gd_epd_042_ret_t app_lib_epd_impl_write_data(app_lib_epd_impl_t *impl, uint8_t *data, uint32_t len) {
esp_err_t ret;
uint8_t *dma_buffer = heap_caps_malloc(MAXIMUM_XFER_SIZE, MALLOC_CAP_DMA);
if(dma_buffer == NULL) return EPD_ERR;
uint8_t has_partial = (len % MAXIMUM_XFER_SIZE ? 1 : 0);
uint32_t txn_count = len / MAXIMUM_XFER_SIZE + has_partial;
spi_transaction_t txn = {
.length = 8 * len,
.tx_buffer = data,
.user = (void *)1
};
for(uint32_t i = 0; i < txn_count; i++) {
uint16_t txn_bytes = MAXIMUM_XFER_SIZE;
if(i == (txn_count - 1) && has_partial) {
txn_bytes = len % MAXIMUM_XFER_SIZE;
}
memcpy(dma_buffer, &data[i * MAXIMUM_XFER_SIZE], txn_bytes);
txn.length = 8 * txn_bytes;
txn.tx_buffer = dma_buffer;
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
if(ret != ESP_OK) return EPD_ERR;
}
free(dma_buffer);
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
if(ret != ESP_OK) return EPD_ERR;
return EPD_OK;
}

View File

@ -12,7 +12,6 @@ typedef struct {
void app_lib_epd_impl_init(app_lib_epd_impl_t *impl);
gd_epd_042_ret_t app_lib_epd_impl_reset(app_lib_epd_impl_t *impl);
gd_epd_042_ret_t app_lib_epd_delay_ms(app_lib_epd_impl_t *impl, uint32_t ms);
gd_epd_042_ret_t app_lib_epd_impl_write_cmd(app_lib_epd_impl_t *impl, uint8_t *cmd, uint8_t len);
gd_epd_042_ret_t app_lib_epd_impl_write_data(app_lib_epd_impl_t *impl, uint8_t *data, uint32_t len);
gd_epd_042_ret_t app_lib_epd_impl_poll_busy(app_lib_epd_impl_t *impl);

View File

@ -1,54 +0,0 @@
#include "app_lib_fs_impl.h"
#include "user_board.h"
sdmmc_card_t *g_card;
static const char *TAG = "APP_FS";
static const char *MOUNT_POINT = APP_FS_MOUNT_POINT;
void app_lib_fs_init(void) {
esp_err_t ret;
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
spi_bus_config_t bus_cfg = {
.mosi_io_num = BOARD_SD_MOSI_PIN,
.miso_io_num = BOARD_SD_MISO_PIN,
.sclk_io_num = BOARD_SD_SCLK_PIN,
.quadhd_io_num = -1,
.quadwp_io_num = -1,
.max_transfer_sz = 4000
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CH_AUTO);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize SPI bus.");
return;
}
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = BOARD_SD_CS_PIN;
slot_config.gpio_cd = BOARD_SD_DET_PIN;
slot_config.host_id = host.slot;
ret = esp_vfs_fat_sdspi_mount(MOUNT_POINT, &host, &slot_config, &mount_config, &g_card);
if(ret != ESP_OK) {
if(ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount SD card.");
}
else {
ESP_LOGE(TAG, "Failed to initialize SD card. Result is %s", esp_err_to_name(ret));
}
return;
}
sdmmc_card_print_info(stdout, g_card);
}

View File

@ -1,17 +0,0 @@
#ifndef __APP_LIB_FS_IMPL_H
#define __APP_LIB_FS_IMPL_H
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
extern sdmmc_card_t *g_card;
#define APP_FS_MOUNT_POINT "/sdcard"
void app_lib_fs_init(void);
#endif

View File

@ -1,14 +0,0 @@
#include "esp_pm.h"
#define DVFS_MAXIMUM_FREQ CONFIG_APP_MAX_CPU_FREQ_MHZ
#define DVFS_MINIMUM_FREQ CONFIG_APP_MIN_CPU_FREQ_MHZ
void app_lib_pm_init(void) {
esp_pm_config_esp32s2_t pm_config = {
.max_freq_mhz = DVFS_MAXIMUM_FREQ,
.min_freq_mhz = DVFS_MINIMUM_FREQ,
.light_sleep_enable = true
};
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
}

View File

@ -1,6 +0,0 @@
#ifndef __APP_LIB_PM_IMPL_H
#define __APP_LIB_PM_IMPL_H
void app_lib_pm_init(void);
#endif

View File

@ -1,102 +0,0 @@
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "app_lib_wifi_impl.h"
EventGroupHandle_t g_wifi_event_group;
static uint8_t s_retry_num = 0;
static const char *TAG = "APP_WIFI";
#define APP_WIFI_SSID CONFIG_APP_WIFI_SSID
#define APP_WIFI_PASS CONFIG_APP_WIFI_PASSWORD
#define APP_WIFI_RETR CONFIG_APP_WIFI_MAXIMUM_RETRY
#define APP_WIFI_INTV CONFIG_APP_WIFI_LISTEN_INTERVAL
#if CONFIG_APP_POWER_SAVE_MIN_MODEM
#define DEFAULT_PS_MODE WIFI_PS_MIN_MODEM
#elif CONFIG_APP_POWER_SAVE_MAX_MODEM
#define DEFAULT_PS_MODE WIFI_PS_MAX_MODEM
#elif CONFIG_APP_POWER_SAVE_NONE
#define DEFAULT_PS_MODE WIFI_PS_NONE
#else
#define DEFAULT_PS_MODE WIFI_PS_NONE
#endif
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (s_retry_num < APP_WIFI_RETR) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "Connect attempt failed, retrying (%u/%u)...", s_retry_num, APP_WIFI_RETR);
} else {
xEventGroupSetBits(g_wifi_event_group, WIFI_ERROR_BIT);
ESP_LOGI(TAG, "WiFi connection failed, no more retries scheduled.");
}
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
ESP_LOGI(TAG, "Client IP:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(g_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
void app_lib_init_wifi(void) {
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
g_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
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 instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
.ssid = APP_WIFI_SSID,
.password = APP_WIFI_PASS,
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.listen_interval = APP_WIFI_INTV,
.pmf_cfg = {
.capable = true,
.required = false
}
}
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
}
void app_lib_start_wifi(void) {
ESP_ERROR_CHECK(esp_wifi_start());
}
void app_lib_stop_wifi(void) {
ESP_ERROR_CHECK(esp_wifi_stop());
}

View File

@ -1,17 +0,0 @@
#ifndef __APP_LIB_WIFI_IMPL_H
#define __APP_LIB_WIFI_IMPL_H
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
extern EventGroupHandle_t g_wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_ERROR_BIT BIT1
void app_lib_init_wifi(void);
void app_lib_start_wifi(void);
void app_lib_stop_wifi(void);
#endif

View File

@ -1,20 +0,0 @@
#ifndef __APP_TASK_H
#define __APP_TASK_H
#include "esp_sleep.h"
typedef struct {
esp_sleep_source_t wakeup_source;
void *user_params;
} app_task_params_t;
void vTaskLEDs(void *pvParameters);
extern TaskHandle_t xTaskLEDsHandle;
void vTasBatteryExample(void *pvParameters);
extern TaskHandle_t xTaskBatteryExampleHandle;
extern TaskHandle_t xTaskEPDExampleHandle;
void vTaskEPDExample(void *pvParameters);
#endif

View File

@ -9,8 +9,8 @@
#include "app_lib_bat_impl.h"
#define BATTERY_CAP 3000.0
#define MAH_LSB 0.0850 // Shunt 50mR
#define PRESCALER_M LTC2941_PRE_128
#define MAH_LSB 0.053125 // Shunt 20mR
#define PRESCALER_M LTC2941_PRE_32
const static char *TAG = "TASK_BAT";
@ -39,10 +39,9 @@ void vTasBatteryExample(void *pvParameters) {
uint16_t fg_data = 0x00;
ltc2941_read_charge(&battery_fg, &fg_data);
float mah = fg_data * MAH_LSB;
float percentage = fg_data * MAH_LSB * 100.0 / BATTERY_CAP;
ESP_LOGI(TAG, "Capacity: %04.2fmAh, Charge: %03.2f%%", mah, percentage);
ESP_LOGI(TAG, "Charge: %.2f", percentage);
vTaskDelay(pdMS_TO_TICKS(30000));
}

View File

@ -4,35 +4,13 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "app_lib_epd_impl.h"
static uint8_t *frame_data[2];
static const char *TAG = "TASK_EPD";
extern const unsigned char pixiv_82311703_p0_4indexed[];
extern const unsigned char pixiv_57852730_p0_4indexed[];
#define ARRAY_EVEN_BYTES(arr, i) ((arr[2 * i] & 0x01) << 4U) | ((arr[2 * i] & 0x04) << 3U) | ((arr[2 * i] & 0x10) << 2U) | ((arr[2 * i] & 0x40) << 1U) | \
((arr[2 * i + 1] & 0x01)) | ((arr[2 * i + 1] & 0x04) >> 1U) | ((arr[2 * i + 1] & 0x10) >> 2U) | ((arr[2 * i + 1] & 0x40) >> 3U)
#define ARRAY_ODD_BYTES(arr, i) ((arr[2 * i] & 0x02) << 3U) | ((arr[2 * i] & 0x08) << 2U) | ((arr[2 * i] & 0x20) << 1U) | ((arr[2 * i] & 0x80)) | \
((arr[2 * i + 1] & 0x02) >> 1U) | ((arr[2 * i + 1] & 0x08) >> 2U) | ((arr[2 * i + 1] & 0x20) >> 3U) | ((arr[2 * i + 1] & 0x80) >> 4U)
static uint8_t frame_data[15000][2];
static uint8_t current_frame = 0;
TaskHandle_t xTaskEPDExampleHandle = NULL;
void vTaskEPDExample(void *pvParameters) {
ESP_LOGI(TAG, "EPD task started.");
frame_data[0] = malloc(15000);
frame_data[1] = malloc(15000);
if(frame_data[0] == NULL || frame_data[1] == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory on heap.");
vTaskSuspend(NULL);
}
app_lib_epd_impl_t epd_impl = {0};
gd_epd_042_t epd = {
@ -40,8 +18,7 @@ void vTaskEPDExample(void *pvParameters) {
.write_data_cb = (gd_epd_042_ret_t (*)(void *, uint8_t *, uint32_t))app_lib_epd_impl_write_data,
.write_cmd_cb = (gd_epd_042_ret_t (*)(void *, uint8_t *, uint8_t))app_lib_epd_impl_write_cmd,
.poll_busy_cb = (gd_epd_042_ret_t (*)(void *))app_lib_epd_impl_poll_busy,
.reset_cb = (gd_epd_042_ret_t (*)(void *))app_lib_epd_impl_reset,
.delay_ms_cb = (gd_epd_042_ret_t (*)(void *, uint32_t))app_lib_epd_delay_ms
.reset_cb = (gd_epd_042_ret_t (*)(void *))app_lib_epd_impl_reset
},
.user_data = &epd_impl
};
@ -49,20 +26,14 @@ void vTaskEPDExample(void *pvParameters) {
app_lib_epd_impl_init(&epd_impl);
gd_epd_042_init(&epd);
for(uint32_t i = 0; i < 15000; i++) {
frame_data[0][i] = ARRAY_ODD_BYTES(pixiv_57852730_p0_4indexed, i);
frame_data[1][i] = ARRAY_EVEN_BYTES(pixiv_57852730_p0_4indexed, i);
}
memset(frame_data[current_frame], 0xFF, 15000);
memset(frame_data[(~current_frame) & 0x01], 0xFF, 15000);
ESP_LOGI(TAG, "EPD frame constructed.");
gd_epd_042_load(&epd, frame_data[0], frame_data[1]);
gd_epd_042_load(&epd, frame_data[current_frame], frame_data[(~current_frame) & 0x01]);
gd_epd_042_update(&epd);
gd_epd_042_deepsleep(&epd);
ESP_LOGI(TAG, "EPD task finished.");
for(;;) {
vTaskSuspend(NULL);
vTaskDelay(10000);
}
}

View File

@ -7,6 +7,8 @@
#include "user_board.h"
#define BREATHE_LED_NUM 3
#define BREATHE_LED_MAXIMUM_BRIGHTNESS 512
#define BREATHE_LED_CYCLE 2500
TaskHandle_t xTaskLEDsHandle = NULL;
@ -84,34 +86,18 @@ void vTaskLEDs(void *pvParameters) {
ledc_fade_func_install(0);
uint32_t fade_matrix[8][4] = {
{ 8191, 0, 0, 0 },
{ 8191, 8191, 0, 0 },
{ 0, 8191, 0, 0 },
{ 0, 8191, 8191, 0 },
{ 0, 0, 8191, 0 },
{ 0, 0, 8191, 8191 },
{ 0, 0, 0, 8191 },
{ 8191, 0, 0, 8191 }
};
uint8_t current_phase = 0;
for(;;) {
for(uint8_t i = 0; i < 4; i++) {
ledc_set_fade_with_time(ledc_channels[i].speed_mode,
ledc_channels[i].channel, fade_matrix[current_phase][i], BREATHE_LED_CYCLE);
ledc_fade_start(ledc_channels[i].speed_mode,
ledc_channels[i].channel, LEDC_FADE_NO_WAIT);
}
current_phase++;
if(current_phase == 8) {
for(uint8_t i = 0; i < 4; i++) {
ledc_set_duty(ledc_channels[i].speed_mode, ledc_channels[i].channel, 0);
}
vTaskDelay(pdMS_TO_TICKS(BREATHE_LED_CYCLE));
ledc_set_fade_with_time(ledc_channels[BREATHE_LED_NUM].speed_mode,
ledc_channels[BREATHE_LED_NUM].channel, BREATHE_LED_MAXIMUM_BRIGHTNESS, BREATHE_LED_CYCLE);
ledc_fade_start(ledc_channels[BREATHE_LED_NUM].speed_mode,
ledc_channels[BREATHE_LED_NUM].channel, LEDC_FADE_NO_WAIT);
vTaskDelay(pdMS_TO_TICKS(BREATHE_LED_CYCLE));
vTaskSuspend(NULL);
}
ledc_set_fade_with_time(ledc_channels[BREATHE_LED_NUM].speed_mode,
ledc_channels[BREATHE_LED_NUM].channel, 0, BREATHE_LED_CYCLE);
ledc_fade_start(ledc_channels[BREATHE_LED_NUM].speed_mode,
ledc_channels[BREATHE_LED_NUM].channel, LEDC_FADE_NO_WAIT);
vTaskDelay(pdMS_TO_TICKS(BREATHE_LED_CYCLE));
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,182 +1,19 @@
#include "gdew042t2_epd.h"
static uint8_t gd_epd_042_grayscale_lut[6][44] = {
{ // VCOM -> 0x20
0x00, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x60, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
0x00, 0x13, 0x0A, 0x01, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // WW -> 0x21
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x10, 0x14, 0x0A, 0x00, 0x00, 0x01,
0xA0, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // BW -> 0x22
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x99, 0x0C, 0x01, 0x03, 0x04, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // WB -> 0x23
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x99, 0x0B, 0x04, 0x04, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // BB -> 0x24
0x80, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x20, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x50, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // WW -> 0x25 ?????????
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x10, 0x14, 0x0A, 0x00, 0x00, 0x01,
0xA0, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
};
static uint8_t gd_epd_042_normal_lut[6][44] = {
{ // VCOM -> 0x20
0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
0x60, 0x28, 0x28, 0x00, 0x00, 0x01,
0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
0x00, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // WW -> 0x21
0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // BW -> 0x22
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
0x90, 0x0F, 0x0F, 0x00, 0x00, 0x03,
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // WB -> 0x23
0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // BB -> 0x24
0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{ // WW -> 0x25 ????????
0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
};
static uint8_t gd_epd_042_init_data_1[] = {
0x04, 0x01, 0x03, 0x00, 0x2B, 0x2B,
0x03, 0x06, 0x17, 0x17, 0x17,
0x00, 0x04,
};
static uint8_t gd_epd_042_init_data_2[] = {
0x02, 0x00, 0x3F, 0x0D,
0x01, 0x30, 0x3C,
0x04, 0x61, 0x01, 0x90, 0x01, 0x2C,
0x01, 0x82, 0x12,
0x01, 0x50, 0x97,
};
#define GD_ERROR_CHECK(x) if(x != EPD_OK) return EPD_ERR
static gd_epd_042_ret_t _gd_epd_042_init_seq(gd_epd_042_t *epd) {
uint16_t i = 0;
while(i < sizeof(gd_epd_042_init_data_1)) {
GD_ERROR_CHECK(epd->cb.write_cmd_cb(epd->user_data, &gd_epd_042_init_data_1[i + 1], gd_epd_042_init_data_1[i] + 1));
i += gd_epd_042_init_data_1[i] + 2;
}
GD_ERROR_CHECK(epd->cb.poll_busy_cb(epd->user_data));
i = 0;
while(i < sizeof(gd_epd_042_init_data_2)) {
GD_ERROR_CHECK(epd->cb.write_cmd_cb(epd->user_data, &gd_epd_042_init_data_2[i + 1], gd_epd_042_init_data_2[i] + 1));
i += gd_epd_042_init_data_2[i] + 2;
}
return EPD_OK;
}
static gd_epd_042_ret_t _gd_epd_042_lut(gd_epd_042_t *epd) {
uint8_t data_len[6] = { 44, 42, 42, 42, 42, 42 };
for(uint8_t i = 0; i < 6; i++) {
uint8_t cmd = 0x20 + i;
GD_ERROR_CHECK(epd->cb.write_cmd_cb(epd->user_data, &cmd, 0x01));
GD_ERROR_CHECK(epd->cb.write_data_cb(epd->user_data, gd_epd_042_grayscale_lut[i], data_len[i]));
}
return EPD_OK;
}
static gd_epd_042_ret_t _gd_epd_042_reset(gd_epd_042_t *epd) {
return epd->cb.reset_cb(epd->user_data);
}
static gd_epd_042_ret_t _gd_epd_delay_ms(gd_epd_042_t *epd, uint32_t ms) {
return epd->cb.delay_ms_cb(epd->user_data, ms);
}
static gd_epd_042_ret_t _gd_epd_042_poll_busy(gd_epd_042_t *epd) {
uint8_t cmd = 0x71;
GD_ERROR_CHECK(epd->cb.write_cmd_cb(epd->user_data, &cmd, 0x01));
return epd->cb.poll_busy_cb(epd->user_data);
}
gd_epd_042_ret_t gd_epd_042_init(gd_epd_042_t *epd) {
GD_ERROR_CHECK(_gd_epd_042_reset(epd));
GD_ERROR_CHECK(_gd_epd_042_init_seq(epd));
epd->cb.reset_cb(epd->user_data);
uint8_t tx_buf[4] = { 0x06, 0x17, 0x17, 0x17 };
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x04);
tx_buf[0] = 0x04;
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x01);
epd->cb.poll_busy_cb(epd->user_data);
tx_buf[0] = 0x00;
tx_buf[1] = 0x1F;
tx_buf[2] = 0x0D;
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x03);
return EPD_OK;
}
@ -186,11 +23,11 @@ gd_epd_042_ret_t gd_epd_042_deepsleep(gd_epd_042_t *epd) {
tx_buf[0] = 0x02;
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x01);
GD_ERROR_CHECK(_gd_epd_042_poll_busy(epd));
epd->cb.poll_busy_cb(epd->user_data);
tx_buf[0] = 0x07;
tx_buf[1] = 0xA5;
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x02);
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x01);
return EPD_OK;
}
@ -198,14 +35,13 @@ gd_epd_042_ret_t gd_epd_042_deepsleep(gd_epd_042_t *epd) {
gd_epd_042_ret_t gd_epd_042_load(gd_epd_042_t *epd, uint8_t *old_data, uint8_t *new_data) {
uint8_t tx_buf[2] = { 0x10 };
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x01);
epd->cb.write_data_cb(epd->user_data, old_data, 400 * 300 / 8);
tx_buf[0] = 0x13;
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x01);
epd->cb.write_data_cb(epd->user_data, new_data, 400 * 300 / 8);
GD_ERROR_CHECK(_gd_epd_042_lut(epd));
return EPD_OK;
}
@ -213,8 +49,6 @@ gd_epd_042_ret_t gd_epd_042_update(gd_epd_042_t *epd) {
uint8_t tx_buf[2] = { 0x12 };
epd->cb.write_cmd_cb(epd->user_data, tx_buf, 0x01);
GD_ERROR_CHECK(_gd_epd_delay_ms(epd, 100));
GD_ERROR_CHECK(_gd_epd_042_poll_busy(epd));
epd->cb.poll_busy_cb(epd->user_data);
return EPD_OK;
}

View File

@ -13,7 +13,6 @@ typedef struct {
gd_epd_042_ret_t (* write_data_cb)(void *handle, uint8_t *data, uint32_t len);
gd_epd_042_ret_t (* reset_cb)(void *handle);
gd_epd_042_ret_t (* poll_busy_cb)(void *handle);
gd_epd_042_ret_t (* delay_ms_cb)(void *handle, uint32_t ms);
} gd_epd_042_cb_t;
typedef struct {

View File

@ -28,15 +28,5 @@ ltc2941_ret_t ltc2941_read_charge(ltc2941_t *bat, uint16_t *charge) {
bat->cb.read_register_cb(bat->user_data, LTC2941_REG_CHARGE_LSB, &reg);
*charge |= reg;
return LTC2941_OK;
}
ltc2941_ret_t ltc2941_write_charge(ltc2941_t *bat, uint16_t charge) {
uint8_t reg = (charge >> 0x08U); // MSB
bat->cb.write_register_cb(bat->user_data, LTC2941_REG_CHARGE_MSB, reg);
reg = (charge & 0xFFU); // LSB
bat->cb.write_register_cb(bat->user_data, LTC2941_REG_CHARGE_LSB, reg);
return LTC2941_OK;
}

View File

@ -59,6 +59,5 @@ typedef struct {
ltc2941_ret_t ltc2941_init(ltc2941_t *bat);
ltc2941_ret_t ltc2941_read_status(ltc2941_t *bat, uint8_t *status);
ltc2941_ret_t ltc2941_read_charge(ltc2941_t *bat, uint16_t *charge);
ltc2941_ret_t ltc2941_write_charge(ltc2941_t *bat, uint16_t charge);
#endif

View File

@ -6,13 +6,19 @@
#include "esp_log.h"
#include "app_lib_wifi_impl.h"
#include "app_lib_fs_impl.h"
#include "app_lib_pm_impl.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "user_board.h"
#include "app_task.h"
void vTaskLEDs(void *pvParameters);
extern TaskHandle_t xTaskLEDsHandle;
void vTasBatteryExample(void *pvParameters);
extern TaskHandle_t xTaskBatteryExampleHandle;
extern TaskHandle_t xTaskEPDExampleHandle;
void vTaskEPDExample(void *pvParameters);
void app_lib_i2c_system_init(void);
@ -22,36 +28,10 @@ void app_main(void) {
// Init system peripherals.
app_lib_i2c_system_init();
//app_lib_pm_init();
app_lib_init_wifi();
app_lib_start_wifi();
app_lib_fs_init();
ESP_LOGI(TAG, "System initialized, starting tasks.");
// Init tasks
if(xTaskCreate(vTaskLEDs, "TASK_LEDs", 1024, NULL, 4, &xTaskLEDsHandle) != pdPASS) {
ESP_LOGE(TAG, "Task LED creation failed.");
for(;;) {
vTaskSuspend(NULL);
}
}
if(xTaskCreate(vTasBatteryExample, "TASK_BAT", 2048, NULL, 4, &xTaskBatteryExampleHandle) != pdPASS) {
ESP_LOGE(TAG, "Task BAT creation failed.");
for(;;) {
vTaskSuspend(NULL);
}
}
if(xTaskCreate(vTaskEPDExample, "TASK_EPD", 2048, NULL, 4, &xTaskEPDExampleHandle) != pdPASS) {
ESP_LOGE(TAG, "Task EPD creation failed.");
for(;;) {
vTaskSuspend(NULL);
}
}
ESP_LOGI(TAG, "Task created, suspending current task.");
xTaskCreate(vTaskLEDs, "TASK_LEDs", 1024, NULL, 4, &xTaskLEDsHandle);
xTaskCreate(vTasBatteryExample, "TASK_BAT", 2048, NULL, 4, &xTaskBatteryExampleHandle);
xTaskCreate(vTaskEPDExample, "TASK_EPD", 2048, NULL, 4, &xTaskEPDExampleHandle);
for(;;) {
vTaskSuspend(NULL);

View File

@ -23,10 +23,4 @@
#define BOARD_EPD_DC_PIN GPIO_NUM_12
#define BOARD_EPD_BUSY_PIN GPIO_NUM_11
#define BOARD_SD_MISO_PIN GPIO_NUM_3
#define BOARD_SD_MOSI_PIN GPIO_NUM_5
#define BOARD_SD_SCLK_PIN GPIO_NUM_4
#define BOARD_SD_CS_PIN GPIO_NUM_6
#define BOARD_SD_DET_PIN GPIO_NUM_7
#endif