지상파 프로그램을 케이블 프로그램으로 변환하기
현재 한창 개발중인 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 채널이 스캔될 것이다.