임베디드 레시피

Egloos | Log-in





엘시디가 뭐죠?

뭘 알아야 이해를 하지
엘시디라고 하면 무엇일까요? 호스트 피시에 모니터가 있어서 화면이 보이듯이 임베디드 시스템에도 화면을 보이도록 하는 장치랍니다.
일반적으로 시피유에서 엘시디 컨트롤러를 조절하고, 엘시디 컨트롤러는 엘시디 전용칩과 연결 되어 있으며, 엘시디 전용칩은 엘시디와 연결을 하죠. 이러한 엘시디는 종류가 많아서 제품 목적에 맞게 선택하시면 되요. 우리 주변에서 흔히 볼 수 있는 엘시디 종류로는 에스티엔(STN), 티에프티(TFT) 등이 있어요. 자체발광하는 것은 아니고 빛이 통과하는 정도를 조절해서 표현하죠. 주로 휴대폰이나 전자사전, 네비게이션, 휴대용 게임기, 전자시계, 액정TV, 노트PC 등 전자제품에서 폭넓게 사용되고 있답니다. 에스티엔은 정면에서만 제대로 보이고 측면에서는 화면이 어둡게 보인답니다. 티에프티는 옆면에서도 선명하게 잘 보여 현재 노트PC 모니터에서 많이 사용되고 있죠.
그럼 하드웨어 구성요소를 살펴보아요.
 
엘시디 컨트롤러에는 어떤 레지스터가 있는지 살펴볼게요.
엘시디 컨트롤러 스패셜 레지스터(LCD CONTROLLER SPECIAL REGISTER) 1 ~5번까지 있어요.
주로 에스티엔(STN) or 티에프티(TFT) 선택, 칼라모드 선택(16bpp), 클럭설정, 비디오 데이타출력 방식(5:6:5) 등을 지정한답니다. 프레임 버퍼 스타트 어드레스(FRAME BUFFER START ADDRESS) 1 ~ 3번까지 있어요. 프레임 버퍼 뱅크 중에 어떤 어드레스에 있는 것을 가져 올 것인지, 프레임 버퍼 사이즈는 얼마나 할 것인지 등을 지정한답니다.  레드, 그린, 블루 룩업 테이블 레지스터(RED, GREEN,BLUE Lookup Table Register)는 각각 색깔 표현을 해 주는 테이블을 구성하지요. 엘시디 인터럽트 관련 레지스터들(LCD Interrupt Pending Register, LCD Source Pending Register, LCD Interrupt Mask Register)은 엘시디에 그림을 표현하기 위해 사용되는 인터럽트들이죠. 기타 레지스터들도 있지만 생략할께요.
다음은 엘시디 전용칩의 회로도를 살펴보죠.


A라인쪽이 엘시디 컨트롤러에서 들어오는 곳이고 B라인이 엘시디 패널쪽으로 나가는 곳이랍니다.
 
이제 소프트웨어 구성을 살펴 보아요.
엘시디 컨트롤러에 있는 레지스터를 먼저 설정을 해야 해요.



▶설정

rLCDCON1=(5<<8) | /* VCLK = HCLK / ((CLKVAL + 1) * 2) -> About 7 Mhz */
(MVAL_USED << 7) | /* 0 : Each Frame */
(3 << 5) | /* TFT LCD Pannel */
(12 << 1) | /* 16bpp Mode */
(0 << 0) ; /* Disable LCD Output */
rLCDCON2=(VBPD << 24) | /* VBPD : 1 */
(LINEVAL_TFT << 14) | /* Virtical Size : 320 - 1 */
(VFPD << 6) | /* VFPD : 2 */
(VSPW << 0) ; /* VSPW : 1 */
rLCDCON3=(HBPD << 19) | /* HBPD : 6 */
(HOZVAL_TFT << 8) | /* HOZVAL_TFT : 240 - 1 */
(HFPD << 0) ; /* HFPD : 2 */
rLCDCON4=(MVAL << 8) | /* MVAL : 13 */
(HSPW << 0) ; /* HSPW : 4 */
rLCDCON5=(0 << 12) | /* BPP24BL : LSB valid */
(1 << 11) | /* FRM565 MODE : 5:6:5 Format */
(0 << 10) | /* INVVCLK : VCLK Falling Edge */
(0 << 9) | /* INVVLINE : Inverted Polarity */
(1 << 8) | /* INVVFRAME : Inverted Polarity */
(0 << 6) | /* INVVDEN : Normal */
(0 << 5) | /* INVPWREN : Normal */
(0 << 4) | /* INVENDLINE : Normal */
(0 << 3) | /* PWREN : Disable PWREN */
(0 << 2) | /* ENLEND : Disable LEND signal */
(0 << 1) | /* BSWP : Swap Disable */
(1 << 0) ; /* HWSWP : Swap Enable */
rLCDSADDR1 = ((LCDFRAMEBUFFER >> 22) << 21) |
((M5D(LCDFRAMEBUFFER >> 1)) << 0);
rLCDSADDR2 = M5D((LCDFRAMEBUFFER + (LCD_XSIZE_TFT * LCD_YSIZE_TFT * 2)) >> 1);
rLCDSADDR3 = (((LCD_XSIZE_TFT - LCD_XSIZE_TFT) / 1) << 11) | (LCD_XSIZE_TFT / 1);
rLCDINTMSK |= (3);


