| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593 |
- // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
- // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
- //
- // GxEPD2_it60 class is based on Demo Example from Waveshare for Raspberry PI https://github.com/waveshare/IT8951/archive/master.zip
- // Controller: IT8951 : https://www.waveshare.com/w/upload/1/18/IT8951_D_V0.2.4.3_20170728.pdf
- //
- // The GxEPD2_it60 driver class supports the Waveshare e-Paper IT8951 Driver HAT connected with SPI for the ED060SCT 6" e-paper panel (parallel IF)
- // https://www.waveshare.com/product/mini-pc/raspberry-pi/hats/6inch-e-paper-hat.htm
- // This Driver HAT requires 5V power supply but works with 3.3V data lines; requires both MOSI and MISO SPI lines.
- //
- // Author: Jean-Marc Zingg
- //
- // Version: see library.properties
- //
- // Library: https://github.com/ZinggJM/GxEPD2
- #include "GxEPD2_it60.h"
- #define VCOM 1500 //e.g. -1.53 = 1530 = 0x5FA
- //Built in I80 Command Code
- #define IT8951_TCON_SYS_RUN 0x0001
- #define IT8951_TCON_STANDBY 0x0002
- #define IT8951_TCON_SLEEP 0x0003
- #define IT8951_TCON_REG_RD 0x0010
- #define IT8951_TCON_REG_WR 0x0011
- #define IT8951_TCON_LD_IMG 0x0020
- #define IT8951_TCON_LD_IMG_AREA 0x0021
- #define IT8951_TCON_LD_IMG_END 0x0022
- //I80 User defined command code
- #define USDEF_I80_CMD_DPY_AREA 0x0034
- #define USDEF_I80_CMD_GET_DEV_INFO 0x0302
- #define USDEF_I80_CMD_DPY_BUF_AREA 0x0037
- #define USDEF_I80_CMD_VCOM 0x0039
- //Rotate mode
- #define IT8951_ROTATE_0 0
- #define IT8951_ROTATE_90 1
- #define IT8951_ROTATE_180 2
- #define IT8951_ROTATE_270 3
- //Pixel mode , BPP - Bit per Pixel
- #define IT8951_2BPP 0
- #define IT8951_3BPP 1
- #define IT8951_4BPP 2
- #define IT8951_8BPP 3
- //Endian Type
- #define IT8951_LDIMG_L_ENDIAN 0
- #define IT8951_LDIMG_B_ENDIAN 1
- #define SYS_REG_BASE 0x0000
- #define I80CPCR (SYS_REG_BASE + 0x04)
- #define MCSR_BASE_ADDR 0x0200
- #define LISAR (MCSR_BASE_ADDR + 0x0008)
- GxEPD2_it60::GxEPD2_it60(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
- GxEPD2_EPD(cs, dc, rst, busy, LOW, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate),
- _spi_settings(24000000, MSBFIRST, SPI_MODE0),
- _spi_settings_for_read(1000000, MSBFIRST, SPI_MODE0)
- {
- }
- void GxEPD2_it60::init(uint32_t serial_diag_bitrate)
- {
- init(serial_diag_bitrate, true, false);
- }
- void GxEPD2_it60::init(uint32_t serial_diag_bitrate, bool initial, bool pulldown_rst_mode)
- {
- GxEPD2_EPD::init(serial_diag_bitrate, initial, pulldown_rst_mode);
- // we need a long reset pulse
- if (_rst >= 0)
- {
- digitalWrite(_rst, LOW);
- delay(200);
- digitalWrite(_rst, HIGH);
- delay(200);
- _waitWhileBusy("init reset_to_ready", reset_to_ready_time);
- }
- _writeCommand16(USDEF_I80_CMD_GET_DEV_INFO);
- _waitWhileBusy("GetIT8951SystemInfo", power_on_time);
- _readData16((uint16_t*)&IT8951DevInfo, sizeof(IT8951DevInfo) / 2);
- if (_diag_enabled)
- {
- //Show Device information of IT8951
- printf("Panel(W,H) = (%d,%d)\r\n",
- IT8951DevInfo.usPanelW, IT8951DevInfo.usPanelH );
- printf("Image Buffer Address = %X\r\n",
- IT8951DevInfo.usImgBufAddrL | (IT8951DevInfo.usImgBufAddrH << 16));
- //Show Firmware and LUT Version
- printf("FW Version = %s\r\n", (uint8_t*)IT8951DevInfo.usFWVersion);
- printf("LUT Version = %s\r\n", (uint8_t*)IT8951DevInfo.usLUTVersion);
- }
- //Set to Enable I80 Packed mode
- _IT8951WriteReg(I80CPCR, 0x0001);
- if (VCOM != _IT8951GetVCOM())
- {
- _IT8951SetVCOM(VCOM);
- printf("VCOM = -%.02fV\n", (float)_IT8951GetVCOM() / 1000);
- }
- printf("VCOM = -%.02fV\n", (float)_IT8951GetVCOM() / 1000);
- }
- void GxEPD2_it60::clearScreen(uint8_t value)
- {
- if (_initial) _Init_Full();
- else _Init_Part();
- _initial = false;
- _setPartialRamArea(0, 0, WIDTH, HEIGHT);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x0000); // preamble for write data
- _waitWhileBusy2("clearScreen preamble", default_wait_time);
- for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT); i++)
- {
- SPI.transfer(value);
- #if defined(ESP8266) || defined(ESP32)
- if (0 == i % 10000) yield();
- #endif
- }
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- _writeCommand16(IT8951_TCON_LD_IMG_END);
- _waitWhileBusy2("clearScreen load end", default_wait_time);
- _refresh(0, 0, WIDTH, HEIGHT, false);
- }
- void GxEPD2_it60::writeScreenBuffer(uint8_t value)
- {
- if (_initial) clearScreen(value);
- else _writeScreenBuffer(value);
- }
- void GxEPD2_it60::_writeScreenBuffer(uint8_t value)
- {
- if (!_using_partial_mode) _Init_Part();
- _setPartialRamArea(0, 0, WIDTH, HEIGHT);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x0000); // preamble for write data
- _waitWhileBusy2("clearScreen preamble", default_wait_time);
- for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT); i++)
- {
- SPI.transfer(value);
- #if defined(ESP8266) || defined(ESP32)
- if (0 == i % 10000) yield();
- #endif
- }
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- _writeCommand16(IT8951_TCON_LD_IMG_END);
- _waitWhileBusy2("_writeScreenBuffer load end", default_wait_time);
- }
- void GxEPD2_it60::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
- {
- delay(1); // yield() to avoid WDT on ESP8266 and ESP32
- int16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
- x -= x % 8; // byte boundary
- w = wb * 8; // byte boundary
- int16_t x1 = x < 0 ? 0 : x; // limit
- int16_t y1 = y < 0 ? 0 : y; // limit
- int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
- int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
- int16_t dx = x1 - x;
- int16_t dy = y1 - y;
- w1 -= dx;
- h1 -= dy;
- if ((w1 <= 0) || (h1 <= 0)) return;
- if (!_using_partial_mode) _Init_Part();
- _setPartialRamArea(x1, y1, w1, h1);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x0000); // preamble for write data
- _waitWhileBusy2("writeImage preamble", default_wait_time);
- for (int16_t i = 0; i < h1; i++)
- {
- for (int16_t j = 0; j < w1 / 8; j++)
- {
- uint8_t data;
- // use wb, h of bitmap for index!
- uint32_t idx = mirror_y ? uint32_t(j + dx / 8) + uint32_t((h - 1 - (i + dy))) * uint32_t(wb) : uint32_t(j + dx / 8) + uint32_t(i + dy) * uint32_t(wb);
- if (pgm)
- {
- #if defined(__AVR) || defined(ESP8266) || defined(ESP32)
- data = pgm_read_byte(&bitmap[idx]);
- #else
- data = bitmap[idx];
- #endif
- }
- else
- {
- data = bitmap[idx];
- }
- if (invert) data = ~data;
- _send8pixel(~data);
- }
- #if defined(ESP8266) || defined(ESP32)
- yield();
- #endif
- }
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- _writeCommand16(IT8951_TCON_LD_IMG_END);
- _waitWhileBusy2("writeImage load end", default_wait_time);
- delay(1); // yield() to avoid WDT on ESP8266 and ESP32
- }
- void GxEPD2_it60::writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
- {
- if (black)
- {
- writeImage(black, x, y, w, h, invert, mirror_y, pgm);
- }
- }
- void GxEPD2_it60::writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
- {
- if (data1)
- {
- delay(1); // yield() to avoid WDT on ESP8266 and ESP32
- int16_t x1 = x < 0 ? 0 : x; // limit
- int16_t y1 = y < 0 ? 0 : y; // limit
- int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
- int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
- int16_t dx = x1 - x;
- int16_t dy = y1 - y;
- w1 -= dx;
- h1 -= dy;
- if ((w1 <= 0) || (h1 <= 0)) return;
- if (!_using_partial_mode) _Init_Part();
- _setPartialRamArea(x1, y1, w1, h1);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x0000); // preamble for write data
- _waitWhileBusy2("writeNative preamble", default_wait_time);
- for (int16_t i = 0; i < h1; i++)
- {
- for (int16_t j = 0; j < w1; j++)
- {
- uint8_t data;
- // use w, h of bitmap for index!
- uint32_t idx = mirror_y ? uint32_t(j + dx) + uint32_t((h - 1 - (i + dy))) * uint32_t(w) : uint32_t(j + dx) + uint32_t(i + dy) * uint32_t(w);
- if (pgm)
- {
- #if defined(__AVR) || defined(ESP8266) || defined(ESP32)
- data = pgm_read_byte(&data1[idx]);
- #else
- data = data1[idx];
- #endif
- }
- else
- {
- data = data1[idx];
- }
- if (invert) data = ~data;
- SPI.transfer(data);
- }
- #if defined(ESP8266) || defined(ESP32)
- yield();
- #endif
- }
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- _writeCommand16(IT8951_TCON_LD_IMG_END);
- _waitWhileBusy2("writeNative load end", default_wait_time);
- delay(1); // yield() to avoid WDT on ESP8266 and ESP32
- }
- }
- void GxEPD2_it60::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
- {
- writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
- _refresh(x, y, w, h, true);
- }
- void GxEPD2_it60::drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
- {
- writeImage(black, color, x, y, w, h, invert, mirror_y, pgm);
- _refresh(x, y, w, h, true);
- }
- void GxEPD2_it60::drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
- {
- writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
- _refresh(x, y, w, h, false);
- }
- void GxEPD2_it60::refresh(bool partial_update_mode)
- {
- _refresh(0, 0, WIDTH, HEIGHT, partial_update_mode);
- }
- void GxEPD2_it60::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
- {
- _refresh(x, y, w, h, true);
- }
- void GxEPD2_it60::_refresh(int16_t x, int16_t y, int16_t w, int16_t h, bool partial_update_mode)
- {
- //x -= x % 8; // byte boundary
- //w -= x % 8; // byte boundary
- int16_t x1 = x < 0 ? 0 : x; // limit
- int16_t y1 = y < 0 ? 0 : y; // limit
- int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
- int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
- w1 -= x1 - x;
- h1 -= y1 - y;
- //Send I80 Display Command (User defined command of IT8951)
- _writeCommand16(USDEF_I80_CMD_DPY_AREA); //0x0034
- _waitWhileBusy2("refresh cmd", refresh_cmd_time);
- //Write arguments
- _writeData16(x1);
- _waitWhileBusy2("refresh x", refresh_par_time);
- _writeData16(y1);
- _waitWhileBusy2("refresh y", refresh_par_time);
- _writeData16(w1);
- _waitWhileBusy2("refresh w", refresh_par_time);
- _writeData16(h1);
- _waitWhileBusy2("refresh h", refresh_par_time);
- _writeData16(partial_update_mode ? 1 : 2); // mode
- _waitWhileBusy("refresh", full_refresh_time);
- }
- void GxEPD2_it60::powerOff(void)
- {
- _PowerOff();
- }
- void GxEPD2_it60::hibernate()
- {
- if (_power_is_on) _PowerOff();
- if (_rst >= 0)
- {
- // this does not work, does not reduce power, uses more than in stand by mode
- //delay(1000);
- //_IT8951Sleep();
- //delay(1000);
- //_hibernating = true;
- }
- }
- void GxEPD2_it60::_send8pixel(uint8_t data)
- {
- for (uint8_t j = 0; j < 8; j++)
- {
- SPI.transfer(data & 0x80 ? 0x00 : 0xFF);
- data <<= 1;
- }
- }
- void GxEPD2_it60::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
- {
- //_IT8951WriteReg(LISAR + 2 , IT8951DevInfo.usImgBufAddrH);
- //_IT8951WriteReg(LISAR , IT8951DevInfo.usImgBufAddrL);
- uint16_t usArg[5];
- //usArg[0] = (IT8951_LDIMG_L_ENDIAN << 8 ) | (IT8951_8BPP << 4) | (IT8951_ROTATE_0);
- usArg[0] = (IT8951_LDIMG_B_ENDIAN << 8 ) | (IT8951_8BPP << 4) | (IT8951_ROTATE_0);
- usArg[1] = x;
- usArg[2] = y;
- usArg[3] = w;
- usArg[4] = h;
- _writeCommandData16(IT8951_TCON_LD_IMG_AREA , usArg , 5);
- }
- void GxEPD2_it60::_PowerOn()
- {
- if (!_power_is_on)
- {
- _IT8951SystemRun();
- _waitWhileBusy("_PowerOn", power_on_time);
- }
- _power_is_on = true;
- }
- void GxEPD2_it60::_PowerOff()
- {
- _IT8951StandBy();
- _waitWhileBusy("_PowerOff", power_off_time);
- _power_is_on = false;
- _using_partial_mode = false;
- }
- void GxEPD2_it60::_InitDisplay()
- {
- // we need a long reset pulse
- if (_hibernating && (_rst >= 0))
- {
- digitalWrite(_rst, LOW);
- delay(200);
- digitalWrite(_rst, HIGH);
- delay(200);
- }
- }
- void GxEPD2_it60::_Init_Full()
- {
- _InitDisplay();
- _PowerOn();
- _using_partial_mode = false;
- }
- void GxEPD2_it60::_Init_Part()
- {
- _InitDisplay();
- _PowerOn();
- _using_partial_mode = true;
- }
- void GxEPD2_it60::_waitWhileBusy2(const char* comment, uint16_t busy_time)
- {
- if (_busy >= 0)
- {
- unsigned long start = micros();
- while (1)
- {
- if (digitalRead(_busy) != _busy_level) break;
- delay(1);
- if (micros() - start > _busy_timeout)
- {
- Serial.println("Busy Timeout!");
- break;
- }
- }
- if (comment)
- {
- #if !defined(DISABLE_DIAGNOSTIC_OUTPUT)
- if (_diag_enabled)
- {
- unsigned long elapsed = micros() - start;
- if (elapsed > diag_min_time * 1000)
- {
- Serial.print(comment);
- Serial.print(" : ");
- Serial.println(elapsed);
- }
- }
- #endif
- }
- (void) start;
- }
- else delay(busy_time);
- }
- uint16_t GxEPD2_it60::_transfer16(uint16_t value)
- {
- uint16_t rv = SPI.transfer(value >> 8) << 8;
- return (rv | SPI.transfer(value));
- }
- void GxEPD2_it60::_writeCommand16(uint16_t c)
- {
- String s = String("_writeCommand16(0x") + String(c, HEX) + String(")");
- _waitWhileBusy2(s.c_str(), default_wait_time);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x6000); // preamble for write command
- _waitWhileBusy2("_writeCommand16 preamble", default_wait_time);
- _transfer16(c);
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- //_waitWhileBusy(s.c_str(), default_wait_time);
- }
- void GxEPD2_it60::_writeData16(uint16_t d)
- {
- _waitWhileBusy2("_writeData16", default_wait_time);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x0000); // preamble for write data
- _waitWhileBusy2("_writeData16 preamble", default_wait_time);
- _transfer16(d);
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- }
- void GxEPD2_it60::_writeData16(const uint16_t* d, uint32_t n)
- {
- _waitWhileBusy2("_writeData16", default_wait_time);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x0000); // preamble for write data
- _waitWhileBusy2("_writeData16 preamble", default_wait_time);
- for (uint32_t i = 0; i < n; i++)
- {
- _transfer16(*d++);
- }
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- }
- uint16_t GxEPD2_it60::_readData16()
- {
- _waitWhileBusy2("_readData16", default_wait_time);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x1000); // preamble for read data
- _waitWhileBusy2("_readData16 preamble", default_wait_time);
- _transfer16(0); // dummy
- _waitWhileBusy2("_readData16 dummy", default_wait_time);
- uint16_t rv = _transfer16(0);
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- return rv;
- }
- void GxEPD2_it60::_readData16(uint16_t* d, uint32_t n)
- {
- _waitWhileBusy2("_readData16", default_wait_time);
- SPI.beginTransaction(_spi_settings);
- if (_cs >= 0) digitalWrite(_cs, LOW);
- _transfer16(0x1000); // preamble for read data
- _waitWhileBusy2("_readData16 preamble", default_wait_time);
- _transfer16(0); // dummy
- _waitWhileBusy2("_readData16 dummy", default_wait_time);
- for (uint32_t i = 0; i < n; i++)
- {
- *d++ = _transfer16(0);
- //_waitWhileBusy("_readData16 data", default_wait_time);
- }
- if (_cs >= 0) digitalWrite(_cs, HIGH);
- SPI.endTransaction();
- }
- void GxEPD2_it60::_writeCommandData16(uint16_t c, const uint16_t* d, uint16_t n)
- {
- _writeCommand16(c);
- for (uint16_t i = 0; i < n; i++)
- {
- _writeData16(d[i]);
- }
- }
- void GxEPD2_it60::_IT8951SystemRun()
- {
- _writeCommand16(IT8951_TCON_SYS_RUN);
- }
- void GxEPD2_it60::_IT8951StandBy()
- {
- _writeCommand16(IT8951_TCON_STANDBY);
- }
- void GxEPD2_it60::_IT8951Sleep()
- {
- _writeCommand16(IT8951_TCON_SLEEP);
- }
- uint16_t GxEPD2_it60::_IT8951ReadReg(uint16_t usRegAddr)
- {
- uint16_t usData;
- //Send Cmd and Register Address
- _writeCommand16(IT8951_TCON_REG_RD);
- _writeData16(usRegAddr);
- //Read data from Host Data bus
- usData = _readData16();
- return usData;
- }
- void GxEPD2_it60::_IT8951WriteReg(uint16_t usRegAddr, uint16_t usValue)
- {
- //Send Cmd , Register Address and Write Value
- _writeCommand16(IT8951_TCON_REG_WR);
- _writeData16(usRegAddr);
- _writeData16(usValue);
- }
- uint16_t GxEPD2_it60::_IT8951GetVCOM(void)
- {
- uint16_t vcom;
- _writeCommand16(USDEF_I80_CMD_VCOM);
- _waitWhileBusy2("_IT8951GetVCOM", default_wait_time);
- _writeData16(0);
- //Read data from Host Data bus
- vcom = _readData16();
- return vcom;
- }
- void GxEPD2_it60::_IT8951SetVCOM(uint16_t vcom)
- {
- _writeCommand16(USDEF_I80_CMD_VCOM);
- _waitWhileBusy2("_IT8951SetVCOM", default_wait_time);
- _writeData16(1);
- //Read data from Host Data bus
- _writeData16(vcom);
- _waitWhileBusy2("_IT8951SetVCOM", set_vcom_time);
- }
|