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