Skip to content

Commit

Permalink
160 remove board defines (#168)
Browse files Browse the repository at this point in the history
* Add board HAL (Hardware abstraction layer)

Instead of using defines to set the board hardware definitions each
board get its own file with the routines to access the hardware
functions. This way also third party boards can be implemented
without being required to modify the epdiy source.

So far only logic from display_ops.c has been ported. Work still
also exists to optimize duplicated code.

Care has been taken to not break existing code bases. If a board is
defined in menuconfig this will still be used.

* Move content of config_reg_v4.h into epd_board_v5.c

The goal is to get rid of the config_reg_v*.h files

* Move content of config_reg_v4.h into epd_board_v4.c

* Move content of config_reg_v6.h into epd_board_v6.c

* Move content of config_reg_v2.h into epd_board_v2_v3.c

* Move content of config_reg_v2.h into epd_board_lilygo_t5_47.c

* Remove board specific defines from display_ops.h

* Free the i2s clock pin in i2s code

This should not be done for individual boards.

* Deprecate v6 board specific functions as generic function.

Boards specific code should be marked as such.

* Move temperature readings into board code

* Implement a control interface for gpios

Move signals oe, mode and stv to this
Implement start_frame using the ctrl interface

* Move logic of end_frame() from board to display_opts

* Remove uneccesary function latch_row()

* Move logic for latch_row from board to display_opts

* Remove warning about v6_wait_for_interrupt() is unused

* Optimize set_ctrl by supplying a mask with the changed signals

* Share the temperature readings between boards v2 to v5

* Deprecate epd_powerdown() and make it to a board specific function instead

* Read vcom voltage from epd_board_vcom_v6()

This makes vcom voltage available at runtime and not at compile time
  • Loading branch information
mickeprag committed May 30, 2022
1 parent 3ffb83c commit f1e266c
Show file tree
Hide file tree
Showing 25 changed files with 1,350 additions and 728 deletions.
13 changes: 13 additions & 0 deletions src/epd_board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
// This file is only used in the Arduino IDE
// and just includes the IDF component header.

#ifdef __cplusplus
extern "C" {
#endif

#include "epd_driver/include/epd_board.h"

#ifdef __cplusplus
}
#endif
10 changes: 9 additions & 1 deletion src/epd_driver/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

set(app_sources "epd_driver.c"
"epd_board.c"
"render.c"
"display_ops.c"
"tps65185.c"
Expand All @@ -11,7 +12,14 @@ set(app_sources "epd_driver.c"
"i2s_data_bus.c"
"rmt_pulse.c"
"highlevel.c"
"epd_temperature.c")
"epd_temperature.c"
"board/epd_board_common.c"
"board/epd_board_lilygo_t5_47.c"
"board/epd_board_v2_v3.c"
"board/epd_board_v4.c"
"board/epd_board_v5.c"
"board/epd_board_v6.c"
)


idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "include" REQUIRES esp_adc_cal)
Expand Down
3 changes: 3 additions & 0 deletions src/epd_driver/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ menu "E-Paper Driver"

config EPD_BOARD_REVISION_V6
bool "epdiy v6"

config EPD_BOARD_CUSTOM
bool "Custom board"
endchoice

config EPD_DRIVER_V6_VCOM
Expand Down
35 changes: 35 additions & 0 deletions src/epd_driver/board/epd_board_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "epd_board.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "esp_log.h"

static const adc1_channel_t channel = ADC1_CHANNEL_7;
static esp_adc_cal_characteristics_t adc_chars;

#define NUMBER_OF_SAMPLES 100

void epd_board_temperature_init_v2() {
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(
ADC_UNIT_1, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_12, 1100, &adc_chars
);
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
ESP_LOGI("epd_temperature", "Characterized using Two Point Value\n");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
ESP_LOGI("esp_temperature", "Characterized using eFuse Vref\n");
} else {
ESP_LOGI("esp_temperature", "Characterized using Default Vref\n");
}
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(channel, ADC_ATTEN_DB_6);
}

float epd_board_ambient_temperature_v2() {
uint32_t value = 0;
for (int i = 0; i < NUMBER_OF_SAMPLES; i++) {
value += adc1_get_raw(channel);
}
value /= NUMBER_OF_SAMPLES;
// voltage in mV
float voltage = esp_adc_cal_raw_to_voltage(value, &adc_chars);
return (voltage - 500.0) / 10.0;
}
8 changes: 8 additions & 0 deletions src/epd_driver/board/epd_board_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @file "epd_board_common.h"
* @brief Common board functions shared between boards.
*/
#pragma once

void epd_board_temperature_init_v2();
float epd_board_ambient_temperature_v2();
198 changes: 198 additions & 0 deletions src/epd_driver/board/epd_board_lilygo_t5_47.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#include "epd_board.h"

#include "../display_ops.h"
#include "../i2s_data_bus.h"
#include "../rmt_pulse.h"

#define CFG_DATA GPIO_NUM_23
#define CFG_CLK GPIO_NUM_18
#define CFG_STR GPIO_NUM_0
#define D7 GPIO_NUM_22
#define D6 GPIO_NUM_21
#define D5 GPIO_NUM_27
#define D4 GPIO_NUM_2
#define D3 GPIO_NUM_19
#define D2 GPIO_NUM_4
#define D1 GPIO_NUM_32
#define D0 GPIO_NUM_33

/* Control Lines */
#define CKV GPIO_NUM_25
#define STH GPIO_NUM_26

#define V4_LATCH_ENABLE GPIO_NUM_15

