현재 한창 개발중인 5517 + 7020 지상파 프로그램을 오픈 케이블용 프로그램으로 변환하는 방법을 정리했다.
지금 현재 최신 버전인, TA5000K_v18_1010 을 기준으로 설명하도록 하겠다. 차후에 소스코드가 크게 바뀌지 않는한 여기서 설명하는 방법대로 변환하면 될 것이다.
수정할 것들
우선 현재의 지상파 H/W 보드와 오픈 케이블 H/W 가 다르기 때문에, 크게 두 가지로 수정할 것을 나눌 수 있다.
- H/W 에 의한 수정
- S/W 에 의한 수정
먼저 H/W 에 대한 것부터 살펴보겠다. 현재 실험하는 지상파 보드에는 POD 가 빠져있다. 또한 POD 를 초기화 하는 데 필요한 PIO 핀들이 해상도를 조절하는 핀으로 사용되고 있기 때문에, 프로그램 수정이 불가피하다. S/W 에서는 QAM 채널(오픈케이블)을 스캔 및 파싱하기 위해서 cm 과 psip 의 수정이 불가피하다.
수정하기
H/W 에 의한 수정
include/arena_inc/arenaDefine.h
#ifndef __arenaDefineh #define __arenaDefineh #include "stddefs.h" #include "sttbx.h" #define DAC5000 //#define USE_VSB ------>> 주석 처리!! //mode change define
src/시스템/main.c
int main(void) { U16 letter[10]; ST_ErrorCode_t ST_ErrorCode; U16 ma,mi,countCh; ST_ErrorCode = BasicInfraStructure_Init(); /* setup basic set of drivers for reporting and I/O */ if (ST_ErrorCode != ST_NO_ERROR) { printf("Basic Init Fail!!!\n"); return 0; } //OpenUsedPio(); ------>> 주석 처리!! ChangeOutputVideoMode(I1080); ChangeOuputVideoType(YPbPr); #ifdef ENABLE_VIDEO_MODE_CHANGE // ReadVideoOuputSeting(); ------->> 주석 처리!! #endif Boot7020(); DDR_INIT(SDRAM_FREQUENCY); ST_ErrorCode = AV_INIT(); if (ST_ErrorCode != ST_NO_ERROR) { printf("Back end Init Fail!!!\n"); return 0; }
src/시스템/debug.c
void Debug시스템() { long int buf[10]; U8 cmd; // task_delay(TICKS_SECOND*3); while(1) { /* debugpollkey(buf); // cmd=getchar(); // if(buf[0]=='1') // printf("%d\n\n\n",buf[0]); switch(buf[0]) { case 's': OutputMainManu(); printf("%c\n",'s'); break; case '0': AddCmd(0); break; case '1': AddCmd(1); break; case '2': AddCmd(2); break; case '3': AddCmd(3); break; case '4': AddCmd(4); break; case '5': AddCmd(5); break; case '6': AddCmd(6); break; case '7': AddCmd(7); break; case '8': AddCmd(8); break; case '9': AddCmd(9); break; case 'h': break; case 'r': nCmd=0; nCurrentDebugDepth=0; OutputMainManu(); break; case 'b': if(nCurrentDebugDepth>0) { nCmd=nCmd/10; nCurrentDebugDepth--; } break; case 'c': bDebugState=FALSE; break; case 'x': // task_exit(); return; break; default: break; } */ task_delay(TICKS_100MS*5); CheckCurrentState(); // CheckChangeVideoModeSwitch(); -------->> 주석 처리!!
S/W 에 의한 수정
src/cm/cmScan.c
void channelScan (U32 *pStartEndCh) { float scannedChannel, scanCount = 0, endChannel,startChannel,physicalNum; ARENA_RTN_t errVal; percentOfScannedChannel = 0; autoScanInitial (); if (pStartEndCh == NULL) { #ifdef USE_VSB if (cmCheckCurrentAirMode()) { startChannel = 2; endChannel = 69; } else { startChannel = 2; endChannel = 130; } #else startChannel = 45; ------->> 스캔 채널 번호 변경!! endChannel = 50; ------->> 역시 마찬가지로 변경!! #endif // USE_VSB }
src/cm/cmScan.c
//analog tune /* ------>>> 전체 구문을 주석처리한다!! scaningPch.NumInfo.physicalNum = physicalNum; scaningPch.NumInfo.chType = SOURCE_NTSC; scaningPch.NumInfo.modFormat = CM_NTSC; cmChannelPlan = CM_STD;//dont't care in VSB errVal = analogTuneAndDBmake (physicalNum, percentOfScannedChannel); if(errVal == RTN_OK) continue; //current is analog channel else if (errVal == RTN_ABORT) { printf("Analog SCAN_ABORT_JMP\n"); goto SCAN_ABORT_JMP; } */ ------>>> 전체 구문을 주석처리한다!!
src/psip/psip_filtersetup.c
ST_ErrorCode_t FilterStart( Filter_t *Filter_p, STPTI_Pid_t Pid, U8 TableId, U16 TableType_Info ) { ST_ErrorCode_t ErrCode = ST_NO_ERROR; U8 filterNumber, slotNumber; switch(TableId) {/*-- 테이블에 따라서 어떤 슬롯(버퍼),필터 핸들을 사용할것인지 결정한다. --*/ case STT_TABLE_ID : filterNumber = FILTER_STT; slotNumber = FILTER_STT; break;/*-- Filter맵핑에 의해 처음 할당한 PTI 슬롯의 PSIP_SLOT_BasePID 슬롯은 FILTER_STT 슬롯과 같음. --*/ case RRT_TABLE_ID : filterNumber = FILTER_RRT; slotNumber = FILTER_STT; break; case TVCT_TABLE_ID : filterNumber = FILTER_VCT; slotNumber = FILTER_STT; numberOfSectionsOfVCT = 0; /*-- 수신된 VCT 섹션 갯수 --*/ break; case CVCT_TABLE_ID : ------>>>> CASE 문 추가!! filterNumber = FILTER_VCT; slotNumber = FILTER_STT; numberOfSectionsOfVCT = 0; /*-- 수신된 VCT 섹션 갯수 --*/ break; ------>>>> 여기까지 추가!! case MGT_TABLE_ID : filterNumber = FILTER_MGT; slotNumber = FILTER_STT;
src/psip/psip_parsing.c
message_send (pPsipMainQid, (void*) pMsgTvct); } } break; case CVCT_TABLE_ID : --------->>> 여기부터 CASE 문 전체 수정 할 것!! { MSG_PSIP *pMsgTvct, msgTvct; U16 currentTsId; psipCvctParser(Buffer_p, Data_Size); if(receiveDataEnd_p) psipWatchDog = PSIP_PARSING_COMPLETE; if (psipParsingMode == PSIP_PARSING_SCAN) { if (prevTsId != currentTsId) { msgTvct.msgId = MSG_CM_PSIP_END_NOTIFY; pMsgTvct = (MSG_PSIP *) message_claim_timeout (pPsipMainQid, TIMEOUT_INFINITY); *pMsgTvct = msgTvct; message_send (pPsipMainQid, (void*) pMsgTvct); prevTsId = currentTsId; } } else if (psipParsingMode == PSIP_PARSING_CHANGE) { msgTvct.msgId = MSG_CM_PSIP_END_NOTIFY; pMsgTvct = (MSG_PSIP *) message_claim_timeout (pPsipMainQid, TIMEOUT_INFINITY); *pMsgTvct = msgTvct; message_send (pPsipMainQid, (void*) pMsgTvct); /*-- 두개의 메시지를 보내는데, 하나는 완료 이고, 또 하나는 MGT 파싱 명령이다.두개 순서를 바꿔봤다. 그냥 함수 하나 콜해서 MGT 파싱해도될것같지만, 역시 파싱시작 창구의 단일화를 위해서는 메시지로 보내는 방식이 최선임 --*/ msgTvct.msgId = MSG_MGT_PARSING; pMsgTvct = (MSG_PSIP *) message_claim_timeout (pPsipMainQid, TIMEOUT_INFINITY); *pMsgTvct = msgTvct; message_send (pPsipMainQid, (void*) pMsgTvct); } else if (psipParsingMode == PSIP_EPG_SCAN) { msgTvct.msgId = MSG_MGT_PARSING; pMsgTvct = (MSG_PSIP *) message_claim_timeout (pPsipMainQid, TIMEOUT_INFINITY); *pMsgTvct = msgTvct; message_send (pPsipMainQid, (void*) pMsgTvct); } } break; --------->>> 여기까지 CASE 문 전체 수정 할 것!! case MGT_TABLE_ID: /* Master Guide Table */
결론
위에서 언급했던 부분을 수정하고, 채널스캔시에 '일반모드' 를 선택하면 QAM 채널이 스캔될 것이다.