Initial EPD driver.

This commit is contained in:
imi415 2021-05-31 00:49:50 +08:00
parent 55888994c8
commit 00c2d28ea7
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
16 changed files with 318 additions and 13 deletions

View File

@ -2,6 +2,7 @@ idf_component_register(SRCS
"main.c"
"app_task_led.c"
"app_task_epd.c"
"app_task_battery.c"
"app_lib_i2c_system.c"
"app_lib_bat_impl.c"
"app_lib_epd_impl.c"

View File

@ -1,15 +1,52 @@
#include "esp_log.h"
#include "driver/i2c.h"
#include "user_board.h"
#include "app_lib_bat_impl.h"
#define LTC2941_ADDR 0x64 // Unshifted
static const char *TAG = "BAT_IMPL"
static const char *TAG = "BAT_IMPL";
ltc2941_ret_t app_lib_bat_read_register(app_lib_bat_impl_t *impl, uint8_t reg, uint8_t *value) {
ESP_LOGD(TAG, "Read register: %d", reg);
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, LTC2941_ADDR << 1 | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg, true);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, LTC2941_ADDR << 1 | I2C_MASTER_READ, true);
i2c_master_read_byte(cmd, value, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
esp_err_t err = i2c_master_cmd_begin(impl->i2c_num, cmd, pdMS_TO_TICKS(1000));
i2c_cmd_link_delete(cmd);
if(err != ESP_OK) {
ESP_LOGE(TAG, "Read register reported error, %s", esp_err_to_name(err));
return LTC2941_ERROR;
}
return LTC2941_OK;
}
ltc2941_ret_t app_lib_bat_write_register(app_lib_bat_impl_t *impl, uint8_t reg, uint8_t value) {
ESP_LOGD(TAG, "Write register: %d", reg);
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, LTC2941_ADDR << 1 | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg, true);
i2c_master_write_byte(cmd, value, true);
i2c_master_stop(cmd);
esp_err_t err = i2c_master_cmd_begin(impl->i2c_num, cmd, pdMS_TO_TICKS(1000));
i2c_cmd_link_delete(cmd);
if(err != ESP_OK) {
ESP_LOGE(TAG, "Write register reported error, %s", esp_err_to_name(err));
return LTC2941_ERROR;
}
return LTC2941_OK;
}

View File

@ -1,10 +1,12 @@
#ifndef __APP_LIB_BAT_IMPL_H
#define __APP_LIB_BAT_IMPL_H
#include "driver/i2c.h"
#include "ltc2941_battery.h"
typedef struct {
int i2c_num;
} app_lib_bat_impl_t;
ltc2941_ret_t app_lib_bat_read_register(app_lib_bat_impl_t *impl, uint8_t reg, uint8_t *value);

View File