/* Edges */
#define CKH GPIO_NUM_5

typedef struct {
bool power_disable : 1;
bool pos_power_enable : 1;
bool neg_power_enable : 1;
bool ep_scan_direction : 1;
} epd_config_register_t;

static i2s_bus_config i2s_config = {
.clock = CKH,
.start_pulse = STH,
.data_0 = D0,
.data_1 = D1,
.data_2 = D2,
.data_3 = D3,
.data_4 = D4,
.data_5 = D5,
.data_6 = D6,
.data_7 = D7,
};

static void IRAM_ATTR push_cfg_bit(bool bit) {
gpio_set_level(CFG_CLK, 0);
gpio_set_level(CFG_DATA, bit);
gpio_set_level(CFG_CLK, 1);
}

static epd_config_register_t config_reg;

static void epd_board_init(uint32_t epd_row_width) {
/* Power Control Output/Off */
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_DATA], PIN_FUNC_GPIO);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_CLK], PIN_FUNC_GPIO);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_STR], PIN_FUNC_GPIO);
gpio_set_direction(CFG_DATA, GPIO_MODE_OUTPUT);
gpio_set_direction(CFG_CLK, GPIO_MODE_OUTPUT);
gpio_set_direction(CFG_STR, GPIO_MODE_OUTPUT);
fast_gpio_set_lo(CFG_STR);

config_reg.power_disable = true;
config_reg.pos_power_enable = false;
config_reg.neg_power_enable = false;
config_reg.ep_scan_direction = true;

// Setup I2S
// add an offset off dummy bytes to allow for enough timing headroom
i2s_bus_init( &i2s_config, epd_row_width + 32 );

rmt_pulse_init(CKV);
}

static void epd_board_set_ctrl(epd_ctrl_state_t *state, const epd_ctrl_state_t * const mask) {
if (state->ep_sth) {
fast_gpio_set_hi(STH);
} else {
fast_gpio_set_lo(STH);
}

if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv || mask->ep_latch_enable) {
fast_gpio_set_lo(CFG_STR);

// push config bits in reverse order
push_cfg_bit(state->ep_output_enable);
push_cfg_bit(state->ep_mode);
push_cfg_bit(config_reg.ep_scan_direction);
push_cfg_bit(state->ep_stv);

push_cfg_bit(config_reg.neg_power_enable);
push_cfg_bit(config_reg.pos_power_enable);
push_cfg_bit(config_reg.power_disable);
push_cfg_bit(state->ep_latch_enable);

fast_gpio_set_hi(CFG_STR);
}
}

static void epd_board_poweron(epd_ctrl_state_t *state) {
i2s_gpio_attach(&i2s_config);

// This was re-purposed as power enable.
config_reg.ep_scan_direction = true;

// POWERON
epd_ctrl_state_t mask = { // Trigger output to shift register
.ep_stv = true,
};
config_reg.power_disable = false;
epd_board_set_ctrl(state, &mask);
busy_delay(100 * 240);
config_reg.neg_power_enable = true;
epd_board_set_ctrl(state, &mask);
busy_delay(500 * 240);
config_reg.pos_power_enable = true;
epd_board_set_ctrl(state, &mask);
busy_delay(100 * 240);
state->ep_stv = true;
state->ep_sth = true;
mask.ep_sth = true;
epd_board_set_ctrl(state, &mask);
// END POWERON
}

void epd_powerdown_lilygo_t5_47() {
epd_ctrl_state_t *state = epd_ctrl_state();

// This was re-purposed as power enable however it also disables the touch.
// this workaround may still leave power on to epd and as such may cause other
// problems such as grey screen.
epd_ctrl_state_t mask = { // Trigger output to shift register
.ep_stv = true,
};
config_reg.pos_power_enable = false;
epd_board_set_ctrl(state, &mask);
busy_delay(10 * 240);

config_reg.neg_power_enable = false;
config_reg.pos_power_enable = false;
epd_board_set_ctrl(state, &mask);
busy_delay(100 * 240);

state->ep_stv = false;
mask.ep_stv = true;
state->ep_output_enable = false;
mask.ep_output_enable = true;
state->ep_mode = false;
mask.ep_mode = true;
config_reg.power_disable = true;
epd_board_set_ctrl(state, &mask);

i2s_gpio_detach(&i2s_config);
}

static void epd_board_poweroff(epd_ctrl_state_t *state) {
// This was re-purposed as power enable.
config_reg.ep_scan_direction = false;

// POWEROFF
epd_ctrl_state_t mask = { // Trigger output to shift register
.ep_stv = true,
};
config_reg.pos_power_enable = false;
epd_board_set_ctrl(state, &mask);
busy_delay(10 * 240);

config_reg.neg_power_enable = false;
config_reg.pos_power_enable = false;
epd_board_set_ctrl(state, &mask);
busy_delay(100 * 240);

state->ep_stv = false;
mask.ep_stv = true;
state->ep_output_enable = false;
mask.ep_output_enable = true;
state->ep_mode = false;
mask.ep_mode = true;
config_reg.power_disable = true;
epd_board_set_ctrl(state, &mask);

i2s_gpio_detach(&i2s_config);
// END POWEROFF
}

const EpdBoardDefinition epd_board_lilygo_t5_47 = {
.init = epd_board_init,
.deinit = NULL,
.set_ctrl = epd_board_set_ctrl,
.poweron = epd_board_poweron,
.poweroff = epd_board_poweroff,

.temperature_init = NULL,
.ambient_temperature = NULL,
};

0 comments on commit f1e266c

Please sign in to comment.