root/branches/streaming-rework/src/motu/motu_avdevice.cpp

Revision 416, 28.0 kB (checked in by pieterpalmers, 16 years ago)

- Introduced a generic option mechanism. AvDevices? now automatically

inherit from OptionContainer? (via IAvDevice) and can specify options
(e.g. at construction). These can then be get/set using the container
functions from the outside.

- Modified the bebob, bounce, motu, mh, rme AvDevices? to make use of the

option system for their Id value and the 'snoopMode' option.

- Made M-Audio avdevice a subclass of the BeBoB avdevice to avoid code

duplication.

- Extended the bounce device

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