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

Revision 412, 27.4 kB (checked in by pieterpalmers, 17 years ago)

- added some documentation
- added a lock()/unlock() to IAvDevice (see header)
- reimplemented test-freebob to the new C++ api
- started with support for AddressRangeMapping?, i.e. response

to reads/writes of the 1394 memory space on the host

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