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

Revision 386, 15.9 kB (checked in by pieterpalmers, 16 years ago)

- moved files around to the place they belong
- fixed all compile warnings

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