Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 84ad143

Browse files
committedNov 13, 2023
Split ht16k33 into separate components
1 parent b091405 commit 84ad143

16 files changed

+397
-217
lines changed
 

‎components/ht16k33_7segment/README.md

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# HT16K33 4 character 7-segment display
2+
3+
This component supports the 4 character (plus colon) 7 segment character display.
4+
5+
> :warning: If using this component as an external component, you need to include both `ht16k33_7segment` **and** `ht16k33_base` components.
6+
```yaml
7+
external_components:
8+
source: github://ssieb/custom_components/
9+
components: [ ht16k33_base, ht16k33_7segment ]
10+
```
11+
12+
There are no print functions for addressing rows and columns. With such a small display I didn't see any point.
13+
All the print functions without the row and column parameters are available.
14+
A "." will get added to the previous character as the decimal point.
15+
All the same parameters for the i2c display can be used other than the dimensions.
16+
There are also lambda functions `get_brightness` and `set_brightness` for adjusting the brightness of the display.
17+
You can extend the display across multiple units.
18+
19+
The colon in the middle of the display will be lit if the print string contains a ":" at the 3rd position (e.g. 12:34).
20+
21+
Example:
22+
```yaml
23+
i2c:
24+
sda: D0
25+
scl: D1
26+
27+
display:
28+
- platform: ht16k33_7segment
29+
address: 0x70
30+
scroll: true
31+
scroll_speed: 250ms
32+
scroll_dwell: 2s
33+
scroll_delay: 3
34+
lambda: |-
35+
auto time = id(time_sensor).now();
36+
it.strftime("%H:%M", time);
37+
```
38+
39+
# Optional parameters
40+
41+
`scroll:` defaults to false
42+
43+
`scroll_speed:` is the time between each movement, default 250ms
44+
45+
`scroll_dwell:` is the time to wait at the end before going back to the start, default 2s
46+
47+
`scroll_delay:` is the number (float, minimum 1) of `scroll_speed` cycles to wait at the beginning before starting to scroll, default 3
48+
49+
`secondary_display:` is a list of i2c devices where `address:` is required and `i2c_id:` is optional unless there is more than one i2c bus.
50+

‎components/ht16k33_7segment/__init__.py

Whitespace-only changes.
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import esphome.codegen as cg
2+
from esphome.const import CONF_ID
3+
from ..ht16k33_base.display import (
4+
base_to_code,
5+
CONF_SECONDARY_DISPLAYS,
6+
CONFIG_SCHEMA,
7+
ht16k33_ns,
8+
HT16K33BaseDisplay,
9+
)
10+
11+
AUTO_LOAD = ['ht16k33_base']
12+
13+
HT16K337SegmentDisplay = ht16k33_ns.class_("HT16K337SegmentDisplay", HT16K33BaseDisplay)
14+
15+
async def to_code(config):
16+
instance_var = HT16K337SegmentDisplay.new()
17+
var = cg.Pvariable(config[CONF_ID], instance_var)
18+
await base_to_code(var, config)
19+
20+
if CONF_SECONDARY_DISPLAYS in config:
21+
for conf in config[CONF_SECONDARY_DISPLAYS]:
22+
instance_disp = HT16K337SegmentDisplay.new()
23+
disp = cg.Pvariable(conf[CONF_ID], instance_disp)
24+
await i2c.register_i2c_device(disp, conf)
25+
cg.add(var.add_secondary_display(disp))
26+

