Jelajahi Sumber

update: 3.7寸墨水屏驱动小改下

chenxuuu 4 tahun lalu
induk
melakukan
ef454b7776

+ 687 - 0
luat/packages/eink/epd3in7.c

@@ -0,0 +1,687 @@
+/**
+ *  @filename   :   epd3in7.c
+ *  @brief      :   Implements for e-paper library
+ *  @author     :   Yehui from Waveshare
+ *
+ *  Copyright (C) Waveshare     September 12 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 "epd3in7.h"
+#include "epdif.h"
+
+#define LUAT_LOG_TAG "luat.epaper"
+#include "luat_log.h"
+
+//#define CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED 0
+#define CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT 0
+#define EPD_3IN7F_WIDTH           280
+#define EPD_3IN7F_HEIGHT          480
+#define EPD_3IN7F_ROW_LEN         (EPD_3IN7F_HEIGHT / 8u)
+#define EPD_3IN7F_PARTIAL_CNT     5;
+
+static uint8_t partial_counter = 0;
+static const uint8_t lut_vcom_dc1[] = {
+    0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+static const uint8_t lut_ww1[] = {
+    0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+static const uint8_t lut_bw1[] = {
+    0x01, 0x84, 0x84, 0x83, 0x01, 0x01, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+static const uint8_t lut_wb1[] = {
+    0x01, 0x44, 0x44, 0x43, 0x01, 0x01, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+static const uint8_t lut_bb1[] = {
+    0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+
+static void EPD_3IN7F_load_partial_lut(EPD* epd)
+{
+    EPD_3IN7F_SendCommand(epd,0x20); // LUT VCOM register
+    for (int i = 0; i < 56; i++)
+      EPD_3IN7F_SendData(epd, lut_vcom_dc1[i]);
+  //  EPD_3IN7F_SendData((uint8_t *)lut_vcom_dc1, sizeof(lut_vcom_dc1));
+
+    EPD_3IN7F_SendCommand(epd,0x21); // LUT White-to-White
+    for (int i = 0; i < 56; i++)
+      EPD_3IN7F_SendData(epd, lut_ww1[i]);
+  //  EPD_3IN7F_SendData((uint8_t *)lut_ww1, sizeof(lut_ww1));
+
+    EPD_3IN7F_SendCommand(epd,0x22); // LUT Black-to-White
+    //EPD_3IN7F_SendData((uint8_t *)lut_bw1, sizeof(lut_bw1));
+    for (int i = 0; i < 56; i++)
+      EPD_3IN7F_SendData(epd, lut_bw1[i]);
+
+    EPD_3IN7F_SendCommand(epd,0x23); // LUT White-to-Black
+    //EPD_3IN7F_SendData((uint8_t *)lut_wb1,sizeof(lut_wb1));
+    for (int i = 0; i < 56; i++)
+      EPD_3IN7F_SendData(epd, lut_wb1[i]);
+
+    EPD_3IN7F_SendCommand(epd,0x24); // LUT Black-to-Black
+    //EPD_3IN7F_SendData((uint8_t *)lut_bb1, sizeof(lut_bb1));
+    for (int i = 0; i < 56; i++)
+      EPD_3IN7F_SendData(epd, lut_bb1[i]);
+}
+static void EPD_3IN7F_partial_in(EPD* epd)
+{
+//    ESP_LOGD(TAG, "Partial in!");
+
+    // Panel setting: accept LUT from registers instead of OTP
+#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
+    uint8_t pst_use_reg_lut[] = { 0xf3, 0x0e };
+#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
+    uint8_t pst_use_reg_lut[] = { 0xff, 0x0e };
+#else
+#//error "Unsupported orientation - only portrait modes are supported for now"
+#endif
+    EPD_3IN7F_SendCommand(epd,0x00);
+   // EPD_3IN7F_SendData(pst_use_reg_lut, sizeof(pst_use_reg_lut));
+    for (int i = 0; i < 2; i++)
+      EPD_3IN7F_SendData(epd, pst_use_reg_lut[i]);
+
+    // WORKAROUND: need to ignore OLD framebuffer or otherwise partial refresh won't work
+    uint8_t vcom = 0xb7;
+    EPD_3IN7F_SendCommand(epd,0x50);
+    EPD_3IN7F_SendData(epd, vcom);
+
+    // Dump LUT in
+    EPD_3IN7F_load_partial_lut(epd);
+
+    // Go partial!
+    EPD_3IN7F_SendCommand(epd,0x91);
+}
+
+static void EPD_3IN7F_partial_out(EPD* epd)
+{
+//    ESP_LOGD(TAG, "Partial out!");
+
+    // Panel setting: use LUT from OTP
+#if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
+    uint8_t pst_use_otp_lut[] = { 0xd3, 0x0e };
+#elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
+    uint8_t pst_use_otp_lut[] = { 0xdf, 0x0e };
+#else
+//#error "Unsupported orientation - only portrait modes are supported for now"
+#endif
+    EPD_3IN7F_SendCommand(epd,0x00);
+    //EPD_3IN7F_SendData(pst_use_otp_lut, sizeof(pst_use_otp_lut));
+    for (int i = 0; i < 2; i++)
+      EPD_3IN7F_SendData(epd, pst_use_otp_lut[i]);
+
+    // WORKAROUND: re-enable OLD framebuffer to get a better full refresh
+    uint8_t vcom = 0x97;
+    EPD_3IN7F_SendCommand(epd,0x50);
+    EPD_3IN7F_SendData(epd, vcom);
+
+    // Out from partial!
+    EPD_3IN7F_SendCommand(epd,0x92);
+}
+
+int EPD_3IN7F_Init(EPD* epd) {
+  epd->reset_pin = RST_PIN;
+  epd->dc_pin = DC_PIN;
+  epd->cs_pin = CS_PIN;
+  epd->busy_pin = BUSY_PIN;
+  epd->width = EPD_3IN7F_WIDTH;
+  epd->height = EPD_3IN7F_HEIGHT;
+  /* this calls the peripheral hardware interface, see epdif */
+  if (EpdInitCallback() != 0) {
+    return -1;
+  }
+  /* EPD hardware init start */
+  EPD_3IN7F_Reset(epd);
+  /*
+  EPD_3IN7F_SendCommand(epd, DRIVER_OUTPUT_CONTROL);
+  EPD_3IN7F_SendData(epd, (EPD_3IN7F_HEIGHT - 1) & 0xFF);
+  EPD_3IN7F_SendData(epd, ((EPD_3IN7F_HEIGHT - 1) >> 8) & 0xFF);
+  EPD_3IN7F_SendData(epd, 0x00);                     // GD = 0; SM = 0; TB = 0;
+  EPD_3IN7F_SendCommand(epd, BOOSTER_SOFT_START_CONTROL);
+  EPD_3IN7F_SendData(epd, 0xD7);
+  EPD_3IN7F_SendData(epd, 0xD6);
+  EPD_3IN7F_SendData(epd, 0x9D);
+  EPD_3IN7F_SendCommand(epd, WRITE_VCOM_REGISTER);
+  EPD_3IN7F_SendData(epd, 0xA8);                     // VCOM 7C
+  EPD_3IN7F_SendCommand(epd, SET_DUMMY_LINE_PERIOD);
+  EPD_3IN7F_SendData(epd, 0x1A);                     // 4 dummy lines per gate
+  EPD_3IN7F_SendCommand(epd, SET_GATE_TIME);
+  EPD_3IN7F_SendData(epd, 0x08);                     // 2us per line
+  EPD_3IN7F_SendCommand(epd, DATA_ENTRY_MODE_SETTING);
+  EPD_3IN7F_SendData(epd, 0x03);                     // X increment; Y increment
+  EPD_3IN7F_SetLut(epd, epd->lut);
+  */
+///*
+  EPD_3IN7F_SendCommand(epd,0x00); // panel setting
+  EPD_3IN7F_SendData (epd,0xdf);
+  EPD_3IN7F_SendData (epd,0x0e);
+
+  EPD_3IN7F_SendCommand(epd,0x01); // power setting
+  EPD_3IN7F_SendData(epd,0x03);
+  EPD_3IN7F_SendData(epd,0x06); // 16V
+  EPD_3IN7F_SendData(epd,0x2A);//
+  EPD_3IN7F_SendData(epd,0x2A);//
+
+  EPD_3IN7F_SendCommand(epd,0x4D); // FITIinternal code
+  EPD_3IN7F_SendData (epd,0x55);
+
+  EPD_3IN7F_SendCommand(epd,0xaa);
+  EPD_3IN7F_SendData (epd,0x0f);
+
+  EPD_3IN7F_SendCommand(epd,0xE9);
+  EPD_3IN7F_SendData (epd,0x02);
+
+  EPD_3IN7F_SendCommand(epd,0xb6);
+  EPD_3IN7F_SendData (epd,0x11);
+
+  EPD_3IN7F_SendCommand(epd,0xF3);
+  EPD_3IN7F_SendData (epd,0x0a);
+
+  EPD_3IN7F_SendCommand(epd,0x06); // boost soft start
+  EPD_3IN7F_SendData (epd,0xc7);
+  EPD_3IN7F_SendData (epd,0x0c);
+  EPD_3IN7F_SendData (epd,0x0c);
+
+  EPD_3IN7F_SendCommand(epd,0x61); // resolution setting
+  EPD_3IN7F_SendData (epd,0xc8); // 200
+  EPD_3IN7F_SendData (epd,0x00);
+  EPD_3IN7F_SendData (epd,0xc8); // 200
+
+  EPD_3IN7F_SendCommand(epd,0x60); // Tcon setting
+  EPD_3IN7F_SendData (epd,0x00);
+
+  EPD_3IN7F_SendCommand(epd,0x82); // VCOM DC setting
+  EPD_3IN7F_SendData (epd,0x12);
+
+  EPD_3IN7F_SendCommand(epd,0x30); // PLL control
+  EPD_3IN7F_SendData (epd,0x3C);   // default 50Hz
+
+  EPD_3IN7F_SendCommand(epd,0X50); // VCOM and data interval
+  EPD_3IN7F_SendData(epd,0x97);//
+
+  EPD_3IN7F_SendCommand(epd,0XE3); // power saving register
+  EPD_3IN7F_SendData(epd,0x00); // default
+
+  EPD_3IN7F_SendCommand(epd,0X04);
+//*/
+
+/*  esp32 lib
+  EPD_3IN7F_SendCommand(epd,0x00); // panel setting
+  EPD_3IN7F_SendData (epd,0xdf);
+  EPD_3IN7F_SendData (epd,0x0e);
+
+  EPD_3IN7F_SendCommand(epd,0x4d); // panel setting
+  EPD_3IN7F_SendData (epd,0x55);
+
+  EPD_3IN7F_SendCommand(epd,0xaa); // panel setting
+  EPD_3IN7F_SendData (epd,0x0f);
+
+  EPD_3IN7F_SendCommand(epd,0xe9); // panel setting
+  EPD_3IN7F_SendData (epd,0x02);
+
+  EPD_3IN7F_SendCommand(epd,0xb6); // panel setting
+  EPD_3IN7F_SendData (epd,0x11);
+
+  EPD_3IN7F_SendCommand(epd,0xf3); // panel setting
+  EPD_3IN7F_SendData (epd,0x0a);
+
+  EPD_3IN7F_SendCommand(epd,0x61); // resolution setting
+  EPD_3IN7F_SendData (epd,0xc8); // 200
+  EPD_3IN7F_SendData (epd,0x00);
+  EPD_3IN7F_SendData (epd,0xc8); // 200
+
+  EPD_3IN7F_SendCommand(epd,0x60); // panel setting
+  EPD_3IN7F_SendData (epd,0x00);
+
+  EPD_3IN7F_SendCommand(epd,0x50); // panel setting
+  EPD_3IN7F_SendData (epd,0x97);
+
+  EPD_3IN7F_SendCommand(epd,0xe3); // panel setting
+  EPD_3IN7F_SendData (epd,0x00);
+*/
+  EPD_3IN7F_DelayMs(epd, 100);
+  EPD_3IN7F_WaitUntilIdle(epd);
+
+  /* EPD hardware init end */
+  return 0;
+}
+
+/**
+ *  @brief: this calls the corresponding function from epdif.h
+ *          usually there is no need to change this function
+ */
+void EPD_3IN7F_DigitalWrite(EPD* epd, int pin, int value) {
+  EpdDigitalWriteCallback(pin, value);
+}
+
+/**
+ *  @brief: this calls the corresponding function from epdif.h
+ *          usually there is no need to change this function
+ */
+int EPD_3IN7F_DigitalRead(EPD* epd, int pin) {
+  return EpdDigitalReadCallback(pin);
+}
+
+/**
+ *  @brief: this calls the corresponding function from epdif.h
+ *          usually there is no need to change this function
+ */
+void EPD_3IN7F_DelayMs(EPD* epd, unsigned int delaytime) {  // 1ms
+  EpdDelayMsCallback(delaytime);
+}
+
+/**
+ *  @brief: basic function for sending commands
+ */
+void EPD_3IN7F_SendCommand(EPD* epd, unsigned char command) {
+  EPD_3IN7F_DigitalWrite(epd, epd->dc_pin, LOW);
+  EpdSpiTransferCallback(command);
+}
+
+/**
+ *  @brief: basic function for sending data
+ */
+void EPD_3IN7F_SendData(EPD* epd, unsigned char data) {
+  EPD_3IN7F_DigitalWrite(epd, epd->dc_pin, HIGH);
+  EpdSpiTransferCallback(data);
+}
+
+/**
+ *  @brief: Wait until the busy_pin goes LOW
+ */
+void EPD_3IN7F_WaitUntilIdle(EPD* epd) {
+  while(EPD_3IN7F_DigitalRead(epd, epd->busy_pin) == HIGH) {      //0: busy, 1: idle
+    EPD_3IN7F_DelayMs(epd, 100);
+  }      
+}
+
+/**
+ *  @brief: module reset.
+ *          often used to awaken the module in deep sleep,
+ *          see EPD::Sleep();
+ */
+void EPD_3IN7F_Reset(EPD* epd) {
+  EPD_3IN7F_DigitalWrite(epd, epd->reset_pin, LOW);                //module reset    
+  EPD_3IN7F_DelayMs(epd, 200);
+  EPD_3IN7F_DigitalWrite(epd, epd->reset_pin, HIGH);
+  EPD_3IN7F_DelayMs(epd, 200);    
+}
+
+/**
+ *  @brief: module Power on.
+ */
+void EPD_3IN7F_power_on(EPD* epd) {
+  EPD_3IN7F_SendCommand(epd, 0x50);  
+  EPD_3IN7F_SendData(epd,0x97); 
+
+  EPD_3IN7F_SendCommand(epd, 0x04);     
+}
+
+/**
+ *  @brief: module Power off.
+ */
+void EPD_3IN7F_power_off(EPD* epd) {
+  EPD_3IN7F_SendCommand(epd, 0x50);  
+  EPD_3IN7F_SendData(epd,0xf7);  
+
+  EPD_3IN7F_SendCommand(epd, 0x02);
+}
+
+/**
+ *  @brief: put an image buffer to the frame memory.
+ *          this won't update the display.
+ */
+
+
+void EPD_3IN7F_SetFrameMemory(
+  EPD* epd,
+  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 >= epd->width) {
+    x_end = epd->width - 1;
+  } else {
+    x_end = x + image_width - 1;
+  }
+  if (y + image_height >= epd->height) {
+    y_end = epd->height - 1;
+  } else {
+    y_end = y + image_height - 1;
+  }
+
+  // 局刷还不行
+  EPD_3IN7F_SetMemoryArea(epd, x, y, x_end, y_end);
+  //EPD_3IN7F_SetMemoryPointer(epd, x, y);
+  //EPD_3IN7F_SendCommand(epd, WRITE_RAM);
+  EPD_3IN7F_SendCommand(epd, 0x10);
+  /* 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++) {
+      EPD_3IN7F_SendData(epd, image_buffer[i + j * (image_width / 8)]);
+    }
+  }
+
+    EPD_3IN7F_SendCommand(epd, 0x13);
+  /* 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++) {
+      EPD_3IN7F_SendData(epd, image_buffer[i + j * (image_width / 8)]);
+    }
+  }
+}
+
+/**
+*  @brief: clear the frame memory with the specified color.
+*          this won't update the display.
+*/
+void EPD_3IN7F_ClearFrameMemory(EPD* epd, unsigned char color) {
+  EPD_3IN7F_SetMemoryArea(epd, 0, 0, epd->width - 1, epd->height - 1);
+  EPD_3IN7F_SetMemoryPointer(epd, 0, 0);
+  EPD_3IN7F_SendCommand(epd, WRITE_RAM);
+  /* send the color data */
+  for (int i = 0; i < epd->width / 8 * epd->height; i++) {
+    EPD_3IN7F_SendData(epd, 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_3IN7F_DisplayFrame(EPD* epd) {
+  // EPD_3IN7F_SendCommand(epd, DISPLAY_UPDATE_CONTROL_2);
+  // EPD_3IN7F_SendData(epd, 0xC4);
+  // EPD_3IN7F_SendCommand(epd, MASTER_ACTIVATION);
+  // EPD_3IN7F_SendCommand(epd, TERMINATE_FRAME_READ_WRITE);
+
+
+  EPD_3IN7F_SendCommand(epd, 0x12);
+  EPD_3IN7F_WaitUntilIdle(epd);
+}
+
+/**
+ *  @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_3IN7F_Init() to awaken
+ */
+void EPD_3IN7F_Sleep(EPD* epd) {
+  EPD_3IN7F_SendCommand(epd, DEEP_SLEEP_MODE);
+  EPD_3IN7F_WaitUntilIdle(epd);
+}
+
+/**
+ *  @brief: set the look-up tables
+ */
+static void EPD_3IN7F_SetLut(EPD* epd, const unsigned char* lut) {
+  epd->lut = lut;
+  EPD_3IN7F_SendCommand(epd, WRITE_LUT_REGISTER);
+  /* the length of look-up table is 30 bytes */
+  for (int i = 0; i < 30; i++) {
+    EPD_3IN7F_SendData(epd, epd->lut[i]);
+  } 
+}
+
+
+
+
+/**
+ *  @brief: private function to specify the memory area for data R/W
+ */
+static void EPD_3IN7F_SetMemoryArea(EPD* epd, int x_start, int y_start, int x_end, int y_end) {
+  // EPD_3IN7F_SendCommand(epd, SET_RAM_X_ADDRESS_START_END_POSITION);
+  // /* x point must be the multiple of 8 or the last 3 bits will be ignored */
+  // EPD_3IN7F_SendData(epd, (x_start >> 3) & 0xFF);
+  // EPD_3IN7F_SendData(epd, (x_end >> 3) & 0xFF);
+  // EPD_3IN7F_SendCommand(epd, SET_RAM_Y_ADDRESS_START_END_POSITION);
+  // EPD_3IN7F_SendData(epd, y_start & 0xFF);
+  // EPD_3IN7F_SendData(epd, (y_start >> 8) & 0xFF);
+  // EPD_3IN7F_SendData(epd, y_end & 0xFF);
+  // EPD_3IN7F_SendData(epd, (y_end >> 8) & 0xFF);
+
+  uint16_t xe = (x_start + x_end - 1) | 0x0007; // byte boundary inclusive (last byte)
+  uint16_t ye = y_start + y_end - 1;
+  x_start &= 0xFFF8; // byte boundary
+  EPD_3IN7F_SendCommand(epd,0x90); // partial window
+  //_writeData(x / 256);
+  EPD_3IN7F_SendData(epd,x_start % 256);
+  //_writeData(xe / 256);
+  EPD_3IN7F_SendData(epd,xe % 256);
+  EPD_3IN7F_SendData(epd,y_start / 256);
+  EPD_3IN7F_SendData(epd,y_start % 256);
+  EPD_3IN7F_SendData(epd,ye / 256);
+  EPD_3IN7F_SendData(epd,ye % 256);
+  EPD_3IN7F_SendData(epd,0x01); // don't see any difference
+  //_writeData(0x00); // don't see any difference
+}
+
+/**
+ *  @brief: private function to specify the start point for data R/W
+ */
+static void EPD_3IN7F_SetMemoryPointer(EPD* epd, int x, int y) {
+  EPD_3IN7F_SendCommand(epd, SET_RAM_X_ADDRESS_COUNTER);
+  /* x point must be the multiple of 8 or the last 3 bits will be ignored */
+  EPD_3IN7F_SendData(epd, (x >> 3) & 0xFF);
+  EPD_3IN7F_SendCommand(epd, SET_RAM_Y_ADDRESS_COUNTER);
+  EPD_3IN7F_SendData(epd, y & 0xFF);
+  EPD_3IN7F_SendData(epd, (y >> 8) & 0xFF);
+  EPD_3IN7F_WaitUntilIdle(epd);
+}
+
+
+
+
+
+static void EPD_3IN7F_update_partial(EPD* epd,uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t *data)
+{
+  EPD_3IN7F_power_on(epd);
+  EPD_3IN7F_partial_in(epd);
+
+  // Set partial window
+  uint8_t ptl_setting[8] = { x1, x2, 0, y1, 0, y2, 0x01 };
+  //uint8_t ptl_setting[8] = { x1, x1+x2, 0, y1, 0, y1+y2, 0x01 };
+  //EPD_3IN7F_SendCommand(epd,0X90); // power saving register
+  EPD_3IN7F_SendCommand(epd,0x90);
+  for (int i = 0; i < 7; i++)
+    EPD_3IN7F_SendData(epd, ptl_setting[i]);
+
+  //uint8_t *data_ptr = (uint8_t *)data;
+
+  EPD_3IN7F_SendCommand(epd,0x13);
+  for (size_t h_idx = 0; h_idx < y2; h_idx++) {
+    //EPD_3IN7F_SendData(data_ptr, EPD_3IN7F_ROW_LEN);
+    for (int i = 0; i < x2/8; i++)
+      EPD_3IN7F_SendData(epd, data[i]);
+    data += x2/8;
+ //   len -= EPD_3IN7F_ROW_LEN;
+  }
+
+
+
+//  ESP_LOGD(TAG, "Partial wait start");
+
+  EPD_3IN7F_SendCommand(epd,0x12);
+  EPD_3IN7F_WaitUntilIdle(epd);
+
+//  ESP_LOGD(TAG, "Partial updated");
+  EPD_3IN7F_partial_out(epd);
+  EPD_3IN7F_power_off(epd);
+
+}
+
+void EPD_3IN7F_fb_full_update(EPD* epd,uint8_t *data, size_t len)
+{
+  EPD_3IN7F_power_on(epd);
+//    ESP_LOGD(TAG, "Performing full update, len: %u", len);
+
+  uint8_t *data_ptr = data;
+
+    // Fill OLD data (maybe not necessary)
+  uint8_t old_data[EPD_3IN7F_ROW_LEN] = { 0 };
+  EPD_3IN7F_SendCommand(epd,0x10);
+  for (size_t idx = 0; idx < EPD_3IN7F_HEIGHT; idx++) {
+      //jd79653a_spi_send_data(old_data, EPD_3IN7F_ROW_LEN);
+    for (int i = 0; i < EPD_3IN7F_ROW_LEN; i++)
+      EPD_3IN7F_SendData(epd, old_data[i]);
+  }
+
+  // Fill NEW data
+  EPD_3IN7F_SendCommand(epd,0x13);
+  for (size_t h_idx = 0; h_idx < EPD_3IN7F_HEIGHT; h_idx++) {
+        //jd79653a_spi_send_data(data_ptr, EPD_3IN7F_ROW_LEN);
+    for (int i = 0; i < EPD_3IN7F_ROW_LEN; i++)
+      EPD_3IN7F_SendData(epd, data_ptr[i]);
+    data_ptr += EPD_3IN7F_ROW_LEN;
+      //len -= EPD_3IN7F_ROW_LEN;
+  }
+    //ESP_LOGD(TAG, "Rest len: %u", len);
+  EPD_3IN7F_SendCommand(epd,0x12); // Issue refresh command
+  EPD_3IN7F_DelayMs(epd, 100);
+  EPD_3IN7F_WaitUntilIdle(epd);
+
+  EPD_3IN7F_power_off(epd);
+}
+//void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
+void jd79653a_lv_fb_flush(
+  EPD* epd,
+  const unsigned char *color_map,
+  int x,
+  int y,
+  int image_width,
+  int image_height
+){
+//    size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
+
+   // ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
+ //   ESP_LOGD(TAG, "Writing LVGL fb with len: %u, partial counter: %u", len, partial_counter);
+
+    uint8_t *buf = (uint8_t *) color_map;
+
+    if (partial_counter == 0) {
+    //    ESP_LOGD(TAG, "Refreshing in FULL");
+        EPD_3IN7F_fb_full_update(epd, buf, ((EPD_3IN7F_HEIGHT * EPD_3IN7F_WIDTH) / 8));
+        partial_counter = EPD_3IN7F_PARTIAL_CNT; // Reset partial counter here
+    } else {
+        EPD_3IN7F_update_partial(epd, x, y, x+image_width-1, y+image_height-1, buf);
+        partial_counter -= 1;   // ...or otherwise, decrease 1
+    }
+
+ //   lv_disp_flush_ready(drv);
+}
+
+#define UBYTE uint8_t
+UBYTE EPD_3IN7FF_Init(void);
+void EPD_3IN7FF_Clear(void);
+void EPD_3IN7FF_Display(UBYTE *Image);
+void EPD_3IN7FF_Sleep(void);
+
+#define BUSY_Pin          (18)
+#define RST_Pin           (7)
+#define DC_Pin            (9)
+#define SPI_CS_Pin        (16)
+
+static EPD _epd;
+UBYTE EPD_3IN7FF_Init(void) {
+  _epd.busy_pin = BUSY_Pin;
+  _epd.reset_pin = RST_PIN;
+  _epd.dc_pin = DC_PIN;
+  _epd.cs_pin = SPI_CS_Pin;
+  _epd.width = EPD_3IN7F_WIDTH;
+  _epd.height = EPD_3IN7F_HEIGHT;
+  LLOGD("EPD_3IN7F_Init");
+  EPD_3IN7F_Init(&_epd);
+  return 0;
+}
+void EPD_3IN7FF_Clear(void) {
+  ;
+}
+void EPD_3IN7FF_Display(UBYTE *Image) {
+  EPD_3IN7F_SetFrameMemory(&_epd, Image, 0, 0, EPD_3IN7F_WIDTH, EPD_3IN7F_HEIGHT);
+  EPD_3IN7F_DisplayFrame(&_epd);
+}
+void EPD_3IN7FF_Sleep(void) {
+  EPD_3IN7F_Sleep(&_epd);
+}
+
+/* END OF FILE */
+
+

+ 110 - 0
luat/packages/eink/epd3in7.h

@@ -0,0 +1,110 @@
+/**
+ *  @filename   :   EPD3IN7.h
+ *  @brief      :   Header file for e-paper library EPD3IN7.c
+ *  @author     :   Yehui from Waveshare
+ *  
+ *  Copyright (C) Waveshare     September 12 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.
+ */
+
+#ifndef EPD3IN7_H
+#define EPD3IN7_H
+
+#include "fonts.h"
+
+// Display resolution
+#define EPD_3IN7F_WIDTH       280
+#define EPD_3IN7F_HEIGHT      480
+
+// EPD3IN7 commands
+#define DRIVER_OUTPUT_CONTROL                       0x01
+#define BOOSTER_SOFT_START_CONTROL                  0x0C
+#define GATE_SCAN_START_POSITION                    0x0F
+#define DEEP_SLEEP_MODE                             0x07 // 0x10
+#define DATA_ENTRY_MODE_SETTING                     0x11
+#define SW_RESET                                    0x12
+#define TEMPERATURE_SENSOR_CONTROL                  0x1A
+#define MASTER_ACTIVATION                           0x20
+#define DISPLAY_UPDATE_CONTROL_1                    0x21
+#define DISPLAY_UPDATE_CONTROL_2                    0x22
+#define WRITE_RAM                                   0x24
+#define WRITE_VCOM_REGISTER                         0x2C
+#define WRITE_LUT_REGISTER                          0x32
+#define SET_DUMMY_LINE_PERIOD                       0x3A
+#define SET_GATE_TIME                               0x3B
+#define BORDER_WAVEFORM_CONTROL                     0x3C
+#define SET_RAM_X_ADDRESS_START_END_POSITION        0x44
+#define SET_RAM_Y_ADDRESS_START_END_POSITION        0x45
+#define SET_RAM_X_ADDRESS_COUNTER                   0x4E
+#define SET_RAM_Y_ADDRESS_COUNTER                   0x4F
+#define TERMINATE_FRAME_READ_WRITE                  0xFF
+
+static const unsigned char lut_full_update[];
+static const unsigned char lut_partial_update[];
+
+typedef struct EPD_t {
+  int reset_pin;
+  int dc_pin;
+  int cs_pin;
+  int busy_pin;
+  int width;
+  int height;
+  const unsigned char* lut;
+} EPD;
+
+/* Hardware operating functions */
+/* public functions */
+int  EPD_3IN7F_Init(EPD* epd);
+void EPD_3IN7F_SendCommand(EPD* epd, unsigned char command);
+void EPD_3IN7F_SendData(EPD* epd, unsigned char data);
+void EPD_3IN7F_WaitUntilIdle(EPD* epd);
+void EPD_3IN7F_Reset(EPD* epd);
+void EPD_3IN7F_SetFrameMemory(
+  EPD* epd,
+  const unsigned char* image_buffer,
+  int x,
+  int y,
+  int image_width,
+  int image_height
+);
+void EPD_3IN7F_ClearFrameMemory(EPD* epd, unsigned char color);
+void EPD_3IN7F_DisplayFrame(EPD* epd);
+void EPD_3IN7F_Sleep(EPD* epd);
+void EPD_3IN7F_DelayMs(EPD* epd, unsigned int delay_time);
+void EPD_3IN7F_DigitalWrite(EPD* epd, int pin, int value);
+int  EPD_3IN7F_DigitalRead(EPD* epd, int pin);
+
+/* private functions */
+static void EPD_3IN7F_SetLut(EPD* epd, const unsigned char* lut);
+static void EPD_3IN7F_SetMemoryArea(EPD* epd, int x_start, int y_start, int x_end, int y_end);
+static void EPD_3IN7F_SetMemoryPointer(EPD* epd, int x, int y);
+
+
+void jd79653a_lv_fb_flush(
+  EPD* epd,
+  const unsigned char *color_map,
+  int x,
+  int y,
+  int image_width,
+  int image_height
+);
+#endif /* EPD3IN7_H */
+
+/* END OF FILE */

+ 1 - 0
luat/packages/eink/luat_lib_eink.c

@@ -619,6 +619,7 @@ static const rotable_Reg reg_eink[] =
     { "MODEL_2in9b_V3",       NULL,                 MODEL_2in9b_V3},
     { "MODEL_2in9d",          NULL,                 MODEL_2in9d},
     { "MODEL_2in9f",          NULL,                 MODEL_2in9f},
+    { "MODEL_3in7",           NULL,                 MODEL_3in7},
 
 	{ NULL,             NULL,                   0}
 };

+ 53 - 53
luat/packages/epaper/EPD_3in7.c

@@ -44,7 +44,7 @@ static const UBYTE lut_4Gray_GC[] =
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//9
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//10
 0x22,0x22,0x22,0x22,0x22
-};	
+};
 
 static const UBYTE lut_1Gray_GC[] =
 {
@@ -59,7 +59,7 @@ static const UBYTE lut_1Gray_GC[] =
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//9
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//10
 0x22,0x22,0x22,0x22,0x22
-};  
+};
 
 static const UBYTE lut_1Gray_DU[] =
 {
@@ -74,7 +74,7 @@ static const UBYTE lut_1Gray_DU[] =
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//9
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x22,0x22,0x22,0x22,0x22
-}; 
+};
 
 static const UBYTE lut_1Gray_A2[] =
 {
@@ -89,7 +89,7 @@ static const UBYTE lut_1Gray_A2[] =
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //9
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //10
 0x22,0x22,0x22,0x22,0x22
-}; 
+};
 
 /******************************************************************************
 function :	Software reset
@@ -159,7 +159,7 @@ void EPD_3IN7_Load_LUT(UBYTE lut)
     else if(lut == 2)
         EPD_3IN7_SendData(lut_1Gray_DU[i]);
     else if(lut == 3)
-        EPD_3IN7_SendData(lut_1Gray_A2[i]);  
+        EPD_3IN7_SendData(lut_1Gray_A2[i]);
     else
         Debug("There is no such lut \r\n");
   }
@@ -172,17 +172,17 @@ parameter:
 void EPD_3IN7_4Gray_Init(void)
 {
     EPD_3IN7_Reset();
-    
+
     EPD_3IN7_SendCommand(0x12);
     DEV_Delay_ms(300);
-    
-    EPD_3IN7_SendCommand(0x46); 
+
+    EPD_3IN7_SendCommand(0x46);
     EPD_3IN7_SendData(0xF7);
     EPD_3IN7_ReadBusy_HIGH();
     EPD_3IN7_SendCommand(0x47);
     EPD_3IN7_SendData(0xF7);
-    EPD_3IN7_ReadBusy_HIGH(); 
-    
+    EPD_3IN7_ReadBusy_HIGH();
+
     EPD_3IN7_SendCommand(0x01); // setting gaet number
     EPD_3IN7_SendData(0xDF);
     EPD_3IN7_SendData(0x01);
@@ -199,7 +199,7 @@ void EPD_3IN7_4Gray_Init(void)
     EPD_3IN7_SendCommand(0x11); // set data entry sequence
     EPD_3IN7_SendData(0x03);
 
-    EPD_3IN7_SendCommand(0x3C); // set border 
+    EPD_3IN7_SendCommand(0x3C); // set border
     EPD_3IN7_SendData(0x00);
 
     EPD_3IN7_SendCommand(0x0C); // set booster strength
@@ -207,25 +207,25 @@ void EPD_3IN7_4Gray_Init(void)
     EPD_3IN7_SendData(0xC7);
     EPD_3IN7_SendData(0xC3);
     EPD_3IN7_SendData(0xC0);
-    EPD_3IN7_SendData(0xC0);  
+    EPD_3IN7_SendData(0xC0);
 
     EPD_3IN7_SendCommand(0x18); // set internal sensor on
     EPD_3IN7_SendData(0x80);
-     
+
     EPD_3IN7_SendCommand(0x2C); // set vcom value
     EPD_3IN7_SendData(0x44);
-    
+
     EPD_3IN7_SendCommand(0x37); // set display option, these setting turn on previous function
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-    EPD_3IN7_SendData(0x00);  
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-    EPD_3IN7_SendData(0x00);  
+    EPD_3IN7_SendData(0x00);
+    EPD_3IN7_SendData(0x00);
 
     EPD_3IN7_SendCommand(0x44); // setting X direction start/end position of RAM
     EPD_3IN7_SendData(0x00);
@@ -250,17 +250,17 @@ parameter:
 void EPD_3IN7_1Gray_Init(void)
 {
     EPD_3IN7_Reset();
-    
+
     EPD_3IN7_SendCommand(0x12);
     DEV_Delay_ms(300);
-    
-    EPD_3IN7_SendCommand(0x46); 
+
+    EPD_3IN7_SendCommand(0x46);
     EPD_3IN7_SendData(0xF7);
     EPD_3IN7_ReadBusy_HIGH();
     EPD_3IN7_SendCommand(0x47);
     EPD_3IN7_SendData(0xF7);
-    EPD_3IN7_ReadBusy_HIGH(); 
-    
+    EPD_3IN7_ReadBusy_HIGH();
+
     EPD_3IN7_SendCommand(0x01); // setting gaet number
     EPD_3IN7_SendData(0xDF);
     EPD_3IN7_SendData(0x01);
@@ -277,7 +277,7 @@ void EPD_3IN7_1Gray_Init(void)
     EPD_3IN7_SendCommand(0x11); // set data entry sequence
     EPD_3IN7_SendData(0x03);
 
-    EPD_3IN7_SendCommand(0x3C); // set border 
+    EPD_3IN7_SendCommand(0x3C); // set border
     EPD_3IN7_SendData(0x00);
 
     EPD_3IN7_SendCommand(0x0C); // set booster strength
@@ -285,25 +285,25 @@ void EPD_3IN7_1Gray_Init(void)
     EPD_3IN7_SendData(0xC7);
     EPD_3IN7_SendData(0xC3);
     EPD_3IN7_SendData(0xC0);
-    EPD_3IN7_SendData(0xC0);  
+    EPD_3IN7_SendData(0xC0);
 
     EPD_3IN7_SendCommand(0x18); // set internal sensor on
     EPD_3IN7_SendData(0x80);
-     
+
     EPD_3IN7_SendCommand(0x2C); // set vcom value
     EPD_3IN7_SendData(0x44);
-    
+
     EPD_3IN7_SendCommand(0x37); // set display option, these setting turn on previous function
     EPD_3IN7_SendData(0x00);     //can switch 1 gray or 4 gray
     EPD_3IN7_SendData(0xFF);
     EPD_3IN7_SendData(0xFF);
     EPD_3IN7_SendData(0xFF);
-    EPD_3IN7_SendData(0xFF);  
+    EPD_3IN7_SendData(0xFF);
     EPD_3IN7_SendData(0x4F);
     EPD_3IN7_SendData(0xFF);
     EPD_3IN7_SendData(0xFF);
     EPD_3IN7_SendData(0xFF);
-    EPD_3IN7_SendData(0xFF);  
+    EPD_3IN7_SendData(0xFF);
 
     EPD_3IN7_SendCommand(0x44); // setting X direction start/end position of RAM
     EPD_3IN7_SendData(0x00);
@@ -339,35 +339,35 @@ void EPD_3IN7_4Gray_Clear(void)
     EPD_3IN7_SendCommand(0x4F);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-    
+
     EPD_3IN7_SendCommand(0x24);
     for (UWORD j = 0; j < Height; j++) {
        for (UWORD i = 0; i < Width; i++) {
            EPD_3IN7_SendData(0xff);
        }
     }
-    
+
     EPD_3IN7_SendCommand(0x4E);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-     
+
     EPD_3IN7_SendCommand(0x4F);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-    
+
     EPD_3IN7_SendCommand(0x26);
     for (UWORD j = 0; j < Height; j++) {
        for (UWORD i = 0; i < Width; i++) {
            EPD_3IN7_SendData(0xff);
        }
     }
-      
+
     EPD_3IN7_Load_LUT(0);
     EPD_3IN7_SendCommand(0x22);
     EPD_3IN7_SendData(0xC7);
 
     EPD_3IN7_SendCommand(0x20);
-    EPD_3IN7_ReadBusy_HIGH();     
+    EPD_3IN7_ReadBusy_HIGH();
 }
 
 /******************************************************************************
@@ -391,11 +391,11 @@ void EPD_3IN7_1Gray_Clear(void)
   {
     EPD_3IN7_SendData(0xff);
   }
-  
-  EPD_3IN7_Load_LUT(2);
-  
+
+  EPD_3IN7_Load_LUT(1);
+
   EPD_3IN7_SendCommand(0x20);
-  EPD_3IN7_ReadBusy_HIGH();    
+  EPD_3IN7_ReadBusy_HIGH();
 }
 
 /******************************************************************************
@@ -406,20 +406,20 @@ void EPD_3IN7_4Gray_Display(const UBYTE *Image)
 {
     UDOUBLE i,j,k;
     UBYTE temp1,temp2,temp3;
-    
+
     EPD_3IN7_SendCommand(0x49);
     EPD_3IN7_SendData(0x00);
 
-    
+
     EPD_3IN7_SendCommand(0x4E);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-    
-    
+
+
     EPD_3IN7_SendCommand(0x4F);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-    
+
     EPD_3IN7_SendCommand(0x24);
     for(i=0;i<16800;i++){
         temp3=0;
@@ -460,12 +460,12 @@ void EPD_3IN7_4Gray_Display(const UBYTE *Image)
     EPD_3IN7_SendCommand(0x4E);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-     
-    
+
+
     EPD_3IN7_SendCommand(0x4F);
     EPD_3IN7_SendData(0x00);
     EPD_3IN7_SendData(0x00);
-    
+
     EPD_3IN7_SendCommand(0x26);
     for(i=0; i<16800; i++) {
         temp3=0;
@@ -503,13 +503,13 @@ void EPD_3IN7_4Gray_Display(const UBYTE *Image)
     }
 
     EPD_3IN7_Load_LUT(0);
-    
+
     EPD_3IN7_SendCommand(0x22);
     EPD_3IN7_SendData(0xC7);
-    
+
     EPD_3IN7_SendCommand(0x20);
-    
-    EPD_3IN7_ReadBusy_HIGH(); 
+
+    EPD_3IN7_ReadBusy_HIGH();
 }
 
 /******************************************************************************
@@ -534,9 +534,9 @@ void EPD_3IN7_1Gray_Display(const UBYTE *Image)
     EPD_3IN7_SendData(Image[i]);
   }
 
-  EPD_3IN7_Load_LUT(2);
+  EPD_3IN7_Load_LUT(1);
   EPD_3IN7_SendCommand(0x20);
-  EPD_3IN7_ReadBusy_HIGH();  
+  EPD_3IN7_ReadBusy_HIGH();
 }
 
 /******************************************************************************
@@ -565,10 +565,10 @@ void EPD_3IN7_1Gray_Display_Part(const UBYTE *Image, UWORD Xstart, UWORD Ystart,
   {
     EPD_3IN7_SendData(Image[i]);
   }
-  
+
   EPD_3IN7_Load_LUT(2);
   EPD_3IN7_SendCommand(0x20);
-  EPD_3IN7_ReadBusy_HIGH();    
+  EPD_3IN7_ReadBusy_HIGH();
 }
 
 /******************************************************************************

+ 1 - 1
luat/packages/epaper/EPD_3in7.h

@@ -35,7 +35,7 @@
 
 // Display resolution
 #define EPD_3IN7_WIDTH       280
-#define EPD_3IN7_HEIGHT      480 
+#define EPD_3IN7_HEIGHT      480
 
 void EPD_3IN7_4Gray_Clear(void);
 void EPD_3IN7_4Gray_Init(void);

+ 17 - 4
luat/packages/epaper/epd.c

@@ -86,7 +86,11 @@ int EPD_Init(UBYTE mode, size_t *w, size_t *h) {
         *h = EPD_2IN9F_HEIGHT;
         EPD_2IN9D_Init();
         break;
-    
+    case MODEL_3in7:
+        *w = EPD_3IN7_WIDTH;
+        *h = EPD_3IN7_HEIGHT;
+        EPD_3IN7_1Gray_Init();
+        break;
     default:
         return -1;
     }
@@ -140,7 +144,10 @@ void EPD_Clear(void) {
     case MODEL_2in9f:
         EPD_2IN9FF_Clear();
         break;
-    
+    case MODEL_3in7:
+        EPD_3IN7_1Gray_Clear();
+        break;
+
     default:
         break;
     }
@@ -193,7 +200,10 @@ void EPD_Display(UBYTE *Image, UBYTE *Image2) {
     case MODEL_2in9f:
         EPD_2IN9FF_Display(Image);
         break;
-    
+    case MODEL_3in7:
+        EPD_3IN7_1Gray_Display(Image);
+        break;
+
     default:
         break;
     }
@@ -246,7 +256,10 @@ void EPD_Sleep(void) {
     case MODEL_2in9f:
         EPD_2IN9FF_Sleep();
         break;
-    
+    case MODEL_3in7:
+        EPD_3IN7_Sleep();
+        break;
+
     default:
         break;
     }

+ 2 - 0
luat/packages/epaper/epd.h

@@ -29,6 +29,7 @@ enum EPD_MODEL {
     MODEL_2in9b_V3,
     MODEL_2in9d,
     MODEL_2in9f,
+    MODEL_3in7,
 };
 
 
@@ -48,6 +49,7 @@ enum EPD_MODEL {
 #include "EPD_2in9b_V3.h"
 #include "EPD_2in9d.h"
 #include "EPD_2in9f.h"
+#include "EPD_3in7.h"
 
 
 #endif