Initial EPD driver.
This commit is contained in:
parent
55888994c8
commit
00c2d28ea7
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
18
main/main.c
18
main/main.c
|
@ -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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue