1// ****************************************************************************
2//
3//		CLayla.cpp
4//
5//		Implementation file for the CLayla driver class; this is for 20-bit
6//		Layla.
7//
8//		Set editor tabs to 3 for your viewing pleasure.
9//
10// ----------------------------------------------------------------------------
11//
12// This file is part of Echo Digital Audio's generic driver library.
13// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
14// All rights reserved
15// www.echoaudio.com
16//
17// This library is free software; you can redistribute it and/or
18// modify it under the terms of the GNU Lesser General Public
19// License as published by the Free Software Foundation; either
20// version 2.1 of the License, or (at your option) any later version.
21//
22// This library is distributed in the hope that it will be useful,
23// but WITHOUT ANY WARRANTY; without even the implied warranty of
24// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25// Lesser General Public License for more details.
26//
27// You should have received a copy of the GNU Lesser General Public
28// License along with this library; if not, write to the Free Software
29// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30//
31// ****************************************************************************
32
33#include "CLayla.h"
34
35#define LAYLA20_ANALOG_OUTPUT_LATENCY		57
36#define LAYLA20_ANALOG_INPUT_LATENCY		64
37#define LAYLA20_DIGITAL_OUTPUT_LATENCY		32
38#define LAYLA20_DIGITAL_INPUT_LATENCY		32
39
40
41/****************************************************************************
42
43	Construction and destruction
44
45 ****************************************************************************/
46
47//===========================================================================
48//
49// Overload new & delete so memory for this object is allocated
50//	from non-paged memory.
51//
52//===========================================================================
53
54PVOID CLayla::operator new( size_t Size )
55{
56	PVOID 		pMemory;
57	ECHOSTATUS 	Status;
58
59	Status = OsAllocateNonPaged(Size,&pMemory);
60
61	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
62	{
63		ECHO_DEBUGPRINTF(("CLayla::operator new - memory allocation failed\n"));
64
65		pMemory = NULL;
66	}
67	else
68	{
69		memset( pMemory, 0, Size );
70	}
71
72	return pMemory;
73
74}	// PVOID CLayla::operator new( size_t Size )
75
76
77VOID  CLayla::operator delete( PVOID pVoid )
78{
79	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
80	{
81		ECHO_DEBUGPRINTF( ("CLayla::operator delete memory free failed\n") );
82	}
83}	// VOID  CLayla::operator delete( PVOID pVoid )
84
85
86//===========================================================================
87//
88// Constructor and destructor
89//
90//===========================================================================
91
92CLayla::CLayla( PCOsSupport pOsSupport )
93		 : CEchoGalsMTC( pOsSupport )
94{
95	ECHO_DEBUGPRINTF( ( "CLayla::CLayla() is born!\n" ) );
96
97	m_wAnalogOutputLatency = LAYLA20_ANALOG_OUTPUT_LATENCY;
98	m_wAnalogInputLatency = LAYLA20_ANALOG_INPUT_LATENCY;
99	m_wDigitalOutputLatency = LAYLA20_DIGITAL_OUTPUT_LATENCY;
100	m_wDigitalInputLatency = LAYLA20_DIGITAL_INPUT_LATENCY;
101
102}	// CLayla::CLayla()
103
104
105CLayla::~CLayla()
106{
107	ECHO_DEBUGPRINTF( ( "CLayla::~CLayla() is toast!\n" ) );
108}	// CLayla::~CLayla()
109
110
111
112
113/****************************************************************************
114
115	Setup and hardware initialization
116
117 ****************************************************************************/
118
119//===========================================================================
120//
121// Every card has an InitHw method
122//
123//===========================================================================
124
125ECHOSTATUS CLayla::InitHw()
126{
127	ECHOSTATUS	Status;
128	WORD			i;
129
130	//
131	// Call the base method
132	//
133	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
134		return Status;
135
136	//
137	// Create the DSP comm object
138	//
139	ECHO_ASSERT(NULL == m_pDspCommObject );
140	m_pDspCommObject = new CLaylaDspCommObject( (PDWORD) m_pvSharedMemory,
141																m_pOsSupport );
142	if (NULL == m_pDspCommObject)
143	{
144		ECHO_DEBUGPRINTF(("CLayla::InitHw - could not create DSP comm object\n"));
145		return ECHOSTATUS_NO_MEM;
146	}
147
148	//
149	// Load the DSP and the external box ASIC
150	//
151	GetDspCommObject()->LoadFirmware();
152	if ( GetDspCommObject()->IsBoardBad() )
153		return ECHOSTATUS_DSP_DEAD;
154
155	//
156	// Clear the "bad board" flag; set the flag to indicate that
157	// Darla24 can handle super-interleave.
158	//
159	m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
160	m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK;
161
162	//
163	//	Must call this here after DSP is init to
164	//	init gains and mutes
165	//
166	Status = InitLineLevels();
167	if ( ECHOSTATUS_OK != Status )
168		return Status;
169
170	//
171	// Initialize the MIDI input
172	//
173	Status = m_MidiIn.Init( this );
174	if ( ECHOSTATUS_OK != Status )
175		return Status;
176
177	ECHO_DEBUGPRINTF(("\tMIDI input init done\n"));
178
179	//
180	// Set defaults for +4/-10
181	//
182	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
183	{
184		ECHO_DEBUGPRINTF(("\tSetting nominal output level %d\n",i));
185		GetDspCommObject()->SetNominalLevel( i, TRUE );	// TRUE is -10 here
186	}
187	for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
188	{
189		ECHO_DEBUGPRINTF(("\tSetting nominal input level %d\n",i));
190		GetDspCommObject()->SetNominalLevel( GetNumBussesOut() + i, TRUE );
191	}
192
193	ECHO_DEBUGPRINTF(("\tNominal levels done\n"));
194
195	//
196	// Set the S/PDIF output format to "professional"
197	//
198	SetProfessionalSpdif( TRUE );
199	ECHO_DEBUGPRINTF(("\tSet S/PDIF format OK\n"));
200
201	//
202	//	Get default sample rate from DSP
203	//
204	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
205	ECHO_DEBUGPRINTF( ( "\tCLayla::InitHw() finished\n" ) );
206
207	return Status;
208
209}	// ECHOSTATUS CLayla::InitHw()
210
211
212
213
214/****************************************************************************
215
216	Informational methods
217
218 ****************************************************************************/
219
220//===========================================================================
221//
222// Override GetCapabilities to enumerate unique capabilties for Layla20
223//
224//===========================================================================
225
226ECHOSTATUS CLayla::GetCapabilities
227(
228	PECHOGALS_CAPS	pCapabilities
229)
230{
231	ECHOSTATUS	Status;
232	WORD			i;
233
234	Status = GetBaseCapabilities(pCapabilities);
235
236	//
237	// Add input gain and nominal level to input busses
238	//
239	for (i = 0; i < GetFirstDigitalBusIn(); i++)
240	{
241		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_GAIN |
242													ECHOCAPS_MUTE |
243													ECHOCAPS_NOMINAL_LEVEL;
244	}
245
246	//
247	// Add nominal levels to output busses
248	//
249	for (i = 0; i < GetFirstDigitalBusOut(); i++)
250	{
251		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
252	}
253
254	if ( ECHOSTATUS_OK != Status )
255		return Status;
256
257	pCapabilities->dwInClockTypes |= 	ECHO_CLOCK_BIT_WORD  |
258													ECHO_CLOCK_BIT_SUPER |
259													ECHO_CLOCK_BIT_SPDIF |
260													ECHO_CLOCK_BIT_MTC;
261
262	pCapabilities->dwOutClockTypes |= 	ECHO_CLOCK_BIT_WORD |
263													ECHO_CLOCK_BIT_SUPER;
264
265	return Status;
266
267}	// ECHOSTATUS CLayla::GetCapabilities
268
269
270//===========================================================================
271//
272// QueryAudioSampleRate is used to find out if this card can handle a
273// given sample rate.
274//
275//===========================================================================
276
277ECHOSTATUS CLayla::QueryAudioSampleRate
278(
279	DWORD		dwSampleRate
280)
281{
282	if ( dwSampleRate <  8000 ||
283		  dwSampleRate > 50000 )
284	{
285		ECHO_DEBUGPRINTF(
286			("CLayla::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
287		return ECHOSTATUS_BAD_FORMAT;
288	}
289	ECHO_DEBUGPRINTF( ( "CLayla::QueryAudioSampleRate() %ld Hz OK\n",
290							  dwSampleRate ) );
291	return ECHOSTATUS_OK;
292
293}	// ECHOSTATUS CLayla::QueryAudioSampleRate
294
295
296void CLayla::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
297{
298	dwMinRate = 8000;
299	dwMaxRate = 50000;
300}
301
302
303//===========================================================================
304//
305// GetInputClockDetect returns a bitmask consisting of all the input
306// clocks currently connected to the hardware; this changes as the user
307// connects and disconnects clock inputs.
308//
309// You should use this information to determine which clocks the user is
310// allowed to select.
311//
312// Layla20 supports S/PDIF clock, word clock, and super clock.
313//
314//===========================================================================
315
316ECHOSTATUS CLayla::GetInputClockDetect(DWORD &dwClockDetectBits)
317{
318	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
319	{
320		ECHO_DEBUGPRINTF( ("CLayla::GetInputClockDetect: DSP Dead!\n") );
321		return ECHOSTATUS_DSP_DEAD;
322	}
323
324	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
325
326	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_MTC;
327
328	if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SPDIF))
329		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
330
331	if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_WORD))
332	{
333		if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SUPER))
334			dwClockDetectBits |= ECHO_CLOCK_BIT_SUPER;
335		else
336			dwClockDetectBits |= ECHO_CLOCK_BIT_WORD;
337	}
338
339	return ECHOSTATUS_OK;
340
341}	// GetInputClockDetect
342
343
344// *** CLayla.cpp ***
345