xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/C3gDco.cpp (revision 4dd9e43637031d2c5a6755a0184040f0de8f2884)
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