Skip to content

Commit 0a8d382

Browse files
committed
Add support for 7 segment displays
1 parent 7351165 commit 0a8d382

File tree

4 files changed

+180
-28
lines changed

4 files changed

+180
-28
lines changed

components/ht16k33_alpha/display.py

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
import esphome.codegen as cg
22
import esphome.config_validation as cv
33
from esphome.components import display, i2c
4-
from esphome.const import CONF_ID, CONF_LAMBDA
4+
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_TYPE
55

66
DEPENDENCIES = ['i2c']
77

8-
ht16k33_alpha_ns = cg.esphome_ns.namespace('ht16k33_alpha')
9-
HT16K33AlphaDisplay = ht16k33_alpha_ns.class_('HT16K33AlphaDisplay', cg.PollingComponent, i2c.I2CDevice)
8+
ht16k33_ns = cg.esphome_ns.namespace('ht16k33')
9+
HT16K33BaseDisplay = ht16k33_ns.class_('HT16K33BaseDisplay', cg.PollingComponent, i2c.I2CDevice)
10+
11+
TYPES = {
12+
"ALPHA": ht16k33_ns.class_("HT16K33AlphaDisplay", HT16K33BaseDisplay),
13+
"7SEGMENT": ht16k33_ns.class_("HT16K337SegmentDisplay", HT16K33BaseDisplay),
14+
}
1015

1116
CONF_SCROLL = "scroll"
1217
CONF_SCROLL_SPEED = "scroll_speed"
1318
CONF_SCROLL_DWELL = "scroll_dwell"
1419
CONF_SCROLL_DELAY = "scroll_delay"
1520
CONF_SECONDARY_DISPLAYS = "secondary_displays"
1621

22+
1723
CONFIG_SECONDARY = cv.Schema({
1824
cv.GenerateID(): cv.declare_id(i2c.I2CDevice)
1925
}).extend(i2c.i2c_device_schema(None))
2026

2127
CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({
22-
cv.GenerateID(): cv.declare_id(HT16K33AlphaDisplay),
28+
cv.GenerateID(): cv.declare_id(HT16K33BaseDisplay),
29+
cv.Optional(CONF_TYPE, default="ALPHA"): cv.enum(TYPES, upper=True),
2330
cv.Optional(CONF_SCROLL, default=False): cv.boolean,
2431
cv.Optional(CONF_SCROLL_SPEED, default='250ms'): cv.positive_time_period_milliseconds,
2532
cv.Optional(CONF_SCROLL_DWELL, default='2s'): cv.positive_time_period_milliseconds,
@@ -28,14 +35,15 @@
2835
}).extend(cv.polling_component_schema('1s')).extend(i2c.i2c_device_schema(0x70))
2936

3037
async def to_code(config):
31-
var = cg.new_Pvariable(config[CONF_ID])
38+
instance_var = TYPES[config[CONF_TYPE]].new()
39+
var = cg.Pvariable(config[CONF_ID], instance_var)
3240
await cg.register_component(var, config)
3341
await display.register_display(var, config)
3442
await i2c.register_i2c_device(var, config)
3543

3644
if CONF_LAMBDA in config:
3745
lambda_ = await cg.process_lambda(config[CONF_LAMBDA],
38-
[(HT16K33AlphaDisplay.operator('ref'), 'it')],
46+
[(HT16K33BaseDisplay.operator('ref'), 'it')],
3947
return_type=cg.void)
4048
cg.add(var.set_writer(lambda_))
4149
if config[CONF_SCROLL]:

components/ht16k33_alpha/font.h

+100-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// based on Adafruit backpack library
22