@ -0,0 +1,114 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "user_board.h"
#include "app_lib_epd_impl.h"
#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) {
gpio_set_level(BOARD_EPD_DC_PIN, (int)txn->user);
}
void app_lib_epd_impl_init(app_lib_epd_impl_t *impl) {
gpio_config_t io_config = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT_OD,
.pin_bit_mask = (1 << BOARD_EPD_RES_PIN),
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE
};
gpio_config(&io_config);
io_config.pin_bit_mask = (1 << BOARD_EPD_DC_PIN);
io_config.pull_up_en = GPIO_PULLUP_DISABLE;
io_config.mode = GPIO_MODE_OUTPUT;
gpio_config(&io_config);
io_config.pin_bit_mask = (1 << BOARD_EPD_BUSY_PIN);
io_config.mode = GPIO_MODE_INPUT;
gpio_config(&io_config);
spi_bus_config_t bus_cfg = {
.mosi_io_num = BOARD_EPD_SPI_MOSI_PIN,
.sclk_io_num = BOARD_EPD_SPI_SCK_PIN,
.miso_io_num = -1,
.quadhd_io_num = -1,
.quadwp_io_num = -1,
.max_transfer_sz = MAXIMUM_XFER_SIZE
};
spi_device_interface_config_t interface_config = {
.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,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &interface_config, &impl->spi_handle));
}
gd_epd_042_ret_t app_lib_epd_impl_reset(app_lib_epd_impl_t *impl) {
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_impl_write_cmd(app_lib_epd_impl_t *impl, uint8_t *cmd, uint8_t len) {
esp_err_t ret;
spi_transaction_t txn = {
.length = 8,
.tx_buffer = cmd,
.user = (void *)0
};
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
if(ret != ESP_OK) return EPD_ERR;
if(len > 1) {
txn.length = 8 * len - 1;
txn.tx_buffer = &cmd[1];
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
if(ret != ESP_OK) return EPD_ERR;
}
return EPD_OK;
}
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;
spi_transaction_t txn = {
.length = 8 * len,
.tx_buffer = data,
.user = (void *)1
};
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
if(ret != ESP_OK) return EPD_ERR;
return EPD_OK;
}
gd_epd_042_ret_t app_lib_epd_impl_poll_busy(app_lib_epd_impl_t *impl) {
uint8_t count = MAX_BUSY_POLL_COUNT;
while(gpio_get_level(BOARD_EPD_BUSY_PIN) == 0) {
vTaskDelay(10);
if(count == 0) {
return EPD_ERR;
}
count--;
}
return EPD_OK;
}

View File

@ -1,6 +1,19 @@
#ifndef __APP_LIB_EPD_IMPL_H
#define __APP_LIB_EPD_IMPL_H
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "gdew042t2_epd.h"
typedef struct {
spi_device_handle_t spi_handle;
} app_lib_epd_impl_t;
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_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);
#endif

View File

@ -8,9 +8,9 @@ void app_lib_i2c_system_init(void) {
.mode = I2C_MODE_MASTER,
.sda_io_num = BOARD_SYSTEM_I2C_SDA_PIN,
.scl_io_num = BOARD_SYSTEM_I2C_SCL_PIN,
.sda_pullup_en = GPIO_PULLUP_DISABLE,
.scl_pullup_en = GPIO_PULLUP_DISABLE,
.master.clk_speed = 400000
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000
};
esp_err_t err = i2c_param_config(BOARD_SYSTEM_I2C_NUM, &conf);

48
main/app_task_battery.c Normal file
View File

@ -0,0 +1,48 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "user_board.h"
#include "app_lib_bat_impl.h"
#define BATTERY_CAP 3000.0
#define MAH_LSB 0.053125 // Shunt 20mR
#define PRESCALER_M LTC2941_PRE_32
const static char *TAG = "TASK_BAT";
TaskHandle_t xTaskBatteryExampleHandle = NULL;
void vTasBatteryExample(void *pvParameters) {
app_lib_bat_impl_t impl = {
.i2c_num = BOARD_SYSTEM_I2C_NUM
};
ltc2941_t battery_fg = {
.user_data = &impl,
.cb = {
.read_register_cb = (ltc2941_ret_t (*)(void *, uint8_t, uint8_t *))app_lib_bat_read_register,
.write_register_cb = (ltc2941_ret_t (*)(void *, uint8_t, uint8_t))app_lib_bat_write_register
},
.config = {
.alert_level = LTC2941_ALERT_3_0V,
.alert_mode = LTC2941_ALERT_DISABLED,
.prescaler = PRESCALER_M
}
};
ltc2941_init(&battery_fg);
for(;;) {
uint16_t fg_data = 0x00;
ltc2941_read_charge(&battery_fg, &fg_data);
float percentage = fg_data * MAH_LSB * 100.0 / BATTERY_CAP;
ESP_LOGI(TAG, "Charge: %.2f", percentage);
vTaskDelay(pdMS_TO_TICKS(30000));
}
}

View File

