Changeset 733

Show
Ignore:
Timestamp:
11/28/07 03:25:27 (13 years ago)
Author:
ppalmers
Message:

adapt motu code to new SP base class (compiles, needs real testing)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp

    r729 r733  
    3131#include <assert.h> 
    3232 
    33 // in ticks 
    34 // as per AMDTP2.1: 
    35 // 354.17us + 125us @ 24.576ticks/usec = 11776.08192 ticks 
    36 #define DEFAULT_TRANSFER_DELAY (11776U) 
    37  
    38 #define TRANSMIT_TRANSFER_DELAY DEFAULT_TRANSFER_DELAY 
    39  
    4033namespace Streaming { 
    4134 
     
    4639    , m_dimension( dimension ) 
    4740{} 
    48  
    49 unsigned int 
    50 AmdtpReceiveStreamProcessor::getNominalPacketsNeeded(unsigned int nframes) 
    51 { 
    52     unsigned int nominal_frames_per_second = m_manager->getNominalRate(); 
    53     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second; 
    54     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes; 
    55     uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE; 
    56     return nominal_packets; 
    57 } 
    58  
    59 unsigned int 
    60 AmdtpReceiveStreamProcessor::getPacketsPerPeriod() 
    61 { 
    62     return getNominalPacketsNeeded(m_manager->getPeriodSize()); 
    63 } 
    6441 
    6542bool AmdtpReceiveStreamProcessor::prepareChild() { 
     
    206183            if(decodeMBLAEventsToPort(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    207184                debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str()); 
    208                 no_problem=false; 
    209             } 
    210             break; 
    211         case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    212             break; 
    213     /* for this processor, midi is a packet based port 
    214         case AmdtpPortInfo::E_Midi: 
    215             break;*/ 
    216         default: // ignore 
    217             break; 
    218         } 
    219     } 
    220     return no_problem; 
    221 } 
    222  
    223 /** 
    224  * @brief write silence events to the stream ringbuffers. 
    225  */ 
    226 bool AmdtpReceiveStreamProcessor::provideSilenceBlock(unsigned int nevents, unsigned int offset) 
    227 { 
    228     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->proviceSilenceBlock(%u, %u)\n", this, nevents, offset); 
    229  
    230     bool no_problem=true; 
    231  
    232     for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    233           it != m_PeriodPorts.end(); 
    234           ++it ) 
    235     { 
    236         if((*it)->isDisabled()) {continue;}; 
    237         //FIXME: make this into a static_cast when not DEBUG? 
    238         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    239         assert(pinfo); // this should not fail!! 
    240  
    241         switch(pinfo->getFormat()) { 
    242         case AmdtpPortInfo::E_MBLA: 
    243             if(provideSilenceToPort(static_cast<AmdtpAudioPort *>(*it), offset, nevents)) { 
    244                 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); 
    245185                no_problem=false; 
    246186            } 
     
    368308    return 0; 
    369309} 
    370  
    371 int 
    372 AmdtpReceiveStreamProcessor::provideSilenceToPort( 
    373                        AmdtpAudioPort *p, unsigned int offset, unsigned int nevents) 
    374 { 
    375     unsigned int j=0; 
    376     switch(p->getDataType()) { 
    377         default: 
    378         case Port::E_Int24: 
    379             { 
    380                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
    381                 assert(nevents + offset <= p->getBufferSize()); 
    382                 buffer+=offset; 
    383  
    384                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    385                     *(buffer)=0; 
    386                     buffer++; 
    387                 } 
    388             } 
    389             break; 
    390         case Port::E_Float: 
    391             { 
    392                 float *buffer=(float *)(p->getBufferAddress()); 
    393                 assert(nevents + offset <= p->getBufferSize()); 
    394                 buffer+=offset; 
    395  
    396                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    397                     *buffer = 0.0; 
    398                     buffer++; 
    399                 } 
    400             } 
    401             break; 
    402     } 
    403     return 0; 
    404 } 
    405  
    406310} // end of namespace Streaming 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h

    r729 r733  
    9696    virtual unsigned int getNominalFramesPerPacket()  
    9797                    {return m_syt_interval;}; 
    98     virtual unsigned int getPacketsPerPeriod(); 
    99     virtual unsigned int getNominalPacketsNeeded(unsigned int nframes); 
    10098 
    10199protected: 
    102100    bool processReadBlock(char *data, unsigned int nevents, unsigned int offset); 
    103     bool provideSilenceBlock(unsigned int nevents, unsigned int offset); 
    104101 
    105102private: 
    106103    bool decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc); 
    107  
    108104    int decodeMBLAEventsToPort(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); 
    109     int provideSilenceToPort(AmdtpAudioPort *p, unsigned int offset, unsigned int nevents); 
    110105 
    111106    int m_dimension; 
    112107    unsigned int m_syt_interval; 
    113  
    114     uint64_t m_last_syt; /// FIXME:debug 
    115     uint64_t m_last_now; /// FIXME:debug 
    116108}; 
    117109 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

    r729 r733  
    345345} 
    346346 
    347 unsigned int 
    348 AmdtpTransmitStreamProcessor::getNominalPacketsNeeded(unsigned int nframes) 
    349 { 
    350     unsigned int nominal_frames_per_second = m_manager->getNominalRate(); 
    351     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second; 
    352     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes; 
    353     uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE; 
    354     return nominal_packets; 
    355 } 
    356  
    357 unsigned int 
    358 AmdtpTransmitStreamProcessor::getPacketsPerPeriod() 
    359 { 
    360     return getNominalPacketsNeeded(m_manager->getPeriodSize()); 
    361 } 
    362  
    363347bool AmdtpTransmitStreamProcessor::prepareChild() 
    364348{ 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h

    r729 r733  
    103103    virtual unsigned int getNominalFramesPerPacket() 
    104104                    {return m_syt_interval;}; 
    105     virtual unsigned int getPacketsPerPeriod(); 
    106     virtual unsigned int getNominalPacketsNeeded(unsigned int nframes); 
    107105 
    108106protected: 
  • branches/ppalmers-streaming/src/libstreaming/generic/StreamProcessor.cpp

    r729 r733  
    7171        return (int)(m_handler->getWakeupInterval() * TICKS_PER_CYCLE); 
    7272    } 
     73} 
     74 
     75unsigned int 
     76StreamProcessor::getNominalPacketsNeeded(unsigned int nframes) 
     77{ 
     78    unsigned int nominal_frames_per_second = m_manager->getNominalRate(); 
     79    uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second; 
     80    uint64_t nominal_ticks = nominal_ticks_per_frame * nframes; 
     81    uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE; 
     82    return nominal_packets; 
    7383} 
    7484 
     
    705715        return result; 
    706716    } 
     717} 
     718 
     719/** 
     720 * @brief write silence events to the stream ringbuffers. 
     721 */ 
     722bool StreamProcessor::provideSilenceBlock(unsigned int nevents, unsigned int offset) 
     723{ 
     724    bool no_problem=true; 
     725    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
     726          it != m_PeriodPorts.end(); 
     727          ++it ) { 
     728        if((*it)->isDisabled()) {continue;}; 
     729 
     730        //FIXME: make this into a static_cast when not DEBUG? 
     731        Port *port=dynamic_cast<Port *>(*it); 
     732 
     733        switch(port->getPortType()) { 
     734 
     735        case Port::E_Audio: 
     736            if(provideSilenceToPort(static_cast<AudioPort *>(*it), offset, nevents)) { 
     737                debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); 
     738                no_problem=false; 
     739            } 
     740            break; 
     741        // midi is a packet based port, don't process 
     742        //    case MotuPortInfo::E_Midi: 
     743        //        break; 
     744 
     745        default: // ignore 
     746            break; 
     747        } 
     748    } 
     749    return no_problem; 
     750} 
     751 
     752int 
     753StreamProcessor::provideSilenceToPort( 
     754                       AudioPort *p, unsigned int offset, unsigned int nevents) 
     755{ 
     756    unsigned int j=0; 
     757    switch(p->getDataType()) { 
     758        default: 
     759        case Port::E_Int24: 
     760            { 
     761                quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
     762                assert(nevents + offset <= p->getBufferSize()); 
     763                buffer+=offset; 
     764 
     765                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
     766                    *(buffer)=0; 
     767                    buffer++; 
     768                } 
     769            } 
     770            break; 
     771        case Port::E_Float: 
     772            { 
     773                float *buffer=(float *)(p->getBufferAddress()); 
     774                assert(nevents + offset <= p->getBufferSize()); 
     775                buffer+=offset; 
     776 
     777                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
     778                    *buffer = 0.0; 
     779                    buffer++; 
     780                } 
     781            } 
     782            break; 
     783    } 
     784    return 0; 
    707785} 
    708786 
  • branches/ppalmers-streaming/src/libstreaming/generic/StreamProcessor.h

    r729 r733  
    210210    virtual bool processReadBlock(char *data, unsigned int nevents, unsigned int offset) 
    211211        {debugWarning("call not allowed\n"); return false;}; 
    212     virtual bool provideSilenceBlock(unsigned int nevents, unsigned int offset) 
    213         {debugWarning("call not allowed\n"); return false;}; 
    214212 
    215213    // the following methods are to be implemented by transmit SP subclasses 
     
    238236    virtual bool transmitSilenceBlock(char *data, unsigned int nevents, unsigned int offset) 
    239237        {debugWarning("call not allowed\n"); return false;}; 
     238protected: // some generic helpers 
     239    int provideSilenceToPort(AudioPort *p, unsigned int offset, unsigned int nevents); 
     240    bool provideSilenceBlock(unsigned int nevents, unsigned int offset); 
    240241 
    241242private: 
     
    392393        /** 
    393394         * @brief get the nominal number of frames in a packet 
     395         * 
     396         * This is the amount of frames that is nominally present 
     397         * in one packet. It is recommended that in the receive handler 
     398         * you write this amount of frames when a valid packet has 
     399         * been received. (although this is not mandatory) 
     400         * 
    394401         * @return the nominal number of frames in a packet 
    395402         */ 
     
    400407         * @return the nominal number of packet necessary 
    401408         */ 
    402         virtual unsigned int getNominalPacketsNeeded(unsigned int nframes) = 0; 
     409        virtual unsigned int getNominalPacketsNeeded(unsigned int nframes); 
     410 
     411        /** 
     412         * @brief returns the actual frame rate as calculated by the SP's DLL 
     413         * @return the actual frame rate as detected by the DLL 
     414         */ 
     415        float getActualRate() 
     416            {return m_data_buffer->getRate();}; 
    403417 
    404418    protected: 
  • branches/ppalmers-streaming/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp

    r732 r733  
    2222 */ 
    2323 
    24 #include "AmdtpReceiveStreamProcessor.h" 
    25 #include "AmdtpPort.h" 
     24#include "MotuReceiveStreamProcessor.h" 
     25#include "MotuPort.h" 
    2626#include "../StreamProcessorManager.h" 
    2727 
    2828#include "../util/cycletimer.h" 
    2929 
     30#include <math.h> 
    3031#include <netinet/in.h> 
    3132#include <assert.h> 
    3233 
    33 // in ticks 
    34 // as per AMDTP2.1: 
    35 // 354.17us + 125us @ 24.576ticks/usec = 11776.08192 ticks 
    36 #define DEFAULT_TRANSFER_DELAY (11776U) 
    37  
    38 #define TRANSMIT_TRANSFER_DELAY DEFAULT_TRANSFER_DELAY 
    39  
    4034namespace Streaming { 
    4135 
    42 /* --------------------- RECEIVE ----------------------- */ 
    43  
    44 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int dimension) 
     36// A macro to extract specific bits from a native endian quadlet 
     37#define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1)) 
     38 
     39// Convert an SPH timestamp as received from the MOTU to a full timestamp in ticks. 
     40static inline uint32_t sphRecvToFullTicks(uint32_t sph, uint32_t ct_now) { 
     41 
     42uint32_t timestamp = CYCLE_TIMER_TO_TICKS(sph & 0x1ffffff); 
     43uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(ct_now); 
     44 
     45uint32_t ts_sec = CYCLE_TIMER_GET_SECS(ct_now); 
     46    // If the cycles have wrapped, correct ts_sec so it represents when timestamp 
     47    // was received.  The timestamps sent by the MOTU are always 1 or two cycles 
     48    // in advance of the cycle timer (reasons unknown at this stage).  In addition, 
     49    // iso buffering can delay the arrival of packets for quite a number of cycles 
     50    // (have seen a delay >12 cycles). 
     51    // Every so often we also see sph wrapping ahead of ct_now, so deal with that 
     52    // too. 
     53    if (CYCLE_TIMER_GET_CYCLES(sph) > now_cycles + 1000) { 
     54        if (ts_sec) 
     55            ts_sec--; 
     56        else 
     57            ts_sec = 127; 
     58    } else 
     59    if (now_cycles > CYCLE_TIMER_GET_CYCLES(sph) + 1000) { 
     60        if (ts_sec == 127) 
     61            ts_sec = 0; 
     62        else 
     63            ts_sec++; 
     64    } 
     65    return timestamp + ts_sec*TICKS_PER_SECOND; 
     66
     67 
     68MotuReceiveStreamProcessor::MotuReceiveStreamProcessor(int port, unsigned int event_size) 
    4569    : StreamProcessor(ePT_Receive , port) 
    46     , m_dimension( dimension
     70    , m_event_size(event_size
    4771{} 
    4872 
    4973unsigned int 
    50 AmdtpReceiveStreamProcessor::getNominalPacketsNeeded(unsigned int nframes) 
    51 
    52     unsigned int nominal_frames_per_second = m_manager->getNominalRate(); 
    53     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second; 
    54     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes; 
    55     uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE; 
    56     return nominal_packets; 
     74MotuReceiveStreamProcessor::getMaxPacketSize() { 
     75    int framerate = m_manager->getNominalRate(); 
     76    return framerate<=48000?616:(framerate<=96000?1032:1160); 
    5777} 
    5878 
    5979unsigned int 
    60 AmdtpReceiveStreamProcessor::getPacketsPerPeriod() 
    61 
    62     return getNominalPacketsNeeded(m_manager->getPeriodSize()); 
    63 
    64  
    65 bool AmdtpReceiveStreamProcessor::prepareChild() { 
     80MotuReceiveStreamProcessor::getNominalFramesPerPacket() { 
     81    int framerate = m_manager->getNominalRate(); 
     82    return framerate<=48000?8:(framerate<=96000?16:32); 
     83
     84 
     85bool 
     86MotuReceiveStreamProcessor::prepareChild() { 
    6687    debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this); 
    6788 
    68     switch (m_manager->getNominalRate()) { 
    69         case 32000: 
    70         case 44100: 
    71         case 48000: 
    72             m_syt_interval = 8; 
    73             break; 
    74         case 88200: 
    75         case 96000: 
    76             m_syt_interval = 16; 
    77             break; 
    78         case 176400: 
    79         case 192000: 
    80             m_syt_interval = 32; 
    81             break; 
    82         default: 
    83             debugError("Unsupported rate: %d\n", m_manager->getNominalRate()); 
    84             return false; 
    85     } 
     89    // prepare the framerate estimate 
     90    // FIXME: not needed anymore? 
     91    //m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_manager->getNominalRate()); 
    8692 
    8793    debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n"); 
    88     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n", 
    89              m_manager->getNominalRate(), m_dimension, m_syt_interval); 
     94    debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d\n", 
     95             m_manager->getNominalRate()); 
    9096    debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", 
    9197             m_manager->getPeriodSize(), m_manager->getNbBuffers()); 
    9298    debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", 
    93              m_port,m_channel); 
     99             m_port, m_channel); 
    94100 
    95101    return true; 
     
    98104 
    99105/** 
    100  * Processes packet header to extract timestamps and so on 
     106 * Processes packet header to extract timestamps and check if the packet is valid 
    101107 * @param data  
    102108 * @param length  
     
    109115 */ 
    110116enum StreamProcessor::eChildReturnValue 
    111 AmdtpReceiveStreamProcessor::processPacketHeader(unsigned char *data, unsigned int length, 
     117MotuReceiveStreamProcessor::processPacketHeader(unsigned char *data, unsigned int length, 
    112118                  unsigned char channel, unsigned char tag, unsigned char sy, 
    113119                  unsigned int cycle, unsigned int dropped) 
    114120{ 
    115     struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    116     assert(packet); 
    117     bool ok = (packet->syt != 0xFFFF) && 
    118                   (packet->fdf != 0xFF) && 
    119                   (packet->fmt == 0x10) && 
    120                   (packet->dbs > 0) && 
    121                   (length >= 2*sizeof(quadlet_t)); 
    122     if(ok) { 
    123         uint64_t now = m_handler->getCycleTimer(); 
    124         //=> convert the SYT to a full timestamp in ticks 
    125         m_last_timestamp = sytRecvToFullTicks((uint32_t)ntohs(packet->syt), 
    126                                               cycle, now); 
    127     } 
    128     return (ok ? eCRV_OK : eCRV_Invalid ); 
     121    if (length > 8) { 
     122        // The iso data blocks from the MOTUs comprise a CIP-like 
     123        // header followed by a number of events (8 for 1x rates, 16 
     124        // for 2x rates, 32 for 4x rates). 
     125        quadlet_t *quadlet = (quadlet_t *)data; 
     126        unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size 
     127        unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits 
     128 
     129        // Don't even attempt to process a packet if it isn't what 
     130        // we expect from a MOTU.  Yes, an FDF value of 32 bears 
     131        // little relationship to the actual data (24 bit integer) 
     132        // sent by the MOTU - it's one of those areas where MOTU 
     133        // have taken a curious detour around the standards. 
     134        if (tag!=1 || fdf_size!=32) { 
     135            return eCRV_Invalid; 
     136        } 
     137 
     138        // put this after the check because event_length can become 0 on invalid packets 
     139        unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes 
     140        unsigned int n_events = (length-8) / event_length; 
     141 
     142        // Acquire the timestamp of the last frame in the packet just 
     143        // received.  Since every frame from the MOTU has its own timestamp 
     144        // we can just pick it straight from the packet. 
     145        uint32_t last_sph = ntohl(*(quadlet_t *)(data+8+(n_events-1)*event_length)); 
     146        m_last_timestamp = sphRecvToFullTicks(last_sph, m_handler->getCycleTimer()); 
     147        return eCRV_OK; 
     148    } else { 
     149        return eCRV_Invalid; 
     150    } 
    129151} 
    130152 
     
    142164 */ 
    143165enum StreamProcessor::eChildReturnValue 
    144 AmdtpReceiveStreamProcessor::processPacketData(unsigned char *data, unsigned int length, 
     166MotuReceiveStreamProcessor::processPacketData(unsigned char *data, unsigned int length, 
    145167                  unsigned char channel, unsigned char tag, unsigned char sy, 
    146168                  unsigned int cycle, unsigned int dropped_cycles) { 
    147     struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    148     assert(packet); 
    149  
    150     unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs; 
     169    quadlet_t* quadlet = (quadlet_t*) data; 
     170 
     171    unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size 
     172    unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits 
     173    // this is only called for packets that return eCRV_OK on processPacketHeader 
     174    // so event_length won't become 0 
     175    unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes 
     176    unsigned int n_events = (length-8) / event_length; 
    151177 
    152178    // we have to keep in mind that there are also 
     
    159185    #ifdef DEBUG 
    160186    if(isRunning()) { 
    161         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | buff=%d, syt_interval=%d, tpf=%f\n", 
    162             m_last_timestamp, m_handler->getWakeupInterval(), m_syt_interval, getTicksPerFrame()); 
     187        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | buff=%d, tpf=%f\n", 
     188            m_last_timestamp, m_handler->getWakeupInterval(), getTicksPerFrame()); 
    163189    } 
    164190    #endif 
    165191 
    166     if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) { 
     192    if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) { 
     193        int dbc = get_bits(ntohl(quadlet[0]), 8, 8); 
    167194        // process all ports that should be handled on a per-packet base 
    168195        // this is MIDI for AMDTP (due to the need of DBC) 
    169196        if(isRunning()) { 
    170             if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) { 
     197            if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { 
    171198                debugWarning("Problem decoding Packet Ports\n"); 
    172199            } 
     
    182209 ***********************************************/ 
    183210/** 
    184  * @brief write received events to the stream ringbuffers. 
    185  */ 
    186 bool AmdtpReceiveStreamProcessor::processReadBlock(char *data, 
     211 * \brief write received events to the port ringbuffers. 
     212 */ 
     213bool MotuReceiveStreamProcessor::processReadBlock(char *data, 
    187214                       unsigned int nevents, unsigned int offset) 
    188215{ 
    189     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->processReadBlock(%u, %u)\n",this,nevents,offset); 
    190  
    191216    bool no_problem=true; 
    192  
    193217    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    194218          it != m_PeriodPorts.end(); 
    195           ++it ) 
    196     { 
     219          ++it ) { 
    197220        if((*it)->isDisabled()) {continue;}; 
    198221 
    199222        //FIXME: make this into a static_cast when not DEBUG? 
    200  
    201         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    202         assert(pinfo); // this should not fail!! 
    203  
    204         switch(pinfo->getFormat()) { 
    205         case AmdtpPortInfo::E_MBLA: 
    206             if(decodeMBLAEventsToPort(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    207                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str()); 
     223        Port *port=dynamic_cast<Port *>(*it); 
     224 
     225        switch(port->getPortType()) { 
     226 
     227        case Port::E_Audio: 
     228            if(decodeMotuEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     229                debugWarning("Could not decode packet data to port %s",(*it)->getName().c_str()); 
    208230                no_problem=false; 
    209231            } 
    210232            break; 
    211         case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    212             break; 
    213     /* for this processor, midi is a packet based port 
    214         case AmdtpPortInfo::E_Midi: 
    215             break;*/ 
    216         default: // ignore 
    217             break; 
    218         } 
    219     } 
    220     return no_problem; 
    221 
    222  
    223 /** 
    224  * @brief write silence events to the stream ringbuffers. 
    225  */ 
    226 bool AmdtpReceiveStreamProcessor::provideSilenceBlock(unsigned int nevents, unsigned int offset) 
    227 
    228     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->proviceSilenceBlock(%u, %u)\n", this, nevents, offset); 
    229  
    230     bool no_problem=true; 
    231  
    232     for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    233           it != m_PeriodPorts.end(); 
    234           ++it ) 
    235     { 
    236         if((*it)->isDisabled()) {continue;}; 
    237         //FIXME: make this into a static_cast when not DEBUG? 
    238         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    239         assert(pinfo); // this should not fail!! 
    240  
    241         switch(pinfo->getFormat()) { 
    242         case AmdtpPortInfo::E_MBLA: 
    243             if(provideSilenceToPort(static_cast<AmdtpAudioPort *>(*it), offset, nevents)) { 
    244                 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); 
    245                 no_problem=false; 
    246             } 
    247             break; 
    248         case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    249             break; 
    250     /* for this processor, midi is a packet based port 
    251         case AmdtpPortInfo::E_Midi: 
    252             break;*/ 
     233        // midi is a packet based port, don't process 
     234        //    case MotuPortInfo::E_Midi: 
     235        //        break; 
     236 
    253237        default: // ignore 
    254238            break; 
     
    266250 * @return true if all successfull 
    267251 */ 
    268 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc) 
    269 
     252bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, 
     253        unsigned int dbc)
    270254    bool ok=true; 
    271255 
    272     quadlet_t *target_event=NULL; 
    273     unsigned int j; 
     256    // Use char here since the source address won't necessarily be 
     257    // aligned; use of an unaligned quadlet_t may cause issues on 
     258    // certain architectures.  Besides, the source for MIDI data going 
     259    // directly to the MOTU isn't structured in quadlets anyway; it is a 
     260    // sequence of 3 unaligned bytes. 
     261    unsigned char *src = NULL; 
    274262 
    275263    for ( PortVectorIterator it = m_PacketPorts.begin(); 
    276           it != m_PacketPorts.end(); 
    277           ++it ) 
    278     { 
    279  
    280 #ifdef DEBUG 
    281         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    282         assert(pinfo); // this should not fail!! 
    283  
    284         // the only packet type of events for AMDTP is MIDI in mbla 
    285         assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi); 
    286 #endif 
    287         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it); 
    288  
    289         // we decode this directly (no function call) due to the high frequency 
    290         /* idea: 
    291         spec says: current_midi_port=(dbc+j)%8; 
    292         => if we start at (dbc+stream->location-1)%8, 
    293         we'll start at the right event for the midi port. 
    294         => if we increment j with 8, we stay at the right event. 
    295         */ 
    296         // FIXME: as we know in advance how big a packet is (syt_interval) we can 
    297         //        predict how much loops will be present here 
    298         for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) { 
    299             target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 
    300             quadlet_t sample_int=ntohl(*target_event); 
    301             // FIXME: this assumes that 2X and 3X speed isn't used, 
    302             // because only the 1X slot is put into the ringbuffer 
    303             if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { 
    304                 sample_int=(sample_int >> 16) & 0x000000FF; 
    305                 if(!mp->writeEvent(&sample_int)) { 
    306                     debugWarning("Packet port events lost\n"); 
    307                     ok=false; 
     264        it != m_PacketPorts.end(); 
     265        ++it ) { 
     266 
     267        Port *port=dynamic_cast<Port *>(*it); 
     268        assert(port); // this should not fail!! 
     269 
     270        // Currently the only packet type of events for MOTU 
     271        // is MIDI in mbla.  However in future control data 
     272        // might also be sent via "packet" events, so allow 
     273        // for this possible expansion. 
     274 
     275        // FIXME: MIDI input is completely untested at present. 
     276        switch (port->getPortType()) { 
     277            case Port::E_Midi: { 
     278                MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it); 
     279                signed int sample; 
     280                unsigned int j = 0; 
     281                // Get MIDI bytes if present anywhere in the 
     282                // packet.  MOTU MIDI data is sent using a 
     283                // 3-byte sequence starting at the port's 
     284                // position.  It's thought that there can never 
     285                // be more than one MIDI byte per packet, but 
     286                // for completeness we'll check the entire packet 
     287                // anyway. 
     288                src = (unsigned char *)data + mp->getPosition(); 
     289                while (j < nevents) { 
     290                    if (*src==0x01 && *(src+1)==0x00) { 
     291                        sample = *(src+2); 
     292                        if (!mp->writeEvent(&sample)) { 
     293                            debugWarning("MIDI packet port events lost\n"); 
     294                            ok = false; 
     295                        } 
     296                    } 
     297                    j++; 
     298                    src += m_event_size; 
    308299                } 
    309             } 
    310         } 
    311  
     300                break; 
     301            } 
     302            default: 
     303                debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port format %d\n",port->getPortType()); 
     304                return ok; 
     305              } 
    312306    } 
    313307 
     
    315309} 
    316310 
    317 int 
    318 AmdtpReceiveStreamProcessor::decodeMBLAEventsToPort( 
    319                        AmdtpAudioPort *p, quadlet_t *data, 
    320                        unsigned int offset, unsigned int nevents) 
     311signed int MotuReceiveStreamProcessor::decodeMotuEventsToPort(MotuAudioPort *p, 
     312        quadlet_t *data, unsigned int offset, unsigned int nevents) 
    321313{ 
    322314    unsigned int j=0; 
    323     quadlet_t *target_event; 
    324  
    325     target_event=(quadlet_t *)(data + p->getPosition()); 
     315 
     316    // Use char here since a port's source address won't necessarily be 
     317    // aligned; use of an unaligned quadlet_t may cause issues on 
     318    // certain architectures.  Besides, the source (data coming directly 
     319    // from the MOTU) isn't structured in quadlets anyway; it mainly 
     320    // consists of packed 24-bit integers. 
     321 
     322    unsigned char *src_data; 
     323    src_data = (unsigned char *)data + p->getPosition(); 
    326324 
    327325    switch(p->getDataType()) { 
     
    333331                assert(nevents + offset <= p->getBufferSize()); 
    334332 
     333                // Offset is in frames, but each port is only a single 
     334                // channel, so the number of frames is the same as the 
     335                // number of quadlets to offset (assuming the port buffer 
     336                // uses one quadlet per sample, which is the case currently). 
    335337                buffer+=offset; 
    336338 
    337                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    338                     *(buffer)=(ntohl((*target_event) ) & 0x00FFFFFF); 
     339                for(j = 0; j < nevents; j += 1) { // Decode nsamples 
     340                    *buffer = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2); 
     341                    // Sign-extend highest bit of 24-bit int. 
     342                    // FIXME: this isn't strictly needed since E_Int24 is a 24-bit, 
     343                    // but doing so shouldn't break anything and makes the data 
     344                    // easier to deal with during debugging. 
     345                    if (*src_data & 0x80) 
     346                        *buffer |= 0xff000000; 
     347 
    339348                    buffer++; 
    340                     target_event+=m_dimension
     349                    src_data+=m_event_size
    341350                } 
    342351            } 
     
    353362                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    354363 
    355                     unsigned int v = ntohl(*target_event) & 0x00FFFFFF; 
     364                    unsigned int v = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2); 
     365 
    356366                    // sign-extend highest bit of 24-bit int 
    357367                    int tmp = (int)(v << 8) / 256; 
     
    360370 
    361371                    buffer++; 
    362                     target_event+=m_dimension
     372                    src_data+=m_event_size
    363373                } 
    364374            } 
     
    369379} 
    370380 
    371 int 
    372 AmdtpReceiveStreamProcessor::provideSilenceToPort( 
    373                        AmdtpAudioPort *p, unsigned int offset, unsigned int nevents) 
    374 { 
    375     unsigned int j=0; 
    376     switch(p->getDataType()) { 
    377         default: 
    378         case Port::E_Int24: 
    379             { 
    380                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
    381                 assert(nevents + offset <= p->getBufferSize()); 
    382                 buffer+=offset; 
    383  
    384                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    385                     *(buffer)=0; 
    386                     buffer++; 
    387                 } 
    388             } 
    389             break; 
    390         case Port::E_Float: 
    391             { 
    392                 float *buffer=(float *)(p->getBufferAddress()); 
    393                 assert(nevents + offset <= p->getBufferSize()); 
    394                 buffer+=offset; 
    395  
    396                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    397                     *buffer = 0.0; 
    398                     buffer++; 
    399                 } 
    400             } 
    401             break; 
    402     } 
    403     return 0; 
    404 } 
    405  
    406381} // end of namespace Streaming 
  • branches/ppalmers-streaming/src/libstreaming/motu/MotuReceiveStreamProcessor.h

    r732 r733  
    2222 */ 
    2323 
    24 #ifndef __FFADO_AMDTPRECEIVESTREAMPROCESSOR__ 
    25 #define __FFADO_AMDTPRECEIVESTREAMPROCESSOR__ 
     24#ifndef __FFADO_MOTURECEIVESTREAMPROCESSOR__ 
     25#define __FFADO_MOTURECEIVESTREAMPROCESSOR__ 
    2626 
    2727/** 
    28  * This class implements IEC61883-6 / AM824 / AMDTP based streaming 
     28 * This class implements MOTU streaming 
    2929 */ 
    3030 
     
    3434#include "../util/cip.h" 
    3535 
    36 #include <libiec61883/iec61883.h> 
    37 #include <pthread.h> 
    38  
    39 #define AMDTP_MAX_PACKET_SIZE 2048 
    40  
    41 #define IEC61883_STREAM_TYPE_MIDI   0x0D 
    42 #define IEC61883_STREAM_TYPE_SPDIF  0x00 
    43 #define IEC61883_STREAM_TYPE_MBLA   0x06 
    44  
    45 #define IEC61883_AM824_LABEL_MASK             0xFF000000 
    46 #define IEC61883_AM824_GET_LABEL(x)         (((x) & 0xFF000000) >> 24) 
    47 #define IEC61883_AM824_SET_LABEL(x,y)         ((x) | ((y)<<24)) 
    48  
    49 #define IEC61883_AM824_LABEL_MIDI_NO_DATA     0x80 
    50 #define IEC61883_AM824_LABEL_MIDI_1X          0x81 
    51 #define IEC61883_AM824_LABEL_MIDI_2X          0x82 
    52 #define IEC61883_AM824_LABEL_MIDI_3X          0x83 
    53  
    5436namespace Streaming { 
    5537 
    56 class Port; 
    57 class AmdtpAudioPort; 
    58 class AmdtpMidiPort; 
     38class MotuAudioPort; 
    5939/*! 
    60 \brief The Base Class for an AMDTP receive stream processor 
    61  
    62  This class implements a ReceiveStreamProcessor that demultiplexes 
    63  AMDTP streams into Ports. 
    64  
    65 */ 
    66 class AmdtpReceiveStreamProcessor 
     40 * \brief The Base Class for a MOTU receive stream processor 
     41 * 
     42 * This class implements the outgoing stream processing for 
     43 * motu devices 
     44 * 
     45 */ 
     46class MotuReceiveStreamProcessor 
    6747    : public StreamProcessor 
    6848{ 
     
    7050public: 
    7151    /** 
    72      * Create a AMDTP receive StreamProcessor 
     52     * Create a MOTU receive StreamProcessor 
    7353     * @param port 1394 port 
    7454     * @param dimension number of substreams in the ISO stream 
    7555     *                  (midi-muxed is only one stream) 
    7656     */ 
    77     AmdtpReceiveStreamProcessor(int port, int dimension); 
    78     virtual ~AmdtpReceiveStreamProcessor() {}; 
     57    MotuReceiveStreamProcessor(int port, unsigned int event_size); 
     58    virtual ~MotuReceiveStreamProcessor() {}; 
    7959 
    8060    enum eChildReturnValue processPacketHeader(unsigned char *data, unsigned int length, 
     
    8969public: 
    9070    virtual unsigned int getEventSize()  
    91                     {return 4;}; 
    92     virtual unsigned int getMaxPacketSize()  
    93                     {return 4 * (2 + m_syt_interval * m_dimension);}; 
     71                {return m_event_size;}; 
     72    virtual unsigned int getMaxPacketSize(); 
    9473    virtual unsigned int getEventsPerFrame()  
    95                     { return m_dimension; }; 
    96     virtual unsigned int getNominalFramesPerPacket()  
    97                     {return m_syt_interval;}; 
    98     virtual unsigned int getPacketsPerPeriod(); 
    99     virtual unsigned int getNominalPacketsNeeded(unsigned int nframes); 
     74                    { return 1; }; // FIXME: check 
     75    virtual unsigned int getNominalFramesPerPacket(); 
    10076 
    10177protected: 
    10278    bool processReadBlock(char *data, unsigned int nevents, unsigned int offset); 
    103     bool provideSilenceBlock(unsigned int nevents, unsigned int offset); 
    10479 
    10580private: 
    10681    bool decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc); 
    10782 
    108     int decodeMBLAEventsToPort(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); 
    109     int provideSilenceToPort(AmdtpAudioPort *p, unsigned int offset, unsigned int nevents); 
     83    int decodeMotuEventsToPort(MotuAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); 
    11084 
    111     int m_dimension; 
    112     unsigned int m_syt_interval; 
    113  
    114     uint64_t m_last_syt; /// FIXME:debug 
    115     uint64_t m_last_now; /// FIXME:debug 
     85    /* 
     86    * An iso packet mostly consists of multiple events.  m_event_size 
     87     * is the size of a single 'event' in bytes. 
     88    */ 
     89    unsigned int m_event_size; 
    11690}; 
    11791 
     
    11993} // end of namespace Streaming 
    12094 
    121 #endif /* __FFADO_AMDTPRECEIVESTREAMPROCESSOR__ */ 
     95#endif /* __FFADO_MOTURECEIVESTREAMPROCESSOR__ */ 
    12296 
  • branches/ppalmers-streaming/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp

    r732 r733  
    2222 */ 
    2323 
    24 #include "AmdtpTransmitStreamProcessor.h" 
    25 #include "AmdtpPort.h" 
     24#include "MotuTransmitStreamProcessor.h" 
     25#include "MotuPort.h" 
    2626#include "../StreamProcessorManager.h" 
    2727 
     
    4141{ 
    4242 
     43// A macro to extract specific bits from a native endian quadlet 
     44#define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1)) 
     45 
     46// Convert a full timestamp into an SPH timestamp as required by the MOTU 
     47static inline uint32_t fullTicksToSph(int64_t timestamp) { 
     48    return TICKS_TO_CYCLE_TIMER(timestamp) & 0x1ffffff; 
     49} 
     50 
    4351/* transmit */ 
    44 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor ( int port, int dimension
     52MotuTransmitStreamProcessor::MotuTransmitStreamProcessor ( int port, unsigned int event_size
    4553        : StreamProcessor ( ePT_Transmit, port ) 
    46         , m_dimension ( dimension
    47         , m_dbc ( 0 ) 
     54        , m_event_size ( event_size
     55        , m_tx_dbc ( 0 ) 
    4856{} 
    4957 
     58 
     59unsigned int 
     60MotuTransmitStreamProcessor::getMaxPacketSize() { 
     61    int framerate = m_manager->getNominalRate(); 
     62    return framerate<=48000?616:(framerate<=96000?1032:1160); 
     63} 
     64 
     65unsigned int 
     66MotuTransmitStreamProcessor::getNominalFramesPerPacket() { 
     67    int framerate = m_manager->getNominalRate(); 
     68    return framerate<=48000?8:(framerate<=96000?16:32); 
     69} 
     70 
    5071enum StreamProcessor::eChildReturnValue 
    51 AmdtpTransmitStreamProcessor::generatePacketHeader ( 
     72MotuTransmitStreamProcessor::generatePacketHeader ( 
    5273    unsigned char *data, unsigned int *length, 
    5374    unsigned char *tag, unsigned char *sy, 
    5475    int cycle, unsigned int dropped, unsigned int max_length ) 
    5576{ 
    56     struct iec61883_packet *packet = ( struct iec61883_packet * ) data; 
    57     /* Our node ID can change after a bus reset, so it is best to fetch 
    58     * our node ID for each packet. */ 
    59     packet->sid = m_handler->getLocalNodeId() & 0x3f; 
    60  
    61     packet->dbs = m_dimension; 
    62     packet->fn = 0; 
    63     packet->qpc = 0; 
    64     packet->sph = 0; 
    65     packet->reserved = 0; 
    66     packet->dbc = m_dbc; 
    67     packet->eoh1 = 2; 
    68     packet->fmt = IEC61883_FMT_AMDTP; 
    69  
    70     *tag = IEC61883_TAG_WITH_CIP; 
    71     *sy = 0; 
     77    // The number of events per packet expected by the MOTU is solely 
     78    // dependent on the current sample rate.  An 'event' is one sample from 
     79    // all channels plus possibly other midi and control data. 
     80    signed n_events = getNominalFramesPerPacket(); 
     81 
     82    // Do housekeeping expected for all packets sent to the MOTU, even 
     83    // for packets containing no audio data. 
     84    *sy = 0x00; 
     85    *tag = 1;      // All MOTU packets have a CIP-like header 
     86    *length = n_events*m_event_size + 8; 
    7287 
    7388    signed int fc; 
     
    143158    // 2) there are enough packets 
    144159    //      => determine whether we have to send them in this packet 
    145     if ( fc < ( signed int ) m_syt_interval
     160    if ( fc < ( signed int ) getNominalFramesPerPacket()
    146161    { 
    147162        // not enough frames in the buffer, 
     
    201216            { 
    202217                // we are not that late and can still try to transmit the packet 
    203                 m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp); 
     218                m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp); 
     219                if (m_tx_dbc > 0xff) 
     220                    m_tx_dbc -= 0x100; 
    204221                return eCRV_Packet; 
    205222            } 
     
    212229        { 
    213230            // it's time send the packet 
    214             m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp); 
     231            m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp); 
     232            if (m_tx_dbc > 0xff) 
     233                m_tx_dbc -= 0x100; 
    215234            return eCRV_Packet; 
    216235        } 
     
    242261 
    243262enum StreamProcessor::eChildReturnValue 
    244 AmdtpTransmitStreamProcessor::generatePacketData ( 
     263MotuTransmitStreamProcessor::generatePacketData ( 
    245264    unsigned char *data, unsigned int *length, 
    246265    unsigned char *tag, unsigned char *sy, 
    247266    int cycle, unsigned int dropped, unsigned int max_length ) 
    248267{ 
    249     struct iec61883_packet *packet = ( struct iec61883_packet * ) data; 
    250     if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) ) 
    251     { 
    252         // process all ports that should be handled on a per-packet base 
    253         // this is MIDI for AMDTP (due to the need of DBC) 
    254         if ( !encodePacketPorts ( ( quadlet_t * ) ( data+8 ), m_syt_interval, packet->dbc ) ) 
    255         { 
    256             debugWarning ( "Problem encoding Packet Ports\n" ); 
    257         } 
    258         debugOutput ( DEBUG_LEVEL_VERY_VERBOSE, "XMIT DATA: TSP=%011llu (%04u)\n", 
    259                     cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) ); 
     268    quadlet_t *quadlet = (quadlet_t *)data; 
     269    quadlet += 2; // skip the header 
     270    // Size of a single data frame in quadlets 
     271    unsigned dbs = m_event_size / 4; 
     272 
     273    // The number of events per packet expected by the MOTU is solely 
     274    // dependent on the current sample rate.  An 'event' is one sample from 
     275    // all channels plus possibly other midi and control data. 
     276    signed n_events = getNominalFramesPerPacket(); 
     277 
     278    if (m_data_buffer->readFrames(n_events, (char *)(data + 8))) { 
     279        float ticks_per_frame = m_manager->getSyncSource().getActualRate(); 
     280 
     281#if TESTTONE 
     282        // FIXME: remove this hacked in 1 kHz test signal to 
     283        // analog-1 when testing is complete. 
     284        signed int int_tpf = (int)ticks_per_frame; 
     285        unsigned char *sample = data+8+16; 
     286        for (i=0; i<n_events; i++, sample+=m_event_size) { 
     287            static signed int a_cx = 0; 
     288            // Each sample is 3 bytes with MSB in lowest address (ie:  
     289            // network byte order).  After byte order swap, the 24-bit 
     290            // MSB is in the second byte of val. 
     291            signed int val = htonl((int)(0x7fffff*sin((1000.0*2.0*M_PI/24576000.0)*a_cx))); 
     292            memcpy(sample,((char *)&val)+1,3); 
     293            if ((a_cx+=int_tpf) >= 24576000) { 
     294                a_cx -= 24576000; 
     295            } 
     296        } 
     297#endif 
     298 
     299        // Set up each frames's SPH. 
     300        for (unsigned int i=0; i<n_events; i++, quadlet += dbs) { 
     301//FIXME: not sure which is best for the MOTU 
     302//            int64_t ts_frame = addTicks(ts, (unsigned int)(i * ticks_per_frame)); 
     303            int64_t ts_frame = addTicks(m_last_timestamp, (unsigned int)(i * ticks_per_frame)); 
     304            *quadlet = htonl(fullTicksToSph(ts_frame)); 
     305        } 
     306 
     307        // Process all ports that should be handled on a per-packet base 
     308        // this is MIDI for AMDTP (due to the need of DBC, which is lost 
     309        // when putting the events in the ringbuffer) 
     310        // for motu this might also be control data, however as control 
     311        // data isn't time specific I would also include it in the period 
     312        // based processing 
     313 
     314        // FIXME: m_tx_dbc probably needs to be initialised to a non-zero 
     315        // value somehow so MIDI sync is possible.  For now we ignore 
     316        // this issue. 
     317        if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) { 
     318            debugWarning("Problem encoding Packet Ports\n"); 
     319        } 
     320 
    260321        return eCRV_OK; 
    261322    } 
     
    265326 
    266327enum StreamProcessor::eChildReturnValue 
    267 AmdtpTransmitStreamProcessor::generateSilentPacketHeader ( 
     328MotuTransmitStreamProcessor::generateSilentPacketHeader ( 
    268329    unsigned char *data, unsigned int *length, 
    269330    unsigned char *tag, unsigned char *sy, 
    270331    int cycle, unsigned int dropped, unsigned int max_length ) 
    271332{ 
    272     struct iec61883_packet *packet = ( struct iec61883_packet * ) data; 
    273333    debugOutput ( DEBUG_LEVEL_VERY_VERBOSE, "XMIT NONE: CY=%04u, TSP=%011llu (%04u)\n", 
    274334                cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) ); 
    275335 
    276     /* Our node ID can change after a bus reset, so it is best to fetch 
    277     * our node ID for each packet. */ 
    278     packet->sid = m_handler->getLocalNodeId() & 0x3f; 
    279  
    280     packet->dbs = m_dimension; 
    281     packet->fn = 0; 
    282     packet->qpc = 0; 
    283     packet->sph = 0; 
    284     packet->reserved = 0; 
    285     packet->dbc = m_dbc; 
    286     packet->eoh1 = 2; 
    287     packet->fmt = IEC61883_FMT_AMDTP; 
    288  
    289     *tag = IEC61883_TAG_WITH_CIP; 
    290     *sy = 0; 
    291  
    292     m_dbc += fillNoDataPacketHeader ( packet, length ); 
     336    // Do housekeeping expected for all packets sent to the MOTU, even 
     337    // for packets containing no audio data. 
     338    *sy = 0x00; 
     339    *tag = 1;      // All MOTU packets have a CIP-like header 
     340    *length = 8; 
     341 
     342    m_tx_dbc += fillNoDataPacketHeader ( (quadlet_t *)data, length ); 
    293343    return eCRV_OK; 
    294344} 
    295345 
    296346enum StreamProcessor::eChildReturnValue 
    297 AmdtpTransmitStreamProcessor::generateSilentPacketData ( 
     347MotuTransmitStreamProcessor::generateSilentPacketData ( 
    298348    unsigned char *data, unsigned int *length, 
    299349    unsigned char *tag, unsigned char *sy, 
     
    303353} 
    304354 
    305 unsigned int AmdtpTransmitStreamProcessor::fillDataPacketHeader ( 
    306     struct iec61883_packet *packet, unsigned int* length, 
     355unsigned int MotuTransmitStreamProcessor::fillDataPacketHeader ( 
     356    quadlet_t *data, unsigned int* length, 
    307357    uint32_t ts ) 
    308358{ 
    309  
    310     packet->fdf = m_fdf; 
    311  
    312     // convert the timestamp to SYT format 
    313     uint16_t timestamp_SYT = TICKS_TO_SYT ( ts ); 
    314     packet->syt = ntohs ( timestamp_SYT ); 
    315  
    316     *length = m_syt_interval*sizeof ( quadlet_t ) *m_dimension + 8; 
    317  
    318     return m_syt_interval; 
    319 
    320  
    321 unsigned int AmdtpTransmitStreamProcessor::fillNoDataPacketHeader ( 
    322     struct iec61883_packet *packet, unsigned int* length ) 
    323 
    324  
    325     // no-data packets have syt=0xFFFF 
    326     // and have the usual amount of events as dummy data (?) 
    327     packet->fdf = IEC61883_FDF_NODATA; 
    328     packet->syt = 0xffff; 
    329  
    330     // FIXME: either make this a setting or choose 
    331     bool send_payload=true; 
    332     if ( send_payload ) 
    333     { 
    334         // this means no-data packets with payload (DICE doesn't like that) 
    335         *length = 2*sizeof ( quadlet_t ) + m_syt_interval * m_dimension * sizeof ( quadlet_t ); 
    336         return m_syt_interval; 
    337     } 
    338     else 
    339     { 
    340         // dbc is not incremented 
    341         // this means no-data packets without payload 
    342         *length = 2*sizeof ( quadlet_t ); 
    343         return 0; 
    344     } 
    345 
    346  
    347 unsigned int 
    348 AmdtpTransmitStreamProcessor::getNominalPacketsNeeded(unsigned int nframes) 
    349 
    350     unsigned int nominal_frames_per_second = m_manager->getNominalRate(); 
    351     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second; 
    352     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes; 
    353     uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE; 
    354     return nominal_packets; 
    355 
    356  
    357 unsigned int 
    358 AmdtpTransmitStreamProcessor::getPacketsPerPeriod() 
    359 
    360     return getNominalPacketsNeeded(m_manager->getPeriodSize()); 
    361 
    362  
    363 bool AmdtpTransmitStreamProcessor::prepareChild() 
     359    quadlet_t *quadlet = (quadlet_t *)data; 
     360    // Size of a single data frame in quadlets 
     361    unsigned dbs = m_event_size / 4; 
     362 
     363    // The number of events per packet expected by the MOTU is solely 
     364    // dependent on the current sample rate.  An 'event' is one sample from 
     365    // all channels plus possibly other midi and control data. 
     366    signed n_events = getNominalFramesPerPacket(); 
     367 
     368    // construct the packet CIP-like header.  Even if this is a data-less 
     369    // packet the dbs field is still set as if there were data blocks 
     370    // present.  For data-less packets the dbc is the same as the previously 
     371    // transmitted block. 
     372    *quadlet = htonl(0x00000400 | ((m_handler->getLocalNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     373    quadlet++; 
     374    *quadlet = htonl(0x8222ffff); 
     375    quadlet++; 
     376    return n_events; 
     377
     378 
     379unsigned int MotuTransmitStreamProcessor::fillNoDataPacketHeader ( 
     380    quadlet_t *data, unsigned int* length ) 
     381
     382    quadlet_t *quadlet = (quadlet_t *)data; 
     383    // Size of a single data frame in quadlets 
     384    unsigned dbs = m_event_size / 4; 
     385    // construct the packet CIP-like header.  Even if this is a data-less 
     386    // packet the dbs field is still set as if there were data blocks 
     387    // present.  For data-less packets the dbc is the same as the previously 
     388    // transmitted block. 
     389    *quadlet = htonl(0x00000400 | ((m_handler->getLocalNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     390    quadlet++; 
     391    *quadlet = htonl(0x8222ffff); 
     392    quadlet++; 
     393    *length = 8; 
     394    return 0; 
     395
     396 
     397bool MotuTransmitStreamProcessor::prepareChild() 
    364398{ 
    365399    debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this ); 
    366     switch ( m_manager->getNominalRate() ) 
    367     { 
    368         case 32000: 
    369             m_syt_interval = 8; 
    370             m_fdf = IEC61883_FDF_SFC_32KHZ; 
    371             break; 
    372         case 44100: 
    373             m_syt_interval = 8; 
    374             m_fdf = IEC61883_FDF_SFC_44K1HZ; 
    375             break; 
    376         default: 
    377         case 48000: 
    378             m_syt_interval = 8; 
    379             m_fdf = IEC61883_FDF_SFC_48KHZ; 
    380             break; 
    381         case 88200: 
    382             m_syt_interval = 16; 
    383             m_fdf = IEC61883_FDF_SFC_88K2HZ; 
    384             break; 
    385         case 96000: 
    386             m_syt_interval = 16; 
    387             m_fdf = IEC61883_FDF_SFC_96KHZ; 
    388             break; 
    389         case 176400: 
    390             m_syt_interval = 32; 
    391             m_fdf = IEC61883_FDF_SFC_176K4HZ; 
    392             break; 
    393         case 192000: 
    394             m_syt_interval = 32; 
    395             m_fdf = IEC61883_FDF_SFC_192KHZ; 
    396             break; 
    397     } 
    398  
    399     iec61883_cip_init ( 
    400         &m_cip_status, 
    401         IEC61883_FMT_AMDTP, 
    402         m_fdf, 
    403         m_manager->getNominalRate(), 
    404         m_dimension, 
    405         m_syt_interval ); 
    406  
     400 
     401 
     402#if 0 
    407403    for ( PortVectorIterator it = m_Ports.begin(); 
    408404            it != m_Ports.end(); 
     
    431427        } 
    432428    } 
     429#endif 
    433430 
    434431    debugOutput ( DEBUG_LEVEL_VERBOSE, "Prepared for:\n" ); 
    435     debugOutput ( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, FDF: %d, DBS: %d, SYT: %d\n", 
    436                 m_manager->getNominalRate(), m_fdf, m_dimension, m_syt_interval ); 
     432    debugOutput ( DEBUG_LEVEL_VERBOSE, " Samplerate: %d\n", 
     433                m_manager->getNominalRate() ); 
    437434    debugOutput ( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", 
    438435                m_manager->getPeriodSize(), m_manager->getNbBuffers() ); 
    439436    debugOutput ( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", 
    440                 m_port,m_channel ); 
     437                m_port, m_channel ); 
    441438    return true; 
    442439} 
     
    445442* compose the event streams for the packets from the port buffers 
    446443*/ 
    447 bool AmdtpTransmitStreamProcessor::processWriteBlock ( char *data, 
    448         unsigned int nevents, unsigned int offset ) 
    449 
     444bool MotuTransmitStreamProcessor::processWriteBlock(char *data, 
     445                       unsigned int nevents, unsigned int offset) { 
     446    bool no_problem=true; 
     447    unsigned int i; 
     448 
     449    // FIXME: ensure the MIDI and control streams are all zeroed until 
     450    // such time as they are fully implemented. 
     451    for (i=0; i<nevents; i++) { 
     452        memset(data+4+i*m_event_size, 0x00, 6); 
     453    } 
     454 
     455    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
     456      it != m_PeriodPorts.end(); 
     457      ++it ) { 
     458        // If this port is disabled, don't process it 
     459        if((*it)->isDisabled()) {continue;}; 
     460 
     461        //FIXME: make this into a static_cast when not DEBUG? 
     462        Port *port=dynamic_cast<Port *>(*it); 
     463 
     464        switch(port->getPortType()) { 
     465 
     466        case Port::E_Audio: 
     467            if (encodePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     468                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     469                no_problem=false; 
     470            } 
     471            break; 
     472        // midi is a packet based port, don't process 
     473        //    case MotuPortInfo::E_Midi: 
     474        //        break; 
     475 
     476        default: // ignore 
     477            break; 
     478        } 
     479    } 
     480    return no_problem; 
     481
     482 
     483bool 
     484MotuTransmitStreamProcessor::transmitSilenceBlock(char *data, 
     485                       unsigned int nevents, unsigned int offset) { 
     486    // This is the same as the non-silence version, except that is 
     487    // doesn't read from the port buffers. 
    450488    bool no_problem = true; 
    451  
    452489    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    453           it != m_PeriodPorts.end(); 
    454           ++it ) 
    455     { 
    456         if ( (*it)->isDisabled() ) { continue; }; 
    457  
     490      it != m_PeriodPorts.end(); 
     491      ++it ) { 
    458492        //FIXME: make this into a static_cast when not DEBUG? 
    459         AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); 
    460         assert ( pinfo ); // this should not fail!! 
    461  
    462         switch( pinfo->getFormat() ) 
    463         { 
    464             case AmdtpPortInfo::E_MBLA: 
    465                 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    466                 { 
    467                     debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); 
    468                     no_problem = false; 
     493        Port *port=dynamic_cast<Port *>(*it); 
     494 
     495        switch(port->getPortType()) { 
     496 
     497        case Port::E_Audio: 
     498            if (encodeSilencePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     499                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     500                no_problem = false; 
     501            } 
     502            break; 
     503        // midi is a packet based port, don't process 
     504        //    case MotuPortInfo::E_Midi: 
     505        //        break; 
     506 
     507        default: // ignore 
     508            break; 
     509        } 
     510    } 
     511    return no_problem; 
     512
     513 
     514/** 
     515 * @brief encode a packet for the packet-based ports 
     516 * 
     517 * @param data Packet data 
     518 * @param nevents number of events in data (including events of other ports & port types) 
     519 * @param dbc DataBlockCount value for this packet 
     520 * @return true if all successfull 
     521 */ 
     522bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, 
     523        unsigned int dbc) { 
     524    bool ok=true; 
     525    char byte; 
     526 
     527    // Use char here since the target address won't necessarily be 
     528    // aligned; use of an unaligned quadlet_t may cause issues on 
     529    // certain architectures.  Besides, the target for MIDI data going 
     530    // directly to the MOTU isn't structured in quadlets anyway; it is a 
     531    // sequence of 3 unaligned bytes. 
     532    unsigned char *target = NULL; 
     533 
     534    for ( PortVectorIterator it = m_PacketPorts.begin(); 
     535        it != m_PacketPorts.end(); 
     536        ++it ) { 
     537 
     538        Port *port=static_cast<Port *>(*it); 
     539         assert(port); // this should not fail!! 
     540 
     541        // Currently the only packet type of events for MOTU 
     542        // is MIDI in mbla.  However in future control data 
     543        // might also be sent via "packet" events. 
     544        // assert(pinfo->getFormat()==MotuPortInfo::E_Midi); 
     545 
     546        // FIXME: MIDI output is completely untested at present. 
     547        switch (port->getPortType()) { 
     548            case Port::E_Midi: { 
     549                MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it); 
     550 
     551                // Send a byte if we can. MOTU MIDI data is 
     552                // sent using a 3-byte sequence starting at 
     553                // the port's position.  For now we'll 
     554                // always send in the first event of a 
     555                // packet, but this might need refinement 
     556                // later. 
     557                if (mp->canRead()) { 
     558                    mp->readEvent(&byte); 
     559                    target = (unsigned char *)data + mp->getPosition(); 
     560                    *(target++) = 0x01; 
     561                    *(target++) = 0x00; 
     562                    *(target++) = byte; 
    469563                } 
    470564                break; 
    471             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    472                 break; 
    473             default: // ignore 
    474                 break; 
    475         } 
    476     } 
    477     return no_problem; 
    478 
    479  
    480 bool 
    481 AmdtpTransmitStreamProcessor::transmitSilenceBlock( 
    482     char *data, unsigned int nevents, unsigned int offset) 
    483 
    484     bool no_problem = true; 
    485     for(PortVectorIterator it = m_PeriodPorts.begin(); 
    486         it != m_PeriodPorts.end(); 
    487         ++it ) 
    488     { 
    489         //FIXME: make this into a static_cast when not DEBUG? 
    490         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    491         assert(pinfo); // this should not fail!! 
    492  
    493         switch( pinfo->getFormat() ) 
    494         { 
    495             case AmdtpPortInfo::E_MBLA: 
    496                 if ( encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    497                 { 
    498                     debugWarning("Could not encode port %s to MBLA events", (*it)->getName().c_str()); 
    499                     no_problem = false; 
    500                 } 
    501                 break; 
    502             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    503                 break; 
    504             default: // ignore 
    505                 break; 
    506         } 
    507     } 
    508     return no_problem; 
    509 
    510  
    511 /** 
    512 * @brief decode a packet for the packet-based ports 
    513 
    514 * @param data Packet data 
    515 * @param nevents number of events in data (including events of other ports & port types) 
    516 * @param dbc DataBlockCount value for this packet 
    517 * @return true if all successfull 
    518 */ 
    519 bool AmdtpTransmitStreamProcessor::encodePacketPorts ( quadlet_t *data, unsigned int nevents, unsigned int dbc ) 
    520 
    521     bool ok=true; 
    522     quadlet_t byte; 
    523  
    524     quadlet_t *target_event=NULL; 
    525     unsigned int j; 
    526  
    527     for ( PortVectorIterator it = m_PacketPorts.begin(); 
    528             it != m_PacketPorts.end(); 
    529             ++it ) 
    530     { 
    531  
    532 #ifdef DEBUG 
    533         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *> ( *it ); 
    534         assert ( pinfo ); // this should not fail!! 
    535  
    536         // the only packet type of events for AMDTP is MIDI in mbla 
    537         assert ( pinfo->getFormat() ==AmdtpPortInfo::E_Midi ); 
    538 #endif 
    539  
    540         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *> ( *it ); 
    541  
    542         // we encode this directly (no function call) due to the high frequency 
    543         /* idea: 
    544         spec says: current_midi_port=(dbc+j)%8; 
    545         => if we start at (dbc+stream->location-1)%8, 
    546         we'll start at the right event for the midi port. 
    547         => if we increment j with 8, we stay at the right event. 
    548         */ 
    549         // FIXME: as we know in advance how big a packet is (syt_interval) we can 
    550         //        predict how much loops will be present here 
    551         // first prefill the buffer with NO_DATA's on all time muxed channels 
    552  
    553         for ( j = ( dbc & 0x07 ) +mp->getLocation(); j < nevents; j += 8 ) 
    554         { 
    555  
    556             quadlet_t tmpval; 
    557  
    558             target_event= ( quadlet_t * ) ( data + ( ( j * m_dimension ) + mp->getPosition() ) ); 
    559  
    560             if ( mp->canRead() )   // we can send a byte 
    561             { 
    562                 mp->readEvent ( &byte ); 
    563                 byte &= 0xFF; 
    564                 tmpval=htonl ( 
    565                         IEC61883_AM824_SET_LABEL ( ( byte ) <<16, 
    566                                                     IEC61883_AM824_LABEL_MIDI_1X ) ); 
    567  
    568                 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n", 
    569                             mp->getName().c_str(), mp->getPosition(), mp->getLocation(), dbc, nevents, m_dimension ); 
    570                 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", 
    571                             data, target_event, tmpval ); 
    572  
    573             } 
    574             else 
    575             { 
    576                 // can't send a byte, either because there is no byte, 
    577                 // or because this would exceed the maximum rate 
    578                 tmpval=htonl ( 
    579                         IEC61883_AM824_SET_LABEL ( 0,IEC61883_AM824_LABEL_MIDI_NO_DATA ) ); 
    580             } 
    581  
    582             *target_event=tmpval; 
    583         } 
    584  
    585     } 
     565            } 
     566            default: 
     567                debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port type %d\n",port->getPortType()); 
     568                return ok; 
     569              } 
     570    } 
     571 
    586572    return ok; 
    587573} 
    588574 
    589  
    590 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    591         unsigned int offset, unsigned int nevents ) 
    592 
     575int MotuTransmitStreamProcessor::encodePortToMotuEvents(MotuAudioPort *p, quadlet_t *data, 
     576                       unsigned int offset, unsigned int nevents) { 
     577// Encodes nevents worth of data from the given port into the given buffer.  The 
     578// format of the buffer is precisely that which will be sent to the MOTU. 
     579// The basic idea: 
     580//   iterate over the ports 
     581//     * get port buffer address 
     582//     * loop over events 
     583//         - pick right sample in event based upon PortInfo 
     584//         - convert sample from Port format (E_Int24, E_Float, ..) to MOTU 
     585//           native format 
     586// 
     587// We include the ability to start the transfer from the given offset within 
     588// the port (expressed in frames) so the 'efficient' transfer method can be 
     589// utilised. 
     590 
    593591    unsigned int j=0; 
    594592 
    595     quadlet_t *target_event; 
    596  
    597     target_event= ( quadlet_t * ) ( data + p->getPosition() ); 
    598  
    599     switch ( p->getDataType() ) 
    600     { 
     593    // Use char here since the target address won't necessarily be 
     594    // aligned; use of an unaligned quadlet_t may cause issues on certain 
     595    // architectures.  Besides, the target (data going directly to the MOTU) 
     596    // isn't structured in quadlets anyway; it mainly consists of packed 
     597    // 24-bit integers. 
     598    unsigned char *target; 
     599    target = (unsigned char *)data + p->getPosition(); 
     600 
     601    switch(p->getDataType()) { 
    601602        default: 
    602603        case Port::E_Int24: 
    603         { 
    604             quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() ); 
    605  
    606             assert ( nevents + offset <= p->getBufferSize() ); 
    607  
    608             buffer+=offset; 
    609  
    610             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    611604            { 
    612                 *target_event = htonl ( ( * ( buffer ) & 0x00FFFFFF ) | 0x40000000 ); 
    613                 buffer++; 
    614                 target_event += m_dimension; 
    615             } 
    616         } 
    617         break; 
     605                quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
     606 
     607                assert(nevents + offset <= p->getBufferSize()); 
     608 
     609                // Offset is in frames, but each port is only a single 
     610                // channel, so the number of frames is the same as the 
     611                // number of quadlets to offset (assuming the port buffer 
     612                // uses one quadlet per sample, which is the case currently). 
     613                buffer+=offset; 
     614 
     615                for(j = 0; j < nevents; j += 1) { // Decode nsamples 
     616                    *target = (*buffer >> 16) & 0xff; 
     617                    *(target+1) = (*buffer >> 8) & 0xff; 
     618                    *(target+2) = (*buffer) & 0xff; 
     619 
     620                    buffer++; 
     621                    target+=m_event_size; 
     622                } 
     623            } 
     624            break; 
    618625        case Port::E_Float: 
    619         { 
    620             const float multiplier = ( float ) ( 0x7FFFFF00 ); 
    621             float *buffer= ( float * ) ( p->getBufferAddress() ); 
    622  
    623             assert ( nevents + offset <= p->getBufferSize() ); 
    624  
    625             buffer+=offset; 
    626  
    627             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    628626            { 
    629  
    630                 // don't care for overflow 
    631                 float v = *buffer * multiplier;  // v: -231 .. 231 
    632                 unsigned int tmp = ( ( int ) v ); 
    633                 *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 
    634  
    635                 buffer++; 
    636                 target_event += m_dimension; 
    637             } 
    638         } 
    639         break; 
     627                const float multiplier = (float)(0x7FFFFF); 
     628                float *buffer=(float *)(p->getBufferAddress()); 
     629 
     630                assert(nevents + offset <= p->getBufferSize()); 
     631 
     632                buffer+=offset; 
     633 
     634                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
     635                    unsigned int v = (int)(*buffer * multiplier); 
     636                    *target = (v >> 16) & 0xff; 
     637                    *(target+1) = (v >> 8) & 0xff; 
     638                    *(target+2) = v & 0xff; 
     639 
     640                    buffer++; 
     641                    target+=m_event_size; 
     642                } 
     643            } 
     644            break; 
    640645    } 
    641646 
    642647    return 0; 
    643648} 
    644 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    645         unsigned int offset, unsigned int nevents ) 
    646 
     649 
     650int MotuTransmitStreamProcessor::encodeSilencePortToMotuEvents(MotuAudioPort *p, quadlet_t *data, 
     651                       unsigned int offset, unsigned int nevents)
    647652    unsigned int j=0; 
    648  
    649     quadlet_t *target_event; 
    650  
    651     target_event= ( quadlet_t * ) ( data + p->getPosition() ); 
    652  
    653     switch ( p->getDataType() ) 
    654     { 
    655         default: 
     653    unsigned char *target = (unsigned char *)data + p->getPosition(); 
     654 
     655    switch (p->getDataType()) { 
     656    default: 
    656657        case Port::E_Int24: 
    657658        case Port::E_Float: 
    658         { 
    659             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    660             { 
    661                 *target_event = htonl ( 0x40000000 ); 
    662                 target_event += m_dimension; 
    663             } 
     659        for (j = 0; j < nevents; j++) { 
     660            *target = *(target+1) = *(target+2) = 0; 
     661            target += m_event_size; 
    664662        } 
    665663        break; 
  • branches/ppalmers-streaming/src/libstreaming/motu/MotuTransmitStreamProcessor.h

    r732 r733  
    2222 */ 
    2323 
    24 #ifndef __FFADO_AMDTPTRANSMITSTREAMPROCESSOR__ 
    25 #define __FFADO_AMDTPTRANSMITSTREAMPROCESSOR__ 
     24#ifndef __FFADO_MOTUTRANSMITSTREAMPROCESSOR__ 
     25#define __FFADO_MOTUTRANSMITSTREAMPROCESSOR__ 
    2626 
    2727/** 
    28  * This class implements IEC61883-6 / AM824 / AMDTP based streaming 
     28 * This class implements MOTU based streaming 
    2929 */ 
    3030 
     
    3434#include "../util/cip.h" 
    3535 
    36 #include <libiec61883/iec61883.h> 
    37 #include <pthread.h> 
    38  
    39 #define AMDTP_MAX_PACKET_SIZE 2048 
    40  
    41 #define IEC61883_STREAM_TYPE_MIDI   0x0D 
    42 #define IEC61883_STREAM_TYPE_SPDIF  0x00 
    43 #define IEC61883_STREAM_TYPE_MBLA   0x06 
    44  
    45 #define IEC61883_AM824_LABEL_MASK             0xFF000000 
    46 #define IEC61883_AM824_GET_LABEL(x)         (((x) & 0xFF000000) >> 24) 
    47 #define IEC61883_AM824_SET_LABEL(x,y)         ((x) | ((y)<<24)) 
    48  
    49 #define IEC61883_AM824_LABEL_MIDI_NO_DATA     0x80 
    50 #define IEC61883_AM824_LABEL_MIDI_1X          0x81 
    51 #define IEC61883_AM824_LABEL_MIDI_2X          0x82 
    52 #define IEC61883_AM824_LABEL_MIDI_3X          0x83 
    53  
    5436namespace Streaming { 
    5537 
    5638class Port; 
    57 class AmdtpAudioPort; 
    58 class AmdtpMidiPort; 
     39class MotuAudioPort; 
    5940 
    6041/*! 
    61 \brief The Base Class for an AMDTP transmit stream processor 
     42\brief The Base Class for an MOTU transmit stream processor 
    6243 
    6344 This class implements a TransmitStreamProcessor that multiplexes Ports 
    64  into AMDTP streams. 
     45 into MOTU streams. 
    6546 
    6647*/ 
    67 class AmdtpTransmitStreamProcessor 
     48class MotuTransmitStreamProcessor 
    6849    : public StreamProcessor 
    6950{ 
     
    7152public: 
    7253    /** 
    73      * Create a AMDTP transmit StreamProcessor 
    74      * @param port 1394 port 
    75      * @param framerate frame rate 
    76      * @param dimension number of substreams in the ISO stream 
    77      *                  (midi-muxed is only one stream) 
     54     * Create a MOTU transmit StreamProcessor 
    7855     */ 
    79     AmdtpTransmitStreamProcessor(int port, int dimension); 
    80     virtual ~AmdtpTransmitStreamProcessor() {}; 
     56    MotuTransmitStreamProcessor(int port, unsigned int event_size); 
     57    virtual ~MotuTransmitStreamProcessor() {}; 
    8158 
    8259    enum eChildReturnValue generatePacketHeader(unsigned char *data, unsigned int *length, 
     
    9572 
    9673public: 
    97     virtual unsigned int getEventSize() 
    98                     {return 4;}; 
    99     virtual unsigned int getMaxPacketSize() 
    100                     {return 4 * (2 + m_syt_interval * m_dimension);}; 
    101     virtual unsigned int getEventsPerFrame() 
    102                     { return m_dimension; }; 
    103     virtual unsigned int getNominalFramesPerPacket() 
    104                     {return m_syt_interval;}; 
    105     virtual unsigned int getPacketsPerPeriod(); 
    106     virtual unsigned int getNominalPacketsNeeded(unsigned int nframes); 
     74    virtual unsigned int getEventSize()  
     75                {return m_event_size;}; 
     76    virtual unsigned int getMaxPacketSize(); 
     77    virtual unsigned int getEventsPerFrame()  
     78                    { return 1; }; // FIXME: check 
     79    virtual unsigned int getNominalFramesPerPacket(); 
    10780 
    10881protected: 
     
    11184 
    11285private: 
    113     unsigned int fillNoDataPacketHeader(struct iec61883_packet *packet, unsigned int* length); 
    114     unsigned int fillDataPacketHeader(struct iec61883_packet *packet, unsigned int* length, uint32_t ts); 
     86    unsigned int fillNoDataPacketHeader(quadlet_t *data, unsigned int* length); 
     87    unsigned int fillDataPacketHeader(quadlet_t *data, unsigned int* length, uint32_t ts); 
    11588 
    11689    int transmitBlock(char *data, unsigned int nevents, 
     
    12093                           unsigned int dbc); 
    12194 
    122     int encodePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 
     95    int encodePortToMotuEvents(MotuAudioPort *, quadlet_t *data, 
    12396                                unsigned int offset, unsigned int nevents); 
    124     int encodeSilencePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 
     97    int encodeSilencePortToMotuEvents(MotuAudioPort *, quadlet_t *data, 
    12598                                unsigned int offset, unsigned int nevents); 
    12699 
    127     struct iec61883_cip m_cip_status; 
    128     int m_dimension; 
    129     unsigned int m_syt_interval; 
    130     int m_fdf; 
    131     unsigned int m_dbc; 
     100    /* 
     101     * An iso packet mostly consists of multiple events.  m_event_size 
     102     * is the size of a single 'event' in bytes. 
     103     */ 
     104    unsigned int m_event_size; 
     105 
     106    // Keep track of transmission data block count 
     107    unsigned int m_tx_dbc; 
     108 
    132109}; 
    133110 
    134111} // end of namespace Streaming 
    135112 
    136 #endif /* __FFADO_AMDTPTRANSMITSTREAMPROCESSOR__ */ 
     113#endif /* __FFADO_MOTUTRANSMITSTREAMPROCESSOR__ */ 
    137114 
  • branches/ppalmers-streaming/src/motu/motu_avdevice.cpp

    r705 r733  
    3232#include "debugmodule/debugmodule.h" 
    3333 
    34 #include "libstreaming/motu/MotuStreamProcessor.h" 
     34#include "libstreaming/motu/MotuReceiveStreamProcessor.h" 
     35#include "libstreaming/motu/MotuTransmitStreamProcessor.h" 
    3536#include "libstreaming/motu/MotuPort.h" 
    3637 
     
    523524 
    524525    m_receiveProcessor=new Streaming::MotuReceiveStreamProcessor( 
    525         m_p1394Service->getPort(), samp_freq, event_size_in); 
     526        m_p1394Service->getPort(), event_size_in); 
    526527 
    527528    // The first thing is to initialize the processor.  This creates the 
     
    593594    // Do the same for the transmit processor 
    594595    m_transmitProcessor=new Streaming::MotuTransmitStreamProcessor( 
    595         m_p1394Service->getPort(), getSamplingFrequency(), event_size_out); 
     596        m_p1394Service->getPort(), event_size_out); 
    596597 
    597598    m_transmitProcessor->setVerboseLevel(getDebugLevel()); 
  • branches/ppalmers-streaming/src/motu/motu_avdevice.h

    r705 r733  
    3131#include "libavc/avc_definitions.h" 
    3232 
    33 #include "libstreaming/motu/MotuStreamProcessor.h" 
     33#include "libstreaming/motu/MotuReceiveStreamProcessor.h" 
     34#include "libstreaming/motu/MotuTransmitStreamProcessor.h" 
    3435 
    3536#define MOTUFW_BASE_ADDR                0xfffff0000000ULL 
  • branches/ppalmers-streaming/src/SConscript

    r730 r733  
    123123        libstreaming/motu/MotuPort.cpp \ 
    124124        libstreaming/motu/MotuPortInfo.cpp \ 
    125         libstreaming/motu/MotuStreamProcessor.cpp \ 
     125        libstreaming/motu/MotuReceiveStreamProcessor.cpp \ 
     126        libstreaming/motu/MotuTransmitStreamProcessor.cpp \ 
    126127' ) 
    127128