DEKI/ENGINE 문서
deki-display 0.20.2
Deki 패키지 레퍼런스
deki-display

Deki 자체 디스플레이 라이브러리. 취미용 보드에서 흔히 쓰는 화면을 구동하고, 터치를 읽고, 모든 프레임을 온전히 보냅니다.

저장소: github.com/dekiengine/deki-display · 최신 릴리스: 0.20.0 · 엔진 0.20.0 이상 필요 · 의존: deki-spi, deki-gpio, deki-i2c, deki-input, deki-rendering

DekiEditor --packages-add deki-display <project> 또는 패키지 관리자로 설치합니다. 엔진 자체의 컴포넌트와 C++ API는 Deki 문서에 있습니다.

에디터에는 Display(으)로 표시됩니다.

컴포넌트

컴포넌트 카테고리 설명
DisplayPanelComponent 디스플레이 Deki 자체 디스플레이 라이브러리로 SPI, 쿼드 SPI 또는 8비트·16비트 병렬 버스를 통해 디스플레이 패널(ST7789, ILI9341, GC9A01 등)을 구동하고 엔진에 넘깁니다.
TouchPanelComponent 디스플레이 Deki 자체 디스플레이 라이브러리로 패널의 터치 컨트롤러(I2C의 GT911, CST816, FT5x06; SPI의 XPT2046)를 읽어 포인터 입력으로 사용합니다.

기능 플래그

빌드에서 뺄 수 있는 부분입니다. define이 있는 기능은 그 define으로 켜고 끄며, 나머지는 컴포넌트와 함께 제거됩니다.

기능 define 기본값
Display Panel DEKI_FEATURE_DISPLAY_PANEL 켜짐
Touch Panel DEKI_FEATURE_DISPLAY_TOUCH 켜짐

컴포넌트 레퍼런스

DisplayPanelComponent

Deki 자체 디스플레이 라이브러리로 SPI, 쿼드 SPI 또는 8비트·16비트 병렬 버스를 통해 디스플레이 패널(ST7789, ILI9341, GC9A01 등)을 구동하고 엔진에 넘깁니다.

인스펙터 이름: 디스플레이 패널 컴포넌트 · 카테고리: 디스플레이 · 유형: DekiDisplay::DisplayPanelComponent

