| 424 | } |
| 425 | |
| 426 | void ssd1306Send(PocoPixel *pixels, int byteLength, void *refcon) |
| 427 | { |
| 428 | ssd1606 ssd = refcon; |
| 429 | uint8_t pixel, lines; |
| 430 | |
| 431 | #if MODDEF_SSD1306_SPI |
| 432 | modSPIFlush(); |
| 433 | #endif |
| 434 | |
| 435 | if (byteLength < 0) byteLength = -byteLength; |
| 436 | lines = (uint8_t)(byteLength / ssd->width); |
| 437 | pixel = ssd->pixel; |
| 438 | while (lines--) { |
| 439 | uint8_t *out; |
| 440 | uint8_t w; |
| 441 | #if MODDEF_SSD1306_DITHER |
| 442 | int16_t *thisLineErrors, *nextLineErrors; |
| 443 | |
| 444 | if (ssd->ditherPhase) { |
| 445 | c_memset(ssd->ditherB, 0, sizeof(ssd->ditherB)); // zero out next line |
| 446 | thisLineErrors = ssd->ditherA + 2; |
| 447 | nextLineErrors = ssd->ditherB + 2; |
| 448 | ssd->ditherPhase = 0; |
| 449 | } |
| 450 | else { |
| 451 | c_memset(ssd->ditherA, 0, sizeof(ssd->ditherA)); // zero out next line |
| 452 | thisLineErrors = ssd->ditherB + 2; |
| 453 | nextLineErrors = ssd->ditherA + 2; |
| 454 | ssd->ditherPhase = 1; |
| 455 | } |
| 456 | #endif |
| 457 | |
| 458 | if (0 == pixel) { // start new group of 8 rows |
| 459 | pixel = 1; |
| 460 | c_memset(&ssd->buffer[kBufferSlop], 0, sizeof(ssd->buffer) - kBufferSlop); |
| 461 | } |
| 462 | |
| 463 | #if MODDEF_SSD1306_DITHER |
| 464 | for (w = ssd->width, out = &ssd->buffer[kBufferSlop]; 0 != w; w--, out++) { |
| 465 | int16_t thisPixel = *pixels++ + (thisLineErrors[0] >> 4); |
| 466 | |
| 467 | if (thisPixel >= 128) { |
| 468 | *out |= pixel; |
| 469 | thisPixel -= 255; |
| 470 | } |
| 471 | |
| 472 | // Burkes |
| 473 | thisLineErrors[ 1] += thisPixel << 2; |
| 474 | thisLineErrors[ 2] += thisPixel << 1; |
| 475 | nextLineErrors[-2] += thisPixel; |
| 476 | nextLineErrors[-1] += thisPixel << 1; |
| 477 | nextLineErrors[ 0] += thisPixel << 2; |
| 478 | nextLineErrors[ 1] += thisPixel << 1; |
| 479 | nextLineErrors[ 2] += thisPixel; |
| 480 | |
| 481 | thisLineErrors++; |
| 482 | nextLineErrors++; |
| 483 | } |
no test coverage detected