1 // **************************************************************************** 2 // 3 // C3g.cpp 4 // 5 // Implementation file for the C3g driver class. 6 // Set editor tabs to 3 for your viewing pleasure. 7 // 8 // ---------------------------------------------------------------------------- 9 // 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 13 // www.echoaudio.com 14 // 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. 19 // 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. 24 // 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 28 // 29 // **************************************************************************** 30 31 #include "C3g.h" 32 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) 37 38 #define ECHO3G_DIGITAL_OUTPUT_LATENCY (1 + 32) 39 #define ECHO3G_DIGITAL_INPUT_LATENCY (1 + 32) 40 41 42 43 /**************************************************************************** 44 45 Construction and destruction 46 47 ****************************************************************************/ 48 49 //=========================================================================== 50 // 51 // Overload new & delete so memory for this object is allocated 52 // from non-paged memory. 53 // 54 //=========================================================================== 55 56 PVOID C3g::operator new( size_t Size ) 57 { 58 PVOID pMemory; 59 ECHOSTATUS Status; 60 61 Status = OsAllocateNonPaged(Size,&pMemory); 62 63 if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory )) 64 { 65 ECHO_DEBUGPRINTF(("C3g::operator new - memory allocation failed\n")); 66 67 pMemory = NULL; 68 } 69 else 70 { 71 memset( pMemory, 0, Size ); 72 } 73 74 return pMemory; 75 76 } // PVOID C3g::operator new( size_t Size ) 77 78 79 VOID C3g::operator delete( PVOID pVoid ) 80 { 81 if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) ) 82 { 83 ECHO_DEBUGPRINTF(("C3g::operator delete memory free failed\n")); 84 } 85 } // VOID C3g::operator delete( PVOID pVoid ) 86 87 88 //=========================================================================== 89 // 90 // Constructor and destructor 91 // 92 //=========================================================================== 93 94 C3g::C3g( PCOsSupport pOsSupport ) 95 : CEchoGalsMTC( pOsSupport ) 96 { 97 ECHO_DEBUGPRINTF( ( "C3g::C3g() is born!\n" ) ); 98 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; 103 } 104 105 106 C3g::~C3g() 107 { 108 ECHO_DEBUGPRINTF( ( "C3g::~C3g() is toast!\n" ) ); 109 } 110 111 112 113 114 /**************************************************************************** 115 116 Setup and hardware initialization 117 118 ****************************************************************************/ 119 120 //=========================================================================== 121 // 122 // Every card has an InitHw method 123 // 124 //=========================================================================== 125 126 ECHOSTATUS C3g::InitHw() 127 { 128 ECHOSTATUS Status; 129 WORD i; 130 131 // 132 // Call the base method 133 // 134 if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) ) 135 return Status; 136 137 // 138 // Create the DSP comm object 139 // 140 ECHO_ASSERT(NULL == m_pDspCommObject ); 141 m_pDspCommObject = new C3gDco( (PDWORD) m_pvSharedMemory, m_pOsSupport ); 142 if (NULL == m_pDspCommObject) 143 { 144 ECHO_DEBUGPRINTF(("C3g::InitHw - could not create DSP comm object\n")); 145 return ECHOSTATUS_NO_MEM; 146 } 147 148 // 149 // Load the DSP 150 // 151 DWORD dwBoxType; 152 153 GetDspCommObject()->LoadFirmware(); 154 155 GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL); 156 if (NO3GBOX == dwBoxType) 157 return ECHOSTATUS_NO_3G_BOX; 158 159 if ( GetDspCommObject()->IsBoardBad() ) 160 return ECHOSTATUS_DSP_DEAD; 161 162 // 163 // Clear the "bad board" flag; set the flags to indicate that 164 // 3G can handle super-interleave. 165 // 166 m_wFlags &= ~ECHOGALS_FLAG_BADBOARD; 167 m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK; 168 169 // 170 // Must call this here after DSP is init to 171 // init gains and mutes 172 // 173 Status = InitLineLevels(); 174 if ( ECHOSTATUS_OK != Status ) 175 return Status; 176 177 // 178 // Initialize the MIDI input 179 // 180 Status = m_MidiIn.Init( this ); 181 if ( ECHOSTATUS_OK != Status ) 182 return Status; 183 184 // 185 // Set defaults for +4/-10 186 // 187 for (i = 0; i < GetFirstDigitalBusOut(); i++ ) 188 { 189 GetDspCommObject()-> 190 SetNominalLevel( i, FALSE ); // FALSE is +4 here 191 } 192 for ( i = 0; i < GetFirstDigitalBusIn(); i++ ) 193 { 194 GetDspCommObject()-> 195 SetNominalLevel( GetNumBussesOut() + i, FALSE ); 196 } 197 198 // 199 // Set the digital mode to S/PDIF RCA 200 // 201 SetDigitalMode( DIGITAL_MODE_SPDIF_RCA ); 202 203 // 204 // Get default sample rate from DSP 205 // 206 m_dwSampleRate = GetDspCommObject()->GetSampleRate(); 207 208 ECHO_DEBUGPRINTF( ( "C3g::InitHw()\n" ) ); 209 return Status; 210 211 } // ECHOSTATUS C3g::InitHw() 212 213 214 215 216 /**************************************************************************** 217 218 Informational methods 219 220 ****************************************************************************/ 221 222 //=========================================================================== 223 // 224 // Override GetCapabilities to enumerate unique capabilties for this card 225 // 226 //=========================================================================== 227 228 ECHOSTATUS C3g::GetCapabilities 229 ( 230 PECHOGALS_CAPS pCapabilities 231 ) 232 { 233 ECHOSTATUS Status; 234 WORD i; 235 236 Status = GetBaseCapabilities(pCapabilities); 237 if ( ECHOSTATUS_OK != Status ) 238 return Status; 239 240 // 241 // Add nominal level control to all ins & outs except the universal 242 // 243 for (i = 0 ; i < pCapabilities->wNumBussesOut; i++) 244 { 245 pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL; 246 } 247 248 for (i = 2 ; i < pCapabilities->wNumBussesIn; i++) 249 { 250 pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL; 251 } 252 253 pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_SPDIF | 254 ECHO_CLOCK_BIT_ADAT | 255 ECHO_CLOCK_BIT_MTC; 256 257 // 258 // Box-specific capabilities 259 // 260 DWORD dwBoxType; 261 262 GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL); 263 switch (dwBoxType) 264 { 265 case GINA3G : 266 pCapabilities->dwBusInCaps[0] |= ECHOCAPS_PHANTOM_POWER; 267 pCapabilities->dwBusInCaps[1] |= ECHOCAPS_PHANTOM_POWER; 268 break; 269 270 case LAYLA3G : 271 pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_WORD; 272 break; 273 274 } 275 276 pCapabilities->dwOutClockTypes = 0; 277 278 return Status; 279 280 } // ECHOSTATUS C3g::GetCapabilities 281 282 283 //=========================================================================== 284 // 285 // QueryAudioSampleRate is used to find out if this card can handle a 286 // given sample rate. 287 // 288 //=========================================================================== 289 290 ECHOSTATUS C3g::QueryAudioSampleRate 291 ( 292 DWORD dwSampleRate 293 ) 294 { 295 // 296 // Check rates that are supported by continuous mode; only allow 297 // double-speed rates if not in ADAT mode 298 // 299 if ((dwSampleRate >= 32000) && (dwSampleRate <= 50000)) 300 return ECHOSTATUS_OK; 301 302 if ( (DIGITAL_MODE_ADAT != GetDigitalMode()) && 303 (dwSampleRate > 50000) && 304 (dwSampleRate <= 100000)) 305 return ECHOSTATUS_OK; 306 307 ECHO_DEBUGPRINTF(("C3g::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) ); 308 309 return ECHOSTATUS_BAD_FORMAT; 310 311 } // ECHOSTATUS C3g::QueryAudioSampleRate 312 313 314 void C3g::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate) 315 { 316 dwMinRate = 32000; 317 dwMaxRate = 96000; 318 } 319 320 321 322 //=========================================================================== 323 // 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. 327 // 328 // You should use this information to determine which clocks the user is 329 // allowed to select. 330 // 331 //=========================================================================== 332 333 ECHOSTATUS C3g::GetInputClockDetect(DWORD &dwClockDetectBits) 334 { 335 if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() ) 336 { 337 ECHO_DEBUGPRINTF( ("C3g::GetInputClockDetect: DSP Dead!\n") ); 338 return ECHOSTATUS_DSP_DEAD; 339 } 340 341 // 342 // Map the DSP clock detect bits to the generic driver clock detect bits 343 // 344 DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect(); 345 346 dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_MTC; 347 348 if (0 != (dwClocksFromDsp & E3G_CLOCK_DETECT_BIT_WORD)) 349 dwClockDetectBits |= ECHO_CLOCK_BIT_WORD; 350 351 switch (GetDigitalMode()) 352 { 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; 357 break; 358 359 case DIGITAL_MODE_ADAT : 360 if (0 != (dwClocksFromDsp & E3G_CLOCK_DETECT_BIT_ADAT)) 361 dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT; 362 break; 363 } 364 365 return ECHOSTATUS_OK; 366 367 } // GetInputClockDetect 368 369 370 //=========================================================================== 371 // 372 // Get the external box type 373 // 374 //=========================================================================== 375 376 void C3g::Get3gBoxType(DWORD *pOriginalBoxType,DWORD *pCurrentBoxType) 377 { 378 GetDspCommObject()->Get3gBoxType(pOriginalBoxType,pCurrentBoxType); 379 } 380 381 382 //=========================================================================== 383 // 384 // Get the external box name 385 // 386 //=========================================================================== 387 388 char *C3g::Get3gBoxName() 389 { 390 char *pszName; 391 DWORD dwBoxType; 392 393 GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL); 394 switch (dwBoxType) 395 { 396 case GINA3G : 397 pszName = "Gina3G"; 398 break; 399 400 case LAYLA3G : 401 pszName = "Layla3G"; 402 break; 403 404 case NO3GBOX : 405 default : 406 pszName = "Echo3G"; 407 break; 408 } 409 410 return pszName; 411 } 412 413 414 //=========================================================================== 415 // 416 // Get phantom power state for Gina3G 417 // 418 //=========================================================================== 419 420 void C3g::GetPhantomPower(BOOL *pfPhantom) 421 { 422 *pfPhantom = m_fPhantomPower; 423 } 424 425 426 //=========================================================================== 427 // 428 // Set phantom power state for Gina3G 429 // 430 //=========================================================================== 431 432 void C3g::SetPhantomPower(BOOL fPhantom) 433 { 434 DWORD dwBoxType; 435 436 GetDspCommObject()->Get3gBoxType(&dwBoxType,NULL); 437 if (GINA3G == dwBoxType) 438 { 439 GetDspCommObject()->SetPhantomPower( fPhantom ); 440 m_fPhantomPower = fPhantom; 441 } 442 } 443 444 445 //=========================================================================== 446 // 447 // GetAudioLatency - returns the latency for a single pipe 448 // 449 //=========================================================================== 450 451 void C3g::GetAudioLatency(ECHO_AUDIO_LATENCY *pLatency) 452 { 453 DWORD dwSampleRate; 454 455 // 456 // Adjust the stored latency values based on the sample rate 457 // 458 dwSampleRate = GetDspCommObject()->GetSampleRate(); 459 if (dwSampleRate <= 50000) 460 { 461 m_wAnalogOutputLatency = ECHO3G_ANALOG_OUTPUT_LATENCY_1X; 462 m_wAnalogInputLatency = ECHO3G_ANALOG_INPUT_LATENCY_1X; 463 } 464 else 465 { 466 m_wAnalogOutputLatency = ECHO3G_ANALOG_OUTPUT_LATENCY_2X; 467 m_wAnalogInputLatency = ECHO3G_ANALOG_INPUT_LATENCY_2X; 468 } 469 470 // 471 // Let the base class worry about analog vs. digital 472 // 473 CEchoGals::GetAudioLatency(pLatency); 474 475 } // GetAudioLatency 476 477 478 479 //=========================================================================== 480 // 481 // Start transport for a group of pipes 482 // 483 // Use this to make sure no one tries to start digital channels 3-8 484 // with the hardware in double speed mode. 485 // 486 //=========================================================================== 487 488 ECHOSTATUS C3g::Start 489 ( 490 PCChannelMask pChannelMask 491 ) 492 { 493 PC3gDco pDCO; 494 495 // 496 // Double speed mode? 497 // 498 pDCO = GetDspCommObject(); 499 if (pDCO->DoubleSpeedMode()) 500 { 501 BOOL intersect; 502 503 // 504 // See if ADAT in 3-8 or out 3-8 are being started 505 // 506 intersect = pChannelMask->IsIntersectionOf( pDCO->m_Adat38Mask ); 507 if (intersect) 508 { 509 ECHO_DEBUGPRINTF(("Cannot start ADAT channels 3-8 in double speed mode\n")); 510 return ECHOSTATUS_INVALID_CHANNEL; 511 } 512 } 513 514 return CEchoGals::Start(pChannelMask); 515 } 516 517 // *** C3g.cpp *** 518