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 few milliseconds to set up 149 // 150 m_pOsSupport->OsSnooze( 2000 ); 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 // fixme - it's pointless to return the sample rate back? 286 // 287 //=========================================================================== 288 289 DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate ) 290 { 291 DWORD dwControlReg,dwNewClock,dwBaseRate,dwFreqReg; 292 293 ECHO_DEBUGPRINTF(("3G set sample rate to %ld\n",dwNewSampleRate)); 294 295 // 296 // Only set the clock for internal mode. If the clock is not set to 297 // internal, try and re-set the input clock; this more transparently 298 // handles switching between single and double-speed mode 299 // 300 if ( GetInputClock() != ECHO_CLOCK_INTERNAL ) 301 { 302 ECHO_DEBUGPRINTF( ( "C3gDco::SetSampleRate: Cannot set sample rate - " 303 "clock not set to ECHO_CLOCK_INTERNAL\n" ) ); 304 305 // 306 // Save the rate anyhow 307 // 308 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 309 310 // 311 // Set the input clock to the current value 312 // 313 SetInputClock( m_wInputClock ); 314 315 return dwNewSampleRate; 316 } 317 318 // 319 // Get the control register & clear the appropriate bits 320 // 321 dwControlReg = GetControlRegister(); 322 dwControlReg &= E3G_CLOCK_CLEAR_MASK; 323 324 // 325 // Set the sample rate 326 // 327 switch ( dwNewSampleRate ) 328 { 329 case 96000 : 330 dwNewClock = E3G_96KHZ; 331 break; 332 333 case 88200 : 334 dwNewClock = E3G_88KHZ; 335 break; 336 337 case 48000 : 338 dwNewClock = E3G_48KHZ; 339 break; 340 341 case 44100 : 342 dwNewClock = E3G_44KHZ; 343 break; 344 345 case 32000 : 346 dwNewClock = E3G_32KHZ; 347 break; 348 349 default : 350 dwNewClock = E3G_CONTINUOUS_CLOCK; 351 if (dwNewSampleRate > 50000) 352 dwNewClock |= E3G_DOUBLE_SPEED_MODE; 353 break; 354 } 355 356 dwControlReg |= dwNewClock; 357 SetSpdifBits(&dwControlReg,dwNewSampleRate); 358 359 ECHO_DEBUGPRINTF(("\tdwNewClock 0x%lx dwControlReg 0x%lx\n",dwNewClock,dwControlReg)); 360 361 // 362 // Set up the frequency reg 363 // 364 dwBaseRate = dwNewSampleRate; 365 if (dwBaseRate > 50000) 366 dwBaseRate /= 2; 367 368 if (dwBaseRate < 32000) 369 dwBaseRate = 32000; 370 371 dwFreqReg = E3G_MAGIC_NUMBER / dwBaseRate - 2; 372 if (dwFreqReg > E3G_FREQ_REG_MAX) 373 dwFreqReg = E3G_FREQ_REG_MAX; 374 375 // 376 // Tell the DSP about it - DSP reads both control reg & freq reg 377 // 378 if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg, dwFreqReg) ) 379 { 380 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 381 382 ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: %ld clock %lx\n", dwNewSampleRate, dwControlReg) ); 383 } 384 385 return dwNewSampleRate; 386 387 } // DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate ) 388 389 390 391 //=========================================================================== 392 // 393 // SetDigitalMode 394 // 395 //=========================================================================== 396 397 ECHOSTATUS C3gDco::SetDigitalMode 398 ( 399 BYTE byNewMode 400 ) 401 { 402 DWORD dwControlReg; 403 WORD wInvalidClock; 404 405 // 406 // See if the current input clock doesn't match the new digital mode 407 // 408 switch (byNewMode) 409 { 410 case DIGITAL_MODE_SPDIF_RCA : 411 case DIGITAL_MODE_SPDIF_OPTICAL : 412 wInvalidClock = ECHO_CLOCK_ADAT; 413 break; 414 415 case DIGITAL_MODE_ADAT : 416 wInvalidClock = ECHO_CLOCK_SPDIF; 417 break; 418 419 default : 420 wInvalidClock = 0xffff; 421 break; 422 } 423 424 if (wInvalidClock == GetInputClock()) 425 { 426 SetInputClock( ECHO_CLOCK_INTERNAL ); 427 SetSampleRate( 48000 ); 428 } 429 430 431 // 432 // Clear the current digital mode 433 // 434 dwControlReg = GetControlRegister(); 435 dwControlReg &= E3G_DIGITAL_MODE_CLEAR_MASK; 436 437 // 438 // Tweak the control reg 439 // 440 switch ( byNewMode ) 441 { 442 default : 443 return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED; 444 445 case DIGITAL_MODE_SPDIF_OPTICAL : 446 dwControlReg |= E3G_SPDIF_OPTICAL_MODE; 447 // fall through 448 449 case DIGITAL_MODE_SPDIF_RCA : 450 break; 451 452 case DIGITAL_MODE_ADAT : 453 dwControlReg |= E3G_ADAT_MODE; 454 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 455 break; 456 } 457 458 // 459 // Write the control reg 460 // 461 WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE ); 462 463 m_byDigitalMode = byNewMode; 464 465 ECHO_DEBUGPRINTF( ("C3gDco::SetDigitalMode to %ld\n", 466 (DWORD) m_byDigitalMode) ); 467 468 return ECHOSTATUS_OK; 469 470 } // ECHOSTATUS C3gDco::SetDigitalMode 471 472 473 474 //=========================================================================== 475 // 476 // WriteControlReg 477 // 478 //=========================================================================== 479 480 ECHOSTATUS C3gDco::WriteControlReg 481 ( 482 DWORD dwControlReg, 483 DWORD dwFreqReg, 484 BOOL fForceWrite 485 ) 486 { 487 ECHOSTATUS Status; 488 489 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg 0x%lx 0x%lx\n",dwControlReg,dwFreqReg)); 490 491 // 492 // New value OK? 493 // 494 Status = ValidateCtrlReg(dwControlReg); 495 if (ECHOSTATUS_OK != Status) 496 return Status; 497 498 // 499 // Ready to go? 500 // 501 if ( !m_bASICLoaded ) 502 { 503 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - ASIC not loaded\n")); 504 return( ECHOSTATUS_ASIC_NOT_LOADED ); 505 } 506 507 if ( !WaitForHandshake() ) 508 { 509 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - no handshake\n")); 510 return ECHOSTATUS_DSP_DEAD; 511 } 512 513 // 514 // Write the control register 515 // 516 if ( fForceWrite || 517 (dwControlReg != GetControlRegister()) || 518 (dwFreqReg != Get3gFreqReg()) 519 ) 520 { 521 m_pDspCommPage->dw3gFreqReg = SWAP( dwFreqReg ); 522 SetControlRegister( dwControlReg ); 523 524 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: Setting 0x%lx, 0x%lx\n", 525 dwControlReg,dwFreqReg) ); 526 527 ClearHandshake(); 528 return SendVector( DSP_VC_WRITE_CONTROL_REG ); 529 } 530 else 531 { 532 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: not written, no change\n") ); 533 } 534 535 return ECHOSTATUS_OK; 536 537 } // ECHOSTATUS C3gDco::WriteControlReg 538 539 540 //=========================================================================== 541 // 542 // SetSpdifBits 543 // 544 //=========================================================================== 545 546 void C3gDco::SetSpdifBits(DWORD *pdwCtrlReg,DWORD dwSampleRate) 547 { 548 DWORD dwCtrlReg; 549 550 dwCtrlReg = *pdwCtrlReg; 551 552 // 553 // Clean out the old status bits 554 // 555 dwCtrlReg &= E3G_SPDIF_FORMAT_CLEAR_MASK; 556 557 // 558 // Sample rate 559 // 560 switch (dwSampleRate) 561 { 562 case 32000 : 563 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0 | 564 E3G_SPDIF_SAMPLE_RATE1; 565 break; 566 567 case 44100 : 568 if (m_bProfessionalSpdif) 569 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0; 570 break; 571 572 case 48000 : 573 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE1; 574 break; 575 } 576 577 // 578 // Professional mode? 579 // 580 if (m_bProfessionalSpdif) 581 dwCtrlReg |= E3G_SPDIF_PRO_MODE; 582 583 // 584 // Non-audio data? 585 // 586 if (m_bNonAudio) 587 dwCtrlReg |= E3G_SPDIF_NOT_AUDIO; 588 589 // 590 // Always stereo, 24 bit, copy permit 591 // 592 dwCtrlReg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | E3G_SPDIF_COPY_PERMIT; 593 594 *pdwCtrlReg = dwCtrlReg; 595 596 } // SetSpdifBits 597 598 599 //=========================================================================== 600 // 601 // SetSpdifOutNonAudio 602 // 603 // Set the state of the non-audio status bit in the S/PDIF out status bits 604 // 605 //=========================================================================== 606 607 void C3gDco::SetSpdifOutNonAudio(BOOL bNonAudio) 608 { 609 DWORD dwControlReg; 610 611 m_bNonAudio = bNonAudio; 612 613 dwControlReg = GetControlRegister(); 614 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate )); 615 WriteControlReg( dwControlReg, Get3gFreqReg() ); 616 } 617 618 619 //=========================================================================== 620 // 621 // Set the S/PDIF output format 622 // 623 //=========================================================================== 624 625 void C3gDco::SetProfessionalSpdif 626 ( 627 BOOL bNewStatus 628 ) 629 { 630 DWORD dwControlReg; 631 632 m_bProfessionalSpdif = bNewStatus; 633 634 dwControlReg = GetControlRegister(); 635 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate )); 636 WriteControlReg( dwControlReg, Get3gFreqReg() ); 637 638 } // void C3gDco::SetProfessionalSpdif( ... ) 639 640 641 //=========================================================================== 642 // 643 // ASIC status check 644 // 645 // 3G ASIC status check returns different values depending on what kind of box 646 // is hooked up 647 // 648 //=========================================================================== 649 650 BOOL C3gDco::CheckAsicStatus() 651 { 652 DWORD dwBoxStatus,dwBoxType; 653 654 if ( !WaitForHandshake() ) 655 return FALSE; 656 657 // 658 // Send the vector command 659 // 660 m_pDspCommPage->dwExtBoxStatus = SWAP( (DWORD) E3G_ASIC_NOT_LOADED); 661 m_bASICLoaded = FALSE; 662 ClearHandshake(); 663 SendVector( DSP_VC_TEST_ASIC ); 664 665 // 666 // Wait for return from DSP 667 // 668 if ( !WaitForHandshake() ) 669 { 670 m_pwDspCode = NULL; 671 m_ullLastLoadAttemptTime = 0; // so LoadFirmware will try again right away 672 return FALSE; 673 } 674 675 // 676 // What box type was set? 677 // 678 dwBoxStatus = SWAP(m_pDspCommPage->dwExtBoxStatus); 679 if (E3G_ASIC_NOT_LOADED == dwBoxStatus) 680 { 681 dwBoxType = NO3GBOX; 682 } 683 else 684 { 685 dwBoxType = dwBoxStatus & E3G_BOX_TYPE_MASK; 686 m_bASICLoaded = TRUE; 687 } 688 689 m_dwCurrentBoxType = dwBoxType; 690 691 // 692 // Has the box type already been set? 693 // 694 if (m_bBoxTypeSet) 695 { 696 // 697 // Did the ASIC load? 698 // Was the box type correct? 699 // 700 if ( (NO3GBOX == dwBoxType) || 701 (dwBoxType != m_dwOriginalBoxType) ) 702 { 703 //GoComatose(); 704 return FALSE; 705 } 706 707 m_bASICLoaded = TRUE; 708 return TRUE; 709 } 710 711 // 712 // First ASIC load - determine the box type and set up for that kind of box 713 // 714 m_dwOriginalBoxType = dwBoxType; 715 m_bBoxTypeSet = TRUE; 716 717 SetChannelCounts(); 718 719 // 720 // Set the bad board flag if no external box 721 // 722 if (NO3GBOX == dwBoxType) 723 m_bBadBoard = TRUE; 724 725 return m_bASICLoaded; 726 727 } // BOOL C3gDco::CheckAsicStatus() 728 729 730 //=========================================================================== 731 // 732 // SetPhantomPower 733 // 734 //=========================================================================== 735 736 void C3gDco::SetPhantomPower(BOOL fPhantom) 737 { 738 DWORD dwControlReg; 739 740 dwControlReg = GetControlRegister(); 741 if (fPhantom) 742 { 743 dwControlReg |= E3G_PHANTOM_POWER; 744 } 745 else 746 { 747 dwControlReg &= ~E3G_PHANTOM_POWER; 748 } 749 750 WriteControlReg( dwControlReg, Get3gFreqReg() ); 751 } 752 753 754 //=========================================================================== 755 // 756 // Set channel counts for the current box type 757 // 758 //=========================================================================== 759 760 void C3gDco::SetChannelCounts() 761 { 762 char *pszName; 763 WORD ch,i; 764 765 switch (m_dwOriginalBoxType) 766 { 767 case GINA3G : 768 m_wNumPipesOut = 14; 769 m_wNumPipesIn = 10; 770 m_wFirstDigitalBusOut = 6; 771 m_wFirstDigitalBusIn = 2; 772 773 pszName = "Gina3G"; 774 break; 775 776 777 case NO3GBOX : 778 case LAYLA3G : 779 default : 780 m_wNumPipesOut = 16; 781 m_wNumPipesIn = 16; 782 m_wFirstDigitalBusOut = 8; 783 m_wFirstDigitalBusIn = 8; 784 785 pszName = "Layla3G"; 786 break; 787 } 788 789 m_wNumBussesOut = m_wNumPipesOut; 790 m_wNumBussesIn = m_wNumPipesIn; 791 strcpy( m_szCardName, pszName); 792 793 // 794 // Build a channel mask for ADAT inputs & outputs 3-8 795 // OK to use bus # here since this hardware has no virtual outputs 796 // 797 m_Adat38Mask.Clear(); 798 ch = m_wFirstDigitalBusOut + 2; 799 for (i = 0; i < 6; i++) 800 { 801 m_Adat38Mask.SetIndexInMask(ch); 802 ch++; 803 } 804 805 ch += m_wFirstDigitalBusIn + 2; 806 for (i = 0; i < 6; i++) 807 { 808 m_Adat38Mask.SetIndexInMask(ch); 809 ch++; 810 } 811 } 812 813 814 //=========================================================================== 815 // 816 // Return the 3G box type 817 // 818 //=========================================================================== 819 820 void C3gDco::Get3gBoxType(DWORD *pOriginalBoxType,DWORD *pCurrentBoxType) 821 { 822 if (NULL != pOriginalBoxType) 823 *pOriginalBoxType = m_dwOriginalBoxType; 824 825 if (NULL != pCurrentBoxType) 826 { 827 CheckAsicStatus(); 828 829 *pCurrentBoxType = m_dwCurrentBoxType; 830 } 831 832 } // Get3gBoxType 833 834 835 836 //=========================================================================== 837 // 838 // Fill out an ECHOGALS_METERS struct using the current values in the 839 // comm page. This method is overridden for vmixer cards. 840 // 841 //=========================================================================== 842 843 ECHOSTATUS C3gDco::GetAudioMeters 844 ( 845 PECHOGALS_METERS pMeters 846 ) 847 { 848 pMeters->iNumPipesOut = 0; 849 pMeters->iNumPipesIn = 0; 850 851 // 852 // Output 853 // 854 DWORD dwCh = 0; 855 WORD i; 856 857 pMeters->iNumBussesOut = (INT32) m_wNumBussesOut; 858 for (i = 0; i < m_wNumBussesOut; i++) 859 { 860 pMeters->iBusOutVU[i] = 861 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) ); 862 863 pMeters->iBusOutPeak[i] = 864 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) ); 865 866 dwCh++; 867 } 868 869 pMeters->iNumBussesIn = (INT32) m_wNumBussesIn; 870 dwCh = E3G_MAX_OUTPUTS; 871 for (i = 0; i < m_wNumBussesIn; i++) 872 { 873 pMeters->iBusInVU[i] = 874 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) ); 875 pMeters->iBusInPeak[i] = 876 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) ); 877 878 dwCh++; 879 } 880 881 return ECHOSTATUS_OK; 882 883 } // GetAudioMeters 884 885 886 887 //=========================================================================== 888 // 889 // Utility function; returns TRUE if double speed mode is set 890 // 891 //=========================================================================== 892 893 BOOL C3gDco::DoubleSpeedMode(DWORD *pdwNewCtrlReg) 894 { 895 DWORD dwControlReg; 896 897 if (NULL == pdwNewCtrlReg) 898 dwControlReg = GetControlRegister(); 899 else 900 dwControlReg = *pdwNewCtrlReg; 901 902 if (0 != (dwControlReg & E3G_DOUBLE_SPEED_MODE)) 903 return TRUE; 904 905 return FALSE; 906 } 907 908 909 //=========================================================================== 910 // 911 // Utility function; validates a new control register value. Prevents 912 // speed change while transport is running 913 // 914 //=========================================================================== 915 916 ECHOSTATUS C3gDco::ValidateCtrlReg(DWORD dwNewControlReg) 917 { 918 BOOL fCurrDoubleSpeed,fNewDoubleSpeed; 919 920 // 921 // Return OK if transport is off 922 // 923 if (m_cmActive.IsEmpty()) 924 return ECHOSTATUS_OK; 925 926 // 927 // Get the new and current state of things 928 // 929 fNewDoubleSpeed = DoubleSpeedMode(&dwNewControlReg); 930 fCurrDoubleSpeed = DoubleSpeedMode(NULL); 931 932 // 933 // OK to change? 934 // 935 if (fCurrDoubleSpeed != fNewDoubleSpeed) 936 { 937 ECHO_DEBUGPRINTF(("Can't switch to speeds with transport active\n")); 938 return ECHOSTATUS_INVALID_CHANNEL; 939 } 940 941 return ECHOSTATUS_OK; 942 } 943 944 // **** C3gDco.cpp **** 945