‎components/ht16k33_7segment/font.h

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#pragma once
2+
// based on Adafruit backpack library
3+
4+
static const uint8_t sevensegfonttable[] PROGMEM = {
5+
6+
0b00000000, // (space)
7+
0b10000110, // !
8+
0b00100010, // "
9+
0b01111110, // #
10+
0b01101101, // $
11+
0b11010010, // %
12+
0b01000110, // &
13+
0b00100000, // '
14+
0b00101001, // (
15+
0b00001011, // )
16+
0b00100001, // *
17+
0b01110000, // +
18+
0b00010000, // ,
19+
0b01000000, // -
20+
0b10000000, // .
21+
0b01010010, // /
22+
0b00111111, // 0
23+
0b00000110, // 1
24+
0b01011011, // 2
25+
0b01001111, // 3
26+
0b01100110, // 4
27+
0b01101101, // 5
28+
0b01111101, // 6
29+
0b00000111, // 7
30+
0b01111111, // 8
31+
0b01101111, // 9
32+
0b00001001, // :
33+
0b00001101, // ;
34+
0b01100001, // <
35+
0b01001000, // =
36+
0b01000011, // >
37+
0b11010011, // ?
38+
0b01011111, // @
39+
0b01110111, // A
40+
0b01111100, // B
41+
0b00111001, // C
42+
0b01011110, // D
43+
0b01111001, // E
44+
0b01110001, // F
45+
0b00111101, // G
46+
0b01110110, // H
47+
0b00110000, // I
48+
0b00011110, // J
49+
0b01110101, // K
50+
0b00111000, // L
51+
0b00010101, // M
52+
0b00110111, // N
53+
0b00111111, // O
54+
0b01110011, // P
55+
0b01101011, // Q
56+
0b00110011, // R
57+
0b01101101, // S
58+
0b01111000, // T
59+
0b00111110, // U
60+
0b00111110, // V
61+
0b00101010, // W
62+
0b01110110, // X
63+
0b01101110, // Y
64+
0b01011011, // Z
65+
0b00111001, // [
66+
0b01100100, //
67+
0b00001111, // ]
68+
0b00100011, // ^
69+
0b00001000, // _
70+
0b00000010, // `
71+
0b01011111, // a
72+
0b01111100, // b
73+
0b01011000, // c
74+
0b01011110, // d
75+
0b01111011, // e
76+
0b01110001, // f
77+
0b01101111, // g
78+
0b01110100, // h
79+
0b00010000, // i
80+
0b00001100, // j
81+
0b01110101, // k
82+
0b00110000, // l
83+
0b00010100, // m
84+
0b01010100, // n
85+
0b01011100, // o
86+
0b01110011, // p
87+
0b01100111, // q
88+
0b01010000, // r
89+
0b01101101, // s
90+
0b01111000, // t
91+
0b00011100, // u
92+
0b00011100, // v
93+
0b00010100, // w
94+
0b01110110, // x
95+
0b01101110, // y
96+
0b01011011, // z
97+
0b01000110, // {
98+
0b00110000, // |
99+
0b01110000, // }
100+
0b00000001, // ~
101+
0b00000000, // del
102+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include "esphome/core/log.h"
2+
#include "esphome/core/hal.h"
3+
#include "ht16k33_7segment.h"
4+
#include "font.h"
5+
6+
#ifndef USE_ESP8266
7+
#define pgm_read_word(s) (*s)
8+
#endif
9+
10+
namespace esphome {
11+
namespace ht16k33 {
12+
13+
static const char *TAG = "ht16k33";
14+
15+
void HT16K337SegmentDisplay::display_() {
16+
constexpr uint8_t size = 10;
17+
uint8_t buffer[size];
18+
uint8_t src_idx = this->offset_;
19+
for (auto *display : this->displays_) {
20+
for (uint8_t dst_idx = 0; dst_idx < size; dst_idx++) {
21+
if (dst_idx == 4) {
22+
buffer[dst_idx++] = this->show_colon_ ? 0x02 : 0;
23+
buffer[dst_idx] = 0;
24+
} else {
25+
buffer[dst_idx] = this->buffer_[src_idx++];
26+
}
27+
}
28+
display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, buffer, size);
29+
}
30+
}
31+
32+
//void HT16K337SegmentDisplay::display_() {
33+
// int offset = this->offset_;
34+
// static const uint8_t size = this->display_size_();
35+
// uint8_t buffer[size];
36+
// memcpy(buffer, this->buffer_ + offset, 4);
37+
// offset += 4;
38+
// if (this->show_colon_) {
39+
// buffer[4] = 0x02;
40+
// } else {
41+
// buffer[4] = 0;
42+
// }
43+
// buffer[5] = 0;
44+
// memcpy(buffer + 6, this->buffer_ + offset, 4);
45+
// offset += 4;
46+
//
47+
// for (auto *display : this->displays_) {
48+
// display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, buffer, size);
49+
// offset += 8;
50+
// }
51+
//}
52+
53+
uint16_t HT16K337SegmentDisplay::read_character_(uint8_t c) const {
54+
return pgm_read_word(&sevensegfonttable[c - 32]);
55+
}
56+
57+
} // namespace ht16k33
58+
} // namespace esphome
59+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "../ht16k33_base/ht16k33_display.h"
4+
5+
namespace esphome {
6+
namespace ht16k33 {
7+
8+
class HT16K337SegmentDisplay : public HT16K33BaseDisplay {
9+
protected:
10+
void display_() override;
11+
uint16_t read_character_(uint8_t c) const override;
12+
uint16_t decimal_point_mask_() const override { return 0x80; };
13+
bool supports_colon_() const override { return true; }
14+
};
15+
16+
} // namespace ht16k33
17+
} // namespace esphome

