Skip to content

Commit d38f3ac

Browse files
trevarjJamie C. Driver
authored andcommitted
diy: waveshare lcd touch 2 improvements
- Added battery voltage and status - Added USB connectivity check (guess from ADC voltage) - Added sleep/wake using BOOT button - Enabled display brightness setting
1 parent 6a61cef commit d38f3ac

File tree

6 files changed

+226
-5
lines changed

6 files changed

+226
-5
lines changed

diy/waveshare/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
## S3 Touch LCD 2
44

5+
The device uses touchscreen navigation and the BOOT button for sleep/wake.
6+
Bluetooth is enabled by default but can be turned off with the NORADIO config
7+
script.
8+
59
## Flashing
610

7-
To prepare the board for flashing, hold down the `boot` button and plug in the
11+
To prepare the board for flashing, hold down the `BOOT` button and plug in the
812
USB at the same time.
913

1014
### Enclosure

main/display_hw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static void esp_lcd_init(void* _ignored)
8484
#ifdef ESP_PLATFORM
8585
esp_lcd_panel_io_handle_t io_handle = NULL;
8686

87-
#if CONFIG_DISPLAY_PIN_BL != -1
87+
#if CONFIG_DISPLAY_PIN_BL != -1 && !defined(CONFIG_BOARD_TYPE_WS_TOUCH_LCD2)
8888
gpio_config_t bk_gpio_config = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = 1ULL << CONFIG_DISPLAY_PIN_BL };
8989
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
9090
ESP_ERROR_CHECK(gpio_set_level(CONFIG_DISPLAY_PIN_BL, 0));

main/power.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "power/twatchs3.inc"
2626
#elif defined(CONFIG_HAS_IP5306)
2727
#include "power/ip5306.inc"
28+
#elif defined(CONFIG_BOARD_TYPE_WS_TOUCH_LCD2)
29+
#include "power/wslcdtouch2.inc"
2830
#else
2931
// Stubs for other hw boards (ie. no power management)
3032
#include "power/minimal.inc"

