ESPHome  2024.11.0
st7920.cpp
Go to the documentation of this file.
1 #include "st7920.h"
2 #include "esphome/core/log.h"
5 
6 namespace esphome {
7 namespace st7920 {
8 
9 static const char *const TAG = "st7920";
10 
11 // ST7920 COMMANDS
12 static const uint8_t LCD_DATA = 0xFA;
13 static const uint8_t LCD_COMMAND = 0xF8;
14 static const uint8_t LCD_CLS = 0x01;
15 static const uint8_t LCD_HOME = 0x02;
16 static const uint8_t LCD_ADDRINC = 0x06;
17 static const uint8_t LCD_DISPLAYON = 0x0C;
18 static const uint8_t LCD_DISPLAYOFF = 0x08;
19 static const uint8_t LCD_CURSORON = 0x0E;
20 static const uint8_t LCD_CURSORBLINK = 0x0F;
21 static const uint8_t LCD_BASIC = 0x30;
22 static const uint8_t LCD_GFXMODE = 0x36;
23 static const uint8_t LCD_EXTEND = 0x34;
24 static const uint8_t LCD_TXTMODE = 0x34;
25 static const uint8_t LCD_STANDBY = 0x01;
26 static const uint8_t LCD_SCROLL = 0x03;
27 static const uint8_t LCD_SCROLLADDR = 0x40;
28 static const uint8_t LCD_ADDR = 0x80;
29 static const uint8_t LCD_LINE0 = 0x80;
30 static const uint8_t LCD_LINE1 = 0x90;
31 static const uint8_t LCD_LINE2 = 0x88;
32 static const uint8_t LCD_LINE3 = 0x98;
33 
34 void ST7920::setup() {
35  ESP_LOGCONFIG(TAG, "Setting up ST7920...");
36  this->dump_config();
37  this->spi_setup();
38  this->init_internal_(this->get_buffer_length_());
39  display_init_();
40 }
41 
42 void ST7920::command_(uint8_t value) {
43  this->enable();
44  this->send_(LCD_COMMAND, value);
45  this->disable();
46 }
47 
48 void ST7920::data_(uint8_t value) {
49  this->enable();
50  this->send_(LCD_DATA, value);
51  this->disable();
52 }
53 
54 void ST7920::send_(uint8_t type, uint8_t value) {
55  this->write_byte(type);
56  this->write_byte(value & 0xF0);
57  this->write_byte(value << 4);
58 }
59 
60 void ST7920::goto_xy_(uint16_t x, uint16_t y) {
61  if (y >= 32 && y < 64) {
62  y -= 32;
63  x += 8;
64  } else if (y >= 64 && y < 64 + 32) {
65  y -= 32;
66  x += 0;
67  } else if (y >= 64 + 32 && y < 64 + 64) {
68  y -= 64;
69  x += 8;
70  }
71  this->command_(LCD_ADDR | y); // 6-bit (0..63)
72  this->command_(LCD_ADDR | x); // 4-bit (0..15)
73 }
74 
76  uint8_t i, j, b;
77  for (j = 0; j < (uint8_t) (this->get_height_internal() / 2); j++) {
78  this->goto_xy_(0, j);
79  this->enable();
80  for (i = 0; i < 16; i++) { // 16 bytes from line #0+
81  b = this->buffer_[i + j * 16];
82  this->send_(LCD_DATA, b);
83  }
84  for (i = 0; i < 16; i++) { // 16 bytes from line #32+
85  b = this->buffer_[i + (j + 32) * 16];
86  this->send_(LCD_DATA, b);
87  }
88  this->disable();
89  App.feed_wdt();
90  }
91 }
92 
93 void ST7920::fill(Color color) { memset(this->buffer_, color.is_on() ? 0xFF : 0x00, this->get_buffer_length_()); }
94 
96  LOG_DISPLAY("", "ST7920", this);
97  LOG_PIN(" CS Pin: ", this->cs_);
98  ESP_LOGCONFIG(TAG, " Height: %d", this->height_);
99  ESP_LOGCONFIG(TAG, " Width: %d", this->width_);
100 }
101 
103 
105  this->clear();
106  if (this->writer_local_.has_value()) // call lambda function if available
107  (*this->writer_local_)(*this);
108  this->write_display_data();
109 }
110 
111 int ST7920::get_width_internal() { return this->width_; }
112 
113 int ST7920::get_height_internal() { return this->height_; }
114 
116  return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 8u;
117 }
118 
119 void HOT ST7920::draw_absolute_pixel_internal(int x, int y, Color color) {
120  if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) {
121  ESP_LOGW(TAG, "Position out of area: %dx%d", x, y);
122  return;
123  }
124  int width = this->get_width_internal() / 8u;
125  if (color.is_on()) {
126  this->buffer_[y * width + x / 8] |= (0x80 >> (x & 7));
127  } else {
128  this->buffer_[y * width + x / 8] &= ~(0x80 >> (x & 7));
129  }
130 }
131 
133  ESP_LOGD(TAG, "Initializing display...");
134  this->command_(LCD_BASIC); // 8bit mode
135  this->command_(LCD_BASIC); // 8bit mode
136  this->command_(LCD_CLS); // clear screen
137  delay(12); // >10 ms delay
138  this->command_(LCD_ADDRINC); // cursor increment right no shift
139  this->command_(LCD_DISPLAYON); // D=1, C=0, B=0
140  this->command_(LCD_EXTEND); // LCD_EXTEND);
141  this->command_(LCD_GFXMODE); // LCD_GFXMODE);
142  this->write_display_data();
143 }
144 
145 } // namespace st7920
146 } // namespace esphome
int get_width_internal() override
Definition: st7920.cpp:111
void draw_absolute_pixel_internal(int x, int y, Color color) override
Definition: st7920.cpp:119
optional< st7920_writer_t > writer_local_
Definition: st7920.h:47
uint16_t x
Definition: tt21100.cpp:17
void fill(Color color) override
Definition: st7920.cpp:93
int get_height_internal() override
Definition: st7920.cpp:113
GPIOPin * cs_
Definition: spi.h:378
bool has_value() const
Definition: optional.h:87
void dump_config() override
Definition: st7920.cpp:95
bool is_on() ESPHOME_ALWAYS_INLINE
Definition: color.h:46
void send_(uint8_t type, uint8_t value)
Definition: st7920.cpp:54
uint16_t y
Definition: tt21100.cpp:18
void command_(uint8_t value)
Definition: st7920.cpp:42
void init_internal_(uint32_t buffer_length)
void goto_xy_(uint16_t x, uint16_t y)
Definition: st7920.cpp:60
void clear()
Clear the entire screen by filling it with OFF pixels.
Definition: display.cpp:16
void setup() override
Definition: st7920.cpp:34
uint8_t type
const float PROCESSOR
For components that use data from sensors like displays.
Definition: component.cpp:20
Application App
Global storage of Application pointer - only one Application can exist.
float get_setup_priority() const override
Definition: st7920.cpp:102
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
size_t get_buffer_length_()
Definition: st7920.cpp:115
void update() override
Definition: st7920.cpp:104
void data_(uint8_t value)
Definition: st7920.cpp:48
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26