이번에 HD 셋톱박스에 개발을 위한 프로젝트인 DAC5000 에 관한 내용을 중심으로 적었다. 아무래도 기존의 SD 프로젝트인 DACS1000 과 하드웨어적으로나 소프트웨어적으로 바뀐 것들이 있다. 여기서는 AV 쪽을 중심으로 설명하려고 한다.
SD vs HD
기존의 SD 와 비교해서 크게 달라진 점을 바로 AV 쪽이다. SD의 경우 튜너(3125)에서 인코딩된 스트림을 5517 자체에서 처리후에 출력했다. 하지만, HD의 경우 sti7020 이라는 칩이 추가되었다. 바로 이것이 HD 기능의 핵심을 맡고 있는 칩이다.
이 칩으로해서, 튜너(3125)로 부터 들어오는 스트림을 sti7020 쪽으로 입력하여, 그쪽에서 처리를 한 후에 출력단자를 통해 화면에 뿌리는 역할을 한다. 또한 이 칩은 따로 DDR 램을 사용하기 때문에 이것과의 통신도 필수적이다.
말로서 간단하게 나마 설명을 했지만, 알고보면 좀 복잡하다. 다행스럽게도, 나머지 부분은 거의 SD의 경우와 같다고 보면된다.
앞에서 설명했듯이, 하드웨어적으로 바뀜에 따라 소프트웨어 또한 변경이 되었다.
DAC5000 소스를 보면 알겠지만, 기존의 SD 소스의 기반에서 HD 부분이 추가되거나 수정되었다.
실행하기
일단 새로운 HD 소스인 DAC5000 을 실행해보자!! c:\stm 아래에 디렉토리를 통째로 복사하고 난 뒤에 setup.bat 파일을 c\stm\5517ref\bin 아래에 복사한다. 기존의 setup.bat 파일은 이름을 변경한다.
그리고 언제나 그랬(?)듯이
#gmake clean; gmake; gmake run
을 입력한다.
출력 바꾸기
HD 의 경우, 다양한 형태의 출력을 내보낸다.
- DVI
- YBCR
- RGB
- CVBS
아무래도, 현재 쓰이고 있는 출력의 형태는 모두 지원하기 위함인듯 하다. 이 모든 출력은 sti7020 에서 지원한다. 이 부분에서 각각의 출력으로 바꾸기 위해서는 소스 파일을 수정해주어야 한다.
src\system\sysinit.c
ST_ErrorCode_t VOUT_Inital( void ) { STVOUT_InitParams_t VOUTInitParams; STVOUT_OutputParams_t VOUTOutputParams; STVOUT_OpenParams_t OpenParams; ST_ErrorCode_t ErrCode; memset((void *)&VOUTInitParams, 0, sizeof(STVOUT_InitParams_t)); VOUTInitParams.CPUPartition_p = system_partition; VOUTInitParams.MaxOpen = 3; VOUTInitParams.DeviceType = STVOUT_DEVICE_TYPE_7020; VOUTInitParams.OutputType = STVOUT_OUTPUT_HD_ANALOG_RGB;//STVOUT_OUTPUT_ANALOG_CVBS;//STVOUT_OUTPUT_ANALOG_RGB; <<-- 이 부분이 가장 중요하다!! //strcpy( VOUTInitParams.Target.GenericCell.DencName,DENC_DeviceName); strcpy(VOUTInitParams.Target.DencName,""); VOUTInitParams.Target.GenericCell.DeviceBaseAddress_p = (void*)(STI7020_BASE_ADDRESS); VOUTInitParams.Target.GenericCell.BaseAddress_p = (void *)(ST7020_DSPCFG_OFFSET); ErrCode = STVOUT_Init(VOUTDeviceName, &VOUTInitParams); if (ErrCode != ST_NO_ERROR) { STTBX_Print(("STVOUT_Init %s\n", GetErrorText(ErrCode) )); } memset((void *) &OpenParams, 0, sizeof(STVOUT_OpenParams_t)); ErrCode = STVOUT_Open(VOUTDeviceName, &OpenParams,&VOUTHndl); if (ErrCode != ST_NO_ERROR) { STTBX_Print(("STVOUT_Init %s\n", GetErrorText(ErrCode) )); } /* VOUTOutputParams.Analog.StateAnalogLevel = STVOUT_PARAMS_DEFAULT; VOUTOutputParams.Analog.StateBCSLevel = STVOUT_PARAMS_DEFAULT; VOUTOutputParams.Analog.StateChrLumFilter = STVOUT_PARAMS_DEFAULT; VOUTOutputParams.Analog.EmbeddedType = FALSE; VOUTOutputParams.Analog.InvertedOutput = FALSE; VOUTOutputParams.Analog.SyncroInChroma = FALSE; ErrCode = STVOUT_SetOutputParams(VOUTHndl, &VOUTOutputParams); STTBX_Print(("GlobalOpen: STVOUT_SetOutputParams %s\n", GetErrorText(ErrCode))); if (ErrCode != ST_NO_ERROR) return(ErrCode); */ ErrCode = STVOUT_Enable(VOUTHndl); printf("VOUT Ver %s\n", STVOUT_GetRevision() ); STTBX_Print(("GlobalOpen: STVOUT_Enable %s\n", GetErrorText(ErrCode))); if (ErrCode != ST_NO_ERROR) return(ErrCode); }
위의 소스에서 주석을 달아논 부분을 보기 바란다. 현재는 'STVOUT_OUTPUT_HD_ANALOG_RGB' 로 되어있다. 즉, RGB 모드로 세팅되어 있다. 다른 모드로 바꾸기 위해서는 이 부분을 바꿔주면 된다. 아래의 typedef 중에서 바꿔주면 된다.
typedef enum STVOUT_OutputType_e { STVOUT_OUTPUT_ANALOG_RGB = 1, STVOUT_OUTPUT_ANALOG_YUV = 2, STVOUT_OUTPUT_ANALOG_YC = 4, STVOUT_OUTPUT_ANALOG_CVBS = 8, STVOUT_OUTPUT_ANALOG_SVM = 16, STVOUT_OUTPUT_DIGITAL_YCBCR444_24BITSCOMPONENTS = 32, STVOUT_OUTPUT_DIGITAL_YCBCR422_16BITSCHROMAMULTIPLEXED = 64, /* SMPTE274/295 */ STVOUT_OUTPUT_DIGITAL_YCBCR422_8BITSMULTIPLEXED = 128, /* CCIR656 */ STVOUT_OUTPUT_DIGITAL_RGB888_24BITSCOMPONENTS = 256, STVOUT_OUTPUT_HD_ANALOG_RGB = 512, STVOUT_OUTPUT_HD_ANALOG_YUV = 1024 } STVOUT_OutputType_t;
또 한가지가 더있다.
src\system\vtg.c
/*------------------------------------------------------------------------ * Function : VTG_SetMode * Input : Timing Mode * Output : * Return : Error Code * ----------------------------------------------------------------------*/ static ST_ErrorCode_t VTG_SetMode(void) { ST_ErrorCode_t ST_ErrorCode; STVTG_TimingMode_t STVTG_TimingMode; ST_ErrorCode = STVTG_SetMode(VTG_Handle, STVTG_TIMING_MODE_480P24000_10811); <<-- 이 부분 중요 STTBX_Print(("VTG_SetMode(")); STTBX_Print(("STDENC_MODE_NTSCM)=")); STVTG_TimingMode =STVTG_TIMING_MODE_1080I60000_74250; //STVTG_TIMING_MODE_1080I60000_74250;//TVTG_TIMING_MODE_480I59940_13500;//STVTG_TIMING_MODE_480I59940_13500; <<-- 역시 중요 //STVTG_TIMING_MODE_480P59940_24545 //STVTG_TIMING_MODE_480I59940_13500 NTSC //STVTG_TIMING_MODE_1080I60000_74250 VGA ST_ErrorCode = STVTG_SetMode(VTG_Handle, STVTG_TimingMode); STTBX_Print(("%s\n", GetErrorText(ST_ErrorCode) )); return( ST_ErrorCode ); }
역시 주석이 들어간 곳은 영상을 보여줄 타이밍을 조절하는 부분이다. 이 부분이 잘못 세팅하게 되면 화면이 안 나올 수 있다.
typedef enum STVTG_TimingMode_e { STVTG_TIMING_MODE_SLAVE, STVTG_TIMING_MODE_480I60000_13514, /* NTSC 60Hz */ STVTG_TIMING_MODE_480P60000_27027, /* ATSC 60P */ STVTG_TIMING_MODE_480P30000_13514, /* ATSC 30P */ STVTG_TIMING_MODE_480P24000_10811, /* ATSC 24P */ STVTG_TIMING_MODE_480I59940_13500, /* NTSC, PAL M */ STVTG_TIMING_MODE_480P59940_27000, /* ATSC 60P/1.001 */ STVTG_TIMING_MODE_480P29970_13500, /* ATSC 30P/1.001 */ STVTG_TIMING_MODE_480P23976_10800, /* ATSC 24P/1.001 */ STVTG_TIMING_MODE_480I60000_12285, /* NTSC 60Hz square */ STVTG_TIMING_MODE_480P60000_24570, /* ATSC 60P square */ STVTG_TIMING_MODE_480P30000_12285, /* ATSC 30P square */ STVTG_TIMING_MODE_480P24000_9828 , /* ATSC 24P square */ STVTG_TIMING_MODE_480I59940_12273, /* NTSC square, PAL M square */ STVTG_TIMING_MODE_480P59940_24545, /* ATSC 60P/1.001 square */ STVTG_TIMING_MODE_480P29970_12273, /* ATSC 30P/1.001 square */ STVTG_TIMING_MODE_480P23976_9818 , /* ATSC 24P/1.001 square */ STVTG_TIMING_MODE_576I50000_13500, /* PAL B,D,G,H,I,N, SECAM */ STVTG_TIMING_MODE_576I50000_14750, /* PAL B,D,G,H,I,N, SECAM square */ STVTG_TIMING_MODE_1080P60000_148500, /* SMPTE 274M #1 P60 */ STVTG_TIMING_MODE_1080P59940_148352, /* SMPTE 274M #2 P60 /1.001 */ STVTG_TIMING_MODE_1080P50000_148500, /* SMPTE 274M #3 P50 */ STVTG_TIMING_MODE_1080I60000_74250, /* EIA770.3 #3 I60 = SMPTE274M #4 I60 */ STVTG_TIMING_MODE_1080I59940_74176, /* EIA770.3 #4 I60 /1.001 = SMPTE274M #5 I60 /1.001 */ STVTG_TIMING_MODE_1080I50000_74250, /* SMPTE 295M #2 I50 */ STVTG_TIMING_MODE_1080P30000_74250, /* SMPTE 274M #7 P30 */ STVTG_TIMING_MODE_1080P29970_74176, /* SMPTE 274M #8 P30 /1.001 */ STVTG_TIMING_MODE_1080P25000_74250, /* SMPTE 274M #9 P25 */ STVTG_TIMING_MODE_1080P24000_74250, /* SMPTE 274M #10 P24 */ STVTG_TIMING_MODE_1080P23976_74176, /* SMPTE 274M #11 P24 /1.001 */ STVTG_TIMING_MODE_1035I60000_74250, /* SMPTE 240M #1 I60 */ STVTG_TIMING_MODE_1035I59940_74176, /* SMPTE 240M #2 I60 /1.001 */ STVTG_TIMING_MODE_720P60000_74250, /* EIA770.3 #1 P60 = SMPTE 296M #1 P60 */ STVTG_TIMING_MODE_720P59940_74176, /* EIA770.3 #2 P60 /1.001= SMPTE 296M #2 P60 /1.001 */ STVTG_TIMING_MODE_720P30000_37125, /* ATSC 720x1280 30P */ STVTG_TIMING_MODE_720P29970_37088, /* ATSC 720x1280 30P/1.001 */ STVTG_TIMING_MODE_720P24000_29700, /* ATSC 720x1280 24P */ STVTG_TIMING_MODE_720P23976_29670, /* ATSC 720x1280 24P/1.001 */ STVTG_TIMING_MODE_720P50000_74250, STVTG_TIMING_MODE_1152I50000_74250, STVTG_TIMING_MODE_1080I50000_72000, /* AS 4933-1 200x 1080i(1250) */ STVTG_TIMING_MODE_COUNT /* must stay last */ } STVTG_TimingMode_t;
위의 많은 여러가지의 설정값 중에서 알맞는 것을 찾아 세팅해주어야 한다. 이제 프로그램을 실행해 보자!!