#include "CEchoGals.h"
#ifdef DSP_56361
#include "LoaderDSP.c"
#endif
#define COMM_PAGE_PHYS_BYTES ((sizeof(DspCommPage)+PAGE_SIZE-1)/PAGE_SIZE)*PAGE_SIZE
Construction and destruction
****************************************************************************/
PVOID CDspCommObject::operator new( size_t Size )
{
PVOID pMemory;
ECHOSTATUS Status;
Status = OsAllocateNonPaged(Size,&pMemory);
if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
{
ECHO_DEBUGPRINTF(("CDspCommObject::operator new - memory allocation failed\n"));
pMemory = NULL;
}
else
{
memset( pMemory, 0, Size );
}
return pMemory;
}
VOID CDspCommObject::operator delete( PVOID pVoid )
{
if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
{
ECHO_DEBUGPRINTF( ("CDspCommObject::operator delete memory free "
"failed\n") );
}
}
CDspCommObject::CDspCommObject
(
PDWORD pdwDspRegBase,
PCOsSupport pOsSupport
)
{
INT32 i;
ECHO_ASSERT(pOsSupport );
strcpy( m_szCardName, "??????" );
m_pOsSupport = pOsSupport;
m_pdwDspRegBase = pdwDspRegBase;
m_bBadBoard = TRUE;
m_pwDspCode = NULL;
m_byDigitalMode = DIGITAL_MODE_NONE;
m_wInputClock = ECHO_CLOCK_INTERNAL;
m_wOutputClock = ECHO_CLOCK_WORD;
m_ullLastLoadAttemptTime = (ULONGLONG)(DWORD)(0L - DSP_LOAD_ATTEMPT_PERIOD);
#ifdef MIDI_SUPPORT
m_ullNextMidiWriteTime = 0;
#endif
ECHOSTATUS Status;
DWORD dwSegmentSize;
PHYS_ADDR PhysAddr;
Status = pOsSupport->AllocPhysPageBlock( COMM_PAGE_PHYS_BYTES,
m_pDspCommPageBlock);
if (ECHOSTATUS_OK != Status)
{
ECHO_DEBUGPRINTF( ("CDspCommObject::CDspCommObject DSP comm page "
"memory allocation failed\n") );
return;
}
m_pDspCommPage = (PDspCommPage) pOsSupport->
GetPageBlockVirtAddress( m_pDspCommPageBlock );
pOsSupport->GetPageBlockPhysSegment(m_pDspCommPageBlock,
0,
PhysAddr,
dwSegmentSize);
m_dwCommPagePhys = PhysAddr;
m_pDspCommPage->dwCommSize = SWAP( sizeof( DspCommPage ) );
m_pDspCommPage->dwHandshake = 0xffffffff;
m_pDspCommPage->dwMidiOutFreeCount = SWAP( (DWORD) DSP_MIDI_OUT_FIFO_SIZE );
for ( i = 0; i < DSP_MAXAUDIOINPUTS; i++ )
m_pDspCommPage->InLineLevel[ i ] = 0x00;
memset( m_pDspCommPage->byMonitors,
GENERIC_TO_DSP(ECHOGAIN_MUTED),
MONITOR_ARRAY_SIZE );
memset( m_pDspCommPage->byVmixerLevel,
GENERIC_TO_DSP(ECHOGAIN_MUTED),
VMIXER_ARRAY_SIZE );
#ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT
m_fDigitalInAutoMute = TRUE;
#endif
}
CDspCommObject::~CDspCommObject()
{
GoComatose();
if ( NULL != m_pDspCommPageBlock )
{
m_pOsSupport->FreePhysPageBlock( COMM_PAGE_PHYS_BYTES,
m_pDspCommPageBlock);
}
ECHO_DEBUGPRINTF( ( "CDspCommObject::~CDspCommObject() is toast!\n" ) );
}
Firmware loading functions
****************************************************************************/
BOOL CDspCommObject::CheckAsicStatus()
{
DWORD dwAsicStatus;
DWORD dwReturn;
if ( !m_bHasASIC )
{
m_bASICLoaded = TRUE;
return TRUE;
}
m_bASICLoaded = FALSE;
SendVector( DSP_VC_TEST_ASIC );
dwReturn = Read_DSP( &dwAsicStatus );
if ( ECHOSTATUS_OK != dwReturn )
{
ECHO_DEBUGPRINTF(("CDspCommObject::CheckAsicStatus - failed on Read_DSP\n"));
ECHO_DEBUGBREAK();
return FALSE;
}
#ifdef ECHO_DEBUG
if ( (dwAsicStatus != ASIC_LOADED) && (dwAsicStatus != ASIC_NOT_LOADED) )
{
ECHO_DEBUGBREAK();
}
#endif
if ( dwAsicStatus == ASIC_LOADED )
m_bASICLoaded = TRUE;
return m_bASICLoaded;
}
BOOL CDspCommObject::LoadASIC
(
DWORD dwCmd,
PBYTE pCode,
DWORD dwSize
)
{
DWORD i;
#ifdef _WIN32
DWORD dwChecksum = 0;
#endif
ECHO_DEBUGPRINTF(("CDspCommObject::LoadASIC\n"));
if ( !m_bHasASIC )
return TRUE;
#ifdef _DEBUG
ULONGLONG ullStartTime, ullCurTime;
m_pOsSupport->OsGetSystemTime( &ullStartTime );
#endif
if ( ECHOSTATUS_OK != Write_DSP( dwCmd ) )
return FALSE;
if ( ECHOSTATUS_OK != Write_DSP( dwSize ) )
return FALSE;
for ( i = 0; i < dwSize; i++ )
{
#ifdef _WIN32
dwChecksum += pCode[i];
#endif
if ( ECHOSTATUS_OK != Write_DSP( pCode[ i ] ) )
{
ECHO_DEBUGPRINTF(("\tfailed on Write_DSP\n"));
return FALSE;
}
}
#ifdef _DEBUG
m_pOsSupport->OsGetSystemTime( &ullCurTime );
ECHO_DEBUGPRINTF( ("CDspCommObject::LoadASIC took %ld usec.\n",
(ULONG) ( ullCurTime - ullStartTime ) ) );
ECHO_DEBUGPRINTF(("ASIC load OK\n"));
#endif
#if defined(_WIN32) && (DBG)
DbgPrint("--- ASIC checksum is 0x%lx\n",dwChecksum);
#endif
return TRUE;
}
#ifdef DSP_56361
ECHOSTATUS CDspCommObject::InstallResidentLoader()
{
DWORD dwAddress;
DWORD dwIndex;
INT32 iNum;
INT32 i;
DWORD dwReturn;
PWORD pCode;
ECHO_DEBUGPRINTF( ("CDspCommObject::InstallResidentLoader\n") );
if (DEVICE_ID_56361 != m_pOsSupport->GetDeviceId() )
return ECHOSTATUS_OK;
DWORD dwStatus;
dwStatus = GetDspRegister( CHI32_STATUS_REG );
if ( 0 != (dwStatus & CHI32_STATUS_REG_HF5 ) )
{
ECHO_DEBUGPRINTF(("\tResident loader already installed; status is 0x%lx\n",
dwStatus));
return ECHOSTATUS_OK;
}
SetDspRegister( CHI32_CONTROL_REG,
GetDspRegister( CHI32_CONTROL_REG ) | 0x900 );
pCode = pwLoaderDSP;
dwIndex = pCode[ 0 ];
dwIndex += 3;
iNum = pCode[ dwIndex++ ];
dwAddress = ( pCode[ dwIndex ] << 16 ) + pCode[ dwIndex + 1 ];
dwIndex += 2;
dwReturn = Write_DSP( (DWORD) iNum );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF( ("CDspCommObject::InstallResidentLoader: Failed to "
"write word count!\n") );
return ECHOSTATUS_DSP_DEAD;
}
dwReturn = Write_DSP( dwAddress );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF( ("CDspCommObject::InstallResidentLoader: Failed to "
"write DSP address!\n") );
return ECHOSTATUS_DSP_DEAD;
}
for ( i = 0; i < iNum; i++)
{
DWORD dwData;
dwData = ( pCode[ dwIndex ] << 16 ) + pCode[ dwIndex + 1 ];
dwReturn = Write_DSP( dwData );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF( ("CDspCommObject::InstallResidentLoader: Failed to "
"write DSP code\n") );
return ECHOSTATUS_DSP_DEAD;
}
dwIndex+=2;
}
BOOL fSuccess;
ULONGLONG ullCurTime,ullTimeout;
m_pOsSupport->OsGetSystemTime( &ullCurTime );
ullTimeout = ullCurTime + 10000L;
fSuccess = FALSE;
do
{
m_pOsSupport->OsSnooze(50);
dwStatus = GetDspRegister( CHI32_STATUS_REG );
if (0 != (dwStatus & CHI32_STATUS_REG_HF5))
{
fSuccess = TRUE;
break;
}
m_pOsSupport->OsGetSystemTime( &ullCurTime );
} while (ullCurTime < ullTimeout);
if (FALSE == fSuccess)
{
ECHO_DEBUGPRINTF(("\tResident loader failed to set HF5\n"));
return ECHOSTATUS_DSP_DEAD;
}
ECHO_DEBUGPRINTF(("\tResident loader successfully installed\n"));
return ECHOSTATUS_OK;
}
#endif
ECHOSTATUS CDspCommObject::LoadDSP
(
PWORD pCode
)
{
DWORD dwAddress;
DWORD dwIndex;
INT32 iNum;
INT32 i;
DWORD dwReturn;
ULONGLONG ullTimeout, ullCurTime;
ECHOSTATUS Status;
ECHO_DEBUGPRINTF(("CDspCommObject::LoadDSP\n"));
if ( m_pwDspCode == pCode )
{
ECHO_DEBUGPRINTF( ("\tDSP is already loaded!\n") );
return ECHOSTATUS_FIRMWARE_LOADED;
}
m_bBadBoard = TRUE;
m_pwDspCode = NULL;
m_bASICLoaded = FALSE;
ECHO_DEBUGPRINTF(("CDspCommObject::LoadDSP Set m_bBadBoard to TRUE\n"));
#ifdef DSP_56361
InstallResidentLoader();
#endif
if ( ECHOSTATUS_OK != SendVector( DSP_VC_RESET ) )
{
m_pOsSupport->EchoErrorMsg(
"CDspCommObject::LoadDsp SendVector DSP_VC_RESET failed",
"Critical Failure" );
return ECHOSTATUS_DSP_DEAD;
}
m_pOsSupport->OsSnooze( 10L );
m_pOsSupport->OsGetSystemTime( &ullCurTime );
ullTimeout = ullCurTime + 10000L;
wait_for_hf3:
if ( GetDspRegister( CHI32_STATUS_REG ) & CHI32_STATUS_REG_HF3 )
goto set_dsp_format_bits;
m_pOsSupport->OsGetSystemTime( &ullCurTime );
if ( ullCurTime > ullTimeout)
{
ECHO_DEBUGPRINTF( ("CDspCommObject::LoadDSP Timeout waiting for "
"CHI32_STATUS_REG_HF3\n") );
m_pOsSupport->EchoErrorMsg(
"CDspCommObject::LoadDSP SendVector DSP_VC_RESET failed",
"Critical Failure" );
return ECHOSTATUS_DSP_TIMEOUT;
}
goto wait_for_hf3;
set_dsp_format_bits:
SetDspRegister( CHI32_CONTROL_REG,
GetDspRegister( CHI32_CONTROL_REG ) | (DWORD) 0x900 );
dwIndex = pCode[ 0 ];
for (;;)
{
INT32 iBlockType;
INT32 iMemType;
dwIndex++;
iBlockType = pCode[ dwIndex ];
if ( iBlockType == 4 )
break;
dwIndex++;
iMemType = pCode[ dwIndex ];
dwIndex++;
iNum = pCode[ dwIndex ];
dwIndex++;
if ( iNum == 0 )
break;
dwAddress = ( (DWORD) pCode[ dwIndex ] << 16 ) + pCode[ dwIndex + 1 ];
dwIndex += 2;
dwReturn = Write_DSP( (DWORD)iNum );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF(("LoadDSP - failed to write number of DSP words\n"));
return ECHOSTATUS_DSP_DEAD;
}
dwReturn = Write_DSP( dwAddress );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF(("LoadDSP - failed to write DSP address\n"));
return ECHOSTATUS_DSP_DEAD;
}
dwReturn = Write_DSP( (DWORD)iMemType );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF(("LoadDSP - failed to write DSP memory type\n"));
return ECHOSTATUS_DSP_DEAD;
}
for ( i = 0; i < iNum; i++ )
{
DWORD dwData;
dwData = ( (DWORD) pCode[ dwIndex ] << 16 ) + pCode[ dwIndex + 1 ];
dwReturn = Write_DSP( dwData );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF(("LoadDSP - failed to write DSP data\n"));
return ECHOSTATUS_DSP_DEAD;
}
dwIndex += 2;
}
}
dwReturn = Write_DSP( 0 );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF(("LoadDSP: Failed to write final zero\n"));
return ECHOSTATUS_DSP_DEAD;
}
m_pOsSupport->OsSnooze( 10L );
m_pOsSupport->OsGetSystemTime( &ullCurTime );
ullTimeout = ullCurTime + 500000L;
while ( ullCurTime <= ullTimeout)
{
if ( GetDspRegister( CHI32_STATUS_REG ) & CHI32_STATUS_REG_HF4 )
{
SetDspRegister( CHI32_CONTROL_REG,
GetDspRegister( CHI32_CONTROL_REG ) & ~0x1b00 );
dwReturn = Write_DSP( DSP_FNC_SET_COMMPAGE_ADDR );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF(("LoadDSP - Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n"));
return ECHOSTATUS_DSP_DEAD;
}
dwReturn = Write_DSP( m_dwCommPagePhys );
if ( dwReturn != 0 )
{
ECHO_DEBUGPRINTF(("LoadDSP - Failed to write comm page address\n"));
return ECHOSTATUS_DSP_DEAD;
}
Status = ReadSn();
if ( ECHOSTATUS_OK != Status )
{
ECHO_DEBUGPRINTF(("LoadDSP - Failed to read serial number\n"));
return Status;
}
m_pwDspCode = pCode;
m_bBadBoard = FALSE;
ECHO_DEBUGPRINTF(("CDspCommObject::LoadDSP Set m_bBadBoard to FALSE\n"));
return ECHOSTATUS_OK;
}
m_pOsSupport->OsGetSystemTime( &ullCurTime );
}
ECHO_DEBUGPRINTF( ("LoadDSP: DSP load timed out waiting for HF4\n") );
return ECHOSTATUS_DSP_TIMEOUT;
}
ECHOSTATUS CDspCommObject::LoadFirmware()
{
ECHOSTATUS dwReturn;
ULONGLONG ullRightNow;
if ( NULL == m_pwDspCodeToLoad || NULL == m_pDspCommPage )
{
ECHO_DEBUGBREAK();
return ECHOSTATUS_NO_MEM;
}
m_pOsSupport->OsGetSystemTime(&ullRightNow);
if ( (FALSE == m_bASICLoaded) &&
(DSP_LOAD_ATTEMPT_PERIOD > (ullRightNow - m_ullLastLoadAttemptTime)) )
return ECHOSTATUS_ASIC_NOT_LOADED;
m_ullLastLoadAttemptTime = ullRightNow;
if (NULL != m_pwDspCode)
{
dwReturn = CheckAsicStatus();
if (TRUE == dwReturn)
return ECHOSTATUS_OK;
m_pwDspCode = NULL;
}
dwReturn = LoadDSP( m_pwDspCodeToLoad );
if ( (ECHOSTATUS_OK != dwReturn) &&
(ECHOSTATUS_FIRMWARE_LOADED != dwReturn) )
{
return dwReturn;
}
ECHO_DEBUGPRINTF(("DSP load OK\n"));
dwReturn = LoadASIC();
if ( FALSE == dwReturn )
{
dwReturn = ECHOSTATUS_ASIC_NOT_LOADED;
}
else
{
RestoreDspSettings();
dwReturn = ECHOSTATUS_OK;
}
return dwReturn;
}
ECHOSTATUS CDspCommObject::ReadSn()
{
INT32 j;
DWORD dwSn[ 6 ];
ECHOSTATUS Status;
ECHO_DEBUGPRINTF( ("CDspCommObject::ReadSn\n") );
for ( j = 0; j < 5; j++ )
{
Status = Read_DSP( &dwSn[ j ] );
if ( Status != 0 )
{
ECHO_DEBUGPRINTF( ("\tFailed to read serial number word %ld\n",
j) );
return ECHOSTATUS_DSP_DEAD;
}
}
ECHO_DEBUGPRINTF( ("\tRead serial number %08lx %08lx %08lx %08lx %08lx\n",
dwSn[0], dwSn[1], dwSn[2], dwSn[3], dwSn[4]) );
return ECHOSTATUS_OK;
}
void CDspCommObject::RestoreDspSettings()
{
ECHO_DEBUGPRINTF(("RestoreDspSettings\n"));
ECHO_DEBUGPRINTF(("\tControl reg is 0x%lx\n",SWAP(m_pDspCommPage->dwControlReg) ));
if ( !CheckAsicStatus() )
return;
m_pDspCommPage->dwHandshake = 0xffffffff;
#ifdef MIDI_SUPPORT
m_ullNextMidiWriteTime = 0;
#endif
SetSampleRate();
if ( 0 != m_wMeterOnCount )
{
SendVector( DSP_VC_METERS_ON );
}
SetInputClock( m_wInputClock );
SetOutputClock( m_wOutputClock );
if ( !WaitForHandshake() )
{
return;
}
UpdateAudioOutLineLevel();
if ( !WaitForHandshake() )
return;
UpdateAudioInLineLevel();
if ( HasVmixer() )
{
if ( !WaitForHandshake() )
return;
UpdateVmixerLevel();
}
if ( !WaitForHandshake() )
return;
ClearHandshake();
SendVector( DSP_VC_UPDATE_FLAGS );
ECHO_DEBUGPRINTF(("RestoreDspSettings done\n"));
}
DSP utilities
****************************************************************************/
ECHOSTATUS CDspCommObject::Write_DSP
(
DWORD dwData
)
{
DWORD dwStatus;
ULONGLONG ullCurTime, ullTimeout;
m_pOsSupport->OsGetSystemTime( &ullCurTime );
ullTimeout = ullCurTime + 10000000L;
while ( ullTimeout >= ullCurTime )
{
dwStatus = GetDspRegister( CHI32_STATUS_REG );
if ( ( dwStatus & CHI32_STATUS_HOST_WRITE_EMPTY ) != 0 )
{
SetDspRegister( CHI32_DATA_REG, dwData );
return ECHOSTATUS_OK;
}
m_pOsSupport->OsGetSystemTime( &ullCurTime );
}
m_bBadBoard = TRUE;
ECHO_DEBUGPRINTF(("CDspCommObject::Write_DSP Set m_bBadBoard to TRUE\n"));
return ECHOSTATUS_DSP_TIMEOUT;
}
ECHOSTATUS CDspCommObject::Read_DSP
(
DWORD *pdwData
)
{
DWORD dwStatus;
ULONGLONG ullCurTime, ullTimeout;
m_pOsSupport->OsGetSystemTime( &ullCurTime );
ullTimeout = ullCurTime + READ_DSP_TIMEOUT;
while ( ullTimeout >= ullCurTime )
{
dwStatus = GetDspRegister( CHI32_STATUS_REG );
if ( ( dwStatus & CHI32_STATUS_HOST_READ_FULL ) != 0 )
{
*pdwData = GetDspRegister( CHI32_DATA_REG );
return ECHOSTATUS_OK;
}
m_pOsSupport->OsGetSystemTime( &ullCurTime );
}
m_bBadBoard = TRUE;
ECHO_DEBUGPRINTF(("CDspCommObject::Read_DSP Set m_bBadBoard to TRUE\n"));
return ECHOSTATUS_DSP_TIMEOUT;
}
ECHOSTATUS CDspCommObject::SendVector
(
DWORD dwCommand
)
{
ULONGLONG ullTimeout;
ULONGLONG ullCurTime;
#if 0
char * pszCmd;
switch ( dwCommand )
{
case DSP_VC_ACK_INT :
pszCmd = "DSP_VC_ACK_INT";
break;
case DSP_VC_SET_VMIXER_GAIN :
pszCmd = "DSP_VC_SET_VMIXER_GAIN";
break;
case DSP_VC_START_TRANSFER :
pszCmd = "DSP_VC_START_TRANSFER";
break;
case DSP_VC_METERS_ON :
pszCmd = "DSP_VC_METERS_ON";
break;
case DSP_VC_METERS_OFF :
pszCmd = "DSP_VC_METERS_OFF";
break;
case DSP_VC_UPDATE_OUTVOL :
pszCmd = "DSP_VC_UPDATE_OUTVOL";
break;
case DSP_VC_UPDATE_INGAIN :
pszCmd = "DSP_VC_UPDATE_INGAIN";
break;
case DSP_VC_ADD_AUDIO_BUFFER :
pszCmd = "DSP_VC_ADD_AUDIO_BUFFER";
break;
case DSP_VC_TEST_ASIC :
pszCmd = "DSP_VC_TEST_ASIC";
break;
case DSP_VC_UPDATE_CLOCKS :
pszCmd = "DSP_VC_UPDATE_CLOCKS";
break;
case DSP_VC_SET_LAYLA_SAMPLE_RATE :
if ( GetCardType() == LAYLA )
pszCmd = "DSP_VC_SET_LAYLA_RATE";
else if ( GetCardType() == GINA || GetCardType() == DARLA )
pszCmd = "DSP_VC_SET_GD_AUDIO_STATE";
else
pszCmd = "DSP_VC_WRITE_CONTROL_REG";
break;
case DSP_VC_MIDI_WRITE :
pszCmd = "DSP_VC_MIDI_WRITE";
break;
case DSP_VC_STOP_TRANSFER :
pszCmd = "DSP_VC_STOP_TRANSFER";
break;
case DSP_VC_UPDATE_FLAGS :
pszCmd = "DSP_VC_UPDATE_FLAGS";
break;
case DSP_VC_RESET :
pszCmd = "DSP_VC_RESET";
break;
default :
pszCmd = "?????";
break;
}
ECHO_DEBUGPRINTF( ("SendVector: %s dwCommand %s (0x%x)\n",
GetCardName(),
pszCmd,
dwCommand) );
#endif
m_pOsSupport->OsGetSystemTime( &ullCurTime );
ullTimeout = ullCurTime + 100000L;
while ( ullCurTime <= ullTimeout)
{
DWORD dwReg;
dwReg = GetDspRegister( CHI32_VECTOR_REG );
if ( 0 == (dwReg & CHI32_VECTOR_BUSY) )
{
SetDspRegister( CHI32_VECTOR_REG, dwCommand );
return ECHOSTATUS_OK;
}
m_pOsSupport->OsGetSystemTime( &ullCurTime );
}
ECHO_DEBUGPRINTF( ("\tPunked out on SendVector\n") );
ECHO_DEBUGBREAK();
return ECHOSTATUS_DSP_TIMEOUT;
}
BOOL CDspCommObject::WaitForHandshake()
{
ULONGLONG ullDelta;
ULONGLONG ullStartTime,ullTime;
m_pOsSupport->OsGetSystemTime( &ullStartTime );
do
{
if ( 0 != GetHandshakeFlag() )
{
return TRUE;
}
m_pOsSupport->OsSnooze( 2 );
m_pOsSupport->OsGetSystemTime(&ullTime);
ullDelta = ullTime - ullStartTime;
} while (ullDelta < (ULONGLONG) HANDSHAKE_TIMEOUT);
ECHO_DEBUGPRINTF( ("CDspCommObject::WaitForHandshake: Timeout waiting "
"for DSP\n") );
ECHO_DEBUGBREAK();
return FALSE;
}
Transport methods
****************************************************************************/
ECHOSTATUS CDspCommObject::StartTransport
(
PCChannelMask pChannelMask
)
{
ECHO_DEBUGPRINTF( ("StartTransport\n") );
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
m_pDspCommPage->cmdStart.Clear();
m_pDspCommPage->cmdStart = *pChannelMask;
if ( !m_pDspCommPage->cmdStart.IsEmpty() )
{
ClearHandshake();
SendVector( DSP_VC_START_TRANSFER );
m_cmActive += *pChannelMask;
return ECHOSTATUS_OK;
}
ECHO_DEBUGPRINTF( ("CDspCommObject::StartTransport: No pipes to start!\n") );
return ECHOSTATUS_INVALID_CHANNEL;
}
ECHOSTATUS CDspCommObject::StopTransport
(
PCChannelMask pChannelMask
)
{
ECHO_DEBUGPRINTF(("StopTransport\n"));
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
m_pDspCommPage->cmdStop.Clear();
m_pDspCommPage->cmdStop = *pChannelMask;
m_pDspCommPage->cmdReset.Clear();
if ( !m_pDspCommPage->cmdStop.IsEmpty() )
{
ClearHandshake();
SendVector( DSP_VC_STOP_TRANSFER );
m_cmActive -= *pChannelMask;
return ECHOSTATUS_OK;
}
ECHO_DEBUGPRINTF( ("CDspCommObject::StopTransport: No pipes to stop!\n") );
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::ResetTransport
(
PCChannelMask pChannelMask
)
{
ECHO_DEBUGPRINTF(("ResetTransport\n"));
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
m_pDspCommPage->cmdStop.Clear();
m_pDspCommPage->cmdReset.Clear();
m_pDspCommPage->cmdStop = *pChannelMask;
m_pDspCommPage->cmdReset = *pChannelMask;
if ( !m_pDspCommPage->cmdReset.IsEmpty() )
{
ClearHandshake();
SendVector( DSP_VC_STOP_TRANSFER );
m_cmActive -= *pChannelMask;
return ECHOSTATUS_OK;
}
ECHO_DEBUGPRINTF( ("CDspCommObject::ResetTransport: No pipes to reset!\n") );
return ECHOSTATUS_OK;
}
void CDspCommObject::SetAudioDuckListPhys
(
WORD wPipeIndex,
DWORD dwNewPhysAdr
)
{
if (wPipeIndex < GetNumPipes() )
{
m_pDspCommPage->DuckListPhys[ wPipeIndex ].PhysAddr =
SWAP( dwNewPhysAdr );
}
}
void CDspCommObject::GetActivePipes
(
PCChannelMask pChannelMask
)
{
pChannelMask->Clear();
*pChannelMask += m_cmActive;
}
ECHOSTATUS CDspCommObject::SetAudioFormat
(
WORD wPipeIndex,
PECHOGALS_AUDIOFORMAT pFormat
)
{
WORD wDspFormat = DSP_AUDIOFORM_SS_16LE;
ECHO_DEBUGPRINTF(("CDspCommObject::SetAudioFormat - pipe %d bps %d channels %d\n",
wPipeIndex,pFormat->wBitsPerSample,pFormat->wDataInterleave));
if (wPipeIndex >= GetNumPipes() )
{
ECHO_DEBUGPRINTF( ("CDspCommObject::SetAudioFormat: Invalid pipe"
"%d\n",
wPipeIndex) );
return ECHOSTATUS_INVALID_CHANNEL;
}
if (pFormat->wDataInterleave > 2)
{
switch (pFormat->wBitsPerSample)
{
case 16 :
wDspFormat = DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE;
break;
case 24 :
wDspFormat = DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE;
break;
case 32 :
wDspFormat = DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE;
break;
}
wDspFormat |= pFormat->wDataInterleave;
}
else
{
if (pFormat->byDataAreBigEndian)
{
switch ( pFormat->wDataInterleave )
{
case 1 :
wDspFormat = DSP_AUDIOFORM_MM_32BE;
break;
#ifdef STEREO_BIG_ENDIAN32_SUPPORT
case 2 :
wDspFormat = DSP_AUDIOFORM_SS_32BE;
break;
#endif
}
}
else
{
if ( (1 == pFormat->wDataInterleave) &&
(32 == pFormat->wBitsPerSample) &&
(0 == pFormat->byMonoToStereo) )
{
wDspFormat = DSP_AUDIOFORM_MM_32LE;
}
else
{
switch (pFormat->wBitsPerSample)
{
case 8 :
if (2 == pFormat->wDataInterleave)
wDspFormat = DSP_AUDIOFORM_SS_8;
else
wDspFormat = DSP_AUDIOFORM_MS_8;
break;
default :
case 16 :
if (2 == pFormat->wDataInterleave)
wDspFormat = DSP_AUDIOFORM_SS_16LE;
else
wDspFormat = DSP_AUDIOFORM_MS_16LE;
break;
case 24 :
if (2 == pFormat->wDataInterleave)
wDspFormat = DSP_AUDIOFORM_SS_24LE;
else
wDspFormat = DSP_AUDIOFORM_MS_24LE;
break;
case 32 :
if (2 == pFormat->wDataInterleave)
wDspFormat = DSP_AUDIOFORM_SS_32LE;
else
wDspFormat = DSP_AUDIOFORM_MS_32LE;
break;
}
}
}
}
m_pDspCommPage->wAudioFormat[wPipeIndex] = SWAP( wDspFormat );
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::GetAudioFormat
(
WORD wPipeIndex,
PECHOGALS_AUDIOFORMAT pFormat
)
{
if (wPipeIndex >= GetNumPipes() )
{
ECHO_DEBUGPRINTF( ("CDspCommObject::GetAudioFormat: Invalid pipe %d\n",
wPipeIndex) );
return ECHOSTATUS_INVALID_CHANNEL;
}
pFormat->byDataAreBigEndian = 0;
pFormat->byMonoToStereo = 0;
switch (SWAP(m_pDspCommPage->wAudioFormat[wPipeIndex]))
{
case DSP_AUDIOFORM_MS_8 :
pFormat->wDataInterleave = 1;
pFormat->wBitsPerSample = 8;
pFormat->byMonoToStereo = 1;
break;
case DSP_AUDIOFORM_MS_16LE :
pFormat->wDataInterleave = 1;
pFormat->wBitsPerSample = 16;
pFormat->byMonoToStereo = 1;
break;
case DSP_AUDIOFORM_SS_8 :
pFormat->wDataInterleave = 2;
pFormat->wBitsPerSample = 8;
break;
case DSP_AUDIOFORM_SS_16LE :
pFormat->wDataInterleave = 2;
pFormat->wBitsPerSample = 16;
break;
case DSP_AUDIOFORM_SS_32LE :
pFormat->wDataInterleave = 2;
pFormat->wBitsPerSample = 32;
break;
case DSP_AUDIOFORM_MS_32LE :
pFormat->byMonoToStereo = 1;
case DSP_AUDIOFORM_MM_32LE :
pFormat->wDataInterleave = 1;
pFormat->wBitsPerSample = 32;
break;
case DSP_AUDIOFORM_MM_32BE :
pFormat->wDataInterleave = 1;
pFormat->wBitsPerSample = 32;
pFormat->byDataAreBigEndian = 1;
break;
case DSP_AUDIOFORM_SS_32BE :
pFormat->wDataInterleave = 2;
pFormat->wBitsPerSample = 32;
pFormat->byDataAreBigEndian = 1;
break;
}
return ECHOSTATUS_OK;
}
Mixer methods
****************************************************************************/
ECHOSTATUS CDspCommObject::SetPipeOutGain
(
WORD wPipeOut,
WORD wBusOut,
INT32 iGain,
BOOL fImmediate
)
{
if ( wPipeOut < m_wNumPipesOut )
{
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
iGain = GENERIC_TO_DSP(iGain);
m_pDspCommPage->OutLineLevel[ wPipeOut ] = (BYTE) iGain;
ECHO_DEBUGPRINTF( ("CDspCommObject::SetPipeOutGain: Out pipe %d "
"= 0x%lx\n",
wPipeOut,
iGain) );
*/
if (fImmediate)
{
return UpdateAudioOutLineLevel();
}
return ECHOSTATUS_OK;
}
ECHO_DEBUGPRINTF( ("CDspCommObject::SetPipeOutGain: Invalid out pipe "
"%d\n",
wPipeOut) );
ECHO_DEBUGBREAK();
return ECHOSTATUS_INVALID_CHANNEL;
}
ECHOSTATUS CDspCommObject::GetPipeOutGain
(
WORD wPipeOut,
WORD wBusOut,
INT32 &iGain
)
{
if (wPipeOut < m_wNumPipesOut)
{
iGain = (INT32) (char) m_pDspCommPage->OutLineLevel[ wPipeOut ];
iGain = DSP_TO_GENERIC(8);
return ECHOSTATUS_OK;
}
ECHO_DEBUGPRINTF( ("CDspCommObject::GetPipeOutGain: Invalid out pipe "
"%d\n",
wPipeOut) );
return ECHOSTATUS_INVALID_CHANNEL;
}
ECHOSTATUS CDspCommObject::SetBusInGain( WORD wBusIn, INT32 iGain)
{
if (wBusIn > m_wNumBussesIn)
return ECHOSTATUS_INVALID_CHANNEL;
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
iGain += GL20_INPUT_GAIN_MAGIC_NUMBER;
m_pDspCommPage->InLineLevel[wBusIn] = (BYTE) iGain;
return UpdateAudioInLineLevel();
}
ECHOSTATUS CDspCommObject::GetBusInGain( WORD wBusIn, INT32 &iGain)
{
if (wBusIn > m_wNumBussesIn)
return ECHOSTATUS_INVALID_CHANNEL;
iGain = m_pDspCommPage->InLineLevel[wBusIn];
iGain -= GL20_INPUT_GAIN_MAGIC_NUMBER;
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::SetNominalLevel
(
WORD wBus,
BOOL bState
)
{
if (wBus < (m_wNumBussesOut + m_wNumBussesIn))
{
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
if ( bState )
m_pDspCommPage->cmdNominalLevel.SetIndexInMask( wBus );
else
m_pDspCommPage->cmdNominalLevel.ClearIndexInMask( wBus );
return UpdateAudioOutLineLevel();
}
ECHO_DEBUGPRINTF( ("CDspCommObject::SetNominalOutLineLevel Invalid "
"index %d\n",
wBus ) );
return ECHOSTATUS_INVALID_CHANNEL;
}
ECHOSTATUS CDspCommObject::GetNominalLevel
(
WORD wBus,
PBYTE pbyState
)
{
if (wBus < (m_wNumBussesOut + m_wNumBussesIn))
{
*pbyState = (BYTE)
m_pDspCommPage->cmdNominalLevel.TestIndexInMask( wBus );
return ECHOSTATUS_OK;
}
ECHO_DEBUGPRINTF( ("CDspCommObject::GetNominalLevel Invalid "
"index %d\n",
wBus ) );
return ECHOSTATUS_INVALID_CHANNEL;
}
ECHOSTATUS CDspCommObject::SetAudioMonitor
(
WORD wBusOut,
WORD wBusIn,
INT32 iGain,
BOOL fImmediate
)
{
ECHO_DEBUGPRINTF( ("CDspCommObject::SetAudioMonitor: "
"Out %d in %d Gain %d (0x%x)\n",
wBusOut, wBusIn, iGain, iGain) );
*/
WORD wOffset = ComputeAudioMonitorIndex( wBusOut, wBusIn );
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
iGain = GENERIC_TO_DSP(iGain);
m_pDspCommPage->byMonitors[ wOffset ] = (BYTE) (iGain);
if (fImmediate)
{
return UpdateAudioOutLineLevel();
}
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::SetMetersOn
(
BOOL bOn
)
{
if ( bOn )
{
if ( 0 == m_wMeterOnCount )
{
SendVector( DSP_VC_METERS_ON );
}
m_wMeterOnCount++;
}
else
{
INT32 iDevice;
if ( m_wMeterOnCount == 0 )
return ECHOSTATUS_OK;
if ( 0 == --m_wMeterOnCount )
{
SendVector( DSP_VC_METERS_OFF );
for ( iDevice = 0; iDevice < DSP_MAXPIPES; iDevice++ )
{
BYTE muted;
muted = (BYTE) GENERIC_TO_DSP(ECHOGAIN_MUTED);
m_pDspCommPage->VUMeter[ iDevice ] = muted;
m_pDspCommPage->PeakMeter[ iDevice ] = muted;
}
}
}
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::UpdateAudioOutLineLevel()
{
if (FALSE == m_bASICLoaded)
return ECHOSTATUS_ASIC_NOT_LOADED;
ClearHandshake();
return( SendVector( DSP_VC_UPDATE_OUTVOL ) );
}
ECHOSTATUS CDspCommObject::UpdateAudioInLineLevel()
{
if (FALSE == m_bASICLoaded)
return ECHOSTATUS_ASIC_NOT_LOADED;
ClearHandshake();
return( SendVector( DSP_VC_UPDATE_INGAIN ) );
}
ECHOSTATUS CDspCommObject::UpdateVmixerLevel()
{
ECHO_DEBUGPRINTF(("CDspCommObject::UpdateVmixerLevel\n"));
return ECHOSTATUS_NOT_SUPPORTED;
}
ECHOSTATUS CDspCommObject::SetInputClock(WORD wClock)
{
if (!WaitForHandshake())
return ECHOSTATUS_DSP_DEAD;
ECHO_DEBUGPRINTF( ("CDspCommObject::SetInputClock:\n") );
m_pDspCommPage->wInputClock = SWAP(wClock);
ClearHandshake();
ECHOSTATUS Status = SendVector(DSP_VC_UPDATE_CLOCKS);
return Status;
}
ECHOSTATUS CDspCommObject::SetOutputClock(WORD wClock)
{
return ECHOSTATUS_CLOCK_NOT_SUPPORTED;
}
ECHOSTATUS CDspCommObject::GetAudioMeters
(
PECHOGALS_METERS pMeters
)
{
pMeters->iNumPipesOut = 0;
pMeters->iNumPipesIn = 0;
DWORD dwCh = 0;
WORD i;
pMeters->iNumBussesOut = (INT32) m_wNumBussesOut;
for (i = 0; i < m_wNumBussesOut; i++)
{
pMeters->iBusOutVU[i] =
DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) );
pMeters->iBusOutPeak[i] =
DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) );
dwCh++;
}
pMeters->iNumBussesIn = (INT32) m_wNumBussesIn;
for (i = 0; i < m_wNumBussesIn; i++)
{
pMeters->iBusInVU[i] =
DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) );
pMeters->iBusInPeak[i] =
DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) );
dwCh++;
}
return ECHOSTATUS_OK;
}
#ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT
ECHOSTATUS CDspCommObject::GetDigitalInputAutoMute(BOOL &fAutoMute)
{
fAutoMute = m_fDigitalInAutoMute;
ECHO_DEBUGPRINTF(("CDspCommObject::GetDigitalInputAutoMute %d\n",fAutoMute));
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::SetDigitalInputAutoMute(BOOL fAutoMute)
{
ECHO_DEBUGPRINTF(("CDspCommObject::SetDigitalInputAutoMute %d\n",fAutoMute));
m_fDigitalInAutoMute = fAutoMute;
SetInputClock(m_wInputClock);
return ECHOSTATUS_OK;
}
#endif
Power management
****************************************************************************/
ECHOSTATUS CDspCommObject::GoComatose()
{
ECHO_DEBUGPRINTF(("CDspCommObject::GoComatose\n"));
if (NULL != m_pwDspCode)
{
m_pwDspCode = NULL;
m_pDspCommPage->dwControlReg = 0;
return SendVector(DSP_VC_GO_COMATOSE);
}
return ECHOSTATUS_OK;
}
#ifdef MIDI_SUPPORT
MIDI
****************************************************************************/
ECHOSTATUS CDspCommObject::WriteMidi
(
PBYTE pData,
DWORD dwLength,
PDWORD pdwActualCt
)
{
DWORD dwWriteCount,dwHandshake,dwStatus;
BYTE *pOutBuffer;
dwHandshake = GetHandshakeFlag();
if (0 == dwHandshake)
{
ECHO_DEBUGPRINTF(("CDCO::WriteMidi - can't write - handshake %ld\n",dwHandshake));
*pdwActualCt = 0;
return ECHOSTATUS_BUSY;
}
dwStatus = GetDspRegister( CHI32_STATUS_REG );
if ( 0 == (dwStatus & CHI32_STATUS_REG_HF4 ) )
{
ECHO_DEBUGPRINTF(("CDCO::WriteMidi - can't write - dwStatus 0x%lx\n",dwStatus));
*pdwActualCt = 0;
return ECHOSTATUS_BUSY;
}
dwWriteCount = dwLength;
if (dwWriteCount > (CP_MIDI_OUT_BUFFER_SIZE - 1))
{
dwWriteCount = CP_MIDI_OUT_BUFFER_SIZE - 1;
}
ECHO_DEBUGPRINTF(("WriteMidi - dwWriteCount %ld\n",dwWriteCount));
*pdwActualCt = dwWriteCount;
pOutBuffer = m_pDspCommPage->byMidiOutData;
*pOutBuffer = (BYTE) dwWriteCount;
pOutBuffer++;
OsCopyMemory(pOutBuffer,pData,dwWriteCount);
ClearHandshake();
m_pDspCommPage->dwMidiOutFreeCount = 0;
SendVector( DSP_VC_MIDI_WRITE );
ULONGLONG ullTime;
m_pOsSupport->OsGetSystemTime( &ullTime );
m_ullMidiOutTime = ullTime;
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::ReadMidi
(
WORD wIndex,
DWORD & dwData
)
{
if ( wIndex >= CP_MIDI_IN_BUFFER_SIZE )
return ECHOSTATUS_INVALID_INDEX;
dwData = SWAP( m_pDspCommPage->wMidiInData[ wIndex ] );
ULONGLONG ullTime;
m_pOsSupport->OsGetSystemTime( &ullTime );
m_ullMidiInTime = ullTime;
return ECHOSTATUS_OK;
}
ECHOSTATUS CDspCommObject::SetMidiOn( BOOL bOn )
{
if ( bOn )
{
if ( 0 == m_wMidiOnCount )
{
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
m_pDspCommPage->dwFlags |= SWAP( (DWORD) DSP_FLAG_MIDI_INPUT );
ClearHandshake();
SendVector( DSP_VC_UPDATE_FLAGS );
}
m_wMidiOnCount++;
}
else
{
if ( m_wMidiOnCount == 0 )
return ECHOSTATUS_OK;
if ( 0 == --m_wMidiOnCount )
{
if ( !WaitForHandshake() )
return ECHOSTATUS_DSP_DEAD;
m_pDspCommPage->dwFlags &= SWAP( (DWORD) ~DSP_FLAG_MIDI_INPUT );
ClearHandshake();
SendVector( DSP_VC_UPDATE_FLAGS );
}
}
return ECHOSTATUS_OK;
}
BOOL CDspCommObject::IsMidiOutActive()
{
ULONGLONG ullCurTime;
m_pOsSupport->OsGetSystemTime( &ullCurTime );
return( ( ( ullCurTime - m_ullMidiOutTime ) > MIDI_ACTIVITY_TIMEOUT_USEC ) ? FALSE : TRUE );
}
#endif