리모콘으로 어떤 버튼을 눌렀을 때, 어떤 루틴을 거쳐서 동작을 하는지 루틴을 분석한다. 어떻게 보면, 어려울 것 같지만 어찌보면 무지 어려울 것 같아 보인다.

두개의 서로다른 디바이스

현재, 개발중인 STB 는 크게 두개의 디바이스(부분)으로 나눌 수 있다. 하나는 메인 보드이고, 나머지는 프론트(채널과 시간표시, 리모콘입력)이다.
메인보드는 말 그대로, 5517 과 함께 메인 프로그램인 DACS1000 or 5000 이 돌아간다. 한편 프론트에는 8051 을 사용하고, 시간과 채널 번호를 출력하기위해 메인보드쪽과 인터페이스하는 프로그램이 돌아간다. 이 프로그램은 8051 에 write 되어진다.

메인보드와 프론트는 UART 를 통해 서로 통신한다.
사용자가 어떤 KEY 를 눌렀을 때, 프론트에서 이것을 받아서 어떤 특정한 값으로(예를들어 10101) 인식하고, 이 값을 UART 를 통해 메인 프로그램으로 보낸다. 메인프로그램에서는 각각의 KEY 값에 매핑되는 KEY 맵을 가지고 있는 데, 이에 매칭되는 값으로 각각의 함수를 부른다.

소스 레벨에서의 분석

다음은 가장 먼저 main() 함수에서 부르는 루틴이다.

void KeyServerStart(void)
	{
	pKeyQid = message_create_queue_timeout (MSG_KEY_SIZE, MAX_KEY_MSG);
 
	task_create((void (*)(void *))keyMicom, NULL, 8192, 7, "tKEYm", 0);
	task_create((void (*)(void *))keyTask, NULL, 8192, 7, "tKEY", 0);
	}

2개의 task 를 돌리고 있다.

이름 설명
keyMicom UART 를 open 하고, 무한 루프를 돌면서 UART 로 부터 들어오는 입력값을 keyTask 로 넘겨준다
keyTask keyMicom 태스크가 넘겨준 값을 출력하고, sendkeyToUI() 함수로 넘겨준다

덧붙여서