‎components/ht16k33_alpha/README.md

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
# HT16K33 4 character display
1+
# HT16K33 4 character alphanumeric display
22

3-
This component supports both the 4 character 14 segment alphanumeric display and the 4 character (plus colon) 7 segment character display. Use the `type` parameter to select which kind of display you have.
3+
This component supports the 4 character 14 segment alphanumeric display.
4+
5+
> :warning: If using this component as an external component, you need to include both `ht16k33_alpha` **and** `ht16k33_base` components.
6+
```yaml
7+
external_components:
8+
source: github://ssieb/custom_components/
9+
components: [ ht16k33_base, ht16k33_alpha ]
10+
```
411
512
There are no print functions for addressing rows and columns. With such a small display I didn't see any point.
613
All the print functions without the row and column parameters are available.
@@ -9,8 +16,6 @@ All the same parameters for the i2c display can be used other than the dimension
916
There are also lambda functions `get_brightness` and `set_brightness` for adjusting the brightness of the display.
1017
You can extend the display across multiple units.
1118

12-
For the 7-segment displays with colon, there is also the `show_colon` lambda function, that can be used to select whether the colon between the second and third digits should be lit or not.
13-
1419
Example:
1520
```yaml
1621
i2c:
@@ -19,7 +24,6 @@ i2c:
1924
2025
display:
2126
- platform: ht16k33_alpha
22-
type: alpha
2327
address: 0x70
2428
scroll: true
2529
scroll_speed: 250ms
@@ -30,10 +34,6 @@ display:
3034
secondary_displays:
3135
- address: 0x71
3236
```
33-
# Required parameters
34-
35-
`type:` choose between `alpha` or `7segment`, depending on which kind of display you have
36-
3737
# Optional parameters
3838

3939
`scroll:` defaults to false

‎components/ht16k33_alpha/display.py

+14-47
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,26 @@
11
import esphome.codegen as cg
2-
import esphome.config_validation as cv
3-
from esphome.components import display, i2c
4-
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_TYPE
2+
from esphome.const import CONF_ID
3+
from ..ht16k33_base.display import (
4+
base_to_code,
5+
CONF_SECONDARY_DISPLAYS,
6+
CONFIG_SCHEMA,
7+
ht16k33_ns,
8+
HT16K33BaseDisplay,
9+
)
510

6-
DEPENDENCIES = ['i2c']
11+
AUTO_LOAD = ['ht16k33_base']
712

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-
}
15-
16-
CONF_SCROLL = "scroll"
17-
CONF_SCROLL_SPEED = "scroll_speed"
18-
CONF_SCROLL_DWELL = "scroll_dwell"
19-
CONF_SCROLL_DELAY = "scroll_delay"
20-
CONF_SECONDARY_DISPLAYS = "secondary_displays"
21-
22-
23-
CONFIG_SECONDARY = cv.Schema({
24-
cv.GenerateID(): cv.declare_id(i2c.I2CDevice)
25-
}).extend(i2c.i2c_device_schema(None))
26-
27-
CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({
28-
cv.GenerateID(): cv.declare_id(HT16K33BaseDisplay),
29-
cv.Optional(CONF_TYPE, default="ALPHA"): cv.enum(TYPES, upper=True),
30-
cv.Optional(CONF_SCROLL, default=False): cv.boolean,
31-
cv.Optional(CONF_SCROLL_SPEED, default='250ms'): cv.positive_time_period_milliseconds,
32-
cv.Optional(CONF_SCROLL_DWELL, default='2s'): cv.positive_time_period_milliseconds,
33-
cv.Optional(CONF_SCROLL_DELAY, default='3'): cv.float_range(min=1),
34-
cv.Optional(CONF_SECONDARY_DISPLAYS): cv.ensure_list(CONFIG_SECONDARY),
35-
}).extend(cv.polling_component_schema('1s')).extend(i2c.i2c_device_schema(0x70))
13+
HT16K33AlphaDisplay = ht16k33_ns.class_("HT16K33AlphaDisplay", HT16K33BaseDisplay)
3614