main/power/wslcdtouch2.inc

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
// Waveshare LCD Touch 2 implmentation
2+
//
3+
#include "esp_err.h"
4+
#include "freertos/idf_additions.h"
5+
#include "hal/adc_types.h"
6+
#include "hal/gpio_types.h"
7+
#include "iot_button.h"
8+
#include "power.h"
9+
#include "sdkconfig.h"
10+
#include "soc/gpio_num.h"
11+
#include <button_gpio.h>
12+
#include <driver/gpio.h>
13+
#include <driver/ledc.h>
14+
#include <esp_adc/adc_cali.h>
15+
#include <esp_adc/adc_cali_scheme.h>
16+
#include <esp_adc/adc_oneshot.h>
17+
#include <esp_sleep.h>
18+
19+
#define BATTERY_ADC_CHANNEL ADC_CHANNEL_4
20+
#define ADC_ATTEN ADC_ATTEN_DB_12
21+
22+
#define LCD_BL_LEDC_TIMER LEDC_TIMER_0
23+
#define LCD_BL_LEDC_MODE LEDC_LOW_SPEED_MODE
24+
25+
#define LCD_BL_LEDC_CHANNEL LEDC_CHANNEL_0
26+
#define LCD_BL_LEDC_DUTY_RES LEDC_TIMER_10_BIT
27+
#define LCD_BL_LEDC_DUTY (1024)
28+
#define LCD_BL_LEDC_FREQUENCY (10000)
29+
30+
static adc_oneshot_unit_handle_t adc1_handle = NULL;
31+
adc_cali_handle_t adc1_cali_chan0_handle = NULL;
32+
33+
const float ema_alpha = 0.3; // Estimated moving average smoothing factor
34+
int ema_voltage = 0;
35+
36+
void brightness_init(void)
37+
{
38+
gpio_set_direction(CONFIG_DISPLAY_PIN_BL, GPIO_MODE_OUTPUT);
39+
gpio_set_level(CONFIG_DISPLAY_PIN_BL, 1);
40+
41+
ledc_timer_config_t ledc_timer = { .speed_mode = LCD_BL_LEDC_MODE,
42+
.timer_num = LCD_BL_LEDC_TIMER,
43+
.duty_resolution = LCD_BL_LEDC_DUTY_RES,
44+
.freq_hz = LCD_BL_LEDC_FREQUENCY, // Set output frequency at 5 kHz
45+
.clk_cfg = LEDC_AUTO_CLK };
46+
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
47+
48+
ledc_channel_config_t ledc_channel = { .speed_mode = LCD_BL_LEDC_MODE,
49+
.channel = LCD_BL_LEDC_CHANNEL,
50+
.timer_sel = LCD_BL_LEDC_TIMER,
51+
.intr_type = LEDC_INTR_DISABLE,
52+
.gpio_num = CONFIG_DISPLAY_PIN_BL,
53+
.duty = 0, // Set duty to 0%
54+
.hpoint = 0 };
55+
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
56+
}
57+
58+
static void button_shutdown(void* arg, void* ctx)
59+
{
60+
power_backlight_off();
61+
while (gpio_get_level(GPIO_NUM_0) == 0) {
62+
vTaskDelay(pdMS_TO_TICKS(10));
63+
}
64+
power_shutdown();
65+
}
66+
67+
void boot_button_init(void)
68+
{
69+
const button_config_t btn_cfg = {
70+
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
71+
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
72+
};
73+
74+
const button_gpio_config_t btn_gpio_cfg = {
75+
.gpio_num = 0,
76+
.active_level = 0,
77+
};
78+
79+
button_handle_t btn_handle = NULL;
80+
ESP_ERROR_CHECK(iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &btn_handle));
81+
82+
JADE_ASSERT(btn_handle);
83+
84+
ESP_ERROR_CHECK(iot_button_register_cb(btn_handle, BUTTON_LONG_PRESS_HOLD, NULL, button_shutdown, NULL));
85+
86+
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
87+
gpio_hold_en(GPIO_NUM_0);
88+
gpio_deep_sleep_hold_en();
89+
esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 0);
90+
}
91+
92+
esp_err_t power_init(void)
93+
{
94+
// Use the BOOT button as a sleep/wakeup button
95+
boot_button_init();
96+
97+
// Initialise backlight brightness
98+
brightness_init();
99+
100+
// Initialise the ADC to measure battery level
101+
adc_oneshot_unit_init_cfg_t init_config1 = {
102+
.unit_id = ADC_UNIT_1,
103+
};
104+
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
105+
JADE_ASSERT(adc1_handle);
106+
107+
adc_oneshot_chan_cfg_t config = {
108+
.bitwidth = ADC_BITWIDTH_DEFAULT,
109+
.atten = ADC_ATTEN_DB_12,
110+
};
111+
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, BATTERY_ADC_CHANNEL, &config));
112+
113+
// Use voltage calibration
114+
adc_cali_curve_fitting_config_t cali_config = {
115+
.unit_id = ADC_UNIT_1,
116+
.atten = ADC_ATTEN,
117+
.bitwidth = ADC_BITWIDTH_DEFAULT,
118+
};
119+
if (adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_chan0_handle) != ESP_OK) {
120+
JADE_LOGW("ADC calibration not available, continuing without it");
121+
adc1_cali_chan0_handle = NULL;
122+
}
123+
124+
return ESP_OK;
125+
}
126+
127+
esp_err_t power_shutdown(void) { esp_deep_sleep_start(); }
128+
129+
esp_err_t power_screen_on(void) { return ESP_OK; }
130+
esp_err_t power_screen_off(void) { return ESP_OK; }
131+
132+
esp_err_t power_backlight_on(const uint8_t brightness)
133+
{
134+
uint32_t new_brightness = brightness * 20;
135+
if (new_brightness > 100) {
136+
return ESP_OK;
137+
}
138+
139+
uint32_t duty = (new_brightness * (LCD_BL_LEDC_DUTY - 1)) / 100;
140+
ESP_ERROR_CHECK(ledc_set_duty(LCD_BL_LEDC_MODE, LCD_BL_LEDC_CHANNEL, duty));
141+
ESP_ERROR_CHECK(ledc_update_duty(LCD_BL_LEDC_MODE, LCD_BL_LEDC_CHANNEL));
142+
143+
return ESP_OK;
144+
}
145+
146+
esp_err_t power_backlight_off(void)
147+
{
148+
ESP_ERROR_CHECK(ledc_set_duty(LCD_BL_LEDC_MODE, LCD_BL_LEDC_CHANNEL, 0));
149+
ESP_ERROR_CHECK(ledc_update_duty(LCD_BL_LEDC_MODE, LCD_BL_LEDC_CHANNEL));
150+
151+
return ESP_OK;
152+
}
153+
154+
esp_err_t power_camera_on(void) { return ESP_OK; }
155+
esp_err_t power_camera_off(void) { return ESP_OK; }
156+
157+
uint16_t power_get_vbat(void)
158+
{
159+
JADE_ASSERT(adc1_handle);
160+
int raw_adc = 0;
161+
int voltage;
162+
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, BATTERY_ADC_CHANNEL, &raw_adc));
163+
164+
if (adc1_cali_chan0_handle) {
165+
adc_cali_raw_to_voltage(adc1_cali_chan0_handle, raw_adc, &voltage);
166+
} else {
167+
voltage = (raw_adc * 3300) / 4095; // mV
168+
}
169+
170+
// apply Estimated Moving Average since the ADC seems to have a lot of noise
171+
ema_voltage = ema_alpha * voltage + (1 - ema_alpha) * (ema_voltage == 0 ? voltage : ema_voltage);
172+
/* JADE_LOGI("Raw: %.2dmV, Smoothed: %.2d mV", voltage, ema_voltage); */
173+
return (uint16_t)ema_voltage;
174+
}
175+
176+
uint8_t power_get_battery_status(void)
177+
{
178+
int vbat = power_get_vbat() * 3; // apply voltage divider
179+
if (vbat < 3000)
180+
return 0;
181+
else if (vbat < 3200)
182+
return 1;
183+
else if (vbat < 3400)
184+
return 2;
185+
else if (vbat < 3600)
186+
return 3;
187+
else if (vbat < 3800)
188+
return 4;
189+
else
190+
return 5;
191+
}
192+
193+
// The STAT pin on the charging IC isn't exposed to a GPIO so we cannot read it
194+
// and can't easily tap it with a wire. There is a charging LED though so you
195+
// can see if the battery is being charged.
196+
bool power_get_battery_charging(void) { return 0; }
197+
uint16_t power_get_ibat_charge(void) { return 0; }
198+
uint16_t power_get_ibat_discharge(void) { return 0; }
199+
uint16_t power_get_vusb(void) { return 0; }
200+
uint16_t power_get_iusb(void) { return 0; }
201+
uint16_t power_get_temp(void) { return 0; }
202+
203+
void disable_usb_host(void) {}
204+
void enable_usb_host(void) {}
205+
206+
// This is only a guess by the ADC voltage when the USB is plugged in
207+
bool usb_connected(void) { return power_get_vbat() > 1350; }

