xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CDspCommObject.h (revision 39241fe22890fb958b6ba32d6ab9526da98be187)
1 // ****************************************************************************
2 //
3 //		CDspCommObject.H
4 //
5 //		Include file for EchoGals generic driver DSP interface base class.
6 //
7 // ----------------------------------------------------------------------------
8 //
9 //		Copyright Echo Digital Audio Corporation (c) 1998 - 2002
10 //		All rights reserved
11 //		www.echoaudio.com
12 //
13 //		Permission is hereby granted, free of charge, to any person obtaining a
14 //		copy of this software and associated documentation files (the
15 //		"Software"), to deal with the Software without restriction, including
16 //		without limitation the rights to use, copy, modify, merge, publish,
17 //		distribute, sublicense, and/or sell copies of the Software, and to
18 //		permit persons to whom the Software is furnished to do so, subject to
19 //		the following conditions:
20 //
21 //		- Redistributions of source code must retain the above copyright
22 //		notice, this list of conditions and the following disclaimers.
23 //
24 //		- Redistributions in binary form must reproduce the above copyright
25 //		notice, this list of conditions and the following disclaimers in the
26 //		documentation and/or other materials provided with the distribution.
27 //
28 //		- Neither the name of Echo Digital Audio, nor the names of its
29 //		contributors may be used to endorse or promote products derived from
30 //		this Software without specific prior written permission.
31 //
32 //		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 //		EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 //		MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
35 //		IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
36 //		ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
37 //		TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
38 //		SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
39 //
40 // ****************************************************************************
41 
42 #ifndef _DSPCOMMOBJECT_
43 #define _DSPCOMMOBJECT_
44 
45 #ifdef _DEBUG
46 #ifdef ECHO_WDM
47 #pragma optimize("",off)
48 #endif
49 #endif
50 
51 #ifdef _WIN32
52 
53 //	Must match structure alignment w/DSP
54 #pragma pack( push, 2 )
55 
56 #endif
57 
58 #include "OsSupport.h"
59 #include "CDaffyDuck.h"
60 
61 /****************************************************************************
62 
63 	Lots of different defines for the different cards
64 
65  ****************************************************************************/
66 
67 
68 //==================================================================================
69 //
70 // Macros to convert to and from generic driver mixer values.  Since it can be tough
71 // to do floating point math in a driver, the generic driver uses fixed-point values.
72 // The numbers are in a 24.8 format; that is, the upper 24 bits are the integer part
73 // of the number and the lower 8 bits represent the fractional part.  In this scheme,
74 // a value of 0x180 would be equal to 1.5.
75 //
76 // Since the DSP usually wants 8 bit integer gains, the following macros are useful.
77 //
78 //==================================================================================
79 
80 #define GENERIC_TO_DSP(iValue) 	((iValue + 0x80) >> 8)
81 #define DSP_TO_GENERIC(iValue)	(iValue << 8)
82 
83 
84 //==================================================================================
85 //
86 //	Max inputs and outputs
87 //
88 //==================================================================================
89 
90 #define DSP_MAXAUDIOINPUTS			16				// Max audio input channels
91 #define DSP_MAXAUDIOOUTPUTS		16				// Max audio output channels
92 #define DSP_MAXPIPES					32				// Max total pipes (input + output)
93 
94 
95 //==================================================================================
96 //
97 //	These are the offsets for the memory-mapped DSP registers; the DSP base
98 // address is treated as the start of a DWORD array.
99 //
100 //==================================================================================
101 
102 #define	CHI32_CONTROL_REG					4
103 #define	CHI32_STATUS_REG					5
104 #define	CHI32_VECTOR_REG					6
105 #define	CHI32_DATA_REG						7
106 
107 
108 //==================================================================================
109 //
110 //	Interesting bits within the DSP registers
111 //
112 //==================================================================================
113 
114 #define	CHI32_VECTOR_BUSY					0x00000001
115 #define	CHI32_STATUS_REG_HF3				0x00000008
116 #define	CHI32_STATUS_REG_HF4				0x00000010
117 #define	CHI32_STATUS_REG_HF5				0x00000020
118 #define	CHI32_STATUS_HOST_READ_FULL	0x00000004
119 #define	CHI32_STATUS_HOST_WRITE_EMPTY	0x00000002
120 #define 	CHI32_STATUS_IRQ			      0x00000040
121 
122 
123 //==================================================================================
124 //
125 // DSP commands sent via slave mode; these are sent to the DSP by
126 // CDspCommObject::Write_DSP
127 //
128 //==================================================================================
129 
130 #define  DSP_FNC_SET_COMMPAGE_ADDR				0x02
131 #define  DSP_FNC_SET_CACHELINE_SIZE				0x03
132 #define	DSP_FNC_LOAD_LAYLA_ASIC					0xd8
133 #define	DSP_FNC_LOAD_GINA24_ASIC				0xd8
134 #define 	DSP_FNC_LOAD_MONA_PCI_CARD_ASIC		0xd8
135 #define 	DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC	0xd8
136 #define 	DSP_FNC_LOAD_MONA_EXTERNAL_ASIC		0xd9
137 #define 	DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC	0xd9
138 
139 
140 //==================================================================================
141 //
142 // Defines to handle the MIDI input state engine; these are used to properly
143 // extract MIDI time code bytes and their timestamps from the MIDI input stream.
144 //
145 //==================================================================================
146 
147 #define	MTC_STATE_NORMAL				0
148 #define	MTC_STATE_TS_HIGH				1
149 #define	MTC_STATE_TS_LOW				2
150 #define	MTC_STATE_F1_DATA				3
151 
152 #define	MTC_SKIP_DATA					((DWORD)-1)
153 
154 
155 /*------------------------------------------------------------------------------------
156 
157 Setting the sample rates on Layla24 is somewhat schizophrenic.
158 
159 For standard rates, it works exactly like Mona and Gina24.  That is, for
160 8, 11.025, 16, 22.05, 32, 44.1, 48, 88.2, and 96 kHz, you just set the
161 appropriate bits in the control register and write the control register.
162 
163 In order to support MIDI time code sync (and possibly SMPTE LTC sync in
164 the future), Layla24 also has "continuous sample rate mode".  In this mode,
165 Layla24 can generate any sample rate between 25 and 50 kHz inclusive, or
166 50 to 100 kHz inclusive for double speed mode.
167 
168 To use continuous mode:
169 
170 -Set the clock select bits in the control register to 0xe (see the #define
171  below)
172 
173 -Set double-speed mode if you want to use sample rates above 50 kHz
174 
175 -Write the control register as you would normally
176 
177 -Now, you need to set the frequency register. First, you need to determine the
178  value for the frequency register.  This is given by the following formula:
179 
180 frequency_reg = (LAYLA24_MAGIC_NUMBER / sample_rate) - 2
181 
182 Note the #define below for the magic number
183 
184 -Wait for the DSP handshake
185 -Write the frequency_reg value to the dwSampleRate field of the comm page
186 -Send the vector command SET_LAYLA24_FREQUENCY_REG (see vmonkey.h)
187 
188 Once you have set the control register up for continuous mode, you can just
189 write the frequency register to change the sample rate.  This could be
190 used for MIDI time code sync. For MTC sync, the control register is set for
191 continuous mode.  The driver then just keeps writing the
192 SET_LAYLA24_FREQUENCY_REG command.
193 
194 ----------------------------------------------------------------------------------*/
195 
196 #define	LAYLA24_MAGIC_NUMBER						677376000
197 #define	LAYLA24_CONTINUOUS_CLOCK				0x000e
198 
199 
200 //==================================================================================
201 //
202 // DSP vector commands
203 //
204 //==================================================================================
205 
206 #define	DSP_VC_RESET							0x80ff
207 
208 #ifndef DSP_56361
209 
210 //
211 // Vector commands for families that only use the 56301
212 // Only used for Darla20, Gina20, Layla20, and Darla24
213 //
214 #define	DSP_VC_ACK_INT							0x8073
215 #define	DSP_VC_SET_VMIXER_GAIN				0x0000	// Not used, only for compile
216 #define	DSP_VC_START_TRANSFER				0x0075	// Handshke rqd.
217 #define	DSP_VC_METERS_ON						0x0079
218 #define	DSP_VC_METERS_OFF						0x007b
219 #define	DSP_VC_UPDATE_OUTVOL					0x007d	// Handshke rqd.
220 #define	DSP_VC_UPDATE_INGAIN					0x007f	// Handshke rqd.
221 #define	DSP_VC_ADD_AUDIO_BUFFER				0x0081	// Handshke rqd.
222 #define	DSP_VC_TEST_ASIC						0x00eb
223 #define	DSP_VC_UPDATE_CLOCKS					0x00ef	// Handshke rqd.
224 #define 	DSP_VC_SET_LAYLA_SAMPLE_RATE		0x00f1	// Handshke rqd.
225 #define	DSP_VC_SET_GD_AUDIO_STATE			0x00f1	// Handshke rqd.
226 #define	DSP_VC_WRITE_CONTROL_REG			0x00f1	// Handshke rqd.
227 #define 	DSP_VC_MIDI_WRITE						0x00f5	// Handshke rqd.
228 #define 	DSP_VC_STOP_TRANSFER					0x00f7	// Handshke rqd.
229 #define	DSP_VC_UPDATE_FLAGS					0x00fd	// Handshke rqd.
230 #define 	DSP_VC_GO_COMATOSE					0x00f9
231 
232 #else
233 
234 //
235 // Vector commands for families that use either the 56301 or 56361
236 //
237 #define	DSP_VC_ACK_INT							0x80F5
238 #define	DSP_VC_SET_VMIXER_GAIN				0x00DB	// Handshke rqd.
239 #define	DSP_VC_START_TRANSFER				0x00DD	// Handshke rqd.
240 #define	DSP_VC_METERS_ON						0x00EF
241 #define	DSP_VC_METERS_OFF						0x00F1
242 #define	DSP_VC_UPDATE_OUTVOL					0x00E3	// Handshke rqd.
243 #define	DSP_VC_UPDATE_INGAIN					0x00E5	// Handshke rqd.
244 #define	DSP_VC_ADD_AUDIO_BUFFER				0x00E1	// Handshke rqd.
245 #define	DSP_VC_TEST_ASIC						0x00ED
246 #define	DSP_VC_UPDATE_CLOCKS					0x00E9	// Handshke rqd.
247 #define	DSP_VC_SET_LAYLA24_FREQUENCY_REG	0x00E9	// Handshke rqd.
248 #define 	DSP_VC_SET_LAYLA_SAMPLE_RATE		0x00EB	// Handshke rqd.
249 #define	DSP_VC_SET_GD_AUDIO_STATE			0x00EB	// Handshke rqd.
250 #define	DSP_VC_WRITE_CONTROL_REG			0x00EB	// Handshke rqd.
251 #define 	DSP_VC_MIDI_WRITE						0x00E7	// Handshke rqd.
252 #define 	DSP_VC_STOP_TRANSFER					0x00DF	// Handshke rqd.
253 #define	DSP_VC_UPDATE_FLAGS					0x00FB	// Handshke rqd.
254 #define 	DSP_VC_GO_COMATOSE					0x00d9
255 
256 #endif
257 
258 
259 //==================================================================================
260 //
261 //	Timeouts
262 //
263 //==================================================================================
264 
265 #define HANDSHAKE_TIMEOUT		5000		//	SendVector command timeout (times 2 u.s.)
266 #define MIDI_OUT_DELAY_USEC	2000		// How long to wait after MIDI fills up
267 
268 
269 //==================================================================================
270 //
271 //	Flags for dwFlags field in the comm page
272 //
273 //==================================================================================
274 
275 #define	DSP_FLAG_MIDI_INPUT				0x0001	// Enable MIDI input
276 #define	DSP_FLAG_PROFESSIONAL_SPDIF	0x0008	// 1 Professional, 0 Consumer
277 
278 
279 //==================================================================================
280 //
281 //	Clock detect bits reported by the DSP for Gina20, Layla20, Darla24, and Mia
282 //
283 //==================================================================================
284 
285 #define GLDM_CLOCK_DETECT_BIT_WORD		0x0002
286 #define GLDM_CLOCK_DETECT_BIT_SUPER		0x0004
287 #define GLDM_CLOCK_DETECT_BIT_SPDIF		0x0008
288 #define GLDM_CLOCK_DETECT_BIT_ESYNC		0x0010
289 
290 
291 //==================================================================================
292 //
293 //	Clock detect bits reported by the DSP for Gina24, Mona, and Layla24
294 //
295 //==================================================================================
296 
297 #define GML_CLOCK_DETECT_BIT_WORD96		0x0002
298 #define GML_CLOCK_DETECT_BIT_WORD48		0x0004
299 #define GML_CLOCK_DETECT_BIT_SPDIF48	0x0008
300 #define GML_CLOCK_DETECT_BIT_SPDIF96	0x0010
301 #define GML_CLOCK_DETECT_BIT_WORD		(GML_CLOCK_DETECT_BIT_WORD96|GML_CLOCK_DETECT_BIT_WORD48)
302 #define GML_CLOCK_DETECT_BIT_SPDIF		(GML_CLOCK_DETECT_BIT_SPDIF48|GML_CLOCK_DETECT_BIT_SPDIF96)
303 #define GML_CLOCK_DETECT_BIT_ESYNC		0x0020
304 #define GML_CLOCK_DETECT_BIT_ADAT		0x0040
305 
306 
307 //==================================================================================
308 //
309 //	Gina/Darla clock states
310 //
311 //==================================================================================
312 
313 #define GD_CLOCK_NOCHANGE			0
314 #define GD_CLOCK_44					1
315 #define GD_CLOCK_48					2
316 #define GD_CLOCK_SPDIFIN			3
317 #define GD_CLOCK_UNDEF				0xff
318 
319 
320 //==================================================================================
321 //
322 //	Gina/Darla S/PDIF status bits
323 //
324 //==================================================================================
325 
326 #define GD_SPDIF_STATUS_NOCHANGE	0
327 #define GD_SPDIF_STATUS_44			1
328 #define GD_SPDIF_STATUS_48			2
329 #define GD_SPDIF_STATUS_UNDEF		0xff
330 
331 
332 //==================================================================================
333 //
334 //	Return values from the DSP when ASIC is loaded
335 //
336 //==================================================================================
337 
338 #define ASIC_ALREADY_LOADED		0x1
339 #define ASIC_NOT_LOADED				0x0
340 
341 
342 //==================================================================================
343 //
344 //	DSP Audio formats
345 //
346 // These are the audio formats that the DSP can transfer
347 // via input and output pipes.  LE means little-endian,
348 // BE means big-endian.
349 //
350 // DSP_AUDIOFORM_MS_8
351 //
352 // 	8-bit mono unsigned samples.  For playback,
353 //		mono data is duplicated out the left and right channels
354 // 	of the output bus.  The "MS" part of the name
355 //		means mono->stereo.
356 //
357 //	DSP_AUDIOFORM_MS_16LE
358 //
359 //		16-bit signed little-endian mono samples.  Playback works
360 //		like the previous code.
361 //
362 //	DSP_AUDIOFORM_MS_32LE
363 //
364 //		24-bit signed little-endian mono samples in a 32-bit
365 //		container.  In other words, each sample is a 32-bit signed
366 //		integer, where the actual audio data is left-justified
367 //		in the 32 bits and only the 24 most significant bits are valid.
368 //
369 //	DSP_AUDIOFORM_SS_8
370 //	DSP_AUDIOFORM_SS_16LE
371 //	DSP_AUDIOFORM_SS_32LE
372 //
373 //		Like the previous ones, except now with stereo interleaved
374 //		data.  "SS" means stereo->stereo.
375 //
376 // DSP_AUDIOFORM_MM_32LE
377 //
378 //		Similar to DSP_AUDIOFORM_MS_32LE, except that the mono
379 //		data is not duplicated out both the left and right outputs.
380 //		This mode is used by the ASIO driver.  Here, "MM" means
381 //		mono->mono.
382 //
383 //	DSP_AUDIOFORM_MM_32BE
384 //
385 //		Just like DSP_AUDIOFORM_MM_32LE, but now the data is
386 //		in big-endian format.
387 //
388 //	DSP_AUDIOFORM_MS_16LE_ND
389 //
390 // 	Just like DSP_AUDIOFORM_MS_16LE; the only difference is
391 //		that when recording, the signal is not dithered.  This
392 //		is useful when recording from digital inputs.
393 //
394 //	DSP_AUDIOFORM_SS_16LE_ND
395 //
396 //		Just like the last one, but for stereo interleaved data.
397 //
398 //==================================================================================
399 
400 #define DSP_AUDIOFORM_MS_8			0		// 8 bit mono
401 #define DSP_AUDIOFORM_MS_16LE		1		// 16 bit mono
402 #define DSP_AUDIOFORM_MS_32LE		3		// 32 bit mono
403 #define DSP_AUDIOFORM_SS_8			4		// 8 bit stereo
404 #define DSP_AUDIOFORM_SS_16LE		5		// 16 bit stereo
405 #define DSP_AUDIOFORM_SS_32LE		7		// 32 bit stereo
406 #define DSP_AUDIOFORM_MM_32LE		8		// 32 bit mono->mono little-endian
407 #define DSP_AUDIOFORM_MM_32BE		9		// 32 bit mono->mono big-endian
408 #define DSP_AUDIOFORM_MS_16LE_ND	10		// 16 bit mono no dither s/pdif
409 #define DSP_AUDIOFORM_SS_16LE_ND	11		// 16 bit stereo no dither s/pdif
410 #define DSP_AUDIOFORM_SS_32BE		12		// 32 bit stereo big endian
411 #define DSP_AUDIOFORM_INVALID		0xFF	// Invalid audio format
412 
413 
414 //==================================================================================
415 //
416 // Super-interleave is defined as interleaving by 4 or more.  Darla20 and Gina20
417 // do not support super interleave.
418 //
419 // Only 32 bit little endian samples are supported for super interleave.  The
420 // interleave factor must be even.  16 - way interleave is the current maximum,
421 // so you can interleave by 4, 6, 8, 10, 12, 14, and 16.
422 //
423 // The actual format code is derived by taking the define below and or-ing with
424 // the interleave factor.  So, interleave by 6 is 0x86 and interleave by 16 is 0x90.
425 //
426 //==================================================================================
427 
428 #define DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE	0x80
429 
430 
431 //==================================================================================
432 //
433 //	Gina24, Mona, and Layla24 control register defines
434 //
435 //==================================================================================
436 
437 #define GML_CONVERTER_ENABLE		0x0010
438 #define GML_SPDIF_PRO_MODE			0x0020		// Professional S/PDIF == 1, consumer == 0
439 #define GML_SPDIF_SAMPLE_RATE0	0x0040
440 #define GML_SPDIF_SAMPLE_RATE1	0x0080
441 #define GML_SPDIF_TWO_CHANNEL		0x0100		// 1 == two channels, 0 == one channel
442 #define GML_SPDIF_NOT_AUDIO		0x0200
443 #define GML_SPDIF_COPY_PERMIT		0x0400
444 #define GML_SPDIF_24_BIT			0x0800		// 1 == 24 bit, 0 == 20 bit
445 #define GML_ADAT_MODE				0x1000		// 1 == ADAT mode, 0 == S/PDIF mode
446 #define GML_SPDIF_OPTICAL_MODE	0x2000		// 1 == optical mode, 0 == RCA mode
447 #define GML_SPDIF_CDROM_MODE		0x3000		// 1 == CDROM mode, 0 == RCA or optical mode
448 #define GML_DOUBLE_SPEED_MODE		0x4000		// 1 == double speed, 0 == single speed
449 
450 #define GML_DIGITAL_IN_AUTO_MUTE	0x800000
451 
452 #define GML_96KHZ						(0x0 | GML_DOUBLE_SPEED_MODE)
453 #define GML_88KHZ						(0x1 | GML_DOUBLE_SPEED_MODE)
454 #define GML_48KHZ						0x2
455 #define GML_44KHZ						0x3
456 #define GML_32KHZ						0x4
457 #define GML_22KHZ						0x5
458 #define GML_16KHZ						0x6
459 #define GML_11KHZ						0x7
460 #define GML_8KHZ						0x8
461 #define GML_SPDIF_CLOCK				0x9
462 #define GML_ADAT_CLOCK				0xA
463 #define GML_WORD_CLOCK				0xB
464 #define GML_ESYNC_CLOCK				0xC
465 #define GML_ESYNCx2_CLOCK			0xD
466 
467 #define GML_CLOCK_CLEAR_MASK			0xffffbff0
468 #define GML_SPDIF_RATE_CLEAR_MASK   (~(GML_SPDIF_SAMPLE_RATE0|GML_SPDIF_SAMPLE_RATE1))
469 #define GML_DIGITAL_MODE_CLEAR_MASK	0xffffcfff
470 #define GML_SPDIF_FORMAT_CLEAR_MASK	0xfffff01f
471 
472 
473 //==================================================================================
474 //
475 //	MIA Sample rate conversion constants
476 //
477 //==================================================================================
478 
479 #define MIA_1_TO_2	0x00010000  // Sample rate conversion ratio 1:2
480 #define MIA_1_TO_4	0x00020000	// Sample rate conversion ratio 1:4
481 
482 #define MIA_SRC_MASK	0xffff0000
483 
484 
485 //==================================================================================
486 //
487 //	Mia sample rate and clock setting constants
488 //
489 //==================================================================================
490 
491 #define MIA_32000		0x0040
492 #define MIA_44100		0x0042
493 #define MIA_48000		0x0041
494 #define MIA_88200		0x0142
495 #define MIA_96000		0x0141
496 
497 #define MIA_8000		(MIA_1_TO_4 | MIA_32000)
498 #define MIA_11025		(MIA_1_TO_4 | MIA_44100)
499 #define MIA_12000		(MIA_1_TO_4 | MIA_48000)
500 #define MIA_16000		(MIA_1_TO_2 | MIA_32000)
501 #define MIA_22050		(MIA_1_TO_2 | MIA_44100)
502 #define MIA_24000		(MIA_1_TO_2 | MIA_48000)
503 
504 #define MIA_SPDIF		0x00000044
505 #define MIA_SPDIF96	0x00000144
506 
507 
508 //==================================================================================
509 //
510 // Gina20 & Layla20 have input gain controls for the analog inputs;
511 // this is the magic number for the hardware that gives you 0 dB at -10.
512 //
513 //==================================================================================
514 
515 #define GL20_INPUT_GAIN_MAGIC_NUMBER	0xC8
516 
517 
518 //==================================================================================
519 //
520 //	Defines how much time must pass between DSP load attempts
521 //
522 //==================================================================================
523 
524 #define DSP_LOAD_ATTEMPT_PERIOD	1000000L	// One million microseconds == one second
525 
526 
527 //==================================================================================
528 //
529 // Size of arrays for the comm page.  MAX_PLAY_TAPS and MAX_REC_TAPS are no longer
530 // used, but the sizes must still be right for the DSP to see the comm page correctly.
531 //
532 //==================================================================================
533 
534 #define MONITOR_ARRAY_SIZE		0x180
535 #define VMIXER_ARRAY_SIZE		0x40
536 #define DSP_MIDI_BUFFER_SIZE 	256
537 #define MAX_PLAY_TAPS			168
538 #define MAX_REC_TAPS				192
539 
540 
541 /****************************************************************************
542 
543 	The comm page.  This structure is read and written by the DSP; the
544 	DSP code is a firm believer in the byte offsets written in the comments
545 	at the end of each line.  This structure should not be changed.
546 
547 	Any reads from or writes to this structure should be in little-endian
548 	format.
549 
550  ****************************************************************************/
551 
552 typedef struct
553 {
554 	DWORD				dwCommSize;				// size of this object							0x000	4
555 
556 	DWORD				dwFlags;					// See Appendix A below							0x004	4
557 	DWORD				dwUnused;				// Unused entry									0x008	4
558 
559 	DWORD				dwSampleRate;			// Card sample rate in Hz						0x00c	4
560 	DWORD				dwHandshake;			// DSP command handshake						0x010	4
561 	CChMaskDsp		cmdStart;				// Chs. to start mask							0x014	4
562 	CChMaskDsp		cmdStop;					// Chs. to stop mask								0x018	4
563 	CChMaskDsp		cmdReset;				// Chs. to reset mask							0x01c	4
564 	WORD				wAudioFormat[ DSP_MAXPIPES ];
565               									// Chs. audio format								0x020	16*2*2
566 	DUCKENTRY		dwDuckListPhys[ DSP_MAXPIPES ];
567      												// Chs. Physical duck addrs					0x060	16*2*8
568 	DWORD				dwPosition[ DSP_MAXPIPES ];
569 													// Positions for ea. ch.						0x160	16*2*4
570 	BYTE				VULevel[ DSP_MAXPIPES ];
571 													// VU meters										0x1e0	16*2*1
572 	BYTE				PeakMeter[ DSP_MAXPIPES ];
573 													// Peak meters										0x200	16*2*1
574 	BYTE				OutLineLevel[ DSP_MAXAUDIOOUTPUTS ];
575 													// Output gain										0x220	16*1
576 	BYTE				InLineLevel[ DSP_MAXAUDIOINPUTS ];
577 													// Input gain										0x230	16*1
578 	BYTE				byMonitors[ MONITOR_ARRAY_SIZE ];
579 													// Monitor map										0x240	0x180
580 	DWORD				dwPlayCoeff[ MAX_PLAY_TAPS ];
581 													// Gina/Darla play filters - obsolete		0x3c0	168*4
582 	DWORD				dwRecCoeff [ MAX_REC_TAPS ];
583 													// Gina/Darla record filters - obsolete	0x660	192*4
584 	WORD				wMidiInData[ DSP_MIDI_BUFFER_SIZE ];
585 													// MIDI input data transfer buffer			0x960	256*2
586 	BYTE				byGDClockState;		// Chg Gina/Darla clock state					0xb60	4
587 	BYTE				byGDSpdifStatus;		// Chg. Gina/Darla S/PDIF state
588 	BYTE				byGDResamplerState;	// Should always be 3
589 	BYTE				byFiller2;
590 	CChMaskDsp		cmdNominalLevel;
591 													// -10 level enable mask						0xb64	4
592 	WORD				wInputClock; 			// Chg. Input clock state
593 	WORD				wOutputClock; 			// Chg. Output clock state						0xb68
594 	DWORD				dwStatusClocks;	 	// Current Input clock state					0xb6c	4
595 
596 	DWORD				dwMIDIOutData;			// Output MIDI bytes to DSP					0xb70
597 	CChMaskDsp		cmdAddBuffer;			// Pipes. to add									0xb74	4
598 	DWORD				dwMidiXmitStatus;		// MIDI transmit status							0xb78	4
599 	CChMaskDsp		cmdCyclicBuffer;		// Cyclic pipes									0xb7c	4
600 	DWORD				dwControlReg;			// Mona, Gina24 & Layla24 control reg		0xb80 4
601 	BYTE				byFiller[28];			// filler											0xb84
602 	BYTE				byVmixerLevel[ VMIXER_ARRAY_SIZE ];
603 													// Vmixer levels									0xba0 64
604 } DspCommPage, *PDspCommPage;
605 
606 
607 /****************************************************************************
608 
609 	CDspCommObject is the class which wraps both the comm page and the
610 	DSP registers.  CDspCommObject talks directly to the hardware; anyone
611 	who wants to do something to the hardware goes through CDspCommObject or
612 	one of the derived classes.
613 
614 	Note that an instance of CDspCommObject is never actually created; it
615 	is treated as an abstract base class.
616 
617  ****************************************************************************/
618 
619 class CDspCommObject
620 {
621 protected:
622 	PDspCommPage	m_pDspCommPage;		// Physical memory seen by DSP
623 
624  	//
625  	//	These members are not seen by the DSP; they are used internally by
626 	// this class.
627  	//
628 	WORD				m_wNumPipesOut;
629 	WORD				m_wNumPipesIn;
630 	WORD				m_wNumBussesOut;
631 	WORD				m_wNumBussesIn;
632 	WORD				m_wFirstDigitalBusOut;
633 	WORD				m_wFirstDigitalBusIn;
634 
635 	BOOL				m_fHasVmixer;
636 
637 	WORD				m_wNumMidiOut;			// # MIDI out channels
638 	WORD				m_wNumMidiIn;			// # MIDI in  channels
639 	PWORD 			m_pwDspCode;			// Current DSP code loaded, NULL if nothing loaded
640 	PWORD 			m_pwDspCodeToLoad;	// DSP code to load
641 	BOOL				m_bHasASIC;				// Set TRUE if card has an ASIC
642 	BOOL				m_bASICLoaded;			// Set TRUE when ASIC loaded
643 	DWORD				m_dwCommPagePhys;		// Physical addr of this object
644 	PDWORD			m_pdwDspRegBase;		// DSP's register base
645 	CChannelMask	m_cmActive;				// Chs. active mask
646 	BOOL				m_bBadBoard;			// Set TRUE if DSP won't load
647 													// or punks out
648 	WORD				m_wMeterOnCount;		// How many times meters have been
649 													// enabled
650 	PCOsSupport		m_pOsSupport;			// Ptr to OS specific methods & data
651 	CHAR				m_szCardName[ 20 ];
652 	BYTE				m_byDigitalMode;		// Digital mode (see DIGITAL_MODE_??
653 													//	defines in EchoGalsXface.h
654 	WORD				m_wInputClock;			// Currently selected input clock
655 	WORD				m_wOutputClock;		// Currently selected output clock
656 
657 	ULONGLONG		m_ullLastLoadAttemptTime;	// Last system time that the driver
658 															// attempted to load the DSP & ASIC
659 #ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT
660 	BOOL				m_fDigitalInAutoMute;
661 #endif
662 
663 #ifdef MIDI_SUPPORT
664 	WORD				m_wMidiOnCount;		// Count MIDI enabled cmds
665 	ULONGLONG		m_ullMidiInTime;		// Last time MIDI in occured
666 	ULONGLONG		m_ullMidiOutTime;		// Last time MIDI out occured
667 	ULONGLONG		m_ullNextMidiWriteTime;	// Next time to try MIDI output
668 
669 	WORD				m_wMtcState;			// State for MIDI input parsing state machine
670 #endif
671 
672 protected :
673 
674 	virtual WORD ComputeAudioMonitorIndex
675 	(
676 		WORD	wBusOut,
677 		WORD	wBusIn
678 	)
679 	{
680 		return( wBusOut * m_wNumBussesIn + wBusIn );
681 	}
682 
683 	//
684 	//	Load code into DSP
685 	//
686 #ifdef DSP_56361
687 	virtual ECHOSTATUS InstallResidentLoader();
688 #endif
689 	virtual ECHOSTATUS LoadDSP( PWORD pCode );
690 
691 	//
692 	//	Read the serial number from DSP
693 	//
694 	virtual ECHOSTATUS	ReadSn();
695 
696 	//
697 	//	Load code into ASIC
698 	//
699 	BOOL LoadASIC( DWORD dwCmd, PBYTE pCode, DWORD dwSize );
700 	virtual BOOL LoadASIC() { return TRUE; }
701 
702 	//
703 	//	Check status of ASIC - loaded or not loaded
704 	//
705 	BOOL CheckAsicStatus();
706 
707 	//
708 	//	Write to DSP
709 	//
710 	ECHOSTATUS	Write_DSP( DWORD dwData );
711 
712 	//
713 	//	Read from DSP
714 	//
715 	ECHOSTATUS	Read_DSP( DWORD *pdwData );
716 
717 	//
718 	//	Get/Set handshake Flag
719 	//
720 	DWORD GetHandshakeFlag()
721 		{ ASSERT( NULL != m_pDspCommPage );
722 		  return( SWAP( m_pDspCommPage->dwHandshake ) ); }
723 	void ClearHandshake()
724 		{ ASSERT( NULL != m_pDspCommPage );
725 		  m_pDspCommPage->dwHandshake = 0; }
726 
727 	//
728 	//	Get/set DSP registers
729 	//
730 	DWORD GetDspRegister( DWORD dwIndex )
731 		{ ASSERT( NULL != m_pdwDspRegBase );
732 		  return( SWAP( m_pdwDspRegBase[ dwIndex ] ) ); }
733 	void SetDspRegister( DWORD dwIndex, DWORD dwValue )
734 		{ ASSERT( NULL != m_pdwDspRegBase );
735 		  m_pdwDspRegBase[ dwIndex ] = SWAP( dwValue ); }
736 
737 	//
738 	//	Set control register in CommPage
739 	//
740 	void SetControlRegister( DWORD dwControlRegister )
741 		{ ASSERT( NULL != m_pDspCommPage );
742 		  m_pDspCommPage->dwControlReg = SWAP( dwControlRegister ); }
743 
744 	//
745 	//	Called after load firmware to restore old gains, meters on, monitors, etc.
746 	//
747 	virtual void RestoreDspSettings();
748 
749 	//
750 	// Send a vector command to the DSP
751 	//
752 	ECHOSTATUS SendVector( DWORD dwCommand );
753 
754 	//
755 	//	Wait for DSP to finish the last vector command
756 	//
757 	BOOL WaitForHandshake();
758 
759 	//
760 	// Send new input line setting to DSP
761 	//
762 	ECHOSTATUS UpdateAudioInLineLevel();
763 
764 public:
765 
766 	//
767 	//	Construction/destruction
768 	//
769 	CDspCommObject( PDWORD pdwRegBase, PCOsSupport pOsSupport );
770 	virtual ~CDspCommObject();
771 
772 	//
773 	//	Card information
774 	//
775 	virtual WORD GetCardType() = NULL;
776 										// Undefined, must be done in derived class
777 	const PCHAR GetCardName() { return( m_szCardName ); }
778 										// Must be init in derived class
779 
780 	//
781 	// Get mask with active pipes
782 	//
783 	void GetActivePipes
784 	(
785 		PCChannelMask	pChannelMask
786 	);
787 
788 	//
789 	// Basic info methods
790 	//
791 	WORD GetNumPipesOut()
792 	{
793 		return m_wNumPipesOut;
794 	}
795 
796 	WORD GetNumPipesIn()
797 	{
798 		return m_wNumPipesIn;
799 	}
800 
801 	WORD GetNumBussesOut()
802 	{
803 		return m_wNumBussesOut;
804 	}
805 
806 	WORD GetNumBussesIn()
807 	{
808 		return m_wNumBussesIn;
809 	}
810 
811 	WORD GetNumPipes()
812 	{
813 		return m_wNumPipesOut + m_wNumPipesIn;
814 	}
815 
816 	WORD GetNumBusses()
817 	{
818 		return m_wNumBussesOut + m_wNumBussesIn;
819 	}
820 
821 	WORD GetFirstDigitalBusOut()
822 	{
823 		return m_wFirstDigitalBusOut;
824 	}
825 
826 	WORD GetFirstDigitalBusIn()
827 	{
828 		return m_wFirstDigitalBusIn;
829 	}
830 
831 	BOOL HasVmixer()
832 	{
833 		return m_fHasVmixer;
834 	}
835 
836 	WORD GetNumMidiOutChannels()
837 		{ return( m_wNumMidiOut ); }
838 	WORD GetNumMidiInChannels()
839 		{ return( m_wNumMidiIn ); }
840 	WORD GetNumMidiChannels()
841 		{ return( m_wNumMidiIn + m_wNumMidiOut ); }
842 
843 	BOOL VerifySize( DWORD dwExpSize )
844 		{ return( SWAP( dwExpSize ) == m_pDspCommPage->dwCommSize ); }
845 
846 	//
847 	// Get, set, and clear comm page flags
848 	//
849 	DWORD GetFlags()
850 		{
851 			return( SWAP( m_pDspCommPage->dwFlags ) );  }
852 	DWORD SetFlags( DWORD dwFlags )
853 		{
854 			DWORD dwCpFlags = SWAP( m_pDspCommPage->dwFlags );
855 			dwCpFlags |= dwFlags;
856 			m_pDspCommPage->dwFlags = SWAP( dwCpFlags );
857 
858 			if ( m_bASICLoaded && WaitForHandshake() )
859 				UpdateFlags();
860 		  return( GetFlags() );
861 		}
862 	DWORD ClearFlags( DWORD dwFlags )
863 		{
864 			DWORD dwCpFlags = SWAP( m_pDspCommPage->dwFlags );
865 			dwCpFlags &= ~dwFlags;
866 			m_pDspCommPage->dwFlags = SWAP( dwCpFlags );
867 
868 			if ( m_bASICLoaded && WaitForHandshake() )
869 				UpdateFlags();
870 			return( GetFlags() );
871 		}
872 
873 	//
874 	//	Returns currently selected input clock
875 	//
876 	WORD GetInputClock()
877 	{
878 		return m_wInputClock;
879 	}
880 
881 	//
882 	//	Returns what input clocks are currently detected
883 	//
884 	DWORD GetInputClockDetect()
885 		{ return( SWAP( m_pDspCommPage->dwStatusClocks ) ); }
886 
887 	//
888 	//	Returns currently selected output clock
889 	//
890 	WORD GetOutputClock()
891 	{
892 		return m_wOutputClock;
893 	}
894 
895 	//
896 	//	Returns control register
897 	//
898 	DWORD GetControlRegister()
899 		{ ASSERT( NULL != m_pDspCommPage );
900 		  return SWAP( m_pDspCommPage->dwControlReg ); }
901 
902 	//
903 	//	Set input and output clocks
904 	//
905 	virtual ECHOSTATUS SetInputClock(WORD wClock);
906 	virtual ECHOSTATUS SetOutputClock(WORD wClock);
907 
908 	//
909 	//	Set digital mode
910 	//
911 	virtual ECHOSTATUS SetDigitalMode( BYTE byNewMode )
912 		{ return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED; }
913 	//
914 	//	Get digital mode
915 	//
916 	virtual BYTE GetDigitalMode()
917 		{ return( m_byDigitalMode ); }
918 
919 	//
920 	//	Get mask of all supported digital modes.
921 	//	(See ECHOCAPS_HAS_DIGITAL_MODE_??? defines in EchoGalsXface.h)
922 	//
923 	//	Note: If the card does not have a digital mode switch
924 	//			then return 0 (no digital modes supported).
925 	//			Some legacy cards support S/PDIF as their only
926 	//			digital mode.  We still return 0 here because it
927 	//			is not switchable.
928 	//
929 	virtual DWORD GetDigitalModes()
930 		{ return( 0 ); }
931 
932 	//
933 	//	Return audio channel position in bytes
934 	//
935 	DWORD GetAudioPosition( WORD wPipeIndex )
936 		{ ASSERT( wPipeIndex < ECHO_MAXAUDIOPIPES );
937 
938 		  return( ( wPipeIndex < ECHO_MAXAUDIOPIPES )
939 							? SWAP( m_pDspCommPage->dwPosition[ wPipeIndex ] )
940 							: 0  );  }
941 
942 	//
943 	// Reset the pipe position for a single pipe
944 	//
945 	void ResetPipePosition(WORD wPipeIndex)
946 	{
947 		if (wPipeIndex < ECHO_MAXAUDIOPIPES)
948 		{
949 			m_pDspCommPage->dwPosition[ wPipeIndex ] = 0;
950 		}
951 	}
952 
953 	//
954 	// Warning: Never write to the pointer returned by this
955 	// function!!!
956 	//
957 	//	The data pointed to by this pointer is in little-
958 	// endian format.
959 	//
960 	PDWORD GetAudioPositionPtr()
961 		{ return( m_pDspCommPage->dwPosition ); }
962 
963 	//
964 	// Get the current sample rate
965 	//
966 	DWORD GetSampleRate()
967 	    { return( SWAP( m_pDspCommPage->dwSampleRate ) ); }
968 
969 	//
970 	//	Set the sample rate.
971 	//	Return rate that was set, 0xffffffff if error
972 	//
973 	virtual DWORD SetSampleRate( DWORD dwNewSampleRate ) = NULL;
974 
975 	//
976 	//	Send current setting to DSP & return what it is
977 	//
978 	virtual DWORD SetSampleRate() = NULL;
979 
980 	//
981 	// Start a group of pipes
982 	//
983 	ECHOSTATUS StartTransport
984 	(
985 		PCChannelMask	pChannelMask,		// Pipes to start
986 		PCChannelMask	pCyclicMask			// Which pipes are cyclic buffers
987 	);
988 
989 	//
990 	// Stop a group of pipes
991 	//
992 	ECHOSTATUS StopTransport
993 	(
994 		PCChannelMask	pChannelMask
995 	);
996 
997 	//
998 	// Reset a group of pipes
999 	//
1000 	ECHOSTATUS ResetTransport
1001 	(
1002 		PCChannelMask	pChannelMask
1003 	);
1004 
1005 	//
1006 	// Tell DSP we added a buffer to a channel
1007 	//
1008 	ECHOSTATUS AddBuffer( WORD wPipeIndex );
1009 
1010 	//
1011 	// Add start of duck list for one channel to commpage so DSP can read it.
1012 	//
1013 	void SetAudioDuckListPhys( WORD wPipeIndex, DWORD dwNewPhysAdr );
1014 
1015 	//
1016 	// Read extended status register from the DSP
1017 	//
1018 	DWORD GetStatusReg()
1019 		{ return( SWAP( m_pdwDspRegBase[ CHI32_STATUS_REG ] ) ); }
1020 
1021 	//
1022 	// Tell DSP to release the hardware interrupt
1023 	//
1024 	void AckInt()
1025 	{
1026 		m_pDspCommPage->wMidiInData[ 0 ] = 0;
1027 		SendVector( DSP_VC_ACK_INT );
1028 	}
1029 
1030 	//
1031 	// Overload new & delete so memory for this object is allocated
1032 	// from contiguous non-paged memory.
1033 	//
1034 	PVOID operator new( size_t Size );
1035 	VOID  operator delete( PVOID pVoid );
1036 
1037 	//
1038 	//	Get status of board
1039 	//
1040 	BOOL IsBoardBad()
1041 		{ return( m_bBadBoard ); }
1042 
1043 	//
1044 	//	Tell DSP flags have been updated
1045 	//
1046 	ECHOSTATUS UpdateFlags()
1047 	{
1048 		ECHO_DEBUGPRINTF(("CDspCommObject::UpdateFlags\n"));
1049 		ClearHandshake();
1050 		return( SendVector( DSP_VC_UPDATE_FLAGS ) );
1051 	}
1052 
1053 	//
1054 	//	Get/Set Professional or consumer S/PDIF status
1055 	//
1056 	virtual BOOL IsProfessionalSpdif()
1057 		{
1058 			ECHO_DEBUGPRINTF(("CDspCommObject::IsProfessionalSpdif - flags are 0x%lx\n",
1059 									GetFlags()));
1060 			return( ( GetFlags() & DSP_FLAG_PROFESSIONAL_SPDIF ) ? TRUE : FALSE );
1061 		}
1062 
1063 	virtual void SetProfessionalSpdif( BOOL bNewStatus )
1064 		{
1065 			ECHO_DEBUGPRINTF(("CDspCommObject::SetProfessionalSpdif %d\n",bNewStatus));
1066 			if ( 0 != bNewStatus )
1067 				SetFlags( DSP_FLAG_PROFESSIONAL_SPDIF );
1068 			else
1069 				ClearFlags( DSP_FLAG_PROFESSIONAL_SPDIF );
1070 
1071 			ECHO_DEBUGPRINTF(("CDspCommObject::SetProfessionalSpdif - flags are now 0x%lx\n",
1072 									GetFlags()));
1073 		}
1074 
1075 	//
1076 	// Mixer functions
1077 	//
1078 	virtual ECHOSTATUS SetNominalLevel( WORD wBus, BOOL bState );
1079 	ECHOSTATUS GetNominalLevel( WORD wBus, PBYTE pbyState );
1080 
1081 	ECHOSTATUS SetAudioMonitor
1082 	(
1083 		WORD	wOutCh,
1084 		WORD	wInCh,
1085 		int	iGain,
1086 		BOOL 	fImmediate = TRUE
1087 	);
1088 
1089 	//
1090 	// SetBusOutGain - empty function on non-vmixer cards
1091 	//
1092 	virtual ECHOSTATUS SetBusOutGain(WORD wBusOut,int iGain)
1093 	{
1094 		return ECHOSTATUS_OK;
1095 	}
1096 
1097 	// Send volume to DSP
1098 	ECHOSTATUS UpdateAudioOutLineLevel();
1099 
1100 	// Send vmixer volume to DSP
1101 	virtual ECHOSTATUS UpdateVmixerLevel();
1102 
1103 	virtual ECHOSTATUS SetPipeOutGain
1104 	(
1105 		WORD 	wPipeOut,
1106 		WORD 	wBusOut,
1107 		int 	iGain,
1108 		BOOL 	fImmediate = TRUE
1109 	);
1110 
1111 	virtual ECHOSTATUS GetPipeOutGain
1112 	(
1113 		WORD 	wPipeOut,
1114 		WORD 	wBusOut,
1115 		int 	&iGain
1116 	);
1117 
1118 	virtual ECHOSTATUS SetBusInGain
1119 	(
1120 		WORD 	wBusIn,
1121 		int 	iGain
1122 	);
1123 
1124 	virtual ECHOSTATUS GetBusInGain( WORD wBusIn, int &iGain);
1125 
1126 	//
1127 	//	See description of ECHOGALS_METERS above for
1128 	//	data format information.
1129 	//
1130 	virtual ECHOSTATUS GetAudioMeters
1131 	(
1132 		PECHOGALS_METERS	pMeters
1133 	);
1134 
1135 	ECHOSTATUS GetMetersOn
1136 	(
1137 		BOOL & bOn
1138 	)
1139 		{	bOn = ( 0 != m_wMeterOnCount ); return ECHOSTATUS_OK; }
1140 
1141 	ECHOSTATUS SetMetersOn( BOOL bOn );
1142 
1143 	//
1144 	//	Set/get Audio Format
1145 	//
1146 	ECHOSTATUS SetAudioFormat
1147 	(
1148 		WORD 							wPipeIndex,
1149 		PECHOGALS_AUDIOFORMAT	pFormat,
1150 		BOOL							fDitherDigitalInputs
1151 	);
1152 	ECHOSTATUS GetAudioFormat
1153 	(
1154 		WORD 							wPipeIndex,
1155 		PECHOGALS_AUDIOFORMAT	pFormat
1156 	);
1157 
1158 #ifdef MIDI_SUPPORT
1159 
1160 	//
1161 	//	MIDI output activity
1162 	//
1163 	virtual BOOL IsMidiOutActive()
1164 		{ return FALSE; }
1165 
1166 	//
1167 	// Set MIDI I/O on or off
1168 	//
1169 	ECHOSTATUS SetMidiOn( BOOL bOn );
1170 
1171 	//
1172 	// Read and write MIDI data
1173 	//
1174 	ECHOSTATUS WriteMidi
1175 	(
1176 		PBYTE		pData,
1177 		DWORD		dwLength,
1178 		PDWORD	pdwActualCt
1179 	);
1180 
1181 	ECHOSTATUS ReadMidi
1182 	(
1183 		WORD 		wIndex,				// Buffer index
1184 		DWORD &	dwData				// Return data
1185 	);
1186 
1187 	//
1188 	// Returns TRUE if no more MIDI data can be sent
1189 	// right now
1190 	//
1191 	virtual BOOL MidiOutFull()
1192 	{
1193 		if (0 == (GetDspRegister( CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4))
1194 		{
1195 			return TRUE;
1196 		}
1197 
1198 		return FALSE;
1199 	}
1200 
1201 #endif // MIDI_SUPPORT
1202 
1203 	//
1204 	//	Reset the DSP and load new firmware.
1205 	//
1206 	virtual ECHOSTATUS LoadFirmware();
1207 
1208 	//
1209 	// Put the hardware to sleep
1210 	//
1211 	virtual ECHOSTATUS GoComatose();
1212 
1213 
1214 #ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT
1215 	//
1216 	// Get and set the digital input auto-mute flag
1217 	//
1218 	virtual ECHOSTATUS GetDigitalInputAutoMute(BOOL &fAutoMute);
1219 	virtual ECHOSTATUS SetDigitalInputAutoMute(BOOL fAutoMute);
1220 
1221 #endif // DIGITAL_INPUT_AUTO_MUTE_SUPPORT
1222 
1223 };		// class CDspCommObject
1224 
1225 typedef CDspCommObject * PCDspCommObject;
1226 
1227 #ifdef _WIN32
1228 #pragma pack( pop )
1229 #endif
1230 
1231 #endif
1232 
1233 // **** DspCommObject.h ****
1234