root/trunk/libffado/src/motu/motu_avdevice.cpp

Revision 654, 31.5 kB (checked in by f.ernoult, 16 years ago)

MotU: - Rewrite the ports declaration (easier to maintain for new devices)

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