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 #include "EPD.h" 17 #include "bsp.h" 18 #include <stdio.h> 19 20 static void EPD_line(uint16_t line, const uint8_t *data, uint8_t fixed_value, EPD_stage stage); 21 static void SPI_send(const uint8_t *buffer, uint16_t length); 22 static void SPI_put(uint8_t c); 23 static void SPI_put_wait(uint8_t c); 24 25 static void epd_pwm_active(uint16_t delayInMs); 26 27 28 // inline arrays 29 #define ARRAY(type, ...) ((type[]){__VA_ARGS__}) 30 #define CU8(...) (ARRAY(const uint8_t, __VA_ARGS__)) 31 32 static COG_Parameters_t epd; 33 34 /****************************************************************************** 35 * Local functions 36 *****************************************************************************/ 37 38 39 // convert a temperature in Celcius to 40 // the scale factor for frame_*_repeat methods 41 static int16_t EPD_temperature_to_factor_10x(int16_t temperature) { 42 if (temperature <= -10) { 43 return 170; 44 } else if (temperature <= -5) { 45 return 120; 46 } else if (temperature <= 5) { 47 return 80; 48 } else if (temperature <= 10) { 49 return 40; 50 } else if (temperature <= 15) { 51 return 30; 52 } else if (temperature <= 20) { 53 return 20; 54 } else if (temperature <= 40) { 55 return 10; 56 } 57 return 7; 58 } 59 60 61 // One frame of data is the number of lines * rows. For example: 62 // The 1.44??? frame of data is 96 lines * 128 dots. 63 // The 2??? frame of data is 96 lines * 200 dots. 64 // The 2.7??? frame of data is 176 lines * 264 dots. 65 66 // the image is arranged by line which matches the display size 67 // so smallest would have 96 * 32 bytes 68 69 static void EPD_frame_fixed(uint8_t fixed_value, EPD_stage stage) { 70 uint8_t line; 71 for (line = 0; line < epd.lines_per_display ; ++line) { 72 EPD_line(line, 0, fixed_value, stage); 73 } 74 } 75 76 static void EPD_frame_data(const uint8_t *image, EPD_stage stage){ 77 uint8_t line; 78 for (line = 0; line < epd.lines_per_display ; ++line) { 79 EPD_line(line, &image[line * epd.bytes_per_line], 0, stage); 80 } 81 } 82 83 84 static void EPD_frame_fixed_repeat(uint8_t fixed_value, EPD_stage stage) { 85 int32_t stage_time = epd.factored_stage_time; 86 do { 87 uint32_t t_start = bsp_getMsTicks(); 88 EPD_frame_fixed(fixed_value, stage); 89 uint32_t t_end = bsp_getMsTicks(); 90 if (t_end > t_start) { 91 stage_time -= t_end - t_start; 92 } else { 93 stage_time -= t_start - t_end + 1 + 0xffffffffU; 94 } 95 } while (stage_time > 0); 96 } 97 98 99 static void EPD_frame_data_repeat(const uint8_t *image, EPD_stage stage) { 100 int32_t stage_time = epd.factored_stage_time; 101 do { 102 uint32_t t_start = bsp_getMsTicks(); 103 EPD_frame_data(image, stage); 104 uint32_t t_end = bsp_getMsTicks(); 105 if (t_end > t_start) { 106 stage_time -= t_end - t_start; 107 } else { 108 stage_time -= t_start - t_end + 1 + 0xffffffffU; 109 } 110 } while (stage_time > 0); 111 } 112 113 static void EPD_line(uint16_t line, const uint8_t *data, uint8_t fixed_value, EPD_stage stage) { 114 // charge pump voltage levels 115 bsp_delayUs(10); 116 SPI_send(CU8(0x70, 0x04), 2); 117 bsp_delayUs(10); 118 SPI_send(epd.gate_source, epd.gate_source_length); 119 120 // send data 121 bsp_delayUs(10); 122 SPI_send(CU8(0x70, 0x0a), 2); 123 bsp_delayUs(10); 124 125 // CS low 126 EPD_Pin_EPD_CS(LOW); 127 SPI_put_wait(0x72); 128 129 // even pixels 130 uint16_t b; 131 for (b = epd.bytes_per_line; b > 0; --b) { 132 if (0 != data) { 133 uint8_t pixels = data[b - 1] & 0xaa; 134 switch(stage) { 135 case EPD_compensate: // B -> W, W -> B (Current Image) 136 pixels = 0xaa | ((pixels ^ 0xaa) >> 1); 137 break; 138 case EPD_white: // B -> N, W -> W (Current Image) 139 pixels = 0x55 + ((pixels ^ 0xaa) >> 1); 140 break; 141 case EPD_inverse: // B -> N, W -> B (New Image) 142 pixels = 0x55 | (pixels ^ 0xaa); 143 break; 144 case EPD_normal: // B -> B, W -> W (New Image) 145 pixels = 0xaa | (pixels >> 1); 146 break; 147 } 148 SPI_put_wait(pixels); 149 } else { 150 SPI_put_wait(fixed_value); 151 } } 152 153 // scan line 154 for (b = 0; b < epd.bytes_per_scan; ++b) { 155 if (line / 4 == b) { 156 SPI_put_wait(0xc0 >> (2 * (line & 0x03))); 157 } else { 158 SPI_put_wait(0x00); 159 } 160 } 161 162 // odd pixels 163 for (b = 0; b < epd.bytes_per_line; ++b) { 164 if (0 != data) { 165 uint8_t pixels = data[b] & 0x55; 166 switch(stage) { 167 case EPD_compensate: // B -> W, W -> B (Current Image) 168 pixels = 0xaa | (pixels ^ 0x55); 169 break; 170 case EPD_white: // B -> N, W -> W (Current Image) 171 pixels = 0x55 + (pixels ^ 0x55); 172 break; 173 case EPD_inverse: // B -> N, W -> B (New Image) 174 pixels = 0x55 | ((pixels ^ 0x55) << 1); 175 break; 176 case EPD_normal: // B -> B, W -> W (New Image) 177 pixels = 0xaa | pixels; 178 break; 179 } 180 uint8_t p1 = (pixels >> 6) & 0x03; 181 uint8_t p2 = (pixels >> 4) & 0x03; 182 uint8_t p3 = (pixels >> 2) & 0x03; 183 uint8_t p4 = (pixels >> 0) & 0x03; 184 pixels = (p1 << 0) | (p2 << 2) | (p3 << 4) | (p4 << 6); 185 SPI_put_wait(pixels); 186 } else { 187 SPI_put_wait(fixed_value); 188 } 189 } 190 191 if (epd.filler == TRUE) { 192 SPI_put_wait(0x00); 193 } 194 195 // CS high 196 EPD_Pin_EPD_CS(HIGH); 197 198 // output data to panel 199 bsp_delayUs(10); 200 SPI_send(CU8(0x70, 0x02), 2); 201 bsp_delayUs(10); 202 SPI_send(CU8(0x72, 0x2f), 2); 203 } 204 205 206 /****************************************************************************** 207 * Public functions 208 *****************************************************************************/ 209 210 211 void EPD_init(EPD_size size) { 212 static uint8_t cs[] = {0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00}; 213 static uint8_t gs[] = {0x72, 0x03}; 214 215 EPD_Pin_init(); 216 217 epd.size = size; 218 epd.stage_time = 480; // milliseconds 219 epd.lines_per_display = 96; 220 epd.dots_per_line = 128; 221 epd.bytes_per_line = 128 / 8; 222 epd.bytes_per_scan = 96 / 4; 223 epd.filler = FALSE; 224 epd.channel_select = cs; 225 epd.channel_select_length = sizeof(cs); 226 epd.gate_source = gs; 227 epd.gate_source_length = sizeof(gs); 228 229 // set up size structure 230 switch (size) { 231 default: 232 case EPD_1_44: // default so no change 233 break; 234 235 case EPD_2_0: { 236 epd.lines_per_display = 96; 237 epd.dots_per_line = 200; 238 epd.bytes_per_line = 200 / 8; 239 epd.bytes_per_scan = 96 / 4; 240 epd.filler = TRUE; 241 cs[0] = 0x72; 242 cs[1] = 0x00; 243 cs[2] = 0x00; 244 cs[3] = 0x00; 245 cs[4] = 0x00; 246 cs[5] = 0x01; 247 cs[6] = 0xff; 248 cs[7] = 0xe0; 249 cs[8] = 0x00; 250 gs[0] = 0x72; 251 gs[1] = 0x03; 252 break; 253 } 254 255 case EPD_2_7: { 256 epd.stage_time = 630; // milliseconds 257 epd.lines_per_display = 176; 258 epd.dots_per_line = 264; 259 epd.bytes_per_line = 264 / 8; 260 epd.bytes_per_scan = 176 / 4; 261 epd.filler = TRUE; 262 cs[0] = 0x72; 263 cs[1] = 0x00; 264 cs[2] = 0x00; 265 cs[3] = 0x00; 266 cs[4] = 0x7f; 267 cs[5] = 0xff; 268 cs[6] = 0xfe; 269 cs[7] = 0x00; 270 cs[8] = 0x00; 271 gs[0] = 0x72; 272 gs[1] = 0x00; 273 break; 274 } 275 } 276 277 epd.factored_stage_time = epd.stage_time; 278 } 279 280 281 void EPD_begin(void) 282 { 283 // power up sequence 284 SPI_put(0x00); 285 286 EPD_Pin_RESET(LOW); 287 EPD_Pin_PANEL_ON(LOW); 288 EPD_Pin_DISCHARGE(LOW); 289 EPD_Pin_BORDER(LOW); 290 EPD_Pin_EPD_CS(LOW); 291 292 // PWM_start(this->EPD_Pin_PWM); 293 // Delay_ms(5); 294 epd_pwm_active(5); 295 EPD_Pin_PANEL_ON(HIGH); 296 // Delay_ms(10); 297 epd_pwm_active(10); 298 299 EPD_Pin_RESET(HIGH); 300 EPD_Pin_BORDER(HIGH); 301 EPD_Pin_EPD_CS(HIGH); 302 // Delay_ms(5); 303 epd_pwm_active(5); 304 305 EPD_Pin_RESET(LOW); 306 // Delay_ms(5); 307 epd_pwm_active(5); 308 309 EPD_Pin_RESET(HIGH); 310 // Delay_ms(5); 311 epd_pwm_active(5); 312 313 // wait for COG to become ready 314 while (HIGH == epd_get_busy()) { 315 epd_pwm_active(10); 316 } 317 318 // channel select 319 bsp_delayUs(10); 320 SPI_send(CU8(0x70, 0x01), 2); 321 bsp_delayUs(10); 322 SPI_send(epd.channel_select, epd.channel_select_length); 323 324 // DC/DC frequency 325 bsp_delayUs(10); 326 SPI_send(CU8(0x70, 0x06), 2); 327 bsp_delayUs(10); 328 SPI_send(CU8(0x72, 0xff), 2); 329 330 // high power mode osc 331 bsp_delayUs(10); 332 SPI_send(CU8(0x70, 0x07), 2); 333 bsp_delayUs(10); 334 SPI_send(CU8(0x72, 0x9d), 2); 335 336 337 // disable ADC 338 bsp_delayUs(10); 339 SPI_send(CU8(0x70, 0x08), 2); 340 bsp_delayUs(10); 341 SPI_send(CU8(0x72, 0x00), 2); 342 343 // Vcom level 344 bsp_delayUs(10); 345 SPI_send(CU8(0x70, 0x09), 2); 346 bsp_delayUs(10); 347 SPI_send(CU8(0x72, 0xd0, 0x00), 3); 348 349 // gate and source voltage levels 350 bsp_delayUs(10); 351 SPI_send(CU8(0x70, 0x04), 2); 352 bsp_delayUs(10); 353 SPI_send(epd.gate_source, epd.gate_source_length); 354 355 // Delay_ms(5); //??? 356 epd_pwm_active(5); 357 358 // driver latch on 359 bsp_delayUs(10); 360 SPI_send(CU8(0x70, 0x03), 2); 361 bsp_delayUs(10); 362 SPI_send(CU8(0x72, 0x01), 2); 363 364 // driver latch off 365 bsp_delayUs(10); 366 SPI_send(CU8(0x70, 0x03), 2); 367 bsp_delayUs(10); 368 SPI_send(CU8(0x72, 0x00), 2); 369 370 // Delay_ms(5); 371 epd_pwm_active(5); 372 373 // charge pump positive voltage on 374 bsp_delayUs(10); 375 SPI_send(CU8(0x70, 0x05), 2); 376 bsp_delayUs(10); 377 SPI_send(CU8(0x72, 0x01), 2); 378 379 // final delay before PWM off 380 // Delay_ms(30); 381 // PWM_stop(this->EPD_Pin_PWM); 382 epd_pwm_active(30); 383 384 // charge pump negative voltage on 385 bsp_delayUs(10); 386 SPI_send(CU8(0x70, 0x05), 2); 387 bsp_delayUs(10); 388 SPI_send(CU8(0x72, 0x03), 2); 389 390 bsp_delayMs(30); 391 392 // Vcom driver on 393 bsp_delayUs(10); 394 SPI_send(CU8(0x70, 0x05), 2); 395 bsp_delayUs(10); 396 SPI_send(CU8(0x72, 0x0f), 2); 397 398 bsp_delayMs(30); 399 400 // output enable to disable 401 bsp_delayUs(10); 402 SPI_send(CU8(0x70, 0x02), 2); 403 bsp_delayUs(10); 404 SPI_send(CU8(0x72, 0x24), 2); 405 } 406 407 408 void EPD_end(void) { 409 410 EPD_frame_fixed(0x55, EPD_normal); // dummy frame 411 EPD_line(0x7fffu, 0, 0x55, EPD_normal); // dummy_line 412 413 bsp_delayMs(25); 414 415 EPD_Pin_BORDER(LOW); 416 bsp_delayMs(30); 417 418 EPD_Pin_BORDER(HIGH); 419 420 // latch reset turn on 421 bsp_delayUs(10); 422 SPI_send(CU8(0x70, 0x03), 2); 423 bsp_delayUs(10); 424 SPI_send(CU8(0x72, 0x01), 2); 425 426 // output enable off 427 bsp_delayUs(10); 428 SPI_send(CU8(0x70, 0x02), 2); 429 bsp_delayUs(10); 430 SPI_send(CU8(0x72, 0x05), 2); 431 432 // Vcom power off 433 bsp_delayUs(10); 434 SPI_send(CU8(0x70, 0x05), 2); 435 bsp_delayUs(10); 436 SPI_send(CU8(0x72, 0x0e), 2); 437 438 // power off negative charge pump 439 bsp_delayUs(10); 440 SPI_send(CU8(0x70, 0x05), 2); 441 bsp_delayUs(10); 442 SPI_send(CU8(0x72, 0x02), 2); 443 444 // discharge 445 bsp_delayUs(10); 446 SPI_send(CU8(0x70, 0x04), 2); 447 bsp_delayUs(10); 448 SPI_send(CU8(0x72, 0x0c), 2); 449 450 bsp_delayMs(120); 451 452 // all charge pumps off 453 bsp_delayUs(10); 454 SPI_send(CU8(0x70, 0x05), 2); 455 bsp_delayUs(10); 456 SPI_send(CU8(0x72, 0x00), 2); 457 458 // turn of osc 459 bsp_delayUs(10); 460 SPI_send(CU8(0x70, 0x07), 2); 461 bsp_delayUs(10); 462 SPI_send(CU8(0x72, 0x0d), 2); 463 464 // discharge internal - 1 465 bsp_delayUs(10); 466 SPI_send(CU8(0x70, 0x04), 2); 467 bsp_delayUs(10); 468 SPI_send(CU8(0x72, 0x50), 2); 469 470 bsp_delayMs(40); 471 472 // discharge internal - 2 473 bsp_delayUs(10); 474 SPI_send(CU8(0x70, 0x04), 2); 475 bsp_delayUs(10); 476 SPI_send(CU8(0x72, 0xA0), 2); 477 478 bsp_delayMs(40); 479 480 // discharge internal - 3 481 bsp_delayUs(10); 482 SPI_send(CU8(0x70, 0x04), 2); 483 bsp_delayUs(10); 484 SPI_send(CU8(0x72, 0x00), 2); 485 486 // turn of power and all signals 487 EPD_Pin_RESET(LOW); 488 EPD_Pin_PANEL_ON(LOW); 489 EPD_Pin_BORDER(LOW); 490 EPD_Pin_EPD_CS(LOW); 491 492 EPD_Pin_DISCHARGE(HIGH); 493 494 SPI_put(0x00); 495 496 bsp_delayMs(150); 497 498 EPD_Pin_DISCHARGE(LOW); 499 } 500 501 502 void EPD_setFactor(int16_t temperature) { 503 epd.factored_stage_time = epd.stage_time * EPD_temperature_to_factor_10x(temperature) / 10; 504 } 505 506 // clear display (anything -> white) 507 void EPD_clear() { 508 EPD_frame_fixed_repeat(0xff, EPD_compensate); 509 EPD_frame_fixed_repeat(0xff, EPD_white); 510 EPD_frame_fixed_repeat(0xaa, EPD_inverse); 511 EPD_frame_fixed_repeat(0xaa, EPD_normal); 512 } 513 514 // assuming a clear (white) screen output an image 515 void EPD_image(const uint8_t *image) { 516 EPD_frame_fixed_repeat(0xaa, EPD_compensate); 517 EPD_frame_fixed_repeat(0xaa, EPD_white); 518 EPD_frame_data_repeat(image, EPD_inverse); 519 EPD_frame_data_repeat(image, EPD_normal); 520 } 521 522 // change from old image to new image 523 void EPD_image_change(const uint8_t *old_image, const uint8_t *new_image) { 524 EPD_frame_data_repeat(old_image, EPD_compensate); 525 EPD_frame_data_repeat(old_image, EPD_white); 526 EPD_frame_data_repeat(new_image, EPD_inverse); 527 EPD_frame_data_repeat(new_image, EPD_normal); 528 } 529 530 531 static void SPI_put(uint8_t c) { 532 uint8_t placeholder = c; 533 bsp_spiWrite(&placeholder, 1); 534 } 535 536 537 static void SPI_put_wait(uint8_t c) { 538 539 SPI_put(c); 540 541 // wait for COG ready 542 while (HIGH == epd_get_busy()) { 543 } 544 } 545 546 547 static void SPI_send(const uint8_t *buffer, uint16_t length) { 548 // CS low 549 EPD_Pin_EPD_CS(LOW); 550 551 bsp_spiWrite((uint8_t*)buffer, length); 552 553 // CS high 554 EPD_Pin_EPD_CS(HIGH); 555 } 556 557 static void epd_pwm_active(uint16_t delayInMs) 558 { 559 uint16_t numOfIterations; 560 uint32_t now = bsp_getMsTicks(); 561 562 numOfIterations = delayInMs * 100; 563 564 for(; numOfIterations > 0; numOfIterations--) 565 { 566 EPD_Pin_PWM(HIGH); 567 bsp_delayUs(5); //100kHz 568 EPD_Pin_PWM(LOW); 569 bsp_delayUs(5); 570 } 571 572 printf("PWM done for %dms.\n", bsp_getMsTicks() - now); 573 }