main/process/dashboard.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,7 +1708,8 @@ static void handle_view_otps(void)
17081708
}
17091709

17101710
// NOTE: Only Jade v1.1's and v2's have brightness controls
1711-
#if defined(CONFIG_BOARD_TYPE_JADE_V1_1) || defined(CONFIG_BOARD_TYPE_JADE_V2)
1711+
#if defined(CONFIG_BOARD_TYPE_JADE_V1_1) || defined(CONFIG_BOARD_TYPE_JADE_V2) \
1712+
|| defined(CONFIG_BOARD_TYPE_WS_TOUCH_LCD2)
17121713
static void handle_screen_brightness(void)
17131714
{
17141715
static const char* LABELS[] = { "Min(1)", "Low(2)", "Medium(3)", "High(4)", "Max(5)" };
@@ -2053,6 +2054,12 @@ static void handle_display_battery_volts(void)
20532054
const int ret = snprintf(power_status, sizeof(power_status), "%umv", vbat);
20542055
JADE_ASSERT(ret > 0 && ret < sizeof(power_status));
20552056
}
2057+
#elif defined(CONFIG_BOARD_TYPE_WS_TOUCH_LCD2)
2058+
const uint16_t vbat = power_get_vbat() * 3; // applying voltage divider
2059+
if (vbat > 0) {
2060+
const int ret = snprintf(power_status, sizeof(power_status), "%umv", vbat);
2061+
JADE_ASSERT(ret > 0 && ret < sizeof(power_status));
2062+
}
20562063
#elif defined(CONFIG_HAS_IP5306)
20572064
const float approx_voltage = power_get_vbat() / 1000.0;
20582065
const int ret = snprintf(power_status, sizeof(power_status), "Approx %.1fv", approx_voltage);
@@ -2277,7 +2284,8 @@ static void handle_settings(const bool startup_menu)
22772284
break;
22782285

22792286
// NOTE: Only Jade v1.1's and v2's have brightness controls
2280-
#if defined(CONFIG_BOARD_TYPE_JADE_V1_1) || defined(CONFIG_BOARD_TYPE_JADE_V2)
2287+
#if defined(CONFIG_BOARD_TYPE_JADE_V1_1) || defined(CONFIG_BOARD_TYPE_JADE_V2) \
2288+
|| defined(CONFIG_BOARD_TYPE_WS_TOUCH_LCD2)
22812289
case BTN_SETTINGS_DISPLAY_BRIGHTNESS:
22822290
handle_screen_brightness();
22832291
break;

main/ui/dashboard.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ gui_activity_t* make_display_settings_activity(void)
403403

404404
// NOTE: Only Jade v1.1's and v2's have brightness controls
405405
// NOTE: Jade v1.1's do not support Flip Orientation because of issues with screen offsets
406-
#if defined(CONFIG_BOARD_TYPE_JADE_V2)
406+
#if defined(CONFIG_BOARD_TYPE_JADE_V2) || defined(CONFIG_BOARD_TYPE_WS_TOUCH_LCD2)
407407
btn_data_t menubtns[]
408408
= { { .txt = "Display Brightness", .font = GUI_DEFAULT_FONT, .ev_id = BTN_SETTINGS_DISPLAY_BRIGHTNESS },
409409
{ .txt = "Flip Orientation", .font = GUI_DEFAULT_FONT, .ev_id = BTN_SETTINGS_DISPLAY_ORIENTATION },

0 commit comments

Comments
 (0)