Skip to content

Commit a7dcd11

Browse files
authored
Merge pull request #608 from Quency-D/dev-heltec_e213
Add heltec_vision_master_e213 board.
2 parents 82206fd + aa7f9d8 commit a7dcd11

File tree

11 files changed

+444
-23
lines changed

11 files changed

+444
-23
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"build": {
3+
"arduino": {
4+
"ldscript": "esp32s3_out.ld",
5+
"partitions": "default_16MB.csv",
6+
"memory_type": "qio_opi"
7+
},
8+
"core": "esp32",
9+
"extra_flags": [
10+
"-DBOARD_HAS_PSRAM",
11+
"-DARDUINO_USB_MODE=0",
12+
"-DARDUINO_USB_CDC_ON_BOOT=1",
13+
"-DARDUINO_RUNNING_CORE=1",
14+
"-DARDUINO_EVENT_RUNNING_CORE=1"
15+
],
16+
"f_cpu": "240000000L",
17+
"f_flash": "80000000L",
18+
"flash_mode": "qio",
19+
"psram_type": "opi",
20+
"hwids": [
21+
["0x303A", "0x1001"],
22+
["0x303A", "0x0002"]
23+
],
24+
"mcu": "esp32s3",
25+
"variant": "heltec_vision_master_e213"
26+
},
27+
"connectivity": ["wifi", "bluetooth", "lora"],
28+
"debug": {
29+
"openocd_target": "esp32s3.cfg"
30+
},
31+
"frameworks": ["arduino", "espidf"],
32+
"name": "Heltec Vision Master E213",
33+
"upload": {
34+
"flash_size": "16MB",
35+
"maximum_ram_size": 8388608,
36+
"maximum_size": 16777216,
37+
"use_1200bps_touch": true,
38+
"wait_for_upload_port": true,
39+
"require_upload_port": true,
40+
"speed": 921600
41+
},
42+
"url": "https://heltec.org/project/vision-master-e213/",
43+
"vendor": "Heltec"
44+
}

src/helpers/RefCountedDigitalPin.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,25 @@
55
class RefCountedDigitalPin {
66
uint8_t _pin;
77
int8_t _claims = 0;
8-
8+
uint8_t _active = 0;
99
public:
10-
RefCountedDigitalPin(uint8_t pin): _pin(pin) { }
10+
RefCountedDigitalPin(uint8_t pin,uint8_t active=HIGH): _pin(pin), _active(active) { }
1111

1212
void begin() {
1313
pinMode(_pin, OUTPUT);
14-
digitalWrite(_pin, LOW); // initial state
14+
digitalWrite(_pin, !_active); // initial state
1515
}
1616

1717
void claim() {
1818
_claims++;
1919
if (_claims > 0) {
20-
digitalWrite(_pin, HIGH);
20+
digitalWrite(_pin, _active);
2121
}
2222
}
2323
void release() {
2424
_claims--;
2525
if (_claims == 0) {
26-
digitalWrite(_pin, LOW);
26+
digitalWrite(_pin, !_active);
2727
}
2828
}
2929
};

src/helpers/ui/E213Display.cpp

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,82 @@
22

33
#include "../../MeshCore.h"
44

