리모콘으로 어떤 버튼을 눌렀을 때, 어떤 루틴을 거쳐서 동작을 하는지 루틴을 분석한다. 어떻게 보면, 어려울 것 같지만 어찌보면 무지 어려울 것 같아 보인다.
현재, 개발중인 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 } }