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
operator new(size_t Size)54 PVOID 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
operator delete(PVOID pVoid)77 VOID 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
CLayla(PCOsSupport pOsSupport)92 CLayla::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
~CLayla()105 CLayla::~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
InitHw()125 ECHOSTATUS 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
GetCapabilities(PECHOGALS_CAPS pCapabilities)226 ECHOSTATUS 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
QueryAudioSampleRate(DWORD dwSampleRate)277 ECHOSTATUS 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
QuerySampleRateRange(DWORD & dwMinRate,DWORD & dwMaxRate)296 void 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
GetInputClockDetect(DWORD & dwClockDetectBits)316 ECHOSTATUS 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