만일 리모콘이 없어서 테스트를 해볼 수 없는 상황이라면, 아래와 같이 프로그램을 수정한다.
src/common 디렉토리 아래에 key 관련한 소스 파일들이 있다. 그 중에서 keyBoard.c 파일을 수정한다.

 void keyTask (void)
	{
    MSG_TYPE		*pMsgKey, msgKey;
	U8	skey;
 
 
 
task_delay(15600);
//pMsgKey = message_receive_timeout (pKeyQid, TIMEOUT_INFINITY);   // 어짜피 키 입력이 들어올 수 없으므로, keyMicom 은 필요없음
 
skey=0x20;                   // Menu 키가 입력됨
sendkeyToUI(skey);           // UI 로 보냄
task_delay(5560);
skey=0x48;                   // 취소 키가 입력됨
sendkeyToUI(skey);           // UI 로 보냄
task_delay(5560);
skey=0x20;
sendkeyToUI(skey);
task_delay(5560);
 
skey=0xb8;                   // Down 키가 입력됨
sendkeyToUI(skey);
task_delay(5560);
 
skey=0x38;                   // OK 키가 입력됨
sendkeyToUI(skey);
task_delay(5560);
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
 
 
	while(1)
		{
		break;
#ifndef TESTFUN	
/*
		pMsgKey = message_receive_timeout (pKeyQid, TIMEOUT_INFINITY);
		//ARENA_Print( ("===== key msg receive =====\n"));
 
		if (pMsgKey == NULL) {
			ARENA_Print( ("===== key receive error =====\n"));
		 } else {
			msgKey = *pMsgKey;
			message_release (pKeyQid, pMsgKey);
		}
 
		printf("skey == %#x\n", msgKey.value1);
		skey = (U8)(msgKey.value1);
 
		sendkeyToUI(skey);
		*/
/*		
task_delay(15600);
//pMsgKey = message_receive_timeout (pKeyQid, TIMEOUT_INFINITY);
 
skey=0x20;
sendkeyToUI(skey);
task_delay(5560);
skey=0x48;
sendkeyToUI(skey);
task_delay(5560);
skey=0x20;
sendkeyToUI(skey);
task_delay(5560);
 
skey=0xb8;
sendkeyToUI(skey);
task_delay(5560);
 
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
*/
 
 
 
#endif
 
#ifdef TESTFUN
		// 가상 입력 테스트 
/*		task_delay(3*TICKS_SECOND);		// channel 5-1
		skey=0xe2;
		sendkeyToUI(skey);		
		task_delay(0.5*TICKS_SECOND);
		skey=0x40;
		sendkeyToUI(skey);
		task_delay(0.5 *TICKS_SECOND);
		skey=0xb2;
		sendkeyToUI(skey);
		task_delay(3*TICKS_SECOND);		// channel 5-2
		skey=0xe2;
		sendkeyToUI(skey);
		task_delay(0.5*TICKS_SECOND);
		skey=0x40;
		sendkeyToUI(skey);
		task_delay(0.5 *TICKS_SECOND);
		skey=0x62;
		sendkeyToUI(skey);
*/	  
		cmGetScanStatus(&pStatus, &pNumOfFoundChannel, &pFoundedPhysical);
		task_delay(TICKS_100MS);		
 
		if(pStatus == DB_COMPLETE) {
			task_delay(10*TICKS_SECOND);	
			cmGetCurrentChannelId(NULL, NULL, &pSourceID);
//			ARENA_Print(("Current Channel SourceID : %d\n", pSourceID));
 
//			if(IsEPGDB()	== RTN_ERR)
//				break;
			if(pSourceID) {
 
				if(turn == 0)  {
					TEST_EPG(1);
 
					task_delay(5*TICKS_SECOND);	
					skey=0xf0;					// menu_key (main menu) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);		
 
					skey=0x40;					// right_key (epg menu) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
					skey	=0x90;					// OK_key( 현채널)  
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
					skey=0x40;					// right_key (1) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
 
					skey=0x40;					// right_key (2) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
					skey=0x40;					// right_key (3) 
					sendkeyToUI(skey);
					task_delay(TICKS_SECOND);			
 
 
					skey=0x40;					// right_key (4) 
					sendkeyToUI(skey);
					task_delay(TICKS_SECOND);		
 
					skey	=0x40;					// right_key( list)  
					sendkeyToUI(skey);
					task_delay(5*TICKS_SECOND);	
 
				}
 
				skey=0xe8;					// down_key  
				sendkeyToUI(skey);
				task_delay(TICKS_SECOND);		
 
 
				skey=0xe8;					// down_key  
				sendkeyToUI(skey);
				task_delay(TICKS_SECOND);		
 
 
				skey=0xe8;					// down_key  
				sendkeyToUI(skey);
				task_delay(5* TICKS_SECOND);	
 
				turn++;
			}
 
		}
#endif		
	}
}

소스 파일이 많아 보이지만, 정작 필요한 부분은 얼마 안된다. 위에서 주석처리하여 부연설명한 부분만 이해하면 된다.
실제로 프로그램을 수행해 보면, 리모콘의 조작없이 채널 스캔이 실행된다.

수정된 것들

이 후에 프론트가 바뀌었다. 이 말은 고로 리모콘 key 값이 바뀌었다는 것이다. 그래서 바로 위에 예를 들었던 소스 코드를 바꾸어야 한다.
더 자세한 key 값을 알고 싶다면, src/common/keydef/keydef.h 파일을 참고하면 된다.