3715
async def to_code(config):
38-
instance_var = TYPES[config[CONF_TYPE]].new()
16+
instance_var = HT16K33AlphaDisplay.new()
3917
var = cg.Pvariable(config[CONF_ID], instance_var)
40-
await cg.register_component(var, config)
41-
await display.register_display(var, config)
42-
await i2c.register_i2c_device(var, config)
18+
await base_to_code(var, config)
4319

44-
if CONF_LAMBDA in config:
45-
lambda_ = await cg.process_lambda(config[CONF_LAMBDA],
46-
[(HT16K33BaseDisplay.operator('ref'), 'it')],
47-
return_type=cg.void)
48-
cg.add(var.set_writer(lambda_))
49-
if config[CONF_SCROLL]:
50-
cg.add(var.set_scroll(True))
51-
cg.add(var.set_scroll_speed(config[CONF_SCROLL_SPEED]))
52-
cg.add(var.set_scroll_dwell(config[CONF_SCROLL_DWELL]))
53-
cg.add(var.set_scroll_delay(int(config[CONF_SCROLL_DELAY] * config[CONF_SCROLL_SPEED].total_milliseconds)))
5420
if CONF_SECONDARY_DISPLAYS in config:
5521
for conf in config[CONF_SECONDARY_DISPLAYS]:
56-
disp = cg.new_Pvariable(conf[CONF_ID])
22+
instance_disp = HT16K33AlphaDisplay.new()
23+
disp = cg.Pvariable(conf[CONF_ID], instance_disp)
5724
await i2c.register_i2c_device(disp, conf)
5825
cg.add(var.add_secondary_display(disp))
5926

‎components/ht16k33_alpha/font.h

+1-99
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#pragma once
12
// based on Adafruit backpack library
23

34
static const uint16_t alphafonttable[] PROGMEM = {
@@ -131,102 +132,3 @@ static const uint16_t alphafonttable[] PROGMEM = {
131132
0b0011111111111111,
132133
};
133134

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-
};
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "esphome/core/log.h"
2+
#include "esphome/core/hal.h"
3+
#include "ht16k33_alpha.h"
4+
#include "font.h"
5+
6+
#ifndef USE_ESP8266
7+
#define pgm_read_word(s) (*s)
8+
#endif
9+
10+
namespace esphome {
11+
namespace ht16k33 {
12+
13+
static const char *TAG = "ht16k33";
14+
15+
void HT16K33AlphaDisplay::display_() {
16+
int offset = this->offset_;
17+
for (auto *display : this->displays_) {
18+
display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, this->buffer_ + offset, 8);
19+
offset += 8;
20+
}
21+
}
22+
23+
uint16_t HT16K33AlphaDisplay::read_character_(uint8_t c) const {
24+
return pgm_read_word(&alphafonttable[c]);
25+
}
26+
27+
} // namespace ht16k33
28+
} // namespace esphome
29+
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "../ht16k33_base/ht16k33_display.h"
4+
5+
namespace esphome {
6+
namespace ht16k33 {
7+
8+
class HT16K33AlphaDisplay : public HT16K33BaseDisplay {
9+
protected:
10+
void display_() override;
11+
uint16_t read_character_(uint8_t c) const override;
12+
uint16_t decimal_point_mask_() const override { return 0x4000; }
13+
bool supports_colon_() const override { return false; }
14+
};
15+
16+
} // namespace ht16k33
17+
} // namespace esphome

‎components/ht16k33_base/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# HT16K33 4 character display base component
2+
3+
This component provides the common functionality for both the 4 character 14 segment alphanumeric display and the 4 character (plus colon) 7 segment character display. It cannot be used as standalone. Use the ``ht16k33_alpha`` or ``ht16k33_7segment`` components instead.
4+

‎components/ht16k33_base/__init__.py

Whitespace-only changes.

