root/trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

Revision 847, 27.7 kB (checked in by ppalmers, 15 years ago)

use SSE2 for byteswaps (20% faster than ntohl())

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program 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
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25 #include "AmdtpTransmitStreamProcessor.h"
26 #include "AmdtpPort.h"
27 #include "../StreamProcessorManager.h"
28 #include "devicemanager.h"
29
30 #include "libutil/Time.h"
31
32 #include "libieee1394/ieee1394service.h"
33 #include "libieee1394/IsoHandlerManager.h"
34 #include "libieee1394/cycletimer.h"
35
36 #include <netinet/in.h>
37 #include <assert.h>
38
39 #include "libutil/ByteSwap.h"
40
41 #define AMDTP_FLOAT_MULTIPLIER 2147483392.0
42
43 namespace Streaming
44 {
45
46 /* transmit */
47 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(FFADODevice &parent, int dimension)
48         : StreamProcessor(parent, ePT_Transmit)
49         , m_dimension( dimension )
50         , m_dbc( 0 )
51         , m_nb_audio_ports( 0 )
52         , m_nb_midi_ports( 0 )
53 {}
54
55 enum StreamProcessor::eChildReturnValue
56 AmdtpTransmitStreamProcessor::generatePacketHeader (
57     unsigned char *data, unsigned int *length,
58     unsigned char *tag, unsigned char *sy,
59     int cycle, unsigned int dropped, unsigned int max_length )
60 {
61     __builtin_prefetch(data, 1, 0); // prefetch events for write, no temporal locality
62     struct iec61883_packet *packet = (struct iec61883_packet *)data;
63     /* Our node ID can change after a bus reset, so it is best to fetch
64     * our node ID for each packet. */
65     packet->sid = m_local_node_id;
66
67     packet->dbs = m_dimension;
68     packet->fn = 0;
69     packet->qpc = 0;
70     packet->sph = 0;
71     packet->reserved = 0;
72     packet->dbc = m_dbc;
73     packet->eoh1 = 2;
74     packet->fmt = IEC61883_FMT_AMDTP;
75
76     *tag = IEC61883_TAG_WITH_CIP;
77     *sy = 0;
78
79     signed int fc;
80     uint64_t presentation_time;
81     unsigned int presentation_cycle;
82     int cycles_until_presentation;
83
84     uint64_t transmit_at_time;
85     unsigned int transmit_at_cycle;
86     int cycles_until_transmit;
87
88     debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "Try for cycle %d\n", cycle );
89     // check whether the packet buffer has packets for us to send.
90     // the base timestamp is the one of the next sample in the buffer
91     ffado_timestamp_t ts_head_tmp;
92     m_data_buffer->getBufferHeadTimestamp ( &ts_head_tmp, &fc ); // thread safe
93
94     // the timestamp gives us the time at which we want the sample block
95     // to be output by the device
96     presentation_time = ( uint64_t ) ts_head_tmp;
97     m_last_timestamp = presentation_time;
98
99     // now we calculate the time when we have to transmit the sample block
100     transmit_at_time = substractTicks ( presentation_time, AMDTP_TRANSMIT_TRANSFER_DELAY );
101
102     // calculate the cycle this block should be presented in
103     // (this is just a virtual calculation since at that time it should
104     //  already be in the device's buffer)
105     presentation_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( presentation_time ) );
106
107     // calculate the cycle this block should be transmitted in
108     transmit_at_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( transmit_at_time ) );
109
110     // we can check whether this cycle is within the 'window' we have
111     // to send this packet.
112     // first calculate the number of cycles left before presentation time
113     cycles_until_presentation = diffCycles ( presentation_cycle, cycle );
114
115     // we can check whether this cycle is within the 'window' we have
116     // to send this packet.
117     // first calculate the number of cycles left before presentation time
118     cycles_until_transmit = diffCycles ( transmit_at_cycle, cycle );
119
120     if (dropped) {
121         debugOutput ( DEBUG_LEVEL_VERBOSE,
122                     "Gen HDR: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
123                     cycle,
124                     transmit_at_cycle, cycles_until_transmit,
125                     transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
126                     presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
127     }
128     // two different options:
129     // 1) there are not enough frames for one packet
130     //      => determine wether this is a problem, since we might still
131     //         have some time to send it
132     // 2) there are enough packets
133     //      => determine whether we have to send them in this packet
134     if ( fc < ( signed int ) m_syt_interval )
135     {
136         // not enough frames in the buffer,
137
138         // we can still postpone the queueing of the packets
139         // if we are far enough ahead of the presentation time
140         if ( cycles_until_presentation <= AMDTP_MIN_CYCLES_BEFORE_PRESENTATION )
141         {
142             debugOutput ( DEBUG_LEVEL_VERBOSE,
143                         "Insufficient frames (P): N=%02d, CY=%04u, TC=%04u, CUT=%04d\n",
144                         fc, cycle, transmit_at_cycle, cycles_until_transmit );
145             // we are too late
146             return eCRV_XRun;
147         }
148         else
149         {
150             unsigned int now_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( m_1394service.getCycleTimerTicks() ) );
151
152             debugOutput ( DEBUG_LEVEL_VERBOSE,
153                         "Insufficient frames (NP): N=%02d, CY=%04u, TC=%04u, CUT=%04d, NOW=%04d\n",
154                         fc, cycle, transmit_at_cycle, cycles_until_transmit, now_cycle );
155             debugWarning("Insufficient frames (NP): N=%02d, CY=%04u, TC=%04u, CUT=%04d, NOW=%04d\n",
156                          fc, cycle, transmit_at_cycle, cycles_until_transmit, now_cycle );
157
158             // there is still time left to send the packet
159             // we want the system to give this packet another go at a later time instant
160             return eCRV_Again; // note that the raw1394 again system doesn't work as expected
161
162             // we could wait here for a certain time before trying again. However, this
163             // is not going to work since we then block the iterator thread, hence also
164             // the receiving code, meaning that we are not processing received packets,
165             // and hence there is no progression in the number of frames available.
166
167             // for example:
168             // SleepRelativeUsec(125); // one cycle
169             // goto try_block_of_frames;
170
171             // or more advanced, calculate how many cycles we are ahead of 'now' and
172             // base the sleep on that.
173
174             // note that this requires that there is one thread for each IsoHandler,
175             // otherwise we're in the deadlock described above.
176         }
177     }
178     else
179     {
180         // there are enough frames, so check the time they are intended for
181         // all frames have a certain 'time window' in which they can be sent
182         // this corresponds to the range of the timestamp mechanism:
183         // we can send a packet 15 cycles in advance of the 'presentation time'
184         // in theory we can send the packet up till one cycle before the presentation time,
185         // however this is not very smart.
186
187         // There are 3 options:
188         // 1) the frame block is too early
189         //      => send an empty packet
190         // 2) the frame block is within the window
191         //      => send it
192         // 3) the frame block is too late
193         //      => discard (and raise xrun?)
194         //         get next block of frames and repeat
195
196         if(cycles_until_transmit < 0)
197         {
198             // we are too late
199             debugOutput(DEBUG_LEVEL_VERBOSE,
200                         "Too late: CY=%04u, TC=%04u, CUT=%04d, TSP=%011llu (%04u)\n",
201                         cycle,
202                         transmit_at_cycle, cycles_until_transmit,
203                         presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time) );
204             //debugShowBackLogLines(200);
205 //             // however, if we can send this sufficiently before the presentation
206 //             // time, it could be harmless.
207 //             // NOTE: dangerous since the device has no way of reporting that it didn't get
208 //             //       this packet on time.
209 //             if(cycles_until_presentation >= AMDTP_MIN_CYCLES_BEFORE_PRESENTATION)
210 //             {
211 //                 // we are not that late and can still try to transmit the packet
212 //                 m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp);
213 //                 return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet);
214 //             }
215 //             else   // definitely too late
216 //             {
217                 return eCRV_XRun;
218 //             }
219         }
220         else if(cycles_until_transmit <= AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY)
221         {
222             // it's time send the packet
223             m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp);
224             return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet);
225         }
226         else
227         {
228             debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
229                         "Too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
230                         cycle,
231                         transmit_at_cycle, cycles_until_transmit,
232                         transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
233                         presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
234 #ifdef DEBUG
235             if ( cycles_until_transmit > AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY + 1 )
236             {
237                 debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
238                             "Way too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
239                             cycle,
240                             transmit_at_cycle, cycles_until_transmit,
241                             transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
242                             presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
243             }
244 #endif
245             // we are too early, send only an empty packet
246             return eCRV_EmptyPacket;
247         }
248     }
249     return eCRV_Invalid;
250 }
251
252 enum StreamProcessor::eChildReturnValue
253 AmdtpTransmitStreamProcessor::generatePacketData (
254     unsigned char *data, unsigned int *length,
255     unsigned char *tag, unsigned char *sy,
256     int cycle, unsigned int dropped, unsigned int max_length )
257 {
258     if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) )
259     {
260         debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT DATA (cy %04d): TSP=%011llu (%04u)\n",
261                     cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) );
262         return eCRV_OK;
263     }
264     else return eCRV_XRun;
265
266 }
267
268 enum StreamProcessor::eChildReturnValue
269 AmdtpTransmitStreamProcessor::generateSilentPacketHeader (
270     unsigned char *data, unsigned int *length,
271     unsigned char *tag, unsigned char *sy,
272     int cycle, unsigned int dropped, unsigned int max_length )
273 {
274     struct iec61883_packet *packet = ( struct iec61883_packet * ) data;
275     debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT NONE (cy %04d): CY=%04u, TSP=%011llu (%04u)\n",
276                 cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) );
277
278     /* Our node ID can change after a bus reset, so it is best to fetch
279     * our node ID for each packet. */
280     packet->sid = m_local_node_id;
281
282     packet->dbs = m_dimension;
283     packet->fn = 0;
284     packet->qpc = 0;
285     packet->sph = 0;
286     packet->reserved = 0;
287     packet->dbc = m_dbc;
288     packet->eoh1 = 2;
289     packet->fmt = IEC61883_FMT_AMDTP;
290
291     *tag = IEC61883_TAG_WITH_CIP;
292     *sy = 0;
293
294     m_dbc += fillNoDataPacketHeader ( packet, length );
295     return eCRV_OK;
296 }
297
298 enum StreamProcessor::eChildReturnValue
299 AmdtpTransmitStreamProcessor::generateSilentPacketData (
300     unsigned char *data, unsigned int *length,
301     unsigned char *tag, unsigned char *sy,
302     int cycle, unsigned int dropped, unsigned int max_length )
303 {
304     return eCRV_OK; // no need to do anything
305 }
306
307 unsigned int AmdtpTransmitStreamProcessor::fillDataPacketHeader (
308     struct iec61883_packet *packet, unsigned int* length,
309     uint32_t ts )
310 {
311
312     packet->fdf = m_fdf;
313
314     // convert the timestamp to SYT format
315     uint16_t timestamp_SYT = TICKS_TO_SYT ( ts );
316     packet->syt = ntohs ( timestamp_SYT );
317
318     *length = m_syt_interval*sizeof ( quadlet_t ) *m_dimension + 8;
319
320     return m_syt_interval;
321 }
322
323 unsigned int AmdtpTransmitStreamProcessor::fillNoDataPacketHeader (
324     struct iec61883_packet *packet, unsigned int* length )
325 {
326
327     // no-data packets have syt=0xFFFF
328     // and have the usual amount of events as dummy data (?)
329     packet->fdf = IEC61883_FDF_NODATA;
330     packet->syt = 0xffff;
331
332     // FIXME: either make this a setting or choose
333     bool send_payload=true;
334     if ( send_payload )
335     {
336         // this means no-data packets with payload (DICE doesn't like that)
337         *length = 2*sizeof ( quadlet_t ) + m_syt_interval * m_dimension * sizeof ( quadlet_t );
338         return m_syt_interval;
339     }
340     else
341     {
342         // dbc is not incremented
343         // this means no-data packets without payload
344         *length = 2*sizeof ( quadlet_t );
345         return 0;
346     }
347 }
348
349 unsigned int
350 AmdtpTransmitStreamProcessor::getSytInterval() {
351     switch (m_StreamProcessorManager.getNominalRate()) {
352         case 32000:
353         case 44100:
354         case 48000:
355             return 8;
356         case 88200:
357         case 96000:
358             return 16;
359         case 176400:
360         case 192000:
361             return 32;
362         default:
363             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
364             return 0;
365     }
366 }
367 unsigned int
368 AmdtpTransmitStreamProcessor::getFDF() {
369     switch (m_StreamProcessorManager.getNominalRate()) {
370         case 32000: return IEC61883_FDF_SFC_32KHZ;
371         case 44100: return IEC61883_FDF_SFC_44K1HZ;
372         case 48000: return IEC61883_FDF_SFC_48KHZ;
373         case 88200: return IEC61883_FDF_SFC_88K2HZ;
374         case 96000: return IEC61883_FDF_SFC_96KHZ;
375         case 176400: return IEC61883_FDF_SFC_176K4HZ;
376         case 192000: return IEC61883_FDF_SFC_192KHZ;
377         default:
378             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
379             return 0;
380     }
381 }
382
383 bool AmdtpTransmitStreamProcessor::prepareChild()
384 {
385     debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this );
386     m_syt_interval = getSytInterval();
387     m_fdf = getFDF();
388
389     iec61883_cip_init (
390         &m_cip_status,
391         IEC61883_FMT_AMDTP,
392         m_fdf,
393         m_StreamProcessorManager.getNominalRate(),
394         m_dimension,
395         m_syt_interval );
396
397     if (!initPortCache()) {
398         debugError("Could not init port cache\n");
399         return false;
400     }
401
402     return true;
403 }
404
405 /*
406 * compose the event streams for the packets from the port buffers
407 */
408 bool AmdtpTransmitStreamProcessor::processWriteBlock ( char *data,
409         unsigned int nevents, unsigned int offset )
410 {
411     updatePortCache();
412     switch(m_StreamProcessorManager.getAudioDataType()) {
413         case StreamProcessorManager::eADT_Int24:
414             encodeAudioPortsInt24((quadlet_t *)data, offset, nevents);
415             break;
416         case StreamProcessorManager::eADT_Float:
417             encodeAudioPortsFloat((quadlet_t *)data, offset, nevents);
418             break;
419     }
420     encodeMidiPorts((quadlet_t *)data, offset, nevents);
421     byteSwapToBus(((quadlet_t *)data), nevents * m_dimension);
422     return true;
423 }
424
425 bool
426 AmdtpTransmitStreamProcessor::transmitSilenceBlock(
427     char *data, unsigned int nevents, unsigned int offset)
428 {
429     // no need to update the port cache when transmitting silence since
430     // no dynamic values are used to do so.
431
432     encodeAudioPortsSilence((quadlet_t *)data, offset, nevents);
433     encodeMidiPortsSilence((quadlet_t *)data, offset, nevents);
434     byteSwapToBus(((quadlet_t *)data), nevents * m_dimension);
435     return true;
436 }
437
438 /**
439  * @brief encodes all audio ports in the cache to events (silent data)
440  * @param data
441  * @param offset
442  * @param nevents
443  */
444 void
445 AmdtpTransmitStreamProcessor::encodeAudioPortsSilence(quadlet_t *data,
446                                                       unsigned int offset,
447                                                       unsigned int nevents)
448 {
449     unsigned int j;
450     quadlet_t *target_event;
451     unsigned int i;
452
453     for (i = 0; i < m_nb_audio_ports; i++) {
454         target_event = (quadlet_t *)(data + i);
455         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
456
457         for (j = 0;j < nevents; j += 1)
458         {
459             *target_event = 0x40000000;
460             target_event += m_dimension;
461             __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
462         }
463     }
464 }
465
466 /**
467  * @brief encodes all audio ports in the cache to events (float data)
468  * @param data
469  * @param offset
470  * @param nevents
471  */
472 void
473 AmdtpTransmitStreamProcessor::encodeAudioPortsFloat(quadlet_t *data,
474                                                     unsigned int offset,
475                                                     unsigned int nevents)
476 {
477     unsigned int j;
478     quadlet_t *target_event;
479     unsigned int i;
480
481     for (i = 0; i < m_nb_audio_ports; i++) {
482         struct _MBLA_port_cache &p = m_audio_ports.at(i);
483         target_event = (quadlet_t *)(data + i);
484         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
485         assert(nevents + offset <= p.buffer_size );
486
487         if(p.buffer && p.enabled) {
488             float *buffer = (float *)(p.buffer);
489             buffer += offset;
490             __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
491    
492             for (j = 0;j < nevents; j += 1)
493             {
494                 // don't care for overflow
495                 float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER;
496                 unsigned int tmp = ((int) v);
497                 *target_event = ( tmp >> 8 ) | 0x40000000;
498                 buffer++;
499                 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
500                 target_event += m_dimension;
501                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
502             }
503         } else {
504             for (j = 0;j < nevents; j += 1)
505             {
506                 *target_event = 0x40000000;
507                 target_event += m_dimension;
508                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
509             }
510         }
511     }
512 }
513
514 /**
515  * @brief encodes all audio ports in the cache to events (int24 data)
516  * @param data
517  * @param offset
518  * @param nevents
519  */
520 void
521 AmdtpTransmitStreamProcessor::encodeAudioPortsInt24(quadlet_t *data,
522                                                     unsigned int offset,
523                                                     unsigned int nevents)
524 {
525     unsigned int j;
526     quadlet_t *target_event;
527     unsigned int i;
528
529     for (i = 0; i < m_nb_audio_ports; i++) {
530         struct _MBLA_port_cache &p = m_audio_ports.at(i);
531         target_event = (quadlet_t *)(data + i);
532         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
533         assert(nevents + offset <= p.buffer_size );
534
535         if(p.buffer && p.enabled) {
536             uint32_t *buffer = (uint32_t *)(p.buffer);
537             buffer += offset;
538             __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
539
540             for (j = 0; j < nevents; j += 1)
541             {
542                 *target_event = ((*buffer) & 0x00FFFFFF) | 0x40000000;
543                 buffer++;
544                 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
545
546                 target_event += m_dimension;
547                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
548             }
549         } else {
550             for (j = 0;j < nevents; j += 1)
551             {
552                 *target_event = 0x40000000;
553                 target_event += m_dimension;
554                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
555             }
556         }
557     }
558 }
559
560 /**
561  * @brief encodes all midi ports in the cache to events (silence)
562  * @param data
563  * @param offset
564  * @param nevents
565  */
566 void
567 AmdtpTransmitStreamProcessor::encodeMidiPortsSilence(quadlet_t *data,
568                                                      unsigned int offset,
569                                                      unsigned int nevents)
570 {
571     quadlet_t *target_event;
572     unsigned int i,j;
573
574     for (i = 0; i < m_nb_midi_ports; i++) {
575         struct _MIDI_port_cache &p = m_midi_ports.at(i);
576
577         for (j = p.location;j < nevents; j += 8) {
578             target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position));
579             __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
580             *target_event = IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA);
581         }
582     }
583 }
584
585 /**
586  * @brief encodes all midi ports in the cache to events
587  * @param data
588  * @param offset
589  * @param nevents
590  */
591 void
592 AmdtpTransmitStreamProcessor::encodeMidiPorts(quadlet_t *data,
593                                               unsigned int offset,
594                                               unsigned int nevents)
595 {
596     quadlet_t *target_event;
597     unsigned int i,j;
598
599     for (i = 0; i < m_nb_midi_ports; i++) {
600         struct _MIDI_port_cache &p = m_midi_ports.at(i);
601         if (p.buffer && p.enabled) {
602             uint32_t *buffer = (quadlet_t *)(p.buffer);
603             buffer += offset;
604             __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
605    
606             for (j = p.location;j < nevents; j += 8) {
607                 target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position));
608                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
609    
610                 if ( *buffer & 0xFF000000 )   // we can send a byte
611                 {
612                     quadlet_t tmpval;
613                     tmpval = ((*buffer)<<16) & 0x00FF0000;
614                     tmpval = IEC61883_AM824_SET_LABEL(tmpval, IEC61883_AM824_LABEL_MIDI_1X);
615                     *target_event = tmpval;
616
617 //                     debugOutput ( DEBUG_LEVEL_VERBOSE, "MIDI port %s, pos=%u, loc=%u, nevents=%u, dim=%d\n",
618 //                                p.port->getName().c_str(), p.position, p.location, nevents, m_dimension );
619 //                     debugOutput ( DEBUG_LEVEL_VERBOSE, "base=%p, target=%p, value=%08X\n",
620 //                                data, target_event, tmpval );
621                 } else {
622                     // can't send a byte, either because there is no byte,
623                     // or because this would exceed the maximum rate
624                     // FIXME: this can be ifdef optimized since it's a constant
625                     *target_event = IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA);
626                 }
627                 buffer+=8;
628             }
629         } else {
630             for (j = p.location;j < nevents; j += 8) {
631                 target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position));
632                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
633                 *target_event = IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA);
634             }
635         }
636     }
637 }
638
639 bool
640 AmdtpTransmitStreamProcessor::initPortCache() {
641     // make use of the fact that audio ports are the first ports in
642     // the cluster as per AMDTP. so we can sort the ports by position
643     // and have very efficient lookups:
644     // m_float_ports.at(i).buffer -> audio stream i buffer
645     // for midi ports we simply cache all port info since they are (usually) not
646     // that numerous
647     m_nb_audio_ports = 0;
648     m_audio_ports.clear();
649    
650     m_nb_midi_ports = 0;
651     m_midi_ports.clear();
652    
653     for(PortVectorIterator it = m_Ports.begin();
654         it != m_Ports.end();
655         ++it )
656     {
657         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
658         assert(pinfo); // this should not fail!!
659
660         switch( pinfo->getFormat() )
661         {
662             case AmdtpPortInfo::E_MBLA:
663                 m_nb_audio_ports++;
664                 break;
665             case AmdtpPortInfo::E_SPDIF: // still unimplemented
666                 break;
667             case AmdtpPortInfo::E_Midi:
668                 m_nb_midi_ports++;
669                 break;
670             default: // ignore
671                 break;
672         }
673     }
674
675     unsigned int idx;
676     for (idx = 0; idx < m_nb_audio_ports; idx++) {
677         for(PortVectorIterator it = m_Ports.begin();
678             it != m_Ports.end();
679             ++it )
680         {
681             AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
682             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "idx %u: looking at port %s at position %u\n",
683                                               idx, (*it)->getName().c_str(), pinfo->getPosition());
684             if(pinfo->getPosition() == idx) {
685                 struct _MBLA_port_cache p;
686                 p.port = dynamic_cast<AmdtpAudioPort *>(*it);
687                 if(p.port == NULL) {
688                     debugError("Port is not an AmdtpAudioPort!\n");
689                     return false;
690                 }
691                 p.buffer = NULL; // to be filled by updatePortCache
692                 #ifdef DEBUG
693                 p.buffer_size = (*it)->getBufferSize();
694                 #endif
695
696                 m_audio_ports.push_back(p);
697                 debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n",
698                                                  p.port->getName().c_str(), idx);
699                 goto next_index;
700             }
701         }
702         debugError("No MBLA port found for position %d\n", idx);
703         return false;
704 next_index:
705         continue;
706     }
707
708     for(PortVectorIterator it = m_Ports.begin();
709         it != m_Ports.end();
710         ++it )
711     {
712         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
713         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "idx %u: looking at port %s at position %u, location %u\n",
714                                         idx, (*it)->getName().c_str(), pinfo->getPosition(), pinfo->getLocation());
715         if ((*it)->getPortType() == Port::E_Midi) {
716             struct _MIDI_port_cache p;
717             p.port = dynamic_cast<AmdtpMidiPort *>(*it);
718             if(p.port == NULL) {
719                 debugError("Port is not an AmdtpMidiPort!\n");
720                 return false;
721             }
722             p.position = pinfo->getPosition();
723             p.location = pinfo->getLocation();
724             p.buffer = NULL; // to be filled by updatePortCache
725             #ifdef DEBUG
726             p.buffer_size = (*it)->getBufferSize();
727             #endif
728
729             m_midi_ports.push_back(p);
730             debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u, location %u\n",
731                                             p.port->getName().c_str(), p.position, p.location);
732         }
733     }
734
735     return true;
736 }
737
738 void
739 AmdtpTransmitStreamProcessor::updatePortCache() {
740     unsigned int idx;
741     for (idx = 0; idx < m_nb_audio_ports; idx++) {
742         struct _MBLA_port_cache& p = m_audio_ports.at(idx);
743         AmdtpAudioPort *port = p.port;
744         p.buffer = port->getBufferAddress();
745         p.enabled = !port->isDisabled();
746     }
747     for (idx = 0; idx < m_nb_midi_ports; idx++) {
748         struct _MIDI_port_cache& p = m_midi_ports.at(idx);
749         AmdtpMidiPort *port = p.port;
750         p.buffer = port->getBufferAddress();
751         p.enabled = !port->isDisabled();
752     }
753 }
754
755 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.