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

Revision 283, 23.0 kB (checked in by jwoithe, 18 years ago)

More additions for MOTU playback (transmit) functionality.
Bugfix for MOTU stream stop method.

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         // Connect the transmit stream to the SPH offset DLL in the
338         // receive stream.
339         m_transmitProcessor->set_sph_ofs_dll(m_receiveProcessor->get_sph_ofs_dll());
340
341         // now we add ports to the processor
342         debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
343
344         // Add audio playback ports
345         if (!addDirPorts(FreebobStreaming::Port::E_Playback, samp_freq, optical_mode)) {
346                 return false;
347         }
348
349 //      // example of adding an midi port:
350 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
351 //   
352 //    p=new FreebobStreaming::MotuMidiPort(
353 //            buff,
354 //            FreebobStreaming::Port::E_Playback,
355 //            0 // you can add all other port specific stuff you
356 //              // need to pass by extending MotuXXXPort and MotuPortInfo
357 //    );
358 //    free(buff);
359 //
360 //    if (!p) {
361 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
362 //    } else {
363 //        if (!m_transmitProcessor->addPort(p)) {
364 //            debugWarning("Could not register port with stream processor\n");
365 //            return false;
366 //        } else {
367 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
368 //        }
369 //    }
370    
371         // example of adding an control port:
372 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
373 //   
374 //    p=new FreebobStreaming::MotuControlPort(
375 //            buff,
376 //            FreebobStreaming::Port::E_Playback,
377 //            0 // you can add all other port specific stuff you
378 //              // need to pass by extending MotuXXXPort and MotuPortInfo
379 //    );
380 //    free(buff);
381 //
382 //    if (!p) {
383 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
384 //    } else {
385 //        if (!m_transmitProcessor->addPort(p)) {
386 //            debugWarning("Could not register port with stream processor\n");
387 //            return false;
388 //        } else {
389 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
390 //        }
391 //    }
392        
393         return true;
394 }
395
396 int
397 MotuDevice::getStreamCount() {
398         return 2; // one receive, one transmit
399 }
400
401 FreebobStreaming::StreamProcessor *
402 MotuDevice::getStreamProcessorByIndex(int i) {
403         switch (i) {
404         case 0:
405                 return m_receiveProcessor;
406         case 1:
407                 return m_transmitProcessor;
408         default:
409                 return NULL;
410         }
411         return 0;
412 }
413
414 int
415 MotuDevice::startStreamByIndex(int i) {
416
417 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
418
419         // NOTE: this assumes that you have two streams
420         switch (i) {
421         case 0:
422                 // TODO: do the stuff that is nescessary to make the device
423                 // transmit a stream
424
425                 // Set the streamprocessor channel to the one obtained by
426                 // the connection management
427                 m_receiveProcessor->setChannel(m_iso_recv_channel);
428
429                 // Mask out current transmit settings of the MOTU and replace
430                 // with new ones.  Turn bit 24 on to enable changes to the
431                 // MOTU's iso transmit settings when the iso control register
432                 // is written.  Bit 23 enables iso transmit from the MOTU.
433                 isoctrl &= 0xff00ffff;
434                 isoctrl |= (m_iso_recv_channel << 16);
435                 isoctrl |= 0x00c00000;
436                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
437                 break;
438         case 1:
439                 // TODO: do the stuff that is nescessary to make the device
440                 // receive a stream
441
442                 // Set the streamprocessor channel to the one obtained by
443                 // the connection management
444                 m_transmitProcessor->setChannel(m_iso_send_channel);
445
446                 // Mask out current receive settings of the MOTU and replace
447                 // with new ones.  Turn bit 31 on to enable changes to the
448                 // MOTU's iso receive settings when the iso control register
449                 // is written.  Bit 30 enables iso receive by the MOTU.
450                 isoctrl &= 0x00ffffff;
451                 isoctrl |= (m_iso_send_channel << 24);
452                 isoctrl |= 0xc0000000;
453                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
454                 break;
455                
456         default: // Invalid stream index
457                 return -1;
458         }
459
460         return 0;
461 }
462
463 int
464 MotuDevice::stopStreamByIndex(int i) {
465
466 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
467
468         // TODO: connection management: break connection
469         // cfr the start function
470
471         // NOTE: this assumes that you have two streams
472         switch (i) {
473         case 0:
474                 // Turn bit 22 off to disable iso send by the MOTU.  Turn
475                 // bit 23 on to enable changes to the MOTU's iso transmit
476                 // settings when the iso control register is written.
477                 isoctrl &= 0xffbfffff;
478                 isoctrl |= 0x00800000;
479                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
480                 break;
481         case 1:
482                 // Turn bit 30 off to disable iso receive by the MOTU.  Turn
483                 // bit 31 on to enable changes to the MOTU's iso receive
484                 // settings when the iso control register is written.
485                 isoctrl &= 0xbfffffff;
486                 isoctrl |= 0x80000000;
487                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
488                 break;
489                
490         default: // Invalid stream index
491                 return -1;
492         }
493
494         return 0;
495 }
496
497 signed int MotuDevice::getIsoRecvChannel(void) {
498         return m_iso_recv_channel;
499 }
500
501 signed int MotuDevice::getIsoSendChannel(void) {
502         return m_iso_send_channel;
503 }
504
505 unsigned int MotuDevice::getOpticalMode(void) {
506         unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
507         return reg & MOTUFW_OPTICAL_MODE_MASK;
508 }
509
510 signed int MotuDevice::setOpticalMode(unsigned int mode) {
511         unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
512
513         // FIXME: there seems to be more to it than this.
514         reg &= ~MOTUFW_OPTICAL_MODE_MASK;
515         reg |= mode & MOTUFW_OPTICAL_MODE_MASK;
516         return WriteRegister(MOTUFW_REG_ROUTE_PORT_CONF, reg);
517 }
518
519 signed int MotuDevice::getEventSize(void) {
520 //
521 // Return the size of a single event sent by the MOTU as part of an iso
522 // data packet in bytes.
523 //
524 // FIXME: for performance it may turn out best to calculate the event
525 // size in setOpticalMode and cache the result in a data field.  However,
526 // as it stands this will not adapt to dynamic changes in sample rate - we'd
527 // need a setFrameRate() for that.
528 //
529 // At the very least an event consists of the SPH (4 bytes), the control/MIDI
530 // bytes (6 bytes) and 8 analog audio channels (each 3 bytes long).  Note that
531 // all audio channels are sent using 3 bytes.
532 signed int sample_rate = getSamplingFrequency();
533 signed int optical_mode = getOpticalMode();
534 signed int size = 4+6+8*3;
535
536         // 2 channels of AES/EBU is present if a 1x or 2x sample rate is in
537         // use
538         if (sample_rate <= 96000)
539                 size += 2*3;
540
541         // 2 channels of (coax) SPDIF is present for 1x or 2x sample rates so
542         // long as the optical mode is not TOSLINK.  If the optical mode is 
543         // TOSLINK the coax SPDIF channels are replaced by optical TOSLINK   
544         // channels.  Thus between these options we always have an addition 
545         // 2 channels here for 1x or 2x sample rates regardless of the optical
546         // mode.
547         if (sample_rate <= 96000)
548                 size += 2*3;
549
550         // ADAT channels 1-4 are present for 1x or 2x sample rates so long
551         // as the optical mode is ADAT.
552         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT)
553                 size += 4*3;
554
555         // ADAT channels 5-8 are present for 1x sample rates so long as the
556         // optical mode is ADAT.
557         if (sample_rate<=48000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT)
558                 size += 4*3;
559
560         // When 1x or 2x sample rate is active there are an additional
561         // 2 channels sent in an event.  For capture it is a Mix1 return,
562         // while for playback it is a separate headphone mix.
563         if (sample_rate<=96000)
564                 size += 2*3;
565
566         // Finally round size up to the next quadlet boundary
567         return ((size+3)/4)*4;
568 }
569 /* ======================================================================= */
570
571 bool MotuDevice::addPort(FreebobStreaming::StreamProcessor *s_processor,
572   char *name, enum FreebobStreaming::Port::E_Direction direction,
573   int position, int size) {
574 /*
575  * Internal helper function to add a MOTU port to a given stream processor.
576  * This just saves the unnecessary replication of what is essentially
577  * boilerplate code.  Note that the port name is freed by this function
578  * prior to exit.
579  */
580 FreebobStreaming::Port *p=NULL;
581
582         p = new FreebobStreaming::MotuAudioPort(name, direction, position, size);
583
584         if (!p) {
585                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name);
586         } else {
587                 if (!s_processor->addPort(p)) {
588                         debugWarning("Could not register port with stream processor\n");
589                         free(name);
590                         return false;
591                 } else {
592                         debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",name);
593                 }
594                 p->enable();
595         }
596         free(name);
597         return true;
598 }
599 /* ======================================================================= */
600
601 bool MotuDevice::addDirPorts(
602   enum FreebobStreaming::Port::E_Direction direction,
603   unsigned int sample_rate, unsigned int optical_mode) {
604 /*
605  * Internal helper method: adds all required ports for the given direction
606  * based on the indicated sample rate and optical mode.
607  *
608  * Notes: currently ports are not created if they are disabled due to sample
609  * rate or optical mode.  However, it might be better to unconditionally
610  * create all ports and just disable those which are not active.
611  */
612 const char *mode_str = direction==FreebobStreaming::Port::E_Capture?"cap":"pbk";
613 const char *aux_str = direction==FreebobStreaming::Port::E_Capture?"Mix1":"Phones";
614 FreebobStreaming::StreamProcessor *s_processor;
615 unsigned int i, ofs;
616 char *buff;
617
618         if (direction == FreebobStreaming::Port::E_Capture) {
619                 s_processor = m_receiveProcessor;
620         } else {
621                 s_processor = m_transmitProcessor;
622         }
623         // Offset into an event's data of the first audio data
624         ofs = 10;
625
626         // Add ports for the Mix1 return / Phones send which is present for
627         // 1x and 2x sampling rates.
628         if (sample_rate<=96000) {
629                 for (i=0; i<2; i++, ofs+=3) {
630                         asprintf(&buff,"dev%d_%s_%s-%c", m_id, mode_str,
631                           aux_str, i==0?'L':'R');
632                         if (!addPort(s_processor, buff, direction, ofs, 0))
633                                 return false;
634                 }
635         }
636
637         // Unconditionally add the 8 analog capture ports since they are
638         // always present no matter what the device configuration is.
639         for (i=0; i<8; i++, ofs+=3) {
640                 asprintf(&buff,"dev%d_%s_Analog%d", m_id, mode_str, i+1);
641                 if (!addPort(s_processor, buff, direction, ofs, 0))
642                         return false;
643         }
644
645         // AES/EBU ports are present for 1x and 2x sampling rates on the
646         // Traveler.  On earlier interfaces (for example, 828 MkII) this
647         // space was taken up with a separate "main out" send.
648         // FIXME: what is in this position of incoming data on an 828 MkII?
649         if (sample_rate <= 96000) {
650                 for (i=0; i<2; i++, ofs+=3) {
651                         if (m_motu_model == MOTUFW_MODEL_TRAVELER) {
652                                 asprintf(&buff,"dev%d_%s_AES/EBU%d", m_id, mode_str, i+1);
653                         } else {
654                                 if (direction == FreebobStreaming::Port::E_Capture)
655                                         asprintf(&buff,"dev%d_%s_MainOut-%c", m_id, mode_str, i==0?'L':'R');
656                                 else
657                                         asprintf(&buff,"dev%d_%s_????%d", m_id, mode_str, i+1);
658                         }
659                         if (!addPort(s_processor, buff, direction, ofs, 0))
660                                 return false;
661                 }
662         }
663
664         // SPDIF ports are present for 1x and 2x sampling rates so long
665         // as the optical mode is not TOSLINK.
666         if (sample_rate<=96000 && optical_mode!=MOTUFW_OPTICAL_MODE_TOSLINK) {
667                 for (i=0; i<2; i++, ofs+=3) {
668                         asprintf(&buff,"dev%d_%s_SPDIF%d", m_id, mode_str, i+1);
669                         if (!addPort(s_processor, buff, direction, ofs, 0))
670                                 return false;
671                 }
672         }
673
674         // TOSLINK ports are present for 1x and 2x sampling rates so long
675         // as the optical mode is set to TOSLINK.
676         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_TOSLINK) {
677                 for (i=0; i<2; i++, ofs+=3) {
678                         asprintf(&buff,"dev%d_%s_TOSLINK%d", m_id, mode_str, i+1);
679                         if (!addPort(s_processor, buff, direction, ofs, 0))
680                                 return false;
681                 }
682         }
683
684         // ADAT ports 1-4 are present for 1x and 2x sampling rates so long
685         // as the optical mode is set to ADAT.
686         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT) {
687                 for (i=0; i<4; i++, ofs+=3) {
688                         asprintf(&buff,"dev%d_%s_ADAT%d", m_id, mode_str, i+1);
689                         if (!addPort(s_processor, buff, direction, ofs, 0))
690                                 return false;
691                 }
692         }
693
694         // ADAT ports 5-8 are present for 1x sampling rates so long as the
695         // optical mode is set to ADAT.
696         if (sample_rate<=48000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT) {
697                 for (i=4; i<8; i++, ofs+=3) {
698                         asprintf(&buff,"dev%d_%s_ADAT%d", m_id, mode_str, i+1);
699                         if (!addPort(s_processor, buff, direction, ofs, 0))
700                                 return false;
701                 }
702         }
703
704         return true;
705 }
706 /* ======================================================================== */
707
708 unsigned int MotuDevice::ReadRegister(unsigned int reg) {
709 /*
710  * Attempts to read the requested register from the MOTU.
711  */
712
713 quadlet_t quadlet;
714 assert(m_1394Service);
715        
716   quadlet = 0;
717   // Note: 1394Service::read() expects a physical ID, not the node id
718   if (m_1394Service->read(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &quadlet) < 0) {
719     debugError("Error doing motu read from register 0x%06x\n",reg);
720   }
721
722   return ntohl(quadlet);
723 }
724
725 signed int MotuDevice::WriteRegister(unsigned int reg, quadlet_t data) {
726 /*
727  * Attempts to write the given data to the requested MOTU register.
728  */
729
730   unsigned int err = 0;
731   data = htonl(data);
732
733   // Note: 1394Service::write() expects a physical ID, not the node id
734   if (m_1394Service->write(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &data) < 0) {
735     err = 1;
736     debugError("Error doing motu write to register 0x%06x\n",reg);
737   }
738
739   usleep(100);
740   return (err==0)?0:-1;
741 }
742
743 }
Note: See TracBrowser for help on using the browser.