4.2inch e-Paper HAT (C) made by WAVESHARE
Dependents: ePD_4R2inch_test_program_on_nRF52
Diff: epd4in2b.cpp
- Revision:
- 1:b1aa1d6a96bc
- Parent:
- 0:825022100d0f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/epd4in2b.cpp Wed Aug 28 23:35:01 2019 +0000 @@ -0,0 +1,296 @@ +/** + * @filename : epd4in2b.cpp + * @brief : Implements for Dual-color e-paper library + * @author : Yehui from Waveshare + * + * Copyright (C) Waveshare August 10 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. + */ + +/* + * Modified by Kenji Arai / JH1PJL + * + * http://www.page.sannet.ne.jp/kenjia/index.html + * http://mbed.org/users/kenjiArai/ + * Created: April 27th, 2019 + * Revised: May 26th, 2019 + * + * Refrence software + * https://github.com/waveshare/e-Paper + * https://os.mbed.com/users/imachooon/code/epd1in54/ + * + * Technical documents + * https://www.waveshare.com/wiki/4.2inch_e-Paper_Module_(B) + * + * Product + * https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-58UR + * https://www.waveshare.com/4.2inch-e-paper-module-b.htm + * + */ + +#include "epd4in2b.h" + +Epd::Epd(PinName mosi, + PinName miso, + PinName sclk, + PinName cs, + PinName dc, + PinName rst, + PinName busy, + PinName pwr + ):EpdIf(mosi, miso, sclk, cs, dc, rst, busy, pwr) +{ + width = EPD_WIDTH; + height = EPD_HEIGHT; +}; + +int Epd::Init(void) +{ + /* this calls the peripheral hardware interface, see epdif */ + if (IfInit() != 0) { + return -1; + } + /* EPD hardware init start */ + Reset(); + SendCommand(BOOSTER_SOFT_START); + SendData(0x17); + SendData(0x17); + SendData(0x17); //07 0f 17 1f 27 2F 37 2f + SendCommand(POWER_ON); + WaitUntilIdle(); + SendCommand(PANEL_SETTING); + SendData(0x0F); // LUT from OTP + /* EPD hardware init end */ + return 0; +} + +/** + * @brief: basic function for sending commands + */ +void Epd::SendCommand(unsigned char command) +{ + DigitalWrite(m_dc, LOW); + SpiTransfer(command); +} + +/** + * @brief: basic function for sending data + */ +void Epd::SendData(unsigned char data) +{ + DigitalWrite(m_dc, HIGH); + SpiTransfer(data); +} + +/** + * @brief: Wait until the busy_pin goes HIGH + */ +void Epd::WaitUntilIdle(void) +{ + while(DigitalRead(m_busy) == 0) { //0: busy, 1: idle + DelayMs(100); + } +} + +/** + * @brief: module reset. + * often used to awaken the module in deep sleep, + * see Epd::Sleep(); + */ +void Epd::Reset(void) +{ + DigitalWrite(m_rst, LOW); + DelayMs(200); + DigitalWrite(m_rst, HIGH); + DelayMs(200); +} + +/** + * @brief: transmit partial data to the SRAM + */ +void Epd::SetPartialWindow(const unsigned char* buffer_black, const unsigned char* buffer_red, int x, int y, int w, int l) +{ + SendCommand(PARTIAL_IN); + SendCommand(PARTIAL_WINDOW); + SendData(x >> 8); + SendData(x & 0xf8); // x should be the multiple of 8, the last 3 bit will always be ignored + SendData(((x & 0xf8) + w - 1) >> 8); + SendData(((x & 0xf8) + w - 1) | 0x07); + SendData(y >> 8); + SendData(y & 0xff); + SendData((y + l - 1) >> 8); + SendData((y + l - 1) & 0xff); + SendData(0x01); // Gates scan both inside and outside of the partial window. (default) + DelayMs(2); + SendCommand(DATA_START_TRANSMISSION_1); + if (buffer_black != NULL) { + for(int i = 0; i < w / 8 * l; i++) { + SendData(buffer_black[i]); + } + } + DelayMs(2); + SendCommand(DATA_START_TRANSMISSION_2); + if (buffer_red != NULL) { + for(int i = 0; i < w / 8 * l; i++) { + SendData(buffer_red[i]); + } + } + DelayMs(2); + SendCommand(PARTIAL_OUT); +} + +/** + * @brief: transmit partial data to the black part of SRAM + */ +void Epd::SetPartialWindowBlack(const unsigned char* buffer_black, int x, int y, int w, int l) +{ + SendCommand(PARTIAL_IN); + SendCommand(PARTIAL_WINDOW); + SendData(x >> 8); + SendData(x & 0xf8); // x should be the multiple of 8, the last 3 bit will always be ignored + SendData(((x & 0xf8) + w - 1) >> 8); + SendData(((x & 0xf8) + w - 1) | 0x07); + SendData(y >> 8); + SendData(y & 0xff); + SendData((y + l - 1) >> 8); + SendData((y + l - 1) & 0xff); + SendData(0x01); // Gates scan both inside and outside of the partial window. (default) + DelayMs(2); + SendCommand(DATA_START_TRANSMISSION_1); + if (buffer_black != NULL) { + for(int i = 0; i < w / 8 * l; i++) { + SendData(buffer_black[i]); + } + } + DelayMs(2); + SendCommand(PARTIAL_OUT); +} + +/** + * @brief: transmit partial data to the yellow part of SRAM + */ +void Epd::SetPartialWindowRed(const unsigned char* buffer_red, int x, int y, int w, int l) +{ + SendCommand(PARTIAL_IN); + SendCommand(PARTIAL_WINDOW); + SendData(x >> 8); + SendData(x & 0xf8); // x should be the multiple of 8, the last 3 bit will always be ignored + SendData(((x & 0xf8) + w - 1) >> 8); + SendData(((x & 0xf8) + w - 1) | 0x07); + SendData(y >> 8); + SendData(y & 0xff); + SendData((y + l - 1) >> 8); + SendData((y + l - 1) & 0xff); + SendData(0x01); // Gates scan both inside and outside of the partial window. (default) + DelayMs(2); + SendCommand(DATA_START_TRANSMISSION_2); + if (buffer_red != NULL) { + for(int i = 0; i < w / 8 * l; i++) { + SendData(buffer_red[i]); + } + } + DelayMs(2); + SendCommand(PARTIAL_OUT); +} + +/** + * @brief: refresh and displays the frame + */ +void Epd::DisplayFrame(const unsigned char* frame_buffer_black, const unsigned char* frame_buffer_red) +{ + if (frame_buffer_black != NULL) { + SendCommand(DATA_START_TRANSMISSION_1); + DelayMs(2); + for (int i = 0; i < this->width / 8 * this->height; i++) { + SendData(*(frame_buffer_black + i)); + } + DelayMs(2); + } + if (frame_buffer_red != NULL) { + SendCommand(DATA_START_TRANSMISSION_2); + DelayMs(2); + for (int i = 0; i < this->width / 8 * this->height; i++) { + SendData(*(frame_buffer_red + i)); + } + DelayMs(2); + } + SendCommand(DISPLAY_REFRESH); + WaitUntilIdle(); +} + +/** + * @brief: clear the frame data from the SRAM, this won't refresh the display + */ +void Epd::ClearFrame(void) +{ + SendCommand(DATA_START_TRANSMISSION_1); + DelayMs(2); + for(int i = 0; i < width / 8 * height; i++) { + SendData(0xFF); + } + DelayMs(2); + SendCommand(DATA_START_TRANSMISSION_2); + DelayMs(2); + for(int i = 0; i < width / 8 * height; i++) { + SendData(0xFF); + } + DelayMs(2); +} + +/** + * @brief: This displays the frame data from SRAM + */ +void Epd::DisplayFrame(void) +{ + SendCommand(DISPLAY_REFRESH); + DelayMs(100); + 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 executed if check code = 0xA5. + * You can use Epd::Reset() to awaken and use Epd::Init() to initialize. + */ +void Epd::Sleep() +{ + SendCommand(VCOM_AND_DATA_INTERVAL_SETTING); + SendData(0xF7); // border floating + SendCommand(POWER_OFF); + WaitUntilIdle(); + SendCommand(DEEP_SLEEP); + SendData(0xA5); // check code +} + +/** + * @brief: e-Paper power control + */ +void Epd::PwrOn() +{ + DigitalWrite(m_pwr, 1); +} + +void Epd::PwrOff() +{ + all_off(); +} + +/* END OF FILE */