비디오 아웃풋 포트를 가지고 있는데
실제로 RGB를 연결할 수 있는 커넥터가 있다.
VGA 컨트롤러는 640, 480 연결할 수 있구요
비디오 아웃풋은 결국 GPIO의 형태고 GPIO는 메모리 맵드 IO 형태로
우리가 Access하게 된다. 구체적으로 어떻게 하는지에 대해서
다음 슬라이드에서 얘기해봅시다.
기본적으로 그래픽에 대해서 얘기해봅시다.
이미지가 두가지 포멧이 있는데
벡터 이미지가 있고 Raster 이미지가 있다.
벡터이미지
사각형으로 주어지는데
=>식의 형태로 되어있어요
장점은 확대하거나 늘려도 깨지지 않습니다.
파워포인트에서 그림을 그렸을 때
네모가 깨지거나 그러지 않죠=> 수식으로 되어있어서 깨지지 않는거에요.
단점은 실제로 나타낼 때 연산을 많이 해야 합니다.
Raster 이미지는 Bitmap을 생각하면 됩니다.
하나 하나의 픽셀이 하나 하나 전부 있는것
비트 혹은 바이트 형태로 전부 다 맵핑되어있는것
0~256까지 칼라의 개수를 결정할 수 있다.
컴퓨터 모니터에서 쓰는것은 Raster 이미지이다.
벡터맵으로 되어있는 형태를 실제로 디스플레이할 때는
레스터형식으로 바꿔서 표시를 해줘야 하는데
이과정을 rendering이라고 합니다.
행렬 연산 처리를 통해서 렌더링 해줘야하는데
GPU가 이런연산을 위해서 나온거에요 원래
임의의 메모리 공간에
한바이트 혹은 비트를 적으면
이게 한픽셀에 해당하게 된다.
DE1-SoC에서는 그래픽할 수 있는곳을
pixel 버퍼라고 부른다.
문자를 타입하고 싶다==>character buffer를 사용하는데 여기서 안다룸
픽셀버퍼에서는 픽셀 하나가 어떤 값을 가져야 한다.
각각의 픽셀이 8비트를 쓸수도 있고~~
보통 제일 많이 사용하는게 24비트를 사용한다.
이번에는 16비트 포멧을 사용할겁니다.
일정 비트 RGB를 우겨 넣어서 표현할것이다.
픽셀 하나당 16비트니까 2바이트를 사용하는것
RGB값을 우겨 넣는데 0에서 4비트까지는 Blue
5~10비트 Green 11~15 Red
R은 5비트 B도 5비트 G는 6비트
정확하게 스케일이 일치하지는 않는다.
2바이트된 데이터가 그림에서 보는 좌표하나랑 이렇게 맵핑이 되어야 하는데
어떻게 표시하느냐? X-Y 어드레스 형태로 표시가 된다.
메모리의 주소값이 픽셀 버퍼에서 어떤 위치에 해당될 수 있는지 알려준다.
어드레스 포멧을 결정할 때 여러가지 방법이 있는데
X 코디네잇을 0~9까지 10비트 ==>640
Y는 10~18까지 9비트 사용 ==>480
어드레스에 따라 데이터들이 결정되는 형식으로 픽셀 버퍼를 사용하게 된다.
픽셀버퍼 레지스터인데
우리가 IO하는것 처럼 위에 4개의 워드로 구성되어있다.
첫번째 바이트에는 버퍼의 스타터 어드레스가 들어간다
버퍼자체는 메모리 외의 공간에 있을것인데
이것을 결정해주는데 이 어드레스는 0번지에 적어주는 거에요.
백버퍼도 표시해줄 수 있고 위의 버퍼랑 똑같이 두면 버퍼 하나만 사용한다는 의미에요
8번지는 레솔루션
12번지는 앞의 최상위 비트 부터 보면
8자리가 y 코디네이터의 어드레스의 width를 얘기한다.
7-4는 칼라를 정해준다.
맨마지막 비트 두개는 어드레싱 모드
0(XY) 모드만 생각하고
마지막 비트는 스왑 비트
스왑이 일어나면 0이되고 아니면 1이되고 이런비트가 있는데 나중에 다시 얘기하겠다.
레지스터 맵이 구성되고 코드를 봅시다.
두개의 메크로를 선언했는데
하나는 픽셀
결과는 무엇이 나오는가? (short int)
define PIXEL(r,g,b)
RGB 다 합쳐서 16비트
define FILL_(x,y,r,g,b)
xy좌표로 rgb값으로 구성된 픽셀을 칠하겠다. 점하나 찍겠다.
픽셀 버퍼에서 시작해서 x좌표는
하나 쉬프트 하는 이유는
마지막 비트는 항상 0이 되어야 한다.
왜냐하면 어드레스 하나당 한바이트를 써먹을 수 있는데
우리는 RGB값을 16비트 2바이트를 쓸거니까
어드레스 영역에서는 짝수번만 쓸 수 있는것이다.
홀수번은 이미 전 어드레스에서 쓰고있는것과 마찬가지여서
1비트만큼 쉬프트 시켜줘야합니다.
y값 같은 경우 8비트만해서 10비트 쉬프트 해주는겁니다.
가리키고 있는곳에 픽셀값을 박아준다
타입이 애매해서 캐스팅 해줍니다.
필 픽셀을 부르면 xy좌표에 rgb값을 색칠 할 수 있다.
필 픽셀만 알면 위 환경에서 필함수를 쓰면 해결이 된다.
픽셀버퍼 스타트를 인티저를 잡아놨고
clear_screen을 잡아났는데
이 함수는 rgb값을 보고 모든 화면을 색칠하는것
draw_square은 x좌표 y좌표가 있는데
x1 y1 x2 y2 서로 반대 방향의 꼭지점이 주어지고
이 공간을 RGB값을 이용해서 색칠하라는것
==>for문 두번 돌리면 됩니다 ^~^
pixel_ctrl_ptr은
여기 위치를 포인터로 저장해주는것
버퍼 스타트 어드레스를 읽어서 픽셀버퍼 스타트에 저장한다.
흰색으로 그리겠다.
빨간색으로 그리겠다.
동영상 같은 경우 여러가지 문제가 발생한다.
V-SYNC가 없으면 피어링==> 프레임이 분리되는 현상이 나타난다.
모니터의 주사율이 어떻게 되느냐? =>60헤르츠 =>1초에 60번 디스플레이를 리프레쉬한다는것
랜더링하는것을 60분의1초보다 더 빨리 해줘야하는데
싱크가 안맞는것이다.
두번째 그림 그리고 있는데 프레임 버퍼가 바뀐것
이런것을 막기 위해서
V-SYNC를 사용한다.
문제는 싱글 버퍼링이면 V-SYNC를 쓰는데
왔다 갔다 할 수 있다.
이런일들이 벌어질 수 있어서
싱글 버퍼를 쓰면 디스플레이하는놈이랑 렌더링하는놈이랑 충돌이 일어나서
깜박깜박할 수 있다=>Flickering =>
듀얼 버퍼를 사용해라 버퍼를 두개 넣어서 한장 그리고
실제로 메모리에 있는 데이터를 화면에 표시해주고
뒤에서 백버퍼해서 다음에 그려줄 내용을 그려주고
시간이 지나면 바뀌어서 디스플레이가 되고
이과정의 반복
V-SYNC가 일어날 때 마다 미리
다음 프레임에서 디스플레이 할 내용들을 렌더링해서 버퍼에 집어 넣고
V-SYNC가 지나면 바꿔치기해서 디스플레이하고
다른거는 새로 그리고 ==>스무스하게 애니메이션 구현 가능
예제 보기전에 버퍼맵을 다시 보면
첫번째 버퍼 어드레스는 리드만 되고
백버퍼는 우리가 결정할 수 있어요
0번지 버퍼에 1을 적으면 백버퍼와 프론트 버퍼가 다음 싱크에 뒤바뀌게 된다.
내가 원하는 주소 공간이 있으면 밑으로 내려왔을 때 써줄 수 있고
다시 1을 써서 뒤바꿀수 있다.=> 원래 이런식으로 동작합니다
V-SYNC가 일어나는지 안일어나는지 어떻게 하느냐?=> S 플레그가 0이되면 알 수 있다.
V-SYNC off
앞 코드는 똑같고
V-SYNC를 살려본다면?
추가된것은 wait for vsync
V-SYNC 이벤트를 진행해라.
백버퍼와 프론트 버퍼 메모리를 잡아줍시다
픽셀 버퍼값 읽어오고
백버퍼를 써준다.
백 버퍼가 있는곳에 시작 주소를 넣어주고
백버퍼에 색칠해주고 바꾸는거라서 현재 백버퍼를 포인팅 해주는거에요
브레센햄 알고리즘을 이용해서 라인을 그려라
래스터 이미지로 그리게 되면 바둑판 형태로 있을 때
여기 칠하고 여기 칠하고~~
어디 칠할지 결정해줘야하는데 이것을 빨리해줄 수 있는 알고리즘이 위에 꺼다.
+와 - 연산만 하면 된다.
xy 좌표값이 정수값
수평선을 업/다운 하는데 끝에 만나면 바운스
왔다리 갔다리 하는것을 그려보는데 더블 버퍼링을 써서 그려봐라
파트3는 데모 할건데요
점을 8개 만들어요
필드 정사각형 8개를 만들고
가만히 있느냐? 랜덤한 위치에 만든다.
움직이는데 45도 방향으로
끝에 만나면 바운스하는거야