ssd1677-driver.md
1 # SSD1677 E-Ink Display Driver Guide 2 3 ## GDEQ0426T82 (4.26" 800x480) on Xteink X4 4 5 Complete reference for programming the SSD1677 e-paper display controller, including initialization, image updates, custom LUT creation, and low-level protocol details. 6 7 Based on the GxEPD2_426_GDEQ0426T82 driver implementation. 8 9 --- 10 11 ## Table of Contents 12 13 - [Hardware Configuration](#hardware-configuration) 14 - [SPI Communication](#spi-communication) 15 - [Initialization](#initialization) 16 - [RAM Operations](#ram-operations) 17 - [Writing Image Data](#writing-image-data) 18 - [Display Updates](#display-updates) 19 - [Custom LUT Guide](#custom-lut-guide) 20 - [Complete Workflows](#complete-workflows) 21 - [Command Reference](#command-reference) 22 - [Timing & Power Management](#timing--power-management) 23 24 --- 25 26 ## Hardware Configuration 27 28 - **Controller**: SSD1677 29 - **Display**: 800x480 pixels (100x60 bytes = 48,000 bytes) 30 - **SPI Pins**: SCLK=8, MOSI=10, CS=21, DC=4, RST=5, BUSY=6 31 - **SPI Settings**: 40MHz (spec: 20MHz, but 40MHz works), MSB First, SPI Mode 0 32 33 --- 34 35 ## SPI Communication 36 37 ### Low-Level Protocol 38 39 **Command Format:** 40 ``` 41 DC=LOW, CS=LOW -> Transfer(command_byte) -> CS=HIGH, DC=HIGH 42 ``` 43 44 **Data Format:** 45 ``` 46 DC=HIGH, CS=LOW -> Transfer(data_byte) -> CS=HIGH 47 ``` 48 49 **Bulk Transfer Format:** 50 ``` 51 CS=LOW -> Transfer(byte1) -> Transfer(byte2) -> ... -> CS=HIGH 52 ``` 53 54 ### Reset Sequence 55 56 ``` 57 RST=HIGH -> delay(20ms) -> RST=LOW -> delay(2ms) -> RST=HIGH -> delay(20ms) 58 ``` 59 60 --- 61 62 ## Initialization 63 64 ### Minimal Initialization Example 65 66 ```c 67 void ssd1677_init() { 68 // 1. Software Reset 69 epd_cmd(0x12); // SWRESET 70 epd_wait_busy(); // Wait for busy to clear 71 72 // 2. Driver Output Control 73 epd_cmd(0x01); 74 epd_data(0xA7); // 680 rows -> 0x2A7, low byte 75 epd_data(0x02); // high byte 76 epd_data(0x00); // GD=0, SM=0, TB=0 77 78 // 3. Data Entry Mode 79 epd_cmd(0x11); 80 epd_data(0x03); // X+, Y+ 81 82 // 4. RAM X Start/End 83 epd_cmd(0x44); 84 epd_data(0x00); // X start = 0 85 epd_data(0x3B); // X end = 959 / 8 = 0x3B 86 87 // 5. RAM Y Start/End 88 epd_cmd(0x45); 89 epd_data(0x00); // Y start (low byte) 90 epd_data(0x00); // Y start (high byte) 91 epd_data(0xA7); // Y end (low byte) 92 epd_data(0x02); // Y end (high byte) 93 94 // 6. Border Control 95 epd_cmd(0x3C); 96 epd_data(0xC0); // Border = Hi-Z 97 98 // 7. Temperature Sensor (internal) 99 epd_cmd(0x18); 100 epd_data(0x80); 101 } 102 ``` 103 104 ### Detailed Initialization Sequence 105 106 After reset: 107 108 1. **0x12** — Software Reset (SWRESET), then wait BUSY 109 2. **0x18** `0x80` — Temperature sensor control (internal) 110 3. **0x0C** `0xAE, 0xC7, 0xC3, 0xC0, 0x40` — Booster soft start configuration 111 4. **0x01** `0xDF, 0x01, 0x02` — Driver output control (479 gates = HEIGHT-1) 112 5. **0x3C** `0x01` — Border waveform control 113 6. Set RAM area (see below) 114 7. **0x46** `0xF7` — Auto write BW RAM (clear to white), then wait BUSY 115 8. **0x47** `0xF7` — Auto write RED RAM (clear to white), then wait BUSY 116 117 ### Command Explanations 118 119 **Software Reset (0x12)** — Resets the internal registers (except deep sleep). Mandatory after power-up. 120 121 **Driver Output Control (0x01)** — Sets display height and scan direction: 122 - Byte 1: `(HEIGHT - 1) % 256` = `0xDF` (479 & 0xFF) 123 - Byte 2: `(HEIGHT - 1) / 256` = `0x01` (479 >> 8) 124 - Byte 3: `0x02` (interlaced/SM mode) 125 126 **Data Entry Mode (0x11)** — Controls RAM addressing: `0x03 = X increment, Y increment`. 127 128 **Set RAM Window (0x44 & 0x45)** — Defines the region written during RAM writes. For full 960x680 screen, X=0..0x3B, Y=0..0x2A7. 129 130 **Border Waveform (0x3C)** — Controls VBD (border pixel behavior). `0xC0 = Hi-Z`, common default. 131 132 **Temperature Sensor (0x18)** — `0x80 = use internal sensor`. 133 134 --- 135 136 ## RAM Operations 137 138 ### RAM Area Configuration 139 140 Sets the window for subsequent RAM writes. Y-coordinates are reversed due to hardware gates orientation. 141 142 **Important:** X addresses are specified in **pixels**, not bytes. The controller handles the byte conversion internally. 143 144 **For coordinates (x, y, w, h):** 145 146 1. Calculate reversed Y: `y_rev = HEIGHT - y - h` 147 148 2. **Set RAM Entry Mode** (Command `0x11`): Data `0x01` (X increment, Y decrement - Y reversed) 149 150 3. **Set RAM X Address** (Command `0x44`) — In pixels: 151 - Data[0]: `x % 256` (X start LSB) 152 - Data[1]: `x / 256` (X start MSB) 153 - Data[2]: `(x + w - 1) % 256` (X end LSB) 154 - Data[3]: `(x + w - 1) / 256` (X end MSB) 155 156 4. **Set RAM Y Address** (Command `0x45`): 157 - Data[0]: `(y_rev + h - 1) % 256` (Y start LSB) 158 - Data[1]: `(y_rev + h - 1) / 256` (Y start MSB) 159 - Data[2]: `y_rev % 256` (Y end LSB) 160 - Data[3]: `y_rev / 256` (Y end MSB) 161 162 5. **Set RAM X Counter** (Command `0x4E`): 163 - Data[0]: `x % 256` (Initial X LSB) 164 - Data[1]: `x / 256` (Initial X MSB) 165 166 6. **Set RAM Y Counter** (Command `0x4F`): 167 - Data[0]: `(y_rev + h - 1) % 256` (Initial Y LSB) 168 - Data[1]: `(y_rev + h - 1) / 256` (Initial Y MSB) 169 170 --- 171 172 ## Writing Image Data 173 174 ### Write to Current Buffer (Command 0x24) 175 176 ```c 177 void ssd1677_write_bw(uint8_t *buffer, uint32_t size) { 178 // Set RAM Address Counters 179 epd_cmd(0x4E); // X counter 180 epd_data(0x00); 181 epd_cmd(0x4F); // Y counter 182 epd_data(0x00); 183 epd_data(0x00); 184 185 // Write BW RAM 186 epd_cmd(0x24); 187 for (uint32_t i = 0; i < size; i++) 188 epd_data(buffer[i]); 189 } 190 ``` 191 192 **Process:** 193 1. Configure RAM area with `_setPartialRamArea(x, y, w, h)` 194 2. Send command `0x24` 195 3. Start bulk transfer (CS=LOW) 196 4. Transfer image data bytes (one bit per pixel, MSB first) 197 - Total bytes = `(w * h) / 8` 198 - `0xFF` = white, `0x00` = black 199 5. End transfer (CS=HIGH) 200 201 **Explanation:** 202 - **0x4E / 0x4F** set starting address for RAM 203 - **0x24** selects the BW image buffer 204 205 ### Write to Previous Buffer (Command 0x26) 206 207 Same as above but use command `0x26` instead of `0x24`. Used for differential updates. 208 209 ### Full Screen Clear 210 211 1. Write to previous buffer: `_setPartialRamArea(0, 0, 800, 480)` -> Command `0x26` -> 48000 bytes of `0xFF` 212 2. Write to current buffer: `_setPartialRamArea(0, 0, 800, 480)` -> Command `0x24` -> 48000 bytes of `0xFF` 213 3. Perform full refresh 214 215 ### Full Frame Example 216 217 ```c 218 void ssd1677_display_frame(uint8_t *bw, uint8_t *red) { 219 ssd1677_write_bw(bw, BW_BUFFER_SIZE); 220 221 epd_cmd(0x26); // Write RED RAM 222 for (int i = 0; i < RED_BUFFER_SIZE; i++) 223 epd_data(red[i]); 224 225 ssd1677_update(); 226 } 227 ``` 228 229 --- 230 231 ## Display Updates 232 233 ### Power On 234 235 - **0x22** `0xE0` — Display update control sequence 236 - **0x20** — Master activation (trigger update) 237 - Wait ~100ms while BUSY pin is HIGH 238 239 ### Full Refresh 240 241 ```c 242 void ssd1677_update() { 243 epd_cmd(0x22); 244 epd_data(0xC7); // Display mode: load LUT + refresh + power off 245 246 epd_cmd(0x20); // Master activation 247 epd_wait_busy(); // Wait for driving waves to complete 248 } 249 ``` 250 251 **Detailed Sequence:** 252 253 1. **0x21** `0x40, 0x00` — Display update control (bypass RED as 0, single chip) 254 2. For fast mode: **0x1A** `0x5A` (temperature register), then **0x22** `0xD7` 255 3. For normal mode: **0x22** `0xF7` (extended temp) 256 4. **0x20** — Master activation 257 5. Wait ~1600ms while BUSY pin is HIGH 258 259 **Explanation:** 260 - **0x22 / 0xC7** tells SSD1677 which tasks to run (enable analog, load LUT, drive display) 261 - **0x20** starts the entire update cycle 262 - **epd_wait_busy()** waits until the driver finishes waveform driving 263 264 **Fast vs Normal Mode**: `useFastFullUpdate=true` uses faster refresh but limited temperature range. 265 266 ### Display Update Control 2 (0x22) Bit Documentation 267 268 Based on driver implementation analysis: 269 270 - **Bit 7 (0x80)** CLOCK_ON — Start internal oscillator 271 - **Bit 6 (0x40)** ANALOG_ON — Enable analog power rails (VGH/VGL drivers) 272 - **Bit 5 (0x20)** TEMP_LOAD — Load temperature (internal or external) 273 - **Bit 4 (0x10)** LUT_LOAD — Load waveform LUT 274 - **Bit 3 (0x08)** MODE_SELECT — Mode 1/2 selection 275 - **Bit 2 (0x04)** DISPLAY_START — Run display update 276 - **Bit 1 (0x02)** ANALOG_OFF — Analog shutdown phase 277 - **Bit 0 (0x01)** CLOCK_OFF — Disable internal oscillator 278 279 **Common Patterns:** 280 - Full refresh (first power on): `0xC0 | 0x34 = 0xF4` (CLOCK+ANALOG+TEMP+LUT+DISPLAY) 281 - Full refresh (already on): `0x34` (TEMP+LUT+DISPLAY) 282 - Half refresh with high temp: `0xD4` (CLOCK+ANALOG+LUT+DISPLAY) 283 - Fast refresh with custom LUT: `0x0C` (MODE+DISPLAY) 284 - Fast refresh without custom LUT: `0x1C` (LUT+MODE+DISPLAY) 285 286 ### Partial Refresh 287 288 - **0x21** `0x00, 0x00` — Display update control (RED normal, single chip) 289 - **0x22** `0xFC` — Partial update sequence 290 - **0x20** — Master activation 291 - Wait ~600ms while BUSY pin is HIGH 292 293 --- 294 295 ## Custom LUT Guide 296 297 ### What is a LUT? 298 299 The SSD1677 uses a **Look-Up Table (LUT)** to control **pixel waveform driving** during updates. Each pixel (BW/RED) needs a sequence of voltage phases to switch states correctly. 300 301 A LUT controls: 302 - Voltage level per phase (VSH1, VSH2, VSL, Hi-Z) 303 - VCOM toggling pattern 304 - Duration of each phase (TP0-TP7) 305 - Phase repetitions 306 - Additional red-pixel handling 307 308 ### LUT Structure (111 bytes) 309 310 Used in the driver implementation for grayscale support: 311 312 - **Bytes 0-49** (50 bytes) — VS waveforms (5 groups x 10 bytes) 313 - **Bytes 50-99** (50 bytes) — TP/RP timing groups (10 groups x 5 bytes) 314 - **Bytes 100-104** (5 bytes) — Frame rate control 315 - **Byte 105** — VGH (Gate voltage) - sent via 0x03 316 - **Byte 106** — VSH1 (Source voltage 1) - sent via 0x04 317 - **Byte 107** — VSH2 (Source voltage 2) - sent via 0x04 318 - **Byte 108** — VSL (Source voltage low) - sent via 0x04 319 - **Byte 109** — VCOM voltage - sent via 0x2C 320 - **Byte 110** — Reserved 321 322 **Note:** Bytes 105-109 are sent using separate voltage control commands after loading the main LUT. 323 324 ### How to Build a Custom LUT 325 326 **Step 1 — Define Source Voltage Waveform (WS0-WS7)** 327 328 You choose for each phase: 329 - VSH1 (medium positive) 330 - VSH2 (strong positive - drives white) 331 - VSL (strong negative - drives black) 332 - Hi-Z (float) 333 334 These define **pixel movement direction** and strength. 335 336 **Step 2 — Define VCOM Waveform (WS8-WS14)** 337 338 VCOM biases the entire display. These bytes define: 339 - On/off toggling per phase 340 - Matching with source driver phases 341 - Ghost reduction 342 343 **Step 3 — Phase Timing TP0-TP7 (WS15-WS23)** 344 345 Each TPx sets duration of a phase. Longer = cleaner image, slower refresh. Shorter = faster, but potential ghosting. 346 347 **Step 4 — Repeat Counts & Finalization (WS24-WS33)** 348 349 These adjust: 350 - How many times each phase repeats 351 - Red pigment extra driving 352 - Cleanup phases 353 354 ### How to Load a Custom LUT 355 356 A custom LUT is written using **Command 0x32**: 357 358 ``` 359 CMD 0x32 360 DATA WS0 361 DATA WS1 362 ... 363 DATA WS33 364 ``` 365 366 The first **105 bytes** are written to the LUT register (0x32), followed by separate voltage control commands. 367 368 ```c 369 // Load LUT (111-byte format with voltage controls) 370 void ssd1677_load_lut_extended(const uint8_t* lut) { 371 // Load main LUT (105 bytes: VS + TP/RP + frame rate) 372 epd_cmd(0x32); 373 for (int i = 0; i < 105; i++) 374 epd_data(lut[i]); 375 376 // Set voltage values from bytes 105-109 377 epd_cmd(0x03); // Gate voltage (VGH) 378 epd_data(lut[105]); 379 380 epd_cmd(0x04); // Source voltages (VSH1, VSH2, VSL) 381 epd_data(lut[106]); // VSH1 382 epd_data(lut[107]); // VSH2 383 epd_data(lut[108]); // VSL 384 385 epd_cmd(0x2C); // VCOM voltage 386 epd_data(lut[109]); 387 } 388 ``` 389 390 ### How to Apply (Use) the Custom LUT 391 392 After loading the LUT, tell the display to **use it**. 393 394 **1. Configure Display Update Mode (0x22)** 395 396 Typical value enabling LUT usage: 397 ``` 398 CMD 0x22 399 DATA 0xF7 400 ``` 401 402 **2. Start Master Activation (0x20)** 403 404 ``` 405 CMD 0x20 406 WAIT BUSY = LOW 407 ``` 408 409 While BUSY is high, the LUT waveform is driving the display. 410 411 ```c 412 // Apply LUT 413 void ssd1677_apply_lut() { 414 epd_cmd(0x22); 415 epd_data(0xF7); // Use LUT 416 epd_cmd(0x20); // Master Activation 417 epd_wait_busy(); 418 } 419 ``` 420 421 ### LUT Summary 422 423 **Build a custom LUT** — Create 111 bytes: 105 for LUT register + 5 voltage values + 1 reserved 424 425 **Use a custom LUT:** 426 1. Write with **0x32** 427 2. Enable with **0x22** 428 3. Trigger with **0x20** 429 430 **Optional** — Burn to OTP with **0x36** 431 432 ### Grayscale Rendering with Custom LUTs 433 434 The driver implements 4-level grayscale using a multi-pass technique with custom LUTs. 435 436 **Grayscale Principle:** 437 438 1. **First pass (Black/White):** Write BW framebuffer to both RAM buffers, perform standard refresh 439 2. **Second pass (Grayscale):** Write LSB and MSB grayscale buffers, apply custom grayscale LUT, perform fast refresh 440 3. The custom LUT creates intermediate gray levels by controlling pixel voltage phases 441 442 **Grayscale LUT Structure:** 443 444 The driver includes two grayscale LUTs (111 bytes each): 445 - `lut_grayscale`: Forward grayscale rendering 446 - `lut_grayscale_revert`: Cleans up grayscale artifacts back to pure BW 447 448 Key characteristics: 449 - Uses different voltage sequences for 4 gray levels (00, 01, 10, 11) 450 - Frame timing optimized for fast refresh (~500ms) 451 - VS waveforms: 50 bytes (5 groups x 10 bytes) 452 - TP/RP timing: 50 bytes (10 groups x 5 bytes) 453 - Voltages: VGH=0x17, VSH1=0x41, VSH2=0xA8, VSL=0x32, VCOM=0x30 454 455 --- 456 457 ## Complete Workflows 458 459 ### Full Screen Update (Initial or Complete Refresh) 460 461 ``` 462 1. _InitDisplay() [if not initialized] 463 2. _setPartialRamArea(0, 0, 800, 480) 464 3. Write to previous buffer: Command 0x26 + 48000 bytes 465 4. Write to current buffer: Command 0x24 + 48000 bytes 466 5. _Update_Full() 467 ``` 468 469 ### Partial Update (Fast Refresh) 470 471 ``` 472 1. _InitDisplay() [if not initialized] 473 2. [First time only] Clear screen buffers with full refresh 474 3. _setPartialRamArea(x, y, w, h) 475 4. Write image: Command 0x24 + image bytes 476 5. _Update_Part() 477 6. Write image again: Command 0x24 + image bytes 478 7. Write to previous: Command 0x26 + same image bytes 479 ``` 480 481 **Why write twice?** Partial updates compare current vs previous buffer. Writing to both buffers after refresh prevents ghosting on next update. 482 483 ### Minimal Usage Example 484 485 ```c 486 ssd1677_init(); 487 488 ssd1677_display_frame(bw_image, red_image); 489 ``` 490 491 ### Complete Example: Fast Refresh with Double Buffering 492 493 The driver implements double buffering to enable fast partial updates: 494 495 ```cpp 496 // Initialize display 497 display.begin(); 498 display.clearScreen(0xFF); 499 display.displayBuffer(FULL_REFRESH); 500 501 // Draw content to framebuffer 502 uint8_t* fb = display.getFrameBuffer(); 503 // ... draw into fb ... 504 505 // Fast refresh (compares with previous frame) 506 display.displayBuffer(FAST_REFRESH); 507 508 // Next frame 509 // ... modify fb ... 510 display.displayBuffer(FAST_REFRESH); 511 ``` 512 513 **How it works:** 514 1. Two internal buffers (`frameBuffer0` and `frameBuffer1`) alternate as current/previous 515 2. On `displayBuffer()`, current buffer written to BW RAM (0x24), previous to RED RAM (0x26) 516 3. Controller compares buffers and only updates changed pixels 517 4. Buffers swap roles after each display 518 519 ### Auto-Write Commands for Fast Clear 520 521 Commands `0x46` and `0x47` allow rapid buffer clearing: 522 523 ```c 524 // Clear BW RAM to white pattern 525 sendCommand(0x46); // Auto write BW RAM 526 sendData(0xF7); // Fill pattern 527 waitWhileBusy(); 528 529 // Clear RED RAM to white pattern 530 sendCommand(0x47); // Auto write RED RAM 531 sendData(0xF7); // Fill pattern 532 waitWhileBusy(); 533 ``` 534 535 This is much faster than writing 48,000 bytes manually during initialization. 536 537 --- 538 539 ## Command Reference 540 541 - **0x01** Driver Output Control — Set gate scanning (HEIGHT) 542 - **0x03** Gate Voltage — Set VGH voltage level 543 - **0x04** Source Voltage — Set VSH1, VSH2, VSL voltages 544 - **0x0C** Booster Soft Start — Configure boost converter 545 - **0x10** Deep Sleep Mode — Enter low power mode 546 - **0x11** Data Entry Mode — Set X/Y increment direction 547 - **0x12** Software Reset — Reset controller 548 - **0x18** Temperature Sensor — Control temp sensor 549 - **0x1A** Temperature Register — Set temp value (fast mode) 550 - **0x20** Master Activation — Trigger display update 551 - **0x21** Display Update Control — Configure update mode 552 - **0x22** Display Update Sequence — Set update waveform 553 - **0x24** Write RAM (BW) — Write to current buffer 554 - **0x26** Write RAM (RED/OLD) — Write to previous buffer 555 - **0x2C** Write VCOM — Set VCOM voltage 556 - **0x32** Write LUT Register — Load custom 105-byte LUT (part of 111-byte structure) 557 - **0x36** Write OTP — Burn LUT to one-time-programmable memory 558 - **0x3C** Border Waveform — Configure border behavior 559 - **0x44** Set RAM X Address — Define X window (in pixels) 560 - **0x45** Set RAM Y Address — Define Y window (in pixels) 561 - **0x46** Auto Write BW RAM — Fast fill BW RAM with pattern 562 - **0x47** Auto Write RED RAM — Fast fill RED RAM with pattern 563 - **0x4E** Set RAM X Counter — Set initial X position (in pixels) 564 - **0x4F** Set RAM Y Counter — Set initial Y position (in pixels) 565 566 --- 567 568 ## Timing & Power Management 569 570 ### Timing Specifications 571 572 - **Reset pulse** — 10ms low duration 573 - **Power on** — ~100ms BUSY signal duration 574 - **Power off** — ~200ms BUSY signal duration 575 - **Full refresh** — ~1600ms normal mode, wait for BUSY 576 - **Partial refresh** — ~600ms, wait for BUSY 577 - **Software reset delay** — 10ms after command 0x12 578 579 ### BUSY Signal Monitoring 580 581 - **Pin**: GPIO6 (INPUT) 582 - **Active level**: HIGH 583 - **Polling**: Read pin until LOW, with timeout protection 584 - **Timeout**: 10000ms (10 seconds) 585 - **Usage**: Wait after commands `0x20` (master activation) 586 587 ### Power Off 588 589 - **0x22** `0x83` — Power off sequence 590 - **0x20** — Master activation 591 - Wait ~200ms while BUSY pin is HIGH 592 593 ### Hibernate (Deep Sleep) 594 595 1. Execute Power Off sequence 596 2. Send command `0x10` (Deep Sleep Mode) 597 3. Send data `0x01` (Enter deep sleep) 598 599 **Wake from Hibernate**: Requires hardware reset via RST pin. 600 601 --- 602 603 ## Sunlight Fading Issue 604 605 ### Problem 606 607 The XTEINK X4's SSD1677 display driver IC is packaged as "Gold Bump Die" without resin protection. This makes the IC susceptible to UV radiation. In bright sunlight, this causes the screen to fade to white. 608 609 White X4 devices are more affected than black ones due to lower UV absorption by the case. 610 611 ### Solution 612 613 Power down the display's VBUS after rendering each page. This is done by setting the analog shutdown bits in the Display Update Control 2 command (0x22): 614 615 ```c 616 // After refresh, power down display to prevent UV fading 617 sendCommand(0x22); 618 sendData(displayMode | 0x03); // Set ANALOG_OFF_PHASE (bit 1) and CLOCK_OFF (bit 0) 619 sendCommand(0x20); 620 waitWhileBusy(); 621 ``` 622 623 The firmware implements this as the "Sunlight Fading Fix" setting in Device Settings. When enabled: 624 - Sets bits 0 and 1 in the 0x22 command after each refresh 625 - Adds ~100-200ms overhead per page turn (power-on cycle) 626 - Screen will power back on automatically for the next refresh 627 628 This fix was developed by the crosspoint-reader community. 629 630 ### Physical Alternative 631 632 For permanent protection, apply UV-blocking tape over the driver IC area on the display PCB. 633 634 --- 635 636 ## Important Notes 637 638 - BUSY pin *must* be polled after reset and update 639 - All RAM writes auto-increment based on data entry mode 640 - SSD1677 can display BW-only or RED-only if desired 641 - All X coordinates and widths must be multiples of 8 (byte boundaries) 642 - Y coordinates are reversed in hardware (gates bottom-to-top) 643 - RAM auto-increments after each byte transfer 644 - Total RAM size: 48,000 bytes (800x480 / 8) 645 - Dual-buffer system enables differential partial updates 646 - First write after init should be full refresh to clear ghost images 647 - In sunlight: enable "Sunlight Fading Fix" setting to prevent UV-induced screen fading