📄 ave2koverlay.c
字号:
//
//File name: AVE2KOVERLAY.C
//This file contains code to control overlay function of SAA7146A
#include "ave2k.h"
#include "ave2kregs.h"
#include "ave2koverlay.h"
#include "SAA7111.h"
#include "hpsv.h"
#include "hpsh.h"
#include "rps.h"
//Predeclaration of local used functions
static ULONG Dcgx(ULONG x);
static void UploadVideo(PDEVICE_EXTENSION pDE);
static void Setup_HScale(PDEVICE_EXTENSION pDE, int nip, int nop, ULONG hxo);
static void Setup_VScale(PDEVICE_EXTENSION pDE, int nil, int nol, ULONG hyo);
void StopVideo(PDEVICE_EXTENSION pDE);
static void StartVideo(PDEVICE_EXTENSION pDE);
static void Shift(PDEVICE_EXTENSION pDE, int nChannel);
static void BuildClipInfo(ULONG ClipDmaBuffer[], PAVE2KCLIPLIST pClipList);
static void DisableAllClip(PDEVICE_EXTENSION pDE);
static void GetHScaleParas(int nip, int nop, ULONG hxo, ULONG *HPreScale, ULONG *HScale);
static void GetVScaleParas(int nil, int nol, ULONG hyo, ULONG *VScale, ULONG *VGain);
//#define NIP 703
//#define NIL 288
static void SetDual(PDEVICE_EXTENSION pDE);
static void SetFullDual(PDEVICE_EXTENSION pDE);
static void SetFrameRate(PDEVICE_EXTENSION pDE);
static BOOLEAN JudgeInterlace(PDEVICE_EXTENSION pDE);
#define HXO 0x10
#define HYO 0x1a
#define LOCALBUFFER 1
#if _WIN32_WINNT==0x0400
//Simulate win 2k ddk function.
//#define MmGetMdlPfnArray(pMdl) ((PULONG)(pMdl+1))
#endif
ULONG CaptureBitmap(PDEVICE_EXTENSION pDE, PMDL pMdl, PAVE2K_BITMAP_PARA pBitmapPara)
{
int rpsIndex;
ULONG outformat;
int nChannel;
ULONG dFrame;
int nWidth, nHeight;
int pitch,depth,nFormat;
ULONG nol;
ULONG nil;
int i;
ULONG lPage[470];
int nTotalPage;
PHYSICAL_ADDRESS Phy;
ULONG reg_Page, reg_Dma;
PULONG pPage;
LARGE_INTEGER Elapse;
pPage=MmGetMdlPfnArray(pMdl);
nWidth=pBitmapPara->nWidth;
nHeight=pBitmapPara->nHeight;
nChannel=pBitmapPara->nChannel;
nFormat=pBitmapPara->nFormat;
switch(nFormat)
{
case 0:
depth=3;
break;
case 1:
depth=4;
break;
case 2:
depth=2;
break;
case 3:
depth=1;
break;
default:
depth=3;
break;
}
/* if(pBitmapPara->nFormat==0)
depth=3;//RGB24
else
if(pBitmapPara->nFormat==2)
depth=2;//YUYV
else
depth=4;//RGB32*/
//1. pitch
pitch = (nWidth*depth+3)&0xfffffffc;
//pitch = pDE->DisplayParameter.Pitch;
//nWidth=320;
//nHeight=288;
#if(LOCALBUFFER==0)
//A new way to get total MDL page compatible with WIN2K
nTotalPage=(MmSizeOfMdl(MmGetMdlVirtualAddress(pMdl),
MmGetMdlByteCount(pMdl)))/4;
//2.
//nTotalPage=(pMdl->Size-sizeof(MDL))/4;
//nTotalPage=(800*600*4)/4096+2;
for(i=0; i<nTotalPage; i++)
//3.
lPage[i]=*(pPage+i)<<12;
//lPage[i]=pDE->DisplayParameter.PhysicalAddress+(i<<12);
Phy=MmGetPhysicalAddress(lPage);
#endif
//4.
#if(LOCALBUFFER)
reg_Page=0x0;
#else
reg_Page=(Phy.u.LowPart&0xfffff000)|(1<<11);//|0x08;
#endif
//5.
#if(LOCALBUFFER)
reg_Dma=pDE->BitmapCommonBuffer.DMAAddress;
#else
reg_Dma=((Phy.u.LowPart&0xffc)<<10)|pMdl->ByteOffset;
//reg_Dma=((Phy.u.LowPart&0xffc)<<10);
//reg_Dma=pDE->DisplayParameter.PhysicalAddress;
#endif
pDE->NIP = 702;//702->700
if(pDE->VideoType[nChannel]==VIDEOTYPE_UNKNOWN)
{
//pDE->VideoType[nChannel] = GetVideoType(pDE, nChannel);
int nVT=GetVideoType(pDE,nChannel);
if(nVT==VIDEOTYPE_NONE)
pDE->VideoType[nChannel]=pDE->nPreVideoType[nChannel];
else
pDE->VideoType[nChannel] =nVT;
}
if(pDE->VideoType[nChannel] == VIDEOTYPE_NTSC)
pDE->NIL = 240;
else
pDE->NIL = 288;
//Ave2kWriteRegister(pDE, DD1_INIT, 0x07000700);
//------ setup HPS ------
StopVideo(pDE);
dFrame=reg_Dma;
nol = nHeight;
nil = pDE->NIL;
if(nol>nil){
Ave2kWriteRegister(pDE, BASE_ODD1, dFrame+pitch*nol);
Ave2kWriteRegister(pDE, BASE_EVEN1, dFrame+pitch*(nol+1));
Ave2kWriteRegister(pDE, PROT_ADDR1, dFrame-4);
Ave2kWriteRegister(pDE, PITCH1, -pitch*2);
}
else{
Ave2kWriteRegister(pDE, BASE_ODD1, dFrame+ pitch *nol);
Ave2kWriteRegister(pDE, BASE_EVEN1, dFrame+ pitch *nol);
Ave2kWriteRegister(pDE, PROT_ADDR1, dFrame-4);
Ave2kWriteRegister(pDE, PITCH1, -pitch);
nWidth-=2;
//reg_Page |= 0x08;//One-shot
}
Ave2kWriteRegister(pDE, BASE_PAGE1, reg_Page);
Ave2kWriteRegister(pDE, NUM_LINE_BYTE1, (nil << 16) + pDE->NIP);
Ave2kWriteRegister(pDE, MC2, (UPLD_DMA1<<16)|UPLD_DMA1);
Setup_HScale(pDE, pDE->NIP, nWidth, HXO);
Setup_VScale(pDE, pDE->NIL, nol, HYO);
if(nChannel==0)
Ave2kWriteRegister(pDE, HPS_CTRL, (HYO << 12)); // port_a & vert offs
else
Ave2kWriteRegister(pDE, HPS_CTRL, (1<<30)|(1<<28)|(HYO << 12)); // port_b & vert offs
//------ setup BCS ------
Ave2kWriteRegister(pDE, BCS_CTRL, 0x90430040); // brig cont xx sat
switch(depth)
{
case 4:
outformat=RGB32;
break;
case 3:
outformat=RGB24;
break;
case 2:
outformat=YUV422;
break;
case 1:
outformat=Y8;
break;
default:
outformat=RGB24;
break;
}
/*if(depth==4)
outformat = RGB32;
else
if(depth==2)
outformat = YUV422;
else
outformat = RGB24;*/
pDE->outformat= (pDE->outformat & 0xffff)|(((0x00|outformat) << 24)+0x10000);
Ave2kWriteRegister(pDE, CLIP_FORMAT_CTRL, pDE->outformat); // outformat w.o. clip,chroma
UploadVideo(pDE);
//Ave2kWriteRegister(pDE, MC1, 0x20000000); //Disable EPS1
Ave2kWriteRegister(pDE, RPS_TOV1, 0);
Ave2kWriteRegister(pDE, ISR, MASK_28);//clear RPS interrupt
pDE->RPS[1].PhysicalAddress=MmGetPhysicalAddress(&pDE->RPS[1].RPSBuffer[0]).u.LowPart;
Ave2kWriteRegister(pDE, RPS_ADDR1, pDE->RPS[1].PhysicalAddress);
//Fill the RPS sequence
rpsIndex=0;
{//start DMA1
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_WR_REG|(1<<8)|(MC1/4);
pDE->RPS[1].RPSBuffer[rpsIndex++] = (TR_E_1<<16)|TR_E_1;
}
//pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_STOP;
//pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_UPLOAD|0x0C;
if(nol>nil){
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_CLR_EVENT|RE_HPS_EAW;
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_PAUSE|RE_HPS_EAW;
}
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_CLR_EVENT|RE_HPS_EAW;
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_PAUSE|RE_HPS_EAW;
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_CLR_EVENT|RE_HPS_EAW;
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_PAUSE|RE_HPS_EAW;
//send interrupt
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_INTERRUPT|RE_HPS_EAW;
//stop DMA1
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_WR_REG|(1<<8)|(MC1/4);
pDE->RPS[1].RPSBuffer[rpsIndex++] = (TR_E_1<<16);
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_STOP;
KeClearEvent(&pDE->EventVDone);
pDE->IERValue |= MASK_28;
KeSynchronizeExecution(
pDE->pInterrupt,
Ave2kSetInterrupts,
pDE);
//Ave2kWriteRegister(pDE, PCI_BT_V1, 0x07070707); //video1 burst length
Ave2kWriteRegister(pDE, MC1, 0x20002000); //Enable EPS1
Elapse.QuadPart = -(10 * 1000 * 100);
if(KeWaitForSingleObject(&pDE->EventVDone, UserRequest, UserMode, FALSE, &Elapse)==STATUS_TIMEOUT){
KdPrint(("Timeout!\n"));
//disable DMA1
Ave2kWriteRegister(pDE, MC1,(TR_E_1<<16));
}
KeClearEvent(&pDE->EventVDone);
pDE->IERValue &= ~MASK_28;
KeSynchronizeExecution(
pDE->pInterrupt,
Ave2kSetInterrupts,
pDE);
//Ave2kWriteRegister(pDE, PCI_BT_V1, 0x07070707); //video1 burst length
#if(LOCALBUFFER)
memcpy(MmGetMdlVirtualAddress(pMdl), pDE->BitmapCommonBuffer.BaseAddress, pitch*(nol));
#endif
return 1;
}
//This function make SAA7146A ready for overlay function
ULONG ave2kInitOverlay(PDEVICE_EXTENSION pDE)
{
ULONG outformat;
ULONG bSwitch=0;
ULONG ClipDmaPhyAddr;
StopVideo(pDE);
Ave2kWriteRegister(pDE, RPS_TOV1, 0);
if(0 == pDE->OverlayWindow.OpenClose && 0 == pDE->OverlayWindow.OpenClose2){
//StopVideo(pDE);
return 1;
}
if(1 == pDE->OverlayWindow.OpenClose && 1 == pDE->OverlayWindow.OpenClose2)
bSwitch=1;
//Get current video type
pDE->NIP =702;//702->652
if(pDE->OverlayWindow.OpenClose){
if(pDE->VideoType[0]==VIDEOTYPE_UNKNOWN)
{
// pDE->VideoType[0] = GetVideoType(pDE, 0);
int nVT=GetVideoType(pDE,0);
if(nVT==VIDEOTYPE_NONE)
pDE->VideoType[0]=pDE->nPreVideoType[0];
else
pDE->VideoType[0] =nVT;
}
}
if(pDE->OverlayWindow.OpenClose2){
if(pDE->VideoType[1]==VIDEOTYPE_UNKNOWN)
{
// pDE->VideoType[1] = GetVideoType(pDE, 1);
int nVT=GetVideoType(pDE,1);
if(nVT==VIDEOTYPE_NONE)
pDE->VideoType[1]=pDE->nPreVideoType[1];
else
pDE->VideoType[1] =nVT;
}
}
if(pDE->VideoType[0] == VIDEOTYPE_NONE)
pDE->VideoType[0] = pDE->VideoType[1];
if(pDE->VideoType[1] == VIDEOTYPE_NONE)
pDE->VideoType[1] = pDE->VideoType[0];
if(pDE->VideoType[0] == VIDEOTYPE_NTSC)
pDE->NIL = 240;
else
pDE->NIL = 288;
if(pDE->VideoType[1] == VIDEOTYPE_NTSC)
pDE->NIL2 = 240;
else
pDE->NIL2 = 288;
//------ setup HPS ------
if(!bSwitch){
//StopVideo(pDE);
if(pDE->OverlayWindow.OpenClose){
if(pDE->OverlayWindow.Bottom - pDE->OverlayWindow.Top > 2*pDE->NIL)
pDE->OverlayWindow.Bottom=pDE->OverlayWindow.Top+2*pDE->NIL;
Shift(pDE, 0);
Setup_HScale(pDE, pDE->NIP, (pDE->OverlayWindow.Right - pDE->OverlayWindow.Left), HXO);
Setup_VScale(pDE, pDE->NIL, pDE->OverlayWindow.Bottom - pDE->OverlayWindow.Top, HYO);
Ave2kWriteRegister(pDE, HPS_CTRL, (HYO << 12)); // port_a & vert offs
ClipDmaPhyAddr=MmGetPhysicalAddress(&pDE->Clips[0].ClipDmaBuffer[0]).u.LowPart;
}
else{
if(pDE->OverlayWindow.Bottom2 - pDE->OverlayWindow.Top2 > 2*pDE->NIL2)
pDE->OverlayWindow.Bottom2=pDE->OverlayWindow.Top2+2*pDE->NIL2;
Shift(pDE, 1);
Setup_HScale(pDE, pDE->NIP, (pDE->OverlayWindow.Right2 - pDE->OverlayWindow.Left2), HXO);
Setup_VScale(pDE, pDE->NIL2, pDE->OverlayWindow.Bottom2 - pDE->OverlayWindow.Top2, HYO);
Ave2kWriteRegister(pDE, HPS_CTRL, (1<<30)|(1<<28)|(HYO << 12)); // port_a & vert offs
ClipDmaPhyAddr=MmGetPhysicalAddress(&pDE->Clips[1].ClipDmaBuffer[0]).u.LowPart;
}
Ave2kWriteRegister(pDE,BASE_ODD2, ClipDmaPhyAddr);
Ave2kWriteRegister(pDE,BASE_EVEN2, ClipDmaPhyAddr);
Ave2kWriteRegister(pDE,PROT_ADDR2, ClipDmaPhyAddr + 64*sizeof(ULONG));
Ave2kWriteRegister(pDE, MC2,(UPLD_DMA2<<16)|UPLD_DMA2);
}
else{
//Ave2kWriteRegister(pDE, NUM_LINE_BYTE1, (pDE->NIL << 16) + pDE->NIP);
if(pDE->OverlayWindow.Bottom - pDE->OverlayWindow.Top > pDE->NIL-4)
pDE->OverlayWindow.Bottom=pDE->OverlayWindow.Top+pDE->NIL-4;
if(pDE->OverlayWindow.Bottom2 - pDE->OverlayWindow.Top2 > pDE->NIL2-4)
pDE->OverlayWindow.Bottom2=pDE->OverlayWindow.Top2+pDE->NIL2-4;
}
//------ setup BCS ------
Ave2kWriteRegister(pDE, BCS_CTRL, 0x90430040); // brig cont xx sat
//--- outformat & clip --
if(pDE->DisplayParameter.BitCount&0x80000000){
outformat = YUV422;
/* if(pDE->DisplayParameter.BitCount==15)
outformat = YUV2;
else
outformat = YUV422;*/
}
else{
// 80 = 64K, 81= RGB24, 82 = True Color, 83=RGB1555
if(pDE->DisplayParameter.Depth == 2) //64k colors
{
if(pDE->DisplayParameter.BitCount == 15)
outformat = RGB1555;
else
outformat = RGB16;
}
else if(pDE->DisplayParameter.Depth == 3)//24 bits colors
outformat = RGB24;
else if(pDE->DisplayParameter.Depth == 4)//32 bits colors
outformat = RGB32;
else if(pDE->DisplayParameter.Depth == 1)//8 bits colors
outformat = RGB8;
}
pDE->outformat= (pDE->outformat & 0xffff)|(((0x00|outformat) << 24)+0x10000);
Ave2kWriteRegister(pDE, CLIP_FORMAT_CTRL, pDE->outformat); // outformat w.o. clip,chroma
Ave2kWriteRegister(pDE,PITCH2,0x00000000);
Ave2kWriteRegister(pDE,BASE_PAGE2,0x00000004);
Ave2kWriteRegister(pDE,NUM_LINE_BYTE2,0x4040);
#if 0
pDE->outformat= (pDE->outformat & 0xffff0000)|0x200;
Ave2kWriteRegister(pDE, CLIP_FORMAT_CTRL, pDE->outformat); // outformat w.o. clip,chroma
//CHROMA KEY: BLUE
Ave2kWriteRegister(pDE, CHROMA_KEY_RANGE, 0xe8f84858);
//UL UU VL VU 0xe8f84a54=BLUE
#endif
UploadVideo(pDE);
Ave2kWriteRegister(pDE, MC1, ((TR_E_2<<16)|TR_E_2));
//DisableAllClip(pDE);
if(!bSwitch){
if(pDE->FrameRate==FRMRATE_FULL)
StartVideo(pDE);
else
SetFrameRate(pDE);
}
else{
//if(pDE->Compress)
SetDual(pDE);
//else
// SetFullDual(pDE);
}
return 1;
}
static void SetFrameRate(PDEVICE_EXTENSION pDE)
{
int rpsIndex,i;
int RpsTov;
int TovValues[]={9,4,3,2,1};
int TovValue=TovValues[pDE->FrameRate-1];
int Pause=1;
//if(TovValue==1){
// TovValue=2;
// Pause=2;
//}
StartVideo(pDE);
if(pDE->OverlayWindow.OpenClose){
RpsTov=(2<<30)|(1<<29);
}
else{
RpsTov=(2<<30)|(0<<29);
}
Ave2kWriteRegister(pDE, MC1, 0x20000000); //Disable EPS1
pDE->RPS[1].PhysicalAddress=MmGetPhysicalAddress(&pDE->RPS[1].RPSBuffer[0]).u.LowPart;
Ave2kWriteRegister(pDE, RPS_ADDR1, pDE->RPS[1].PhysicalAddress);
//Fill the RPS sequence
rpsIndex=0;
{//start DMA1
pDE->RPS[1].RPSBuffer[rpsIndex++]=CMD_WR_REG|(1<<8)|(MC1/4);
pDE->RPS[1].RPSBuffer[rpsIndex++] = (TR_E_1<<16)|TR_E_1;
}
for(i=0; i<TovValue; i++){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -