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

Revision 404, 29.4 kB (checked in by pieterpalmers, 17 years ago)

- introduce support framework for DICE and Metric Halo
- change probe/discovery code to make adding devices easier
- made conditional compilation effectively work.

./configure now has the following switches:

--enable-bebob build BeBoB support (default=yes)
--enable-motu build Motu support (default=no)
--enable-dice build DICE support (default=no)
--enable-metric-halo build Metric Halo support (note: completely useless)

(default=no)

--enable-rme build RME support (note: completely useless)

(default=no)

--enable-bounce build Bounce device support (default=no)
--enable-all-devices build support for all supported devices (default=no)

these now turn on/off compilation effectively.

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