1 // ****************************************************************************
5 // Implementation file for the C3g driver class.
6 // Set editor tabs to 3 for your viewing pleasure.
8 // ----------------------------------------------------------------------------
10 // This file is part of Echo Digital Audio's generic driver library.
11 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
12 // All rights reserved
15 // This library is free software; you can redistribute it and/or
16 // modify it under the terms of the GNU Lesser General Public
17 // License as published by the Free Software Foundation; either
18 // version 2.1 of the License, or (at your option) any later version.
20 // This library is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 // Lesser General Public License for more details.
25 // You should have received a copy of the GNU Lesser General Public
26 // License along with this library; if not, write to the Free Software
27 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 // ****************************************************************************
33 #define ECHO3G_ANALOG_OUTPUT_LATENCY_1X (1 + 32 + 12) // ASIC + DSP + DAC
34 #define ECHO3G_ANALOG_OUTPUT_LATENCY_2X (1 + 32 + 5)
35 #define ECHO3G_ANALOG_INPUT_LATENCY_1X (1 + 32 + 12)
36 #define ECHO3G_ANALOG_INPUT_LATENCY_2X (1 + 32 + 9)
38 #define ECHO3G_DIGITAL_OUTPUT_LATENCY (1 + 32)
39 #define ECHO3G_DIGITAL_INPUT_LATENCY (1 + 32)
43 /****************************************************************************
45 Construction and destruction
47 ****************************************************************************/
49 //===========================================================================
51 // Overload new & delete so memory for this object is allocated
52 // from non-paged memory.
54 //===========================================================================
56 PVOID
C3g::operator new( size_t Size
)
61 Status
= OsAllocateNonPaged(Size
,&pMemory
);
63 if ( (ECHOSTATUS_OK
!= Status
) || (NULL
== pMemory
))
65 ECHO_DEBUGPRINTF(("C3g::operator new - memory allocation failed\n"));
71 memset( pMemory
, 0, Size
);
76 } // PVOID C3g::operator new( size_t Size )
79 VOID
C3g::operator delete( PVOID pVoid
)
81 if ( ECHOSTATUS_OK
!= OsFreeNonPaged( pVoid
) )
83 ECHO_DEBUGPRINTF(("C3g::operator delete memory free failed\n"));
85 } // VOID C3g::operator delete( PVOID pVoid )
88 //===========================================================================
90 // Constructor and destructor
92 //===========================================================================
94 C3g::C3g( PCOsSupport pOsSupport
)
95 : CEchoGalsMTC( pOsSupport
)
97 ECHO_DEBUGPRINTF( ( "C3g::C3g() is born!\n" ) );
99 m_wAnalogOutputLatency
= ECHO3G_ANALOG_OUTPUT_LATENCY_1X
;
100 m_wAnalogInputLatency
= ECHO3G_ANALOG_INPUT_LATENCY_1X
;
101 m_wDigitalOutputLatency
= ECHO3G_DIGITAL_OUTPUT_LATENCY
;
102 m_wDigitalInputLatency
= ECHO3G_DIGITAL_INPUT_LATENCY
;
108 ECHO_DEBUGPRINTF( ( "C3g::~C3g() is toast!\n" ) );
114 /****************************************************************************
116 Setup and hardware initialization
118 ****************************************************************************/
120 //===========================================================================
122 // Every card has an InitHw method
124 //===========================================================================
126 ECHOSTATUS
C3g::InitHw()
132 // Call the base method
134 if ( ECHOSTATUS_OK
!= ( Status
= CEchoGals::InitHw() ) )
138 // Create the DSP comm object
140 ECHO_ASSERT(NULL
== m_pDspCommObject
);
141 m_pDspCommObject
= new C3gDco( (PDWORD
) m_pvSharedMemory
, m_pOsSupport
);
142 if (NULL
== m_pDspCommObject
)
144 ECHO_DEBUGPRINTF(("C3g::InitHw - could not create DSP comm object\n"));
145 return ECHOSTATUS_NO_MEM
;
153 GetDspCommObject()->LoadFirmware();
155 GetDspCommObject()->Get3gBoxType(&dwBoxType
,NULL
);
156 if (NO3GBOX
== dwBoxType
)
157 return ECHOSTATUS_NO_3G_BOX
;
159 if ( GetDspCommObject()->IsBoardBad() )
160 return ECHOSTATUS_DSP_DEAD
;
163 // Clear the "bad board" flag; set the flags to indicate that
164 // 3G can handle super-interleave.
166 m_wFlags
&= ~ECHOGALS_FLAG_BADBOARD
;
167 m_wFlags
|= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK
;
170 // Must call this here after DSP is init to
171 // init gains and mutes
173 Status
= InitLineLevels();
174 if ( ECHOSTATUS_OK
!= Status
)
178 // Initialize the MIDI input
180 Status
= m_MidiIn
.Init( this );
181 if ( ECHOSTATUS_OK
!= Status
)
185 // Set defaults for +4/-10
187 for (i
= 0; i
< GetFirstDigitalBusOut(); i
++ )
190 SetNominalLevel( i
, FALSE
); // FALSE is +4 here
192 for ( i
= 0; i
< GetFirstDigitalBusIn(); i
++ )
195 SetNominalLevel( GetNumBussesOut() + i
, FALSE
);
199 // Set the digital mode to S/PDIF RCA
201 SetDigitalMode( DIGITAL_MODE_SPDIF_RCA
);
204 // Get default sample rate from DSP
206 m_dwSampleRate
= GetDspCommObject()->GetSampleRate();
208 ECHO_DEBUGPRINTF( ( "C3g::InitHw()\n" ) );
211 } // ECHOSTATUS C3g::InitHw()
216 /****************************************************************************
218 Informational methods
220 ****************************************************************************/
222 //===========================================================================
224 // Override GetCapabilities to enumerate unique capabilties for this card
226 //===========================================================================
228 ECHOSTATUS
C3g::GetCapabilities
230 PECHOGALS_CAPS pCapabilities
236 Status
= GetBaseCapabilities(pCapabilities
);
237 if ( ECHOSTATUS_OK
!= Status
)
241 // Add nominal level control to all ins & outs except the universal
243 for (i
= 0 ; i
< pCapabilities
->wNumBussesOut
; i
++)
245 pCapabilities
->dwBusOutCaps
[i
] |= ECHOCAPS_NOMINAL_LEVEL
;
248 for (i
= 2 ; i
< pCapabilities
->wNumBussesIn
; i
++)
250 pCapabilities
->dwBusInCaps
[i
] |= ECHOCAPS_NOMINAL_LEVEL
;
253 pCapabilities
->dwInClockTypes
|= ECHO_CLOCK_BIT_SPDIF
|
254 ECHO_CLOCK_BIT_ADAT
|
258 // Box-specific capabilities
262 GetDspCommObject()->Get3gBoxType(&dwBoxType
,NULL
);
266 pCapabilities
->dwBusInCaps
[0] |= ECHOCAPS_PHANTOM_POWER
;
267 pCapabilities
->dwBusInCaps
[1] |= ECHOCAPS_PHANTOM_POWER
;
271 pCapabilities
->dwInClockTypes
|= ECHO_CLOCK_BIT_WORD
;
276 pCapabilities
->dwOutClockTypes
= 0;
280 } // ECHOSTATUS C3g::GetCapabilities
283 //===========================================================================
285 // QueryAudioSampleRate is used to find out if this card can handle a
286 // given sample rate.
288 //===========================================================================
290 ECHOSTATUS
C3g::QueryAudioSampleRate
296 // Check rates that are supported by continuous mode; only allow
297 // double-speed rates if not in ADAT mode
299 if ((dwSampleRate
>= 32000) && (dwSampleRate
<= 50000))
300 return ECHOSTATUS_OK
;
302 if ( (DIGITAL_MODE_ADAT
!= GetDigitalMode()) &&
303 (dwSampleRate
> 50000) &&
304 (dwSampleRate
<= 100000))
305 return ECHOSTATUS_OK
;
307 ECHO_DEBUGPRINTF(("C3g::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate
) );
309 return ECHOSTATUS_BAD_FORMAT
;
311 } // ECHOSTATUS C3g::QueryAudioSampleRate
314 void C3g::QuerySampleRateRange(DWORD
&dwMinRate
,DWORD
&dwMaxRate
)
322 //===========================================================================
324 // GetInputClockDetect returns a bitmask consisting of all the input
325 // clocks currently connected to the hardware; this changes as the user
326 // connects and disconnects clock inputs.
328 // You should use this information to determine which clocks the user is
329 // allowed to select.
331 //===========================================================================
333 ECHOSTATUS
C3g::GetInputClockDetect(DWORD
&dwClockDetectBits
)
335 if ( NULL
== GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
337 ECHO_DEBUGPRINTF( ("C3g::GetInputClockDetect: DSP Dead!\n") );
338 return ECHOSTATUS_DSP_DEAD
;
342 // Map the DSP clock detect bits to the generic driver clock detect bits
344 DWORD dwClocksFromDsp
= GetDspCommObject()->GetInputClockDetect();
346 dwClockDetectBits
= ECHO_CLOCK_BIT_INTERNAL
| ECHO_CLOCK_BIT_MTC
;
348 if (0 != (dwClocksFromDsp
& E3G_CLOCK_DETECT_BIT_WORD
))
349 dwClockDetectBits
|= ECHO_CLOCK_BIT_WORD
;
351 switch (GetDigitalMode())
353 case DIGITAL_MODE_SPDIF_RCA
:
354 case DIGITAL_MODE_SPDIF_OPTICAL
:
355 if (0 != (dwClocksFromDsp
& E3G_CLOCK_DETECT_BIT_SPDIF
))
356 dwClockDetectBits
|= ECHO_CLOCK_BIT_SPDIF
;
359 case DIGITAL_MODE_ADAT
:
360 if (0 != (dwClocksFromDsp
& E3G_CLOCK_DETECT_BIT_ADAT
))
361 dwClockDetectBits
|= ECHO_CLOCK_BIT_ADAT
;
365 return ECHOSTATUS_OK
;
367 } // GetInputClockDetect
370 //===========================================================================
372 // Get the external box type
374 //===========================================================================
376 void C3g::Get3gBoxType(DWORD
*pOriginalBoxType
,DWORD
*pCurrentBoxType
)
378 GetDspCommObject()->Get3gBoxType(pOriginalBoxType
,pCurrentBoxType
);
382 //===========================================================================
384 // Get the external box name
386 //===========================================================================
388 char *C3g::Get3gBoxName()
393 GetDspCommObject()->Get3gBoxType(&dwBoxType
,NULL
);
414 //===========================================================================
416 // Get phantom power state for Gina3G
418 //===========================================================================
420 void C3g::GetPhantomPower(BOOL
*pfPhantom
)
422 *pfPhantom
= m_fPhantomPower
;
426 //===========================================================================
428 // Set phantom power state for Gina3G
430 //===========================================================================
432 void C3g::SetPhantomPower(BOOL fPhantom
)
436 GetDspCommObject()->Get3gBoxType(&dwBoxType
,NULL
);
437 if (GINA3G
== dwBoxType
)
439 GetDspCommObject()->SetPhantomPower( fPhantom
);
440 m_fPhantomPower
= fPhantom
;
445 //===========================================================================
447 // GetAudioLatency - returns the latency for a single pipe
449 //===========================================================================
451 void C3g::GetAudioLatency(ECHO_AUDIO_LATENCY
*pLatency
)
456 // Adjust the stored latency values based on the sample rate
458 dwSampleRate
= GetDspCommObject()->GetSampleRate();
459 if (dwSampleRate
<= 50000)
461 m_wAnalogOutputLatency
= ECHO3G_ANALOG_OUTPUT_LATENCY_1X
;
462 m_wAnalogInputLatency
= ECHO3G_ANALOG_INPUT_LATENCY_1X
;
466 m_wAnalogOutputLatency
= ECHO3G_ANALOG_OUTPUT_LATENCY_2X
;
467 m_wAnalogInputLatency
= ECHO3G_ANALOG_INPUT_LATENCY_2X
;
471 // Let the base class worry about analog vs. digital
473 CEchoGals::GetAudioLatency(pLatency
);
479 //===========================================================================
481 // Start transport for a group of pipes
483 // Use this to make sure no one tries to start digital channels 3-8
484 // with the hardware in double speed mode.
486 //===========================================================================
488 ECHOSTATUS
C3g::Start
490 PCChannelMask pChannelMask
496 // Double speed mode?
498 pDCO
= GetDspCommObject();
499 if (pDCO
->DoubleSpeedMode())
504 // See if ADAT in 3-8 or out 3-8 are being started
506 intersect
= pChannelMask
->IsIntersectionOf( pDCO
->m_Adat38Mask
);
509 ECHO_DEBUGPRINTF(("Cannot start ADAT channels 3-8 in double speed mode\n"));
510 return ECHOSTATUS_INVALID_CHANNEL
;
514 return CEchoGals::Start(pChannelMask
);