‎components/ht16k33_base/display.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import esphome.codegen as cg
2+
import esphome.config_validation as cv
3+
from esphome.components import display, i2c
4+
from esphome.const import CONF_ID, CONF_LAMBDA
5+
6+
DEPENDENCIES = ['i2c']
7+
8+
ht16k33_ns = cg.esphome_ns.namespace('ht16k33')
9+
HT16K33BaseDisplay = ht16k33_ns.class_('HT16K33BaseDisplay', cg.PollingComponent, i2c.I2CDevice)
10+
11+
CONF_SCROLL = "scroll"
12+
CONF_SCROLL_SPEED = "scroll_speed"
13+
CONF_SCROLL_DWELL = "scroll_dwell"
14+
CONF_SCROLL_DELAY = "scroll_delay"
15+
CONF_SECONDARY_DISPLAYS = "secondary_displays"
16+
17+
18+
CONFIG_SECONDARY = cv.Schema({
19+
cv.GenerateID(): cv.declare_id(i2c.I2CDevice)
20+
}).extend(i2c.i2c_device_schema(None))
21+
22+
CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({
23+
cv.GenerateID(): cv.declare_id(HT16K33BaseDisplay),
24+
cv.Optional(CONF_SCROLL, default=False): cv.boolean,
25+
cv.Optional(CONF_SCROLL_SPEED, default='250ms'): cv.positive_time_period_milliseconds,
26+
cv.Optional(CONF_SCROLL_DWELL, default='2s'): cv.positive_time_period_milliseconds,
27+
cv.Optional(CONF_SCROLL_DELAY, default='3'): cv.float_range(min=1),
28+
cv.Optional(CONF_SECONDARY_DISPLAYS): cv.ensure_list(CONFIG_SECONDARY),
29+
}).extend(cv.polling_component_schema('1s')).extend(i2c.i2c_device_schema(0x70))
30+
31+
async def base_to_code(var, config):
32+
await cg.register_component(var, config)
33+
await display.register_display(var, config)
34+
await i2c.register_i2c_device(var, config)
35+
36+
if CONF_LAMBDA in config:
37+
lambda_ = await cg.process_lambda(config[CONF_LAMBDA],
38+
[(HT16K33BaseDisplay.operator('ref'), 'it')],
39+
return_type=cg.void)
40+
cg.add(var.set_writer(lambda_))
41+
if config[CONF_SCROLL]:
42+
cg.add(var.set_scroll(True))
43+
cg.add(var.set_scroll_speed(config[CONF_SCROLL_SPEED]))
44+
cg.add(var.set_scroll_dwell(config[CONF_SCROLL_DWELL]))
45+
cg.add(var.set_scroll_delay(int(config[CONF_SCROLL_DELAY] * config[CONF_SCROLL_SPEED].total_milliseconds)))
46+

‎components/ht16k33_alpha/ht16k33_display.cpp ‎components/ht16k33_base/ht16k33_display.cpp

+13-46
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,16 @@
22
#include "esphome/core/hal.h"
33
#include "esphome/core/helpers.h"
44
#include "ht16k33_display.h"
5-
#include "font.h"
6-
7-
#ifndef USE_ESP8266
8-
#define pgm_read_word(s) (*s)
9-
#endif
105

