⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cx5530audio.cpp

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		m_bExiting = true;	// tell interrupt thread to get out of Dodge before sunset...
		SetEvent(m_hInterruptEvent);
		WaitForSingleObject(m_hInterruptThread, 1000);	// wait for sunset... 
		m_hInterruptThread = NULL;
		m_bExiting = false;	
	}
	
	if (m_hInterruptEvent)
	{
		CloseHandle(m_hInterruptEvent);
		m_hInterruptEvent = NULL;
	}
	
	if (m_pCodec)
	{
		delete m_pCodec;
		m_pCodec = NULL;
	}
}

bool CCX5530Audio::IsFormatSupported(LPWAVEFORMATEX lpWaveFormat)
{
	if (!lpWaveFormat)
		return false;
	if (lpWaveFormat->nChannels != 2)
		return false;
	if (lpWaveFormat->wBitsPerSample != 16)
		return false;
	return true;
}


#ifdef MYDEBUG
void CCX5530Audio::Test(bool bDoInt)
{
	FUNCMSG("+CCX5530Audio::Test()");
	
	// fill in the buffers with about 500 Hz sound at 44100 samples/s
	int i;
	static CMemoryBuffer buf;
	if (!buf.ReservePhysicalMem(8192))
	{
		ERRMSG("Can't reserve buf!");
		return;
	}
	WORD *pBuf = (WORD *)buf.GetVirtualAddress();
	WORD *pMax = (WORD*)(((BYTE*)pBuf) + buf.GetSize());
	
	for (i = 0; pBuf < pMax; i++)
	{
		*pBuf++ = ( i < 40)?-200:200;		// left channel 
		*pBuf++ = ( i < 40)?-200:200;		// right channel 
		if (i > 80)
			i = 0;
	}
	
	//--- Reload the descriptors....
	// set no EOPs: just let the thing loop
	
	// Descriptor: Logical address (DMA input buffer - unused).
	PSGD_FORMAT pSGD = (PSGD_FORMAT)( m_PlaybackChannels[0]->GetVirtualAddress());
	int iChunk1 = 4096;
	int iChunk2 = buf.GetSize() - iChunk1;
	
	pSGD[0].PhysicalAddr  = buf.GetPhysicalAddress();
	pSGD[0].CountAndFlag  = iChunk1;      // len (bytes)
	
	pSGD[1].PhysicalAddr  = pSGD[0].PhysicalAddr + iChunk1;
	pSGD[1].CountAndFlag  = iChunk2;      // len (bytes)
	
	pSGD[2].PhysicalAddr = m_PlaybackChannels[0]->GetPhysicalAddress();
	pSGD[2].CountAndFlag  = SGD_JMP;   //  JMP 
	
	if (bDoInt)
	{
		pSGD[0].CountAndFlag |= SGD_EOP;
		pSGD[1].CountAndFlag |= SGD_EOP;
	}
	
	UCHAR status;
	m_pCodec->SetSampleRate(false, 44100);
	
	INFMSG("Test: SGD table is:");
	PSGD_FORMAT pSGD1 = pSGD;
	while(true)
	{
		INFMSG3("\tAddr: 0x%8.8x, size %d, %s", 
			pSGD1->PhysicalAddr, 
			pSGD1->CountAndFlag & ~(SGD_EOP | SGD_EOT |SGD_JMP),
			(pSGD1->CountAndFlag & SGD_EOP)?TEXT("SGD_EOP"):
		(pSGD1->CountAndFlag & SGD_JMP)?TEXT("SGD_JMP"):
		(pSGD1->CountAndFlag & SGD_EOT)?TEXT("SGD_EOT"):TEXT("no flag"));
		
		if (pSGD1->CountAndFlag & (SGD_EOT | SGD_JMP))
			break;
		pSGD1++;
	}
	
	status = m_pAudioRegisters->regBusMaster0Status;	// clear EOP
	m_pAudioRegisters->regBusMaster0PRD = m_PlaybackChannels[0]->GetSGDTable()->GetPhysicalAddress();
	m_pAudioRegisters->regBusMaster0Command.byValue = 0x01;
	
	DEBUGMSG(1, (TEXT("DMA started, sleep\r\n")));
	
	for (i = 0; i < 20; i ++)
	{
		Sleep (100);
		GetDMAPosition(0);
	}
	
	pSGD[1].CountAndFlag  = (pSGD[1].CountAndFlag & ~SGD_EOP)| SGD_EOT;
	Sleep(1000);
	
	FUNCMSG("-CCX5530Audio::Test()");
	return;
}
#endif

