@@ -197,11 +197,22 @@ void EPDDriver::display(bool _leaveOn)
197197void EPDDriver::displayPartial (int16_t x, int16_t y, int16_t w, int16_t h, bool _leaveOn)
198198{
199199 // Clip to the screen bounds for the current rotation.
200- if (x < 0 ) { w += x; x = 0 ; }
201- if (y < 0 ) { h += y; y = 0 ; }
202- if (x + w > _inkplate->width ()) w = _inkplate->width () - x;
203- if (y + h > _inkplate->height ()) h = _inkplate->height () - y;
204- if (w <= 0 || h <= 0 ) return ;
200+ if (x < 0 )
201+ {
202+ w += x;
203+ x = 0 ;
204+ }
205+ if (y < 0 )
206+ {
207+ h += y;
208+ y = 0 ;
209+ }
210+ if (x + w > _inkplate->width ())
211+ w = _inkplate->width () - x;
212+ if (y + h > _inkplate->height ())
213+ h = _inkplate->height () - y;
214+ if (w <= 0 || h <= 0 )
215+ return ;
205216
206217 // Map user rectangle to panel-native rectangle.
207218 // Panel native: col = 0..E_INK_WIDTH-1 (1199), row = 0..E_INK_HEIGHT-1 (1599).
@@ -212,100 +223,109 @@ void EPDDriver::displayPartial(int16_t x, int16_t y, int16_t w, int16_t h, bool
212223 case 0 :
213224 // User space: E_INK_WIDTH × E_INK_HEIGHT.
214225 // panel_col = (E_INK_WIDTH-1) - x, panel_row = (E_INK_HEIGHT-1) - y.
215- colStart = (int16_t )E_INK_WIDTH - x - w;
216- colEnd = (int16_t )E_INK_WIDTH - 1 - x;
226+ colStart = (int16_t )E_INK_WIDTH - x - w;
227+ colEnd = (int16_t )E_INK_WIDTH - 1 - x;
217228 rowStart = (int16_t )E_INK_HEIGHT - y - h;
218- rowEnd = (int16_t )E_INK_HEIGHT - 1 - y;
229+ rowEnd = (int16_t )E_INK_HEIGHT - 1 - y;
219230 break ;
220231 case 2 :
221232 // User space: E_INK_WIDTH × E_INK_HEIGHT.
222233 // panel_col = x, panel_row = y (identity — no transform applied in writePixelInternal).
223234 colStart = x;
224- colEnd = x + w - 1 ;
235+ colEnd = x + w - 1 ;
225236 rowStart = y;
226- rowEnd = y + h - 1 ;
237+ rowEnd = y + h - 1 ;
227238 break ;
228239 case 3 :
229240 // User space: E_INK_HEIGHT × E_INK_WIDTH.
230241 // panel_col = (E_INK_WIDTH-1) - y, panel_row = x.
231242 colStart = (int16_t )E_INK_WIDTH - y - h;
232- colEnd = (int16_t )E_INK_WIDTH - 1 - y;
243+ colEnd = (int16_t )E_INK_WIDTH - 1 - y;
233244 rowStart = x;
234- rowEnd = x + w - 1 ;
245+ rowEnd = x + w - 1 ;
235246 break ;
236247 default :
237248 case 1 :
238249 // User space: E_INK_HEIGHT × E_INK_WIDTH.
239250 // panel_col = y, panel_row = (E_INK_HEIGHT-1) - x.
240251 colStart = y;
241- colEnd = y + h - 1 ;
252+ colEnd = y + h - 1 ;
242253 rowStart = (int16_t )E_INK_HEIGHT - x - w;
243- rowEnd = (int16_t )E_INK_HEIGHT - 1 - x;
254+ rowEnd = (int16_t )E_INK_HEIGHT - 1 - x;
244255 break ;
245256 }
246257
247258 // PTLW alignment requirements (GDEP133C02):
248259 // H: colStart and (colEnd+1) must both be multiples of 4.
249260 // V: rowStart must be even; (rowEnd+1) must be even.
250261 colStart = (colStart / 4 ) * 4 ;
251- colEnd = (((colEnd + 4 ) / 4 ) * 4 ) - 1 ;
252- if (colEnd >= (int16_t )E_INK_WIDTH) colEnd = (int16_t )E_INK_WIDTH - 1 ;
253- if (rowStart % 2 != 0 ) rowStart--;
254- if (rowStart < 0 ) rowStart = 0 ;
255- if ((rowEnd + 1 ) % 2 != 0 ) rowEnd++;
256- if (rowEnd >= (int16_t )E_INK_HEIGHT) rowEnd = (int16_t )E_INK_HEIGHT - 1 ;
262+ colEnd = (((colEnd + 4 ) / 4 ) * 4 ) - 1 ;
263+ if (colEnd >= (int16_t )E_INK_WIDTH)
264+ colEnd = (int16_t )E_INK_WIDTH - 1 ;
265+ if (rowStart % 2 != 0 )
266+ rowStart--;
267+ if (rowStart < 0 )
268+ rowStart = 0 ;
269+ if ((rowEnd + 1 ) % 2 != 0 )
270+ rowEnd++;
271+ if (rowEnd >= (int16_t )E_INK_HEIGHT)
272+ rowEnd = (int16_t )E_INK_HEIGHT - 1 ;
257273
258274 setPanelState (true );
259275
260276 const int16_t HALF_WIDTH = (int16_t )(E_INK_WIDTH / 2 ); // 600 pixels per chip
261- const int16_t HALF_BYTES = HALF_WIDTH / 2 ; // 300 bytes per row per chip
277+ const int16_t HALF_BYTES = HALF_WIDTH / 2 ; // 300 bytes per row per chip
262278
263279 bool masterNeeded = (colStart < HALF_WIDTH);
264- bool slaveNeeded = (colEnd >= HALF_WIDTH);
280+ bool slaveNeeded = (colEnd >= HALF_WIDTH);
265281
266282 // Both chips must receive a full PTLW+DTM cycle before DRF, otherwise the
267283 // uninvolved chip falls back to a full-panel refresh when DRF fires.
268284 // For the uninvolved chip, a minimal 4×4 null window is used: it reads the
269285 // existing framebuffer data (same as what is already on screen) so the
270286 // refresh produces no visible change on that side.
271287 static const uint8_t ptlwNull[9 ] = {
272- 0x00 , 0x00 , // HRST = 0
273- 0x00 , 0x07 , // HRED = 7
274- 0x00 , 0x00 , // VRST = 0
275- 0x00 , 0x01 , // VRED = 1
276- 0x01 // PT = 1 (enable)
288+ 0x00 , 0x00 , // HRST = 0
289+ 0x00 , 0x07 , // HRED = 7
290+ 0x00 , 0x00 , // VRST = 0
291+ 0x00 , 0x01 , // VRED = 1
292+ 0x01 // PT = 1 (enable)
277293 };
278294
279295 // Master chip
280296 {
281- uint8_t ptlwData[9 ];
282- int16_t bytesPerRow, memColOff, rStart, rEnd;
297+ uint8_t ptlwData[9 ];
298+ int16_t bytesPerRow, memColOff, rStart, rEnd;
283299
284300 if (masterNeeded)
285301 {
286- int16_t lcs = colStart;
287- int16_t lce = (colEnd < HALF_WIDTH) ? colEnd : (HALF_WIDTH - 1 );
288- uint16_t HRST = (uint16_t )lcs * 2 ;
289- uint16_t HRED = (uint16_t )(lce + 1 ) * 2 - 1 ;
290- uint16_t VRST = (uint16_t )rowStart / 2 ;
291- uint16_t VRED = (uint16_t )(rowEnd + 1 ) / 2 - 1 ;
292- ptlwData[0 ] = HRST >> 8 ; ptlwData[1 ] = HRST & 0xFF ;
293- ptlwData[2 ] = HRED >> 8 ; ptlwData[3 ] = HRED & 0xFF ;
294- ptlwData[4 ] = VRST >> 8 ; ptlwData[5 ] = VRST & 0xFF ;
295- ptlwData[6 ] = VRED >> 8 ; ptlwData[7 ] = VRED & 0xFF ;
302+ int16_t lcs = colStart;
303+ int16_t lce = (colEnd < HALF_WIDTH) ? colEnd : (HALF_WIDTH - 1 );
304+ uint16_t HRST = (uint16_t )lcs * 2 ;
305+ uint16_t HRED = (uint16_t )(lce + 1 ) * 2 - 1 ;
306+ uint16_t VRST = (uint16_t )rowStart / 2 ;
307+ uint16_t VRED = (uint16_t )(rowEnd + 1 ) / 2 - 1 ;
308+ ptlwData[0 ] = HRST >> 8 ;
309+ ptlwData[1 ] = HRST & 0xFF ;
310+ ptlwData[2 ] = HRED >> 8 ;
311+ ptlwData[3 ] = HRED & 0xFF ;
312+ ptlwData[4 ] = VRST >> 8 ;
313+ ptlwData[5 ] = VRST & 0xFF ;
314+ ptlwData[6 ] = VRED >> 8 ;
315+ ptlwData[7 ] = VRED & 0xFF ;
296316 ptlwData[8 ] = 0x01 ;
297317 bytesPerRow = (lce - lcs + 1 ) / 2 ;
298- memColOff = lcs / 2 ;
299- rStart = rowStart;
300- rEnd = rowEnd;
318+ memColOff = lcs / 2 ;
319+ rStart = rowStart;
320+ rEnd = rowEnd;
301321 }
302322 else
303323 {
304324 memcpy (ptlwData, ptlwNull, 9 );
305- bytesPerRow = 2 ; // 4 px / 2 px-per-byte
306- memColOff = 0 ; // top-left corner of master's region
307- rStart = 0 ;
308- rEnd = 3 ;
325+ bytesPerRow = 2 ; // 4 px / 2 px-per-byte
326+ memColOff = 0 ; // top-left corner of master's region
327+ rStart = 0 ;
328+ rEnd = 3 ;
309329 }
310330
311331 SPI.beginTransaction (epdSpiSettings);
@@ -334,34 +354,38 @@ void EPDDriver::displayPartial(int16_t x, int16_t y, int16_t w, int16_t h, bool
334354 // Slave chip
335355 waitForBusy ();
336356 {
337- uint8_t ptlwData[9 ];
338- int16_t bytesPerRow, memColOff, rStart, rEnd;
357+ uint8_t ptlwData[9 ];
358+ int16_t bytesPerRow, memColOff, rStart, rEnd;
339359
340360 if (slaveNeeded)
341361 {
342- int16_t lcs = (colStart >= HALF_WIDTH) ? (colStart - HALF_WIDTH) : 0 ;
343- int16_t lce = colEnd - HALF_WIDTH;
344- uint16_t HRST = (uint16_t )lcs * 2 ;
345- uint16_t HRED = (uint16_t )(lce + 1 ) * 2 - 1 ;
346- uint16_t VRST = (uint16_t )rowStart / 2 ;
347- uint16_t VRED = (uint16_t )(rowEnd + 1 ) / 2 - 1 ;
348- ptlwData[0 ] = HRST >> 8 ; ptlwData[1 ] = HRST & 0xFF ;
349- ptlwData[2 ] = HRED >> 8 ; ptlwData[3 ] = HRED & 0xFF ;
350- ptlwData[4 ] = VRST >> 8 ; ptlwData[5 ] = VRST & 0xFF ;
351- ptlwData[6 ] = VRED >> 8 ; ptlwData[7 ] = VRED & 0xFF ;
362+ int16_t lcs = (colStart >= HALF_WIDTH) ? (colStart - HALF_WIDTH) : 0 ;
363+ int16_t lce = colEnd - HALF_WIDTH;
364+ uint16_t HRST = (uint16_t )lcs * 2 ;
365+ uint16_t HRED = (uint16_t )(lce + 1 ) * 2 - 1 ;
366+ uint16_t VRST = (uint16_t )rowStart / 2 ;
367+ uint16_t VRED = (uint16_t )(rowEnd + 1 ) / 2 - 1 ;
368+ ptlwData[0 ] = HRST >> 8 ;
369+ ptlwData[1 ] = HRST & 0xFF ;
370+ ptlwData[2 ] = HRED >> 8 ;
371+ ptlwData[3 ] = HRED & 0xFF ;
372+ ptlwData[4 ] = VRST >> 8 ;
373+ ptlwData[5 ] = VRST & 0xFF ;
374+ ptlwData[6 ] = VRED >> 8 ;
375+ ptlwData[7 ] = VRED & 0xFF ;
352376 ptlwData[8 ] = 0x01 ;
353377 bytesPerRow = (lce - lcs + 1 ) / 2 ;
354- memColOff = HALF_BYTES + lcs / 2 ;
355- rStart = rowStart;
356- rEnd = rowEnd;
378+ memColOff = HALF_BYTES + lcs / 2 ;
379+ rStart = rowStart;
380+ rEnd = rowEnd;
357381 }
358382 else
359383 {
360384 memcpy (ptlwData, ptlwNull, 9 );
361- bytesPerRow = 2 ; // 4 px / 2 px-per-byte
362- memColOff = HALF_BYTES; // top-left corner of slave's region
363- rStart = 0 ;
364- rEnd = 3 ;
385+ bytesPerRow = 2 ; // 4 px / 2 px-per-byte
386+ memColOff = HALF_BYTES; // top-left corner of slave's region
387+ rStart = 0 ;
388+ rEnd = 3 ;
365389 }
366390
367391 SPI.beginTransaction (epdSpiSettings);
0 commit comments