DVI 는 무엇인가
일단 나도 잘 모르기 때문에 텀즈에서 찾은 DVI에 대한 용어 설명을 첨부한다.
DVI는 아날로그와 디지털 모니터를 하나의 커넥터에 수용하기 위해 DDWG (Digital Display Working Group)에서 만든 규격이다. DVI에는 모두 세 가지 서로 다른 종류의 구성이 있는데,DVI-A는 아날로그 신호를 위해, DVI-D는 디지털 신호를 위해, 그리고 DVI-I는 아날로그와 디지털 신호 모두를 위해 설계되었다. DVI 커넥터와 포트를 사용하면, 아날로그 모니터로 보내지는 디지털 신호가 아날로그 신호로 변환된다. 만약 모니터가 평면 디스플레이 등과 같은 디지털 모니터라면, 신호 변환이 필요치 않다. 요즘에는 많은 종류의 모니터에 DVI 커넥터가 장착되어 있으며, 비디오 어댑터도 전통적인 15핀 VGA 포트 대신 DVI 포트를 장착한 채 출시되는 경우가 많다.
아무리 읽어봐도 감이 잡히지 않는다. 모르긴 몰라도, DVI 가 디지털 신호와 관련이 있는 듯 하다.
시작하기 전에
내가 이번에 맞게된 일은 HD 보드의 DVI 의 출력을 가능하게 하는 것이다. 현재는 RGB 와 YPPCR 같은 다양한 형태의 포트를 지원해야 한단다. 그중에서 DVI 역시 요즘들어 많이 사용되고 있는 것 중에 하나이다.
셋톱박스는 HEADEND 와 TV 사이에서 신호를 변환하는 역할을 하므로, TV(출력장치) 에 상관없이 AV 를 보여주어야 한다.
DVI 의 경우 I2C 를 이용해서 콘트롤하게 된다.
현재 7020 으로 들어오는 TS 스트림을 튜너에서 튜닝하여, 데이터를 어디로 내보낼 것인지를 선택하게끔 되어있다.
DAC5000 의 VOUT_Inital() 함수가 바로 그것이다.
ST_ErrorCode_t VOUT_Inital( void ) { STVOUT_InitParams_t VOUTInitParams; STVOUT_OutputParams_t VOUTOutputParams; STVOUT_OpenParams_t OpenParams; ST_ErrorCode_t ErrCode; VOUTInitParams.CPUPartition_p = system_partition; VOUTInitParams.MaxOpen = 3; VOUTInitParams.DeviceType = STVOUT_DEVICE_TYPE_7020; VOUTInitParams.OutputType = STVOUT_OUTPUT_HD_ANALOG_YUV;//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)); VOUTOutputParams.Analog.StateBCSLevel=STVOUT_PARAMS_NOT_CHANGED; VOUTOutputParams.Analog.BCSLevel.Brightness=0; VOUTOutputParams.Analog.BCSLevel.Contrast=0; VOUTOutputParams.Analog.BCSLevel.Saturation=0; VOUTOutputParams.Analog.EmbeddedType = TRUE; VOUTOutputParams.Analog.SyncroInChroma = FALSE; VOUTOutputParams.Analog.ColorSpace=2; ErrCode = STVOUT_Open(VOUTDeviceName, &OpenParams,&VOUTHndl); if (ErrCode != ST_NO_ERROR) { STTBX_Print(("STVOUT_Init %s\n", GetErrorText(ErrCode) )); } 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))); return(ErrCode); }
위의 소스를 보고 잘 이해가 안간다면, DAC5000 문서를 참고하기 바란다. 참고로 작업 환경은 다음과 같다.
CPU | 5517 |
AV | 7020 |
APP | DAC5000 |
DVI | SIL178 |
확인된 문제점 및 해결
DVI를 진행하면서, 여러가지 문제점이 발견되고 또한 해결되었다. 추후에 이와 비슷한 일에 대한 대비를 위해 문제가 되었던 것들과 해결방법에 대해서 서술하여 보겠다.
- I2C Device Number 오류 문제
- read/write 문제
- 하드웨어 보드 문제
- DCLK 신호 출력 문제
문제를 크게 2가지로 요약할 수 있었다.
첫번째로 i2c 통신에서 가장 중요하다고 할 수 있는 device number 이다. 데이터시트 상에는 master 일 경우 0x72, slave 일 경우 0x70 으로 적혀 있었다. 여기서 말하는 master 와 slave 는 sil178 을 dual mode 로 사용할 때를 이야기 하는 것이다.
하지만, HD 의 경우는 single mode 로 사용할 것이다. 그래서 나는 당연히 master mode 로 설정해야 하는 줄 알았다. 하지만, 0x72 로 해봐도 sil178 쪽에서 ack 신호가 오지 않았다. 결국 slave mode 였던, 0x70 으로 시도해본 결과 ack 신호가 왔다.
두번째는 이미 resolve 되어 있는 주소번지에 값이 제대로 읽혀지지 않거나, 제대로 쓰여지지 않은 문제이다. 오실로스코프로 테스트해봤지만, device number 와 읽을 주소나, 쓸 주소가 제대로 입력되어지고 있었다. 하지만, 나오는 결과값이 잘못되고 있었다.
결국 문제의 원인은 i2c 의 유일한 통신통로인 sda, sck 의 저항값과 이와 관련한 pull-up 문제였다.
기존의 회로도에서는 저항값이 510 옴을 썼다. 하지만, 이것은 너무 컸다. 그래서 100 옴으로 수정했다. 또한 이 통신 통로의 cpu3.3v 의 pull-up 이 잡혀있었다. 또한 u30 칩을 달면서 pull-up 을 잡아주었다. 만일 둘다 pull-up 을 잡아주지 않으면, read 시 제대로 된 값이 출력되지 않는다.
세번째는 가장 중요하다고 할 수 있는 하드웨어 문제이다. 예전 보드(5517 큰 패키지)의 경우에는 예상대로 잘 동작하였다. 총 3대의 보드 중에서 2개는 정상이었지만, 하나는 처음에 read 또는 write 동작을 하면, ack 시그널이 안뜨는 문제가 있다. 분명히 0x70 주소는 제대로 나갔는데도 말이다.
최신 보드(5517 작은 패키지)의 경우는 더 심각하다. 어떨 때는 read/write 가 제대로 되다가도, 어떨 때는 둘 다 엉뚱한 값이 나온다.
네번째는 7020 에서 DVI 쪽으로 들어가는 DCLK 신호 문제였다. 일종의 클럭인데, 클럭에 따라 DVI 로 들어가는 데이터를 latch 하기 때문에 필수로 들어가야 하는 신호였다. 하지만, 오실로 스코프로 확인한 결과 신호가 나오지 않고 있었다. 문제의 원인은 레지스터 세팅에 있었다. system/clk_gen.c 파일을 보면, 아래와 같은 부분이 있다.
/* Set PIXCLK as an input */ //STSYS_WriteRegDev32LE(CKG + CKG_PRE_DIV, 0x0); <-- 기존의 소스 /* Invert PIXCLK output from STi7015 to get a correct clock */ // STSYS_WriteRegDev32LE(DSPCFG + DSPCFG_CLK, VOS_CLK_INVCLK); <-- 기존의 소스 /* FC: Enable PIXCLK output */ STSYS_WriteRegDev32LE(CKG + CKG_PRE_DIV, CKG_PRE_DIV_PXO); <-- 추가된 부분 /* Invert PIXCLK output from STi7015 to get a correct clock */ STSYS_WriteRegDev32LE(DSPCFG + DSPCFG_CLK, VOS_CLK_INVCLK); <-- 추가된 부분
위처럼 수정을 해주고 나서, 실행해보면, DCLK 가 출력되는 것을 볼 수 있다.
마치면서
하드웨어에 대한 문제는 항상 데이터시트에 답이 있다. 그렇기 때문에 데이터시트를 반드시 정독해야만 한다. 하드웨어만 확실히하면, 50% 는 성공이기 때문이다.
앞에서 문제점을 적었지만, 너무 맹신해서도 안된다. i2c device number 의 경우에도, 어떻게 해석하느냐에 따라서 결과가 달라지기 때문이다.
현재까지 진행상황
지금까지 여러가지 실험을 통해서 Sil178 에 r/w 가 제대로 되고 있다는 것을 확인했다.
또한 7020 으로부터 들어가는 신호 역시 제대로 입력되어지고 있다는 것을 확인했다.
제기된 문제점
레지스터 세팅에 문제가 있다. 현재 가지고 있는 소스코드(Sil168 관련)와 현재 178 과는 많은 차이가 있는 듯 하다. chip 을 reset 하는 과정이다. init 하는 과정에서 r/w 하는 레지스터들을 보면, 구조가 전혀 다르다는 것을 알 수 있다. 게다가 168 데이터시트를 구할 길이 없는 현재로서는, 일일이 맞는 세팅을 찾아야 하는 상태에 있다.
데이터 시트의 내용과 여러가지 실험을 한 결과, 몇가지 문제점과 결론을 내릴 수 있었다.
- 레지스터에 R/W 는 제대로 된다(데이터 시트에 나와 있는 MSEN 의 핀을 통해 확신할 수 있었다)
- SIL178 로 들어가는 신호는 정상으로 판명되었다(오실로스코프로 찍어본 결과 크게 다르지 않았다
위와 같은 상황을 볼 때, 출력이 안 나오는 것이 더 이상할 정도였다.
- SIL178 샘플을 더 충분히 확보
- 더 많은 타겟보드를 확보
- 현재 삼성 STB 에서 나오는 DVI 신호를 찍어봐서 비교
- DVI 모니터 구입
내 생각에서는 현재 두 대의 보드가 현상이 같은 것으로 봐서, 더 많은 보드로 실험한다고 해서, 결과는 달라지지 않을 것 같다. 일단 삼성 STB 의 출력단을 보고, 판단을 해야 할 것이다.
세번째 방법이었던, 실제로 삼성 STB 에서 나오는 DVI 출력단을 오실로 스코프로 찍어보았다.
결과 TX 쪽은 나오지 않았고, 6번(DDC_CLK)과 7번(DDC_DATA) 에서만 3V(High) 가 떴고, 14번(+5V) 에서는 5V 가 떴다. 그 외 나머지 핀들에서는 모두 LOW 가 찍혔다.
앞으로의 계획
데이터시트를 보고, 맡는 세팅을 추측하여, 레지스터를 세팅하는 방법 밖에는 없는 것 같다.