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 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 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 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 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 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 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 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 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 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