//---------------------------------------------------------------------------- // STDISP.C //---------------------------------------------------------------------------- // Description : Display management routines //---------------------------------------------------------------------------- // Copyright SGS Thomson Microelectronics ! Version alpha ! Jan 1st, 1995 //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Include files //---------------------------------------------------------------------------- #include "stdefs.h" #include "common.h" #include "STvideo.h" #include "stllapi.h" #include "error.h" #ifdef STi3520A #include "STi3520A.h" #else #include "STi3520.h" #endif //---------------------------------------------------------------------------- // GLOBAL Variables (avoid as possible) //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Private Constants //---------------------------------------------------------------------------- #define SIZE_OF_PICT 540 //---------------------------------------------------------------------------- // Private Types //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Private GLOBAL Variables (static) //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Functions (statics one are private) //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Enable OSD //---------------------------------------------------------------------------- VOID VideoOsdOn(PVIDEO pVideo) { pVideo->currDCF = pVideo->currDCF | 0x10; DisableIT(); VideoWrite(DCF, 0); VideoWrite(DCF + 1, pVideo->currDCF); EnableIT(); } //---------------------------------------------------------------------------- // Disable OSD //---------------------------------------------------------------------------- VOID VideoOsdOff ( PVIDEO pVideo ) { pVideo->currDCF = pVideo->currDCF & 0xEF; DisableIT(); VideoWrite(DCF, 0); VideoWrite(DCF + 1, pVideo->currDCF); EnableIT(); } //---------------------------------------------------------------------------- // initialisation of the OSD pointers //---------------------------------------------------------------------------- void VideoInitOEP (PVIDEO pVideo, U32 point_oep ) { #ifndef STi3520A VideoWrite ( OEP, ( point_oep >> 13 ) & 0xFF ); VideoWrite ( OEP + 1, ( point_oep >> 5 ) & 0xFF ); VideoWrite ( OOP, ( point_oep >> 13 ) & 0xFF ); VideoWrite ( OOP + 1, ( point_oep >> 5 ) & 0xFF ); #else VideoWrite ( VID_OBP, ( point_oep >> 13 ) & 0xFF ); VideoWrite ( VID_OBP, ( point_oep >> 5 ) & 0xFF ); VideoWrite ( VID_OTP, ( point_oep >> 13 ) & 0xFF ); VideoWrite ( VID_OTP, ( point_oep >> 5 ) & 0xFF ); #endif } //---------------------------------------------------------------------------- // Set video window position and size (top left=X0,Y0) (bottom right=X1,Y1) //---------------------------------------------------------------------------- void VideoSetVideoWindow (PVIDEO pVideo, U16 a, U16 b, U16 c, U16 d ) { pVideo->Xdo = a; pVideo->Ydo = b; pVideo->Xd1 = c; pVideo->Yd1 = d; VideoInitXY (pVideo); } //---------------------------------------------------------------------------- // Initialisation of the horizontal & vertical offsets //---------------------------------------------------------------------------- void VideoInitXY(PVIDEO pVideo) { U16 yds, xds; // set vertical stop position if ( pVideo->StreamInfo.verSize <= 288 ) // half res decoding yds = pVideo->StreamInfo.verSize + pVideo->Ydo - 129; /* number of lines + offset - 128 - 1 */ else // full resolution decoding yds = ( pVideo->StreamInfo.verSize >> 1 ) + pVideo->Ydo - 129; /* number of lines + offset - 128 - 1 */ if ( yds > pVideo->Yd1 ) yds = pVideo->Yd1; // set horizontal stop position: we always display 720 pixels // XDS given by the relation: 2*XDO + 40 + 2*L = 2*XDS + 28 // XDS = XDO + 726 with 720 displayed pixels. xds = pVideo->Xdo + 726; if ( xds > 800 ) /* 800 = max number of pels allowed per line */ xds = 800; if ( xds > pVideo->Xd1 ) xds = pVideo->Xd1; /* not bigger than the video window */ SetXY( pVideo, xds, yds ); } //---------------------------------------------------------------------------- // Storage of the horizontal & vertical offsets //---------------------------------------------------------------------------- void SetXY(PVIDEO pVideo, U16 xds, U16 yds) { #ifndef STi3520A U8 dcfh, dcfl; VideoWrite ( YDO, pVideo->Ydo ); VideoWrite ( XDO, pVideo->Xdo & 0xFF ); VideoWrite ( YDS, yds ); /* stores YDS into tempo internal register */ VideoWrite ( XDS, xds & 0xFF ); /* writes YDS and XDS values into the chip */ // write XDO and XDS MSbits D9 and D8 dcfh = VideoRead ( DCF ); VideoWrite ( DCF, dcfh | 0x10 ); // preset a write to XDO[9:8] dcfl = VideoRead ( DCF + 1 ); VideoWrite ( DCF + 1, dcfl & 0xFF ); // allows to write DCF. VideoWrite ( XDO, (pVideo->Xdo >> 8)&0xFF ); VideoWrite ( XDS, xds >> 8 ); VideoWrite ( DCF, dcfh ); VideoWrite ( DCF + 1, dcfl ); // allows to write DCF. #else //0xds = pVideo->Xdo + SIZE_OF_PICT +6; VideoWrite ( XDO , pVideo->Xdo >> 8 ); VideoWrite ( XDO+1 , pVideo->Xdo & 0xFF ); VideoWrite ( YDO , pVideo->Ydo ); VideoWrite ( XDS , xds >> 8 ); VideoWrite ( XDS+1 , xds & 0xFF ); VideoWrite ( YDS , yds ); #endif } //---------------------------------------------------------------------------- // Set next display frame pointer //---------------------------------------------------------------------------- /* This routine determines which is the next frame pointer that must be used for display. It takes care about the fact that the temporal references may not be consecutive in case of sikipped pictures... */ VOID VideoDisplayCtrl(PVIDEO pVideo) { S16 comput1, index; U16 min_temp_ref; U16 cur_ref; min_temp_ref = ( pVideo->currTempRef & 0xF000 ) + 1024; // keep current pVideo->GOPindex index = 5; pVideo->currTempRef++; /* increment display temporal ref */ /************** WARNING ************/ // this routine will not work properly if GOP size > 1023 if ( ( pVideo->currTempRef & 0xFFF ) > 1023 ) // 2 msb are used as pVideo->GOPindex pVideo->currTempRef = pVideo->currTempRef & 0xF000; /* max temp ref is 1023: reset to 0 */ /* search frame store to display */ for (comput1 = 0; comput1 <= 3; comput1++) { cur_ref = pVideo->pictArray[comput1].tempRef & 0xFFF; if ( ( ( pVideo->currTempRef & 0xF000 ) == ( pVideo->pictArray[comput1].tempRef & 0xF000 ) ) && ( pVideo->currTempRef <= pVideo->pictArray[comput1].tempRef ) && ( min_temp_ref > cur_ref ) ) { // pVideo->currTempRef and pVideo->pictArray[comput1] refer to the same GOP // we want to extract the minimum temporal reference min_temp_ref = cur_ref; index = comput1; } } if (index == 5) { /* There is a group of pictures change: reset pVideo->currTempRef and increment pVideo->GOPindex */ pVideo->currTempRef = ( pVideo->currTempRef & 0xF000 ) + 0x4000; min_temp_ref = min_temp_ref + 0x4000; /* search frame store to display */ for (comput1 = 0; comput1 <= 3; comput1++) { cur_ref = pVideo->pictArray[comput1].tempRef & 0xFFF; if ( ( ( pVideo->currTempRef & 0xF000 ) == ( pVideo->pictArray[comput1].tempRef & 0xF000 ) ) && ( pVideo->currTempRef <= pVideo->pictArray[comput1].tempRef ) && ( min_temp_ref > cur_ref ) ) { // pVideo->currTempRef and pVideo->pictArray[comput1] refer to the same GOP // we want to extract the minimum temporal reference min_temp_ref = cur_ref; index = comput1; } } } if (index == 5) { if (!pVideo->errCode) pVideo->errCode = TEMP_REF; /* No pVideo->currTempRef corresponding to the display one */ SetErrorCode(ERR_NO_TEMPORAL_REFERENCE); } else { pVideo->pNextDisplay->tempRef = 1025; // to release the previous pointer for next decoding pVideo->pNextDisplay = &pVideo->pictArray[index]; if ( pVideo->pNextDisplay->validPTS == FALSE ) { /* PTS not available: compute a theoretical value */ U16 lattency = 3000; /* two 60Hz fields lattency */ if ( pVideo->StreamInfo.displayMode == 0 ) lattency = 3600; /* two 50Hz fields lattency */ pVideo->pNextDisplay->dwPTS = pVideo->pCurrDisplay->dwPTS + lattency; } // set next display pointer pVideo->currTempRef = pVideo->pictArray[index].tempRef; pVideo->pictArray[index].tempRef = 1024; /* this pVideo->currTempRef must not interfer on next tests */ } } //---------------------------------------------------------------------------- // Set parameters related to picture size //---------------------------------------------------------------------------- /* This routine will always program the sample rate converter in order to display 720 horizontal pixels */ VOID VideoSetPictureSize(PVIDEO pVideo) { U16 compute, comput1; if ( (pVideo->StreamInfo.horSize > 720 ) || (pVideo->StreamInfo.verSize > 576 )) { if ( !pVideo->errCode ) pVideo->errCode = HIGH_CCIR601; // picture size higher than CCIR601 format SetErrorCode(ERR_HIGHER_THAN_CCIR601); return; } // set SRC depending on the horizontal size in order to display 720 // pixels if ( pVideo->StreamInfo.horSize < 720 ) { // lsr = 256 * (pVideo->StreamInfo.horSize-4) / (display size - 1) VideoSetSRC(pVideo, pVideo->StreamInfo.horSize, 720); } else { VideoSRCOff(pVideo); } if ( ( pVideo->StreamInfo.horSize >= 544 ) && ( ( pVideo->StreamInfo.pixelRatio == 0x3 ) || ( pVideo->StreamInfo.pixelRatio == 0x6 ) ) ) { // picture size = 720 but pixel aspect ratio is 16/9 // Program the SRC for display on a 4/3 screen // 544 pixels of the decoded picture extended into 720 pixels // for display VideoSetSRC(pVideo, 544, 720); } // set vertical filter and half/full resolution depending on the // vertical picture size if ( pVideo->StreamInfo.verSize > 288 ) { // typically 480 or 576 lines VideoSetFullRes(pVideo); } else { // typically 240 or 288 lines // VideoSetFullRes(pVideo); VideoSetHalfRes(pVideo); } // set picture sizes into the decoder comput1 = pVideo->StreamInfo.horSize + 15; // Horizontal size + 15 comput1 = ( comput1 >> 4 ) & 0xFF; // divide by 16 VideoWrite ( DFW, comput1 ); // Decoded Frame Width in number of MB compute = ( pVideo->StreamInfo.verSize + 15 ) >> 4; compute = ( compute * comput1 ) & 0x3FFF; #ifndef STi3520A VideoWrite ( DFS, ( ( compute >> 8 ) & 0xFF ) ); /* Decoded Frame Size in number of MB */ VideoWrite ( DFS + 1, ( compute & 0xFF ) ); #else VideoWrite ( DFS, ( ( compute >> 8 ) & 0xFF ) ); /* Decoded Frame Size in number of MB */ VideoWrite ( DFS , ( compute & 0xFF ) ); VideoWrite ( VID_DFA , 0 ); VideoWrite ( VID_DFA , 0 ); VideoWrite ( VID_XFW, comput1 ); VideoWrite ( VID_XFS, ( ( compute >> 8 ) & 0xFF ) ); VideoWrite ( VID_XFS, ( compute & 0xFF ) ); VideoWrite ( VID_XFA , 0 ); VideoWrite ( VID_XFA , 0 ); #endif } //---------------------------------------------------------------------------- // store the next pan vector //---------------------------------------------------------------------------- void VideoSetPSV(PVIDEO pVideo) { S16 compute, comput1, psv_index, vert_pan; #ifdef STi3520A U16 Scan, Pan; return; #endif //---- If pan/scan not defined in sequence display extension if (!pVideo->seqDispExt) return; // can't be computed ! /**** point to the next offset ****/ if ( pVideo->pictDispIndex < 0 ) psv_index = 0; // in case of tempo else if ( pVideo->pictDispIndex == pVideo->pCurrDisplay->nb_display_field ) psv_index = pVideo->pictDispIndex - 1; // when we reach the last VSYNC of display else psv_index = pVideo->pictDispIndex; /**** determine next vertical pan and scan offset ****/ compute = ( pVideo->StreamInfo.verSize - pVideo->StreamInfo.verDimension ) >> 1; compute = compute + ( pVideo->pCurrDisplay->pan_vert_offset[psv_index] >> 4 ); // discard fractional part compute = compute >> 2; // vertical offset is multiple of 4 lines if ( compute < 0 ) compute = 0; // negative offsets not supported if ( compute > 0x7F ) compute = 0x7F; // vertical PSV is 7 bits vert_pan = compute << 9; // vert offset in bits 15 to 9 of PSV register /**** determine next horizontal pan and scan offset ****/ // pan&scan = (pVideo->StreamInfo.horSize/2 - pVideo->StreamInfo.horDimension/2 + offset) compute = ( pVideo->StreamInfo.horSize - pVideo->StreamInfo.horDimension ) << 3; // (pVideo->StreamInfo.horSize/2-pVideo->StreamInfo.horDimension/2) * 16 compute = compute + pVideo->pCurrDisplay->pan_hor_offset[psv_index]; if ( compute < 0 ) compute = 0; // negative offsets not supported // program the integer part of the pan and scan offset // into PSV register that will be taken into account on next VSYNC comput1 = compute >> 4; // keep integer part only for PSV if ( comput1 > 0x1FF ) comput1 = 0x1FF; #ifndef STi3520A // max PSV is 9 bits on STi3500 VideoWrite ( PSV, ( comput1 >> 8 ) | vert_pan ); // store pan & scan vector integer part VideoWrite ( PSV + 1, comput1 & 0xFF ); // store pan & scan vector integer part #else vert_pan = vert_pan; Pan = comput1 & 0x1FF; Scan = ((comput1 >> 9)&0x7F)*2; VideoWrite ( VID_PAN, ( Pan >> 8 )); VideoWrite ( VID_PAN + 1, Pan & 0xFF ); VideoWrite ( VID_SCN, ( Scan >> 8 )); VideoWrite ( VID_SCN + 1, Scan & 0xFF ); #endif // program the fractional part of the horizontal offset // the fractional part of the pan and scan offset is expressed as // 1/256 multiples comput1 = ( compute & 0xF ) << 4; // keep fractional part and multiply by 16 VideoRead ( LSO ); compute = VideoRead ( LSR ); VideoWrite ( LSO, comput1 & 0xFF ); // program luma offset VideoWrite ( LSR, compute ); // divide by 2 chroma offset VideoRead ( CSO ); #ifndef STi3520A // program chroma offset compute = VideoRead ( CSR ); VideoWrite ( CSO, comput1 >> 1 ); VideoWrite ( CSR, compute ); #else VideoWrite ( CSO, comput1 >> 1 ); #endif } //---------------------------------------------------------------------------- // Enable/disable the SRC //---------------------------------------------------------------------------- void VideoSwitchSRC ( PVIDEO pVideo ) { if (pVideo->useSRC != 0x0) { pVideo->currDCF = pVideo->currDCF ^ DSR; /* Switch SRC */ VideoWrite (DCF, 0); VideoWrite (DCF + 1, pVideo->currDCF); } else { // what ? } } //---------------------------------------------------------------------------- // enable the SRC //---------------------------------------------------------------------------- void VideoSRCOn ( PVIDEO pVideo ) { pVideo->useSRC = 0xFF; pVideo->currDCF = pVideo->currDCF & ~DSR ; /* Enable SRC */ VideoWrite ( DCF, 0 ); VideoWrite ( DCF + 1, pVideo->currDCF ); } //---------------------------------------------------------------------------- // Disable the SRC //---------------------------------------------------------------------------- void VideoSRCOff ( PVIDEO pVideo ) { pVideo->useSRC = 0x00; pVideo->currDCF = pVideo->currDCF | DSR ; /* Enable SRC */ VideoWrite ( DCF, 0 ); VideoWrite ( DCF + 1, pVideo->currDCF ); } //---------------------------------------------------------------------------- // display a full screen OSD with a uniform color (just as example) */ //---------------------------------------------------------------------------- /* color 0 is green color 1 is yellow color 2 is cyan color 3 is magenta the OSD area is here defined from address zero in normal application this area is reserved for the bit buffer and the OSD will be typically defined after the bit buffer. Note: The bit buffer is defined in multiple of 256 bytes while MWP, OEP and OOP are memory addresses in mulitple of 64 bits */ void VideoFullOSD (PVIDEO pVideo, S16 col ) { long big; U16 counter; VideoSetMWP(0L); counter = 0; while ( !VideoMemWriteFifoEmpty()) { counter ++; if (counter == 0xFF) { pVideo->errCode = BAD_MEM_V; SetErrorCode(ERR_MEM_WRITE_FIFO_NEVER_EMPTY); return ; } } VideoWrite ( MWF, 19 ); /* line 19 */ VideoWrite ( MWF, 0x1 ); /* stop row */ VideoWrite ( MWF, 0x02 ); /* 19 + 240 - 1 */ VideoWrite ( MWF, 0x00 ); /* start column */ VideoWrite ( MWF, 100 ); /* column 100 */ VideoWrite ( MWF, 0x3 ); /* stop column = 100 + 700 - 1= * 31F */ VideoWrite ( MWF, 0x1F ); /* end init display size and * position */ VideoWrite ( MWF, 0x90 ); /* color 0 = green */ VideoWrite ( MWF, 0x32 ); VideoWrite ( MWF, 0xD0 ); /* color 1 = yellow */ VideoWrite ( MWF, 0x19 ); VideoWrite ( MWF, 0xA0 ); /* color 2 = cyan */ VideoWrite ( MWF, 0xA1 ); VideoWrite ( MWF, 0x60 ); /* color 3 = magenta */ VideoWrite ( MWF, 0xDE ); // 6/D/E if ( col == 1 ) col = 0x55; else if ( col == 2 ) col = 0xAA; else if ( col == 3 ) col = 0xFF; for ( big = 0; big < 42000L; big++ ) // 42000 = 240 * 700 / 4 { VideoWrite ( MWF, col ); // select color } for ( big = 0; big < 8; big++ ) // add a dummy window outside // the display VideoWrite ( MWF, 0xFF ); // to stop OSD VideoInitOEP ( pVideo, 0 ); // set OEP and OOP to start of // bit map address VideoWrite ( DCF, 0 ); VideoWrite ( DCF + 1, pVideo->currDCF | 0x30 ); // enable OSD } //------------------------------- End of File --------------------------------