#include "CEchoGals.h"
#include "C3gDco.h"
#include "Echo3gDSP.c"
#include "3G_ASIC.c"
Construction and destruction
****************************************************************************/
C3gDco::C3gDco
(
PDWORD pdwRegBase,
PCOsSupport pOsSupport
) : CDspCommObject( pdwRegBase, pOsSupport )
{
m_pdwDspRegBase = pdwRegBase;
m_dwOriginalBoxType = NO3GBOX;
m_dwCurrentBoxType = m_dwOriginalBoxType;
SetChannelCounts();
m_bBoxTypeSet = FALSE;
m_fHasVmixer = FALSE;
m_wNumMidiOut = 1;
m_wNumMidiIn = 1;
m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 );
m_pDspCommPage->dw3gFreqReg = SWAP( (DWORD) (E3G_MAGIC_NUMBER / 48000) - 2);
m_bHasASIC = TRUE;
m_pwDspCodeToLoad = pwEcho3gDSP;
m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA;
m_bProfessionalSpdif = FALSE;
m_bNonAudio = FALSE;
}
C3gDco::~C3gDco()
{
}
DWORD C3gDco::GetDigitalModes()
{
DWORD dwModes;
dwModes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
return dwModes;
}
Hardware setup and config
****************************************************************************/
BOOL C3gDco::LoadASIC()
{
DWORD dwControlReg;
if ( m_bASICLoaded == TRUE )
return TRUE;
ECHO_DEBUGPRINTF(("C3gDco::LoadASIC\n"));
m_pOsSupport->OsSnooze( 2000 );
if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_3G_ASIC,
pb3g_asic,
sizeof(pb3g_asic) ) )
return FALSE;
m_pOsSupport->OsSnooze( 1000000 );
CheckAsicStatus();
if ( m_bASICLoaded )
{
dwControlReg = E3G_48KHZ;
WriteControlReg( dwControlReg, E3G_FREQ_REG_DEFAULT, TRUE);
}
ECHO_DEBUGPRINTF(("\t3G ASIC loader finished\n"));
return m_bASICLoaded;
}
ECHOSTATUS C3gDco::SetInputClock(WORD wClock)
{
DWORD dwControlReg,dwSampleRate;
ECHOSTATUS Status;
ECHO_DEBUGPRINTF( ("C3gDco::SetInputClock:\n") );
dwControlReg = GetControlRegister();
dwControlReg &= E3G_CLOCK_CLEAR_MASK;
switch (wClock)
{
case ECHO_CLOCK_INTERNAL :
ECHO_DEBUGPRINTF(("\tsetting internal clock\n"));
m_wInputClock = ECHO_CLOCK_INTERNAL;
dwSampleRate = GetSampleRate();
if ((dwSampleRate < 32000) || (dwSampleRate > 100000))
dwSampleRate = 48000;
SetSampleRate(dwSampleRate);
return ECHOSTATUS_OK;
case ECHO_CLOCK_WORD:
dwControlReg |= E3G_WORD_CLOCK;
if ( E3G_CLOCK_DETECT_BIT_WORD96 & GetInputClockDetect() )
{
dwControlReg |= E3G_DOUBLE_SPEED_MODE;
}
else
{
dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
}
ECHO_DEBUGPRINTF( ( "\tSet 3G clock to WORD\n" ) );
break;
case ECHO_CLOCK_SPDIF :
if ( DIGITAL_MODE_ADAT == GetDigitalMode() )
{
return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
}
dwControlReg |= E3G_SPDIF_CLOCK;
if ( E3G_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() )
{
dwControlReg |= E3G_DOUBLE_SPEED_MODE;
}
else
{
dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
}
ECHO_DEBUGPRINTF( ( "\tSet 3G clock to SPDIF\n" ) );
break;
case ECHO_CLOCK_ADAT :
if ( DIGITAL_MODE_ADAT != GetDigitalMode() )
{
return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
}
dwControlReg |= E3G_ADAT_CLOCK;
dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
ECHO_DEBUGPRINTF( ( "\tSet 3G clock to ADAT\n" ) );
break;
default :
ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for 3G\n",wClock));
ECHO_DEBUGBREAK();
return ECHOSTATUS_CLOCK_NOT_SUPPORTED;
}
Status = WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE );
if (ECHOSTATUS_OK == Status)
m_wInputClock = wClock;
return Status;
}
DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate )
{
DWORD dwControlReg,dwNewClock,dwBaseRate,dwFreqReg;
ECHO_DEBUGPRINTF(("3G set sample rate to %ld\n",dwNewSampleRate));
if ( GetInputClock() != ECHO_CLOCK_INTERNAL )
{
ECHO_DEBUGPRINTF( ( "C3gDco::SetSampleRate: Cannot set sample rate - "
"clock not set to ECHO_CLOCK_INTERNAL\n" ) );
m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
SetInputClock( m_wInputClock );
return dwNewSampleRate;
}
dwControlReg = GetControlRegister();
dwControlReg &= E3G_CLOCK_CLEAR_MASK;
switch ( dwNewSampleRate )
{
case 96000 :
dwNewClock = E3G_96KHZ;
break;
case 88200 :
dwNewClock = E3G_88KHZ;
break;
case 48000 :
dwNewClock = E3G_48KHZ;
break;
case 44100 :
dwNewClock = E3G_44KHZ;
break;
case 32000 :
dwNewClock = E3G_32KHZ;
break;
default :
dwNewClock = E3G_CONTINUOUS_CLOCK;
if (dwNewSampleRate > 50000)
dwNewClock |= E3G_DOUBLE_SPEED_MODE;
break;
}
dwControlReg |= dwNewClock;
SetSpdifBits(&dwControlReg,dwNewSampleRate);
ECHO_DEBUGPRINTF(("\tdwNewClock 0x%lx dwControlReg 0x%lx\n",dwNewClock,dwControlReg));
dwBaseRate = dwNewSampleRate;
if (dwBaseRate > 50000)
dwBaseRate /= 2;
if (dwBaseRate < 32000)
dwBaseRate = 32000;
dwFreqReg = E3G_MAGIC_NUMBER / dwBaseRate - 2;
if (dwFreqReg > E3G_FREQ_REG_MAX)
dwFreqReg = E3G_FREQ_REG_MAX;
if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg, dwFreqReg) )
{
m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: %ld clock %lx\n", dwNewSampleRate, dwControlReg) );
}
else
{
ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: could not set sample rate %ld\n", dwNewSampleRate) );
dwNewSampleRate = SWAP( m_pDspCommPage->dwSampleRate );
}
return dwNewSampleRate;
}
ECHOSTATUS C3gDco::SetDigitalMode
(
BYTE byNewMode
)
{
DWORD dwControlReg;
WORD wInvalidClock;
switch (byNewMode)
{
case DIGITAL_MODE_SPDIF_RCA :
case DIGITAL_MODE_SPDIF_OPTICAL :
wInvalidClock = ECHO_CLOCK_ADAT;
break;
case DIGITAL_MODE_ADAT :
wInvalidClock = ECHO_CLOCK_SPDIF;
break;
default :
wInvalidClock = 0xffff;
break;
}
if (wInvalidClock == GetInputClock())
{
SetInputClock( ECHO_CLOCK_INTERNAL );
SetSampleRate( 48000 );
}
dwControlReg = GetControlRegister();
dwControlReg &= E3G_DIGITAL_MODE_CLEAR_MASK;
switch ( byNewMode )
{
default :
return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED;
case DIGITAL_MODE_SPDIF_OPTICAL :
dwControlReg |= E3G_SPDIF_OPTICAL_MODE;
case DIGITAL_MODE_SPDIF_RCA :
break;
case DIGITAL_MODE_ADAT :
dwControlReg |= E3G_ADAT_MODE;
dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
break;
}
WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE );
m_byDigitalMode = byNewMode;
ECHO_DEBUGPRINTF( ("C3gDco::SetDigitalMode to %ld\n",
(DWORD) m_byDigitalMode) );
return ECHOSTATUS_OK;
}
ECHOSTATUS C3gDco::WriteControlReg
(
DWORD dwControlReg,
DWORD dwFreqReg,
BOOL fForceWrite
)
{
ECHOSTATUS Status;
ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg 0x%lx 0x%lx\n",dwControlReg,dwFreqReg));
Status = ValidateCtrlReg(dwControlReg);
if (ECHOSTATUS_OK != Status)
return Status;
if ( !m_bASICLoaded )
{
ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - ASIC not loaded\n"));
return( ECHOSTATUS_ASIC_NOT_LOADED );
}
if ( !WaitForHandshake() )
{
ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - no handshake\n"));
return ECHOSTATUS_DSP_DEAD;
}
if ( fForceWrite ||
(dwControlReg != GetControlRegister()) ||
(dwFreqReg != Get3gFreqReg())
)
{
m_pDspCommPage->dw3gFreqReg = SWAP( dwFreqReg );
SetControlRegister( dwControlReg );
ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: Setting 0x%lx, 0x%lx\n",
dwControlReg,dwFreqReg) );
ClearHandshake();
return SendVector( DSP_VC_WRITE_CONTROL_REG );
}
else
{
ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: not written, no change\n") );
}
return ECHOSTATUS_OK;
}
void C3gDco::SetSpdifBits(DWORD *pdwCtrlReg,DWORD dwSampleRate)
{
DWORD dwCtrlReg;
dwCtrlReg = *pdwCtrlReg;
dwCtrlReg &= E3G_SPDIF_FORMAT_CLEAR_MASK;
switch (dwSampleRate)
{
case 32000 :
dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0 |
E3G_SPDIF_SAMPLE_RATE1;
break;
case 44100 :
if (m_bProfessionalSpdif)
dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0;
break;
case 48000 :
dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE1;
break;
}
if (m_bProfessionalSpdif)
dwCtrlReg |= E3G_SPDIF_PRO_MODE;
if (m_bNonAudio)
dwCtrlReg |= E3G_SPDIF_NOT_AUDIO;
dwCtrlReg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | E3G_SPDIF_COPY_PERMIT;
*pdwCtrlReg = dwCtrlReg;
}
void C3gDco::SetSpdifOutNonAudio(BOOL bNonAudio)
{
DWORD dwControlReg;
m_bNonAudio = bNonAudio;
dwControlReg = GetControlRegister();
SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate ));
WriteControlReg( dwControlReg, Get3gFreqReg() );
}
void C3gDco::SetProfessionalSpdif
(
BOOL bNewStatus
)
{
DWORD dwControlReg;
m_bProfessionalSpdif = bNewStatus;
dwControlReg = GetControlRegister();
SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate ));
WriteControlReg( dwControlReg, Get3gFreqReg() );
}
BOOL C3gDco::CheckAsicStatus()
{
DWORD dwBoxStatus,dwBoxType;
if ( !WaitForHandshake() )
{
ECHO_DEBUGPRINTF(("CheckAsicStatus - no handshake!\n"));
return FALSE;
}
m_pDspCommPage->dwExtBoxStatus = SWAP( (DWORD) E3G_ASIC_NOT_LOADED);
m_bASICLoaded = FALSE;
ClearHandshake();
SendVector( DSP_VC_TEST_ASIC );
if ( !WaitForHandshake() )
{
ECHO_DEBUGPRINTF(("CheckAsicStatus - no handshake after VC\n"));
m_pwDspCode = NULL;
m_ullLastLoadAttemptTime = 0;
return FALSE;
}
dwBoxStatus = SWAP(m_pDspCommPage->dwExtBoxStatus);
if (E3G_ASIC_NOT_LOADED == dwBoxStatus)
{
ECHO_DEBUGPRINTF(("CheckAsicStatus - ASIC not loaded\n"));
dwBoxType = NO3GBOX;
}
else
{
dwBoxType = dwBoxStatus & E3G_BOX_TYPE_MASK;
m_bASICLoaded = TRUE;
ECHO_DEBUGPRINTF(("CheckAsicStatus - read box type %x\n",dwBoxType));
}
m_dwCurrentBoxType = dwBoxType;
if (m_bBoxTypeSet)
{
if ( (NO3GBOX == dwBoxType) ||
(dwBoxType != m_dwOriginalBoxType) )
{
ECHO_DEBUGPRINTF(("CheckAsicStatus - box type mismatch - original %x, got %x\n",m_dwOriginalBoxType,dwBoxType));
return FALSE;
}
ECHO_DEBUGPRINTF(("CheckAsicStatus - ASIC ok\n"));
m_bASICLoaded = TRUE;
return TRUE;
}
m_dwOriginalBoxType = dwBoxType;
m_bBoxTypeSet = TRUE;
SetChannelCounts();
if (NO3GBOX == dwBoxType)
{
ECHO_DEBUGPRINTF(("CheckAsicStatus - no external box\n"));
m_bBadBoard = TRUE;
}
return m_bASICLoaded;
}
void C3gDco::SetPhantomPower(BOOL fPhantom)
{
DWORD dwControlReg;
dwControlReg = GetControlRegister();
if (fPhantom)
{
dwControlReg |= E3G_PHANTOM_POWER;
}
else
{
dwControlReg &= ~E3G_PHANTOM_POWER;
}
WriteControlReg( dwControlReg, Get3gFreqReg() );
}
void C3gDco::SetChannelCounts()
{
char *pszName;
WORD ch,i;
switch (m_dwOriginalBoxType)
{
case GINA3G :
m_wNumPipesOut = 14;
m_wNumPipesIn = 10;
m_wFirstDigitalBusOut = 6;
m_wFirstDigitalBusIn = 2;
pszName = "Gina3G";
break;
case NO3GBOX :
case LAYLA3G :
default :
m_wNumPipesOut = 16;
m_wNumPipesIn = 16;
m_wFirstDigitalBusOut = 8;
m_wFirstDigitalBusIn = 8;
pszName = "Layla3G";
break;
}
m_wNumBussesOut = m_wNumPipesOut;
m_wNumBussesIn = m_wNumPipesIn;
strcpy( m_szCardName, pszName);
m_Adat38Mask.Clear();
ch = m_wFirstDigitalBusOut + 2;
for (i = 0; i < 6; i++)
{
m_Adat38Mask.SetIndexInMask(ch);
ch++;
}
ch += m_wFirstDigitalBusIn + 2;
for (i = 0; i < 6; i++)
{
m_Adat38Mask.SetIndexInMask(ch);
ch++;
}
}
void C3gDco::Get3gBoxType(DWORD *pOriginalBoxType,DWORD *pCurrentBoxType)
{
if (NULL != pOriginalBoxType)
*pOriginalBoxType = m_dwOriginalBoxType;
if (NULL != pCurrentBoxType)
{
CheckAsicStatus();
*pCurrentBoxType = m_dwCurrentBoxType;
}
}
ECHOSTATUS C3gDco::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;
dwCh = E3G_MAX_OUTPUTS;
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;
}
BOOL C3gDco::DoubleSpeedMode(DWORD *pdwNewCtrlReg)
{
DWORD dwControlReg;
if (NULL == pdwNewCtrlReg)
dwControlReg = GetControlRegister();
else
dwControlReg = *pdwNewCtrlReg;
if (0 != (dwControlReg & E3G_DOUBLE_SPEED_MODE))
return TRUE;
return FALSE;
}
ECHOSTATUS C3gDco::ValidateCtrlReg(DWORD dwNewControlReg)
{
BOOL fCurrDoubleSpeed,fNewDoubleSpeed;
if (m_cmActive.IsEmpty())
return ECHOSTATUS_OK;
fNewDoubleSpeed = DoubleSpeedMode(&dwNewControlReg);
fCurrDoubleSpeed = DoubleSpeedMode(NULL);
if (fCurrDoubleSpeed != fNewDoubleSpeed)
{
ECHO_DEBUGPRINTF(("Can't switch to speeds with transport active\n"));
return ECHOSTATUS_INVALID_CHANNEL;
}
return ECHOSTATUS_OK;
}