bool CCX5530Audio::GetRegistryConfig()
{
    HKEY  hKeyActive = HKEY(INVALID_HANDLE_VALUE);
    DWORD dwSize;
    DWORD dwType;
    DWORD dwRet;
	
    //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //
    //  The HLM\Drivers\Active\?? key was passed in from DEVICE.EXE. The "Key"
    //  subkey points to the original registry location where we can find our
    //  extra data about this device.
    //
    dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_PATH, 0, 0, &hKeyActive);
    if (dwRet != ERROR_SUCCESS) 
	{
        ERRMSG2("GetRegistryConfig RegOpenKeyEx(%s) failed %d",REGISTRY_PATH, dwRet);
        return false;
    }
	
	dwSize = sizeof(m_dwInterrupt);
    dwRet = RegQueryValueEx(hKeyActive, REGISTRY_KEY_IRQ, 0, &dwType, (BYTE*)&m_dwInterrupt, &dwSize);
	RegCloseKey(hKeyActive);
    if (dwRet != ERROR_SUCCESS) 
	{
        ERRMSG1("GetRegistryConfig RegQueryValueEx(Key) failed: %d", dwRet);
    }
	
    return dwRet == ERROR_SUCCESS;
}



void CCX5530Audio::InitVSA()
{
	// VSA initialization
	// VSA 2 first
	BYTE byInt = BYTE(m_dwInterrupt);
	
	_outpw( 0xAC1C, 0xFC53 ); //unlock virtual registers
	_outpw( 0xAC1C, 0x108 );  //ID the audio config virtual regs
	_outpw( 0xAC1E, WORD(m_dwInterrupt));  //set the value
	
	
	// VSA1 Irq config method : not thread safe ! Replaced with call to HalSetBusDataByOffset below
	_asm 
	{
		mov		bl, byInt		; because byInt is loaded based on bp, and we clear bp below
		push	bp
		mov     bp, 0h      
		mov     dx, 0CF8h		; PCI cmd register
		mov     eax,800090D0h	; device and other pci stuff
		out     dx, eax
		mov     dx, 0CFCh		; PCI data register
		xor		ax, ax
		mov		al, bl			; target IRQ
		shl		eax,16			; store in upper part of reg for VSA
		mov     ax, 0A00Ah		; load VSA1 cmd
		out     dx, ax
		pop		bp
	}
	
/*
	// and now VSA 1 (multithread safe)
	bridgeSlot.u.bits.FunctionNumber = 0;
	DWORD dwBuffer = (m_dwInterrupt<<16) | 0xA00A;
	HalSetBusDataByOffset(
		PCIConfiguration, 
		bus, 
		bridgeSlot.u.AsULONG, 
		&dwBuffer,
		0xD0,
		sizeof(dwBuffer));
*/	
}

HRESULT CCX5530Audio::CreatePlaybackBuffer(ULONG *pulSize, DsPlaybackDriverBuffer** pBuffer)
{
	FUNCMSG1("CCX5530Audio::CreatePlaybackBuffer, size %d", *pulSize);
	HRESULT hr = DSERR_GENERIC;
	if (!pBuffer)
		return hr;
	
	// any hardware DMA channels free?
	
	for (UINT i = 0; i < MAX_PLAYBACK_CHANNELS; i++)
	{
		if (m_PlaybackChannels[i] == NULL)
			break;
	}
	if (i >= MAX_PLAYBACK_CHANNELS)
	{
		WARNMSG("No more free busmasters");
		return DSERR_ALLOCATED;
	}
	
	// map the channel to a DMA busmaster
	// with the current hardware it's simple: there is a single playback channel, and we use busmaster 0

	volatile BusMasterRegisters* pRegs;

	switch (i)
	{
	case 0:
		pRegs = &m_pAudioRegisters->busMasters[0];
		break;
	default:
		ASSERT(FALSE);
		return DSERR_GENERIC;
	}
	m_PlaybackChannels[i] = new DsPlaybackDriverBuffer(hr, i, pRegs );
	
	if( !m_PlaybackChannels[i] || FAILED(hr) )
	{
		ERRMSG("CCX5530Audio::CreatePlaybackBuffer -- unable to create buffer object");
		
		if( m_PlaybackChannels[i] )
		{
			delete m_PlaybackChannels[i];
			m_PlaybackChannels[i] = NULL;
		}
		
		if( SUCCEEDED(hr))
		{
			// Change the error code to reflect the failure.
			hr = DSERR_OUTOFMEMORY;
		}
		return hr;
	}
	// Allocate buffer
	if( ! m_PlaybackChannels[i]->ReservePhysicalMem(*pulSize) )
	{
		ERRMSG("CCX5530Audio::CreatePlaybackBuffer -- unable to allocate memory for buffers ");
		delete m_PlaybackChannels[i];
		m_PlaybackChannels[i] = NULL;
		*pulSize = 0;
		return DSERR_OUTOFMEMORY;
	}
	*pBuffer = m_PlaybackChannels[i];
	return hr;
}


