#pragma once #include // Spans track dirty rectangular areas on screen struct Span { uint16_t x, endX, y, endY, lastScanEndX; uint32_t size; // Specifies a box of width [x, endX[ * [y, endY[, where scanline endY-1 can be partial, and ends in lastScanEndX. Span *next; // Maintain a linked skip list inside the array for fast seek to next active element when pruning }; extern Span *spans; // Looking at SPI communication in a logic analyzer, it is observed that waiting for the finish of an SPI command FIFO causes pretty exactly one byte of delay to the command stream. // Therefore the time/bandwidth cost of ending the current span and starting a new span is as follows: // 1 byte to wait for the current SPI FIFO batch to finish, // +1 byte to send the cursor X coordinate change command, // +1 byte to wait for that FIFO to flush, // +2 bytes to send the new X coordinate, // +1 byte to wait for the FIFO to flush again, // +1 byte to send the data_write command, // +1 byte to wait for that FIFO to flush, // after which the communication is ready to start pushing pixels. This totals to 8 bytes, or 4 pixels, meaning that if there are 4 unchanged pixels or less between two adjacent dirty // spans, it is all the same to just update through those pixels as well to not have to wait to flush the FIFO. #if defined(ALL_TASKS_SHOULD_DMA) #define SPAN_MERGE_THRESHOLD 320 #elif defined(DISPLAY_SPI_BUS_IS_16BITS_WIDE) #define SPAN_MERGE_THRESHOLD 10 #elif defined(HX8357D) #define SPAN_MERGE_THRESHOLD 6 #else #define SPAN_MERGE_THRESHOLD 4 #endif void DiffFramebuffersToSingleChangedRectangle(uint16_t *framebuffer, uint16_t *prevFramebuffer, Span *&head); void DiffFramebuffersToScanlineSpansExact(uint16_t *framebuffer, uint16_t *prevFramebuffer, bool interlacedDiff, int interlacedFieldParity, Span *&head); void DiffFramebuffersToScanlineSpansFastAndCoarse4Wide(uint16_t *framebuffer, uint16_t *prevFramebuffer, bool interlacedDiff, int interlacedFieldParity, Span *&head); void NoDiffChangedRectangle(Span *&head); void MergeScanlineSpanList(Span *listHead);