SPI
다음 시나리오는 SPI를 사용해 TouchGFX Generator에서 "Custom" 디스플레이 인터페이스를 선택할 때 TouchGFX 드라이버 생성과 관련된 단계들을 보여줍니다. 이러한 단계들은 MCU에 임베디드 디스플레이 컨트롤러가 장착되지 않은 다른 디스플레이 인터페이스의 단계들과 동일합니다.
일단 STM32CubeMX에서 SPI 주변 장치가 구성되면 TouchGFX Generator에서 "Custom" 디스플레이 인터페이스를 이용해 HAL을 생성할 수 있습니다. 따라서 개발자는 직접 작성한 독점 드라이버를 사용해 프레임 버퍼의 업데이트된 부분을 연결된 디스플레이로 전송할 수 있습니다. 그림 X는 Custom 디스플레이 인터페이스를 선택하면 생성된 코드에서 프레임 버퍼의 업데이트된 부분이 디스플레이로 전송될 수 있도록 하는 TouchGFX Generator 구성을 보여줍니다.
일반적으로, 8080 또는 SPI 디스플레이 같이 임베디드 GRAM이 장착된 디스플레이의 경우에는 드라이버가 다음과 같이 구성됩니다.
- 다시 그리고자 하는 프레임 버퍼의 영역을 기준으로 이와 일치하는 GRAM의 한 장소로 "디스플레이 커서"를 이동시킵니다.
- GRAM에 입력되는 픽셀 데이터를 기록할 준비를 합니다.
- 픽셀 데이터를 전송합니다.
프레임 버퍼 전송
프레임 버퍼의 영역이 업데이트되면 TouchGFX Engine은 HAL::flushFrameBuffer
를 호출합니다.
TouchGFX Engine에서 나온 신호(S?)에 반응합니다.
void TouchGFXHAL::flushFrameBuffer(const Rect& rect)
{
/* Set Cursor */
__ST7789H2_SetDisplayWindow(rect.x, rect.y, rect.width, rect.height);
/* Prepare to write to LCD RAM */
ST7789H2_WriteReg(ST7789H2_WRITE_RAM, (uint8_t*)NULL, 0);
/* Send Pixels */
this->copyFrameBufferBlockToLCD(rect);
}
아래의 __ST7789H2_SetDisplayWindow
함수는 GRAM을 사용하는 디스플레이에서 보통 그러하듯이 특정 레지스터에 기록하여 GRAM의 가상 "cursor"에 대한 x
, y
좌표를 설정합니다.
extern "C"
void __ST7789H2_SetDisplayWindow(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
{
uint8_t parameter[4];
/* CASET: Column Address Set */
parameter[0] = 0x00;
parameter[1] = Xpos;
parameter[2] = 0x00;
parameter[3] = Xpos + Width - 1;
ST7789H2_WriteReg(ST7789H2_CASET, parameter, 4);
/* RASET: Row Address Set */
parameter[0] = 0x00;
parameter[1] = Ypos;
parameter[2] = 0x00;
parameter[3] = Ypos + Height - 1;
ST7789H2_WriteReg(ST7789H2_RASET, parameter, 4);
}
아래의 TouchGFXHAL::copyFrameBufferBlockToLCD
함수는 업데이트된 영역(Rect
)의 라인을 한번에 하나씩 전송하고 프레임 버퍼 포인터를 그에 맞게 진행되게 하는 비공개 함수입니다.
void TouchGFXHAL::copyFrameBufferBlockToLCD(const Rect rect)
{
__IO uint16_t* ptr;
uint32_t height;
// Use default implementation (CPU copy!).
// This can be accelerated using regular DMA hardware
for (height = 0; height < rect.height ; height++)
{
ptr = getClientFrameBuffer() + rect.x + (height + rect.y) * BSP_LCD_GetXSize();
LCD_IO_WriteMultipleData((uint16_t*)ptr, rect.width);
}
}
flushFrameBuffer에서 반환
이 함수가 반환되면 TouchGFX Engine은 해당 함수로 돌아갑니다. DMA를 사용해 전송을 하고 싶은 개발자는 DMA Completed 인터럽트에서 신호가 전송되는 세마포어에서 대기함으로써 HAL::flushFrameBuffer(Rect& rect)
가 반환되지 않도록 해야 합니다.