Vivado와 Vitis를 이용한 Pmod OLED 제어 [Pmod IP 이용]
이번 게시글에서는 Digilent의 게시물과 IP 라이브러리를 통해 Pmod OLED의 데모 파일 구현을 진행합니다. 추후 이를 응용하여 Pmod OLED를 통해 다양한 기능을 구현할 예정입니다. Vivado, Vitis 이용방법
semicon-circuit.tistory.com
지난 게시글에서 Vivado에서 Pmod IP를 이용해 하드웨어 파일을 만들고, Vitis로 Pmod OLED 데모 파일을 실행하는 과정까지 포스팅했습니다,
이번 게시글에서는 이어서 직접 비트맵 파일을 Pmod OLED에 표시해보는 작업을 진행합니다.
앞으로 이 디스플레이를 이용해 구글의 공룡게임을 구현할 예정입니다.
먼저 공룡의 모습과 선인장을 픽셀로 표현하기 위해 아래 사이트에서 128x32px의 캔버스에 픽셀로 그림을 그렸습니다.
Make pixel art online - Pixilart
Pixilart, free online pixel drawing tool - This drawing tool allows you to make pixel art, game sprites and animated GIFs online for free.
www.pixilart.com
이제 이 그림을 비트맵으로 저장하고, vitis로 Pmod OLED 디스플레이로 전송하기 위해 1차원 배열로 값을 변환해야 합니다. 이 과정에서는 아래 사이트를 통해 비트맵 이미지를 배열로 전환했습니다.
image2cpp
javl.github.io
세팅은 다음과 같이 진행했습니다. 기존에 다른 사이트를 이용했을 때에는 하단에 Draw mode 선택항목이 없어 표기된 오류같이 이상하게 그림이 출력되었는데, 이 사이트에서 설정을 Vertical로 변경해 해결할 수 있었습니다.
이 사이트를 통해 얻은 공룡+선인장 비트맵 파일의 배열입니다.
// 'dinoncactus', 128x32px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe0, 0xc0, 0x80, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0,
0xf8, 0xff, 0x7f, 0x7e, 0x4b, 0xcb, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xfc, 0xfc, 0x80, 0x80, 0xe0,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x7f, 0x5f, 0x0f, 0x07, 0x0f, 0x7f,
0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0xff, 0x04, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x06, 0x06, 0xff, 0xff, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
이제 이 배열을 헤더파일로 포함시킬건데, Vitis에서 PmodOLED의 src폴더를 우클릭하여 새파일을 생성한 뒤, dinoncactus.h파일로 이름을 변경하고 다음과 같이 배열을 선언했습니다.
#define DINONCACTUS_HEIGHT 32
#define DINONCACTUS_WIDTH 128
// array size is 512
const char dinoncactus[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe0, 0xc0, 0x80, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0,
0xf8, 0xff, 0x7f, 0x7e, 0x4b, 0xcb, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xfc, 0xfc, 0x80, 0x80, 0xe0,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x7f, 0x5f, 0x0f, 0x07, 0x0f, 0x7f,
0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0xff, 0x04, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x06, 0x06, 0xff, 0xff, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
이후 main.c 파일에서 위 헤더 파일을 #include "dinoncactus.h"로 포함시킨 뒤, 기존의 DemoRun함수를 참고하여 비트맵을 프린트하는 displayBitmap 함수를 아래와 같이 선언하고, main함수 내에서 작동하도록 코드를 작성했습니다.
int main() {
DemoInitialize();
displayBitmap();
//DemoRun();
DemoCleanup();
return 0;
}
void DemoInitialize() {
EnableCaches();
OLED_Begin(&myDevice, XPAR_PMODOLED_0_AXI_LITE_GPIO_BASEADDR,
XPAR_PMODOLED_0_AXI_LITE_SPI_BASEADDR, orientation, invert);
}
/* ------------------------------------------------------------ */
/*** displayBitmap()
**
** Parameters:
** none
**
** Return Value:
** none
**
** Errors:
** If the demo is shut down without properly exiting, does not reinitialize
** properly.
**
** Description:
** to display dinoncactus bitmap
*/
void displayBitmap() {
OLED_ClearBuffer(&myDevice);
OLED_MoveTo(&myDevice, 0, 0); // (0,0)에서 출력 시작
//OLED_PutBmp(&myDevice, 128, 32, dinoncactus); // 비트맵 출력
OLED_Update(&myDevice); // OLED 화면 업데이트
u8 *pat;
char c;
xil_printf("print dinosaur and cactus");
while (1) {
xil_printf("entering loop\r\n");
// Choosing Fill pattern 0
pat = OLED_GetStdPattern(0);
OLED_SetFillPattern(&myDevice, pat);
// Turn automatic updating off
OLED_SetCharUpdate(&myDevice, 0);
// Draw a rectangle in center of screen
// Display the 8 different patterns available
OLED_SetDrawMode(&myDevice, OledModeSet);
OLED_ClearBuffer(&myDevice); // 화면 버퍼 초기화
OLED_MoveTo(&myDevice, 0, 0); // (0,0) 좌표에서 비트맵 출력 시작
//OLED_GetBmp(&myDevice, 128, 128, dinoncactus);
OLED_PutBmp(&myDevice, DINONCACTUS_WIDTH, DINONCACTUS_HEIGHT, dinoncactus);
OLED_Update(&myDevice); // OLED 화면 업데이트
#ifdef __MICROBLAZE__
c = 'q';
#else
xil_printf("(q)uit or any key to continue:\n\r");
c = inbyte();
#endif
if (c == 'q' || c == 'Q')
break;
}
xil_printf("Exiting PmodOLED Demo\n\r");
}
void DemoCleanup() {
OLED_End(&myDevice);
DisableCaches();
}
이제 이전 게시글에서와 마찬가지로 프로젝트를 빌드한 뒤 보드에 프로그래밍을 진행하여 다음과 같이 정상적으로 출력되는 것을 확인할 수 있었습니다.
다음 게시글에서는 장애물이 왼쪽으로 움직이는 화면을, 그 다음으로는 공룡이 점프하는 기능, 마지막으로 게임을 구현하는 순서로 진행할 예정입니다.
'자습시간 > Verilog' 카테고리의 다른 글
Pmod OLED 공룡 게임 만들기(3) - 최종 (0) | 2025.02.20 |
---|---|
Pmod OLED 공룡 게임 만들기(2) (0) | 2025.02.17 |
Vivado와 Vitis를 이용한 Pmod OLED 제어 [Pmod IP 이용] (0) | 2025.02.14 |
Verilog 복습 프로젝트(3) - Decoder 설계 [Pmod KYPD 이용] (0) | 2025.02.12 |