root/branches/libfreebob-2.0/src/motu/motu_avdevice.cpp

Revision 277, 22.8 kB (checked in by jwoithe, 17 years ago)

Start of work leading to MOTU iso transmission.
Fix use of uninitialised local variable in DelayLockedLoop::setIntegrator().

Line 
1 /* motu_avdevice.cpp
2  * Copyright (C) 2006 by Pieter Palmers
3  * Copyright (C) 2006 by Jonathan Woithe
4  *
5  * This file is part of FreeBob.
6  *
7  * FreeBob is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  * FreeBob is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with FreeBob; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19  * MA 02111-1307 USA.
20  */
21
22 #include "motu/motu_avdevice.h"
23 #include "configrom.h"
24
25 #include "libfreebobavc/ieee1394service.h"
26 #include "libfreebobavc/avc_definitions.h"
27
28 #include "debugmodule/debugmodule.h"
29
30 #include "libstreaming/MotuStreamProcessor.h"
31 #include "libstreaming/MotuPort.h"
32
33 #include "libutil/DelayLockedLoop.h"
34
35 #include <string>
36 #include <stdint.h>
37 #include <assert.h>
38 #include <netinet/in.h>
39
40 namespace Motu {
41
42 IMPL_DEBUG_MODULE( MotuDevice, MotuDevice, DEBUG_LEVEL_NORMAL );
43
44 char *motufw_modelname[] = {"[unknown]","828MkII", "Traveler"};
45
46 /* ======================================================================= */
47 /* Provide a mechanism for allocating iso channels to MOTU interfaces.
48  *
49  * FIXME: This is overly simplistic at present since it assumes there are no
50  * other users of iso channels on the firewire bus except MOTU interfaces.
51  * It does however allow more than one MOTU interface to exist on the same
52  * bus.  For now the first MOTU discovered will be allocated iso channels 0
53  * (send) and 1 (receive) which mirrors what the official driver appears to
54  * do.  Ultimately we need code to query the IRM for iso channels.
55  */
56 static signed int next_iso_recv_channel_num = 1;
57 static signed int next_iso_send_channel_num = 0; 
58      
59 static signed int next_iso_recv_channel(void) {
60 /*
61  * Returns the next available channel for ISO receive.  If there are no more
62  * available -1 is returned.  Currently the odd channels (starting from 1)
63  * are used for iso receive.  No provision is made to reuse previously
64  * allocated channels in the event that the applicable interface has been
65  * removed - this will change in future to use the IRM.
66  */
67         if (next_iso_recv_channel_num < 64) {
68                 next_iso_recv_channel_num+=2;
69                 return next_iso_recv_channel_num-2;
70         }
71         return -1;
72 }
73 static signed int next_iso_send_channel(void) {
74 /*
75  * Returns the next available channel for ISO send.  If there are no more
76  * available -1 is returned.  Currently the even channels (starting from 0)
77  * are used for iso receive.  No provision is made to reuse previously
78  * allocated channels in the event that the applicable interface has been
79  * removed - this will all change in future to use the IRM.
80  */
81         if (next_iso_send_channel_num < 64) {
82                 next_iso_send_channel_num+=2;
83                 return next_iso_send_channel_num-2;
84         }
85         return -1;
86 }
87 /* ======================================================================= */
88
89 MotuDevice::MotuDevice( Ieee1394Service& ieee1394service,
90                         int nodeId,
91                         int verboseLevel )
92     : m_1394Service( &ieee1394service )
93     , m_motu_model( MOTUFW_MODEL_NONE )
94     , m_nodeId( nodeId )
95     , m_verboseLevel( verboseLevel )
96     , m_id(0)
97     , m_iso_recv_channel ( -1 )
98     , m_iso_send_channel ( -1 )
99     , m_receiveProcessor ( 0 )
100     , m_transmitProcessor ( 0 )
101    
102 {
103     if ( m_verboseLevel ) {
104         setDebugLevel( DEBUG_LEVEL_VERBOSE );
105     }
106     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Motu::MotuDevice (NodeID %d)\n",
107                  nodeId );
108     m_configRom = new ConfigRom( m_1394Service, m_nodeId );
109     m_configRom->initialize();
110
111 }
112
113 MotuDevice::~MotuDevice()
114 {
115         delete m_configRom;
116 }
117
118 ConfigRom&
119 MotuDevice::getConfigRom() const
120 {
121     return *m_configRom;
122 }
123
124 bool
125 MotuDevice::discover()
126 {
127         // Find out if this device is one we know about
128         if (m_configRom->getUnitSpecifierId() == MOTUFW_VENDOR_MOTU) {
129                 switch (m_configRom->getUnitVersion()) {
130                     case MOTUFW_UNITVER_828mkII:
131                         m_motu_model = MOTUFW_MODEL_828mkII;
132                         break;
133                     case MOTUFW_UNITVER_TRAVELER:
134                         m_motu_model = MOTUFW_MODEL_TRAVELER;
135                         break;
136                 }
137         }
138         if (m_motu_model != MOTUFW_MODEL_NONE) {
139                 debugOutput( DEBUG_LEVEL_VERBOSE, "found MOTU %s\n",
140                         motufw_modelname[m_motu_model]);
141
142                 // Assign iso channels if not already done
143                 if (m_iso_recv_channel < 0)
144                         m_iso_recv_channel = next_iso_recv_channel();
145                 if (m_iso_send_channel < 0)
146                         m_iso_send_channel = next_iso_send_channel();
147                 return true;
148         }
149         return false;
150 }
151
152 int
153 MotuDevice::getSamplingFrequency( ) {
154     /*
155      Implement the procedure to retrieve the samplerate here
156     */
157     quadlet_t q = ReadRegister(MOTUFW_REG_RATECTRL);
158     int rate = 0;
159
160     switch (q & ~MOTUFW_BASE_RATE_MASK) {
161         case MOTUFW_BASE_RATE_44100:
162             rate = 44100;
163             break;
164         case MOTUFW_BASE_RATE_48000:
165             rate = 48000;
166             break;
167     }
168     switch (q & ~MOTUFW_RATE_MULTIPLIER_MASK) {
169         case MOTUFW_RATE_MULTIPLIER_2X:
170             rate *= 2;
171             break;
172         case MOTUFW_RATE_MULTIPLIER_4X:
173             rate *= 4;
174             break;
175     }
176     return rate;
177 }
178
179 bool
180 MotuDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
181 {
182     /*
183      Implement the procedure to set the samplerate here
184     */
185
186     quadlet_t new_rate=0;
187         int supported=true;
188
189     switch ( samplingFrequency ) {
190         case eSF_22050Hz:
191             supported=false;
192             break;
193         case eSF_24000Hz:
194             supported=false;
195             break;
196         case eSF_32000Hz:
197             supported=false;
198             break;
199         case eSF_44100Hz:
200             new_rate = MOTUFW_BASE_RATE_44100 | MOTUFW_RATE_MULTIPLIER_1X;
201             break;
202         case eSF_48000Hz:
203             new_rate = MOTUFW_BASE_RATE_48000 | MOTUFW_RATE_MULTIPLIER_1X;
204             break;
205         case eSF_88200Hz:
206             new_rate = MOTUFW_BASE_RATE_44100 | MOTUFW_RATE_MULTIPLIER_2X;
207             break;
208         case eSF_96000Hz:
209             new_rate = MOTUFW_BASE_RATE_48000 | MOTUFW_RATE_MULTIPLIER_2X;
210             break;
211         case eSF_176400Hz:
212             new_rate = MOTUFW_BASE_RATE_44100 | MOTUFW_RATE_MULTIPLIER_4X;
213             break;
214         case eSF_192000Hz:
215             new_rate = MOTUFW_BASE_RATE_48000 | MOTUFW_RATE_MULTIPLIER_4X;
216             break;
217         default:
218             supported=false;
219     }
220
221     // update the register.  FIXME: there's more to it than this
222     if (supported) {
223         quadlet_t value=ReadRegister(MOTUFW_REG_RATECTRL);
224         value &= ~(MOTUFW_BASE_RATE_MASK|MOTUFW_RATE_MULTIPLIER_MASK);
225         value |= new_rate;
226 //        value |= 0x04000000;
227         if (WriteRegister(MOTUFW_REG_RATECTRL, value) == 0) {
228             supported=true;
229         } else {
230             supported=false;
231         }
232     }
233     return supported;
234 }
235
236 bool MotuDevice::setId( unsigned int id) {
237     debugOutput( DEBUG_LEVEL_VERBOSE, "Set id to %d...\n", id);
238     m_id=id;
239     return true;
240 }
241
242 void
243 MotuDevice::showDevice() const
244 {
245     printf( "MOTU %s at node %d\n",
246         motufw_modelname[m_motu_model],
247         m_nodeId );
248 }
249
250 bool
251 MotuDevice::prepare() {
252
253         int samp_freq = getSamplingFrequency();
254         unsigned int optical_mode = getOpticalMode();
255         unsigned int event_size = getEventSize();
256
257         debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
258
259         m_receiveProcessor=new FreebobStreaming::MotuReceiveStreamProcessor(
260                 m_1394Service->getPort(), samp_freq, event_size);
261                                  
262         // the first thing is to initialize the processor
263         // this creates the data structures
264         if(!m_receiveProcessor->init()) {
265                 debugFatal("Could not initialize receive processor!\n");
266                 return false;
267         }
268         m_receiveProcessor->setVerboseLevel(getDebugLevel());
269
270         // now we add ports to the processor
271         debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
272        
273         // TODO: change this into something based upon device detection/configuration
274         char *buff;
275         unsigned int i;
276         FreebobStreaming::Port *p=NULL;
277
278         // Add audio capture ports
279         if (!addDirPorts(FreebobStreaming::Port::E_Capture, samp_freq, optical_mode)) {
280                 return false;
281         }
282
283         // example of adding an midi port:
284 //    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
285 //    p=new FreebobStreaming::MotuMidiPort(
286 //            buff,
287 //            FreebobStreaming::Port::E_Capture,
288 //            0 // you can add all other port specific stuff you
289 //              // need to pass by extending MotuXXXPort and MotuPortInfo
290 //    );
291 //    free(buff);
292 //
293 //    if (!p) {
294 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
295 //    } else {
296 //        if (!m_receiveProcessor->addPort(p)) {
297 //            debugWarning("Could not register port with stream processor\n");
298 //            return false;
299 //        } else {
300 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
301 //        }
302 //    }
303    
304         // example of adding an control port:
305 //    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
306 //    p=new FreebobStreaming::MotuControlPort(
307 //            buff,
308 //            FreebobStreaming::Port::E_Capture,
309 //            0 // you can add all other port specific stuff you
310 //              // need to pass by extending MotuXXXPort and MotuPortInfo
311 //    );
312 //    free(buff);
313 //
314 //    if (!p) {
315 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
316 //    } else {
317 //
318 //        if (!m_receiveProcessor->addPort(p)) {
319 //            debugWarning("Could not register port with stream processor\n");
320 //            return false;
321 //        } else {
322 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
323 //        }
324 //    }
325
326         // do the same for the transmit processor
327         m_transmitProcessor=new FreebobStreaming::MotuTransmitStreamProcessor(
328                 m_1394Service->getPort(), getSamplingFrequency(), event_size);
329
330         m_transmitProcessor->setVerboseLevel(getDebugLevel());
331        
332         if(!m_transmitProcessor->init()) {
333                 debugFatal("Could not initialize transmit processor!\n");
334                 return false;
335         }
336
337         // now we add ports to the processor
338         debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
339
340         // Add audio playback ports
341         if (!addDirPorts(FreebobStreaming::Port::E_Playback, samp_freq, optical_mode)) {
342                 return false;
343         }
344
345 //      // example of adding an midi port:
346 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
347 //   
348 //    p=new FreebobStreaming::MotuMidiPort(
349 //            buff,
350 //            FreebobStreaming::Port::E_Playback,
351 //            0 // you can add all other port specific stuff you
352 //              // need to pass by extending MotuXXXPort and MotuPortInfo
353 //    );
354 //    free(buff);
355 //
356 //    if (!p) {
357 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
358 //    } else {
359 //        if (!m_transmitProcessor->addPort(p)) {
360 //            debugWarning("Could not register port with stream processor\n");
361 //            return false;
362 //        } else {
363 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
364 //        }
365 //    }
366    
367         // example of adding an control port:
368 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
369 //   
370 //    p=new FreebobStreaming::MotuControlPort(
371 //            buff,
372 //            FreebobStreaming::Port::E_Playback,
373 //            0 // you can add all other port specific stuff you
374 //              // need to pass by extending MotuXXXPort and MotuPortInfo
375 //    );
376 //    free(buff);
377 //
378 //    if (!p) {
379 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
380 //    } else {
381 //        if (!m_transmitProcessor->addPort(p)) {
382 //            debugWarning("Could not register port with stream processor\n");
383 //            return false;
384 //        } else {
385 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
386 //        }
387 //    }
388        
389         return true;
390 }
391
392 int
393 MotuDevice::getStreamCount() {
394         return 2; // one receive, one transmit
395 }
396
397 FreebobStreaming::StreamProcessor *
398 MotuDevice::getStreamProcessorByIndex(int i) {
399         switch (i) {
400         case 0:
401                 return m_receiveProcessor;
402         case 1:
403                 return m_transmitProcessor;
404         default:
405                 return NULL;
406         }
407         return 0;
408 }
409
410 int
411 MotuDevice::startStreamByIndex(int i) {
412
413 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
414
415         // NOTE: this assumes that you have two streams
416         switch (i) {
417         case 0:
418                 // TODO: do the stuff that is nescessary to make the device
419                 // transmit a stream
420
421                 // Set the streamprocessor channel to the one obtained by
422                 // the connection management
423                 m_receiveProcessor->setChannel(m_iso_recv_channel);
424
425                 // Mask out current transmit settings of the MOTU and replace
426                 // with new ones.  Turn bit 24 on to enable changes to the
427                 // MOTU's iso transmit settings when the iso control register
428                 // is written.  Bit 23 enables iso transmit from the MOTU.
429                 isoctrl &= 0xff00ffff;
430                 isoctrl |= (m_iso_recv_channel << 16);
431                 isoctrl |= 0x00c00000;
432                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
433                 break;
434         case 1:
435                 // TODO: do the stuff that is nescessary to make the device
436                 // receive a stream
437
438                 // Set the streamprocessor channel to the one obtained by
439                 // the connection management
440                 m_transmitProcessor->setChannel(m_iso_send_channel);
441
442                 // Mask out current receive settings of the MOTU and replace
443                 // with new ones.  Turn bit 31 on to enable changes to the
444                 // MOTU's iso receive settings when the iso control register
445                 // is written.  Bit 30 enables iso receive by the MOTU.
446                 isoctrl &= 0x00ffffff;
447                 isoctrl |= (m_iso_send_channel << 24);
448                 isoctrl |= 0xc0000000;
449                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
450                 break;
451                
452         default: // Invalid stream index
453                 return -1;
454         }
455
456         return 0;
457 }
458
459 int
460 MotuDevice::stopStreamByIndex(int i) {
461
462 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
463
464         // TODO: connection management: break connection
465         // cfr the start function
466
467         // NOTE: this assumes that you have two streams
468         switch (i) {
469         case 0:
470                 // Turn bit 22 off to disable iso send by the MOTU.  Turn
471                 // bit 23 on to enable changes to the MOTU's iso transmit
472                 // settings when the iso control register is written.
473                 isoctrl &= 0xffbfffff;
474                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
475                 break;
476         case 1:
477                 // Turn bit 30 off to disable iso receive by the MOTU.  Turn
478                 // bit 31 on to enable changes to the MOTU's iso receive
479                 // settings when the iso control register is written.
480                 isoctrl &= 0xbfffffff;
481                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
482                 break;
483                
484         default: // Invalid stream index
485                 return -1;
486         }
487
488         return 0;
489 }
490
491 signed int MotuDevice::getIsoRecvChannel(void) {
492         return m_iso_recv_channel;
493 }
494
495 signed int MotuDevice::getIsoSendChannel(void) {
496         return m_iso_send_channel;
497 }
498
499 unsigned int MotuDevice::getOpticalMode(void) {
500         unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
501         return reg & MOTUFW_OPTICAL_MODE_MASK;
502 }
503
504 signed int MotuDevice::setOpticalMode(unsigned int mode) {
505         unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
506
507         // FIXME: there seems to be more to it than this.
508         reg &= ~MOTUFW_OPTICAL_MODE_MASK;
509         reg |= mode & MOTUFW_OPTICAL_MODE_MASK;
510         return WriteRegister(MOTUFW_REG_ROUTE_PORT_CONF, reg);
511 }
512
513 signed int MotuDevice::getEventSize(void) {
514 //
515 // Return the size of a single event sent by the MOTU as part of an iso
516 // data packet in bytes.
517 //
518 // FIXME: for performance it may turn out best to calculate the event
519 // size in setOpticalMode and cache the result in a data field.  However,
520 // as it stands this will not adapt to dynamic changes in sample rate - we'd
521 // need a setFrameRate() for that.
522 //
523 // At the very least an event consists of the SPH (4 bytes), the control/MIDI
524 // bytes (6 bytes) and 8 analog audio channels (each 3 bytes long).  Note that
525 // all audio channels are sent using 3 bytes.
526 signed int sample_rate = getSamplingFrequency();
527 signed int optical_mode = getOpticalMode();
528 signed int size = 4+6+8*3;
529
530         // 2 channels of AES/EBU is present if a 1x or 2x sample rate is in
531         // use
532         if (sample_rate <= 96000)
533                 size += 2*3;
534
535         // 2 channels of (coax) SPDIF is present for 1x or 2x sample rates so
536         // long as the optical mode is not TOSLINK.  If the optical mode is 
537         // TOSLINK the coax SPDIF channels are replaced by optical TOSLINK   
538         // channels.  Thus between these options we always have an addition 
539         // 2 channels here for 1x or 2x sample rates regardless of the optical
540         // mode.
541         if (sample_rate <= 96000)
542                 size += 2*3;
543
544         // ADAT channels 1-4 are present for 1x or 2x sample rates so long
545         // as the optical mode is ADAT.
546         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT)
547                 size += 4*3;
548
549         // ADAT channels 5-8 are present for 1x sample rates so long as the
550         // optical mode is ADAT.
551         if (sample_rate<=48000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT)
552                 size += 4*3;
553
554         // When 1x or 2x sample rate is active there are an additional
555         // 2 channels sent in an event.  For capture it is a Mix1 return,
556         // while for playback it is a separate headphone mix.
557         if (sample_rate<=96000)
558                 size += 2*3;
559
560         // Finally round size up to the next quadlet boundary
561         return ((size+3)/4)*4;
562 }
563 /* ======================================================================= */
564
565 bool MotuDevice::addPort(FreebobStreaming::StreamProcessor *s_processor,
566   char *name, enum FreebobStreaming::Port::E_Direction direction,
567   int position, int size) {
568 /*
569  * Internal helper function to add a MOTU port to a given stream processor.
570  * This just saves the unnecessary replication of what is essentially
571  * boilerplate code.  Note that the port name is freed by this function
572  * prior to exit.
573  */
574 FreebobStreaming::Port *p=NULL;
575
576         p = new FreebobStreaming::MotuAudioPort(name, direction, position, size);
577
578         if (!p) {
579                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name);
580         } else {
581                 if (!s_processor->addPort(p)) {
582                         debugWarning("Could not register port with stream processor\n");
583                         free(name);
584                         return false;
585                 } else {
586                         debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",name);
587                 }
588                 p->enable();
589         }
590         free(name);
591         return true;
592 }
593 /* ======================================================================= */
594
595 bool MotuDevice::addDirPorts(
596   enum FreebobStreaming::Port::E_Direction direction,
597   unsigned int sample_rate, unsigned int optical_mode) {
598 /*
599  * Internal helper method: adds all required ports for the given direction
600  * based on the indicated sample rate and optical mode.
601  *
602  * Notes: currently ports are not created if they are disabled due to sample
603  * rate or optical mode.  However, it might be better to unconditionally
604  * create all ports and just disable those which are not active.
605  */
606 const char *mode_str = direction==FreebobStreaming::Port::E_Capture?"cap":"pbk";
607 const char *aux_str = direction==FreebobStreaming::Port::E_Capture?"Mix1":"Phones";
608 FreebobStreaming::StreamProcessor *s_processor;
609 unsigned int i, ofs;
610 char *buff;
611
612         if (direction == FreebobStreaming::Port::E_Capture) {
613                 s_processor = m_receiveProcessor;
614         } else {
615                 s_processor = m_transmitProcessor;
616         }
617         // Offset into an event's data of the first audio data
618         ofs = 10;
619
620         // Add ports for the Mix1 return / Phones send which is present for
621         // 1x and 2x sampling rates.
622         if (sample_rate<=96000) {
623                 for (i=0; i<2; i++, ofs+=3) {
624                         asprintf(&buff,"dev%d_%s_%s-%c", m_id, mode_str,
625                           aux_str, i==0?'L':'R');
626                         if (!addPort(s_processor, buff, direction, ofs, 0))
627                                 return false;
628                 }
629         }
630
631         // Unconditionally add the 8 analog capture ports since they are
632         // always present no matter what the device configuration is.
633         for (i=0; i<8; i++, ofs+=3) {
634                 asprintf(&buff,"dev%d_%s_Analog%d", m_id, mode_str, i+1);
635                 if (!addPort(s_processor, buff, direction, ofs, 0))
636                         return false;
637         }
638
639         // AES/EBU ports are present for 1x and 2x sampling rates on the
640         // Traveler.  On earlier interfaces (for example, 828 MkII) this
641         // space was taken up with a separate "main out" send.
642         // FIXME: what is in this position of incoming data on an 828 MkII?
643         if (sample_rate <= 96000) {
644                 for (i=0; i<2; i++, ofs+=3) {
645                         if (m_motu_model == MOTUFW_MODEL_TRAVELER) {
646                                 asprintf(&buff,"dev%d_%s_AES/EBU%d", m_id, mode_str, i+1);
647                         } else {
648                                 if (direction == FreebobStreaming::Port::E_Capture)
649                                         asprintf(&buff,"dev%d_%s_MainOut-%c", m_id, mode_str, i==0?'L':'R');
650                                 else
651                                         asprintf(&buff,"dev%d_%s_????%d", m_id, mode_str, i+1);
652                         }
653                         if (!addPort(s_processor, buff, direction, ofs, 0))
654                                 return false;
655                 }
656         }
657
658         // SPDIF ports are present for 1x and 2x sampling rates so long
659         // as the optical mode is not TOSLINK.
660         if (sample_rate<=96000 && optical_mode!=MOTUFW_OPTICAL_MODE_TOSLINK) {
661                 for (i=0; i<2; i++, ofs+=3) {
662                         asprintf(&buff,"dev%d_%s_SPDIF%d", m_id, mode_str, i+1);
663                         if (!addPort(s_processor, buff, direction, ofs, 0))
664                                 return false;
665                 }
666         }
667
668         // TOSLINK ports are present for 1x and 2x sampling rates so long
669         // as the optical mode is set to TOSLINK.
670         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_TOSLINK) {
671                 for (i=0; i<2; i++, ofs+=3) {
672                         asprintf(&buff,"dev%d_%s_TOSLINK%d", m_id, mode_str, i+1);
673                         if (!addPort(s_processor, buff, direction, ofs, 0))
674                                 return false;
675                 }
676         }
677
678         // ADAT ports 1-4 are present for 1x and 2x sampling rates so long
679         // as the optical mode is set to ADAT.
680         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT) {
681                 for (i=0; i<4; i++, ofs+=3) {
682                         asprintf(&buff,"dev%d_%s_ADAT%d", m_id, mode_str, i+1);
683                         if (!addPort(s_processor, buff, direction, ofs, 0))
684                                 return false;
685                 }
686         }
687
688         // ADAT ports 5-8 are present for 1x sampling rates so long as the
689         // optical mode is set to ADAT.
690         if (sample_rate<=48000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT) {
691                 for (i=4; i<8; i++, ofs+=3) {
692                         asprintf(&buff,"dev%d_%s_ADAT%d", m_id, mode_str, i+1);
693                         if (!addPort(s_processor, buff, direction, ofs, 0))
694                                 return false;
695                 }
696         }
697
698         return true;
699 }
700 /* ======================================================================== */
701
702 unsigned int MotuDevice::ReadRegister(unsigned int reg) {
703 /*
704  * Attempts to read the requested register from the MOTU.
705  */
706
707 quadlet_t quadlet;
708 assert(m_1394Service);
709        
710   quadlet = 0;
711   // Note: 1394Service::read() expects a physical ID, not the node id
712   if (m_1394Service->read(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &quadlet) < 0) {
713     debugError("Error doing motu read from register 0x%06x\n",reg);
714   }
715
716   return ntohl(quadlet);
717 }
718
719 signed int MotuDevice::WriteRegister(unsigned int reg, quadlet_t data) {
720 /*
721  * Attempts to write the given data to the requested MOTU register.
722  */
723
724   unsigned int err = 0;
725   data = htonl(data);
726
727   // Note: 1394Service::write() expects a physical ID, not the node id
728   if (m_1394Service->write(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &data) < 0) {
729     err = 1;
730     debugError("Error doing motu write to register 0x%06x\n",reg);
731   }
732
733   usleep(100);
734   return (err==0)?0:-1;
735 }
736
737 }
Note: See TracBrowser for help on using the browser.