/** * @filename : epd3in7.cpp * @brief : Implements for e-paper library * @author : Waveshare * * Copyright (C) Waveshare July 17 2020 * * 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 #include "epd3in7.h" #include "imagedata.h" static const UBYTE lut_4Gray_GC[] = { 0x2A,0x06,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//1 0x28,0x06,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//2 0x20,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//3 0x14,0x06,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//4 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//5 0x00,0x02,0x02,0x0A,0x00,0x00,0x00,0x08,0x08,0x02,//6 0x00,0x02,0x02,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,//7 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//8 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[] = { 0x2A,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//1 0x05,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//2 0x2A,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//3 0x05,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//4 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//5 0x00,0x02,0x03,0x0A,0x00,0x02,0x06,0x0A,0x05,0x00,//6 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//7 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//8 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[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//1 0x01,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0A,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//3 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//5 0x00,0x00,0x05,0x05,0x00,0x05,0x03,0x05,0x05,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//7 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 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 }; 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(void) { if (IfInit() != 0) { return -1; } Reset(); SendCommand(0x12); DelayMs(300); SendCommand(0x46); SendData(0xF7); WaitUntilIdle(); SendCommand(0x47); SendData(0xF7); WaitUntilIdle(); SendCommand(0x01); // setting gaet number SendData(0xDF); SendData(0x01); SendData(0x00); SendCommand(0x03); // set gate voltage SendData(0x00); SendCommand(0x04); // set source voltage SendData(0x41); SendData(0xA8); SendData(0x32); SendCommand(0x11); // set data entry sequence SendData(0x03); SendCommand(0x3C); // set border SendData(0x00); SendCommand(0x0C); // set booster strength SendData(0xAE); SendData(0xC7); SendData(0xC3); SendData(0xC0); SendData(0xC0); SendCommand(0x18); // set internal sensor on SendData(0x80); SendCommand(0x2C); // set vcom value SendData(0x44); SendCommand(0x37); // set display option, these setting turn on previous function SendData(0x00); SendData(0xff); SendData(0xff); SendData(0xff); SendData(0xff); SendData(0x4f); SendData(0xff); SendData(0xff); SendData(0xff); SendData(0xff); SendCommand(0x44); // setting X direction start/end position of RAM SendData(0x00); SendData(0x00); SendData(0x17); SendData(0x01); SendCommand(0x45); // setting Y direction start/end position of RAM SendData(0x00); SendData(0x00); SendData(0xDF); SendData(0x01); SendCommand(0x22); // Display Update Control 2 SendData(0xCF); 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 HIGH */ void Epd::WaitUntilIdle(void) { Serial.print("e-Paper busy \r\n "); UBYTE busy; do { busy = DigitalRead(busy_pin); } while(busy); DelayMs(200); Serial.print("e-Paper busy release \r\n "); } /** * @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(1); DigitalWrite(reset_pin, HIGH); DelayMs(200); } /****************************************************************************** function : Display ******************************************************************************/ void Epd::DisplayFrame(const UBYTE *Image) { UWORD i; UWORD IMAGE_COUNTER = width * height / 8; SendCommand(0x4E); SendData(0x00); SendData(0x00); SendCommand(0x4F); SendData(0x00); SendData(0x00); SendCommand(0x24); for (i = 0; i < IMAGE_COUNTER; i++) { SendData(pgm_read_byte(&Image[i])); } Load_LUT(1); SendCommand(0x20); WaitUntilIdle(); } /****************************************************************************** function : Partial Display ******************************************************************************/ void Epd::DisplayFrame_Partial(const UBYTE *Image, UWORD Xstart, UWORD Ystart, UWORD iwidth, UWORD iheight) { UWORD i, j; SendCommand(0x4E); SendData(0x00); SendData(0x00); SendCommand(0x4F); SendData(0x00); SendData(0x00); SendCommand(0x24); for(i=0; i=Ystart && i=Xstart/8 && j<(Xstart+iwidth)/8) SendData(Image[(j-Xstart/8) + (i-Ystart)*iwidth/8]); else SendData(0xff); } } Load_LUT(0); SendCommand(0x20); WaitUntilIdle(); } /****************************************************************************** function : set the look-up tables parameter: ******************************************************************************/ void Epd::Load_LUT(UBYTE mode) { UWORD i; SendCommand(0x32); for (i = 0; i < 105; i++) { if(mode == 1) SendData(lut_1Gray_GC[i]); else if(mode == 0) SendData(lut_1Gray_DU[i]); } } /****************************************************************************** function : Clear Screen parameter: mode: 0:just partial mode 1:clear all ******************************************************************************/ void Epd::Clear(UBYTE mode) { UWORD i; UWORD IMAGE_COUNTER = width * height / 8; SendCommand(0x4E); SendData(0x00); SendData(0x00); SendCommand(0x4F); SendData(0x00); SendData(0x00); SendCommand(0x24); for (i = 0; i < IMAGE_COUNTER; i++) { SendData(0xff); } if(mode) Load_LUT(1); else Load_LUT(0); SendCommand(0x20); 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. * The only one parameter is a check code, the command would be * You can use EPD_Reset() to awaken */ void Epd::Sleep(void) { SendCommand(0X50); SendData(0xf7); SendCommand(0X02); //power off SendCommand(0X07); //deep sleep SendData(0xA5); } /* END OF FILE */