root/branches/streaming-rework/src/rme/rme_avdevice.cpp

Revision 404, 16.0 kB (checked in by pieterpalmers, 16 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 /* rme_avdevice.cpp
2  * Copyright (C) 2006 by Jonathan Woithe
3  * Copyright (C) 2006,2007 by Pieter Palmers
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_RME
23 #warning RME support is currently useless (detection only)
24
25 #include "rme/rme_avdevice.h"
26 #include "configrom.h"
27
28 #include "libfreebobavc/ieee1394service.h"
29 #include "libfreebobavc/avc_definitions.h"
30
31 #include "debugmodule/debugmodule.h"
32
33 //#include "libstreaming/MotuStreamProcessor.h"
34 //#include "libstreaming/MotuPort.h"
35
36 #include "libutil/DelayLockedLoop.h"
37
38 #include <string>
39 #include <stdint.h>
40 #include <assert.h>
41 #include <netinet/in.h>
42
43 #include <libraw1394/csr.h>
44
45 namespace Rme {
46
47 IMPL_DEBUG_MODULE( RmeDevice, RmeDevice, DEBUG_LEVEL_NORMAL );
48
49 // to define the supported devices
50 static VendorModelEntry supportedDeviceList[] =
51 {
52     {0x00000a35, 0x0001, "RME", "Fireface-800"},  // RME Fireface-800
53 };
54
55 /* ======================================================================= */
56 /* Provide a mechanism for allocating iso channels and bandwidth to MOTU
57  * interfaces.
58  */
59
60 // static signed int allocate_iso_channel(raw1394handle_t handle) {
61 // /*
62 //  * Allocates an iso channel for use by the interface in a similar way to
63 //  * libiec61883.  Returns -1 on error (due to there being no free channels)
64 //  * or an allocated channel number.
65 //  * FIXME: As in libiec61883, channel 63 is not requested; this is either a
66 //  * bug or it's omitted since that's the channel preferred by video devices.
67 //  */
68 //      int c = -1;
69 //      for (c = 0; c < 63; c++)
70 //              if (raw1394_channel_modify (handle, c, RAW1394_MODIFY_ALLOC) == 0)
71 //                      break;
72 //      if (c < 63)
73 //              return c;
74 //      return -1;
75 // }
76
77 // static signed int free_iso_channel(raw1394handle_t handle, signed int channel) {
78 // /*
79 //  * Deallocates an iso channel.  Returns -1 on error or 0 on success.  Silently
80 //  * ignores a request to deallocate a negative channel number.
81 //  */
82 //      if (channel < 0)
83 //              return 0;
84 //      if (raw1394_channel_modify (handle, channel, RAW1394_MODIFY_FREE)!=0)
85 //              return -1;
86 //      return 0;
87 // }
88
89 // static signed int get_iso_bandwidth_avail(raw1394handle_t handle) {
90 // /*
91 //  * Returns the current value of the `bandwidth available' register on
92 //  * the IRM, or -1 on error.
93 //  */
94 // quadlet_t buffer;
95 // signed int result = raw1394_read (handle, raw1394_get_irm_id (handle),
96 //      CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
97 //      sizeof (quadlet_t), &buffer);
98 //
99 //      if (result < 0)
100 //              return -1;
101 //      return ntohl(buffer);
102 // }
103 /* ======================================================================= */
104
105 RmeDevice::RmeDevice( std::auto_ptr< ConfigRom >( configRom ),
106                     Ieee1394Service& ieee1394service,
107                     int nodeId,
108                     int verboseLevel )
109     : m_configRom( configRom )
110     , m_1394Service( &ieee1394service )
111     , m_model( NULL )
112     , m_nodeId( nodeId )
113     , m_verboseLevel( verboseLevel )
114     , m_id(0)
115     , m_iso_recv_channel ( -1 )
116     , m_iso_send_channel ( -1 )
117     , m_bandwidth ( -1 )
118 //    , m_receiveProcessor ( 0 )
119 //    , m_transmitProcessor ( 0 )
120    
121 {
122     setDebugLevel( verboseLevel );
123    
124     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Rme::RmeDevice (NodeID %d)\n",
125                  nodeId );
126
127 }
128
129 RmeDevice::~RmeDevice()
130 {
131         // Free ieee1394 bus resources if they have been allocated
132         if (m_1394Service != NULL) {
133                 raw1394handle_t handle = m_1394Service->getHandle();
134                 if (m_bandwidth >= 0)
135                         if (raw1394_bandwidth_modify(handle, m_bandwidth, RAW1394_MODIFY_FREE) < 0)
136                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free bandwidth of %d\n", m_bandwidth);
137                 if (m_iso_recv_channel >= 0)
138                         if (raw1394_channel_modify(handle, m_iso_recv_channel, RAW1394_MODIFY_FREE) < 0)
139                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free recv iso channel %d\n", m_iso_recv_channel);
140                 if (m_iso_send_channel >= 0)
141                         if (raw1394_channel_modify(handle, m_iso_send_channel, RAW1394_MODIFY_FREE) < 0)
142                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free send iso channel %d\n", m_iso_send_channel);
143         }
144
145 }
146
147 ConfigRom&
148 RmeDevice::getConfigRom() const
149 {
150     return *m_configRom;
151 }
152
153 bool
154 RmeDevice::probe( ConfigRom& configRom )
155 {
156     unsigned int vendorId = configRom.getNodeVendorId();
157     unsigned int modelId = configRom.getModelId();
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            )
166         {
167             return true;
168         }
169     }
170
171     return false;
172 }
173
174 bool
175 RmeDevice::discover()
176 {
177     unsigned int vendorId = m_configRom->getNodeVendorId();
178     unsigned int modelId = m_configRom->getModelId();
179
180     for ( unsigned int i = 0;
181           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
182           ++i )
183     {
184         if ( ( supportedDeviceList[i].vendor_id == vendorId )
185              && ( supportedDeviceList[i].model_id == modelId )
186            )
187         {
188             m_model = &(supportedDeviceList[i]);
189         }
190     }
191
192     if (m_model != NULL) {
193         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
194                 m_model->vendor_name, m_model->model_name);
195         return true;
196     }
197
198     return false;
199 }
200
201 int
202 RmeDevice::getSamplingFrequency( ) {
203 /*
204  * Retrieve the current sample rate from the RME device.
205  */
206         return 48000;
207 }
208
209 bool
210 RmeDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
211 {
212 /*
213  * Set the RME device's samplerate.
214  */
215         if (samplingFrequency == eSF_48000Hz)
216                 return true;
217         return false;
218 }
219
220 bool RmeDevice::setId( unsigned int id) {
221         debugOutput( DEBUG_LEVEL_VERBOSE, "Set id to %d...\n", id);
222         m_id=id;
223         return true;
224 }
225
226 void
227 RmeDevice::showDevice() const
228 {
229         debugOutput(DEBUG_LEVEL_VERBOSE,
230                 "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
231                 m_nodeId);
232 }
233
234 bool
235 RmeDevice::prepare() {
236
237 //      int samp_freq = getSamplingFrequency();
238
239 //      raw1394handle_t handle = m_1394Service->getHandle();
240
241         debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
242
243         // Assign iso channels if not already done
244 //      if (m_iso_recv_channel < 0)
245 //              m_iso_recv_channel = allocate_iso_channel(handle);
246 //      if (m_iso_send_channel < 0)
247 //              m_iso_send_channel = allocate_iso_channel(handle);
248 //
249 //      debugOutput(DEBUG_LEVEL_VERBOSE, "recv channel = %d, send channel = %d\n",
250 //              m_iso_recv_channel, m_iso_send_channel);
251 //
252 //      if (m_iso_recv_channel<0 || m_iso_send_channel<0) {
253 //              debugFatal("Could not allocate iso channels!\n");
254 //              return false;
255 //      }
256
257         // Allocate bandwidth if not previously done.
258         // FIXME: The bandwidth allocation calculation can probably be
259         // refined somewhat since this is currently based on a rudimentary
260         // understanding of the iso protocol.
261         // Currently we assume the following.
262         //   * Ack/iso gap = 0.05 us
263         //   * DATA_PREFIX = 0.16 us
264         //   * DATA_END    = 0.26 us
265         // These numbers are the worst-case figures given in the ieee1394
266         // standard.  This gives approximately 0.5 us of overheads per
267         // packet - around 25 bandwidth allocation units (from the ieee1394
268         // standard 1 bandwidth allocation unit is 125/6144 us).  We further
269         // assume the MOTU is running at S400 (which it should be) so one
270         // allocation unit is equivalent to 1 transmitted byte; thus the
271         // bandwidth allocation required for the packets themselves is just
272         // the size of the packet.  We allocate based on the maximum packet
273         // size (1160 bytes at 192 kHz) so the sampling frequency can be
274         // changed dynamically if this ends up being useful in future.
275 //      m_bandwidth = 25 + 1160;
276 //      debugOutput(DEBUG_LEVEL_VERBOSE, "Available bandwidth: %d\n",
277 //              get_iso_bandwidth_avail(handle));
278 //      if (raw1394_bandwidth_modify(handle, m_bandwidth, RAW1394_MODIFY_ALLOC) < 0) {
279 //              debugFatal("Could not allocate bandwidth of %d\n", m_bandwidth);
280 //              m_bandwidth = -1;
281 //              return false;
282 //      }
283 //      debugOutput(DEBUG_LEVEL_VERBOSE,
284 //              "allocated bandwidth of %d for MOTU device\n", m_bandwidth);
285 //      debugOutput(DEBUG_LEVEL_VERBOSE,
286 //              "remaining bandwidth: %d\n", get_iso_bandwidth_avail(handle));
287
288 //      m_receiveProcessor=new FreebobStreaming::MotuReceiveStreamProcessor(
289 //              m_1394Service->getPort(), samp_freq, event_size_in);
290
291         // The first thing is to initialize the processor.  This creates the
292         // data structures.
293 //      if(!m_receiveProcessor->init()) {
294 //              debugFatal("Could not initialize receive processor!\n");
295 //              return false;
296 //      }
297 //      m_receiveProcessor->setVerboseLevel(getDebugLevel());
298
299         // Now we add ports to the processor
300 //      debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
301        
302 //      char *buff;
303 //      FreebobStreaming::Port *p=NULL;
304 //
305 //      // Add audio capture ports
306 //      if (!addDirPorts(FreebobStreaming::Port::E_Capture, samp_freq, optical_in_mode)) {
307 //              return false;
308 //      }
309
310         // Add MIDI port.  The MOTU only has one MIDI input port, with each
311         // MIDI byte sent using a 3 byte sequence starting at byte 4 of the
312         // event data.
313 //      asprintf(&buff,"dev%d_cap_MIDI0",m_id);
314 //      p = new FreebobStreaming::MotuMidiPort(buff,
315 //              FreebobStreaming::Port::E_Capture, 4);
316 //      if (!p) {
317 //              debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
318 //      } else {
319 //              if (!m_receiveProcessor->addPort(p)) {
320 //                      debugWarning("Could not register port with stream processor\n");
321 //                      free(buff);
322 //                      return false;
323 //              } else {
324 //                      debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);
325 //              }
326 //      }
327 //      free(buff);
328
329         // example of adding an control port:
330 //    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
331 //    p=new FreebobStreaming::MotuControlPort(
332 //            buff,
333 //            FreebobStreaming::Port::E_Capture,
334 //            0 // you can add all other port specific stuff you
335 //              // need to pass by extending MotuXXXPort and MotuPortInfo
336 //    );
337 //    free(buff);
338 //
339 //    if (!p) {
340 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
341 //    } else {
342 //
343 //        if (!m_receiveProcessor->addPort(p)) {
344 //            debugWarning("Could not register port with stream processor\n");
345 //            return false;
346 //        } else {
347 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
348 //        }
349 //    }
350
351         // Do the same for the transmit processor
352 //      m_transmitProcessor=new FreebobStreaming::MotuTransmitStreamProcessor(
353 //              m_1394Service->getPort(), getSamplingFrequency(), event_size_out);
354 //
355 //      m_transmitProcessor->setVerboseLevel(getDebugLevel());
356 //     
357 //      if(!m_transmitProcessor->init()) {
358 //              debugFatal("Could not initialize transmit processor!\n");
359 //              return false;
360 //      }
361
362         // Connect the transmit stream ticks-per-frame hook to the
363         // ticks-per-frame DLL integrator in the receive stream.
364 //      m_transmitProcessor->setTicksPerFrameDLL(m_receiveProcessor->getTicksPerFrameDLL());
365
366         // Now we add ports to the processor
367 //      debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
368
369         // Add audio playback ports
370 //      if (!addDirPorts(FreebobStreaming::Port::E_Playback, samp_freq, optical_out_mode)) {
371 //              return false;
372 //      }
373
374         // Add MIDI port.  The MOTU only has one output MIDI port, with each
375         // MIDI byte transmitted using a 3 byte sequence starting at byte 4
376         // of the event data.
377 //      asprintf(&buff,"dev%d_pbk_MIDI0",m_id);
378 //      p = new FreebobStreaming::MotuMidiPort(buff,
379 //              FreebobStreaming::Port::E_Capture, 4);
380 //      if (!p) {
381 //              debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
382 //      } else {
383 //              if (!m_receiveProcessor->addPort(p)) {
384 //                      debugWarning("Could not register port with stream processor\n");
385 //                      free(buff);
386 //                      return false;
387 //              } else {
388 //                      debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);
389 //              }
390 //      }
391 //      free(buff);
392
393         // example of adding an control port:
394 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
395 //   
396 //    p=new FreebobStreaming::MotuControlPort(
397 //            buff,
398 //            FreebobStreaming::Port::E_Playback,
399 //            0 // you can add all other port specific stuff you
400 //              // need to pass by extending MotuXXXPort and MotuPortInfo
401 //    );
402 //    free(buff);
403 //
404 //    if (!p) {
405 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
406 //    } else {
407 //        if (!m_transmitProcessor->addPort(p)) {
408 //            debugWarning("Could not register port with stream processor\n");
409 //            return false;
410 //        } else {
411 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
412 //        }
413 //    }
414        
415         return true;
416 }
417
418 int
419 RmeDevice::getStreamCount() {
420         return 2; // one receive, one transmit
421 }
422
423 FreebobStreaming::StreamProcessor *
424 RmeDevice::getStreamProcessorByIndex(int i) {
425
426 //      switch (i) {
427 //      case 0:
428 //              return m_receiveProcessor;
429 //      case 1:
430 //              return m_transmitProcessor;
431 //      default:
432 //              return NULL;
433 //      }
434 //      return 0;
435         return NULL;
436 }
437
438 int
439 RmeDevice::startStreamByIndex(int i) {
440
441         // NOTE: this assumes that you have two streams
442         switch (i) {
443         case 0:
444                 // TODO: do the stuff that is nescessary to make the device
445                 // transmit a stream
446
447                 // Set the streamprocessor channel to the one obtained by
448                 // the connection management
449 //              m_receiveProcessor->setChannel(m_iso_recv_channel);
450
451                 // Mask out current transmit settings of the MOTU and replace
452                 // with new ones.  Turn bit 24 on to enable changes to the
453                 // MOTU's iso transmit settings when the iso control register
454                 // is written.  Bit 23 enables iso transmit from the MOTU.
455                 break;
456         case 1:
457                 // TODO: do the stuff that is nescessary to make the device
458                 // receive a stream
459
460                 // Set the streamprocessor channel to the one obtained by
461                 // the connection management
462 //              m_transmitProcessor->setChannel(m_iso_send_channel);
463
464                 // Mask out current receive settings of the MOTU and replace
465                 // with new ones.  Turn bit 31 on to enable changes to the
466                 // MOTU's iso receive settings when the iso control register
467                 // is written.  Bit 30 enables iso receive by the MOTU.
468                 break;
469                
470         default: // Invalid stream index
471                 return -1;
472         }
473
474         return 0;
475 }
476
477 int
478 RmeDevice::stopStreamByIndex(int i) {
479
480         // TODO: connection management: break connection
481         // cfr the start function
482
483         // NOTE: this assumes that you have two streams
484         switch (i) {
485         case 0:
486                 break;
487         case 1:
488                 break;
489                
490         default: // Invalid stream index
491                 return -1;
492         }
493
494         return 0;
495 }
496
497 signed int RmeDevice::getIsoRecvChannel(void) {
498         return m_iso_recv_channel;
499 }
500
501 signed int RmeDevice::getIsoSendChannel(void) {
502         return m_iso_send_channel;
503 }
504
505 signed int RmeDevice::getEventSize(unsigned int dir) {
506 //
507 // Return the size in bytes of a single event sent to (dir==MOTUFW_OUT) or
508 // from (dir==MOTUFW_IN) the MOTU as part of an iso data packet.
509
510         return 1;
511 }
512 /* ======================================================================= */
513
514 #if 0
515 unsigned int RmeDevice::ReadRegister(unsigned int reg) {
516 /*
517  * Attempts to read the requested register from the RME device.
518  */
519
520 quadlet_t quadlet;
521 assert(m_1394Service);
522        
523   quadlet = 0;
524   // Note: 1394Service::read() expects a physical ID, not the node id
525   if (m_1394Service->read(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 1, &quadlet) < 0) {
526     debugError("Error doing rme read from register 0x%06x\n",reg);
527   }
528
529   return ntohl(quadlet);
530 }
531
532 signed int RmeDevice::WriteRegister(unsigned int reg, quadlet_t data) {
533 /*
534  * Attempts to write the given data to the requested RME register.
535  */
536
537   unsigned int err = 0;
538   data = htonl(data);
539
540   // Note: 1394Service::write() expects a physical ID, not the node id
541   if (m_1394Service->write(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 1, &data) < 0) {
542     err = 1;
543     debugError("Error doing rme write to register 0x%06x\n",reg);
544   }
545
546   usleep(100);
547   return (err==0)?0:-1;
548 }
549 #endif
550
551 }
552
553 #endif //#ifdef ENABLE_RME
Note: See TracBrowser for help on using the browser.