root/trunk/libffado/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp

Revision 742, 13.8 kB (checked in by ppalmers, 13 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

Line 
1 /*
2  * Copyright (C) 2005-2007 by Jonathan Woithe
3  * Copyright (C) 2005-2007 by Pieter Palmers
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 program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "MotuReceiveStreamProcessor.h"
26 #include "MotuPort.h"
27 #include "../StreamProcessorManager.h"
28
29 #include "../util/cycletimer.h"
30
31 #include <math.h>
32 #include <netinet/in.h>
33 #include <assert.h>
34
35 namespace Streaming {
36
37 // A macro to extract specific bits from a native endian quadlet
38 #define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1))
39
40 // Convert an SPH timestamp as received from the MOTU to a full timestamp in ticks.
41 static inline uint32_t sphRecvToFullTicks(uint32_t sph, uint32_t ct_now) {
42
43 uint32_t timestamp = CYCLE_TIMER_TO_TICKS(sph & 0x1ffffff);
44 uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(ct_now);
45
46 uint32_t ts_sec = CYCLE_TIMER_GET_SECS(ct_now);
47     // If the cycles have wrapped, correct ts_sec so it represents when timestamp
48     // was received.  The timestamps sent by the MOTU are always 1 or two cycles
49     // in advance of the cycle timer (reasons unknown at this stage).  In addition,
50     // iso buffering can delay the arrival of packets for quite a number of cycles
51     // (have seen a delay >12 cycles).
52     // Every so often we also see sph wrapping ahead of ct_now, so deal with that
53     // too.
54     if (CYCLE_TIMER_GET_CYCLES(sph) > now_cycles + 1000) {
55         if (ts_sec)
56             ts_sec--;
57         else
58             ts_sec = 127;
59     } else
60     if (now_cycles > CYCLE_TIMER_GET_CYCLES(sph) + 1000) {
61         if (ts_sec == 127)
62             ts_sec = 0;
63         else
64             ts_sec++;
65     }
66     return timestamp + ts_sec*TICKS_PER_SECOND;
67 }
68
69 MotuReceiveStreamProcessor::MotuReceiveStreamProcessor(int port, unsigned int event_size)
70     : StreamProcessor(ePT_Receive , port)
71     , m_event_size(event_size)
72 {}
73
74 unsigned int
75 MotuReceiveStreamProcessor::getMaxPacketSize() {
76     int framerate = m_manager->getNominalRate();
77     return framerate<=48000?616:(framerate<=96000?1032:1160);
78 }
79
80 unsigned int
81 MotuReceiveStreamProcessor::getNominalFramesPerPacket() {
82     int framerate = m_manager->getNominalRate();
83     return framerate<=48000?8:(framerate<=96000?16:32);
84 }
85
86 bool
87 MotuReceiveStreamProcessor::prepareChild() {
88     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this);
89
90     // prepare the framerate estimate
91     // FIXME: not needed anymore?
92     //m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_manager->getNominalRate());
93
94     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
95     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d\n",
96              m_manager->getNominalRate());
97     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
98              m_manager->getPeriodSize(), m_manager->getNbBuffers());
99     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
100              m_port, m_channel);
101
102     return true;
103 }
104
105
106 /**
107  * Processes packet header to extract timestamps and check if the packet is valid
108  * @param data
109  * @param length
110  * @param channel
111  * @param tag
112  * @param sy
113  * @param cycle
114  * @param dropped
115  * @return
116  */
117 enum StreamProcessor::eChildReturnValue
118 MotuReceiveStreamProcessor::processPacketHeader(unsigned char *data, unsigned int length,
119                   unsigned char channel, unsigned char tag, unsigned char sy,
120                   unsigned int cycle, unsigned int dropped)
121 {
122     if (length > 8) {
123         // The iso data blocks from the MOTUs comprise a CIP-like
124         // header followed by a number of events (8 for 1x rates, 16
125         // for 2x rates, 32 for 4x rates).
126         quadlet_t *quadlet = (quadlet_t *)data;
127         unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size
128         unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits
129
130         // Don't even attempt to process a packet if it isn't what
131         // we expect from a MOTU.  Yes, an FDF value of 32 bears
132         // little relationship to the actual data (24 bit integer)
133         // sent by the MOTU - it's one of those areas where MOTU
134         // have taken a curious detour around the standards.
135         if (tag!=1 || fdf_size!=32) {
136             return eCRV_Invalid;
137         }
138
139         // put this after the check because event_length can become 0 on invalid packets
140         unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes
141         unsigned int n_events = (length-8) / event_length;
142
143         // Acquire the timestamp of the last frame in the packet just
144         // received.  Since every frame from the MOTU has its own timestamp
145         // we can just pick it straight from the packet.
146         uint32_t last_sph = ntohl(*(quadlet_t *)(data+8+(n_events-1)*event_length));
147         m_last_timestamp = sphRecvToFullTicks(last_sph, m_handler->getCycleTimer());
148         return eCRV_OK;
149     } else {
150         return eCRV_Invalid;
151     }
152 }
153
154 /**
155  * extract the data from the packet
156  * @pre the IEC61883 packet is valid according to isValidPacket
157  * @param data
158  * @param length
159  * @param channel
160  * @param tag
161  * @param sy
162  * @param cycle
163  * @param dropped
164  * @return
165  */
166 enum StreamProcessor::eChildReturnValue
167 MotuReceiveStreamProcessor::processPacketData(unsigned char *data, unsigned int length,
168                   unsigned char channel, unsigned char tag, unsigned char sy,
169                   unsigned int cycle, unsigned int dropped_cycles) {
170     quadlet_t* quadlet = (quadlet_t*) data;
171
172     unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size
173     unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits
174     // this is only called for packets that return eCRV_OK on processPacketHeader
175     // so event_length won't become 0
176     unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes
177     unsigned int n_events = (length-8) / event_length;
178
179     // we have to keep in mind that there are also
180     // some packets buffered by the ISO layer,
181     // at most x=m_handler->getWakeupInterval()
182     // these contain at most x*syt_interval
183     // frames, meaning that we might receive
184     // this packet x*syt_interval*ticks_per_frame
185     // later than expected (the real receive time)
186     #ifdef DEBUG
187     if(isRunning()) {
188         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | buff=%d, tpf=%f\n",
189             m_last_timestamp, m_handler->getWakeupInterval(), getTicksPerFrame());
190     }
191     #endif
192
193     if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) {
194         int dbc = get_bits(ntohl(quadlet[0]), 8, 8);
195         // process all ports that should be handled on a per-packet base
196         // this is MIDI for AMDTP (due to the need of DBC)
197         if(isRunning()) {
198             if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) {
199                 debugWarning("Problem decoding Packet Ports\n");
200             }
201         }
202         return eCRV_OK;
203     } else {
204         return eCRV_XRun;
205     }
206 }
207
208 /***********************************************
209  * Encoding/Decoding API                       *
210  ***********************************************/
211 /**
212  * \brief write received events to the port ringbuffers.
213  */
214 bool MotuReceiveStreamProcessor::processReadBlock(char *data,
215                        unsigned int nevents, unsigned int offset)
216 {
217     bool no_problem=true;
218     for ( PortVectorIterator it = m_PeriodPorts.begin();
219           it != m_PeriodPorts.end();
220           ++it ) {
221         if((*it)->isDisabled()) {continue;};
222
223         //FIXME: make this into a static_cast when not DEBUG?
224         Port *port=dynamic_cast<Port *>(*it);
225
226         switch(port->getPortType()) {
227
228         case Port::E_Audio:
229             if(decodeMotuEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
230                 debugWarning("Could not decode packet data to port %s",(*it)->getName().c_str());
231                 no_problem=false;
232             }
233             break;
234         // midi is a packet based port, don't process
235         //    case MotuPortInfo::E_Midi:
236         //        break;
237
238         default: // ignore
239             break;
240         }
241     }
242     return no_problem;
243 }
244
245 /**
246  * @brief decode a packet for the packet-based ports
247  *
248  * @param data Packet data
249  * @param nevents number of events in data (including events of other ports & port types)
250  * @param dbc DataBlockCount value for this packet
251  * @return true if all successfull
252  */
253 bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents,
254         unsigned int dbc) {
255     bool ok=true;
256
257     // Use char here since the source address won't necessarily be
258     // aligned; use of an unaligned quadlet_t may cause issues on
259     // certain architectures.  Besides, the source for MIDI data going
260     // directly to the MOTU isn't structured in quadlets anyway; it is a
261     // sequence of 3 unaligned bytes.
262     unsigned char *src = NULL;
263
264     for ( PortVectorIterator it = m_PacketPorts.begin();
265         it != m_PacketPorts.end();
266         ++it ) {
267
268         Port *port=dynamic_cast<Port *>(*it);
269         assert(port); // this should not fail!!
270
271         // Currently the only packet type of events for MOTU
272         // is MIDI in mbla.  However in future control data
273         // might also be sent via "packet" events, so allow
274         // for this possible expansion.
275
276         // FIXME: MIDI input is completely untested at present.
277         switch (port->getPortType()) {
278             case Port::E_Midi: {
279                 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);
280                 signed int sample;
281                 unsigned int j = 0;
282                 // Get MIDI bytes if present anywhere in the
283                 // packet.  MOTU MIDI data is sent using a
284                 // 3-byte sequence starting at the port's
285                 // position.  It's thought that there can never
286                 // be more than one MIDI byte per packet, but
287                 // for completeness we'll check the entire packet
288                 // anyway.
289                 src = (unsigned char *)data + mp->getPosition();
290                 while (j < nevents) {
291                     if (*src==0x01 && *(src+1)==0x00) {
292                         sample = *(src+2);
293                         if (!mp->writeEvent(&sample)) {
294                             debugWarning("MIDI packet port events lost\n");
295                             ok = false;
296                         }
297                     }
298                     j++;
299                     src += m_event_size;
300                 }
301                 break;
302             }
303             default:
304                 debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port format %d\n",port->getPortType());
305                 return ok;
306               }
307     }
308
309     return ok;
310 }
311
312 signed int MotuReceiveStreamProcessor::decodeMotuEventsToPort(MotuAudioPort *p,
313         quadlet_t *data, unsigned int offset, unsigned int nevents)
314 {
315     unsigned int j=0;
316
317     // Use char here since a port's source address won't necessarily be
318     // aligned; use of an unaligned quadlet_t may cause issues on
319     // certain architectures.  Besides, the source (data coming directly
320     // from the MOTU) isn't structured in quadlets anyway; it mainly
321     // consists of packed 24-bit integers.
322
323     unsigned char *src_data;
324     src_data = (unsigned char *)data + p->getPosition();
325
326     switch(p->getDataType()) {
327         default:
328         case Port::E_Int24:
329             {
330                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
331
332                 assert(nevents + offset <= p->getBufferSize());
333
334                 // Offset is in frames, but each port is only a single
335                 // channel, so the number of frames is the same as the
336                 // number of quadlets to offset (assuming the port buffer
337                 // uses one quadlet per sample, which is the case currently).
338                 buffer+=offset;
339
340                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
341                     *buffer = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
342                     // Sign-extend highest bit of 24-bit int.
343                     // FIXME: this isn't strictly needed since E_Int24 is a 24-bit,
344                     // but doing so shouldn't break anything and makes the data
345                     // easier to deal with during debugging.
346                     if (*src_data & 0x80)
347                         *buffer |= 0xff000000;
348
349                     buffer++;
350                     src_data+=m_event_size;
351                 }
352             }
353             break;
354         case Port::E_Float:
355             {
356                 const float multiplier = 1.0f / (float)(0x7FFFFF);
357                 float *buffer=(float *)(p->getBufferAddress());
358
359                 assert(nevents + offset <= p->getBufferSize());
360
361                 buffer+=offset;
362
363                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
364
365                     unsigned int v = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
366
367                     // sign-extend highest bit of 24-bit int
368                     int tmp = (int)(v << 8) / 256;
369
370                     *buffer = tmp * multiplier;
371
372                     buffer++;
373                     src_data+=m_event_size;
374                 }
375             }
376             break;
377     }
378
379     return 0;
380 }
381
382 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.