| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695 |
- // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "driver/gpio.h"
- #include "driver/spi_master.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/semphr.h"
- #include "freertos/xtensa_api.h"
- #include "freertos/task.h"
- #include "freertos/queue.h"
- #include "freertos/ringbuf.h"
- #include "esp_log.h"
- #include "epaper-29-ws.h"
- static const char* TAG = "ePaper Driver";
- #define EPAPER_QUE_SIZE_DEFAULT 10
- const unsigned char lut_full_update[] =
- {
- 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22,
- 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88,
- 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51,
- 0x35, 0x51, 0x51, 0x19, 0x01, 0x00
- };
- // This LUT is not yet used in the code below
- const unsigned char lut_partial_update[] =
- {
- 0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static portMUX_TYPE epaper_spinlock = portMUX_INITIALIZER_UNLOCKED;
- #define EPAPER_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
- #define EPAPER_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux)
- // LCD data/command
- typedef struct {
- uint8_t dc_io;
- uint8_t dc_level;
- } epaper_dc_t;
- typedef struct {
- spi_device_handle_t bus;
- epaper_conf_t pin; /* EPD properties */
- epaper_paint_t paint; /* Paint properties */
- epaper_dc_t dc;
- xSemaphoreHandle spi_mux;
- } epaper_dev_t;
- /* This function is called (in irq context!) just before a transmission starts.
- * It will set the D/C line to the value indicated in the user field
- */
- static void iot_epaper_pre_transfer_callback(spi_transaction_t *t)
- {
- epaper_dc_t *dc = (epaper_dc_t *) t->user;
- gpio_set_level((int)dc->dc_io, (int)dc->dc_level);
- }
- static esp_err_t _iot_epaper_spi_send(spi_device_handle_t spi, spi_transaction_t* t)
- {
- return spi_device_transmit(spi, t);
- }
- void iot_epaper_send(spi_device_handle_t spi, const uint8_t *data, int len, epaper_dc_t *dc)
- {
- esp_err_t ret;
- if (len == 0) {
- return; // no need to send anything
- }
- spi_transaction_t t = {
- .length = len * 8, // Len is in bytes, transaction length is in bits.
- .tx_buffer = data,
- .user = (void *) dc,
- };
- ret = _iot_epaper_spi_send(spi, &t);
- assert(ret == ESP_OK);
- }
- static void iot_epaper_send_command(epaper_handle_t dev, unsigned char command)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- device->dc.dc_io = device->pin.dc_pin;
- device->dc.dc_level = device->pin.dc_lev_cmd;
- iot_epaper_send(device->bus, &command, 1, &device->dc);
- }
- static void iot_epaper_send_byte(epaper_handle_t dev, const uint8_t data)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- device->dc.dc_io = device->pin.dc_pin;
- device->dc.dc_level = device->pin.dc_lev_data;
- iot_epaper_send(device->bus, &data, 1, &device->dc);
- }
- static void iot_epaper_send_data(epaper_handle_t dev, const uint8_t *data, int length)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- device->dc.dc_io = device->pin.dc_pin;
- device->dc.dc_level = device->pin.dc_lev_data;
- // To Do: original driver was sending byte by byte
- // Pay attention to possible performance issues
- iot_epaper_send(device->bus, data, length, &device->dc);
- ESP_LOGI(TAG, "SPI data sent %d", length);
- }
- static void iot_epaper_paint_init(epaper_handle_t dev, unsigned char* image, int width, int height)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- device->paint.rotate = E_PAPER_ROTATE_0;
- device->paint.image = image;
- /* 1 byte = 8 pixels, so the width should be the multiple of 8 */
- device->paint.width = width % 8 ? width + 8 - (width % 8) : width;
- device->paint.height = height;
- }
- static void iot_epaper_gpio_init(epaper_conf_t * pin)
- {
- gpio_pad_select_gpio(pin->reset_pin);
- gpio_set_direction(pin->reset_pin, GPIO_MODE_OUTPUT);
- gpio_set_level(pin->reset_pin, pin->rst_active_level);
- gpio_pad_select_gpio(pin->dc_pin);
- gpio_set_direction(pin->dc_pin, GPIO_MODE_OUTPUT);
- gpio_set_level(pin->dc_pin, 1);
- ets_delay_us(10000);
- gpio_set_level(pin->dc_pin, 0);
- gpio_pad_select_gpio(pin->busy_pin);
- gpio_set_direction(pin->busy_pin, GPIO_MODE_INPUT);
- gpio_set_pull_mode(pin->busy_pin, GPIO_PULLUP_ONLY);
- }
- static esp_err_t iot_epaper_spi_init(epaper_handle_t dev, spi_device_handle_t *e_spi, epaper_conf_t *pin)
- {
- esp_err_t ret;
- spi_bus_config_t buscfg = {
- .miso_io_num = -1, // MISO not used, we are transferring to the slave only
- .mosi_io_num = pin->mosi_pin,
- .sclk_io_num = pin->sck_pin,
- .quadwp_io_num = -1,
- .quadhd_io_num = -1,
- // The maximum size sent below covers the case
- // when the whole frame buffer is transferred to the slave
- .max_transfer_sz = EPD_WIDTH * EPD_HEIGHT / 8,
- };
- spi_device_interface_config_t devcfg = {
- .clock_speed_hz = pin->clk_freq_hz,
- .mode = 0, // SPI mode 0
- .spics_io_num = pin->cs_pin,
- // To Do: clarify what does it mean
- .queue_size = EPAPER_QUE_SIZE_DEFAULT,
- // We are sending only in one direction (to the ePaper slave)
- .flags = (SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE),
- //Specify pre-transfer callback to handle D/C line
- .pre_cb = iot_epaper_pre_transfer_callback,
- };
- ret = spi_bus_initialize(pin->spi_host, &buscfg, 1);
- assert(ret == ESP_OK);
- ret = spi_bus_add_device(pin->spi_host, &devcfg, e_spi);
- assert(ret == ESP_OK);
- return ret;
- }
- static void iot_epaper_set_lut(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- iot_epaper_send_command(dev, E_PAPER_WRITE_LUT_REGISTER);
- iot_epaper_send_data(dev, lut_full_update, sizeof(lut_full_update));
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- static void iot_epaper_epd_init(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- iot_epaper_reset(dev);
- /* This part of code is ePaper module specific
- * It has been copied from the instructions as it is
- */
- iot_epaper_send_command(dev, E_PAPER_DRIVER_OUTPUT_CONTROL);
- iot_epaper_send_byte(dev, (EPD_HEIGHT - 1) & 0xff);
- iot_epaper_send_byte(dev, ((EPD_HEIGHT - 1) >> 8) & 0xff);
- iot_epaper_send_byte(dev, 0x00); // GD = 0; SM = 0; TB = 0
- iot_epaper_send_command(dev, E_PAPER_BOOSTER_SOFT_START_CONTROL);
- iot_epaper_send_byte(dev, 0xD7);
- iot_epaper_send_byte(dev, 0xD6);
- iot_epaper_send_byte(dev, 0x9D);
- iot_epaper_send_command(dev, E_PAPER_WRITE_VCOM_REGISTER);
- iot_epaper_send_byte(dev, 0xA8); // VCOM 7C
- iot_epaper_send_command(dev, E_PAPER_SET_DUMMY_LINE_PERIOD);
- iot_epaper_send_byte(dev, 0x1A); // 4 dummy lines per gate
- iot_epaper_send_command(dev, E_PAPER_SET_GATE_TIME);
- iot_epaper_send_byte(dev, 0x08); // 2us per line
- iot_epaper_send_command(dev, E_PAPER_DATA_ENTRY_MODE_SETTING);
- iot_epaper_send_byte(dev, 0x03); // X increment; Y increment
- iot_epaper_set_lut(dev);
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- epaper_handle_t iot_epaper_create(spi_device_handle_t bus, epaper_conf_t *epconf)
- {
- epaper_dev_t* dev = (epaper_dev_t*) calloc(1, sizeof(epaper_dev_t));
- dev->spi_mux = xSemaphoreCreateRecursiveMutex();
- uint8_t* frame_buf = (unsigned char*) heap_caps_malloc(
- (epconf->width * epconf->height / 8), MALLOC_CAP_8BIT);
- if (frame_buf == NULL) {
- ESP_LOGE(TAG, "frame_buffer malloc fail");
- return NULL;
- }
- iot_epaper_gpio_init(epconf);
- ESP_LOGD(TAG, "gpio init ok");
- if (bus) {
- dev->bus = bus;
- } else {
- iot_epaper_spi_init(dev, &dev->bus, epconf);
- ESP_LOGD(TAG, "spi init ok");
- }
- dev->pin = *epconf;
- iot_epaper_epd_init(dev);
- iot_epaper_paint_init(dev, frame_buf, epconf->width, epconf->height);
- return (epaper_handle_t) dev;
- }
- esp_err_t iot_epaper_delete(epaper_handle_t dev, bool del_bus)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- iot_epaper_sleep(dev);
- spi_bus_remove_device(device->bus);
- if (del_bus) {
- spi_bus_free(device->pin.spi_host);
- }
- vSemaphoreDelete(device->spi_mux);
- if (device->paint.image) {
- free(device->paint.image);
- device->paint.image = NULL;
- }
- free(device);
- return ESP_OK;
- }
- int iot_epaper_get_width(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- return device->paint.width;
- }
- void iot_epaper_set_width(epaper_handle_t dev, int width)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- device->paint.width = width % 8 ? width + 8 - (width % 8) : width;
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- int iot_epaper_get_height(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- return device->paint.height;
- }
- void iot_epaper_set_height(epaper_handle_t dev, int height)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- device->paint.height = height;
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- int iot_epaper_get_rotate(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- return device->paint.rotate;
- }
- void iot_epaper_set_rotate(epaper_handle_t dev, int rotate)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- device->paint.rotate = rotate;
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: Getters and Setters
- */
- unsigned char* iot_epaper_get_image(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- return device->paint.image;
- }
- /**
- * @brief: this draws a pixel by absolute coordinates.
- * this function won't be affected by the rotate parameter.
- */
- static void iot_epaper_draw_absolute_pixel(epaper_handle_t dev, int x, int y, int colored)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- if (x < 0 || x >= device->paint.width || y < 0 || y >= device->paint.height) {
- return;
- }
- EPAPER_ENTER_CRITICAL(&epaper_spinlock);
- if (device->pin.color_inv) {
- if (colored) {
- device->paint.image[(x + y * device->paint.width) / 8] |= 0x80 >> (x % 8);
- } else {
- device->paint.image[(x + y * device->paint.width) / 8] &= ~(0x80 >> (x % 8));
- }
- } else {
- if (colored) {
- device->paint.image[(x + y * device->paint.width) / 8] &= ~(0x80 >> (x % 8));
- } else {
- device->paint.image[(x + y * device->paint.width) / 8] |= 0x80 >> (x % 8);
- }
- }
- EPAPER_EXIT_CRITICAL(&epaper_spinlock);
- }
- void iot_epaper_clean_paint(epaper_handle_t dev, int colored)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- for (int x = 0; x < device->paint.width; x++) {
- for (int y = 0; y < device->paint.height; y++) {
- iot_epaper_draw_absolute_pixel(dev, x, y, colored);
- }
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this displays a string on the frame buffer but not refresh
- */
- void iot_epaper_draw_string(epaper_handle_t dev, int x, int y, const char* text, epaper_font_t* font, int colored)
- {
- const char* p_text = text;
- unsigned int counter = 0;
- int refcolumn = x;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- /* Send the string character by character on EPD */
- while (*p_text != 0) {
- /* Display one character on EPD */
- iot_epaper_draw_char(dev, refcolumn, y, *p_text, font, colored);
- /* Decrement the column position by 16 */
- refcolumn += font->width;
- /* Point on the next character */
- p_text++;
- counter++;
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a pixel by the coordinates
- */
- void iot_epaper_draw_pixel(epaper_handle_t dev, int x, int y, int colored)
- {
- int point_temp;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- if (device->paint.rotate == E_PAPER_ROTATE_0) {
- if (x < 0 || x >= device->paint.width || y < 0 || y >= device->paint.height) {
- return;
- }
- iot_epaper_draw_absolute_pixel(dev, x, y, colored);
- } else if (device->paint.rotate == E_PAPER_ROTATE_90) {
- if (x < 0 || x >= device->paint.height || y < 0 || y >= device->paint.width) {
- return;
- }
- point_temp = x;
- x = device->paint.width - y;
- y = point_temp;
- iot_epaper_draw_absolute_pixel(dev, x, y, colored);
- } else if (device->paint.rotate == E_PAPER_ROTATE_180) {
- if (x < 0 || x >= device->paint.width || y < 0 || y >= device->paint.height) {
- return;
- }
- x = device->paint.width - x;
- y = device->paint.height - y;
- iot_epaper_draw_absolute_pixel(dev, x, y, colored);
- } else if (device->paint.rotate == E_PAPER_ROTATE_270) {
- if (x < 0 || x >= device->paint.height || y < 0 || y >= device->paint.width) {
- return;
- }
- point_temp = x;
- x = y;
- y = device->paint.height - point_temp;
- iot_epaper_draw_absolute_pixel(dev, x, y, colored);
- }
- }
- /**
- * @brief: this draws a character on the frame buffer but not refresh
- */
- void iot_epaper_draw_char(epaper_handle_t dev, int x, int y, char ascii_char, epaper_font_t* font, int colored)
- {
- int i, j;
- unsigned int char_offset = (ascii_char - ' ') * font->height * (font->width / 8 + (font->width % 8 ? 1 : 0));
- const unsigned char* ptr = &font->font_table[char_offset];
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- for (j = 0; j < font->height; j++) {
- for (i = 0; i < font->width; i++) {
- if (*ptr & (0x80 >> (i % 8))) {
- iot_epaper_draw_pixel(dev, x + i, y + j, colored);
- }
- if (i % 8 == 7) {
- ptr++;
- }
- }
- if (font->width % 8 != 0) {
- ptr++;
- }
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a line on the frame buffer
- */
- void iot_epaper_draw_line(epaper_handle_t dev, int x0, int y0, int x1, int y1,
- int colored)
- {
- /* Bresenham algorithm */
- int dx = x1 - x0 >= 0 ? x1 - x0 : x0 - x1;
- int sx = x0 < x1 ? 1 : -1;
- int dy = y1 - y0 <= 0 ? y1 - y0 : y0 - y1;
- int sy = y0 < y1 ? 1 : -1;
- int err = dx + dy;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- while ((x0 != x1) && (y0 != y1)) {
- iot_epaper_draw_pixel(dev, x0, y0, colored);
- if (2 * err >= dy) {
- err += dy;
- x0 += sx;
- }
- if (2 * err <= dx) {
- err += dx;
- y0 += sy;
- }
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a horizontal line on the frame buffer
- */
- void iot_epaper_draw_horizontal_line(epaper_handle_t dev, int x, int y, int width, int colored)
- {
- int i;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- for (i = x; i < x + width; i++) {
- iot_epaper_draw_pixel(dev, i, y, colored);
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a vertical line on the frame buffer
- */
- void iot_epaper_draw_vertical_line(epaper_handle_t dev, int x, int y, int height, int colored)
- {
- int i;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- for (i = y; i < y + height; i++) {
- iot_epaper_draw_pixel(dev, x, i, colored);
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a rectangle
- */
- void iot_epaper_draw_rectangle(epaper_handle_t dev, int x0, int y0, int x1, int y1, int colored)
- {
- int min_x, min_y, max_x, max_y;
- min_x = x1 > x0 ? x0 : x1;
- max_x = x1 > x0 ? x1 : x0;
- min_y = y1 > y0 ? y0 : y1;
- max_y = y1 > y0 ? y1 : y0;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- iot_epaper_draw_horizontal_line(dev, min_x, min_y, max_x - min_x + 1, colored);
- iot_epaper_draw_horizontal_line(dev, min_x, max_y, max_x - min_x + 1, colored);
- iot_epaper_draw_vertical_line(dev, min_x, min_y, max_y - min_y + 1, colored);
- iot_epaper_draw_vertical_line(dev, max_x, min_y, max_y - min_y + 1, colored);
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a filled rectangle
- */
- void ior_epaper_draw_filled_rectangle(epaper_handle_t dev, int x0, int y0, int x1, int y1, int colored)
- {
- int min_x, min_y, max_x, max_y;
- int i;
- min_x = x1 > x0 ? x0 : x1;
- max_x = x1 > x0 ? x1 : x0;
- min_y = y1 > y0 ? y0 : y1;
- max_y = y1 > y0 ? y1 : y0;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- for (i = min_x; i <= max_x; i++) {
- iot_epaper_draw_vertical_line(dev, i, min_y, max_y - min_y + 1, colored);
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a circle
- */
- void iot_epaper_draw_circle(epaper_handle_t dev, int x, int y, int radius,
- int colored)
- {
- /* Bresenham algorithm */
- int x_pos = -radius;
- int y_pos = 0;
- int err = 2 - 2 * radius;
- int e2;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- do {
- iot_epaper_draw_pixel(dev, x - x_pos, y + y_pos, colored);
- iot_epaper_draw_pixel(dev, x + x_pos, y + y_pos, colored);
- iot_epaper_draw_pixel(dev, x + x_pos, y - y_pos, colored);
- iot_epaper_draw_pixel(dev, x - x_pos, y - y_pos, colored);
- e2 = err;
- if (e2 <= y_pos) {
- err += ++y_pos * 2 + 1;
- if (-x_pos == y_pos && e2 <= x_pos) {
- e2 = 0;
- }
- }
- if (e2 > x_pos) {
- err += ++x_pos * 2 + 1;
- }
- } while (x_pos <= 0);
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /**
- * @brief: this draws a filled circle
- */
- void iot_epaper_draw_filled_circle(epaper_handle_t dev, int x, int y, int radius, int colored)
- {
- /* Bresenham algorithm */
- int x_pos = -radius;
- int y_pos = 0;
- int err = 2 - 2 * radius;
- int e2;
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- do {
- iot_epaper_draw_pixel(dev, x - x_pos, y + y_pos, colored);
- iot_epaper_draw_pixel(dev, x + x_pos, y + y_pos, colored);
- iot_epaper_draw_pixel(dev, x + x_pos, y - y_pos, colored);
- iot_epaper_draw_pixel(dev, x - x_pos, y - y_pos, colored);
- iot_epaper_draw_horizontal_line(dev, x + x_pos, y + y_pos, 2 * (-x_pos) + 1, colored);
- iot_epaper_draw_horizontal_line(dev, x + x_pos, y - y_pos, 2 * (-x_pos) + 1, colored);
- e2 = err;
- if (e2 <= y_pos) {
- err += ++y_pos * 2 + 1;
- if (-x_pos == y_pos && e2 <= x_pos) {
- e2 = 0;
- }
- }
- if (e2 > x_pos) {
- err += ++x_pos * 2 + 1;
- }
- } while (x_pos <= 0);
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- void iot_epaper_wait_idle(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- while (gpio_get_level((gpio_num_t) device->pin.busy_pin) == device->pin.busy_active_level) {
- vTaskDelay(10 / portTICK_RATE_MS);
- }
- }
- void iot_epaper_reset(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- gpio_set_level((gpio_num_t) device->pin.reset_pin, (~(device->pin.rst_active_level)) & 0x1);
- ets_delay_us(200);
- gpio_set_level((gpio_num_t) device->pin.reset_pin, (device->pin.rst_active_level) & 0x1); //module reset
- ets_delay_us(200);
- gpio_set_level((gpio_num_t) device->pin.reset_pin, (~(device->pin.rst_active_level)) & 0x1);
- iot_epaper_wait_idle(dev);
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- /* This function has been exposed to implement partial updates of the image
- * To Do: implement partial updates of the image
- */
- void iot_set_ram_area(epaper_handle_t dev, int x_start, int y_start, int x_end, int y_end)
- {
- iot_epaper_send_command(dev, E_PAPER_SET_RAM_X_ADDRESS_START_END_POSITION);
- iot_epaper_send_byte(dev, x_start >> 3); // 8 pixels per byte
- iot_epaper_send_byte(dev, x_end >> 3); // 8 pixels per byte
- iot_epaper_send_command(dev, E_PAPER_SET_RAM_Y_ADDRESS_START_END_POSITION);
- iot_epaper_send_byte(dev, y_start & 0xff);
- iot_epaper_send_byte(dev, y_start >> 8);
- iot_epaper_send_byte(dev, y_end & 0xff);
- iot_epaper_send_byte(dev, y_end >> 8);
- }
- /* This function has been exposed to implement partial updates of the image
- * To Do: implement partial updates of the image
- */
- void iot_set_ram_address_counter(epaper_handle_t dev, int x, int y)
- {
- iot_epaper_send_command(dev, E_PAPER_SET_RAM_X_ADDRESS_COUNTER);
- iot_epaper_send_byte(dev, x >> 3); // 8 pixels per byte
- iot_epaper_send_command(dev, E_PAPER_SET_RAM_Y_ADDRESS_COUNTER);
- iot_epaper_send_byte(dev, y & 0xff);
- iot_epaper_send_byte(dev, y >> 8);
- }
- /* This transfer to the display the whole image frame
- * To Do: implement partial updates of the image
- */
- void iot_epaper_display_frame(epaper_handle_t dev, const unsigned char* frame_buffer)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- if (frame_buffer == NULL) {
- frame_buffer = device->paint.image;
- }
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- if (frame_buffer != NULL) {
- // configure ePaper's memory to send data
- iot_set_ram_area(dev, 0, 0, EPD_WIDTH-1, EPD_HEIGHT-1);
- iot_set_ram_address_counter(dev, 0, 0);
- // send image data
- iot_epaper_send_command(dev, E_PAPER_WRITE_RAM);
- iot_epaper_send_data(dev, frame_buffer, device->paint.width / 8 * device->paint.height);
- // update display
- iot_epaper_send_command(dev, E_PAPER_DISPLAY_UPDATE_CONTROL_2);
- iot_epaper_send_byte(dev, 0xC4);
- iot_epaper_send_command(dev, E_PAPER_MASTER_ACTIVATION);
- iot_epaper_send_command(dev, E_PAPER_TERMINATE_FRAME_READ_WRITE);
- iot_epaper_wait_idle(dev);
- }
- xSemaphoreGiveRecursive(device->spi_mux);
- }
- void iot_epaper_sleep(epaper_handle_t dev)
- {
- epaper_dev_t* device = (epaper_dev_t*) dev;
- xSemaphoreTakeRecursive(device->spi_mux, portMAX_DELAY);
- iot_epaper_send_command(dev, E_PAPER_DEEP_SLEEP_MODE);
- iot_epaper_wait_idle(dev);
- xSemaphoreGiveRecursive(device->spi_mux);
- }
|