void keyTask (void)
	{
    MSG_TYPE		*pMsgKey, msgKey;
	U8	skey;
 
 
 
task_delay(15600);
//pMsgKey = message_receive_timeout (pKeyQid, TIMEOUT_INFINITY);   // 어짜피 키 입력이 들어올 수 없으므로, keyMicom 은 필요없음
 
skey=0x88;                 // Menu 키가 입력됨
sendkeyToUI(skey);
task_delay(5560);
 
skey=0xd0;                   // Down 키가 입력됨
sendkeyToUI(skey);
task_delay(5560);
 
skey=0x8;                   // OK 키가 입력됨
sendkeyToUI(skey);
task_delay(5560);
skey=0x8;
sendkeyToUI(skey);
task_delay(5560);
skey=0x8;
sendkeyToUI(skey);
task_delay(5560);
 
 
	while(1)
		{
		break;
#ifndef TESTFUN	
/*
		pMsgKey = message_receive_timeout (pKeyQid, TIMEOUT_INFINITY);
		//ARENA_Print( ("===== key msg receive =====\n"));
 
		if (pMsgKey == NULL) {
			ARENA_Print( ("===== key receive error =====\n"));
		 } else {
			msgKey = *pMsgKey;
			message_release (pKeyQid, pMsgKey);
		}
 
		printf("skey == %#x\n", msgKey.value1);
		skey = (U8)(msgKey.value1);
 
		sendkeyToUI(skey);
		*/
/*		
task_delay(15600);
//pMsgKey = message_receive_timeout (pKeyQid, TIMEOUT_INFINITY);
 
skey=0x20;
sendkeyToUI(skey);
task_delay(5560);
skey=0x48;
sendkeyToUI(skey);
task_delay(5560);
skey=0x20;
sendkeyToUI(skey);
task_delay(5560);
 
skey=0xb8;
sendkeyToUI(skey);
task_delay(5560);
 
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
skey=0x38;
sendkeyToUI(skey);
task_delay(5560);
*/
 
 
 
#endif
 
#ifdef TESTFUN
		// 가상 입력 테스트 
/*		task_delay(3*TICKS_SECOND);		// channel 5-1
		skey=0xe2;
		sendkeyToUI(skey);		
		task_delay(0.5*TICKS_SECOND);
		skey=0x40;
		sendkeyToUI(skey);
		task_delay(0.5 *TICKS_SECOND);
		skey=0xb2;
		sendkeyToUI(skey);
		task_delay(3*TICKS_SECOND);		// channel 5-2
		skey=0xe2;
		sendkeyToUI(skey);
		task_delay(0.5*TICKS_SECOND);
		skey=0x40;
		sendkeyToUI(skey);
		task_delay(0.5 *TICKS_SECOND);
		skey=0x62;
		sendkeyToUI(skey);
*/	  
		cmGetScanStatus(&pStatus, &pNumOfFoundChannel, &pFoundedPhysical);
		task_delay(TICKS_100MS);		
 
		if(pStatus == DB_COMPLETE) {
			task_delay(10*TICKS_SECOND);	
			cmGetCurrentChannelId(NULL, NULL, &pSourceID);
//			ARENA_Print(("Current Channel SourceID : %d\n", pSourceID));
 
//			if(IsEPGDB()	== RTN_ERR)
//				break;
			if(pSourceID) {
 
				if(turn == 0)  {
					TEST_EPG(1);
 
					task_delay(5*TICKS_SECOND);	
					skey=0xf0;					// menu_key (main menu) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);		
 
					skey=0x40;					// right_key (epg menu) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
					skey	=0x90;					// OK_key( 현채널)  
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
					skey=0x40;					// right_key (1) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
 
					skey=0x40;					// right_key (2) 
					sendkeyToUI(skey);
					task_delay(2*TICKS_SECOND);				
 
 
					skey=0x40;					// right_key (3) 
					sendkeyToUI(skey);
					task_delay(TICKS_SECOND);			
 
 
					skey=0x40;					// right_key (4) 
					sendkeyToUI(skey);
					task_delay(TICKS_SECOND);		
 
					skey	=0x40;					// right_key( list)  
					sendkeyToUI(skey);
					task_delay(5*TICKS_SECOND);	
 
				}
 
				skey=0xe8;					// down_key  
				sendkeyToUI(skey);
				task_delay(TICKS_SECOND);		
 
 
				skey=0xe8;					// down_key  
				sendkeyToUI(skey);
				task_delay(TICKS_SECOND);		
 
 
				skey=0xe8;					// down_key  
				sendkeyToUI(skey);
				task_delay(5* TICKS_SECOND);	
 
				turn++;
			}
 
		}
#endif		
	}
}
  • computer/digitalarena/key_입력_처리_루틴_분석.txt
  • Last modified: 3 years ago
  • by likewind