속성 유형 기본값 제약 설명
controller enum "ST7789" ST7789, RM67162, ILI9341, ST7735, ST7735S, GC9A01, ST7789P3, ST7796, ILI9488, SSD1351, CO5300 패널의 컨트롤러 IC
initSequence string "" 이 패널 모듈을 시작하는 명령으로, 컨트롤러의 기본 명령을 대신합니다. 패널의 전압, VCOM, 감마는 컨트롤러가 아니라 모듈마다 다르므로 보드가 여기서 설정합니다. 한 줄 또는 ';'마다 명령 하나: 16진수 명령 바이트, 이어서 매개변수 바이트, 필요하면 'delay <ms>'를 씁니다. '#' 뒤는 주석입니다. 비워 두면 컨트롤러의 기본 명령을 사용합니다
panelWidth int32 240 1~1024 회전 전의 보이는 너비 (픽셀)
panelHeight int32 320 1~1024 회전 전의 보이는 높이 (픽셀)
rotation enum "Landscape" Portrait, Landscape, Portrait180, Landscape270, PortraitMirror, LandscapeMirror, Portrait180Mirror, Landscape270Mirror 패널의 방향
offsetX int32 0 컨트롤러 메모리에서 보이는 패널이 시작하는 위치, 가로 방향 (원점이 0이 아닌 패널용)
offsetY int32 0 컨트롤러 메모리에서 보이는 패널이 시작하는 위치, 세로 방향
invertColor bool false 패널 색상을 반전합니다 (대부분의 IPS 패널은 켜야 합니다)
rgbOrder bool false 패널이 빨강을 먼저 받습니다. 끄면 컨트롤러의 BGR 순서를 설정합니다
busType enum "SPI" SPI, QSPI, Parallel8, Parallel16 패널의 배선 방식입니다. 데이터/커맨드 핀이 있는 SPI(대부분의 LCD), 쿼드 SPI(RM67162 같은 AMOLED 패널. IO2와 IO3가 있는 SPI Bus가 필요함), 또는 8비트·16비트 병렬 버스(8080. 이 컴포넌트가 직접 시작함)
spiHost int32 1 0~3; busType이(가) 허용할 때 표시 패널이 연결된 SPI 호스트입니다. 이를 시작하는 SPI Bus 컴포넌트와 같은 번호로 지정합니다 (ESP32-S3에서는 1 = SPI2, 2 = SPI3)
spiWriteHz int32 40000000 busType이(가) 허용할 때 표시 패널의 SPI 클럭입니다. 80 MHz는 ESP32-S3의 최고 속도이며, 대부분의 ST7789 모듈이 지원합니다
parallelWriteHz int32 20000000 busType이(가) 허용할 때 표시 병렬 버스의 쓰기 스트로브 주파수입니다. 대부분의 패널은 20 MHz를 지원하며, 배선이 짧으면 더 높여도 됩니다
dcPin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터/커맨드 핀 (DC, RS라고도 함)
wrPin int32 -1 -1~48; busType이(가) 허용할 때 표시 쓰기 스트로브 핀(WR)
rdPin int32 -1 -1~48; busType이(가) 허용할 때 표시 읽기 스트로브 핀(RD)으로, High로 유지합니다. 패널에는 쓰기만 합니다 (-1 = 보드에서 High로 고정)
d0Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D0
d1Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D1
d2Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D2
d3Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D3
d4Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D4
d5Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D5
d6Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D6
d7Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D7
d8Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D8
d9Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D9
d10Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D10
d11Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D11
d12Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D12
d13Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D13
d14Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D14
d15Pin int32 -1 -1~48; busType이(가) 허용할 때 표시 데이터 라인 D15
csPin int32 -1 -1~48 칩 셀렉트 핀 (-1 = Low에 고정)
rstPin int32 -1 -1~48 리셋 핀 (-1 = 연결 안 됨)
tePin int32 -1 -1~48 패널의 티어링 이펙트(TE) 출력입니다 (-1 = 연결 안 됨). 연결하면 프레임이 찢어지지 않습니다. 각 프레임은 패널이 새로 고침을 시작할 때 보내기 시작하며, 패널 자체의 행 순서로 보냅니다. 회전된 화면은 보낼 때 회전하고 열 스트립으로 그립니다
scanlineSync bool true busType이(가) 허용할 때 표시 TE 선이 연결되어 있지 않으면 대신 패널의 주사선을 읽어 프레임이 여전히 찢어지지 않게 합니다. 다시 읽을 수 없는 패널은 그리는 대로 보내며, 부팅 로그에 그렇게 나옵니다
spiReadHz int32 10000000 scanlineSync이(가) 허용할 때 표시 패널을 다시 읽을 때의 SPI 클럭으로, 쓰기보다 느리게 합니다 (ST7789는 10 MHz에서 안정적으로 읽힘)
readsOnMosi bool false scanlineSync이(가) 허용할 때 표시 패널이 MISO가 아니라 데이터 입력 선으로 응답합니다 (LilyGO T-Deck처럼 SDA가 양방향)
blPin int32 -1 -1~48 백라이트 핀 (-1 = 없음). 켜져 있는 동안 High로 유지합니다. 펄스 수로 밝기를 조절하는 백라이트 드라이버(LilyGO T-Deck의 것)에는 바로 이것이 필요합니다
blInvert bool false 핀이 Low일 때 백라이트가 켜집니다
memoryWidth int32 0 0~1024 컨트롤러 메모리상의 너비로, 보이는 너비보다 클 수 있습니다 (0 = 컨트롤러의 값)
memoryHeight int32 0 0~1024 컨트롤러 메모리상의 높이 (0 = 컨트롤러의 값)
usePsram bool false 프레임 버퍼를 내부 RAM 대신 PSRAM에 둡니다. 화면 한 장 분량의 내부 RAM이 확보되지만, 그리기가 느려집니다
doubleBuffer bool false 프레임 버퍼 두 개를 쓰고 매 프레임 후 교체합니다
asyncPresent bool true 다음 프레임을 그리는 동안 칩의 다른 코어에서 각 프레임을 보냅니다. 한 프레임에 걸리는 시간은 그리기와 보내기의 합이 아니라 더 긴 쪽이 됩니다. 듀얼 코어 칩과 외부 메모리(PSRAM) 두 프레임 분량이 필요하며, 없으면 그리는 대로 보내고 부팅 로그에 그렇게 나옵니다

TouchPanelComponent

Deki 자체 디스플레이 라이브러리로 패널의 터치 컨트롤러(I2C의 GT911, CST816, FT5x06; SPI의 XPT2046)를 읽어 포인터 입력으로 사용합니다.

인스펙터 이름: 터치 패널 컴포넌트 · 카테고리: 디스플레이 · 유형: DekiDisplay::TouchPanelComponent