@ -1,11 +1,39 @@
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "gdew042t2_epd.h"
#include "app_lib_epd_impl.h"
static uint8_t frame_data[15000][2];
static uint8_t current_frame = 0;
TaskHandle_t xTaskEPDExampleHandle = NULL;
void vTaskEPDExample(void *pvParameters) {
for(;;) {
app_lib_epd_impl_t epd_impl = {0};
gd_epd_042_t epd = {
.cb = {
.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
},
.user_data = &epd_impl
};
app_lib_epd_impl_init(&epd_impl);
gd_epd_042_init(&epd);
memset(frame_data[current_frame], 0xFF, 15000);
memset(frame_data[(~current_frame) & 0x01], 0xFF, 15000);
gd_epd_042_load(&epd, frame_data[current_frame], frame_data[(~current_frame) & 0x01]);
gd_epd_042_update(&epd);
gd_epd_042_deepsleep(&epd);
for(;;) {
vTaskDelay(10000);
}
}

View File

@ -8,6 +8,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;
void vTaskLEDs(void *pvParameters) {
@ -85,16 +87,17 @@ void vTaskLEDs(void *pvParameters) {
ledc_fade_func_install(0);
for(;;) {
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, 1023, 2500);
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(2500));
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, 0, 2500);
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(2500));
vTaskDelay(pdMS_TO_TICKS(BREATHE_LED_CYCLE));
}
}

View File

@ -51,4 +51,4 @@ gd_epd_042_ret_t gd_epd_042_update(gd_epd_042_t *epd) {
epd->cb.poll_busy_cb(epd->user_data);
return EPD_OK;
}
}

View File

@ -21,5 +21,8 @@ typedef struct {
} gd_epd_042_t;
gd_epd_042_ret_t gd_epd_042_init(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);
gd_epd_042_ret_t gd_epd_042_update(gd_epd_042_t *epd);
gd_epd_042_ret_t gd_epd_042_deepsleep(gd_epd_042_t *epd);
#endif

6
main/lib/htu21d_dht.c Normal file
View File

@ -0,0 +1,6 @@
#include "htu21d_dht.h"
htu21d_ret_t htu21d_init(htu21d_t *htu) {
htu->cb.write_command_cb(htu->user_data, 0xFE, 0x00);
return HTU21D_OK;
}

21
main/lib/htu21d_dht.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef __HTU21D_DHT_H
#define __HTU21D_DHT_H
#include <stdint.h>
typedef enum {
HTU21D_OK,
HTU21D_ERROR
} htu21d_ret_t;
typedef struct {
htu21d_ret_t (*write_command_cb)(void * handle, uint8_t reg, uint8_t value);
htu21d_ret_t (*read_data_cb)(void *handle, uint8_t reg, uint8_t *value);
} htu21d_cb_t;
typedef struct {
htu21d_cb_t cb;
void *user_data;
} htu21d_t;
#endif

View File

@ -56,4 +56,8 @@ typedef struct {
#define LTC2941_STATUS_ALRT_VBAT (1 << 1U)
#define LTC2941_STATUS_ALRT_UVLO 1U
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);
#endif

View File

@ -4,16 +4,34 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "user_board.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);
static const char *TAG = "APP_MAIN";
void app_main(void) {
// Init system peripherals.
app_lib_i2c_system_init();
// Init tasks
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

@ -16,4 +16,11 @@
#define BOARD_SYSTEM_I2C_SDA_PIN GPIO_NUM_39
#define BOARD_SYSTEM_I2C_SCL_PIN GPIO_NUM_40
#define BOARD_EPD_SPI_CS_PIN GPIO_NUM_13
#define BOARD_EPD_SPI_MOSI_PIN GPIO_NUM_15
#define BOARD_EPD_SPI_SCK_PIN GPIO_NUM_14
#define BOARD_EPD_RES_PIN GPIO_NUM_10
#define BOARD_EPD_DC_PIN GPIO_NUM_12
#define BOARD_EPD_BUSY_PIN GPIO_NUM_11
#endif