epd2in7_V2.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /**
  2. * @filename : epd2in7_V2.cpp
  3. * @brief : Implements for e-paper library
  4. * @author : Waveshare
  5. *
  6. * Copyright (C) Waveshare September 20 2022
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documnetation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdlib.h>
  27. #include "epd2in7_V2.h"
  28. static const unsigned char LUT_DATA_4Gray[159] =
  29. {
  30. 0x40, 0x48, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  31. 0x8, 0x48, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  32. 0x2, 0x48, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  33. 0x20, 0x48, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  34. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  35. 0xA, 0x19, 0x0, 0x3, 0x8, 0x0, 0x0,
  36. 0x14, 0x1, 0x0, 0x14, 0x1, 0x0, 0x3,
  37. 0xA, 0x3, 0x0, 0x8, 0x19, 0x0, 0x0,
  38. 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
  39. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  40. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  41. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  42. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  43. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  44. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  45. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  46. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  47. 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
  48. 0x22, 0x17, 0x41, 0x0, 0x32, 0x1C
  49. };
  50. Epd::~Epd() {
  51. };
  52. Epd::Epd() {
  53. reset_pin = RST_PIN;
  54. dc_pin = DC_PIN;
  55. cs_pin = CS_PIN;
  56. busy_pin = BUSY_PIN;
  57. WIDTH = EPD_WIDTH;
  58. HEIGHT = EPD_HEIGHT;
  59. };
  60. int Epd::Init(void) {
  61. /* this calls the peripheral hardware interface, see epdif */
  62. if (IfInit() != 0) {
  63. return -1;
  64. }
  65. Reset();
  66. ReadBusy();
  67. SendCommand(0x12); //SWRESET
  68. ReadBusy();
  69. SendCommand(0x45); //set Ram-Y address start/end position
  70. SendData(0x00);
  71. SendData(0x00);
  72. SendData(0x07); //0x0107-->(263+1)=264
  73. SendData(0x01);
  74. SendCommand(0x4F); // set RAM y address count to 0;
  75. SendData(0x00);
  76. SendData(0x00);
  77. SendCommand(0x11); // data entry mode
  78. SendData(0x03);
  79. return 0;
  80. }
  81. int Epd::Init_Fast(void) {
  82. /* this calls the peripheral hardware interface, see epdif */
  83. if (IfInit() != 0) {
  84. return -1;
  85. }
  86. Reset();
  87. ReadBusy();
  88. SendCommand(0x12); //SWRESET
  89. ReadBusy();
  90. SendCommand(0x18); //Read built-in temperature sensor
  91. SendData(0x80);
  92. SendCommand(0x22); // Load temperature value
  93. SendData(0xB1);
  94. SendCommand(0x20);
  95. ReadBusy();
  96. SendCommand(0x1A); // Write to temperature register
  97. SendData(0x64);
  98. SendData(0x00);
  99. SendCommand(0x45); //set Ram-Y address start/end position
  100. SendData(0x00);
  101. SendData(0x00);
  102. SendData(0x07); //0x0107-->(263+1)=264
  103. SendData(0x01);
  104. SendCommand(0x4F); // set RAM y address count to 0;
  105. SendData(0x00);
  106. SendData(0x00);
  107. SendCommand(0x11); // data entry mode
  108. SendData(0x03);
  109. SendCommand(0x22); // Load temperature value
  110. SendData(0x91);
  111. SendCommand(0x20);
  112. ReadBusy();
  113. return 0;
  114. }
  115. void Epd::Init_4Gray(void)
  116. {
  117. Reset();
  118. ReadBusy();
  119. SendCommand(0x12); // soft reset
  120. ReadBusy();
  121. SendCommand(0x74); //set analog block control
  122. SendData(0x54);
  123. SendCommand(0x7E); //set digital block control
  124. SendData(0x3B);
  125. SendCommand(0x01); //Driver output control
  126. SendData(0x07);
  127. SendData(0x01);
  128. SendData(0x00);
  129. SendCommand(0x11); //data entry mode
  130. SendData(0x03);
  131. SendCommand(0x44); //set Ram-X address start/end position
  132. SendData(0x00);
  133. SendData(0x15); //0x15-->(21+1)*8=176
  134. SendCommand(0x45); //set Ram-Y address start/end position
  135. SendData(0x00);
  136. SendData(0x00);
  137. SendData(0x07);//0x0107-->(263+1)=264
  138. SendData(0x01);
  139. SendCommand(0x3C); //BorderWavefrom
  140. SendData(0x00);
  141. SendCommand(0x2C); //VCOM Voltage
  142. SendData(LUT_DATA_4Gray[158]); //0x1C
  143. SendCommand(0x3F); //EOPQ
  144. SendData(LUT_DATA_4Gray[153]);
  145. SendCommand(0x03); //VGH
  146. SendData(LUT_DATA_4Gray[154]);
  147. SendCommand(0x04); //
  148. SendData(LUT_DATA_4Gray[155]); //VSH1
  149. SendData(LUT_DATA_4Gray[156]); //VSH2
  150. SendData(LUT_DATA_4Gray[157]); //VSL
  151. Lut(); //LUT
  152. SendCommand(0x4E); // set RAM x address count to 0;
  153. SendData(0x00);
  154. SendCommand(0x4F); // set RAM y address count to 0X199;
  155. SendData(0x00);
  156. SendData(0x00);
  157. ReadBusy();
  158. }
  159. /**
  160. * @brief: basic function for sending commands
  161. */
  162. void Epd::SendCommand(unsigned char command) {
  163. DigitalWrite(dc_pin, LOW);
  164. SpiTransfer(command);
  165. }
  166. /**
  167. * @brief: basic function for sending data
  168. */
  169. void Epd::SendData(unsigned char data) {
  170. DigitalWrite(dc_pin, HIGH);
  171. SpiTransfer(data);
  172. }
  173. /**
  174. * @brief: Wait until the busy_pin goes HIGH
  175. */
  176. void Epd::ReadBusy(void) {
  177. Serial.print("e-Paper busy\r\n");
  178. while(DigitalRead(busy_pin) == 1) { //1: busy, 0: idle
  179. DelayMs(100);
  180. }
  181. Serial.print("e-Paper busy release\r\n");
  182. }
  183. /**
  184. * @brief: module reset.
  185. * often used to awaken the module in deep sleep,
  186. * see Epd::Sleep();
  187. */
  188. void Epd::Reset(void) {
  189. DigitalWrite(reset_pin, HIGH);
  190. DelayMs(200);
  191. DigitalWrite(reset_pin, LOW);
  192. DelayMs(2);
  193. DigitalWrite(reset_pin, HIGH);
  194. DelayMs(200);
  195. }
  196. /**
  197. * @brief: set the look-up tables
  198. */
  199. void Epd::Lut(void) {
  200. unsigned int count;
  201. SendCommand(0x32); //vcom
  202. for(count = 0; count < 153; count++) {
  203. SendData(LUT_DATA_4Gray[count]);
  204. }
  205. }
  206. /******************************************************************************
  207. function : Turn on display
  208. parameter:
  209. ******************************************************************************/
  210. void Epd::TurnOnDisplay(void)
  211. {
  212. SendCommand(0x22); //Display Update Control
  213. SendData(0xF7);
  214. SendCommand(0x20); //Activate Display Update Sequence
  215. ReadBusy();
  216. }
  217. void Epd::TurnOnDisplay_Fast(void)
  218. {
  219. SendCommand(0x22); //Display Update Control
  220. SendData(0xC7);
  221. SendCommand(0x20); //Activate Display Update Sequence
  222. ReadBusy();
  223. }
  224. void Epd::TurnOnDisplay_Partial(void)
  225. {
  226. SendCommand(0x22);
  227. SendData(0xFF);
  228. SendCommand(0x20);
  229. ReadBusy();
  230. }
  231. void Epd::TurnOnDisplay_4GRAY(void)
  232. {
  233. SendCommand(0x22);
  234. SendData(0xC7);
  235. SendCommand(0x20);
  236. ReadBusy();
  237. }
  238. /******************************************************************************
  239. function : Clear screen
  240. parameter:
  241. ******************************************************************************/
  242. void Epd::Clear(void)
  243. {
  244. unsigned int Width, Height;
  245. Width = (WIDTH % 8 == 0)? (WIDTH / 8 ): (WIDTH / 8 + 1);
  246. Height = HEIGHT;
  247. SendCommand(0x24);
  248. for (unsigned int j = 0; j < Height; j++) {
  249. for (unsigned int i = 0; i < Width; i++) {
  250. SendData(0XFF);
  251. }
  252. }
  253. TurnOnDisplay();
  254. }
  255. /******************************************************************************
  256. function : Sends the image buffer in RAM to e-Paper and displays
  257. parameter:
  258. ******************************************************************************/
  259. void Epd::Display(const unsigned char* Image)
  260. {
  261. unsigned int Width, Height;
  262. Width = (WIDTH % 8 == 0)? (WIDTH / 8 ): (WIDTH / 8 + 1);
  263. Height = HEIGHT;
  264. SendCommand(0x24);
  265. for (unsigned int j = 0; j < Height; j++) {
  266. for (unsigned int i = 0; i < Width; i++) {
  267. SendData(pgm_read_byte(&Image[i + j * Width]));
  268. }
  269. }
  270. TurnOnDisplay();
  271. }
  272. void Epd::Display_Fast(const unsigned char* Image)
  273. {
  274. unsigned int Width, Height;
  275. Width = (WIDTH % 8 == 0)? (WIDTH / 8 ): (WIDTH / 8 + 1);
  276. Height = HEIGHT;
  277. SendCommand(0x24);
  278. for (unsigned int j = 0; j < Height; j++) {
  279. for (unsigned int i = 0; i < Width; i++) {
  280. SendData(pgm_read_byte(&Image[i + j * Width]));
  281. }
  282. }
  283. TurnOnDisplay_Fast();
  284. }
  285. void Epd::Display_Base(const unsigned char* Image)
  286. {
  287. unsigned int Width, Height;
  288. Width = (WIDTH % 8 == 0)? (WIDTH / 8 ): (WIDTH / 8 + 1);
  289. Height = HEIGHT;
  290. SendCommand(0x24); //Write Black and White image to RAM
  291. for (unsigned int j = 0; j < Height; j++) {
  292. for (unsigned int i = 0; i < Width; i++) {
  293. SendData(pgm_read_byte(&Image[i + j * Width]));
  294. }
  295. }
  296. SendCommand(0x26); //Write Black and White image to RAM
  297. for (unsigned int j = 0; j < Height; j++) {
  298. for (unsigned int i = 0; i < Width; i++) {
  299. SendData(pgm_read_byte(&Image[i + j * Width]));
  300. }
  301. }
  302. TurnOnDisplay();
  303. }
  304. void Epd::Display_Base_color(unsigned char color)
  305. {
  306. unsigned int Width, Height;
  307. Width = (WIDTH % 8 == 0)? (WIDTH / 8 ): (WIDTH / 8 + 1);
  308. Height = HEIGHT;
  309. SendCommand(0x24); //Write Black and White image to RAM
  310. for (unsigned int j = 0; j < Height; j++) {
  311. for (unsigned int i = 0; i < Width; i++) {
  312. SendData(color);
  313. }
  314. }
  315. SendCommand(0x26); //Write Black and White image to RAM
  316. for (unsigned int j = 0; j < Height; j++) {
  317. for (unsigned int i = 0; i < Width; i++) {
  318. SendData(color);
  319. }
  320. }
  321. // TurnOnDisplay();
  322. }
  323. void Epd::Display_Partial(unsigned char* Image, unsigned int Xstart, unsigned int Ystart, unsigned int Xend, unsigned int Yend)
  324. {
  325. unsigned int i, Width;
  326. unsigned int IMAGE_COUNTER;
  327. if((Xstart % 8 + Xend % 8 == 8 && Xstart % 8 > Xend % 8) || Xstart % 8 + Xend % 8 == 0 || (Xend - Xstart)%8 == 0)
  328. {
  329. Xstart = Xstart / 8 ;
  330. Xend = Xend / 8;
  331. }
  332. else
  333. {
  334. Xstart = Xstart / 8 ;
  335. Xend = Xend % 8 == 0 ? Xend / 8 : Xend / 8 + 1;
  336. }
  337. Width = Xend - Xstart;
  338. IMAGE_COUNTER = Width * (Yend-Ystart);
  339. Serial.println(IMAGE_COUNTER);
  340. Xend -= 1;
  341. Yend -= 1;
  342. //Reset
  343. Reset();
  344. SendCommand(0x3C); //BorderWavefrom
  345. SendData(0x80);
  346. //
  347. SendCommand(0x44); // set RAM x address start/end, in page 35
  348. SendData(Xstart & 0xff); // RAM x address start at 00h;
  349. SendData(Xend & 0xff); // RAM x address end at 0fh(15+1)*8->128
  350. SendCommand(0x45); // set RAM y address start/end, in page 35
  351. SendData(Ystart & 0xff); // RAM y address start at 0127h;
  352. SendData((Ystart>>8) & 0x01); // RAM y address start at 0127h;
  353. SendData(Yend & 0xff); // RAM y address end at 00h;
  354. SendData((Yend>>8) & 0x01);
  355. SendCommand(0x4E); // set RAM x address count to 0;
  356. SendData(Xstart & 0xff);
  357. SendCommand(0x4F); // set RAM y address count to 0X127;
  358. SendData(Ystart & 0xff);
  359. SendData((Ystart>>8) & 0x01);
  360. SendCommand(0x24); //Write Black and White image to RAM
  361. for (i = 0; i < IMAGE_COUNTER; i++) {
  362. SendData(Image[i]);
  363. }
  364. TurnOnDisplay_Partial();
  365. }
  366. void Epd::Display_Partial_Not_refresh(unsigned char* Image, unsigned int Xstart, unsigned int Ystart, unsigned int Xend, unsigned int Yend)
  367. {
  368. unsigned int i, Width;
  369. unsigned int IMAGE_COUNTER;
  370. if((Xstart % 8 + Xend % 8 == 8 && Xstart % 8 > Xend % 8) || Xstart % 8 + Xend % 8 == 0 || (Xend - Xstart)%8 == 0)
  371. {
  372. Xstart = Xstart / 8 ;
  373. Xend = Xend / 8;
  374. }
  375. else
  376. {
  377. Xstart = Xstart / 8 ;
  378. Xend = Xend % 8 == 0 ? Xend / 8 : Xend / 8 + 1;
  379. }
  380. Width = Xend - Xstart;
  381. IMAGE_COUNTER = Width * (Yend-Ystart);
  382. Serial.println(IMAGE_COUNTER);
  383. Xend -= 1;
  384. Yend -= 1;
  385. //Reset
  386. Reset();
  387. SendCommand(0x3C); //BorderWavefrom
  388. SendData(0x80);
  389. //
  390. SendCommand(0x44); // set RAM x address start/end, in page 35
  391. SendData(Xstart & 0xff); // RAM x address start at 00h;
  392. SendData(Xend & 0xff); // RAM x address end at 0fh(15+1)*8->128
  393. SendCommand(0x45); // set RAM y address start/end, in page 35
  394. SendData(Ystart & 0xff); // RAM y address start at 0127h;
  395. SendData((Ystart>>8) & 0x01); // RAM y address start at 0127h;
  396. SendData(Yend & 0xff); // RAM y address end at 00h;
  397. SendData((Yend>>8) & 0x01);
  398. SendCommand(0x4E); // set RAM x address count to 0;
  399. SendData(Xstart & 0xff);
  400. SendCommand(0x4F); // set RAM y address count to 0X127;
  401. SendData(Ystart & 0xff);
  402. SendData((Ystart>>8) & 0x01);
  403. SendCommand(0x24); //Write Black and White image to RAM
  404. for (i = 0; i < IMAGE_COUNTER; i++) {
  405. SendData(Image[i]);
  406. }
  407. // TurnOnDisplay_Partial();
  408. }
  409. void Epd::Display4Gray(const unsigned char *Image)
  410. {
  411. int i,j,k;
  412. unsigned char temp1,temp2,temp3;
  413. SendCommand(0x24);
  414. for(i=0;i<5808;i++) //5808*4 46464
  415. {
  416. temp3=0;
  417. for(j=0;j<2;j++)
  418. {
  419. temp1 = pgm_read_byte(&Image[i*2+j]);
  420. for(k=0;k<2;k++)
  421. {
  422. temp2 = temp1&0xC0 ;
  423. if(temp2 == 0xC0)
  424. temp3 |= 0x00;//white
  425. else if(temp2 == 0x00)
  426. temp3 |= 0x01; //black
  427. else if(temp2 == 0x80)
  428. temp3 |= 0x01; //gray1
  429. else //0x40
  430. temp3 |= 0x00; //gray2
  431. temp3 <<= 1;
  432. temp1 <<= 2;
  433. temp2 = temp1&0xC0 ;
  434. if(temp2 == 0xC0) //white
  435. temp3 |= 0x00;
  436. else if(temp2 == 0x00) //black
  437. temp3 |= 0x01;
  438. else if(temp2 == 0x80)
  439. temp3 |= 0x01; //gray1
  440. else //0x40
  441. temp3 |= 0x00; //gray2
  442. if(j!=1 || k!=1)
  443. temp3 <<= 1;
  444. temp1 <<= 2;
  445. }
  446. }
  447. SendData(temp3);
  448. }
  449. // new data
  450. SendCommand(0x26);
  451. for(i=0;i<5808;i++) //5808*4 46464
  452. {
  453. temp3=0;
  454. for(j=0;j<2;j++)
  455. {
  456. temp1 = pgm_read_byte(&Image[i*2+j]);
  457. for(k=0;k<2;k++)
  458. {
  459. temp2 = temp1&0xC0 ;
  460. if(temp2 == 0xC0)
  461. temp3 |= 0x00;//white
  462. else if(temp2 == 0x00)
  463. temp3 |= 0x01; //black
  464. else if(temp2 == 0x80)
  465. temp3 |= 0x00; //gray1
  466. else //0x40
  467. temp3 |= 0x01; //gray2
  468. temp3 <<= 1;
  469. temp1 <<= 2;
  470. temp2 = temp1&0xC0 ;
  471. if(temp2 == 0xC0) //white
  472. temp3 |= 0x00;
  473. else if(temp2 == 0x00) //black
  474. temp3 |= 0x01;
  475. else if(temp2 == 0x80)
  476. temp3 |= 0x00; //gray1
  477. else //0x40
  478. temp3 |= 0x01; //gray2
  479. if(j!=1 || k!=1)
  480. temp3 <<= 1;
  481. temp1 <<= 2;
  482. }
  483. }
  484. SendData(temp3);
  485. }
  486. TurnOnDisplay_4GRAY();
  487. }
  488. /**
  489. * @brief: After this command is transmitted, the chip would enter the deep-sleep mode to save power.
  490. * The deep sleep mode would return to standby by hardware reset. The only one parameter is a
  491. * check code, the command would be executed if check code = 0xA5.
  492. * You can use Epd::Reset() to awaken and use Epd::Init() to initialize.
  493. */
  494. void Epd::Sleep() {
  495. SendCommand(0X10);
  496. SendData(0x01);
  497. }