-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Begin work on adafruit Epaper Component
- Loading branch information
Showing
6 changed files
with
571 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
#include "adafruit_epaper.h" | ||
|
||
|
||
namespace esphome { | ||
namespace adafruit_epaper { | ||
|
||
static const char * const TAG = "display.adafruit"; | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::busy_wait() { | ||
if (this->busy_pin_ != nullptr) { | ||
ESP_LOGD(TAG, "Hardware busy waiting"); | ||
while (this->busy_pin_->digital_read()) { | ||
delay(10); | ||
} | ||
} else { | ||
delay(500); | ||
} | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
float AdafruitEPaper<WIDTH, HEIGHT, COLOR>::get_setup_priority() const { | ||
return setup_priority::PROCESSOR; | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::setup() { | ||
ESP_LOGD(TAG, "Initializing EPaper display"); | ||
|
||
this->clear_buffers(); | ||
this->cs_->digital_write(true); | ||
//this->init_commands(); | ||
this->hardware_reset(); | ||
|
||
/* | ||
for (int i = 30 ; i < 61; i++ ) { | ||
for (int j = 30; j < 61; j++) | ||
draw_absolute_pixel_internal(i, j, Color(1, 0, 0)); | ||
} | ||
*/ | ||
//this->display(); | ||
//this->clear(); | ||
//this->power_down(); | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::write_framebuffer_to_display(Buffer buf_number, bool invert) { | ||
this->start_write(buf_number); | ||
this->dc_pin_->digital_write(true); | ||
|
||
uint8_t * buffer = buf_number == 0 ? black_buffer : color_buffer; | ||
|
||
for (uint32_t i = 0; i < buffer_size; ++i) { | ||
uint8_t data = buffer[i]; | ||
if (invert) { | ||
data = ~data; | ||
} | ||
this->enable(); | ||
this->write_byte(data); | ||
this->disable(); | ||
} | ||
//this->disable(); | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::display() { | ||
this->power_up(); | ||
this->setRAMAddress(0, 0); | ||
this->write_framebuffer_to_display(Buffer::BLACK, false); | ||
if (COLOR) { | ||
this->setRAMAddress(0, 0); | ||
this->write_framebuffer_to_display(Buffer::COLOR, false); | ||
} | ||
this->update_display(); | ||
this->power_down(); | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::clear_buffers() { | ||
uint8_t black_value = this->invert_black_color[Buffer::BLACK] ? 0xFF : 0x00; | ||
memset(black_buffer, black_value, buffer_size); | ||
|
||
if (COLOR) { | ||
uint8_t color_value = this->invert_black_color[Buffer::COLOR] ? 0xFF : 0x00; | ||
memset(color_buffer, color_value, buffer_size); | ||
|
||
} | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::clear() { | ||
clear_buffers(); | ||
display(); | ||
delay(100); | ||
// do it again to remove ghosts | ||
display(); | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::on_safe_shutdown() { | ||
this->clear(); | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::init_commands() { | ||
if (init_code == nullptr) { | ||
ESP_LOGE(TAG, "No init commands failed, component cant be initialized"); | ||
this->mark_failed(); | ||
return; | ||
} | ||
uint8_t buf[64]; | ||
|
||
while (init_code[0] != 0xFE) { | ||
uint8_t cmd = init_code[0]; | ||
init_code++; | ||
uint8_t num_args = init_code[0]; | ||
init_code++; | ||
if (cmd == 0xFF) { | ||
busy_wait(); | ||
delay(num_args); | ||
continue; | ||
} | ||
|
||
for (int i = 0; i < num_args; ++i) { | ||
buf[i] = init_code[0]; | ||
init_code++; | ||
} | ||
command(cmd, buf, num_args); | ||
} | ||
} | ||
|
||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::command(uint8_t cmd, bool end) { | ||
this->cs_->digital_write(true); | ||
this->dc_pin_->digital_write(false); | ||
|
||
this->enable(); | ||
this->write_byte(cmd); | ||
|
||
if (end) { | ||
this->disable(); | ||
} | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::command(uint8_t cmd, const uint8_t *buf, uint16_t length) { | ||
this->command(cmd, true); | ||
|
||
this->dc_pin_->digital_write(true); | ||
|
||
for (uint16_t i = 0; i < length; i++) { | ||
this->enable(); | ||
this->write_byte(buf[i]); | ||
this->disable(); | ||
} | ||
//this->disable(); | ||
|
||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::hardware_reset() { | ||
if (this->reset_pin_ != nullptr) { | ||
ESP_LOGD(TAG, "hardware reset"); | ||
this->reset_pin_->digital_write(true); | ||
delay(10); | ||
this->reset_pin_->digital_write(false); | ||
delay(10); | ||
this->reset_pin_->digital_write(true); | ||
} else { | ||
ESP_LOGD(TAG, "no hardware reset available"); | ||
|
||
} | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::draw_absolute_pixel_internal(int x, int y, Color color){ | ||
if ( x >= WIDTH || y >= HEIGHT) { | ||
ESP_LOGE(TAG, "got pixel data, above bounds"); | ||
return; | ||
|
||
} | ||
if ( x < 0 || y < 0 ) { | ||
ESP_LOGE(TAG, "got pixel data, below bounds"); | ||
return; | ||
} | ||
|
||
uint16_t offset = ((uint32_t)(WIDTH - 1 - x) * (uint32_t)_HEIGHT + y) / 8; | ||
|
||
uint8_t * black_buf_off = this->black_buffer + offset; | ||
uint8_t * color_buf_off = this->color_buffer + offset; | ||
|
||
bool is_black = (color.r == 0) && (color.g == 0) && (color.b == 0); | ||
if (is_black) { | ||
if (!this->invert_black_color[Buffer::BLACK]) { | ||
*black_buf_off &= ~(1 << (7 - y % 8)); | ||
} else { | ||
*black_buf_off |= (1 << (7 - y % 8)); | ||
} | ||
} | ||
|
||
static uint8_t counter = 0; | ||
|
||
if (COLOR) { | ||
//bool is_red = color.r > 0; | ||
bool is_red = color.is_on(); | ||
if (is_red) { | ||
if (!this->invert_black_color[Buffer::COLOR]) { | ||
*color_buf_off |= (1 << (7 - y % 8)); | ||
} else { | ||
*color_buf_off &= ~(1 << (7 - y % 8)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
void AdafruitEPaper<WIDTH, HEIGHT, COLOR>::update() { | ||
this->do_update_(); | ||
this->display(); | ||
} | ||
|
||
|
||
#ifdef USE_THINKINK_213_TRICOLOR_RW | ||
template void AdafruitEPaper<250, 122, true>::busy_wait(); | ||
template void AdafruitEPaper<250, 122, true>::setup(); | ||
template float AdafruitEPaper<250, 122, true>::get_setup_priority() const; | ||
template void AdafruitEPaper<250, 122, true>::write_framebuffer_to_display(Buffer buf_number, bool invert); | ||
template void AdafruitEPaper<250, 122, true>::display(); | ||
template void AdafruitEPaper<250, 122, true>::clear_buffers(); | ||
template void AdafruitEPaper<250, 122, true>::clear(); | ||
template void AdafruitEPaper<250, 122, true>::on_safe_shutdown(); | ||
template void AdafruitEPaper<250, 122, true>::init_commands(); | ||
template void AdafruitEPaper<250, 122, true>::command(uint8_t cmd, bool end); | ||
template void AdafruitEPaper<250, 122, true>::command(uint8_t cmd, const uint8_t *buf, uint16_t length); | ||
template void AdafruitEPaper<250, 122, true>::hardware_reset(); | ||
template void AdafruitEPaper<250, 122, true>::draw_absolute_pixel_internal(int x, int y, Color color); | ||
template void AdafruitEPaper<250, 122, true>::update(); | ||
#endif | ||
|
||
} // namespace adafruit_epaper | ||
} // namespace esphome |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
#pragma once | ||
|
||
#include "esphome/core/defines.h" | ||
#include "esphome/core/component.h" | ||
#include "esphome/components/spi/spi.h" | ||
#include "esphome/components/display/display_buffer.h" | ||
|
||
namespace esphome { | ||
namespace adafruit_epaper { | ||
|
||
enum Buffer { | ||
BLACK = 0, | ||
COLOR = 1 | ||
}; | ||
|
||
template <int WIDTH, int HEIGHT, bool COLOR> | ||
class AdafruitEPaper : public PollingComponent, | ||
public display::DisplayBuffer, | ||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, | ||
spi::CLOCK_POLARITY_LOW, | ||
spi::CLOCK_PHASE_LEADING, | ||
spi::DATA_RATE_4MHZ> { | ||
public: | ||
void set_dc_pin(GPIOPin *dc_pin) { this->dc_pin_ = dc_pin; } | ||
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; } | ||
void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; } | ||
|
||
float get_setup_priority() const override; | ||
|
||
void display(); | ||
void clear(); | ||
|
||
void on_safe_shutdown() override; | ||
void setup() override; | ||
|
||
void update() override; | ||
|
||
void busy_wait(); | ||
|
||
protected: | ||
//void draw_absolute_pixel_internal(int x, int y, Color color) override; | ||
void write_framebuffer_to_display(Buffer buf_number, bool invert=false); | ||
void command(uint8_t cmd, bool end=true); | ||
void command(uint8_t cmd, const uint8_t *buf, uint16_t length); | ||
void clear_buffers(); | ||
void init_commands(); | ||
void hardware_reset(); | ||
void draw_absolute_pixel_internal(int x, int y, Color color) override; | ||
|
||
int get_height_internal() override { | ||
return HEIGHT; | ||
} | ||
|
||
int get_width_internal() override { | ||
return WIDTH; | ||
} | ||
|
||
// Methods to be overridden by subclasses | ||
virtual void power_up() = 0; | ||
virtual void power_down() = 0; | ||
virtual void update_display(); | ||
virtual void start_write(Buffer buf_number) = 0; | ||
virtual void setRAMAddress(uint16_t x, uint16_t y) = 0; | ||
//virtual uint8_t * get_buffer_from_number(Buffer buf_num) = 0; | ||
|
||
// class members | ||
GPIOPin *reset_pin_ = nullptr; | ||
GPIOPin *dc_pin_ = nullptr; | ||
GPIOPin *busy_pin_ = nullptr; | ||
|
||
const static uint16_t _HEIGHT = HEIGHT + (HEIGHT % 8 != 0) * (8 - (HEIGHT % 8)); | ||
|
||
const static uint32_t buffer_size = WIDTH*_HEIGHT/8; | ||
uint8_t black_buffer[buffer_size]; | ||
const uint8_t * init_code = nullptr; | ||
bool invert_black_color[2] = {true, false}; | ||
uint8_t * _epd_init_code = nullptr; | ||
// use only a single byte if color is not needed | ||
uint8_t color_buffer[COLOR*buffer_size]; | ||
}; | ||
} // namespace adafruit_epaper | ||
} // namespace esphome |
Oops, something went wrong.