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

Revision 302, 26.0 kB (checked in by jwoithe, 16 years ago)

jack driver: call detach() from finish() if detach() hasn't yet been called. This works around the fact that jack doesn't call detach() on close at this stage. Once this is fixed in jack the workaround can be removed.
C streaming API: set sample rate before device initialisation. This permits jackd to set the sample rate to that requested on the command line when starting jackd.
Motu device: start adding details to setSamplingFrequency() beyond that required for basic functionality.

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 #include <libraw1394/csr.h>
41
42 namespace Motu {
43
44 IMPL_DEBUG_MODULE( MotuDevice, MotuDevice, DEBUG_LEVEL_NORMAL );
45
46 char *motufw_modelname[] = {"[unknown]","828MkII", "Traveler"};
47
48 /* ======================================================================= */
49 /* Provide a mechanism for allocating iso channels and bandwidth to MOTU
50  * interfaces.
51  */
52
53 static signed int allocate_iso_channel(raw1394handle_t handle) {
54 /*
55  * Allocates an iso channel for use by the interface in a similar way to
56  * libiec61883.  Returns -1 on error (due to there being no free channels)
57  * or an allocated channel number.
58  * FIXME: As in libiec61883, channel 63 is not requested; this is either a
59  * bug or it's omitted since that's the channel preferred by video devices.
60  */
61         int c = -1;
62         for (c = 0; c < 63; c++)
63                 if (raw1394_channel_modify (handle, c, RAW1394_MODIFY_ALLOC) == 0)
64                         break;
65         if (c < 63)
66                 return c;
67         return -1;
68 }
69
70 static signed int free_iso_channel(raw1394handle_t handle, signed int channel) {
71 /*
72  * Deallocates an iso channel.  Returns -1 on error or 0 on success.  Silently
73  * ignores a request to deallocate a negative channel number.
74  */
75         if (channel < 0)
76                 return 0;
77         if (raw1394_channel_modify (handle, channel, RAW1394_MODIFY_FREE)!=0)
78                 return -1;
79         return 0;
80 }
81
82 static signed int get_iso_bandwidth_avail(raw1394handle_t handle) {
83 /*
84  * Returns the current value of the `bandwidth available' register on
85  * the IRM, or -1 on error.
86  */
87 quadlet_t buffer;
88 signed int result = raw1394_read (handle, raw1394_get_irm_id (handle),
89         CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
90         sizeof (quadlet_t), &buffer);
91
92         if (result < 0)
93                 return -1;
94         return ntohl(buffer);
95 }
96 /* ======================================================================= */
97
98 MotuDevice::MotuDevice( Ieee1394Service& ieee1394service,
99                         int nodeId,
100                         int verboseLevel )
101     : m_1394Service( &ieee1394service )
102     , m_motu_model( MOTUFW_MODEL_NONE )
103     , m_nodeId( nodeId )
104     , m_verboseLevel( verboseLevel )
105     , m_id(0)
106     , m_iso_recv_channel ( -1 )
107     , m_iso_send_channel ( -1 )
108     , m_bandwidth ( -1 )
109     , m_receiveProcessor ( 0 )
110     , m_transmitProcessor ( 0 )
111    
112 {
113     if ( m_verboseLevel ) {
114         setDebugLevel( DEBUG_LEVEL_VERBOSE );
115     }
116     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Motu::MotuDevice (NodeID %d)\n",
117                  nodeId );
118     m_configRom = new ConfigRom( m_1394Service, m_nodeId );
119     m_configRom->initialize();
120
121 }
122
123 MotuDevice::~MotuDevice()
124 {
125         // Free ieee1394 bus resources if they have been allocated
126         if (m_1394Service != NULL) {
127                 raw1394handle_t handle = m_1394Service->getHandle();
128                 if (m_bandwidth >= 0)
129                         if (raw1394_bandwidth_modify(handle, m_bandwidth, RAW1394_MODIFY_FREE) < 0)
130                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free bandwidth of %d\n", m_bandwidth);
131                 if (m_iso_recv_channel >= 0)
132                         if (raw1394_channel_modify(handle, m_iso_recv_channel, RAW1394_MODIFY_FREE) < 0)
133                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free recv iso channel %d\n", m_iso_recv_channel);
134                 if (m_iso_send_channel >= 0)
135                         if (raw1394_channel_modify(handle, m_iso_send_channel, RAW1394_MODIFY_FREE) < 0)
136                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free send iso channel %d\n", m_iso_send_channel);
137         }
138         delete m_configRom;
139 }
140
141 ConfigRom&
142 MotuDevice::getConfigRom() const
143 {
144     return *m_configRom;
145 }
146
147 bool
148 MotuDevice::discover()
149 {
150         // Find out if this device is one we know about
151         if (m_configRom->getUnitSpecifierId() == MOTUFW_VENDOR_MOTU) {
152                 switch (m_configRom->getUnitVersion()) {
153                     case MOTUFW_UNITVER_828mkII:
154                         m_motu_model = MOTUFW_MODEL_828mkII;
155                         break;
156                     case MOTUFW_UNITVER_TRAVELER:
157                         m_motu_model = MOTUFW_MODEL_TRAVELER;
158                         break;
159                 }
160         }
161         if (m_motu_model != MOTUFW_MODEL_NONE) {
162                 debugOutput( DEBUG_LEVEL_VERBOSE, "found MOTU %s\n",
163                         motufw_modelname[m_motu_model]);
164                 return true;
165         }
166
167         return false;
168 }
169
170 int
171 MotuDevice::getSamplingFrequency( ) {
172     /*
173      Implement the procedure to retrieve the samplerate here
174     */
175     quadlet_t q = ReadRegister(MOTUFW_REG_RATECTRL);
176     int rate = 0;
177
178     switch (q & MOTUFW_RATE_BASE_MASK) {
179         case MOTUFW_RATE_BASE_44100:
180             rate = 44100;
181             break;
182         case MOTUFW_RATE_BASE_48000:
183             rate = 48000;
184             break;
185     }
186     switch (q & MOTUFW_RATE_MULTIPLIER_MASK) {
187         case MOTUFW_RATE_MULTIPLIER_2X:
188             rate *= 2;
189             break;
190         case MOTUFW_RATE_MULTIPLIER_4X:
191             rate *= 4;
192             break;
193     }
194     return rate;
195 }
196
197 bool
198 MotuDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
199 {
200 /*
201  * Set the device samplerate.
202  */
203         char *src_name;
204         quadlet_t q, new_rate=0;
205         int i, supported=true;
206
207         switch ( samplingFrequency ) {
208                 case eSF_22050Hz:
209                         supported=false;
210                         break;
211                 case eSF_24000Hz:
212                         supported=false;
213                         break;
214                 case eSF_32000Hz:
215                         supported=false;
216                         break;
217                 case eSF_44100Hz:
218                         new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_1X;
219                         break;
220                 case eSF_48000Hz:
221                         new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_1X;
222                         break;
223                 case eSF_88200Hz:
224                         new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_2X;
225                         break;
226                 case eSF_96000Hz:
227                         new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_2X;
228                         break;
229                 case eSF_176400Hz:
230                         new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_4X;
231                         break;
232                 case eSF_192000Hz:
233                         new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_4X;
234                         break;
235                 default:
236                         supported=false;
237         }
238
239         // Update the clock control register.  FIXME: there's more to it than this
240         if (supported) {
241                 quadlet_t value=ReadRegister(MOTUFW_REG_RATECTRL);
242                 value &= ~(MOTUFW_RATE_BASE_MASK|MOTUFW_RATE_MULTIPLIER_MASK);
243                 value |= new_rate;
244 //        value |= 0x04000000;
245                 if (WriteRegister(MOTUFW_REG_RATECTRL, value) == 0) {
246                         supported=true;
247                 } else {
248                         supported=false;
249                 }
250                 // A write to the rate/clock control register requires the
251                 // textual name of the current clock source be sent to the
252                 // clock source name registers.
253                 switch (value & MOTUFW_CLKSRC_MASK) {
254                         case MOTUFW_CLKSRC_INTERNAL:
255                                 src_name = "Internal        ";
256                                 break;
257                         case MOTUFW_CLKSRC_ADAT_OPTICAL:
258                                 src_name = "ADAT Optical    ";
259                                 break;
260                         case MOTUFW_CLKSRC_SPDIF_TOSLINK:
261                                 src_name = "SPDIF/TOSLink   ";
262                                 break;
263                         case MOTUFW_CLKSRC_SMTPE:
264                                 src_name = "SMPTE           ";
265                                 break;
266                         case MOTUFW_CLKSRC_WORDCLOCK:
267                                 src_name = "Word Clock In   ";
268                                 break;
269                         case MOTUFW_CLKSRC_ADAT_9PIN:
270                                 src_name = "ADAT 9-pin      ";
271                                 break;
272                         case MOTUFW_CLKSRC_AES_EBU:
273                                 src_name = "AES-EBU         ";
274                                 break;
275                         default:
276                                 src_name = "Unknown         ";
277                 }
278                 for (i=0; i<16; i+=4) {
279                         q = (src_name[i]<<24) | (src_name[i+1]<<16) |
280                                 (src_name[i+2]<<8) | src_name[i+3];
281                         WriteRegister(MOTUFW_REG_CLKSRC_NAME0+i, q);
282                 }
283         }
284         return supported;
285 }
286
287 bool MotuDevice::setId( unsigned int id) {
288     debugOutput( DEBUG_LEVEL_VERBOSE, "Set id to %d...\n", id);
289     m_id=id;
290     return true;
291 }
292
293 void
294 MotuDevice::showDevice() const
295 {
296     printf( "MOTU %s at node %d\n",
297         motufw_modelname[m_motu_model],
298         m_nodeId );
299 }
300
301 bool
302 MotuDevice::prepare() {
303
304         int samp_freq = getSamplingFrequency();
305         unsigned int optical_mode = getOpticalMode();
306         unsigned int event_size = getEventSize();
307
308         raw1394handle_t handle = m_1394Service->getHandle();
309
310         debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
311
312         // Assign iso channels if not already done
313         if (m_iso_recv_channel < 0)
314                 m_iso_recv_channel = allocate_iso_channel(handle);
315         if (m_iso_send_channel < 0)
316                 m_iso_send_channel = allocate_iso_channel(handle);
317
318         debugOutput(DEBUG_LEVEL_VERBOSE, "recv channel = %d, send channel = %d\n",
319                 m_iso_recv_channel, m_iso_send_channel);
320
321         if (m_iso_recv_channel<0 || m_iso_send_channel<0) {
322                 debugFatal("Could not allocate iso channels!\n");
323                 return false;
324         }
325
326         // Allocate bandwidth if not previously done.
327         // FIXME: The bandwidth allocation calculation can probably be
328         // refined somewhat since this is currently based on a rudimentary
329         // understanding of the iso protocol.
330         // Currently we assume the following.
331         //   * Ack/iso gap = 0.05 us
332         //   * DATA_PREFIX = 0.16 us
333         //   * DATA_END    = 0.26 us
334         // These numbers are the worst-case figures given in the ieee1394
335         // standard.  This gives approximately 0.5 us of overheads per
336         // packet - around 25 bandwidth allocation units (from the ieee1394
337         // standard 1 bandwidth allocation unit is 125/6144 us).  We further
338         // assume the MOTU is running at S400 (which it should be) so one
339         // allocation unit is equivalent to 1 transmitted byte; thus the
340         // bandwidth allocation required for the packets themselves is just
341         // the size of the packet.  We allocate based on the maximum packet
342         // size (1160 bytes at 192 kHz) so the sampling frequency can be
343         // changed dynamically if this ends up being useful in future.
344         m_bandwidth = 25 + 1160;
345         debugOutput(DEBUG_LEVEL_VERBOSE, "Available bandwidth: %d\n",
346                 get_iso_bandwidth_avail(handle));
347         if (raw1394_bandwidth_modify(handle, m_bandwidth, RAW1394_MODIFY_ALLOC) < 0) {
348                 debugFatal("Could not allocate bandwidth of %d\n", m_bandwidth);
349                 m_bandwidth = -1;
350                 return false;
351         }
352         debugOutput(DEBUG_LEVEL_VERBOSE,
353                 "allocated bandwidth of %d for MOTU device\n", m_bandwidth);
354         debugOutput(DEBUG_LEVEL_VERBOSE,
355                 "remaining bandwidth: %d\n", get_iso_bandwidth_avail(handle));
356
357         m_receiveProcessor=new FreebobStreaming::MotuReceiveStreamProcessor(
358                 m_1394Service->getPort(), samp_freq, event_size);
359                                  
360         // The first thing is to initialize the processor.  This creates the
361         // data structures.
362         if(!m_receiveProcessor->init()) {
363                 debugFatal("Could not initialize receive processor!\n");
364                 return false;
365         }
366         m_receiveProcessor->setVerboseLevel(getDebugLevel());
367
368         // Now we add ports to the processor
369         debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
370        
371         char *buff;
372         unsigned int i;
373         FreebobStreaming::Port *p=NULL;
374
375         // Add audio capture ports
376         if (!addDirPorts(FreebobStreaming::Port::E_Capture, samp_freq, optical_mode)) {
377                 return false;
378         }
379
380         // example of adding an midi port:
381 //    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
382 //    p=new FreebobStreaming::MotuMidiPort(
383 //            buff,
384 //            FreebobStreaming::Port::E_Capture,
385 //            0 // you can add all other port specific stuff you
386 //              // need to pass by extending MotuXXXPort and MotuPortInfo
387 //    );
388 //    free(buff);
389 //
390 //    if (!p) {
391 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
392 //    } else {
393 //        if (!m_receiveProcessor->addPort(p)) {
394 //            debugWarning("Could not register port with stream processor\n");
395 //            return false;
396 //        } else {
397 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
398 //        }
399 //    }
400    
401         // example of adding an control port:
402 //    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
403 //    p=new FreebobStreaming::MotuControlPort(
404 //            buff,
405 //            FreebobStreaming::Port::E_Capture,
406 //            0 // you can add all other port specific stuff you
407 //              // need to pass by extending MotuXXXPort and MotuPortInfo
408 //    );
409 //    free(buff);
410 //
411 //    if (!p) {
412 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
413 //    } else {
414 //
415 //        if (!m_receiveProcessor->addPort(p)) {
416 //            debugWarning("Could not register port with stream processor\n");
417 //            return false;
418 //        } else {
419 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
420 //        }
421 //    }
422
423         // Do the same for the transmit processor
424         m_transmitProcessor=new FreebobStreaming::MotuTransmitStreamProcessor(
425                 m_1394Service->getPort(), getSamplingFrequency(), event_size);
426
427         m_transmitProcessor->setVerboseLevel(getDebugLevel());
428        
429         if(!m_transmitProcessor->init()) {
430                 debugFatal("Could not initialize transmit processor!\n");
431                 return false;
432         }
433
434         // Connect the transmit stream ticks-per-frame hook to the
435         // ticks-per-frame DLL integrator in the receive stream.
436         m_transmitProcessor->setTicksPerFrameDLL(m_receiveProcessor->getTicksPerFrameDLL());
437
438         // Now we add ports to the processor
439         debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
440
441         // Add audio playback ports
442         if (!addDirPorts(FreebobStreaming::Port::E_Playback, samp_freq, optical_mode)) {
443                 return false;
444         }
445
446 //      // example of adding an midi port:
447 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
448 //   
449 //    p=new FreebobStreaming::MotuMidiPort(
450 //            buff,
451 //            FreebobStreaming::Port::E_Playback,
452 //            0 // you can add all other port specific stuff you
453 //              // need to pass by extending MotuXXXPort and MotuPortInfo
454 //    );
455 //    free(buff);
456 //
457 //    if (!p) {
458 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
459 //    } else {
460 //        if (!m_transmitProcessor->addPort(p)) {
461 //            debugWarning("Could not register port with stream processor\n");
462 //            return false;
463 //        } else {
464 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
465 //        }
466 //    }
467    
468         // example of adding an control port:
469 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
470 //   
471 //    p=new FreebobStreaming::MotuControlPort(
472 //            buff,
473 //            FreebobStreaming::Port::E_Playback,
474 //            0 // you can add all other port specific stuff you
475 //              // need to pass by extending MotuXXXPort and MotuPortInfo
476 //    );
477 //    free(buff);
478 //
479 //    if (!p) {
480 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
481 //    } else {
482 //        if (!m_transmitProcessor->addPort(p)) {
483 //            debugWarning("Could not register port with stream processor\n");
484 //            return false;
485 //        } else {
486 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
487 //        }
488 //    }
489        
490         return true;
491 }
492
493 int
494 MotuDevice::getStreamCount() {
495         return 2; // one receive, one transmit
496 }
497
498 FreebobStreaming::StreamProcessor *
499 MotuDevice::getStreamProcessorByIndex(int i) {
500         switch (i) {
501         case 0:
502                 return m_receiveProcessor;
503         case 1:
504                 return m_transmitProcessor;
505         default:
506                 return NULL;
507         }
508         return 0;
509 }
510
511 int
512 MotuDevice::startStreamByIndex(int i) {
513
514 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
515
516         // NOTE: this assumes that you have two streams
517         switch (i) {
518         case 0:
519                 // TODO: do the stuff that is nescessary to make the device
520                 // transmit a stream
521
522                 // Set the streamprocessor channel to the one obtained by
523                 // the connection management
524                 m_receiveProcessor->setChannel(m_iso_recv_channel);
525
526                 // Mask out current transmit settings of the MOTU and replace
527                 // with new ones.  Turn bit 24 on to enable changes to the
528                 // MOTU's iso transmit settings when the iso control register
529                 // is written.  Bit 23 enables iso transmit from the MOTU.
530                 isoctrl &= 0xff00ffff;
531                 isoctrl |= (m_iso_recv_channel << 16);
532                 isoctrl |= 0x00c00000;
533                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
534                 break;
535         case 1:
536                 // TODO: do the stuff that is nescessary to make the device
537                 // receive a stream
538
539                 // Set the streamprocessor channel to the one obtained by
540                 // the connection management
541                 m_transmitProcessor->setChannel(m_iso_send_channel);
542
543                 // Mask out current receive settings of the MOTU and replace
544                 // with new ones.  Turn bit 31 on to enable changes to the
545                 // MOTU's iso receive settings when the iso control register
546                 // is written.  Bit 30 enables iso receive by the MOTU.
547                 isoctrl &= 0x00ffffff;
548                 isoctrl |= (m_iso_send_channel << 24);
549                 isoctrl |= 0xc0000000;
550                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
551                 break;
552                
553         default: // Invalid stream index
554                 return -1;
555         }
556
557         return 0;
558 }
559
560 int
561 MotuDevice::stopStreamByIndex(int i) {
562
563 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
564
565         // TODO: connection management: break connection
566         // cfr the start function
567
568         // NOTE: this assumes that you have two streams
569         switch (i) {
570         case 0:
571                 // Turn bit 22 off to disable iso send by the MOTU.  Turn
572                 // bit 23 on to enable changes to the MOTU's iso transmit
573                 // settings when the iso control register is written.
574                 isoctrl &= 0xffbfffff;
575                 isoctrl |= 0x00800000;
576                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
577                 break;
578         case 1:
579                 // Turn bit 30 off to disable iso receive by the MOTU.  Turn
580                 // bit 31 on to enable changes to the MOTU's iso receive
581                 // settings when the iso control register is written.
582                 isoctrl &= 0xbfffffff;
583                 isoctrl |= 0x80000000;
584                 WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
585                 break;
586                
587         default: // Invalid stream index
588                 return -1;
589         }
590
591         return 0;
592 }
593
594 signed int MotuDevice::getIsoRecvChannel(void) {
595         return m_iso_recv_channel;
596 }
597
598 signed int MotuDevice::getIsoSendChannel(void) {
599         return m_iso_send_channel;
600 }
601
602 unsigned int MotuDevice::getOpticalMode(void) {
603         unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
604         return reg & MOTUFW_OPTICAL_MODE_MASK;
605 }
606
607 signed int MotuDevice::setOpticalMode(unsigned int mode) {
608         unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
609
610         // FIXME: there seems to be more to it than this.
611         reg &= ~MOTUFW_OPTICAL_MODE_MASK;
612         reg |= mode & MOTUFW_OPTICAL_MODE_MASK;
613         return WriteRegister(MOTUFW_REG_ROUTE_PORT_CONF, reg);
614 }
615
616 signed int MotuDevice::getEventSize(void) {
617 //
618 // Return the size of a single event sent by the MOTU as part of an iso
619 // data packet in bytes.
620 //
621 // FIXME: for performance it may turn out best to calculate the event
622 // size in setOpticalMode and cache the result in a data field.  However,
623 // as it stands this will not adapt to dynamic changes in sample rate - we'd
624 // need a setFrameRate() for that.
625 //
626 // At the very least an event consists of the SPH (4 bytes), the control/MIDI
627 // bytes (6 bytes) and 8 analog audio channels (each 3 bytes long).  Note that
628 // all audio channels are sent using 3 bytes.
629 signed int sample_rate = getSamplingFrequency();
630 signed int optical_mode = getOpticalMode();
631 signed int size = 4+6+8*3;
632
633         // 2 channels of AES/EBU is present if a 1x or 2x sample rate is in
634         // use
635         if (sample_rate <= 96000)
636                 size += 2*3;
637
638         // 2 channels of (coax) SPDIF is present for 1x or 2x sample rates so
639         // long as the optical mode is not TOSLINK.  If the optical mode is 
640         // TOSLINK the coax SPDIF channels are replaced by optical TOSLINK   
641         // channels.  Thus between these options we always have an addition 
642         // 2 channels here for 1x or 2x sample rates regardless of the optical
643         // mode.
644         if (sample_rate <= 96000)
645                 size += 2*3;
646
647         // ADAT channels 1-4 are present for 1x or 2x sample rates so long
648         // as the optical mode is ADAT.
649         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT)
650                 size += 4*3;
651
652         // ADAT channels 5-8 are present for 1x sample rates so long as the
653         // optical mode is ADAT.
654         if (sample_rate<=48000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT)
655                 size += 4*3;
656
657         // When 1x or 2x sample rate is active there are an additional
658         // 2 channels sent in an event.  For capture it is a Mix1 return,
659         // while for playback it is a separate headphone mix.
660         if (sample_rate<=96000)
661                 size += 2*3;
662
663         // Finally round size up to the next quadlet boundary
664         return ((size+3)/4)*4;
665 }
666 /* ======================================================================= */
667
668 bool MotuDevice::addPort(FreebobStreaming::StreamProcessor *s_processor,
669   char *name, enum FreebobStreaming::Port::E_Direction direction,
670   int position, int size) {
671 /*
672  * Internal helper function to add a MOTU port to a given stream processor.
673  * This just saves the unnecessary replication of what is essentially
674  * boilerplate code.  Note that the port name is freed by this function
675  * prior to exit.
676  */
677 FreebobStreaming::Port *p=NULL;
678
679         p = new FreebobStreaming::MotuAudioPort(name, direction, position, size);
680
681         if (!p) {
682                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name);
683         } else {
684                 if (!s_processor->addPort(p)) {
685                         debugWarning("Could not register port with stream processor\n");
686                         free(name);
687                         return false;
688                 } else {
689                         debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",name);
690                 }
691                 p->enable();
692         }
693         free(name);
694         return true;
695 }
696 /* ======================================================================= */
697
698 bool MotuDevice::addDirPorts(
699   enum FreebobStreaming::Port::E_Direction direction,
700   unsigned int sample_rate, unsigned int optical_mode) {
701 /*
702  * Internal helper method: adds all required ports for the given direction
703  * based on the indicated sample rate and optical mode.
704  *
705  * Notes: currently ports are not created if they are disabled due to sample
706  * rate or optical mode.  However, it might be better to unconditionally
707  * create all ports and just disable those which are not active.
708  */
709 const char *mode_str = direction==FreebobStreaming::Port::E_Capture?"cap":"pbk";
710 const char *aux_str = direction==FreebobStreaming::Port::E_Capture?"Mix1":"Phones";
711 FreebobStreaming::StreamProcessor *s_processor;
712 unsigned int i, ofs;
713 char *buff;
714
715         if (direction == FreebobStreaming::Port::E_Capture) {
716                 s_processor = m_receiveProcessor;
717         } else {
718                 s_processor = m_transmitProcessor;
719         }
720         // Offset into an event's data of the first audio data
721         ofs = 10;
722
723         // Add ports for the Mix1 return / Phones send which is present for
724         // 1x and 2x sampling rates.
725         if (sample_rate<=96000) {
726                 for (i=0; i<2; i++, ofs+=3) {
727                         asprintf(&buff,"dev%d_%s_%s-%c", m_id, mode_str,
728                           aux_str, i==0?'L':'R');
729                         if (!addPort(s_processor, buff, direction, ofs, 0))
730                                 return false;
731                 }
732         }
733
734         // Unconditionally add the 8 analog capture ports since they are
735         // always present no matter what the device configuration is.
736         for (i=0; i<8; i++, ofs+=3) {
737                 asprintf(&buff,"dev%d_%s_Analog%d", m_id, mode_str, i+1);
738                 if (!addPort(s_processor, buff, direction, ofs, 0))
739                         return false;
740         }
741
742         // AES/EBU ports are present for 1x and 2x sampling rates on the
743         // Traveler.  On earlier interfaces (for example, 828 MkII) this
744         // space was taken up with a separate "main out" send.
745         // FIXME: what is in this position of incoming data on an 828 MkII?
746         if (sample_rate <= 96000) {
747                 for (i=0; i<2; i++, ofs+=3) {
748                         if (m_motu_model == MOTUFW_MODEL_TRAVELER) {
749                                 asprintf(&buff,"dev%d_%s_AES/EBU%d", m_id, mode_str, i+1);
750                         } else {
751                                 if (direction == FreebobStreaming::Port::E_Capture)
752                                         asprintf(&buff,"dev%d_%s_MainOut-%c", m_id, mode_str, i==0?'L':'R');
753                                 else
754                                         asprintf(&buff,"dev%d_%s_????%d", m_id, mode_str, i+1);
755                         }
756                         if (!addPort(s_processor, buff, direction, ofs, 0))
757                                 return false;
758                 }
759         }
760
761         // SPDIF ports are present for 1x and 2x sampling rates so long
762         // as the optical mode is not TOSLINK.
763         if (sample_rate<=96000 && optical_mode!=MOTUFW_OPTICAL_MODE_TOSLINK) {
764                 for (i=0; i<2; i++, ofs+=3) {
765                         asprintf(&buff,"dev%d_%s_SPDIF%d", m_id, mode_str, i+1);
766                         if (!addPort(s_processor, buff, direction, ofs, 0))
767                                 return false;
768                 }
769         }
770
771         // TOSLINK ports are present for 1x and 2x sampling rates so long
772         // as the optical mode is set to TOSLINK.
773         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_TOSLINK) {
774                 for (i=0; i<2; i++, ofs+=3) {
775                         asprintf(&buff,"dev%d_%s_TOSLINK%d", m_id, mode_str, i+1);
776                         if (!addPort(s_processor, buff, direction, ofs, 0))
777                                 return false;
778                 }
779         }
780
781         // ADAT ports 1-4 are present for 1x and 2x sampling rates so long
782         // as the optical mode is set to ADAT.
783         if (sample_rate<=96000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT) {
784                 for (i=0; i<4; i++, ofs+=3) {
785                         asprintf(&buff,"dev%d_%s_ADAT%d", m_id, mode_str, i+1);
786                         if (!addPort(s_processor, buff, direction, ofs, 0))
787                                 return false;
788                 }
789         }
790
791         // ADAT ports 5-8 are present for 1x sampling rates so long as the
792         // optical mode is set to ADAT.
793         if (sample_rate<=48000 && optical_mode==MOTUFW_OPTICAL_MODE_ADAT) {
794                 for (i=4; i<8; i++, ofs+=3) {
795                         asprintf(&buff,"dev%d_%s_ADAT%d", m_id, mode_str, i+1);
796                         if (!addPort(s_processor, buff, direction, ofs, 0))
797                                 return false;
798                 }
799         }
800
801         return true;
802 }
803 /* ======================================================================== */
804
805 unsigned int MotuDevice::ReadRegister(unsigned int reg) {
806 /*
807  * Attempts to read the requested register from the MOTU.
808  */
809
810 quadlet_t quadlet;
811 assert(m_1394Service);
812        
813   quadlet = 0;
814   // Note: 1394Service::read() expects a physical ID, not the node id
815   if (m_1394Service->read(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &quadlet) < 0) {
816     debugError("Error doing motu read from register 0x%06x\n",reg);
817   }
818
819   return ntohl(quadlet);
820 }
821
822 signed int MotuDevice::WriteRegister(unsigned int reg, quadlet_t data) {
823 /*
824  * Attempts to write the given data to the requested MOTU register.
825  */
826
827   unsigned int err = 0;
828   data = htonl(data);
829
830   // Note: 1394Service::write() expects a physical ID, not the node id
831   if (m_1394Service->write(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &data) < 0) {
832     err = 1;
833     debugError("Error doing motu write to register 0x%06x\n",reg);
834   }
835
836   usleep(100);
837   return (err==0)?0:-1;
838 }
839
840 }
Note: See TracBrowser for help on using the browser.