5+
BaseDisplay* E213Display::detectEInk()
6+
{
7+
// Test 1: Logic of BUSY pin
8+
9+
// Determines controller IC manufacturer
10+
// Fitipower: busy when LOW
11+
// Solomon Systech: busy when HIGH
12+
13+
// Force display BUSY by holding reset pin active
14+
pinMode(DISP_RST, OUTPUT);
15+
digitalWrite(DISP_RST, LOW);
16+
17+
delay(10);
18+
19+
// Read whether pin is HIGH or LOW while busy
20+
pinMode(DISP_BUSY, INPUT);
21+
bool busyLogic = digitalRead(DISP_BUSY);
22+
23+
// Test complete. Release pin
24+
pinMode(DISP_RST, INPUT);
25+
26+
if (busyLogic == LOW) {
27+
#ifdef VISION_MASTER_E213
28+
return new EInkDisplay_VisionMasterE213 ;
29+
#else
30+
return new EInkDisplay_WirelessPaperV1_1 ;
31+
#endif
32+
} else {// busy HIGH
33+
#ifdef VISION_MASTER_E213
34+
return new EInkDisplay_VisionMasterE213V1_1 ;
35+
#else
36+
return new EInkDisplay_WirelessPaperV1_1_1 ;
37+
#endif
38+
}
39+
}
40+
541
bool E213Display::begin() {
642
if (_init) return true;
743

844
powerOn();
9-
display.begin();
10-
45+
if(display==NULL) {
46+
display = detectEInk();
47+
}
48+
display->begin();
1149
// Set to landscape mode rotated 180 degrees
12-
display.setRotation(3);
50+
display->setRotation(3);
1351

1452
_init = true;
1553
_isOn = true;
1654

1755
clear();
18-
display.fastmodeOn(); // Enable fast mode for quicker (partial) updates
56+
display->fastmodeOn(); // Enable fast mode for quicker (partial) updates
1957

2058
return true;
2159
}
2260

2361
void E213Display::powerOn() {
2462
#ifdef PIN_VEXT_EN
2563
pinMode(PIN_VEXT_EN, OUTPUT);
64+
#ifdef PIN_VEXT_EN_ACTIVE
65+
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
66+
#else
2667
digitalWrite(PIN_VEXT_EN, LOW); // Active low
68+
#endif
2769
delay(50); // Allow power to stabilize
2870
#endif
2971
}
3072

3173
void E213Display::powerOff() {
3274
#ifdef PIN_VEXT_EN
75+
#ifdef PIN_VEXT_EN_ACTIVE
76+
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE);
77+
#else
3378
digitalWrite(PIN_VEXT_EN, HIGH); // Turn off power
3479
#endif
80+
#endif
3581
}
3682

3783
void E213Display::turnOn() {
@@ -46,41 +92,43 @@ void E213Display::turnOff() {
4692
}
4793

4894
void E213Display::clear() {
49-
display.clear();
95+
display->clear();
96+
5097
}
5198

5299
void E213Display::startFrame(Color bkg) {
53100
// Fill screen with white first to ensure clean background
54-
display.fillRect(0, 0, width(), height(), WHITE);
101+
display->fillRect(0, 0, width(), height(), WHITE);
102+
55103
if (bkg == LIGHT) {
56104
// Fill with black if light background requested (inverted for e-ink)
57-
display.fillRect(0, 0, width(), height(), BLACK);
105+
display->fillRect(0, 0, width(), height(), BLACK);
58106
}
59107
}
60108

61109
void E213Display::setTextSize(int sz) {
62110
// The library handles text size internally
63-
display.setTextSize(sz);
111+
display->setTextSize(sz);
64112
}
65113

66114
void E213Display::setColor(Color c) {
67115
// implemented in individual display methods
68116
}
69117

70118
void E213Display::setCursor(int x, int y) {
71-
display.setCursor(x, y);
119+
display->setCursor(x, y);
72120
}
73121

74122
void E213Display::print(const char *str) {
75-
display.print(str);
123+
display->print(str);
76124
}
77125

78126
void E213Display::fillRect(int x, int y, int w, int h) {
79-
display.fillRect(x, y, w, h, BLACK);
127+
display->fillRect(x, y, w, h, BLACK);
80128
}
81129

82130
void E213Display::drawRect(int x, int y, int w, int h) {
83-
display.drawRect(x, y, w, h, BLACK);
131+
display->drawRect(x, y, w, h, BLACK);
84132
}
85133

86134
void E213Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
@@ -98,7 +146,7 @@ void E213Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
98146

99147
// If the bit is set, draw the pixel
100148
if (bitSet) {
101-
display.drawPixel(x + bx, y + by, BLACK);
149+
display->drawPixel(x + bx, y + by, BLACK);
102150
}
103151
}
104152
}
@@ -107,10 +155,10 @@ void E213Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
107155
uint16_t E213Display::getTextWidth(const char *str) {
108156
int16_t x1, y1;
109157
uint16_t w, h;
110-
display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
158+
display->getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
111159
return w;
112160
}
113161