HRESULT CCX5530Audio::CreateCaptureBuffer(ULONG *pulSize, DsCaptureDriverBuffer** pBuffer)
{
	HRESULT hr = DSERR_GENERIC;
	if (!pBuffer)
		return hr;
	
	// any hardware DMA channels free?
	
	for (UINT i = 0; i < MAX_CAPTURE_CHANNELS; i++)
	{
		if (m_CaptureChannels[i] == NULL)
			break;
	}
	if (i >= MAX_CAPTURE_CHANNELS)
	{
		WARNMSG("No free capture busmasters");
		return DSERR_ALLOCATED;
	}

	// map the capture channel to a DMA busmaster
	// with the current hardware it's simple: there is a single record channel, and we use busmaster 1

	volatile BusMasterRegisters* pRegs;

	switch (i)
	{
	case 0:
		pRegs = &m_pAudioRegisters->busMasters[1];
		break;
	default:
		ASSERT(FALSE);
		return DSERR_GENERIC;
	}
	
	m_CaptureChannels[i] = new DsCaptureDriverBuffer(hr, i, pRegs);
	
	if( !m_CaptureChannels[i] || FAILED(hr) )
	{
		ERRMSG("CCX5530Audio::CreateCaptureBuffer -- unable to create secondary buffer object");
		
		if( m_CaptureChannels[i] )
		{
			delete m_CaptureChannels[i];
			m_CaptureChannels[i] = NULL;
		}
		
		if( SUCCEEDED(hr))
		{
			// Change the error code to reflect the failure.
			hr = DSERR_OUTOFMEMORY;
		}
		return hr;
	}
	// Allocate buffer
	if( ! m_CaptureChannels[i]->ReservePhysicalMem(*pulSize) )
	{
		ERRMSG("CCX5530Audio::CreateCaptureBuffer -- unable to allocate memory for buffers ");
		delete m_CaptureChannels[i];
		m_CaptureChannels[i] = NULL;
		*pulSize = 0;
		return DSERR_OUTOFMEMORY;
	}
	*pBuffer = m_CaptureChannels[i];
	return hr;
}

HRESULT CCX5530Audio::SetFrequency(bool bCapture, DWORD dwFrequency)
{
	if (!m_pCodec)
		return DSERR_CONTROLUNAVAIL;
	if (!m_pCodec->SetSampleRate(bCapture, dwFrequency))
		return DSERR_CONTROLUNAVAIL;
	return DS_OK;
}

#ifdef DEBUG
void CCX5530Audio::DumpRegisters()
{
	RETMSG1("regCodecGPIOStatus is 0x%8.8x", m_pAudioRegisters->regCodecGPIOStatus.dwValue);
	// offset 0x04;
	RETMSG1("regCodecGPIOControl is 0x%8.8x", m_pAudioRegisters->regCodecGPIOControl.dwValue);
	// offset 0x08;
	RETMSG1("regCodecStatus is 0x%8.8x", m_pAudioRegisters->regCodecStatus.dwValue);
	// offset 0x0C
	RETMSG1("regCodecCommand is 0x%8.8x", m_pAudioRegisters->regCodecCommand.dwValue);
	//offset 0x10 This is a WORD register
	RETMSG1("regSMIMirror is 0x%4.4x", m_pAudioRegisters->regSMIMirror);
	//offset 0x12 This is a WORD register
	RETMSG1("regSMI is 0x%4.4x", m_pAudioRegisters->regSMI);
	// offset 0x14
	RETMSG1("regIOTrap is 0x%8.8x", m_pAudioRegisters->regIOTrap);
	// offset 0x18	Word register
	RETMSG1("regIOTrapEnable is 0x%4.4x", m_pAudioRegisters->regIOTrapEnable);
	// offset 0x1A	Word register
	RETMSG1("regIRQEnable is 0x%4.4x", m_pAudioRegisters->regIRQEnable);
	// offset 0x1C	Word register
	RETMSG1("regIRQControl is 0x%4.4x", m_pAudioRegisters->regIRQControl);
	// offset 0x1E	Word register
	RETMSG1("regIRQMask is 0x%4.4x", m_pAudioRegisters->regIRQMask);
	// offset 0x20 BYTE register
	RETMSG1("busMasters is 0x%2.2x", m_pAudioRegisters->busMasters[0].regBusMasterStatus);
	RETMSG1("busMasters is 0x%2.2x", m_pAudioRegisters->busMasters[1].regBusMasterStatus);
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -