#include "C3g.h"
#define ECHO3G_ANALOG_OUTPUT_LATENCY_1X (1 + 32 + 12) // ASIC + DSP + DAC
#define ECHO3G_ANALOG_OUTPUT_LATENCY_2X (1 + 32 + 5)
#define ECHO3G_ANALOG_INPUT_LATENCY_1X (1 + 32 + 12)
#define ECHO3G_ANALOG_INPUT_LATENCY_2X (1 + 32 + 9)
#define ECHO3G_DIGITAL_OUTPUT_LATENCY (1 + 32)
#define ECHO3G_DIGITAL_INPUT_LATENCY (1 + 32)
Construction and destruction
****************************************************************************/
PVOID C3g::operator new( size_t Size )
{
PVOID pMemory;
ECHOSTATUS Status;
Status = OsAllocateNonPaged(Size,&pMemory);
if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
{
ECHO_DEBUGPRINTF(("C3g::operator new - memory allocation failed\n"));
pMemory = NULL;
}
else
{
memset( pMemory, 0, Size );
}
return pMemory;
}
VOID C3g::operator delete( PVOID pVoid )
{
if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
{
ECHO_DEBUGPRINTF(("C3g::operator delete memory free failed\n"));
}
}
C3g::C3g( PCOsSupport pOsSupport )
: CEchoGalsMTC( pOsSupport )
{
ECHO_DEBUGPRINTF( ( "C3g::C3g() is born!\n" ) );
m_wAnalogOutputLatency = ECHO3G_ANALOG_OUTPUT_LATENCY_1X;
m_wAnalogInputLatency = ECHO3G_ANALOG_INPUT_LATENCY_1X;
m_wDigitalOutputLatency = ECHO3G_DIGITAL_OUTPUT_LATENCY;
m_wDigitalInputLatency = ECHO3G_DIGITAL_INPUT_LATENCY;
}
C3g::~C3g()
{
ECHO_DEBUGPRINTF( ( "C3g::~C3g() is toast!\n" ) );
}
Setup and hardware initialization
****************************************************************************/
ECHOSTATUS C3g::InitHw()
{
ECHOSTATUS Status;
WORD i;
if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
return Status;
ECHO_ASSERT(NULL == m_pDspCommObject );
m_pDspCommObject = new C3gDco( (PDWORD) m_pvSharedMemory, m_pOsSupport );
if (NULL == m_pDspCommObject)
{
ECHO_DEBUGPRINTF(("C3g::InitHw - could not create DSP comm object\n"));
return ECHOSTATUS_NO_MEM;
}
DWORD dwBoxType;
GetDspCommObject()->LoadFirmware();
GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL);
if (NO3GBOX == dwBoxType)
return ECHOSTATUS_NO_3G_BOX;
if ( GetDspCommObject()->IsBoardBad() )
return ECHOSTATUS_DSP_DEAD;
m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK;
Status = InitLineLevels();
if ( ECHOSTATUS_OK != Status )
return Status;
Status = m_MidiIn.Init( this );
if ( ECHOSTATUS_OK != Status )
return Status;
for (i = 0; i < GetFirstDigitalBusOut(); i++ )
{
GetDspCommObject()->
SetNominalLevel( i, FALSE );
}
for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
{
GetDspCommObject()->
SetNominalLevel( GetNumBussesOut() + i, FALSE );
}
SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
m_dwSampleRate = GetDspCommObject()->GetSampleRate();
ECHO_DEBUGPRINTF( ( "C3g::InitHw()\n" ) );
return Status;
}
Informational methods
****************************************************************************/
ECHOSTATUS C3g::GetCapabilities
(
PECHOGALS_CAPS pCapabilities
)
{
ECHOSTATUS Status;
WORD i;
Status = GetBaseCapabilities(pCapabilities);
if ( ECHOSTATUS_OK != Status )
return Status;
for (i = 0 ; i < pCapabilities->wNumBussesOut; i++)
{
pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
}
for (i = 2 ; i < pCapabilities->wNumBussesIn; i++)
{
pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
}
pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_SPDIF |
ECHO_CLOCK_BIT_ADAT |
ECHO_CLOCK_BIT_MTC;
DWORD dwBoxType;
GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL);
switch (dwBoxType)
{
case GINA3G :
pCapabilities->dwBusInCaps[0] |= ECHOCAPS_PHANTOM_POWER;
pCapabilities->dwBusInCaps[1] |= ECHOCAPS_PHANTOM_POWER;
break;
case LAYLA3G :
pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_WORD;
break;
}
pCapabilities->dwOutClockTypes = 0;
return Status;
}
ECHOSTATUS C3g::QueryAudioSampleRate
(
DWORD dwSampleRate
)
{
if ((dwSampleRate >= 32000) && (dwSampleRate <= 50000))
return ECHOSTATUS_OK;
if ( (DIGITAL_MODE_ADAT != GetDigitalMode()) &&
(dwSampleRate > 50000) &&
(dwSampleRate <= 100000))
return ECHOSTATUS_OK;
ECHO_DEBUGPRINTF(("C3g::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
return ECHOSTATUS_BAD_FORMAT;
}
void C3g::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
{
dwMinRate = 32000;
dwMaxRate = 96000;
}
ECHOSTATUS C3g::GetInputClockDetect(DWORD &dwClockDetectBits)
{
if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
{
ECHO_DEBUGPRINTF( ("C3g::GetInputClockDetect: DSP Dead!\n") );
return ECHOSTATUS_DSP_DEAD;
}
DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_MTC;
if (0 != (dwClocksFromDsp & E3G_CLOCK_DETECT_BIT_WORD))
dwClockDetectBits |= ECHO_CLOCK_BIT_WORD;
switch (GetDigitalMode())
{
case DIGITAL_MODE_SPDIF_RCA :
case DIGITAL_MODE_SPDIF_OPTICAL :
if (0 != (dwClocksFromDsp & E3G_CLOCK_DETECT_BIT_SPDIF))
dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
break;
case DIGITAL_MODE_ADAT :
if (0 != (dwClocksFromDsp & E3G_CLOCK_DETECT_BIT_ADAT))
dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT;
break;
}
return ECHOSTATUS_OK;
}
void C3g::Get3gBoxType(DWORD *pOriginalBoxType,DWORD *pCurrentBoxType)
{
GetDspCommObject()->Get3gBoxType(pOriginalBoxType,pCurrentBoxType);
}
char *C3g::Get3gBoxName()
{
char *pszName;
DWORD dwBoxType;
GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL);
switch (dwBoxType)
{
case GINA3G :
pszName = "Gina3G";
break;
case LAYLA3G :
pszName = "Layla3G";
break;
case NO3GBOX :
default :
pszName = "Echo3G";
break;
}
return pszName;
}
void C3g::GetPhantomPower(BOOL *pfPhantom)
{
*pfPhantom = m_fPhantomPower;
}
void C3g::SetPhantomPower(BOOL fPhantom)
{
DWORD dwBoxType;
GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL);
if (GINA3G == dwBoxType)
{
GetDspCommObject()->SetPhantomPower( fPhantom );
m_fPhantomPower = fPhantom;
}
}
void C3g::GetAudioLatency(ECHO_AUDIO_LATENCY *pLatency)
{
DWORD dwSampleRate;
dwSampleRate = GetDspCommObject()->GetSampleRate();
if (dwSampleRate <= 50000)
{
m_wAnalogOutputLatency = ECHO3G_ANALOG_OUTPUT_LATENCY_1X;
m_wAnalogInputLatency = ECHO3G_ANALOG_INPUT_LATENCY_1X;
}
else
{
m_wAnalogOutputLatency = ECHO3G_ANALOG_OUTPUT_LATENCY_2X;
m_wAnalogInputLatency = ECHO3G_ANALOG_INPUT_LATENCY_2X;
}
CEchoGals::GetAudioLatency(pLatency);
}
ECHOSTATUS C3g::Start
(
PCChannelMask pChannelMask
)
{
PC3gDco pDCO;
pDCO = GetDspCommObject();
if (pDCO->DoubleSpeedMode())
{
BOOL intersect;
intersect = pChannelMask->IsIntersectionOf( pDCO->m_Adat38Mask );
if (intersect)
{
ECHO_DEBUGPRINTF(("Cannot start ADAT channels 3-8 in double speed mode\n"));
return ECHOSTATUS_INVALID_CHANNEL;
}
}
return CEchoGals::Start(pChannelMask);
}