116
namespace esphome {
127
namespace ht16k33 {
138

149
static const char *TAG = "ht16k33";
1510

16-
// First set bit determines command, bits after that are the data.
17-
static const uint8_t DISPLAY_COMMAND_SET_DDRAM_ADDR = 0x00;
18-
static const uint8_t DISPLAY_COMMAND_SYSTEM_SETUP = 0x21;
19-
static const uint8_t DISPLAY_COMMAND_DISPLAY_OFF = 0x80;
20-
static const uint8_t DISPLAY_COMMAND_DISPLAY_ON = 0x81;
21-
static const uint8_t DISPLAY_COMMAND_DIMMING = 0xE0;
11+
void HT16K33BaseDisplay::dump_config() {
12+
ESP_LOGCONFIG(TAG, "HT16K33 Display:");
13+
LOG_I2C_DEVICE(this);
14+
}
2215

2316
void HT16K33BaseDisplay::setup() {
2417
for (auto *display : this->displays_) {
@@ -57,33 +50,6 @@ void HT16K33BaseDisplay::loop() {
5750

5851
float HT16K33BaseDisplay::get_setup_priority() const { return setup_priority::PROCESSOR; }
5952

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-
if (this->show_colon_) {
66-
buffer[4] = 0x02;
67-
} else {
68-
buffer[4] = 0;
69-
}
70-
buffer[5] = 0;
71-
memcpy(buffer + 6, this->buffer_ + offset + 4, 4);
72-
73-
for (auto *display : this->displays_) {
74-
display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, buffer, size);
75-
offset += 8;
76-
}
77-
}
78-
79-
void HT16K33AlphaDisplay::display_() {
80-
int offset = this->offset_;
81-
for (auto *display : this->displays_) {
82-
display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, this->buffer_ + offset, 8);
83-
offset += 8;
84-
}
85-
}
86-
8753
void HT16K33BaseDisplay::update() {
8854
memset(this->buffer_, 0, 64);
8955
int prev_fill = this->buffer_fill_;
@@ -119,7 +85,9 @@ float HT16K33BaseDisplay::get_brightness() {
11985

12086
void HT16K33BaseDisplay::print(const char *str) {
12187
uint8_t pos = this->buffer_fill_;
88+
uint8_t idx = 1;
12289
uint16_t fontc = 0;
90+
this->show_colon_ = false;
12391
while (*str != '\0') {
12492
if (pos >= 64) {
12593
ESP_LOGW(TAG, "output buffer full!");
@@ -135,9 +103,16 @@ void HT16K33BaseDisplay::print(const char *str) {
135103
if (c == '.') {
136104
fontc |= decimal_point_mask_();
137105
str++;
106+
idx++;
107+
}
108+
if (c == ':' && idx == 2 && this->supports_colon_()) {
109+
this->show_colon_ = true;
110+
str++;
111+
idx++;
138112
}
139113
this->buffer_[pos++] = fontc & 0xff;
140114
this->buffer_[pos++] = fontc >> 8;
115+
idx++;
141116
}
142117
this->buffer_fill_ = pos;
143118
}
@@ -163,14 +138,6 @@ void HT16K33BaseDisplay::strftime(const char *format, ESPTime time) {
163138
}
164139
#endif
165140

166-
uint16_t HT16K33AlphaDisplay::read_character_(uint8_t c) const {
167-
return pgm_read_word(&alphafonttable[c]);
168-
}
169-
170-
uint16_t HT16K337SegmentDisplay::read_character_(uint8_t c) const {
171-
return pgm_read_word(&sevensegfonttable[c - 32]);
172-
}
173-
174141
} // namespace ht16k33
175142
} // namespace esphome
176143

‎components/ht16k33_alpha/ht16k33_display.h ‎components/ht16k33_base/ht16k33_display.h

+10-16
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,17 @@
1212
namespace esphome {
1313
namespace ht16k33 {
1414

15+
// First set bit determines command, bits after that are the data.
16+
constexpr uint8_t DISPLAY_COMMAND_SET_DDRAM_ADDR = 0x00;
17+
constexpr uint8_t DISPLAY_COMMAND_SYSTEM_SETUP = 0x21;
18+
constexpr uint8_t DISPLAY_COMMAND_DISPLAY_OFF = 0x80;
19+
constexpr uint8_t DISPLAY_COMMAND_DISPLAY_ON = 0x81;
20+
constexpr uint8_t DISPLAY_COMMAND_DIMMING = 0xE0;
21+
1522
class HT16K33BaseDisplay : public PollingComponent, public i2c::I2CDevice {
1623
public:
1724
void set_writer(std::function<void(HT16K33BaseDisplay &)> &&writer) { this->writer_ = std::move(writer); }
25+
void dump_config() override;
1826
void setup() override;
1927
void loop() override;
2028
float get_setup_priority() const override;
@@ -40,14 +48,14 @@ class HT16K33BaseDisplay : public PollingComponent, public i2c::I2CDevice {
4048
void strftime(const char *format, ESPTime time) __attribute__((format(strftime, 2, 0)));
4149
#endif
4250

43-
void show_colon(bool show) { this->show_colon_ = show; }
44-
4551
protected:
4652
void command_(uint8_t value);
4753
void call_writer() { this->writer_(*this); }
54+
4855
virtual void display_() = 0;
4956
virtual uint16_t read_character_(uint8_t c) const = 0;
5057
virtual uint16_t decimal_point_mask_() const = 0;
58+
virtual bool supports_colon_() const =0;
5159

5260
std::vector<i2c::I2CDevice *> displays_ {this};
5361
std::function<void(HT16K33BaseDisplay &)> writer_;
@@ -63,19 +71,5 @@ class HT16K33BaseDisplay : public PollingComponent, public i2c::I2CDevice {
6371
bool show_colon_ {false};
6472
};
6573

66-
class HT16K33AlphaDisplay : public HT16K33BaseDisplay {
67-
protected:
68-
void display_() override;
69-
uint16_t read_character_(uint8_t c) const override;
70-
uint16_t decimal_point_mask_() const override { return 0x4000; }
71-
};
72-
73-
class HT16K337SegmentDisplay : public HT16K33BaseDisplay {
74-
protected:
75-
void display_() override;
76-
uint16_t read_character_(uint8_t c) const override;
77-
uint16_t decimal_point_mask_() const override { return 0x80; };
78-
};
79-
8074
} // namespace ht16k33
8175
} // namespace esphome

0 commit comments

Comments
 (0)
Please sign in to comment.