속성 유형 기본값 제약 설명
controller enum "GT911" GT911, CST816, FT5x06, XPT2046 터치 컨트롤러 IC
i2cPort int32 0 0~3; controller이(가) 허용할 때 표시 연결된 I2C 포트 (이 컴포넌트보다 먼저 I2C Bus 컴포넌트가 그 포트를 시작해야 합니다)
i2cAddress int32 0 0~127; controller이(가) 허용할 때 표시 I2C 주소입니다. 0이면 컨트롤러의 일반 주소를 사용합니다 (GT911: 0x5D, 응답이 없으면 0x14; CST816: 0x15; FT5x06: 0x38)
spiHost int32 1 0~3; controller이(가) 허용할 때 표시 연결된 SPI 호스트입니다. 이를 시작하는 SPI Bus 컴포넌트와 같은 번호로 지정합니다 (보통 디스플레이와 같음)
csPin int32 -1 -1~48; controller이(가) 허용할 때 표시 칩 셀렉트 핀
spiHz int32 1000000 controller이(가) 허용할 때 표시 터치 컨트롤러의 SPI 클럭입니다. XPT2046은 1 MHz에서 잘 읽히며 최대 2.5 MHz까지 지원합니다
intPin int32 -1 -1~48 인터럽트 핀: 읽을 터치 보고가 있거나 눌려 있는 동안(XPT2046의 PENIRQ) 컨트롤러가 Low로 내립니다 (-1 = 연결 안 됨, 매 프레임 읽음)
rstPin int32 -1 -1~48; controller이(가) 허용할 때 표시 리셋 핀 (-1 = 연결 안 됨)
xMin int32 0 터치 컨트롤러가 보고하는 원시 X의 최솟값으로, 디스플레이를 회전하기 전 패널의 너비 방향 값입니다 (정전식: 0; XPT2046은 약 300부터 시작하며 보정이 필요함)
xMax int32 239 터치 컨트롤러가 보고하는 원시 X의 최댓값으로, 디스플레이를 회전하기 전 패널의 너비 방향 값입니다 (240x320 패널을 가로로 표시하는 경우: 239)
yMin int32 0 터치 컨트롤러가 보고하는 원시 Y의 최솟값으로, 디스플레이를 회전하기 전 패널의 높이 방향 값입니다
yMax int32 319 터치 컨트롤러가 보고하는 원시 Y의 최댓값으로, 디스플레이를 회전하기 전 패널의 높이 방향 값입니다 (240x320 패널을 가로로 표시하는 경우: 319)
offsetRotation enum "None" None, CW_90, CW_180, CW_270, Mirror, Mirror_CW_90, Mirror_CW_180, Mirror_CW_270 패널에 대한 터치 컨트롤러의 방향으로, 디스플레이 회전에 더해집니다. 컨트롤러가 패널 자체의 방향으로 좌표를 보고하면 없음입니다

변경 내역

변경 내역은 영어로 되어 있습니다.

0.20.0

Changed

  • minEngine 0.20.0: built against engine 0.20.0. A build of this package from before does not load and is rebuilt.

