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
C3gDco(PDWORD pdwRegBase,PCOsSupport pOsSupport)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
~C3gDco()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
GetDigitalModes()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
LoadASIC()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
SetInputClock(WORD wClock)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
SetSampleRate(DWORD dwNewSampleRate)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
SetDigitalMode(BYTE byNewMode)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
WriteControlReg(DWORD dwControlReg,DWORD dwFreqReg,BOOL fForceWrite)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
SetSpdifBits(DWORD * pdwCtrlReg,DWORD dwSampleRate)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
SetSpdifOutNonAudio(BOOL bNonAudio)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
SetProfessionalSpdif(BOOL bNewStatus)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
CheckAsicStatus()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
SetPhantomPower(BOOL fPhantom)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
SetChannelCounts()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
Get3gBoxType(DWORD * pOriginalBoxType,DWORD * pCurrentBoxType)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
GetAudioMeters(PECHOGALS_METERS pMeters)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
DoubleSpeedMode(DWORD * pdwNewCtrlReg)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
ValidateCtrlReg(DWORD dwNewControlReg)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