1 // **************************************************************************** 2 // 3 // CMonaDspCommObject.cpp 4 // 5 // Implementation file for EchoGals generic driver Darla 24 DSP 6 // interface class. 7 // 8 // Copyright Echo Digital Audio Corporation (c) 1998 - 2002 9 // All rights reserved 10 // www.echoaudio.com 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining a 13 // copy of this software and associated documentation files (the 14 // "Software"), to deal with the Software without restriction, including 15 // without limitation the rights to use, copy, modify, merge, publish, 16 // distribute, sublicense, and/or sell copies of the Software, and to 17 // permit persons to whom the Software is furnished to do so, subject to 18 // the following conditions: 19 // 20 // - Redistributions of source code must retain the above copyright 21 // notice, this list of conditions and the following disclaimers. 22 // 23 // - Redistributions in binary form must reproduce the above copyright 24 // notice, this list of conditions and the following disclaimers in the 25 // documentation and/or other materials provided with the distribution. 26 // 27 // - Neither the name of Echo Digital Audio, nor the names of its 28 // contributors may be used to endorse or promote products derived from 29 // this Software without specific prior written permission. 30 // 31 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 34 // IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR 35 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 36 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 37 // SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. 38 // 39 // **************************************************************************** 40 41 #include "CEchoGals.h" 42 #include "CMonaDspCommObject.h" 43 44 #include "MonaDSP.c" 45 #include "Mona361DSP.c" 46 47 #include "Mona1ASIC48.c" 48 #include "Mona1ASIC96.c" 49 #include "Mona1ASIC48_361.c" 50 #include "Mona1ASIC96_361.c" 51 #include "Mona2ASIC.c" 52 53 54 /**************************************************************************** 55 56 Construction and destruction 57 58 ****************************************************************************/ 59 60 //=========================================================================== 61 // 62 // Constructor 63 // 64 //=========================================================================== 65 66 CMonaDspCommObject::CMonaDspCommObject 67 ( 68 PDWORD pdwRegBase, // Virtual ptr to DSP registers 69 PCOsSupport pOsSupport 70 ) : CGMLDspCommObject( pdwRegBase, pOsSupport ) 71 { 72 strcpy( m_szCardName, "Mona" ); 73 m_pdwDspRegBase = pdwRegBase; // Virtual addr DSP's register base 74 75 m_wNumPipesOut = 14; 76 m_wNumPipesIn = 12; 77 m_wNumBussesOut = 14; 78 m_wNumBussesIn = 12; 79 m_wFirstDigitalBusOut = 6; 80 m_wFirstDigitalBusIn = 4; 81 82 m_bProfessionalSpdif = FALSE; 83 84 m_fHasVmixer = FALSE; 85 86 m_wNumMidiOut = 0; // # MIDI out channels 87 m_wNumMidiIn = 0; // # MIDI in channels 88 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 44100 ); 89 // Need this in cse we start with ESYNC 90 m_bHasASIC = TRUE; 91 if ( DEVICE_ID_56361 == pOsSupport->GetDeviceId() ) 92 m_pwDspCodeToLoad = pwMona361DSP; 93 else 94 95 m_pwDspCodeToLoad = pwMonaDSP; 96 97 m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA; 98 } // CMonaDspCommObject::CMonaDspCommObject( DWORD dwPhysRegBase ) 99 100 101 //=========================================================================== 102 // 103 // Destructor 104 // 105 //=========================================================================== 106 107 CMonaDspCommObject::~CMonaDspCommObject() 108 { 109 } // CMonaDspCommObject::~CMonaDspCommObject() 110 111 112 113 114 /**************************************************************************** 115 116 Hardware setup and config 117 118 ****************************************************************************/ 119 120 //=========================================================================== 121 // 122 // Mona has an ASIC on the PCI card and another ASIC in the external box; 123 // both need to be loaded. 124 // 125 //=========================================================================== 126 127 BOOL CMonaDspCommObject::LoadASIC() 128 { 129 DWORD dwControlReg; 130 PBYTE pbAsic1; 131 DWORD dwSize; 132 133 if ( m_bASICLoaded ) 134 return TRUE; 135 136 m_pOsSupport->OsSnooze( 10000 ); 137 138 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() ) 139 { 140 pbAsic1 = pbMona1ASIC48_361; 141 dwSize = sizeof( pbMona1ASIC48_361 ); 142 } 143 else 144 { 145 pbAsic1 = pbMona1ASIC48; 146 dwSize = sizeof( pbMona1ASIC48 ); 147 } 148 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, 149 pbAsic1, 150 dwSize ) ) 151 return FALSE; 152 153 m_pbyAsic = pbAsic1; 154 155 m_pOsSupport->OsSnooze( 10000 ); 156 157 // Do the external one 158 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_MONA_EXTERNAL_ASIC, 159 pbMona2ASIC, 160 sizeof( pbMona2ASIC ) ) ) 161 return FALSE; 162 163 m_pOsSupport->OsSnooze( 10000 ); 164 165 CheckAsicStatus(); 166 167 // 168 // Set up the control register if the load succeeded - 169 // 170 // 48 kHz, internal clock, S/PDIF RCA mode 171 // 172 if ( m_bASICLoaded ) 173 { 174 dwControlReg = GML_CONVERTER_ENABLE | GML_48KHZ; 175 WriteControlReg( dwControlReg ); 176 } 177 178 return m_bASICLoaded; 179 180 } // BOOL CMonaDspCommObject::LoadASIC() 181 182 183 //=========================================================================== 184 // 185 // Depending on what digital mode you want, Mona needs different ASICs 186 // loaded. This function checks the ASIC needed for the new mode and sees 187 // if it matches the one already loaded. 188 // 189 //=========================================================================== 190 191 BOOL CMonaDspCommObject::SwitchAsic( DWORD dwMask96 ) 192 { 193 BYTE * pbyAsicNeeded; 194 DWORD dwAsicSize; 195 196 // 197 // Check the clock detect bits to see if this is 198 // a single-speed clock or a double-speed clock; load 199 // a new ASIC if necessary. 200 // 201 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() ) 202 { 203 pbyAsicNeeded = pbMona1ASIC48_361; 204 dwAsicSize = sizeof( pbMona1ASIC48_361 ); 205 if ( 0 != ( dwMask96 & GetInputClockDetect() ) ) 206 { 207 pbyAsicNeeded = pbMona1ASIC96_361; 208 dwAsicSize = sizeof( pbMona1ASIC96_361 ); 209 } 210 } 211 else 212 { 213 pbyAsicNeeded = pbMona1ASIC48; 214 dwAsicSize = sizeof( pbMona1ASIC48 ); 215 if ( 0 != ( dwMask96 & GetInputClockDetect() ) ) 216 { 217 pbyAsicNeeded = pbMona1ASIC96; 218 dwAsicSize = sizeof( pbMona1ASIC96 ); 219 } 220 } 221 222 if ( pbyAsicNeeded != m_pbyAsic ) 223 { 224 // 225 // Load the desired ASIC 226 // 227 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, 228 pbyAsicNeeded, 229 dwAsicSize ) ) 230 return FALSE; 231 232 m_pbyAsic = pbyAsicNeeded; 233 } 234 235 return TRUE; 236 237 } // BOOL CMonaDspCommObject::SwitchAsic( DWORD dwMask96 ) 238 239 240 //=========================================================================== 241 // 242 // SetInputClock 243 // 244 //=========================================================================== 245 246 ECHOSTATUS CMonaDspCommObject::SetInputClock(WORD wClock) 247 { 248 BOOL bSetRate; 249 BOOL bWriteControlReg; 250 DWORD dwControlReg, dwSampleRate; 251 252 ECHO_DEBUGPRINTF( ("CMonaDspCommObject::SetInputClock:\n") ); 253 254 dwControlReg = GetControlRegister(); 255 256 // 257 // Mask off the clock select bits 258 // 259 dwControlReg &= GML_CLOCK_CLEAR_MASK; 260 dwSampleRate = GetSampleRate(); 261 262 bSetRate = FALSE; 263 bWriteControlReg = TRUE; 264 switch ( wClock ) 265 { 266 case ECHO_CLOCK_INTERNAL : 267 { 268 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to INTERNAL\n" ) ); 269 270 // If the sample rate is out of range for some reason, set it 271 // to a reasonable value. mattg 272 if ( ( dwSampleRate < 8000 ) || 273 ( dwSampleRate > 96000 ) ) 274 { 275 dwSampleRate = 48000; 276 } 277 278 bSetRate = TRUE; 279 bWriteControlReg = FALSE; 280 281 break; 282 } // CLK_CLOCKININTERNAL 283 284 case ECHO_CLOCK_SPDIF : 285 { 286 if ( DIGITAL_MODE_ADAT == GetDigitalMode() ) 287 { 288 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 289 } 290 291 if ( FALSE == SwitchAsic( GML_CLOCK_DETECT_BIT_SPDIF96 ) ) 292 { 293 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 294 } 295 296 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to SPDIF\n" ) ); 297 298 dwControlReg |= GML_SPDIF_CLOCK; 299 300 if ( GML_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() ) 301 { 302 dwControlReg |= GML_DOUBLE_SPEED_MODE; 303 } 304 else 305 { 306 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 307 } 308 break; 309 } // CLK_CLOCKINSPDIF 310 311 case ECHO_CLOCK_WORD : 312 { 313 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to WORD\n" ) ); 314 315 if ( FALSE == SwitchAsic( GML_CLOCK_DETECT_BIT_WORD96 ) ) 316 { 317 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 318 } 319 320 dwControlReg |= GML_WORD_CLOCK; 321 322 if ( GML_CLOCK_DETECT_BIT_WORD96 & GetInputClockDetect() ) 323 { 324 dwControlReg |= GML_DOUBLE_SPEED_MODE; 325 } 326 else 327 { 328 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 329 } 330 break; 331 } // CLK_CLOCKINWORD 332 333 case ECHO_CLOCK_ADAT : 334 { 335 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to ADAT\n" ) ); 336 337 if ( DIGITAL_MODE_ADAT != GetDigitalMode() ) 338 { 339 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 340 } 341 342 dwControlReg |= GML_ADAT_CLOCK; 343 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 344 break; 345 } // CLK_CLOCKINADAT 346 347 default : 348 ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for Mona\n",wClock)); 349 ECHO_DEBUGBREAK(); 350 return ECHOSTATUS_CLOCK_NOT_SUPPORTED; 351 } // switch (wClock) 352 353 // 354 // Winner! Save the new input clock. 355 // 356 m_wInputClock = wClock; 357 358 // 359 // Do things according to the flags 360 // 361 if ( bWriteControlReg ) 362 { 363 WriteControlReg( dwControlReg ); 364 } 365 366 // Set Mona sample rate to something sane if word or superword is 367 // being turned off 368 if ( bSetRate ) 369 { 370 SetSampleRate( GetSampleRate() ); 371 } 372 373 return ECHOSTATUS_OK; 374 375 } // ECHOSTATUS CMonaDspCommObject::SetInputClock 376 377 378 379 //=========================================================================== 380 // 381 // SetSampleRate 382 // 383 // Set the audio sample rate for CMona 384 // 385 //=========================================================================== 386 387 DWORD CMonaDspCommObject::SetSampleRate( DWORD dwNewSampleRate ) 388 { 389 BYTE *pbyAsicNeeded; 390 DWORD dwAsicSize, dwControlReg, dwNewClock; 391 392 // 393 // Only set the clock for internal mode. If the clock is not set to 394 // internal, try and re-set the input clock; this more transparently 395 // handles switching between single and double-speed mode 396 // 397 if ( GetInputClock() != ECHO_CLOCK_INTERNAL ) 398 { 399 ECHO_DEBUGPRINTF( ( "CMonaDspCommObject::SetSampleRate: Cannot set sample rate - " 400 "clock not set to CLK_CLOCKININTERNAL\n" ) ); 401 402 // 403 // Save the rate anyhow 404 // 405 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 406 407 // 408 // Set the input clock to the current value 409 // 410 SetInputClock( m_wInputClock ); 411 412 return GetSampleRate(); 413 } 414 415 // 416 // Now, check to see if the required ASIC is loaded 417 // 418 if ( dwNewSampleRate >= 88200 ) 419 { 420 if ( DIGITAL_MODE_ADAT == GetDigitalMode() ) 421 return( GetSampleRate() ); 422 423 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() ) 424 { 425 pbyAsicNeeded = pbMona1ASIC96_361; 426 dwAsicSize = sizeof(pbMona1ASIC96_361); 427 } 428 else 429 { 430 pbyAsicNeeded = pbMona1ASIC96; 431 dwAsicSize = sizeof(pbMona1ASIC96); 432 } 433 } 434 else 435 { 436 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() ) 437 { 438 pbyAsicNeeded = pbMona1ASIC48_361; 439 dwAsicSize = sizeof(pbMona1ASIC48_361); 440 } 441 else 442 { 443 pbyAsicNeeded = pbMona1ASIC48; 444 dwAsicSize = sizeof(pbMona1ASIC48); 445 } 446 } 447 448 if ( pbyAsicNeeded != m_pbyAsic ) 449 { 450 // 451 // Load the desired ASIC 452 // 453 if ( FALSE == CDspCommObject::LoadASIC 454 ( DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, 455 pbyAsicNeeded, 456 dwAsicSize ) ) 457 return( GetSampleRate() ); 458 459 m_pbyAsic = pbyAsicNeeded; 460 } 461 462 // 463 // Get the new control register value 464 // 465 dwNewClock = 0; 466 467 dwControlReg = GetControlRegister(); 468 dwControlReg &= GML_CLOCK_CLEAR_MASK; 469 dwControlReg &= GML_SPDIF_RATE_CLEAR_MASK; 470 471 switch ( dwNewSampleRate ) 472 { 473 case 96000 : 474 dwNewClock = GML_96KHZ; 475 break; 476 477 case 88200 : 478 dwNewClock = GML_88KHZ; 479 break; 480 481 case 48000 : 482 dwNewClock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; 483 break; 484 485 case 44100 : 486 dwNewClock = GML_44KHZ; 487 // 488 // Professional mode 489 // 490 if ( dwControlReg & GML_SPDIF_PRO_MODE ) 491 { 492 dwNewClock |= GML_SPDIF_SAMPLE_RATE0; 493 } 494 break; 495 496 case 32000 : 497 dwNewClock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | GML_SPDIF_SAMPLE_RATE1; 498 break; 499 500 case 22050 : 501 dwNewClock = GML_22KHZ; 502 break; 503 504 case 16000 : 505 dwNewClock = GML_16KHZ; 506 break; 507 508 case 11025 : 509 dwNewClock = GML_11KHZ; 510 break; 511 512 case 8000 : 513 dwNewClock = GML_8KHZ; 514 break; 515 } 516 517 dwControlReg |= dwNewClock; 518 519 // 520 // Send the new value to the card 521 // 522 if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg ) ) 523 { 524 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 525 526 ECHO_DEBUGPRINTF( ("CMonaDspCommObject::SetSampleRate: %ld " 527 "clock %ld\n", dwNewSampleRate, dwNewClock) ); 528 } 529 530 return GetSampleRate(); 531 532 } // DWORD CMonaDspCommObject::SetSampleRate( DWORD dwNewSampleRate ) 533 534 535 //=========================================================================== 536 // 537 // Set digital mode 538 // 539 //=========================================================================== 540 541 ECHOSTATUS CMonaDspCommObject::SetDigitalMode 542 ( 543 BYTE byNewMode 544 ) 545 { 546 DWORD dwControlReg; 547 548 dwControlReg = GetControlRegister(); 549 // 550 // Clear the current digital mode 551 // 552 dwControlReg &= GML_DIGITAL_MODE_CLEAR_MASK; 553 554 // 555 // Tweak the control reg 556 // 557 switch ( byNewMode ) 558 { 559 default : 560 return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED; 561 562 case DIGITAL_MODE_SPDIF_OPTICAL : 563 564 dwControlReg |= GML_SPDIF_OPTICAL_MODE; 565 566 // fall through 567 568 case DIGITAL_MODE_SPDIF_RCA : 569 570 // 571 // If the input clock is set to ADAT, set the 572 // input clock to internal and the sample rate to 48 KHz 573 // 574 if ( ECHO_CLOCK_ADAT == GetInputClock() ) 575 { 576 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 ); 577 SetInputClock( ECHO_CLOCK_INTERNAL ); 578 } 579 580 break; 581 582 case DIGITAL_MODE_ADAT : 583 584 // 585 // If the input clock is set to S/PDIF, set the 586 // input clock to internal and the sample rate to 48 KHz 587 // 588 if ( ECHO_CLOCK_SPDIF == GetInputClock() ) 589 { 590 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 ); 591 SetInputClock( ECHO_CLOCK_INTERNAL ); 592 } 593 594 // 595 // If the current ASIC is the 96KHz ASIC, switch 596 // the ASIC and set to 48 KHz 597 // 598 if ( ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() && 599 pbMona1ASIC96_361 == m_pbyAsic ) || 600 ( DEVICE_ID_56301 == m_pOsSupport->GetDeviceId() && 601 pbMona1ASIC96 == m_pbyAsic ) ) 602 { 603 SetSampleRate( 48000 ); 604 } 605 606 dwControlReg |= GML_ADAT_MODE; 607 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 608 break; 609 } 610 611 // 612 // Write the control reg 613 // 614 WriteControlReg( dwControlReg ); 615 616 m_byDigitalMode = byNewMode; 617 618 ECHO_DEBUGPRINTF( ("CMonaDspCommObject::SetDigitalMode to %ld\n", 619 (DWORD) m_byDigitalMode) ); 620 621 return ECHOSTATUS_OK; 622 623 } // ECHOSTATUS CMonaDspCommObject::SetDigitalMode 624 625 626 // **** CMonaDspCommObject.cpp **** 627