Added

  • The package: DisplayPanelComponent, which starts a panel on a deki-spi bus from the boot scene and gives the engine PanelDisplay, a Deki::IDisplay presenting whole frames and changed rectangles with the UI overlay blended over them; PanelController, a MIPI DCS controller driven by a table per controller (ST7789 first, its start-up and MADCTL ported from LovyanGFX); SpiPanelIO, 4-wire SPI with pixels queued for DMA; and initSequence, a board's own start-up for its panel module, as text.
  • Async present (asyncPresent): each frame is sent from the other core while the next is drawn. A whole frame is copied, swapped into the wire's byte order as it is copied, to one of two copies in external DMA memory, and sent from there by DMA in parts as long as the bus takes, with no bands in internal RAM; a strip is copied to one of two copies in internal DMA memory and swapped in place a chunk at a time. The worker holds the bus across back-to-back frames and strips, with each one's window commands queued behind the one before, so the wire does not wait between them; a copy goes back to the drawing core as soon as its last part is sent. The platform runs the worker through PanelDisplay::SetWorkerBackend (deki-esp32-integration: a FreeRTOS task pinned to the other core). On a LilyGO T-Deck Plus at 80 MHz with the frame rate uncapped: 63.2 fps in whole frames with 83.6 KB of internal RAM free, 61.0 in strips of 40 rows (LovyanGFX: 62.6 with 73.8 KB, and 60.2).
  • Touch: TouchPanelComponent starts a GT911 (GT911Touch, ported from LovyanGFX's driver) on a deki-i2c bus, shared with whatever else is on it, and gives deki-input PanelTouchInput: a press, moves and a release at screen pixels, turned with the display by TouchMapper (LovyanGFX's default calibration and rotation, so a board's touch bounds carry over). Without an INT pin, a point that stops changing is released and not pressed again until it moves.
  • QSPI panels: DisplayPanelComponent's busType QSPI drives an AMOLED through QspiPanelIO (each register write framed 0x02, pixels 0x32 on four lines, as LovyanGFX frames them). The RM67162 is the first: its start-up, MADCTL and offsets ported from LovyanGFX, rows widened to even, and brightness by command where an LCD has a backlight.
  • The CST816S/T touch controller (TouchController::CST816). It sleeps, and does not answer on I2C, until touched: it is set up when it first answers, and a read it does not answer is no touch.
  • Async present works with render buffers (usePsram, doubleBuffer) too: the worker sends a copy, so the engine never draws into what is being sent.
  • Tear-free presenting: DisplayPanelComponent's tePin, the panel's tearing-effect output. A panel refreshes its own rows one after another, and a frame written while the refresh passes shows half of each frame. With TE on (0x35), each frame starts as the panel starts a refresh, and goes in the panel's own row order, which a write outruns the refresh in. A screen shown turned is turned as it is sent: the controller stays at its own orientation, and the renderer is asked for strips of columns in the order the panel refreshes them (deki-rendering's IScanOrderedDisplay). With async present the worker does the turning, a band at a time while the band before it is on the wire. Whole frames and strips both. A TE line that never pulses is said once in the log, and frames go on without waiting. On a LilyGO T-Display S3 AMOLED (its panel refreshes at 59.6 Hz): 59.5 fps in strips with no tearing, and 28.6 in whole frames, which take 25 ms to draw in PSRAM.
  • More controllers, each a table ported from LovyanGFX 1.2.29: ILI9341, ST7735 (the B version), ST7735S (the R version), GC9A01, ST7789P3, ST7796, ILI9488 and SSD1351 on SPI or a parallel bus, and the CO5300 AMOLED on QSPI. A controller names its own commands (ControllerCommands): the SSD1351's window is a byte a coordinate, its column and row commands trade places when turned, and its remap takes MADCTL's place. The GC9A01 opens its rows before a turned window's columns, as LovyanGFX does. Checked against LovyanGFX's bytes in tests; none has run on a board yet.
  • 18 bits a pixel: the ILI9488 takes no RGB565 over SPI, so its pixels go out as RGB666 through Rgb666PanelIO, which widens each piece into its own DMA buffers while the piece before is sent, and COLMOD is 0x66.
  • Parallel panels: busType Parallel8 and Parallel16, an 8080 bus of 8 or 16 data lines with DC, WR and RD pins and its write clock (parallelWriteHz). The platform drives the bus (ParallelBus, a factory it registers; ParallelPanelIO speaks to it), and the component starts it itself. On 16 lines a pixel goes as memory holds it, so a little-endian frame needs no byte swap.
  • Touch: the FT5x06 family (FT5206, FT6206, FT6336 and others) on I2C, and the XPT2046 resistive controller on SPI, both ported from LovyanGFX. The XPT2046's raw readings need calibrating in the touch bounds. A controller whose count or pressure says when the finger has gone (ITouchController::MayRepeatLastTouch false) is not released for holding still.
  • Tear-free: a frame that missed its refresh's start is started for the longest write any frame has taken (PanelDisplay::LongestWriteUs), not the shorter of the last two. The frame that opens a new scene is late (the scene loads in it) and changes the whole screen, while the frames before it changed a little: started for theirs, it began too late, the refresh caught it, and the screen tore across.
  • Tear-free with no TE line: scanlineSync reads the panel's scanline (Get_Scanline, 0x45) back through the panel IO (IPanelIO::Read) at its own clock (spiReadHz), on MISO or, with readsOnMosi, on the panel's data line. ScanlineClock finds two refresh starts, where the count drops from the last row to the blanking (it holds there; the low byte rolling over at row 256 does not), and keeps the clock right with each start it catches. On a LilyGO T-Deck Plus: 60.2 Hz found, every demo scene at 60 fps with frames in step with the refresh.
  • A frame that takes about a refresh to go out, or up to two, is started just behind the refresh rather than at once (PanelDisplay::WritesBehind): it never catches the refresh's rows up, and the next refresh shows it whole. Before, such a frame was taken to tear wherever it started.
  • A turned frame is read a screen row at a time while it is turned, a run of neighbouring pixels from each, instead of one pixel per screen row: a whole frame in PSRAM, turned on the way out, went from 47.8 fps to 60 on the T-Deck Plus.
  • asyncPresent and scanlineSync are on by default: a board gets frames sent from the other core, and tear-free frames without a TE line, where it can. Where it cannot (one core, no PSRAM for the copies, a panel that cannot be read back) frames are sent as they are drawn, and the boot log says so as information, not an error. Scenes that set them keep what they set.

이전 릴리스: CHANGELOG.md


패키지의 리플렉션 데이터에서 생성했습니다(엔진 0.20.2). 속성 이름은 씬 파일에서 쓰는 키입니다. 이름을 바꿔도 별칭이 유지됩니다(호환성).