//---------------------------------------------------------------------------- // STISR.C //---------------------------------------------------------------------------- // Description : small description of the goal of the module //---------------------------------------------------------------------------- // Copyright SGS Thomson Microelectronics ! Version alpha ! Jan 1st, 1995 //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Include files //---------------------------------------------------------------------------- #include "stdefs.h" #include "common.h" #include "STllapi.h" #include "stvideo.h" #include "debug.h" #include "error.h" #ifdef STi3520A #include "STi3520A.h" #else #include "STi3520.h" #endif //---------------------------------------------------------------------------- // GLOBAL Variables (avoid as possible) //---------------------------------------------------------------------------- U8 Sequence = 1; //---------------------------------------------------------------------------- // Private Constants //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Private Types //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Private GLOBAL Variables (static) //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Functions (statics one are private) //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Mask Video Interrupts //---------------------------------------------------------------------------- void VideoMaskInt ( PVIDEO pVideo ) { VideoWrite( ITM, 0 ); // mask chip interrupts before reading the status VideoWrite( ITM + 1, 0 ); // avoids possible gliches on the IRQ line #ifdef STi3520A VideoWrite( VID_ITM1, 0 ); // mask chip interrupts before #endif } //---------------------------------------------------------------------------- // Restore Video Interrupts Mask //---------------------------------------------------------------------------- void VideoRestoreInt ( PVIDEO pVideo ) { VideoWrite( ITM, ( pVideo->intMask >> 8 ) ); VideoWrite( ITM + 1, ( pVideo->intMask & 0xFF ) ); } //---------------------------------------------------------------------------- // Interrupt routine (All the control is made in this routine) //---------------------------------------------------------------------------- BOOLEAN VideoVideoInt(PVIDEO pVideo) { BOOLEAN VideoITOccured = FALSE; U16 compute; pVideo->VsyncInterrupt = FALSE; pVideo->FirstDTS = FALSE; #ifdef STi3520A VideoRead ( ITS1 ); #endif /* All interrupts except the first one are computed in this area */ pVideo->intStatus = VideoRead ( ITS ) << 8; // Reading the interrupt status register pVideo->intStatus = VideoRead ( ITS + 1 ) | pVideo->intStatus; // All the STI3500 interrupts are cleared */ pVideo->intStatus = pVideo->intStatus & pVideo->intMask; // To mask the IT not used */ while ( pVideo->intStatus ) // stay into interrupt routine // until all the bits have not // been tested { VideoITOccured = TRUE; /******************************************************/ /** BOTTOM VSYNC INTERRUPT **/ /******************************************************/ if ( ( pVideo->intStatus & BOT ) != 0x0 ) { DBG1('B'); pVideo->intStatus = pVideo->intStatus & ~BOT; // clear BOT bit VideoChooseField ( pVideo); pVideo->currField = BOT; if(pVideo->InvertedField) pVideo->currField = TOP; VideoVsyncRout ( pVideo ); } /******************************************************/ /** TOP VSYNC INTERRUPT **/ /******************************************************/ if ( ( pVideo->intStatus & TOP ) != 0x0 ) { DBG1('T'); pVideo->intStatus = pVideo->intStatus & ~TOP; // clear TOP bit VideoChooseField ( pVideo ); pVideo->currField = TOP; if(pVideo->InvertedField) pVideo->currField = BOT; VideoVsyncRout ( pVideo ); } /******************************************************/ /** DSYNC INTERRUPT **/ /******************************************************/ /***************************************************************/ /* The DSYNC interrupt is generated on each VSYNC (RPT = 0) */ /* if the next INStrucztion has the EXE bit set. */ /* On each DSYNC a new Header Search is automatically started. */ /***************************************************************/ if ( ( pVideo->intStatus & PSD ) != 0x0 ) { DBG1('d'); pVideo->intStatus = pVideo->intStatus & ~PSD; // clear PSD bit pVideo->VsyncNumber = 0; /* clear software watch-dog */ /* check if we have reached the first picture with a PTS */ if ( pVideo->NextInstr.Seq ) // first interrupt enabled (Searching Sequence) { VideoWaitDec ( pVideo ); // put decoder in Wait mode pVideo->intMask = 0x1; /* enable header hit interrupt */ pVideo->NextInstr.Seq = 0; pVideo->NextInstr.Exe = 0; } else { Sequence = 0; if ( VideoGetState ( pVideo ) == VIDEO_START_UP ) { if ( pVideo->pDecodedPict->validPTS == TRUE ) { pVideo->FirstDTS = TRUE; pVideo->VideoState = VIDEO_DECODE; } } /* Check bit buffer level consistency with pVideo->vbveDelay */ /* of the picture that the STi3500 starts to decode */ if ( ( pVideo->fieldMode == 0 ) || ( pVideo->fieldMode == 2 ) ) // frame picture or first field of a field picture { compute = VideoGetBBL(); if ( compute < ( 4 * pVideo->vbvDelay / 5) ) // 0.8 is 4/5 ! // bit buffer level is not high enough for the next // picture: wait !!! { // we stop the current decoding // process for two fields DBG1('<'); VideoEnableDecoding(pVideo, OFF); pVideo->needDataInBuff = pVideo->currField; } } /********************************************************************/ /* * We put the decoder in wait mode on DSYNC: EXE bit reset * into INS. */ /* * In normal case the DSYNC interrupt is quickly followed * by a */ /* * Header Hit int. during which the next INS is written * with EXE=1. */ /* * If for any reason the header hit is delayed, the STi3500 * will */ /* see the notEXE and stay in WAIT mode without crashing... */ /* this can typically appear if the bit buffer gets empty. */ /********************************************************************/ if ( !pVideo->needDataInBuff ) { VideoWaitDec ( pVideo ); // put decoder in Wait mode pVideo->NextInstr.Exe = 0; // reset EXE bit. } /* update the display frame pointer for the next VSYNC */ if ( ( pVideo->fieldMode == 0 ) || ( pVideo->fieldMode == 2 ) ) // frame picture or first field of a field picture { pVideo->pCurrDisplay = pVideo->pNextDisplay; // preset the VSYNC counter pVideo->pictDispIndex = 0 - ( 2 * pVideo->decSlowDown ); if ( pVideo->DecodeMode != SLOW_MODE ) pVideo->decSlowDown = 0; /* allows to do the repeat * function */ VideoWrite( DFP, ( pVideo->pCurrDisplay->buffer >> 8 ) ); VideoWrite( DFP + 1, ( pVideo->pCurrDisplay->buffer & 0xFF ) ); pVideo->displaySecondField = 0; VideoChooseField ( pVideo ); } VideoSetPSV ( pVideo ); // update the next pan vector // frame picture or second field of field picture */ // if ( ( pVideo->VideoState == VIDEO_PAUSE ) && ( pVideo->fieldMode != 2 ) ) // pVideo->pictureDecoded = 1; // to know that in step by step, the picture is decoded } } /******************************************************/ /** HEADER HIT INTERRUPT **/ /******************************************************/ if ( ( pVideo->intStatus & HIT ) != 0 ) // Test Header hit interrupt { U16 temp = 0; pVideo->intStatus = pVideo->intStatus & ~HIT; // clear HIT bit while ( VideoHeaderFifoEmpty()) /* Header fifo not available */ { temp++; if ( temp == 0xFFFF ) { if ( !pVideo->errCode ) pVideo->errCode = BUF_EMPTY; SetErrorCode(ERR_HEADER_FIFO_EMPTY); break; } } /* Waiting... */ compute = VideoRead(HDF); //compute = VideoRead ( HDF ); /* load MSB */ pVideo->hdrPos = 0; /* start code is MSB */ if ( compute == 0x01 ) { pVideo->hdrPos = 8; /* start code value is in LSB */ #ifndef STi3520A pVideo->hdrNextWord = VideoRead ( HDF + 1 ) << 8; #else pVideo->hdrNextWord = VideoRead(HDF)<<8;//VideoRead ( HDF ) << 8; #endif VideoReadHeaderDataFifo ( pVideo ); /* Result in pVideo->hdrFirstWord */ } else { pVideo->hdrNextWord = 0; #ifndef STi3520A pVideo->hdrFirstWord = VideoRead ( HDF + 1 ); #else pVideo->hdrFirstWord = VideoRead(HDF); #endif pVideo->hdrFirstWord = pVideo->hdrFirstWord | ( compute << 8 ); } /* * on that point the start code value is always the MSByte of * pVideo->hdrFirstWord */ switch ( pVideo->hdrFirstWord & 0xFF00 ) { U32 buf_control; U32 size_of_pict; case SEQ: DBG1('s'); VideoSequenceHeader ( pVideo ); VideoLaunchHeadSearch ( pVideo ); /* Restart Header Search */ break; case EXT: VideoExtensionHeader ( pVideo ); VideoLaunchHeadSearch ( pVideo ); /* Restart Header Search */ break; case GOP: DBG1('g'); VideoGopHeader ( pVideo ); VideoLaunchHeadSearch ( pVideo ); /* Restart Header Search */ break; case PICT: DBG1('h'); VideoPictureHeader ( pVideo ); //********************************** //* This part of the code //* Computes the size of last picture //* and substracts it to lastbuffer level //* This allows to track if pipe/scd are misalined //********************************** buf_control = VideoReadSCDCount ( pVideo ); if ( pVideo->LastScdCount > buf_control ) size_of_pict = ( 0x1000000L - pVideo->LastScdCount ) + buf_control; else size_of_pict = buf_control - pVideo->LastScdCount; pVideo->LastScdCount = buf_control; if ( pVideo->fastForward ) pVideo->LastPipeReset = 3; pVideo->LastBufferLevel -= ( U16 ) ( size_of_pict >> 7 ); //****************************** //End of misalined pb tracking //****************************** /* don't restart header search !!! */ if ( pVideo->skipMode ) // restart search only if we // skip this picture { VideoLaunchHeadSearch ( pVideo ); /* Restart Header Search */ } break; case USER: // We don't care about user // fields VideoLaunchHeadSearch ( pVideo ); /* Restart Header Search */ break; case SEQ_END: // end of sequence code compute = VideoRead ( ITS ) << 8; // this start code can be back to back with next one compute = ( compute | VideoRead ( ITS + 1 ) ); // in such case the HDS bit can be set pVideo->intStatus = ( pVideo->intStatus | compute ) & pVideo->intMask; if ( !( pVideo->intStatus & HIT ) ) { VideoLaunchHeadSearch ( pVideo ); /* Restart Header Search */ } break; case SEQ_ERR: // the chip will enter the // automatic error concealment // mode compute = VideoRead ( ITS ) << 8; // this start code can be back to back with next one compute = ( compute | VideoRead ( ITS + 1 ) ); // in such case the HDS bit can be set pVideo->intStatus = ( pVideo->intStatus | compute ) & pVideo->intMask; if ( !( pVideo->intStatus & HIT ) ) { VideoLaunchHeadSearch ( pVideo ); /* Restart Header Search */ } break; default: if ( !pVideo->errCode ) pVideo->errCode = S_C_ERR; SetErrorCode(ERR_UNKNOWN_SC); // non video start code break; } } // end of header hit interrupt /******************************************************/ /** BIT BUFFER FULL INTERRUPT **/ /******************************************************/ if ( ( pVideo->intStatus & BBF ) != 0x0 ) /* Bit buffer full */ { DBG1('*'); pVideo->intStatus = pVideo->intStatus & ~BBF; // clear BBF bit if ( pVideo->vbvReached == 1 ) /* bit buffer level too high */ { if ( !pVideo->errCode ) pVideo->errCode = FULL_BUF; /* mention of the error */ SetErrorCode(ERR_BIT_BUFFER_FULL); VideoWaitDec ( pVideo ); // put decoder in Wait mode pVideo->NextInstr = pVideo->ZeroInstr; } else { S16 BitBufferLevel; BitBufferLevel = BUF_FULL - 2; VideoSetBBThresh(BitBufferLevel); pVideo->intMask = PID | SER | PER | PSD | BOT | TOP | BBE | HIT; /* enable all interrupts that may be used */ VideoRead ( ITS ); #ifdef STi3520A VideoRead ( ITS + 1); #endif // to clear previous TOP VSYNC flag pVideo->NextInstr.Exe = 1;; // decoding will start on // next "good" Vsync */ pVideo->VsyncNumber = 0; pVideo->pictDispIndex = 1; pVideo->pCurrDisplay->nb_display_field = 1; pVideo->vbvReached = 1; } } //*****************************************************/ //* pipeline ERROR **/ //*****************************************************/ // The pipeline reset is made here by software */ // It is also possible to enable the automatic */ // Pipeline reset by setting bit EPR of CTL reg. */ // This could be done in the Reset3500 routine */ // In this case the pipeline error interrupt is */ // only used as a flag for the external micro. */ //*****************************************************/ if ( ( pVideo->intStatus & PER ) != 0x0 ) { DBG1('p'); pVideo->intStatus = pVideo->intStatus & ~PER; // clear PER bit // VideoPipeReset ( pVideo ); } /******************************************************/ /** serious ERROR **/ /******************************************************/ if ( ( pVideo->intStatus & SER ) != 0x0 ) { DBG1('s'); pVideo->intStatus = pVideo->intStatus & ~SER; // clear SER bit VideoPipeReset ( pVideo ); } /********************************/ /* bit buffer empty interrupt */ /********************************/ if ( ( pVideo->intStatus & BBE ) != 0x0 ) // bit buffer empty { pVideo->intStatus = pVideo->intStatus & ~BBE; // clear BBE bit } /********************************/ /* pipeline idle interrupt */ /********************************/ if ( ( pVideo->intStatus & PID ) != 0x0 ) // pipeline idle { //*************************************** // Check If pipe is misalined with scd // and restart header search if it is // the case //*************************************** U32 NewCd; U32 EnterBitBuffer; U16 NewBbl; U16 ExpectedBbl; // clear PID bit pVideo->intStatus = pVideo->intStatus & ~PID; /* read BBL level */ NewBbl = VideoGetBBL(); /* Read number of compressed data loaded into the chip */ NewCd = VideoReadCDCount ( pVideo ); if ( NewCd < pVideo->LastCdCount ) EnterBitBuffer = ( 0x1000000L - pVideo->LastCdCount ) + NewCd; else EnterBitBuffer = ( NewCd - pVideo->LastCdCount ); //Expected Bitbuffer level is Old bbl + what enterred - what left //pVideo->LastBufferLevel holds Old bbl + what enterred and has been // updated in picture hit interrupt. ExpectedBbl = pVideo->LastBufferLevel + ( EnterBitBuffer >> 8 ) - 2; if ( pVideo->LastPipeReset == 0 ) { /* BBL is lower than it should be !!! */ if ( NewBbl < ExpectedBbl ) { DBG1('#'); /* here we force manually a new header search because */ /* the pipeline is supposed to have skipped a picture */ /* i.e. the start code detector and the pipeline are */ /* not synchronised on the same picture */ VideoLaunchHeadSearch ( pVideo ); pVideo->LastPipeReset = 1; } } else { pVideo->LastPipeReset--; } pVideo->LastCdCount = NewCd; pVideo->LastBufferLevel = NewBbl; } /******************************************************/ /** END OF INTERRUPT ROUTINE **/ /******************************************************/ /* common to all interrupts */ /* set interrupt mask to the correct value */ } // end of while return VideoITOccured; } //------------------------------- End of File --------------------------------