E_paper, E_ink, Screen size 1.54", resolution 200x200, 4 wire spi, Waveshare, Black and White, Kl25Z, 8 wire print connector, supply 3.3 Volt, IL0373 Controller, font size is 8, 12, 16 and 24.

Dependencies:   mbed

Revision:
0:665e04c85d8d
Child:
1:d27a7e06c233
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/epd1in54.cpp	Sun Mar 25 12:14:55 2018 +0000
@@ -0,0 +1,280 @@
+/**
+ *  @filename   :   epd1in54.cpp
+ *  @brief      :   Implements for e-paper library
+ *  @author     :   Yehui from Waveshare
+ *
+ *  Copyright (C) Waveshare     September 5 2017
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documnetation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to  whom the Software is
+ * furished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include "epd1in54.h"
+
+Epd::~Epd() {
+};
+
+Epd::Epd() {
+    reset_pin = RST_PIN;
+    dc_pin = DC_PIN;
+    cs_pin = CS_PIN;
+    busy_pin = BUSY_PIN;
+    width = EPD_WIDTH;
+    height = EPD_HEIGHT;
+};
+
+int Epd::Init(const unsigned char* lut) {
+    /* this calls the peripheral hardware interface, see epdif */
+    if (IfInit() != 0) {
+        return -1;
+    }
+    /* EPD hardware init start */
+    this->lut = lut;
+    Reset();
+    SendCommand(DRIVER_OUTPUT_CONTROL);
+    SendData((EPD_HEIGHT - 1) & 0xFF);
+    SendData(((EPD_HEIGHT - 1) >> 8) & 0xFF);
+    SendData(0x00);                     // GD = 0; SM = 0; TB = 0;
+    SendCommand(BOOSTER_SOFT_START_CONTROL);
+    SendData(0xD7);
+    SendData(0xD6);
+    SendData(0x9D);
+    SendCommand(WRITE_VCOM_REGISTER);
+    SendData(0xA8);                     // VCOM 7C
+    SendCommand(SET_DUMMY_LINE_PERIOD);
+    SendData(0x1A);                     // 4 dummy lines per gate
+    SendCommand(SET_GATE_TIME);
+    SendData(0x08);                     // 2us per line
+    SendCommand(DATA_ENTRY_MODE_SETTING);
+    SendData(0x03);                     // X increment; Y increment
+    SetLut(this->lut);
+    /* EPD hardware init end */
+    return 0;
+}
+
+/**
+ *  @brief: basic function for sending commands
+ */
+void Epd::SendCommand(unsigned char command) {
+    DigitalWrite(dc_pin, LOW);
+    SpiTransfer(command);
+}
+
+/**
+ *  @brief: basic function for sending data
+ */
+void Epd::SendData(unsigned char data) {
+    DigitalWrite(dc_pin, HIGH);
+    SpiTransfer(data);
+}
+
+/**
+ *  @brief: Wait until the busy_pin goes LOW
+ */
+void Epd::WaitUntilIdle(void) {
+    while(DigitalRead(busy_pin) == HIGH) {      //LOW: idle, HIGH: busy
+        DelayMs(100);
+    }      
+}
+
+/**
+ *  @brief: module reset.
+ *          often used to awaken the module in deep sleep,
+ *          see Epd::Sleep();
+ */
+void Epd::Reset(void) {
+    DigitalWrite(reset_pin, LOW);                //module reset    
+    DelayMs(200);
+    DigitalWrite(reset_pin, HIGH);
+    DelayMs(200);    
+}
+
+/**
+ *  @brief: set the look-up table register
+ */
+void Epd::SetLut(const unsigned char* lut) {
+    this->lut = lut;
+    SendCommand(WRITE_LUT_REGISTER);
+    /* the length of look-up table is 30 bytes */
+    for (int i = 0; i < 30; i++) {
+        SendData(this->lut[i]);
+    }
+}
+
+/**
+ *  @brief: put an image buffer to the frame memory.
+ *          this won't update the display.
+ */
+void Epd::SetFrameMemory(
+    const unsigned char* image_buffer,
+    int x,
+    int y,
+    int image_width,
+    int image_height
+) {
+    int x_end;
+    int y_end;
+
+    if (
+        image_buffer == NULL ||
+        x < 0 || image_width < 0 ||
+        y < 0 || image_height < 0
+    ) {
+        return;
+    }
+    /* x point must be the multiple of 8 or the last 3 bits will be ignored */
+    x &= 0xF8;
+    image_width &= 0xF8;
+    if (x + image_width >= this->width) {
+        x_end = this->width - 1;
+    } else {
+        x_end = x + image_width - 1;
+    }
+    if (y + image_height >= this->height) {
+        y_end = this->height - 1;
+    } else {
+        y_end = y + image_height - 1;
+    }
+    SetMemoryArea(x, y, x_end, y_end);
+    SetMemoryPointer(x, y);
+    SendCommand(WRITE_RAM);
+    /* send the image data */
+    for (int j = 0; j < y_end - y + 1; j++) {
+        for (int i = 0; i < (x_end - x + 1) / 8; i++) {
+            SendData(image_buffer[i + j * (image_width / 8)]);
+        }
+    }
+}
+
+/**
+ *  @brief: put an image buffer to the frame memory.
+ *          this won't update the display.
+ *
+ *          Question: When do you use this function instead of 
+ *          void SetFrameMemory(
+ *              const unsigned char* image_buffer,
+ *              int x,
+ *              int y,
+ *              int image_width,
+ *              int image_height
+ *          );
+ *          Answer: SetFrameMemory with parameters only reads image data
+ *          from the RAM but not from the flash in AVR chips (for AVR chips,
+ *          you have to use the function pgm_read_byte to read buffers 
+ *          from the flash).
+ */
+void Epd::SetFrameMemory(const unsigned char* image_buffer) {
+    SetMemoryArea(0, 0, this->width - 1, this->height - 1);
+    SetMemoryPointer(0, 0);
+    SendCommand(WRITE_RAM);
+    /* send the image data */
+    for (int i = 0; i < this->width / 8 * this->height; i++) {
+        SendData(pgm_read_byte(&image_buffer[i]));
+    }
+}
+
+/**
+ *  @brief: clear the frame memory with the specified color.
+ *          this won't update the display.
+ */
+void Epd::ClearFrameMemory(unsigned char color) {
+    SetMemoryArea(0, 0, this->width - 1, this->height - 1);
+    SetMemoryPointer(0, 0);
+    SendCommand(WRITE_RAM);
+    /* send the color data */
+    for (int i = 0; i < this->width / 8 * this->height; i++) {
+        SendData(color);
+    }
+}
+
+/**
+ *  @brief: update the display
+ *          there are 2 memory areas embedded in the e-paper display
+ *          but once this function is called,
+ *          the the next action of SetFrameMemory or ClearFrame will 
+ *          set the other memory area.
+ */
+void Epd::DisplayFrame(void) {
+    SendCommand(DISPLAY_UPDATE_CONTROL_2);
+    SendData(0xC4);
+    SendCommand(MASTER_ACTIVATION);
+    SendCommand(TERMINATE_FRAME_READ_WRITE);
+    WaitUntilIdle();
+}
+
+/**
+ *  @brief: private function to specify the memory area for data R/W
+ */
+void Epd::SetMemoryArea(int x_start, int y_start, int x_end, int y_end) {
+    SendCommand(SET_RAM_X_ADDRESS_START_END_POSITION);
+    /* x point must be the multiple of 8 or the last 3 bits will be ignored */
+    SendData((x_start >> 3) & 0xFF);
+    SendData((x_end >> 3) & 0xFF);
+    SendCommand(SET_RAM_Y_ADDRESS_START_END_POSITION);
+    SendData(y_start & 0xFF);
+    SendData((y_start >> 8) & 0xFF);
+    SendData(y_end & 0xFF);
+    SendData((y_end >> 8) & 0xFF);
+}
+
+/**
+ *  @brief: private function to specify the start point for data R/W
+ */
+void Epd::SetMemoryPointer(int x, int y) {
+    SendCommand(SET_RAM_X_ADDRESS_COUNTER);
+    /* x point must be the multiple of 8 or the last 3 bits will be ignored */
+    SendData((x >> 3) & 0xFF);
+    SendCommand(SET_RAM_Y_ADDRESS_COUNTER);
+    SendData(y & 0xFF);
+    SendData((y >> 8) & 0xFF);
+    WaitUntilIdle();
+}
+
+/**
+ *  @brief: After this command is transmitted, the chip would enter the 
+ *          deep-sleep mode to save power. 
+ *          The deep sleep mode would return to standby by hardware reset. 
+ *          You can use Epd::Init() to awaken
+ */
+void Epd::Sleep() {
+    SendCommand(DEEP_SLEEP_MODE);
+    WaitUntilIdle();
+}
+
+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
+};
+
+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
+};
+
+
+/* END OF FILE */
+
+
+