8051( 중급 9부 - Graphic LCD ) |
요즈음에는 그래픽 LCD가 핸드폰에도 사용이 될 정도로 보편화 되어 있슴다.
그래픽 LCD를 핸들링 하려면 아무래도 C로 작성하는 편이 훨씬 용이 할검다.
연산도 많고 알고리즘 구현도 많이 해야 하기 때문임다.
그래픽 알고리즘이 정리가 잘 되어 있는 책으로는 "Advanced Graphics in C"라는 책이 있슴다.
산적은 DOS 시절에 구입을 했기 때문에 지금도 그책이 나오고 있는지는 몰겠슴다.
이 책은 PC상에서 그래픽을 구현하기 위한 책이기는 하지만 알고리즘 정리가 잘되어 있어서 8051에 적용하는데도 무리가 없을검다.
먼저 점을 찍는 알고리즘을 보기로 함다.
예를 드는 그래픽 LCD는 256 x 64의 monochrome LCD로 가정 함다.
video RAM
00 01 02 03 ....... 0x1F --첫번째 라인
76543210765432107654321076543210
20 21 22 23 ....... 0x3F --첫번째 라인
76543210765432107654321076543210
여기에서 두번째 라인의 왼쪽에서 두번째 위치에 pixel을 찍는다고 가정을 함다.
그러면 좌표상으로는 x=1, y=1이 됨다. 제일 위쪽의 원점은 x=0, y=0이기 때문임다.
주어진 좌표를 이용해서 video RAM의 address를 구하기로 함다.
y = 0일때의 video RAM의 address는 0x00이 됨다.
그리고 y = 1일때의 video RAM의 address는 0x20가 얻어 짐다.
이것은 가로가 256 pixel로 구성된 LCD를 기준으로 했기 때문에 256 / 8 = 32 = 0x20이 되기 때문임다.
y 값이 1 증가시 마다 RAM의 address는 0x20씩 증가 함다.
그리고 x값이 8의 배수로 address는 1씩 증가 함다. 8개의 pixel이 한 바이트의 address를 차지 하기 때문임다.
그러므로 x 값을 8로 나눈 값을 앞에서 얻어진 RAM의 address에 더해 줌다.
마지막으로 x를 8로 나눈 나머지값을 구함다.
이 나머지 연산에 의해 얻어진 값으로 테이블을 조회해서 원하는 pixel에 대한 16진값을 구함다.
만일 얻어진 값이 1이라면 0x80, 2라면 0x40 이라는 값을 얻어냄다.
앞에서 주어진 좌표에 의해 RAM의 address를 구하면
y x ( 256 / 8 ) + x / 8 = 1 x 32 + 1 / 8 = 32 = 0x20
가 얻어 짐다.
그리고 x를 8로 나눈 나머지를 구하면
x % 8 = 1 % 8 = 1
이 얻어 짐다.
위에서 구한 address에 의해 현재의 video RAM에 씌여진 값을 읽어 들임다.
그 값에 x % 8 에 의해 구해진 값에 의해 40H를 OR 시키면 원하는 위치에 pixel이 찍힘다.
이때 단순한 OR가 아니고 XOR를 시키게 되면 현재의 위치의 pixel이 반전 됨다.
#define XMAX 256 /* 가로가 256 pixels */
#define YMAX 64 /* 세로가 64 pixels */
#define write_io( address, value ) ((( char *)0x010000 )[ address ] = value )
#define read_io( address ) ((( char *)0x010000 )[ address ] )
#define OR 1
#define XOR 2
void point_xy( int x, int y, int method ) {
unsigned char x_mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
unsigned char current_data;
int resident;
int RAM_address;
/* video RAM 영역을 초과 하는 값이 주어질때는 리턴한다. */
if( x < 0 || x > XMAX || y < 0 || y > YMAX ) return;
RAM_address = y * XMAX / 8;
RAM_address += x / 8;
resident = x % 8;
current_data = read_io( RAM_address ); /* 현재 video RAM의 값을 읽어 들임 */
if( method == OR )
write_io( RAM_address, current_data | x_mask[ resident ] );
else if( method == XOR )
wrtie_io( RAM_address, current_data ^ x_mask[ resident ] );
} |
위의 함수를 추적 해 보기로 함다.
x = 1, y = 1을 대입하면
RAM_address = y * XMAX / 8; 에 의해 32( 0x20 ) 가 얻어 지고
RAM_address += x / 8; 에 의해 32( 0x20 ) 가 얻어 짐다.
resident = x % 8; 에 의해 1 이 얻어 짐다.
current_data가 00H라 가정하고 method를 OR로 가정하면
실제 RAM_address에 쓰여지는 데이터는
x_mask[ resident ]; 에 의해 x_mask[ 1 ] = 0x40 이 됨다.
위의 함수는 산적이 그래픽 LCD를 가지고 있지 않은 관계로 시험은 해보지 못했슴다.
하지만 아랫쪽의 설명에 의해 수치로 검증 하였으므로 확실하게 구현 될것임다.
위와 같이 video RAM에 pixel을 표시하는 방법은 과거 8 bit apple 시절 부터 사용하는 방식임다.
산적은 8 bit apple 시절에 이처럼 그래픽을 구현해본 경험이 있슴다.