Skip to content

Commit 06c3aa0

Browse files
committed
Split ht16k33 into separate components
1 parent b091405 commit 06c3aa0

16 files changed

+398
-216
lines changed

components/ht16k33_7segment/README.md

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

components/ht16k33_7segment/font.h

Lines changed: 102 additions & 0 deletions
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+
};
Lines changed: 59 additions & 0 deletions
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+
Lines changed: 17 additions & 0 deletions
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

Lines changed: 9 additions & 9 deletions
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

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,27 @@
11
import esphome.codegen as cg
22
import esphome.config_validation as cv
3-
from esphome.components import display, i2c
4-
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_TYPE
3+
from esphome.const import CONF_ID
4+
from ..ht16k33_base.display import (
5+
base_to_code,
6+
CONF_SECONDARY_DISPLAYS,
7+
CONFIG_SCHEMA,
8+
ht16k33_ns,
9+
HT16K33BaseDisplay,
10+
)
511

6-
DEPENDENCIES = ['i2c']
12+
AUTO_LOAD = ['ht16k33_base']
713

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))
14+
HT16K33AlphaDisplay = ht16k33_ns.class_("HT16K33AlphaDisplay", HT16K33BaseDisplay)
3615

3716
async def to_code(config):
38-
instance_var = TYPES[config[CONF_TYPE]].new()
17+
instance_var = HT16K33AlphaDisplay.new()
3918
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)
19+
await base_to_code(var, config)
4320

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)))
5421
if CONF_SECONDARY_DISPLAYS in config:
5522
for conf in config[CONF_SECONDARY_DISPLAYS]:
56-
disp = cg.new_Pvariable(conf[CONF_ID])
23+
instance_disp = HT16K33AlphaDisplay.new()
24+
disp = cg.Pvariable(conf[CONF_ID], instance_disp)
5725
await i2c.register_i2c_device(disp, conf)
5826
cg.add(var.add_secondary_display(disp))
5927

0 commit comments

Comments
 (0)