1 // Copyright 2013 Pervasive Displays, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, 10 // software distributed under the License is distributed on an 11 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 // express or implied. See the License for the specific language 13 // governing permissions and limitations under the License. 14 15 /****************************************************************************** 16 * Includes 17 *****************************************************************************/ 18 //#include "driver_config.h" 19 //#include "target_config.h" 20 //#include "type.h" 21 //#include "gpio.h" 22 #include "Display_COG_Process.h" 23 #include "Display_Hardware_Driver.h" 24 #include "Display_Controller.h" 25 26 27 /****************************************************************************** 28 * Defines and typedefs 29 *****************************************************************************/ 30 #define _GaugeFrameTimeMark 0 31 32 const COG_Parameters_t COG_Parameters[3]= { 33 { //for 1.44" 34 {0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0x00}, 35 0x03, 36 (128/8), 37 96, 38 (((128+96)*2)/8), 39 (43), 40 480 41 }, 42 { //for 2.0" 43 {0x00,0x00,0x00,0x00,0x01,0xFF,0xE0,0x00}, 44 0x03, 45 (200/8), 46 96, 47 (((200+96)*2)/8)+1, 48 (53), 49 480 50 }, 51 { //for 2.7" 52 {0x00,0x00,0x00,0x7F,0xFF,0xFE,0x00,0x00}, 53 0x00, 54 (264/8), 55 176, 56 (((264+176)*2)/8)+1, 57 105, 58 630 59 }, 60 }; 61 62 const uint8_t ScanTable[4] = {0xC0, 0x30, 0x0C, 0x03}; 63 64 65 /****************************************************************************** 66 * Local variables 67 *****************************************************************************/ 68 static uint32_t StageTime = 480; 69 static COG_LineDataPacket_t COG_Line; 70 static uint16_t EPD_Type_Index = 0; 71 static uint16_t cnt = 0; 72 static uint32_t Currentframe; 73 static uint8_t *DataLineEven; 74 static uint8_t *DataLineOdd; 75 static uint8_t *DataLineScan; 76 static uint8_t *DisplayOrgPtr; 77 78 79 /****************************************************************************** 80 * Local functions 81 *****************************************************************************/ 82 static void SetTemperature_Factor(uint8_t EPD_Type_Index) 83 { 84 int16_t Temperature; 85 86 //Get current temperature 87 Temperature = epd_get_temperature(); 88 89 if (Temperature < -10) 90 { 91 StageTime = COG_Parameters[EPD_Type_Index].StageTime * 17; 92 } 93 else if (Temperature < -5) 94 { 95 StageTime = COG_Parameters[EPD_Type_Index].StageTime * 12; 96 } 97 else if (Temperature < 5) 98 { 99 StageTime = COG_Parameters[EPD_Type_Index].StageTime * 8; 100 } 101 else if (Temperature < 10) 102 { 103 StageTime = COG_Parameters[EPD_Type_Index].StageTime * 4; 104 } 105 else if (Temperature < 15) 106 { 107 StageTime = COG_Parameters[EPD_Type_Index].StageTime * 3; 108 } 109 else if (Temperature < 20) 110 { 111 StageTime = COG_Parameters[EPD_Type_Index].StageTime * 2; 112 } 113 else if (Temperature < 40) 114 { 115 StageTime = COG_Parameters[EPD_Type_Index].StageTime * 1; 116 } 117 else 118 { 119 StageTime = (COG_Parameters[EPD_Type_Index].StageTime * 7)/10; 120 } 121 } 122 123 static void Driver_TypeSelect(uint8_t typeIndex) 124 { 125 switch(typeIndex) 126 { 127 case EPDType_144: 128 DataLineEven=&COG_Line.LineDatas.COG_144LineData.Even[0]; 129 DataLineOdd=&COG_Line.LineDatas.COG_144LineData.Odd[0]; 130 DataLineScan=&COG_Line.LineDatas.COG_144LineData.Scan[0]; 131 break; 132 case EPDType_200: 133 DataLineEven=&COG_Line.LineDatas.COG_20LineData.Even[0]; 134 DataLineOdd=&COG_Line.LineDatas.COG_20LineData.Odd[0]; 135 DataLineScan=&COG_Line.LineDatas.COG_20LineData.Scan[0]; 136 break; 137 case EPDType_270: 138 DataLineEven=&COG_Line.LineDatas.COG_27LineData.Even[0]; 139 DataLineOdd=&COG_Line.LineDatas.COG_27LineData.Odd[0]; 140 DataLineScan=&COG_Line.LineDatas.COG_27LineData.Scan[0]; 141 break; 142 } 143 } 144 145 //#pragma GCC optimize ("-O3") 146 static void Display_Stage_1 (uint8_t *PreviousPicture) 147 { 148 uint16_t i,j,k; // general counters 149 uint8_t TempByte; // Temporary storage for image data check 150 uint16_t StartClock; 151 #ifdef DISPLAY_180_DEGREE 152 uint8_t *DataLinePrt; 153 DisplayOrgPtr = (PreviousPicture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL)); 154 #else 155 DisplayOrgPtr = PreviousPicture; 156 #endif 157 Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime; 158 //TestPinTrigger(); 159 cnt = 0; 160 StartClock = epd_GetCurrentTimeTick(); 161 do 162 { 163 // TestPin2Trigger(); 164 PreviousPicture = DisplayOrgPtr; 165 #ifdef DISPLAY_180_DEGREE 166 DataLinePrt = PreviousPicture; 167 #endif 168 for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line 169 { 170 // SPI (0x04, ...) 171 epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel); 172 k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1; 173 for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // check every bit in the line 174 { 175 TempByte = (*PreviousPicture++); 176 #ifdef DISPLAY_180_DEGREE 177 DataLineEven[j] = ((TempByte & 0x80) ? BLACK3 : WHITE3) 178 | ((TempByte & 0x20) ? BLACK2 : WHITE2) 179 | ((TempByte & 0x08) ? BLACK1 : WHITE1) 180 | ((TempByte & 0x02) ? BLACK0 : WHITE0); 181 182 DataLineOdd[k--] = ((TempByte & 0x01) ? BLACK3 : WHITE3) 183 | ((TempByte & 0x04) ? BLACK2 : WHITE2) 184 | ((TempByte & 0x10) ? BLACK1 : WHITE1) 185 | ((TempByte & 0x40) ? BLACK0 : WHITE0); 186 DataLinePrt--; 187 #else 188 DataLineOdd[j] = ((TempByte & 0x80) ? BLACK3 : WHITE3) 189 | ((TempByte & 0x20) ? BLACK2 : WHITE2) 190 | ((TempByte & 0x08) ? BLACK1 : WHITE1) 191 | ((TempByte & 0x02) ? BLACK0 : WHITE0); 192 193 DataLineEven[k--] = ((TempByte & 0x01) ? BLACK3 : WHITE3) 194 | ((TempByte & 0x04) ? BLACK2 : WHITE2) 195 | ((TempByte & 0x10) ? BLACK1 : WHITE1) 196 | ((TempByte & 0x40) ? BLACK0 : WHITE0); 197 #endif 198 } 199 #ifdef DISPLAY_180_DEGREE 200 PreviousPicture = DataLinePrt; 201 #endif 202 DataLineScan[(i>>2)] = ScanTable[(i%4)]; 203 // SPI (0x0a, line data....) 204 epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize); 205 206 // SPI (0x02, 0x25) 207 epd_SPI_Send_Byte(0x02, 0x2F); 208 209 DataLineScan[(i>>2)] = 0; 210 } 211 #if(!_GaugeFrameTimeMark) 212 if(COG_Parameters[EPD_Type_Index].FrameTime>0) 213 { 214 while(Currentframe>(epd_GetCurrentTimeTick() - StartClock)); 215 } 216 #endif 217 //TestPin2Trigger(); 218 Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ; 219 cnt++; 220 }while (StageTime>Currentframe); 221 // TestPin2Trigger(); 222 while(StageTime>(epd_GetCurrentTimeTick() - StartClock)); 223 // TestPin2Trigger(); 224 // TestPinTrigger(); 225 } 226 227 //#pragma GCC optimize ("-O3") 228 static void Display_Stage_2 (uint8_t *PreviousPicture) 229 { 230 uint16_t i, j, k; // general counters 231 uint8_t TempByte; // Temporary storage for image data check 232 uint16_t StartClock; 233 #ifdef DISPLAY_180_DEGREE 234 uint8_t *DataLinePrt; 235 DisplayOrgPtr = (PreviousPicture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL)); 236 #else 237 DisplayOrgPtr = PreviousPicture; 238 #endif 239 240 // TestPinTrigger(); 241 cnt = 0; 242 Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime; 243 StartClock = epd_GetCurrentTimeTick(); 244 do 245 { 246 // TestPin2Trigger(); 247 PreviousPicture = DisplayOrgPtr; 248 #ifdef DISPLAY_180_DEGREE 249 DataLinePrt = PreviousPicture; 250 #endif 251 for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line 252 { 253 // SPI (0x04, ...) 254 epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel); 255 k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1; 256 for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // make every bit in the line black 257 { 258 TempByte =(*PreviousPicture++); 259 #ifdef DISPLAY_180_DEGREE 260 DataLineEven[j] = ((TempByte & 0x80) ? WHITE3 : NOTHING) 261 | ((TempByte & 0x20) ? WHITE2 : NOTHING) 262 | ((TempByte & 0x08) ? WHITE1 : NOTHING) 263 | ((TempByte & 0x02) ? WHITE0 : NOTHING); 264 DataLineOdd[k--] = ((TempByte & 0x01) ? WHITE3 : NOTHING) 265 | ((TempByte & 0x04) ? WHITE2 : NOTHING) 266 | ((TempByte & 0x10) ? WHITE1 : NOTHING) 267 | ((TempByte & 0x40) ? WHITE0 : NOTHING); 268 DataLinePrt--; 269 #else 270 DataLineOdd[j] = ((TempByte & 0x80) ? WHITE3 : NOTHING) 271 | ((TempByte & 0x20) ? WHITE2 : NOTHING) 272 | ((TempByte & 0x08) ? WHITE1 : NOTHING) 273 | ((TempByte & 0x02) ? WHITE0 : NOTHING); 274 DataLineEven[k--] = ((TempByte & 0x01) ? WHITE3 : NOTHING) 275 | ((TempByte & 0x04) ? WHITE2 : NOTHING) 276 | ((TempByte & 0x10) ? WHITE1 : NOTHING) 277 | ((TempByte & 0x40) ? WHITE0 : NOTHING); 278 #endif 279 } 280 281 #ifdef DISPLAY_180_DEGREE 282 PreviousPicture = DataLinePrt; 283 #endif 284 DataLineScan[(i>>2)] = ScanTable[(i%4)]; 285 // SPI (0x0a, line data....) 286 epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize); 287 288 epd_SPI_Send_Byte(0x02, 0x25); 289 290 DataLineScan[(i>>2)] = 0; 291 } 292 #if(!_GaugeFrameTimeMark) 293 if(COG_Parameters[EPD_Type_Index].FrameTime>0) 294 { 295 while(Currentframe>(epd_GetCurrentTimeTick() - StartClock)); 296 } 297 #endif 298 //TestPin2Trigger(); 299 Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ; 300 cnt++; 301 }while (StageTime>Currentframe); 302 // TestPin2Trigger(); 303 while(StageTime>(epd_GetCurrentTimeTick() - StartClock)); 304 // TestPin2Trigger(); 305 // TestPinTrigger(); 306 } 307 308 309 //#pragma GCC optimize ("-O3") 310 static void Display_Stage_3 (uint8_t *Picture) 311 { 312 uint16_t i, j,k; // general counters 313 uint8_t TempByte; // Temporary storage for image data check 314 uint16_t StartClock; 315 #ifdef DISPLAY_180_DEGREE 316 uint8_t *DataLinePrt; 317 DisplayOrgPtr = (Picture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL)); 318 #else 319 DisplayOrgPtr = Picture; 320 #endif 321 Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime; 322 cnt = 0; 323 // TestPinTrigger(); 324 StartClock = epd_GetCurrentTimeTick(); 325 do 326 { 327 // TestPin2Trigger(); 328 Picture = DisplayOrgPtr; 329 #ifdef DISPLAY_180_DEGREE 330 DataLinePrt = Picture; 331 #endif 332 for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line 333 { 334 // SPI (0x04, 0x03) 335 epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel); 336 k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1; 337 for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // check every bit in the line 338 { 339 TempByte = (*Picture++); 340 #ifdef DISPLAY_180_DEGREE 341 DataLineEven[j] = ((TempByte & 0x80) ? BLACK3 : NOTHING) 342 | ((TempByte & 0x20) ? BLACK2 : NOTHING ) 343 | ((TempByte & 0x08) ? BLACK1 : NOTHING ) 344 | ((TempByte & 0x02) ? BLACK0 : NOTHING ); 345 346 DataLineOdd[k--] = ((TempByte & 0x01) ? BLACK3 : NOTHING) 347 | ((TempByte & 0x04) ? BLACK2 : NOTHING ) 348 | ((TempByte & 0x10) ? BLACK1 : NOTHING ) 349 | ((TempByte & 0x40) ? BLACK0 : NOTHING ); 350 DataLinePrt--; 351 #else 352 DataLineOdd[j] = ((TempByte & 0x80) ? BLACK3 : NOTHING) 353 | ((TempByte & 0x20) ? BLACK2 : NOTHING ) 354 | ((TempByte & 0x08) ? BLACK1 : NOTHING ) 355 | ((TempByte & 0x02) ? BLACK0 : NOTHING ); 356 357 DataLineEven[k--] = ((TempByte & 0x01) ? BLACK3 : NOTHING) 358 | ((TempByte & 0x04) ? BLACK2 : NOTHING ) 359 | ((TempByte & 0x10) ? BLACK1 : NOTHING ) 360 | ((TempByte & 0x40) ? BLACK0 : NOTHING ); 361 #endif 362 } 363 #ifdef DISPLAY_180_DEGREE 364 Picture = DataLinePrt; 365 #endif 366 DataLineScan[(i>>2)] = ScanTable[(i%4)]; 367 // SPI (0x0a, line data....) 368 epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize); 369 370 epd_SPI_Send_Byte(0x02, 0x2F); 371 372 DataLineScan[(i>>2)] = 0; 373 } 374 #if(!_GaugeFrameTimeMark) 375 if(COG_Parameters[EPD_Type_Index].FrameTime>0) 376 { 377 while(Currentframe>(epd_GetCurrentTimeTick() - StartClock)); 378 } 379 #endif 380 //TestPin2Trigger(); 381 Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ; 382 cnt++; 383 }while (StageTime>Currentframe); 384 // TestPin2Trigger(); 385 while(StageTime>(epd_GetCurrentTimeTick() - StartClock)); 386 // TestPin2Trigger(); 387 // TestPinTrigger(); 388 } 389 390 //#pragma GCC optimize ("-O3") 391 static void Display_Stage_4 (uint8_t *Picture) 392 { 393 uint16_t i, j,k; // general counters 394 uint8_t TempByte; // Temporary storage for image data check 395 uint16_t StartClock; 396 #ifdef DISPLAY_180_DEGREE 397 uint8_t *DataLinePrt; 398 DisplayOrgPtr = (Picture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL)); 399 #else 400 DisplayOrgPtr = Picture; 401 #endif 402 Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime; 403 cnt = 0; 404 // TestPinTrigger(); 405 406 StartClock = epd_GetCurrentTimeTick(); 407 do 408 { 409 // TestPin2Trigger(); 410 Picture = DisplayOrgPtr; 411 #ifdef DISPLAY_180_DEGREE 412 DataLinePrt = Picture; 413 #endif 414 for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line 415 { 416 // SPI (0x04, ...) 417 epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel); 418 k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1; 419 for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // check every bit in the line 420 { 421 TempByte =(*Picture++); 422 #ifdef DISPLAY_180_DEGREE 423 DataLineEven[j] = ((TempByte & 0x80) ? WHITE3 : BLACK3 ) 424 | ((TempByte & 0x20) ? WHITE2 : BLACK2 ) 425 | ((TempByte & 0x08) ? WHITE1 : BLACK1 ) 426 | ((TempByte & 0x02) ? WHITE0 : BLACK0 ); 427 428 DataLineOdd[k--] = ((TempByte & 0x01) ? WHITE3 : BLACK3 ) 429 | ((TempByte & 0x04) ? WHITE2 : BLACK2 ) 430 | ((TempByte & 0x10) ? WHITE1 : BLACK1 ) 431 | ((TempByte & 0x40) ? WHITE0 : BLACK0 ); 432 DataLinePrt--; 433 #else 434 DataLineOdd[j] = ((TempByte & 0x80) ? WHITE3 : BLACK3 ) 435 | ((TempByte & 0x20) ? WHITE2 : BLACK2 ) 436 | ((TempByte & 0x08) ? WHITE1 : BLACK1 ) 437 | ((TempByte & 0x02) ? WHITE0 : BLACK0 ); 438 439 DataLineEven[k--] = ((TempByte & 0x01) ? WHITE3 : BLACK3 ) 440 | ((TempByte & 0x04) ? WHITE2 : BLACK2 ) 441 | ((TempByte & 0x10) ? WHITE1 : BLACK1 ) 442 | ((TempByte & 0x40) ? WHITE0 : BLACK0 ); 443 #endif 444 } 445 #ifdef DISPLAY_180_DEGREE 446 Picture = DataLinePrt; 447 #endif 448 DataLineScan[(i>>2)] = ScanTable[(i%4)]; 449 // SPI (0x0a, line data....) 450 epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize); 451 452 epd_SPI_Send_Byte(0x02, 0x2F); 453 454 DataLineScan[(i>>2)] = 0; 455 } 456 #if(!_GaugeFrameTimeMark) 457 if(COG_Parameters[EPD_Type_Index].FrameTime>0) 458 { 459 while(Currentframe>(epd_GetCurrentTimeTick() - StartClock)); 460 } 461 #endif 462 //TestPin2Trigger(); 463 Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ; 464 cnt++; 465 }while (StageTime>Currentframe); 466 467 // TestPin2Trigger(); 468 while(StageTime>(epd_GetCurrentTimeTick() - StartClock)); 469 // TestPin2Trigger(); 470 // TestPinTrigger(); 471 } 472 473 static void Display_Nothing (void) 474 { 475 uint16_t i; // general counters 476 477 for (i = 0; i < COG_Parameters[EPD_Type_Index].HORIZONTAL; i++) // make every bit in the line white 478 { 479 DataLineEven[i] = 0x00; 480 DataLineOdd[i] = 0x00; 481 } 482 483 for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line 484 { 485 epd_SPI_Send_Byte(0x04, 0x03); 486 DataLineScan[(i>>2)] = ScanTable[(i%4)]; 487 // SPI (0x0a, line data....) 488 epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize); 489 490 epd_SPI_Send_Byte(0x02, 0x2F); 491 } 492 } 493 494 static void Dummy_line(void) 495 { 496 uint16_t i; 497 498 for (i = 0; i < COG_Parameters[EPD_Type_Index].DataLineSize; i++) 499 { 500 COG_Line.uint8[i] = 0x00; 501 } 502 503 epd_SPI_Send_Byte(0x04, 0x03); 504 505 // SPI (0x0a, line data....) 506 epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize); 507 508 epd_SPI_Send_Byte(0x02, 0x2F); 509 } 510 511 512 /****************************************************************************** 513 * Public functions 514 *****************************************************************************/ 515 void epd_HwInit(void) 516 { 517 epd_InitDisplayHardware(); 518 } 519 520 void epd_PowerOn(void) 521 { 522 epd_discharge_low(); 523 epd_rst_low(); 524 epd_cs_low(); 525 epd_spi_init(); 526 527 epd_pwm_active(5); 528 529 epd_panelon_on(); 530 531 epd_pwm_active(10); 532 533 epd_cs_high(); 534 535 //epd_border_high(); 536 537 epd_rst_high(); 538 539 epd_pwm_active(5); 540 541 epd_rst_low(); 542 543 epd_pwm_active(5); 544 545 epd_rst_high(); 546 547 epd_pwm_active(5); 548 } 549 550 void epd_InitializeDriver(uint8_t EPDIndex) 551 { 552 uint8_t SendBuffer[2]; 553 uint16_t k; 554 555 EPD_Type_Index = EPDIndex; 556 557 //Data Line Clear 558 for (k = 0; k <= __LineDataSize; k ++) 559 { 560 COG_Line.uint8[k] = 0x00; 561 } 562 Driver_TypeSelect(EPDIndex); 563 k = 0; 564 565 SetTemperature_Factor(EPDIndex); 566 567 /*while (DRIVERBUSY_Get()) 568 { 569 delayT32B0Us(500); 570 if((k++)>=1000) return;//wait 500 ms 571 } 572 */ 573 574 // SPI (0x01, 0x0000, 0x0000, 0x01ff, 0xe000) 575 epd_SPI_Send(0x01, (uint8_t *)&COG_Parameters[EPDIndex].ChannelSelect, 8); 576 577 epd_SPI_Send_Byte(0x06, 0xff); 578 epd_SPI_Send_Byte(0x07, 0x9d); 579 epd_SPI_Send_Byte(0x08, 0x00); 580 581 // SPI (0x09, 0xd000) 582 SendBuffer[0] = 0xd0; 583 SendBuffer[1] = 0x00; 584 epd_SPI_Send(0x09, SendBuffer, 2); 585 586 epd_SPI_Send_Byte(0x04,COG_Parameters[EPDIndex].VoltageLevel); 587 588 epd_SPI_Send_Byte(0x03, 0x01); 589 epd_SPI_Send_Byte(0x03, 0x00); 590 591 epd_pwm_active(5); 592 593 epd_SPI_Send_Byte(0x05, 0x01); 594 595 epd_pwm_active(30); 596 597 epd_SPI_Send_Byte(0x05, 0x03); 598 epd_delay_ms(30); 599 epd_SPI_Send_Byte(0x05, 0x0f); 600 epd_delay_ms(30); 601 epd_SPI_Send_Byte(0x02, 0x24); 602 } 603 604 void epd_Display (uint8_t *pNewImg, uint8_t *pPrevImg) 605 { 606 //COG Process - update display in four steps 607 Display_Stage_1(pPrevImg); 608 Display_Stage_2(pPrevImg); 609 Display_Stage_3(pNewImg); 610 Display_Stage_4(pNewImg); 611 } 612 613 void epd_PowerOff (void) 614 { 615 Display_Nothing(); 616 Dummy_line(); 617 epd_delay_ms(25); 618 619 //border_low(); 620 //epd_delay_ms(_30ms); 621 //border_high(); 622 623 epd_SPI_Send_Byte(0x03, 0x01); 624 epd_SPI_Send_Byte(0x02, 0x05); 625 epd_SPI_Send_Byte(0x05, 0x0E); 626 epd_SPI_Send_Byte(0x05, 0x02); 627 epd_SPI_Send_Byte(0x04, 0x0C); 628 epd_delay_ms(120); 629 epd_SPI_Send_Byte(0x05, 0x00); 630 epd_SPI_Send_Byte(0x07, 0x0D); 631 epd_SPI_Send_Byte(0x04, 0x50); 632 epd_delay_ms(40); 633 epd_SPI_Send_Byte(0x04, 0xA0); 634 epd_delay_ms(40); 635 epd_SPI_Send_Byte(0x04, 0x00); 636 637 epd_rst_low(); 638 epd_cs_low(); 639 epd_spi_detach(); 640 epd_panelon_off(); 641 642 //epd_border_low(); 643 644 epd_discharge_high(); 645 epd_delay_ms(150); 646 epd_discharge_low(); 647 } 648 649 650