하드웨어 디버거로 레지스터 설정을 해 볼께요.



▶설정

// LCD COMFROLLER SPECIAL REGISTER
D.S ASD:0x4D000000 %LONG 0x00000578 ; LCDCON1
D.S ASD:0x4D000004 %LONG 0x2043c281 ; LCDCON2
D.S ASD:0x4D000008 %LONG 0x02B9DF27 ; LCDCON3
D.S ASD:0x4D00000C %LONG 0x00000D7F ; LCDCON4
D.S ASD:0x4D000010 %LONG 0x00000909 ; LCDCON5

// FRAME BUFFER START ADDRESS REGISTER
D.S ASD:0x4D000014 %LONG 0x19C00000 ; LCDSADDR1
D.S ASD:0x4D000018 %LONG 0x0001FE00 ; LCDSADDR2
D.S ASD:0x4D00001C %LONG 0x000001E0 ; LCDSADDR3

// INTERRUPT REGISTER
D.S ASD:0x4D00005C %LONG 0x00000003 ; LCDINTMSK


이제 마지막으로 프레임 버퍼에 그림 이미지를 넣는 것이랍니다.



▶코드

pos_x = 80;
pos_y = 95;
size_x = 320;
size_y = 82;
for( y=0; y {
memcpy( (void *)(LCDFRAMEBUFFER + (480*pos_y*2) + (pos_x*2) + (y*480*2)),
(void *)buffer, (size_x*2) );
buffer += (size_x*2);
}

rLCDCON1 |= 1; /* Enable LCD Output */


여기서 buffer라는 변수에는 *.bmp 그림을 HEX로 변환된 데이타가 들어가 있답니다.
BMP를 hex, *.c, *.h 파일 형태로 변환하는 프로그램을 인터넷에서 찾아보면 많이 있답니다. 그 프로그램 사용법은 매우 간단해서 *.bmp 그림을 쉽게 파일을 만들어 낸답니다.
예를 들면, image.bmp 파일을 변환하는 툴을 이용해서 image.c 파일을 만들었다면, main.c 파일에서 그림 파일에 대한 변수를 선언해 주면 된답니다.

HEX 형태로 변형 시킨 툴을 이용하면 다음과 같은 image.c 파일이 만들어 집니다.



▶데이터

//image.c

const unsigned char ScreenBitmap[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,};



이 파일을 main.c 파일에서 include해 주시고 해당 변수는 버퍼에서 뿌려주면 됩니다.



▶코드

//main.c

extern const unsigned short ScreenBitmap[];

buffer = (unsigned char *)ScreenBitmap;

pos_x = 80;
pos_y = 95;
size_x = 320;
size_y = 82;
for( y=0; y {
memcpy( (void *)(LCDFRAMEBUFFER + (480*pos_y*2) + (pos_x*2) + (y*480*2)),
(void *)buffer, (size_x*2) );
buffer += (size_x*2);
}




Season 1의 "특이한 Device Interface의 CS와 Address의 이용 - LCD" 편도 참고하시면 좋아요.

by 히언 | 2010/05/02 21:36 | SOTO Story | 트랙백 | 핑백(1) | 덧글(2)

Linked at 친절한 임베디드 시스템 개발자.. at 2010/05/02 21:47

... nbsp; 208 시리얼 포트(Serial Port)가 뭐죠? 209 엘시디가 뭐죠? 3장 임베디드 시스템 Software 구성 요소 300 크로스 컴파일러(Cross Complier)가 뭐죠?&nbs ... more

Commented by at 2010/05/03 10:21
그럼 요즘은 자체발광하는 엘이디가 대세겠네요?
Commented by soto at 2010/05/03 23:43
네. 맞습니다.
모두들 아몰레드라고 하죠..^^
※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.

◀ 이전 페이지          다음 페이지 ▶