1 // **************************************************************************** 2 // 3 // C3gDco.cpp 4 // 5 // Implementation file for EchoGals generic driver 3G DSP 6 // interface class. 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 "CEchoGals.h" 32 #include "C3gDco.h" 33 34 #include "Echo3gDSP.c" 35 #include "3G_ASIC.c" 36 37 /**************************************************************************** 38 39 Construction and destruction 40 41 ****************************************************************************/ 42 43 //=========================================================================== 44 // 45 // Constructor 46 // 47 //=========================================================================== 48 49 C3gDco::C3gDco 50 ( 51 PDWORD pdwRegBase, // Virtual ptr to DSP registers 52 PCOsSupport pOsSupport 53 ) : CDspCommObject( pdwRegBase, pOsSupport ) 54 { 55 m_pdwDspRegBase = pdwRegBase; // Virtual addr DSP's register base fixme put this in base class 56 57 m_dwOriginalBoxType = NO3GBOX; 58 m_dwCurrentBoxType = m_dwOriginalBoxType; 59 SetChannelCounts(); 60 m_bBoxTypeSet = FALSE; 61 62 m_fHasVmixer = FALSE; 63 64 m_wNumMidiOut = 1; // # MIDI out channels 65 m_wNumMidiIn = 1; // # MIDI in channels 66 67 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 ); 68 m_pDspCommPage->dw3gFreqReg = SWAP( (DWORD) (E3G_MAGIC_NUMBER / 48000) - 2); 69 70 m_bHasASIC = TRUE; 71 72 m_pwDspCodeToLoad = pwEcho3gDSP; 73 74 m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA; 75 76 m_bProfessionalSpdif = FALSE; 77 m_bNonAudio = FALSE; 78 79 } // C3gDco::C3gDco( DWORD dwPhysRegBase ) 80 81 82 83 //=========================================================================== 84 // 85 // Destructor 86 // 87 //=========================================================================== 88 89 C3gDco::~C3gDco() 90 { 91 } // C3gDco::~C3gDco() 92 93 94 95 //=========================================================================== 96 // 97 // Supported digital modes depend on what kind of box you have 98 // 99 //=========================================================================== 100 101 DWORD C3gDco::GetDigitalModes() 102 { 103 DWORD dwModes; 104 105 dwModes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | 106 ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | 107 ECHOCAPS_HAS_DIGITAL_MODE_ADAT; 108 109 return dwModes; 110 } 111 112 113 /**************************************************************************** 114 115 Hardware setup and config 116 117 ****************************************************************************/ 118 119 //=========================================================================== 120 // 121 // 3G has an ASIC in the external box 122 // 123 //=========================================================================== 124 125 BOOL C3gDco::LoadASIC() 126 { 127 DWORD dwControlReg; 128 129 if ( m_bASICLoaded == TRUE ) 130 return TRUE; 131 132 ECHO_DEBUGPRINTF(("C3gDco::LoadASIC\n")); 133 134 // 135 // Give the DSP a few milliseconds to settle down 136 // 137 m_pOsSupport->OsSnooze( 2000 ); 138 139 // 140 // Load the ASIC 141 // 142 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_3G_ASIC, 143 pb3g_asic, 144 sizeof(pb3g_asic) ) ) 145 return FALSE; 146 147 // 148 // Give the ASIC a whole second to set up 149 // 150 m_pOsSupport->OsSnooze( 1000000 ); 151 152 // 153 // See if it worked 154 // 155 CheckAsicStatus(); 156 157 // 158 // Set up the control register if the load succeeded - 159 // 160 // 48 kHz, internal clock, S/PDIF RCA mode 161 // 162 if ( m_bASICLoaded ) 163 { 164 dwControlReg = E3G_48KHZ; 165 WriteControlReg( dwControlReg, E3G_FREQ_REG_DEFAULT, TRUE); // TRUE == force write 166 } 167 168 ECHO_DEBUGPRINTF(("\t3G ASIC loader finished\n")); 169 170 return m_bASICLoaded; 171 172 } // BOOL C3gDco::LoadASIC() 173 174 175 176 //=========================================================================== 177 // 178 // Set the input clock 179 // 180 //=========================================================================== 181 182 ECHOSTATUS C3gDco::SetInputClock(WORD wClock) 183 { 184 DWORD dwControlReg,dwSampleRate; 185 ECHOSTATUS Status; 186 187 ECHO_DEBUGPRINTF( ("C3gDco::SetInputClock:\n") ); 188 189 // 190 // Mask off the clock select bits 191 // 192 dwControlReg = GetControlRegister(); 193 dwControlReg &= E3G_CLOCK_CLEAR_MASK; 194 195 // 196 // New clock 197 // 198 switch (wClock) 199 { 200 case ECHO_CLOCK_INTERNAL : 201 ECHO_DEBUGPRINTF(("\tsetting internal clock\n")); 202 203 m_wInputClock = ECHO_CLOCK_INTERNAL; // prevent recursion 204 205 dwSampleRate = GetSampleRate(); 206 if ((dwSampleRate < 32000) || (dwSampleRate > 100000)) 207 dwSampleRate = 48000; 208 209 SetSampleRate(dwSampleRate); 210 return ECHOSTATUS_OK; 211 212 213 case ECHO_CLOCK_WORD: 214 dwControlReg |= E3G_WORD_CLOCK; 215 216 if ( E3G_CLOCK_DETECT_BIT_WORD96 & GetInputClockDetect() ) 217 { 218 dwControlReg |= E3G_DOUBLE_SPEED_MODE; 219 } 220 else 221 { 222 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 223 } 224 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to WORD\n" ) ); 225 break; 226 227 228 case ECHO_CLOCK_SPDIF : 229 if ( DIGITAL_MODE_ADAT == GetDigitalMode() ) 230 { 231 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 232 } 233 234 dwControlReg |= E3G_SPDIF_CLOCK; 235 if ( E3G_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() ) 236 { 237 dwControlReg |= E3G_DOUBLE_SPEED_MODE; 238 } 239 else 240 { 241 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 242 } 243 244 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to SPDIF\n" ) ); 245 break; 246 247 248 case ECHO_CLOCK_ADAT : 249 if ( DIGITAL_MODE_ADAT != GetDigitalMode() ) 250 { 251 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 252 } 253 254 dwControlReg |= E3G_ADAT_CLOCK; 255 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 256 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to ADAT\n" ) ); 257 break; 258 259 260 default : 261 ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for 3G\n",wClock)); 262 ECHO_DEBUGBREAK(); 263 return ECHOSTATUS_CLOCK_NOT_SUPPORTED; 264 } 265 266 // 267 // Winner! Try to write the hardware 268 // 269 Status = WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE ); 270 if (ECHOSTATUS_OK == Status) 271 m_wInputClock = wClock; 272 273 return Status; 274 275 } // ECHOSTATUS C3gDco::SetInputClock 276 277 278 279 //=========================================================================== 280 // 281 // SetSampleRate 282 // 283 // Set the audio sample rate for 3G 284 // 285 //=========================================================================== 286 287 DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate ) 288 { 289 DWORD dwControlReg,dwNewClock,dwBaseRate,dwFreqReg; 290 291 ECHO_DEBUGPRINTF(("3G set sample rate to %ld\n",dwNewSampleRate)); 292 293 // 294 // Only set the clock for internal mode. If the clock is not set to 295 // internal, try and re-set the input clock; this more transparently 296 // handles switching between single and double-speed mode 297 // 298 if ( GetInputClock() != ECHO_CLOCK_INTERNAL ) 299 { 300 ECHO_DEBUGPRINTF( ( "C3gDco::SetSampleRate: Cannot set sample rate - " 301 "clock not set to ECHO_CLOCK_INTERNAL\n" ) ); 302 303 // 304 // Save the rate anyhow 305 // 306 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 307 308 // 309 // Set the input clock to the current value 310 // 311 SetInputClock( m_wInputClock ); 312 313 return dwNewSampleRate; 314 } 315 316 // 317 // Get the control register & clear the appropriate bits 318 // 319 dwControlReg = GetControlRegister(); 320 dwControlReg &= E3G_CLOCK_CLEAR_MASK; 321 322 // 323 // Set the sample rate 324 // 325 switch ( dwNewSampleRate ) 326 { 327 case 96000 : 328 dwNewClock = E3G_96KHZ; 329 break; 330 331 case 88200 : 332 dwNewClock = E3G_88KHZ; 333 break; 334 335 case 48000 : 336 dwNewClock = E3G_48KHZ; 337 break; 338 339 case 44100 : 340 dwNewClock = E3G_44KHZ; 341 break; 342 343 case 32000 : 344 dwNewClock = E3G_32KHZ; 345 break; 346 347 default : 348 dwNewClock = E3G_CONTINUOUS_CLOCK; 349 if (dwNewSampleRate > 50000) 350 dwNewClock |= E3G_DOUBLE_SPEED_MODE; 351 break; 352 } 353 354 dwControlReg |= dwNewClock; 355 SetSpdifBits(&dwControlReg,dwNewSampleRate); 356 357 ECHO_DEBUGPRINTF(("\tdwNewClock 0x%lx dwControlReg 0x%lx\n",dwNewClock,dwControlReg)); 358 359 // 360 // Set up the frequency reg 361 // 362 dwBaseRate = dwNewSampleRate; 363 if (dwBaseRate > 50000) 364 dwBaseRate /= 2; 365 366 if (dwBaseRate < 32000) 367 dwBaseRate = 32000; 368 369 dwFreqReg = E3G_MAGIC_NUMBER / dwBaseRate - 2; 370 if (dwFreqReg > E3G_FREQ_REG_MAX) 371 dwFreqReg = E3G_FREQ_REG_MAX; 372 373 // 374 // Tell the DSP about it - DSP reads both control reg & freq reg 375 // 376 if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg, dwFreqReg) ) 377 { 378 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 379 380 ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: %ld clock %lx\n", dwNewSampleRate, dwControlReg) ); 381 } 382 else 383 { 384 ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: could not set sample rate %ld\n", dwNewSampleRate) ); 385 386 dwNewSampleRate = SWAP( m_pDspCommPage->dwSampleRate ); 387 } 388 389 return dwNewSampleRate; 390 391 } // DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate ) 392 393 394 395 //=========================================================================== 396 // 397 // SetDigitalMode 398 // 399 //=========================================================================== 400 401 ECHOSTATUS C3gDco::SetDigitalMode 402 ( 403 BYTE byNewMode 404 ) 405 { 406 DWORD dwControlReg; 407 WORD wInvalidClock; 408 409 // 410 // See if the current input clock doesn't match the new digital mode 411 // 412 switch (byNewMode) 413 { 414 case DIGITAL_MODE_SPDIF_RCA : 415 case DIGITAL_MODE_SPDIF_OPTICAL : 416 wInvalidClock = ECHO_CLOCK_ADAT; 417 break; 418 419 case DIGITAL_MODE_ADAT : 420 wInvalidClock = ECHO_CLOCK_SPDIF; 421 break; 422 423 default : 424 wInvalidClock = 0xffff; 425 break; 426 } 427 428 if (wInvalidClock == GetInputClock()) 429 { 430 SetInputClock( ECHO_CLOCK_INTERNAL ); 431 SetSampleRate( 48000 ); 432 } 433 434 435 // 436 // Clear the current digital mode 437 // 438 dwControlReg = GetControlRegister(); 439 dwControlReg &= E3G_DIGITAL_MODE_CLEAR_MASK; 440 441 // 442 // Tweak the control reg 443 // 444 switch ( byNewMode ) 445 { 446 default : 447 return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED; 448 449 case DIGITAL_MODE_SPDIF_OPTICAL : 450 dwControlReg |= E3G_SPDIF_OPTICAL_MODE; 451 // fall through 452 453 case DIGITAL_MODE_SPDIF_RCA : 454 break; 455 456 case DIGITAL_MODE_ADAT : 457 dwControlReg |= E3G_ADAT_MODE; 458 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 459 break; 460 } 461 462 // 463 // Write the control reg 464 // 465 WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE ); 466 467 m_byDigitalMode = byNewMode; 468 469 ECHO_DEBUGPRINTF( ("C3gDco::SetDigitalMode to %ld\n", 470 (DWORD) m_byDigitalMode) ); 471 472 return ECHOSTATUS_OK; 473 474 } // ECHOSTATUS C3gDco::SetDigitalMode 475 476 477 478 //=========================================================================== 479 // 480 // WriteControlReg 481 // 482 //=========================================================================== 483 484 ECHOSTATUS C3gDco::WriteControlReg 485 ( 486 DWORD dwControlReg, 487 DWORD dwFreqReg, 488 BOOL fForceWrite 489 ) 490 { 491 ECHOSTATUS Status; 492 493 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg 0x%lx 0x%lx\n",dwControlReg,dwFreqReg)); 494 495 // 496 // New value OK? 497 // 498 Status = ValidateCtrlReg(dwControlReg); 499 if (ECHOSTATUS_OK != Status) 500 return Status; 501 502 // 503 // Ready to go? 504 // 505 if ( !m_bASICLoaded ) 506 { 507 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - ASIC not loaded\n")); 508 return( ECHOSTATUS_ASIC_NOT_LOADED ); 509 } 510 511 if ( !WaitForHandshake() ) 512 { 513 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - no handshake\n")); 514 return ECHOSTATUS_DSP_DEAD; 515 } 516 517 // 518 // Write the control register 519 // 520 if ( fForceWrite || 521 (dwControlReg != GetControlRegister()) || 522 (dwFreqReg != Get3gFreqReg()) 523 ) 524 { 525 m_pDspCommPage->dw3gFreqReg = SWAP( dwFreqReg ); 526 SetControlRegister( dwControlReg ); 527 528 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: Setting 0x%lx, 0x%lx\n", 529 dwControlReg,dwFreqReg) ); 530 531 ClearHandshake(); 532 return SendVector( DSP_VC_WRITE_CONTROL_REG ); 533 } 534 else 535 { 536 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: not written, no change\n") ); 537 } 538 539 return ECHOSTATUS_OK; 540 541 } // ECHOSTATUS C3gDco::WriteControlReg 542 543 544 //=========================================================================== 545 // 546 // SetSpdifBits 547 // 548 //=========================================================================== 549 550 void C3gDco::SetSpdifBits(DWORD *pdwCtrlReg,DWORD dwSampleRate) 551 { 552 DWORD dwCtrlReg; 553 554 dwCtrlReg = *pdwCtrlReg; 555 556 // 557 // Clean out the old status bits 558 // 559 dwCtrlReg &= E3G_SPDIF_FORMAT_CLEAR_MASK; 560 561 // 562 // Sample rate 563 // 564 switch (dwSampleRate) 565 { 566 case 32000 : 567 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0 | 568 E3G_SPDIF_SAMPLE_RATE1; 569 break; 570 571 case 44100 : 572 if (m_bProfessionalSpdif) 573 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0; 574 break; 575 576 case 48000 : 577 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE1; 578 break; 579 } 580 581 // 582 // Professional mode? 583 // 584 if (m_bProfessionalSpdif) 585 dwCtrlReg |= E3G_SPDIF_PRO_MODE; 586 587 // 588 // Non-audio data? 589 // 590 if (m_bNonAudio) 591 dwCtrlReg |= E3G_SPDIF_NOT_AUDIO; 592 593 // 594 // Always stereo, 24 bit, copy permit 595 // 596 dwCtrlReg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | E3G_SPDIF_COPY_PERMIT; 597 598 *pdwCtrlReg = dwCtrlReg; 599 600 } // SetSpdifBits 601 602 603 //=========================================================================== 604 // 605 // SetSpdifOutNonAudio 606 // 607 // Set the state of the non-audio status bit in the S/PDIF out status bits 608 // 609 //=========================================================================== 610 611 void C3gDco::SetSpdifOutNonAudio(BOOL bNonAudio) 612 { 613 DWORD dwControlReg; 614 615 m_bNonAudio = bNonAudio; 616 617 dwControlReg = GetControlRegister(); 618 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate )); 619 WriteControlReg( dwControlReg, Get3gFreqReg() ); 620 } 621 622 623 //=========================================================================== 624 // 625 // Set the S/PDIF output format 626 // 627 //=========================================================================== 628 629 void C3gDco::SetProfessionalSpdif 630 ( 631 BOOL bNewStatus 632 ) 633 { 634 DWORD dwControlReg; 635 636 m_bProfessionalSpdif = bNewStatus; 637 638 dwControlReg = GetControlRegister(); 639 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate )); 640 WriteControlReg( dwControlReg, Get3gFreqReg() ); 641 642 } // void C3gDco::SetProfessionalSpdif( ... ) 643 644 645 //=========================================================================== 646 // 647 // ASIC status check 648 // 649 // 3G ASIC status check returns different values depending on what kind of box 650 // is hooked up 651 // 652 //=========================================================================== 653 654 BOOL C3gDco::CheckAsicStatus() 655 { 656 DWORD dwBoxStatus,dwBoxType; 657 658 if ( !WaitForHandshake() ) 659 { 660 ECHO_DEBUGPRINTF(("CheckAsicStatus - no handshake!\n")); 661 return FALSE; 662 } 663 664 // 665 // Send the vector command 666 // 667 m_pDspCommPage->dwExtBoxStatus = SWAP( (DWORD) E3G_ASIC_NOT_LOADED); 668 m_bASICLoaded = FALSE; 669 ClearHandshake(); 670 SendVector( DSP_VC_TEST_ASIC ); 671 672 // 673 // Wait for return from DSP 674 // 675 if ( !WaitForHandshake() ) 676 { 677 ECHO_DEBUGPRINTF(("CheckAsicStatus - no handshake after VC\n")); 678 m_pwDspCode = NULL; 679 m_ullLastLoadAttemptTime = 0; // so LoadFirmware will try again right away 680 return FALSE; 681 } 682 683 // 684 // What box type was set? 685 // 686 dwBoxStatus = SWAP(m_pDspCommPage->dwExtBoxStatus); 687 if (E3G_ASIC_NOT_LOADED == dwBoxStatus) 688 { 689 ECHO_DEBUGPRINTF(("CheckAsicStatus - ASIC not loaded\n")); 690 dwBoxType = NO3GBOX; 691 } 692 else 693 { 694 dwBoxType = dwBoxStatus & E3G_BOX_TYPE_MASK; 695 m_bASICLoaded = TRUE; 696 ECHO_DEBUGPRINTF(("CheckAsicStatus - read box type %x\n",dwBoxType)); 697 } 698 699 m_dwCurrentBoxType = dwBoxType; 700 701 // 702 // Has the box type already been set? 703 // 704 if (m_bBoxTypeSet) 705 { 706 // 707 // Did the ASIC load? 708 // Was the box type correct? 709 // 710 if ( (NO3GBOX == dwBoxType) || 711 (dwBoxType != m_dwOriginalBoxType) ) 712 { 713 ECHO_DEBUGPRINTF(("CheckAsicStatus - box type mismatch - original %x, got %x\n",m_dwOriginalBoxType,dwBoxType)); 714 return FALSE; 715 } 716 717 ECHO_DEBUGPRINTF(("CheckAsicStatus - ASIC ok\n")); 718 m_bASICLoaded = TRUE; 719 return TRUE; 720 } 721 722 // 723 // First ASIC load - determine the box type and set up for that kind of box 724 // 725 m_dwOriginalBoxType = dwBoxType; 726 m_bBoxTypeSet = TRUE; 727 728 SetChannelCounts(); 729 730 // 731 // Set the bad board flag if no external box 732 // 733 if (NO3GBOX == dwBoxType) 734 { 735 ECHO_DEBUGPRINTF(("CheckAsicStatus - no external box\n")); 736 m_bBadBoard = TRUE; 737 } 738 739 return m_bASICLoaded; 740 741 } // BOOL C3gDco::CheckAsicStatus() 742 743 744 //=========================================================================== 745 // 746 // SetPhantomPower 747 // 748 //=========================================================================== 749 750 void C3gDco::SetPhantomPower(BOOL fPhantom) 751 { 752 DWORD dwControlReg; 753 754 dwControlReg = GetControlRegister(); 755 if (fPhantom) 756 { 757 dwControlReg |= E3G_PHANTOM_POWER; 758 } 759 else 760 { 761 dwControlReg &= ~E3G_PHANTOM_POWER; 762 } 763 764 WriteControlReg( dwControlReg, Get3gFreqReg() ); 765 } 766 767 768 //=========================================================================== 769 // 770 // Set channel counts for the current box type 771 // 772 //=========================================================================== 773 774 void C3gDco::SetChannelCounts() 775 { 776 char *pszName; 777 WORD ch,i; 778 779 switch (m_dwOriginalBoxType) 780 { 781 case GINA3G : 782 m_wNumPipesOut = 14; 783 m_wNumPipesIn = 10; 784 m_wFirstDigitalBusOut = 6; 785 m_wFirstDigitalBusIn = 2; 786 787 pszName = "Gina3G"; 788 break; 789 790 791 case NO3GBOX : 792 case LAYLA3G : 793 default : 794 m_wNumPipesOut = 16; 795 m_wNumPipesIn = 16; 796 m_wFirstDigitalBusOut = 8; 797 m_wFirstDigitalBusIn = 8; 798 799 pszName = "Layla3G"; 800 break; 801 } 802 803 m_wNumBussesOut = m_wNumPipesOut; 804 m_wNumBussesIn = m_wNumPipesIn; 805 strcpy( m_szCardName, pszName); 806 807 // 808 // Build a channel mask for ADAT inputs & outputs 3-8 809 // OK to use bus # here since this hardware has no virtual outputs 810 // 811 m_Adat38Mask.Clear(); 812 ch = m_wFirstDigitalBusOut + 2; 813 for (i = 0; i < 6; i++) 814 { 815 m_Adat38Mask.SetIndexInMask(ch); 816 ch++; 817 } 818 819 ch += m_wFirstDigitalBusIn + 2; 820 for (i = 0; i < 6; i++) 821 { 822 m_Adat38Mask.SetIndexInMask(ch); 823 ch++; 824 } 825 } 826 827 828 //=========================================================================== 829 // 830 // Return the 3G box type 831 // 832 //=========================================================================== 833 834 void C3gDco::Get3gBoxType(DWORD *pOriginalBoxType,DWORD *pCurrentBoxType) 835 { 836 if (NULL != pOriginalBoxType) 837 *pOriginalBoxType = m_dwOriginalBoxType; 838 839 if (NULL != pCurrentBoxType) 840 { 841 CheckAsicStatus(); 842 843 *pCurrentBoxType = m_dwCurrentBoxType; 844 } 845 846 } // Get3gBoxType 847 848 849 850 //=========================================================================== 851 // 852 // Fill out an ECHOGALS_METERS struct using the current values in the 853 // comm page. This method is overridden for vmixer cards. 854 // 855 //=========================================================================== 856 857 ECHOSTATUS C3gDco::GetAudioMeters 858 ( 859 PECHOGALS_METERS pMeters 860 ) 861 { 862 pMeters->iNumPipesOut = 0; 863 pMeters->iNumPipesIn = 0; 864 865 // 866 // Output 867 // 868 DWORD dwCh = 0; 869 WORD i; 870 871 pMeters->iNumBussesOut = (INT32) m_wNumBussesOut; 872 for (i = 0; i < m_wNumBussesOut; i++) 873 { 874 pMeters->iBusOutVU[i] = 875 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) ); 876 877 pMeters->iBusOutPeak[i] = 878 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) ); 879 880 dwCh++; 881 } 882 883 pMeters->iNumBussesIn = (INT32) m_wNumBussesIn; 884 dwCh = E3G_MAX_OUTPUTS; 885 for (i = 0; i < m_wNumBussesIn; i++) 886 { 887 pMeters->iBusInVU[i] = 888 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) ); 889 pMeters->iBusInPeak[i] = 890 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) ); 891 892 dwCh++; 893 } 894 895 return ECHOSTATUS_OK; 896 897 } // GetAudioMeters 898 899 900 901 //=========================================================================== 902 // 903 // Utility function; returns TRUE if double speed mode is set 904 // 905 //=========================================================================== 906 907 BOOL C3gDco::DoubleSpeedMode(DWORD *pdwNewCtrlReg) 908 { 909 DWORD dwControlReg; 910 911 if (NULL == pdwNewCtrlReg) 912 dwControlReg = GetControlRegister(); 913 else 914 dwControlReg = *pdwNewCtrlReg; 915 916 if (0 != (dwControlReg & E3G_DOUBLE_SPEED_MODE)) 917 return TRUE; 918 919 return FALSE; 920 } 921 922 923 //=========================================================================== 924 // 925 // Utility function; validates a new control register value. Prevents 926 // speed change while transport is running 927 // 928 //=========================================================================== 929 930 ECHOSTATUS C3gDco::ValidateCtrlReg(DWORD dwNewControlReg) 931 { 932 BOOL fCurrDoubleSpeed,fNewDoubleSpeed; 933 934 // 935 // Return OK if transport is off 936 // 937 if (m_cmActive.IsEmpty()) 938 return ECHOSTATUS_OK; 939 940 // 941 // Get the new and current state of things 942 // 943 fNewDoubleSpeed = DoubleSpeedMode(&dwNewControlReg); 944 fCurrDoubleSpeed = DoubleSpeedMode(NULL); 945 946 // 947 // OK to change? 948 // 949 if (fCurrDoubleSpeed != fNewDoubleSpeed) 950 { 951 ECHO_DEBUGPRINTF(("Can't switch to speeds with transport active\n")); 952 return ECHOSTATUS_INVALID_CHANNEL; 953 } 954 955 return ECHOSTATUS_OK; 956 } 957 958 // **** C3gDco.cpp **** 959