3-
static const uint16_t alphafonttable[] PROGMEM = {
3+
static const uint16_t alphafonttable[] PROGMEM = {
44
0b0000000000000000, // 0 = space
55
0b0000000000000001, // 1 = seg A
66
0b0000000000000010, // 2 = seg B
@@ -131,3 +131,102 @@ static const uint16_t alphafonttable[] PROGMEM = {
131131
0b0011111111111111,
132132
};
133133

134+
static const uint8_t sevensegfonttable[] PROGMEM = {
135+
136+
0b00000000, // (space)
137+
0b10000110, // !
138+
0b00100010, // "
139+
0b01111110, // #
140+
0b01101101, // $
141+
0b11010010, // %
142+
0b01000110, // &
143+
0b00100000, // '
144+
0b00101001, // (
145+
0b00001011, // )
146+
0b00100001, // *
147+
0b01110000, // +
148+
0b00010000, // ,
149+
0b01000000, // -
150+
0b10000000, // .
151+
0b01010010, // /
152+
0b00111111, // 0
153+
0b00000110, // 1
154+
0b01011011, // 2
155+
0b01001111, // 3
156+
0b01100110, // 4
157+
0b01101101, // 5
158+
0b01111101, // 6
159+
0b00000111, // 7
160+
0b01111111, // 8
161+
0b01101111, // 9
162+
0b00001001, // :
163+
0b00001101, // ;
164+
0b01100001, // <
165+
0b01001000, // =
166+
0b01000011, // >
167+
0b11010011, // ?
168+
0b01011111, // @
169+
0b01110111, // A
170+
0b01111100, // B
171+
0b00111001, // C
172+
0b01011110, // D
173+
0b01111001, // E
174+
0b01110001, // F
175+
0b00111101, // G
176+
0b01110110, // H
177+
0b00110000, // I
178+
0b00011110, // J
179+
0b01110101, // K
180+
0b00111000, // L
181+
0b00010101, // M
182+
0b00110111, // N
183+
0b00111111, // O
184+
0b01110011, // P
185+
0b01101011, // Q
186+
0b00110011, // R
187+
0b01101101, // S
188+
0b01111000, // T
189+
0b00111110, // U
190+
0b00111110, // V
191+
0b00101010, // W
192+
0b01110110, // X
193+
0b01101110, // Y
194+
0b01011011, // Z
195+
0b00111001, // [
196+
0b01100100, //
197+
0b00001111, // ]
198+
0b00100011, // ^
199+
0b00001000, // _
200+
0b00000010, // `
201+
0b01011111, // a
202+
0b01111100, // b
203+
0b01011000, // c
204+
0b01011110, // d
205+
0b01111011, // e
206+
0b01110001, // f
207+
0b01101111, // g
208+
0b01110100, // h
209+
0b00010000, // i
210+
0b00001100, // j
211+
0b01110101, // k
212+
0b00110000, // l
213+
0b00010100, // m
214+
0b01010100, // n
215+
0b01011100, // o
216+
0b01110011, // p
217+
0b01100111, // q
218+
0b01010000, // r
219+
0b01101101, // s
220+
0b01111000, // t
221+
0b00011100, // u
222+
0b00011100, // v
223+
0b00010100, // w
224+
0b01110110, // x
225+
0b01101110, // y
226+
0b01011011, // z
227+
0b01000110, // {
228+
0b00110000, // |
229+
0b01110000, // }
230+
0b00000001, // ~
231+
0b00000000, // del
232+
};

components/ht16k33_alpha/ht16k33_display.cpp

+44-15
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
#endif
1010

1111
namespace esphome {
12-
namespace ht16k33_alpha {
12+
namespace ht16k33 {
1313

14-
static const char *TAG = "ht16k33_alpha";
14+
static const char *TAG = "ht16k33";
1515

1616
// First set bit determines command, bits after that are the data.
1717
static const uint8_t DISPLAY_COMMAND_SET_DDRAM_ADDR = 0x00;
@@ -20,7 +20,7 @@ static const uint8_t DISPLAY_COMMAND_DISPLAY_OFF = 0x80;
2020
static const uint8_t DISPLAY_COMMAND_DISPLAY_ON = 0x81;
2121
static const uint8_t DISPLAY_COMMAND_DIMMING = 0xE0;
2222

23-
void HT16K33AlphaDisplay::setup() {
23+
void HT16K33BaseDisplay::setup() {
2424
for (auto *display : this->displays_) {
2525
display->write_bytes(DISPLAY_COMMAND_SYSTEM_SETUP, nullptr, 0);
2626
display->write_bytes(DISPLAY_COMMAND_DISPLAY_ON, nullptr, 0);
@@ -29,7 +29,7 @@ void HT16K33AlphaDisplay::setup() {
2929
memset(this->buffer_, 0, 64);
3030
}
3131

32-
void HT16K33AlphaDisplay::loop() {
32+
void HT16K33BaseDisplay::loop() {
3333
unsigned long now = millis();
3434
int numc = this->displays_.size() * 8;
3535
// check if the buffer has shrunk past the current position since last update
@@ -55,7 +55,27 @@ void HT16K33AlphaDisplay::loop() {
5555
}
5656
}
5757

58-
float HT16K33AlphaDisplay::get_setup_priority() const { return setup_priority::PROCESSOR; }
58+
float HT16K33BaseDisplay::get_setup_priority() const { return setup_priority::PROCESSOR; }
59+
60+
void HT16K337SegmentDisplay::display_() {
61+
int offset = this->offset_;
62+
constexpr uint8_t size = 10;
63+
uint8_t buffer[size];
64+
memcpy(buffer, this->buffer_ + offset, 4);
65+
// TODO: implement method to show/hide colon symbol
66+
// if (this->show_colon()) {
67+
// buffer[4] = 0x02;
68+
// } else {
69+
buffer[4] = 0;
70+
// }
71+
buffer[5] = 0;
72+
memcpy(buffer + 6, this->buffer_ + offset + 4, 4);
73+
74+
for (auto *display : this->displays_) {
75+
display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, buffer, size);
76+
offset += 8;
77+
}
78+
}
5979

6080
void HT16K33AlphaDisplay::display_() {
6181
int offset = this->offset_;
@@ -65,7 +85,7 @@ void HT16K33AlphaDisplay::display_() {
6585
}
6686
}
6787

68-
void HT16K33AlphaDisplay::update() {
88+
void HT16K33BaseDisplay::update() {
6989
memset(this->buffer_, 0, 64);
7090
int prev_fill = this->buffer_fill_;
7191
this->buffer_fill_ = 0;
@@ -77,7 +97,7 @@ void HT16K33AlphaDisplay::update() {
7797
this->display_();
7898
}
7999

80-
void HT16K33AlphaDisplay::set_brightness(float level) {
100+
void HT16K33BaseDisplay::set_brightness(float level) {
81101
int val = (int) round(level * 16);
82102
if (val < 0)
83103
val = 0;
@@ -94,11 +114,19 @@ void HT16K33AlphaDisplay::set_brightness(float level) {
94114
}
95115
}
96116

97-
float HT16K33AlphaDisplay::get_brightness() {
117+
float HT16K33BaseDisplay::get_brightness() {
98118
return this->brightness_ / 16.0;
99119
}
100120

101-
void HT16K33AlphaDisplay::print(const char *str) {
121+
uint16_t HT16K33AlphaDisplay::read_character_(uint8_t c) const {
122+
return pgm_read_word(&alphafonttable[c]);
123+
}
124+
125+
uint16_t HT16K337SegmentDisplay::read_character_(uint8_t c) const {
126+
return pgm_read_word(&sevensegfonttable[c - 32]);
127+
}
128+
129+
void HT16K33BaseDisplay::print(const char *str) {
102130
uint8_t pos = this->buffer_fill_;
103131
uint16_t fontc = 0;
104132
while (*str != '\0') {
@@ -111,21 +139,22 @@ void HT16K33AlphaDisplay::print(const char *str) {
111139
if (c > 127)
112140
fontc = 0;
113141
else
114-
fontc = pgm_read_word(&alphafonttable[c]);
142+
fontc = read_character_(c);
115143
c = *reinterpret_cast<const uint8_t *>(str);
116144
if (c == '.') {
117-
fontc |= 0x4000;
145+
fontc |= decimal_point_mask_();
118146
str++;
119147
}
120148
this->buffer_[pos++] = fontc & 0xff;
121149
this->buffer_[pos++] = fontc >> 8;
122150
}
123151
this->buffer_fill_ = pos;
152+
// ESP_LOGD(TAG, "---------- pos: %n", pos);
124153
}
125154

126-
void HT16K33AlphaDisplay::print(const std::string &str) { this->print(str.c_str()); }
155+
void HT16K33BaseDisplay::print(const std::string &str) { this->print(str.c_str()); }
127156

128-
void HT16K33AlphaDisplay::printf(const char *format, ...) {
157+
void HT16K33BaseDisplay::printf(const char *format, ...) {
129158
va_list arg;
130159
va_start(arg, format);
131160
char buffer[64];
@@ -136,14 +165,14 @@ void HT16K33AlphaDisplay::printf(const char *format, ...) {
136165
}
137166

138167
#ifdef USE_TIME
139-
void HT16K33AlphaDisplay::strftime(const char *format, ESPTime time) {
168+
void HT16K33BaseDisplay::strftime(const char *format, ESPTime time) {
140169
char buffer[64];
141170
size_t ret = time.strftime(buffer, sizeof(buffer), format);
142171
if (ret > 0)
143172
this->print(buffer);
144173
}
145174
#endif
146175

147-
} // namespace ht16k33_alpha
176+
} // namespace ht16k33
148177
} // namespace esphome
149178

components/ht16k33_alpha/ht16k33_display.h

+22-6
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
#endif
1111

1212
namespace esphome {
13-
namespace ht16k33_alpha {
13+
namespace ht16k33 {
1414

15-
class HT16K33AlphaDisplay : public PollingComponent, public i2c::I2CDevice {
15+
class HT16K33BaseDisplay : public PollingComponent, public i2c::I2CDevice {
1616
public:
17-
void set_writer(std::function<void(HT16K33AlphaDisplay &)> &&writer) { this->writer_ = std::move(writer); }
17+
void set_writer(std::function<void(HT16K33BaseDisplay &)> &&writer) { this->writer_ = std::move(writer); }
1818
void setup() override;
1919
void loop() override;
2020
float get_setup_priority() const override;
@@ -43,10 +43,12 @@ class HT16K33AlphaDisplay : public PollingComponent, public i2c::I2CDevice {
4343
protected:
4444
void command_(uint8_t value);
4545
void call_writer() { this->writer_(*this); }
46-
void display_();
46+
virtual void display_() = 0;
47+
virtual uint16_t read_character_(uint8_t c) const = 0;
48+
virtual uint16_t decimal_point_mask_() const = 0;
4749

4850
std::vector<i2c::I2CDevice *> displays_ {this};
49-
std::function<void(HT16K33AlphaDisplay &)> writer_;
51+
std::function<void(HT16K33BaseDisplay &)> writer_;
5052
bool scroll_ {false};
5153
unsigned long scroll_speed_ {250};
5254
unsigned long scroll_dwell_ {2000};
@@ -58,5 +60,19 @@ class HT16K33AlphaDisplay : public PollingComponent, public i2c::I2CDevice {
5860
uint8_t brightness_ = 16;
5961
};
6062

61-
} // namespace ht16k33_alpha
63+
class HT16K33AlphaDisplay : public HT16K33BaseDisplay {
64+
protected:
65+
void display_() override;
66+
uint16_t read_character_(uint8_t c) const override;
67+
uint16_t decimal_point_mask_() const override { return 0x4000; }
68+
};
69+
70+
class HT16K337SegmentDisplay : public HT16K33BaseDisplay {
71+
protected:
72+
void display_() override;
73+
uint16_t read_character_(uint8_t c) const override;
74+
uint16_t decimal_point_mask_() const override { return 0x80; };
75+
};
76+
77+
} // namespace ht16k33
6278
} // namespace esphome

0 commit comments

Comments
 (0)