114162
void E213Display::endFrame() {
115-
display.update();
163+
display->update();
116164
}

src/helpers/ui/E213Display.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88

99
// Display driver for E213 e-ink display
1010
class E213Display : public DisplayDriver {
11-
EInkDisplay_VisionMasterE213 display;
11+
BaseDisplay* display=NULL;
1212
bool _init = false;
1313
bool _isOn = false;
1414

1515
public:
1616
E213Display() : DisplayDriver(250, 122) {}
17-
17+
~E213Display(){
18+
if(display!=NULL) {
19+
delete display;
20+
}
21+
}
1822
bool begin();
1923
bool isOn() override { return _isOn; }
2024
void turnOn() override;
@@ -32,6 +36,7 @@ class E213Display : public DisplayDriver {
3236
void endFrame() override;
3337

3438
private:
39+
BaseDisplay* detectEInk();
3540
void powerOn();
3641
void powerOff();
3742
};
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "HeltecE213Board.h"
2+
3+
void HeltecE213Board::begin() {
4+
ESP32Board::begin();
5+
6+
pinMode(PIN_ADC_CTRL, OUTPUT);
7+
digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive
8+
9+
periph_power.begin();
10+
11+
esp_reset_reason_t reason = esp_reset_reason();
12+
if (reason == ESP_RST_DEEPSLEEP) {
13+
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
14+
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
15+
startup_reason = BD_STARTUP_RX_PACKET;
16+
}
17+
18+
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
19+
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
20+
}
21+
}
22+
23+
void HeltecE213Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
24+
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
25+
26+
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
27+
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
28+
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
29+
30+
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
31+
32+
if (pin_wake_btn < 0) {
33+
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet
34+
} else {
35+
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet OR wake btn
36+
}
37+
38+
if (secs > 0) {
39+
esp_sleep_enable_timer_wakeup(secs * 1000000);
40+
}
41+
42+
// Finally set ESP32 into sleep
43+
esp_deep_sleep_start(); // CPU halts here and never returns!
44+
}
45+
46+
void HeltecE213Board::powerOff() {
47+
// TODO: re-enable this when there is a definite wake-up source pin:
48+
// enterDeepSleep(0);
49+
}
50+
51+
uint16_t HeltecE213Board::getBattMilliVolts() {
52+
analogReadResolution(10);
53+
digitalWrite(PIN_ADC_CTRL, HIGH);
54+
55+
uint32_t raw = 0;
56+
for (int i = 0; i < 8; i++) {
57+
raw += analogRead(PIN_VBAT_READ);
58+
}
59+
raw = raw / 8;
60+
61+
digitalWrite(PIN_ADC_CTRL, LOW);
62+
63+
return (5.42 * (3.3 / 1024.0) * raw) * 1000;
64+
}
65+
66+
const char* HeltecE213Board::getManufacturerName() const {
67+
return "Heltec E213";
68+
}
69+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
3+
#include <Arduino.h>
4+
#include <helpers/RefCountedDigitalPin.h>
5+
#include <helpers/ESP32Board.h>
6+
#include <driver/rtc_io.h>
7+
8+
// LoRa radio module pins for heltec_vision_master_e213
9+
#define P_LORA_DIO_1 14
10+
#define P_LORA_NSS 8
11+
#define P_LORA_RESET 12
12+
#define P_LORA_BUSY 13
13+
#define P_LORA_SCLK 9
14+
#define P_LORA_MISO 11
15+
#define P_LORA_MOSI 10
16+
17+
class HeltecE213Board : public ESP32Board {
18+
19+
public:
20+
RefCountedDigitalPin periph_power;
21+
22+
HeltecE213Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { }
23+
24+
void begin();
25+
void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1);
26+
void powerOff() override;
27+
uint16_t getBattMilliVolts() override;
28+
const char* getManufacturerName() const override ;
29+
30+
};

0 commit comments

Comments
 (0)