📄 vivot.c
字号:
/*
* Copyright (c) 1995,2000 TriMedia Technologies Inc.
*
* +------------------------------------------------------------------+
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such |
* | a license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided|
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be construed as a commitment by |
* | TriMedia Technologies. |
* | |
* | this code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +------------------------------------------------------------------+
*
* Module name : vivot.c 1.51
*
* Last update : 21:41:02 - 99/07/19
*
* Description :
*
* Revision :
*
*/
/**************************************************************************
* *
* Please ignore this, if you have tm1s1.1 or better. *
* *
* ======>>>>>>>>> IMPORTANT NOTICE <<<<<<<<<<<<<========== *
* If you have tm1s1.0 or older version of chip, please contact Philips *
* TriMedia to exchange to newer version of chip. *
* *
* The tm1s1.0 or older version chips contain video-in hardware bugs *
* # 3016, 21217, 21336, 21390, and require extensive workaround. We *
* are no longer supporting the software workaround. *
* *
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <tm1/mmio.h>
#include <ops/custom_defs.h>
#include <tm1/tmVI.h>
#include <tm1/tmVO.h>
#include <tm1/tmICP.h>
#include <tm1/tmAvFormats.h>
#include <tm1/tmVImmio.h>
#include <tm1/tmVOmmio.h>
#include <tm1/tmInterrupts.h>
#include <tm1/tmProcessor.h>
#include <tmlib/tmlibc.h>
#include <tmlib/dprintf.h>
#include <tmlib/AppModel.h>
#if TBC==1
#include "tbc.h"
static float tbcGain = 0; /* COD 3.21.2000 */
static float tbcPhase = 30; /* COD 3.21.2000 */
int tbcDebug = 1;
#endif
#define VID_RDY_VI 1 /* buffer is ready for vi to use */
#define VID_RDY_MM 2 /* buffer is ready for mm to use */
#define VID_RDY_VO 4 /* buffer is ready for vo to use */
#define NUM_BUF_ENTRIES 4
#define CACHE_LINE_SIZE 64
typedef struct _videoBuf { /* video buffer structure example */
UInt32 Y; /* buffer pointer for Y */
UInt32 U; /* buffer pointer for U */
UInt32 V; /* buffer pointer for V */
UInt32 flag; /* flags used in buffer management */
} vBuf, *pvBuf;
static vBuf fullResBuf[NUM_BUF_ENTRIES];
static vBuf cif422Buf[NUM_BUF_ENTRIES];
static vBuf bkBuf[1];
static vBuf genBuf[NUM_BUF_ENTRIES];
static Bool invertField = False;
static Int viInst;
static viInstanceSetup_t viInstSup;
static viYUVSetup_t viYUVSup;
static Int voInst;
static voInstanceSetup_t voInstSup;
static voYUVSetup_t voYUVSup;
static voOverlaySetup_t voOverlaySup;
static Int icpInst;
static icpInstanceSetup_t icpInstSup;
static icpImageColorConversion_t icpImage;
static Int cifStride = 384;
static Int cifWidth = 352;
static Int cifHeight = 240;
static Int fullStride = 768;
static Int fullWidth = 720;
static Int fullHeight = 480;
static Char *Header = "\nTriMedia Video-In to Video-Out "
"Example Program Version 2.0\n";
static Int viNum = 0;
static Int mmNum = 0;
static Int voNum = 0;
static Int yFieldStride = 0;
static Int uvFieldStride = 0;
static Int overlayFieldStride = 0;
static Int yScanWidth = 0;
static Int uvScanWidth = 0;
static Bool capField = False;
static Bool firstField = False;
static Bool runningOverlay = False;
static Bool endless = False;
static Int loopCount = 1000;
static volatile Int voISRCount = 0;
static tmVideoAnalogStandard_t videoStandard = vasNTSC;
static tmVideoAnalogAdapter_t inAdapterType = vaaCVBS;
static tmVideoAnalogAdapter_t outAdapterType = vaaCVBS;
static unitSelect_t videoInUnit = unit0;
static void
my_abort(Char * name, Int err)
{
assert(name != Null);
fprintf(stderr, "%s failed, error code %x\n", name, err);
exit(-1);
}
void
_voTestISR()
{
UInt32 vo_status = MMIO(VO_STATUS);
Int votmpNum;
voISRCount++;
#if TBC==0
DP(("vo ISR %u %x\n", CYCLES(), vo_status));
#endif
if (voYTR(vo_status))
voAckYTR_ACK();
if (voURUN(vo_status))
voAckURUN_ACK();
if (voHBE(vo_status))
voAckHBE_ACK();
if (voBUF2EMPTY(vo_status))
voAckBFR2_ACK();
if (voBUF1EMPTY(vo_status)) { /* bfr1 empty */
if (runningOverlay) {
if (voFIELD2(vo_status)) {
/* from f1 to f2 */
voYUVChangeBuffer(voInst,
bkBuf[0].Y + yFieldStride,
bkBuf[0].U + uvFieldStride,
bkBuf[0].V + uvFieldStride);
voOverlayChangeBuffer(voInst,
genBuf[voNum].Y + overlayFieldStride);
}
else {
votmpNum = (voNum + 1) % NUM_BUF_ENTRIES;
if (genBuf[votmpNum].flag == VID_RDY_VO) {
genBuf[voNum].flag = VID_RDY_VI;
voNum = votmpNum;
}
voYUVChangeBuffer(voInst,
bkBuf[0].Y,
bkBuf[0].U,
bkBuf[0].V);
voOverlayChangeBuffer(voInst, genBuf[voNum].Y);
}
}
else {
if (voFIELD2(vo_status)) {
/* from f1 to f2 */
voYUVChangeBuffer(voInst,
(Char *) genBuf[voNum].Y + yFieldStride,
(Char *) genBuf[voNum].U + uvFieldStride,
(Char *) genBuf[voNum].V + uvFieldStride);
}
else {
votmpNum = (voNum + 1) % NUM_BUF_ENTRIES;
if (genBuf[votmpNum].flag == VID_RDY_VO) {
genBuf[voNum].flag = VID_RDY_VI;
voNum = votmpNum;
}
voYUVChangeBuffer(voInst,
genBuf[voNum].Y,
genBuf[voNum].U,
genBuf[voNum].V);
}
}
voAckBFR1_ACK();
return;
}
}
void
voTestISR()
{
#pragma TCS_handler
AppModel_suspend_scheduling();
AppModel_run_on_sstack((AppModel_Fun)_voTestISR, Null);
AppModel_resume_scheduling();
}
void
_viTestISR()
{
UInt32 vi_status;
Int oddField;
Int vitmpNum;
UInt32 mmioBase;
#if TBC==1
{
tbcAdjust();
if (!(voTbc.frame % tbcDebug))
DP(("TBC: phase %f -> %f degrees, clock %d hz\n",
voTbc.phase, voTbc.skew, tbcClockFreq(MMIO(VO_CLOCK))));
}
#endif
if (videoInUnit == unit0)
mmioBase = VI1_MMIO_BASE;
else
mmioBase = VI2_MMIO_BASE;
vi_status = MMIO(mmioBase + VI_STATUS_OFFSET);
#if TBC==0
DP(("vi ISR %u %x mmioBase %x\n", CYCLES(), vi_status, mmioBase));
#endif
oddField = viExtractODD(vi_status);
/* Should the field ID be inverted? */
if (invertField)
oddField = !oddField;
if ((vi_status & 0x1) == 0) {
/*
* This is due to hardware bug 21390, a spurious interrupt
* may occur. Since we have only enabled capture_enable (0x1)
* we should not check on threshold_reached (0x2)
*/
return;
}
if (viHBE(vi_status)) {
/*
* Highway banmdwidth, VI needs more bandwidth. You can play
* with the highway arbitration setting
*/
viAckHBE_ACKM(mmioBase);
return;
}
if (capField) {
vitmpNum = (viNum + 1) % NUM_BUF_ENTRIES;
if (oddField & (genBuf[vitmpNum].flag == VID_RDY_VI)) {
genBuf[viNum].flag = VID_RDY_MM;
viNum = vitmpNum;
viYUVChangeBufferM(mmioBase, viInst,
genBuf[viNum].Y,
genBuf[viNum].U,
genBuf[viNum].V);
}
viAckCAP_ACKM(mmioBase);
return;
}
if (firstField) {
firstField = False;
if (!oddField) {
/* skip even field to get sync */
firstField = True;
}
else {
/* always start with odd field */
viYUVChangeBufferM(mmioBase, viInst,
genBuf[viNum].Y + yScanWidth,
genBuf[viNum].U + uvScanWidth,
genBuf[viNum].V + uvScanWidth);
}
}
else {
vitmpNum = (viNum + 1) % NUM_BUF_ENTRIES;
if (genBuf[vitmpNum].flag == VID_RDY_VI) {
genBuf[viNum].flag = VID_RDY_MM;
viNum = vitmpNum;
}
viYUVChangeBufferM(mmioBase, viInst,
genBuf[viNum].Y,
genBuf[viNum].U,
genBuf[viNum].V);
firstField = 1;
}
viAckCAP_ACKM(mmioBase); /* read comments above on the acknowledge */
}
void
viTestISR(void)
{
#pragma TCS_handler
AppModel_suspend_scheduling();
AppModel_run_on_sstack((AppModel_Fun)_viTestISR, Null);
AppModel_resume_scheduling();
}
void
mmBufUpdate()
{
Int mmtmpNum;
mmtmpNum = (mmNum + 1) % NUM_BUF_ENTRIES;
if (genBuf[mmtmpNum].flag == VID_RDY_MM) {
genBuf[mmNum].flag = VID_RDY_VO;
mmNum = mmtmpNum;
}
}
static void
SetupICP()
{
tmLibdevErr_t err;
if (err = icpOpen(&icpInst))
my_abort("icpOpen", err);
memset((char *) &icpInstSup, 0, sizeof (icpInstanceSetup_t));
icpInstSup.interruptPriority = intPRIO_4;
icpInstSup.isr = NULL;
if (err = icpInstanceSetup(icpInst, &icpInstSup))
my_abort("icpInstanceSetup", err);
if (err = icpLoadCoeff(icpInst, NULL))
my_abort("icpLoadCoeff", err);
memset((char *) &icpImage, 0, sizeof (icpImageColorConversion_t));
icpImage.yInputStride = cifStride;
icpImage.uvInputStride = (cifStride >> 1);
icpImage.inputHeight = cifHeight;
icpImage.inputWidth = cifWidth;
icpImage.outputStride = cifWidth<<1;
icpImage.outputHeight = cifHeight;
icpImage.outputWidth = cifWidth;
icpImage.filterBypass = icpFILTER;
icpImage.outputPixelOffset = 0;
icpImage.inType = vtfYUV;
icpImage.inu.inYUVFormat = vdfYUV422Planar;
icpImage.outputDestination = icpSDRAM;
#ifdef __LITTLE_ENDIAN__
icpImage.littleEndian = True;
#else
icpImage.littleEndian = False;
#endif
icpImage.outType = vtfYUV;
icpImage.outu.outYUVFormat = vdfYUV422Sequence;
}
void
CIF422OVERLAY(UInt32 yP, UInt32 uP, UInt32 vP,
UInt32 ovP)
{
UInt8 *pp;
UInt8 *pY0;
UInt8 *pY1;
UInt8 *pU;
UInt8 *pV;
UInt *tmpPtr;
Int i, j;
pY0 = (UInt8 *) yP;
pU = (UInt8 *) uP;
pV = (UInt8 *) vP;
pp = (UInt8 *) yP;
pY1 = ++pp;
tmpPtr = (UInt *) ovP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -