Changeset 384

Show
Ignore:
Timestamp:
01/30/07 13:11:25 (17 years ago)
Author:
pieterpalmers
Message:

- temporary commit as backup measure
- rewrote synchronisation code
- receive streaming based on SYT works
- transmit streaming synced to received stream sort of works, still

have to iron out some issues.

NOTE: all devices but the bebob's are disabled in this code,

because they still have to be ported to the new sync
mechanism.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/streaming-rework/config.h.in

    r365 r384  
    8484#undef const 
    8585 
    86 /* Define to `unsigned int' if <sys/types.h> does not define. */ 
     86/* Define to `unsigned' if <sys/types.h> does not define. */ 
    8787#undef size_t 
    8888 
  • branches/streaming-rework/configure.ac

    r358 r384  
    113113 
    114114# Check for dependencies 
     115PKG_CHECK_MODULES(LIBRAW1394_122, libraw1394 >= 1.2.2, libraw1394_1_2_2=yes, libraw1394_1_2_2=no) 
    115116PKG_CHECK_MODULES(LIBRAW1394, libraw1394 >= 1.2.1) 
    116117PKG_CHECK_MODULES(LIBIEC61883, libiec61883 >= 1.0.0) 
     
    129130esac],[debug=false]) 
    130131 
     132if test "x$libraw1394_1_2_2" = xyes; then 
     133        CFLAGS="$CFLAGS -DLIBRAW1394_USE_CTRREAD_API" 
     134        CXXFLAGS="$CXXFLAGS -DLIBRAW1394_USE_CTRREAD_API"  
     135fi 
    131136 
    132137dnl Check for MMX assembly 
     
    248253  Source directory:     $srcdir 
    249254  Installation prefix:  $prefix 
     255  C compiler:           $C $CFLAGS 
    250256  C++ compiler:         $CXX $CXXFLAGS 
    251257 
    252258  libraw1394 CFLAGS:    $LIBRAW1394_CFLAGS 
    253259  libraw1394 LIBS:      $LIBRAW1394_LIBS 
     260   use new cycle timer read api? $libraw1394_1_2_2 
    254261  libiec61883 CFLAGS:   $LIBIEC61883_CFLAGS 
    255262  libiec61883 LIBS:     $LIBIEC61883_LIBS 
  • branches/streaming-rework/src/bebob/bebob_avdevice.cpp

    r379 r384  
    993993        } 
    994994 
    995         // FIXME: do this the proper way! 
    996         m_transmitProcessor->syncmaster=m_receiveProcessor; 
    997  
    998995        if (!addPlugToProcessor(*inputPlug,m_transmitProcessor, 
    999996            FreebobStreaming::AmdtpAudioPort::E_Playback)) { 
     
    11101107} 
    11111108 
     1109// FIXME: error checking 
    11121110int 
    11131111AvDevice::startStreamByIndex(int i) { 
     
    11711169            break; 
    11721170        default: 
    1173             return 0
     1171            return -1
    11741172        } 
    11751173//     } 
    11761174 
     1175    if (iso_channel < 0) return -1; 
     1176     
    11771177    return 0; 
    11781178 
    11791179} 
    11801180 
     1181// FIXME: error checking 
    11811182int 
    11821183AvDevice::stopStreamByIndex(int i) { 
  • branches/streaming-rework/src/debugmodule/debugmodule.cpp

    r383 r384  
    213213DebugModuleManager::registerModule( DebugModule& debugModule ) 
    214214{ 
     215    bool already_present=false; 
     216     
     217    for ( DebugModuleVectorIterator it = m_debugModules.begin(); 
     218          it != m_debugModules.end(); 
     219          ++it ) 
     220    { 
     221        if ( *it == &debugModule ) { 
     222            already_present=true; 
     223            return true; 
     224        } 
     225    } 
     226     
     227    if (already_present) { 
     228        cerr << "DebugModuleManager::registerModule: Module already registered: " 
     229            << "DebugModule (" << debugModule.getName() << ")" << endl; 
     230    } else { 
    215231        m_debugModules.push_back( &debugModule ); 
     232    } 
    216233    return true; 
    217234} 
     
    220237DebugModuleManager::unregisterModule( DebugModule& debugModule ) 
    221238{ 
     239     
    222240    for ( DebugModuleVectorIterator it = m_debugModules.begin(); 
    223241          it != m_debugModules.end(); 
  • branches/streaming-rework/src/debugmodule/debugmodule.h

    r341 r384  
    136136#define CHECK_PREEMPTION(onoff) 
    137137#endif 
    138  
    139 // Intel recommends that a serializing instruction  
    140 // should be called before and after rdtsc.  
    141 // CPUID is a serializing instruction.  
    142 #define read_rdtsc(time) \ 
    143         __asm__ __volatile__( \ 
    144         "pushl %%ebx\n\t" \ 
    145         "cpuid\n\t" \ 
    146         "rdtsc\n\t" \ 
    147         "mov %%eax,(%0)\n\t" \ 
    148         "cpuid\n\t" \ 
    149         "popl %%ebx\n\t" \ 
    150         : /* no output */ \ 
    151         : "S"(&time) \ 
    152         : "eax", "ecx", "edx", "memory") 
    153  
    154 static inline unsigned long debugGetCurrentTSC() { 
    155     unsigned retval; 
    156     read_rdtsc(retval); 
    157     return retval; 
    158 } 
    159138 
    160139unsigned char toAscii( unsigned char c ); 
  • branches/streaming-rework/src/devicemanager.cpp

    r368 r384  
    153153    } 
    154154 
     155#ifdef ENABLE_MOTU 
    155156    if ( MAudio::AvDevice::probe( *configRom.get() ) ) { 
    156157        return new MAudio::AvDevice( configRom, *m_1394Service, id, level ); 
    157158    } 
    158159 
     160 
    159161    if ( Motu::MotuDevice::probe( *configRom.get() ) ) { 
    160162        return new Motu::MotuDevice( configRom, *m_1394Service, id, level ); 
     
    168170        return new Bounce::BounceDevice( configRom, *m_1394Service, id, level ); 
    169171    } 
     172#endif 
    170173 
    171174    return 0; 
  • branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.cpp

    r383 r384  
    3131#include "AmdtpPort.h" 
    3232 
    33 #include "cyclecounter.h" 
     33#include "cycletimer.h" 
    3434 
    3535#include <netinet/in.h> 
    3636#include <assert.h> 
    3737 
    38 #define RECEIVE_PROCESSING_DELAY_IN_SAMPLES 100 
    3938#define RECEIVE_DLL_INTEGRATION_COEFFICIENT 0.015 
    4039 
    41 #define RECEIVE_PROCESSING_DELAY (TICKS_PER_SECOND * 2/1000) 
     40#define RECEIVE_PROCESSING_DELAY 51200 
    4241 
    4342// in ticks 
    44 #define TRANSMIT_TRANSFER_DELAY 10000 
     43#define TRANSMIT_TRANSFER_DELAY 1000 
     44#define TRANSMIT_ADVANCE_CYCLES 10 
    4545 
    4646//#define DO_SYT_SYNC 
     
    8080        } 
    8181         
    82  
    8382        return true; 
    8483} 
     
    9796    unsigned int nevents=0; 
    9897     
    99     packet->eoh0 = 0
     98    debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Xmit handler for cycle %d\n",cycle)
    10099     
    101100#ifdef DEBUG 
     
    121120    m_running=true; 
    122121     
    123     // don't process the stream when it is not enabled. 
    124     // however, we do have to generate (semi) valid packets 
    125     // that means that we'll send NODATA packets FIXME: check!! 
    126     if(m_disabled) { 
     122    // we calculate the timestamp of the next sample in the buffer, which will  
     123    // allow us to check if we are to send this sample now, or later 
     124     
     125    // FIXME: maybe we should use the buffer head timestamp for this? 
     126     
     127    float ticks_per_frame=m_SyncSource->getTicksPerFrame(); 
     128     
     129    // the base timestamp is the one of the last sample in the buffer 
     130    int64_t timestamp = m_buffer_tail_timestamp; 
     131     
     132     
     133    // meaning that the first sample in the buffer lies m_framecounter * rate 
     134    // earlier. This would give the next equation: 
     135    //   timestamp = m_last_timestamp - m_framecounter * rate 
     136    // but to preserve causality, we have to make sure that this timestamp is  
     137    // always bigger than m_last_timestamp. this can be done by adding 
     138    // m_ringbuffersize_frames * rate. 
     139    timestamp += (int64_t)((((int64_t)m_ringbuffer_size_frames)  
     140                                   - ((int64_t)m_framecounter))  
     141                          * ticks_per_frame); 
     142     
     143    // this happens if m_buffer_tail_timestamp wraps around while there are  
     144    // not much frames in the buffer. We should add the wraparound value of the ticks 
     145    // counter 
     146    if (timestamp < 0) { 
     147        timestamp += TICKS_PER_SECOND * 128L; 
     148    } 
     149    // this happens when the last timestamp is near wrapping, and  
     150    // m_framecounter is low. 
     151    // this means: m_last_timestamp is near wrapping and have just had 
     152    // a getPackets() from the client side. the projected next_period 
     153    // boundary lies beyond the wrap value. 
     154    // the action is to wrap the value. 
     155    else if (timestamp >= TICKS_PER_SECOND * 128L) { 
     156        timestamp -= TICKS_PER_SECOND * 128L; 
     157    } 
     158     
     159    // determine if we want to send a packet or not 
     160    uint64_t cycle_timer=m_handler->getCycleTimerTicks(); 
     161     
     162    int64_t until_next=timestamp-cycle_timer; 
     163     
     164    // we send a packet some cycles in advance, to avoid the 
     165    // following situation: 
     166    // suppose we are only a few ticks away from  
     167    // the moment to send this packet. This means that in 
     168    // order to keep causality, we have to make sure that 
     169    // the TRANSFER_DELAY is bigger than one cycle, which 
     170    // might be a little much. 
     171    // this means that we need one cycle of extra buffering. 
     172    until_next -= TICKS_PER_CYCLE * TRANSMIT_ADVANCE_CYCLES; 
     173     
     174    // the maximal difference we can allow (64secs) 
     175    const int64_t max=TICKS_PER_SECOND*64L; 
     176     
     177    if(!m_disabled) { 
     178        debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TS=%11llu, CTR=%11llu, FC=%5d, TPS=%10.6f, UTN=%11lld\n", 
     179            timestamp, cycle_timer, m_framecounter, ticks_per_frame, until_next 
     180            ); 
     181    } 
     182 
     183    if(until_next > max) { 
     184        // this means that cycle_timer has wrapped, but 
     185        // timestamp has not. we should unwrap cycle_timer 
     186        // by adding TICKS_PER_SECOND*128L, meaning that we should substract 
     187        // this value from until_next             
     188        until_next -= TICKS_PER_SECOND*128L; 
     189    } else if (until_next < -max) { 
     190        // this means that timestamp has wrapped, but 
     191        // cycle_timer has not. we should unwrap timestamp 
     192        // by adding TICKS_PER_SECOND*128L, meaning that we should add 
     193        // this value from until_next 
     194        until_next += TICKS_PER_SECOND*128L; 
     195    } 
     196     
     197    if(!m_disabled) { 
     198        debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "   TS=%11llu, CTR=%11llu, FC=%5d, TPS=%10.6f, UTN=%11lld\n", 
     199            timestamp, cycle_timer, m_framecounter, ticks_per_frame, until_next 
     200            ); 
     201    } 
     202     
     203    // don't process the stream when it is not enabled, 
     204    // or when the next sample is not due yet. 
     205     
     206    // we do have to generate (semi) valid packets 
     207    // that means that we'll send NODATA packets. 
     208    // we don't add payload because DICE devices don't like that. 
     209    if((until_next>0) || m_disabled) { 
    127210        // no-data packets have syt=0xFFFF 
    128         // and have the usual amount of events as dummy data  
     211        // and have the usual amount of events as dummy data (?) 
    129212        packet->fdf = IEC61883_FDF_NODATA; 
    130213        packet->syt = 0xffff; 
     
    133216        m_dbc += m_syt_interval; 
    134217 
     218        // this means no-data packets with payload (DICE doesn't like that) 
    135219        *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 
     220         
     221        // this means no-data packets without payload 
     222        //*length = 2*sizeof(quadlet_t); 
     223         
    136224        *tag = IEC61883_TAG_WITH_CIP; 
    137225        *sy = 0; 
     
    140228    } 
    141229     
    142     packet->fdf = m_fdf; 
    143          
    144 //     assert(m_handler->getDroppedCount()<5); 
    145          
    146 //     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 
    147          
    148         // construct the packet cip 
    149         // NOTE: maybe a little outdated 
    150         // FIXME: this should be done differently: 
    151         // first we should determine the timestamp of the first sample in this block 
    152         // this can be done by reading the rate of the compagnion receiver 
    153         // this rate will give us the ticks per sample used by the device 
    154         // then we should take the previous timestamp, and add m_syt_interval * ticks_per_sample 
    155         // to this timestamp (only if we are sending events). This gives us the timestamp 
    156         // of the first sample in this packet. 
    157         // we should define a transfer delay and add it to this timestamp and then send it to 
    158         // the device. 
    159          
    160         // NOTE: this will even work when we're only transmitting (no receive stream): 
    161         //       the ticks_per_sample value is initialized by the receive streamprocessor 
    162         //       to the nominal value. We will then transmit at our own pace, being at nominal 
    163         //       rate compared to the cycle counter. 
    164  
    165     // NOTE: this scheme might even work when sync'ing on the sync streams of the device 
    166     //       they are AMDTP streams with SYT timestamps, therefore a decent estimate of 
    167     //       ticks_per_frame can be found, and we are synced when using it. 
    168          
    169 //      <<compile error here>> 
    170          
    171     // FIXME: if m_last_bufferfill > 0 
    172     float ticks_per_frame=syncmaster->getTicksPerFrame(); 
    173  
    174     // m_last_timestamp is the moment upon which the last 'period signal'   
    175     // should have been given (note: should have been because 
    176     // the timestamp is derrived from the incoming packets, 
    177     // not from the moment the signal was actually given) 
    178      
    179     // at a period boundary, we expect m_ringbuffer_size_frames frames to 
    180     // be in the buffers. 'right after' the transfer(), all of these  
    181     // frames should be in the xmit buffers (if transfer() finishes  
    182     // before new packets are received) 
    183     // therefore the last sample of the xmit buffer lies at  
    184     // T1 = timestamp + (m_ringbuffer_size_frames) * ticks_per_frame 
    185      
    186     // in reality however life is multithreaded, and we don't know 
    187     // exactly how many samples there are in the buffer. but we know 
    188     // how many there should be, so we say that the last frame put  
    189     // into the buffer (by transfer) has the timestamp T1 
    190      
    191     // this means that the current sample has timestamp 
    192     // T2 = T1 - ticks_per_frame * (nb_frames_in_buffer) 
    193     //    = T1 - ticks_per_frame * (m_ringbuffer_size_frames-m_framecounter) 
    194     //    = timestamp + ticks_per_frame *  
    195     //      (m_ringbuffer_size_frames-m_ringbuffer_size_frames+m_framecounter) 
    196     //    = timestamp + ticks_per_frame * m_framecounter 
    197      
    198     int T2 = m_last_timestamp + ticks_per_frame*m_framecounter; 
    199      
    200     // we then need to add the transfer delay for the receiving 
    201     // device to this time to determine the xmit timestamp 
    202     // TSTAMP = T2 + TRANSFER_DELAY 
    203      
    204     // we should determine when to 'queue' this sample to 
    205     // the ISO xmit layer, based upon the cycle parameter 
    206     // we can define the ideal time at which to send the sample as 
    207     // TSEND = TSTAMP - TRANSFER_DELAY 
    208     // being T2 
    209     int TSEND = T2; 
    210      
    211     // the xmit timestamp should then be the TSEND + TRANSMIT_TRANSFER_DELAY 
    212     // note that in this setup, TRANSMIT_TRANSFER_DELAY has to incorporate the  
    213     // iso buffering 
    214     int timestamp = TSEND + TRANSMIT_TRANSFER_DELAY; 
    215      
    216     // if we take a look at TSEND we can determine if we are to send 
    217     // the sample or not: 
    218     // if  
    219     // CYCLES(TSEND) < cycle 
    220     // then the time at which to send the packet has passed (note: wraparound!) 
    221     // we should send the sample 
    222     // if it hasn't passed, we should send an empty packet 
    223     // 
    224     // this should automatically catch up 
    225      
    226     // FIXME: wraparound! 
    227     int cycle_wo_wraparound=cycle; 
    228      
    229     int TSEND_cycle_wo_wraparound = TICKS_TO_CYCLES(TSEND); 
    230      
    231     // arbitrary, should be replaced by a better wraparound 
    232     // detection 
    233      
    234     // if cycles wraps around, and TSEND_cyles doesn't,  
    235     // we need to make sure that we compare the right things 
    236     // i.e. unwrap the cycle parameter 
    237     // if both wrap, this can't be true 
    238     if (cycle_wo_wraparound - TSEND_cycle_wo_wraparound < -4000) { 
    239         cycle_wo_wraparound += 8000; 
    240          
    241          debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"wraparound on cycle detected: %d %d %d\n", 
    242             cycle, cycle_wo_wraparound,  
    243             cycle - TSEND_cycle_wo_wraparound); 
    244     } 
    245      
    246     // if TSEND_cycle wraps around and cycle doesn't, 
    247     // TSEND_cycle suddenly becomes a lot smaller than cycle 
    248     if (TSEND_cycle_wo_wraparound - cycle_wo_wraparound < -4000) { 
    249         TSEND_cycle_wo_wraparound += 8000; 
    250          
    251          debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"wraparound on TSEND detected: %d %d %d\n", 
    252             TICKS_TO_CYCLES(TSEND), TSEND_cycle_wo_wraparound,  
    253             TSEND_cycle_wo_wraparound - cycle_wo_wraparound); 
    254     } 
    255    
    256     if (TSEND_cycle_wo_wraparound < cycle_wo_wraparound) { 
    257         nevents=m_syt_interval; 
    258         m_dbc += m_syt_interval; 
    259  
    260     } else { // no-data 
    261    
    262            // no-data packets have syt=0xFFFF 
    263            // and have the usual amount of events as dummy data  
     230    // construct the packet 
     231    nevents = m_syt_interval; 
     232    m_dbc += m_syt_interval; 
     233     
     234    *tag = IEC61883_TAG_WITH_CIP; 
     235    *sy = 0; 
     236      
     237    enum raw1394_iso_disposition retval; 
     238 
     239    unsigned int read_size=nevents*sizeof(quadlet_t)*m_dimension; 
     240 
     241    if ((freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size)) <  
     242                            read_size)  
     243    { 
     244        /* there is no more data in the ringbuffer */ 
     245 
     246        debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",  
     247                 cycle, m_framecounter, m_handler->getPacketCount()); 
     248 
     249        // TODO: we have to be a little smarter here 
     250        //       because we have some slack on the device side (TRANSFER_DELAY) 
     251        //       we can allow some skipped packets 
     252        // signal underrun 
     253        m_xruns++; 
     254 
     255        // compose a no-data packet, we should always 
     256        // send a valid packet 
    264257        packet->fdf = IEC61883_FDF_NODATA; 
    265258        packet->syt = 0xffff; 
    266259         
    267         // the dbc is incremented even with no data packets 
    268         m_dbc += m_syt_interval; 
    269          
    270                 *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 
    271                 *tag = IEC61883_TAG_WITH_CIP; 
    272                 *sy = 0; 
    273  
    274 //         if(packet->dbs) { 
    275 //             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
    276 //                 "XMT %04d: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",  
    277 //                 cycle, m_channel, packet->fdf, 
    278 //                 packet->syt, 
    279 //                 packet->dbs, 
    280 //                 packet->dbc, 
    281 //                 packet->fmt,  
    282 //                 *length, 
    283 //                 ((*length / sizeof (quadlet_t)) - 2)/packet->dbs); 
    284 //         } 
    285          
    286                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Sending empty packet on cycle %d\n", cycle); 
    287          
    288         // FIXME: this is to prevent libraw to do loop over too 
    289         //        much packets at once (overflowing the receive side) 
    290         //        but putting it here is a little arbitrary 
    291          
    292      
    293                 return RAW1394_ISO_DEFER; 
    294     } 
    295      
    296  
    297 //     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Now=%4d/%8d, Tstamp=%8d, DT=%8d, T2=%8d, T3=%8d, last TS=%d, BF=%d\n", 
    298 //         cycle,(cycle*3072), 
    299 //         timestamp, 
    300 //         timestamp-(cycle*3072), 
    301 //         T2,T3, 
    302 //         m_last_timestamp, 
    303 //         buffer_fill); 
    304      
    305         enum raw1394_iso_disposition retval = RAW1394_ISO_OK; 
    306  
    307         unsigned int read_size=nevents*sizeof(quadlet_t)*m_dimension; 
    308  
    309         if ((freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size)) <  
    310                                 read_size)  
    311         { 
    312         /* there is no more data in the ringbuffer */ 
    313          
    314         debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",  
    315                  cycle, m_framecounter, m_handler->getPacketCount()); 
    316          
    317         // signal underrun 
    318         m_xruns++; 
     260        // this means no-data packets with payload (DICE doesn't like that) 
     261        *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 
     262 
     263        // this means no-data packets without payload 
     264        //*length = 2*sizeof(quadlet_t); 
    319265 
    320266        retval=RAW1394_ISO_DEFER; 
    321         *length=0; 
    322         nevents=0; 
    323  
    324  
    325267    } else { 
    326         retval=RAW1394_ISO_OK; 
    327268        *length = read_size + 8; 
    328          
     269 
    329270        // process all ports that should be handled on a per-packet base 
    330271        // this is MIDI for AMDTP (due to the need of DBC) 
     
    332273            debugWarning("Problem encoding Packet Ports\n"); 
    333274        } 
    334          
    335         // we can forget the seconds for the cycle counter 
    336         // because we are masking with 0xFFFF 
    337          
    338         unsigned int timestamp_SYT = (TICKS_TO_CYCLES(timestamp) << 12)  
    339                                      | TICKS_TO_OFFSET(timestamp); 
    340          
    341         packet->syt = ntohs(timestamp_SYT & 0xffff); 
    342          
    343 //         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"XMIT %d EVENTS, SYT %04X for cycle %2d: %08d (%2u cycles + %04u ticks)\n", 
    344 //           nevents, timestamp_SYT & 0xFFFF, cycle, timestamp_SYT 
    345 //           CYCLE_COUNTER_GET_CYCLES(timestamp_SYT), 
    346 //           CYCLE_COUNTER_GET_OFFSET(timestamp_SYT) 
    347 //           ); 
    348     } 
    349      
    350     *tag = IEC61883_TAG_WITH_CIP; 
    351     *sy = 0; 
    352      
    353     // update the frame counter 
    354     incrementFrameCounter(nevents); 
    355      
    356 /*    if(m_framecounter>m_period) { 
    357        retval=RAW1394_ISO_DEFER; 
    358     }*/ 
    359      
    360 #ifdef DEBUG 
    361 //     if(packet->dbs) { 
    362 //         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
    363 //             "XMT %04d: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",  
    364 //             cycle, m_channel, packet->fdf, 
    365 //             packet->syt, 
    366 //             packet->dbs, 
    367 //             packet->dbc, 
    368 //             packet->fmt,  
    369 //             *length, 
    370 //             ((*length / sizeof (quadlet_t)) - 2)/packet->dbs); 
    371 //     } 
    372 #endif 
     275 
     276        packet->fdf = m_fdf; 
     277 
     278        // convert the timestamp to SYT format 
     279        unsigned int timestamp_SYT = TICKS_TO_SYT(timestamp); 
     280        packet->syt = ntohs(timestamp_SYT); 
     281 
     282        retval=RAW1394_ISO_OK; 
     283    } 
     284     
     285    // calculate the new buffer head timestamp. this is 
     286    // the timestamp of the current packet plus 
     287    // SYT_INTERVAL * rate 
     288      
     289    timestamp += (int64_t)((float)m_syt_interval * ticks_per_frame ); 
     290     
     291    // check if it wrapped 
     292    if (timestamp >= TICKS_PER_SECOND * 128L) { 
     293        timestamp -= TICKS_PER_SECOND * 128L; 
     294    } 
     295     
     296    // update the frame counter such that it reflects the new value 
     297    // also update the buffer head timestamp 
     298    // done in the SP base class 
     299    if (!StreamProcessor::getFrames(nevents, timestamp)) { 
     300        debugError("Could not do StreamProcessor::getFrames(%d, %llu)\n",nevents, timestamp); 
     301        retval=RAW1394_ISO_ERROR; 
     302    } 
    373303 
    374304    return retval; 
     
    376306} 
    377307 
    378 void AmdtpTransmitStreamProcessor::decrementFrameCounter() { 
    379     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "decrement frame counter...\n"); 
    380  
    381 #ifdef DEBUG 
    382     int xmit_bufferspace=freebob_ringbuffer_read_space(m_event_buffer)/m_dimension/4; 
    383     int recv_bufferspace=freebob_ringbuffer_read_space(syncmaster->m_event_buffer)/syncmaster->m_dimension/4; 
    384      
    385     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"XMT: %5d | RCV: %5d | DIFF: %5d | SUM: %5d \n", xmit_bufferspace, recv_bufferspace, xmit_bufferspace - recv_bufferspace, xmit_bufferspace + recv_bufferspace); 
    386 #endif 
    387  
    388     // update the timestamp 
    389      
    390     m_last_timestamp=syncmaster->getPeriodTimeStamp(); 
    391      
    392     StreamProcessor::decrementFrameCounter(); 
    393 
    394  
    395 void AmdtpTransmitStreamProcessor::incrementFrameCounter(int nbframes) { 
    396     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "increment frame counter by %d...\n", nbframes); 
    397      
    398     StreamProcessor::incrementFrameCounter(nbframes); 
    399 
    400  
    401 bool AmdtpTransmitStreamProcessor::isOnePeriodReady() 
    402 {  
    403     return true; 
    404     //return (m_framecounter > m_period);  
     308int64_t AmdtpTransmitStreamProcessor::getTimeUntilNextPeriodUsecs() { 
     309    debugFatal("IMPLEMENT ME!"); 
     310    return 0; 
     311
     312 
     313uint64_t AmdtpTransmitStreamProcessor::getTimeAtPeriodUsecs() { 
     314    // then we should convert this into usecs 
     315    // FIXME: we assume that the TimeSource of the IsoHandler is 
     316    //        in usecs. 
     317    return m_handler->mapToTimeSource(getTimeAtPeriod()); 
     318
     319 
     320uint64_t AmdtpTransmitStreamProcessor::getTimeAtPeriod() { 
     321    debugFatal("IMPLEMENT ME!"); 
     322     
     323    return 0; 
    405324} 
    406325 
    407326bool AmdtpTransmitStreamProcessor::prefill() { 
    408  
    409327    if(!transferSilence(m_ringbuffer_size_frames)) { 
    410328        debugFatal("Could not prefill transmit stream\n"); 
     
    412330    } 
    413331 
    414 /*    int i=m_nb_buffers; 
    415     while(i--) { 
    416         if(!transferSilence(m_period)) { 
    417             debugFatal("Could not prefill transmit stream\n"); 
    418             return false; 
    419         } 
    420     } 
    421      
    422     // and we should also provide enough prefill for the 
    423     // SYT processing delay 
    424     if(!transferSilence(RECEIVE_PROCESSING_DELAY_IN_SAMPLES)) { 
    425         debugFatal("Could not prefill transmit stream (2)\n"); 
     332    // when the buffer is prefilled, we should 
     333    // also initialize the base timestamp 
     334    // this base timestamp is the timestamp of the 
     335    // last buffer transfer. 
     336    uint64_t ts; 
     337    uint64_t fc; 
     338    m_SyncSource->getBufferHeadTimestamp(&ts, &fc); 
     339 
     340    // update the frame counter such that it reflects the buffer content, 
     341    // and also update the buffer tail timestamp 
     342    // done in the SP base class 
     343    if (!StreamProcessor::putFrames(m_ringbuffer_size_frames, ts)) { 
     344        debugError("Could not do StreamProcessor::putFrames(%d, %llu)\n", 
     345            m_ringbuffer_size_frames, ts); 
    426346        return false; 
    427347    } 
    428 */     
    429     // the framecounter should be pulled back to 
    430     // make sure the ISO buffering is used  
    431     // we are using 1 period of iso buffering 
    432 //     m_framecounter=-m_period; 
    433      
    434     // should this also be pre-buffered? 
    435     //m_framecounter=-(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND; 
    436      
     348 
    437349    return true; 
    438350     
     
    524436    m_ringbuffer_size_frames=m_nb_buffers * m_period; 
    525437     
    526     // add the processing delay 
    527     m_ringbuffer_size_frames+=RECEIVE_PROCESSING_DELAY_IN_SAMPLES; 
     438    // prepare the framerate estimate 
     439    m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); 
     440     
     441    // add the receive processing delay 
     442    m_ringbuffer_size_frames+=(uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame); 
    528443     
    529444    if( !(m_event_buffer=freebob_ringbuffer_create( 
    530445            (m_dimension * m_ringbuffer_size_frames) * sizeof(quadlet_t)))) { 
    531446        debugFatal("Could not allocate memory event ringbuffer"); 
    532 //              return -ENOMEM; 
    533447        return false; 
    534448    } 
     
    539453        freebob_ringbuffer_free(m_event_buffer); 
    540454        return false; 
    541 //              return -ENOMEM; 
    542455    } 
    543456 
     
    633546        return false; 
    634547    } 
    635  
    636     // we should prefill the event buffer 
     548     
     549    // prefilling is done in ...() 
     550    // because at that point the streams are running,  
     551    // while here they are not. 
     552     
     553    // prefill the event buffer 
    637554    if (!prefill()) { 
    638555        debugFatal("Could not prefill buffers\n"); 
     
    652569} 
    653570 
     571bool AmdtpTransmitStreamProcessor::prepareForStart() { 
     572 
     573    return true; 
     574} 
     575 
     576bool AmdtpTransmitStreamProcessor::prepareForStop() { 
     577    disable(); 
     578    return true; 
     579} 
     580 
     581bool AmdtpTransmitStreamProcessor::prepareForEnable() { 
     582    uint64_t ts; 
     583    uint64_t fc; 
     584     
     585    m_SyncSource->getBufferHeadTimestamp(&ts, &fc); 
     586 
     587    setBufferTailTimestamp(ts); 
     588     
     589    return true; 
     590} 
     591 
    654592bool AmdtpTransmitStreamProcessor::transferSilence(unsigned int size) { 
    655593    /* a naive implementation would look like this: */ 
     
    668606} 
    669607 
    670 bool AmdtpTransmitStreamProcessor::transfer() { 
     608bool AmdtpTransmitStreamProcessor::canClientTransferFrames(unsigned int nbframes) { 
     609    // there has to be enough space to put the frames in 
     610    return m_ringbuffer_size_frames - getFrameCounter() > nbframes; 
     611
     612 
     613bool AmdtpTransmitStreamProcessor::putFrames(unsigned int nbframes, int64_t ts) { 
    671614    m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    672615 
    673616    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    674     // TODO: improve 
    675 /* a naive implementation would look like this: 
    676  
    677     unsigned int write_size=m_period*sizeof(quadlet_t)*m_dimension; 
    678     char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension); 
    679     transmitBlock(dummybuffer, m_period, 0, 0); 
    680  
    681     if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
    682         debugWarning("Could not write to event buffer\n"); 
    683     } 
    684  
    685  
    686     free(dummybuffer); 
    687 */ 
    688 /* but we're not that naive anymore... */ 
    689617    int xrun; 
    690618    unsigned int offset=0; 
     
    693621    // we received one period of frames 
    694622    // this is period_size*dimension of events 
    695     int events2write=m_period*m_dimension; 
     623    int events2write=nbframes*m_dimension; 
    696624    int bytes2write=events2write*sizeof(quadlet_t); 
    697625 
     
    709637        int byteswritten=0; 
    710638         
    711         unsigned int frameswritten=(m_period*cluster_size-bytes2write)/cluster_size; 
     639        unsigned int frameswritten=(nbframes*cluster_size-bytes2write)/cluster_size; 
    712640        offset=frameswritten; 
    713641         
     
    761689                    // xrun detected 
    762690                debugError("XMT: Frame buffer underrun in processor %p\n",this); 
    763                 break; 
     691                break; // FIXME: return false ? 
    764692            } 
    765693 
     
    771699        assert(bytes2write%cluster_size==0); 
    772700 
     701    } 
     702 
     703    // update the frame counter such that it reflects the new value, 
     704    // and also update the buffer tail timestamp 
     705    // done in the SP base class 
     706    debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor::putFrames(%d, %llu)\n",nbframes, ts); 
     707     
     708    if (!StreamProcessor::putFrames(nbframes, ts)) { 
     709        debugError("Could not do StreamProcessor::putFrames(%d, %llu)\n",nbframes, ts); 
     710        return false; 
    773711    } 
    774712 
     
    859797     
    860798    quadlet_t *target_event=NULL; 
    861     int j; 
     799    unsigned int j; 
    862800     
    863801    for ( PortVectorIterator it = m_PacketPorts.begin(); 
     
    989927 
    990928AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int framerate, int dimension) 
    991     : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0), m_one_period_passed(false)
     929    : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0)
    992930 
    993931 
     
    1021959    struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    1022960    assert(packet); 
    1023         unsigned long in_time=debugGetCurrentTSC(); 
    1024961 
    1025962#ifdef DEBUG 
     
    1029966#endif 
    1030967     
    1031     // how are we going to get this right??? 
    1032 //     m_running=true; 
    1033      
    1034968    if((packet->fmt == 0x10) && (packet->fdf != 0xFF) && (packet->syt != 0xFFFF) && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) { 
    1035969        unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs; 
    1036970         
    1037         // signal that we're running 
    1038                 if(nevents) m_running=true; 
    1039                  
    1040                  
    1041         // do the time stamp processing 
    1042         // put the last time stamp a variable 
    1043         // this will allow us to determine the  
    1044         // actual presentation time later 
    1045         bool wraparound_occurred=false; 
    1046          
     971        //=> store the previous timestamp 
    1047972        m_last_timestamp2=m_last_timestamp; 
    1048973         
     974        //=> convert the SYT to ticks 
    1049975        unsigned int syt_timestamp=ntohs(packet->syt); 
     976         
     977        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"ch%2u: CY=%4u, SYT=%08X (%3u secs + %4u cycles + %04u ticks)\n", 
     978            channel, cycle,syt_timestamp, CYCLE_TIMER_GET_SECS(syt_timestamp),  
     979            CYCLE_TIMER_GET_CYCLES(syt_timestamp), CYCLE_TIMER_GET_OFFSET(syt_timestamp)); 
     980         
     981        // reconstruct the full cycle 
     982        unsigned int cc=m_handler->getCycleTimer(); 
     983        unsigned int cc_cycles=CYCLE_TIMER_GET_CYCLES(cc); 
     984        unsigned int cc_seconds=CYCLE_TIMER_GET_SECS(cc); 
     985         
     986        // the cycletimer has wrapped since this packet was received 
     987        // we want cc_seconds to reflect the 'seconds' at the point this  
     988        // was received 
     989        if (cycle>cc_cycles) { 
     990            if (cc_seconds) { 
     991                cc_seconds--; 
     992            } else { 
     993                // seconds has wrapped around, so we'd better not substract 1 
     994                // the good value is 127 
     995                cc_seconds=127; 
     996            } 
     997        } 
     998         
    1050999        // reconstruct the top part of the timestamp using the current cycle number 
    10511000        unsigned int now_cycle_masked=cycle & 0xF; 
    1052         unsigned int syt_cycle=CYCLE_COUNTER_GET_CYCLES(syt_timestamp); 
     1001        unsigned int syt_cycle=CYCLE_TIMER_GET_CYCLES(syt_timestamp); 
    10531002         
    10541003        // if this is true, wraparound has occurred, undo this wraparound 
    10551004        if(syt_cycle<now_cycle_masked) syt_cycle += 0x10; 
    10561005         
     1006        // this is the difference in cycles wrt the cycle the 
     1007        // timestamp was received 
    10571008        unsigned int delta_cycles=syt_cycle-now_cycle_masked; 
    10581009         
     
    10601011        unsigned int new_cycles=cycle + delta_cycles; 
    10611012         
    1062         if(new_cycles>7999) { 
    1063             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Detected wraparound: %d + %d = %d\n",cycle,delta_cycles,new_cycles); 
     1013        // if the cycles cause a wraparound of the cycle timer, 
     1014        // perform this wraparound 
     1015        // and convert the timestamp into ticks 
     1016        if(new_cycles<8000) { 
     1017            m_last_timestamp  = new_cycles * TICKS_PER_CYCLE; 
     1018        } else { 
     1019            debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 
     1020                "Detected wraparound: %d + %d = %d\n", 
     1021                cycle,delta_cycles,new_cycles); 
    10641022             
    10651023            new_cycles-=8000; // wrap around 
    1066             wraparound_occurred=true; 
     1024            m_last_timestamp  = new_cycles * TICKS_PER_CYCLE; 
     1025            // add one second due to wraparound 
     1026            m_last_timestamp += TICKS_PER_SECOND; 
    10671027        } 
    10681028         
    1069         m_last_timestamp = (new_cycles) << 12; 
    1070          
    1071         // now add the offset part on top of that 
    1072         m_last_timestamp |= (syt_timestamp & 0xFFF); 
    1073          
    1074         // mask off the seconds field 
    1075          
    1076         // m_last_timestamp timestamp now contains all info, 
    1077         // including cycle number 
    1078          
    1079         if (m_last_timestamp && m_last_timestamp2) { 
    1080             // try and estimate the frame rate from the device: 
    1081             int measured_difference=((int)(CYCLE_COUNTER_TO_TICKS(m_last_timestamp))) 
    1082                                      -((int)(CYCLE_COUNTER_TO_TICKS(m_last_timestamp2))); 
     1029        m_last_timestamp += CYCLE_TIMER_GET_OFFSET(syt_timestamp); 
     1030        m_last_timestamp += cc_seconds * TICKS_PER_SECOND; 
     1031 
     1032        //=> now estimate the device frame rate 
     1033        if (m_last_timestamp2 && m_last_timestamp) { 
     1034            // try and estimate the frame rate from the device 
    10831035             
    1084             // handle wrap around of the cycle variable if nescessary 
    1085             // it can be that two successive timestamps cause wraparound  
    1086             // (if the difference between time stamps is larger than 2 cycles),  
    1087             // thus it isn't always nescessary 
    1088             if (wraparound_occurred & (m_last_timestamp<m_last_timestamp2)) { 
    1089                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE," => correcting for timestamp difference wraparound\n"); 
    1090                 measured_difference+=TICKS_PER_SECOND; 
     1036            // first get the measured difference between both  
     1037            // timestamps 
     1038            int64_t measured_difference; 
     1039            measured_difference=((int64_t)(m_last_timestamp)) 
     1040                               -((int64_t)(m_last_timestamp2)); 
     1041            // correct for seconds wraparound 
     1042            if (m_last_timestamp<m_last_timestamp2) { 
     1043                measured_difference+=128L*TICKS_PER_SECOND; 
    10911044            } 
    10921045 
     
    10961049            float err = f / (1.0*m_syt_interval) - m_ticks_per_frame; 
    10971050             
    1098             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT: %08X | STMP: %08X | DLL: in=%5.0f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, f,m_ticks_per_frame,err); 
     1051            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT: %08X | STMP: %lluticks | DLL: in=%f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, f,m_ticks_per_frame,err); 
    10991052 
    11001053#ifdef DEBUG 
     1054            // this helps to detect wraparound issues 
    11011055            if(f > 1.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) { 
    11021056                debugWarning("Timestamp diff more than 50%% of the nominal diff too large!\n"); 
    1103                 debugWarning(" SYT: %08X | STMP: %08X,%08X | DLL: in=%5.0f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, m_last_timestamp2, f,m_ticks_per_frame,err); 
     1057                debugWarning(" SYT: %08X | STMP: %llu,%llu | DLL: in=%f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, m_last_timestamp2, f,m_ticks_per_frame,err); 
     1058                debugWarning(" CC: %08X | CC_CY: %u | CC_SEC: %u | SYT_CY: %u | NEW_CY: %u\n", 
     1059                    cc, cc_cycles, cc_seconds, syt_cycle,new_cycles); 
     1060                 
    11041061            } 
    11051062            if(f < 0.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) { 
    11061063                debugWarning("Timestamp diff more than 50%% of the nominal diff too small!\n"); 
    1107                 debugWarning(" SYT: %08X | STMP: %08X,%08X | DLL: in=%5.0f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, m_last_timestamp2, f,m_ticks_per_frame,err); 
     1064                debugWarning(" SYT: %08X | STMP: %llu,%llu | DLL: in=%f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, m_last_timestamp2, f,m_ticks_per_frame,err); 
    11081065            } 
    11091066#endif 
    1110  
    11111067            // integrate the error 
    11121068            m_ticks_per_frame += RECEIVE_DLL_INTEGRATION_COEFFICIENT*err; 
     
    11161072         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n", 
    11171073            cycle,now_cycle_masked,delta_cycles, 
    1118          CYCLE_COUNTER_TO_TICKS(m_last_timestamp), 
    1119          CYCLE_COUNTER_GET_CYCLES(m_last_timestamp), 
    1120          CYCLE_COUNTER_GET_OFFSET(m_last_timestamp), 
    1121          ntohs(packet->syt),m_last_timestamp&0xFFFF, dropped 
     1074            (m_last_timestamp), 
     1075            TICKS_TO_CYCLES(m_last_timestamp), 
     1076            TICKS_TO_OFFSET(m_last_timestamp), 
     1077            ntohs(packet->syt),TICKS_TO_CYCLE_TIMER(m_last_timestamp)&0xFFFF, dropped 
    11221078         ); 
    11231079 
    1124 #ifdef DEBUG 
    1125         if(m_last_timestamp<m_last_timestamp2) { 
    1126             if(wraparound_occurred) { 
    1127                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"timestamp not sequential for cycle %d, but it's wraparound. %08X %08X %08X\n",cycle,syt_timestamp, m_last_timestamp, m_last_timestamp2);                    
    1128             } else { 
    1129                 debugWarning("timestamp not sequential for cycle %d! %08X %08X %08X\n", cycle, syt_timestamp, m_last_timestamp, m_last_timestamp2); 
    1130                  
    1131                 // the DLL will recover from this. 
    1132 //                     ??? m_last_timestamp2=m_last_timestamp-(m_syt_interval*m_ticks_per_frame); 
    1133             } 
    1134         } 
    1135 #endif 
    1136  
    1137         // don't process the stream samples when it is not enabled. 
     1080        //=> signal that we're running (if we are) 
     1081        if(!m_running && nevents && m_last_timestamp2 && m_last_timestamp) m_running=true; 
     1082 
     1083        //=> don't process the stream samples when it is not enabled. 
    11381084        if(m_disabled) { 
     1085            // we keep track of the timestamp here 
     1086            // this makes sure that we will have a somewhat accurate 
     1087            // estimate as to when a period might be ready. i.e. it will not 
     1088            // be ready earlier than this timestamp + period time 
     1089             
     1090            // the next (possible) sample is not this one, but lies  
     1091            // SYT_INTERVAL * rate later 
     1092            uint64_t ts=m_last_timestamp+(uint64_t)((float)m_syt_interval * m_ticks_per_frame); 
     1093            StreamProcessor::setBufferTimestamps(ts,ts); 
     1094             
    11391095            return RAW1394_ISO_DEFER; 
    11401096        } 
    1141         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n"); 
    1142          
     1097         
     1098        //=> process the packet 
    11431099        unsigned int write_size=nevents*sizeof(quadlet_t)*m_dimension; 
     1100         
    11441101        // add the data payload to the ringbuffer 
    1145          
    11461102        if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size)  
    11471103        { 
    11481104            debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",  
    11491105                 cycle, m_framecounter, m_handler->getPacketCount()); 
     1106             
    11501107            m_xruns++; 
    11511108 
     
    11591116                retval=RAW1394_ISO_DEFER; 
    11601117            } 
    1161  
    11621118        } 
    11631119 
     
    11761132#endif 
    11771133 
    1178         // update the frame counter 
    1179         incrementFrameCounter(nevents); 
    1180         if(m_framecounter>(signed int)m_period) { 
    1181            retval=RAW1394_ISO_DEFER; 
    1182            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"defer!\n"); 
     1134        // update the frame counter such that it reflects the new value, 
     1135        // and also update the buffer tail timestamp, as we add new frames 
     1136        // done in the SP base class 
     1137        if (!StreamProcessor::putFrames(nevents, m_last_timestamp)) { 
     1138            debugError("Could not do StreamProcessor::putFrames(%d, %llu)\n",nevents, m_last_timestamp); 
     1139            return RAW1394_ISO_ERROR; 
    11831140        } 
    11841141 
    1185     } else { 
    1186         // discard packet 
    1187         // can be important for sync though 
    1188          
    1189         // FIXME: this is to prevent libraw to do loop over too 
    1190         //        much packets at once (draining the xmit side) 
    1191         //        but putting it here is a little arbitrary 
    1192         retval=RAW1394_ISO_DEFER; 
    1193     } 
    1194      
    1195     m_PacketStat.mark(debugGetCurrentTSC()-in_time); 
    1196      
    1197 //     m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
     1142    }  
    11981143     
    11991144    return retval; 
    12001145} 
    12011146 
    1202 // this uses SYT to determine if one period is ready 
    1203 bool AmdtpReceiveStreamProcessor::isOnePeriodReady() {  
    1204  
    1205 #ifdef DO_SYT_SYNC 
    1206  // this code is not ready yet 
    1207  
    1208     // one sample will take a number off cycle counter ticks: 
    1209     // The number of ticks per second is 24576000 
    1210     // The number of samples per second is Fs 
    1211     // therefore the number of ticks per sample is 24576000 / Fs 
    1212     // NOTE: this will be rounded!! 
    1213 //     float ticks_per_sample=24576000.0/m_framerate; 
    1214      float ticks_per_sample=m_ticks_per_frame; 
    1215  
    1216     // we are allowed to add some constant  
    1217     // processing delay to the transfer delay 
    1218     // being the period size and some fixed delay 
    1219 //     unsigned int processing_delay=ticks_per_sample*(m_period)+RECEIVE_PROCESSING_DELAY; 
    1220     unsigned int processing_delay=ticks_per_sample*(m_period+RECEIVE_PROCESSING_DELAY_IN_SAMPLES); 
    1221      
    1222     // the number of events in the buffer is 
    1223     // m_framecounter 
    1224  
    1225     // we have the timestamp of the last event block: 
    1226     // m_last_timestamp 
    1227      
    1228     // the time at which the beginning of the buffer should be 
    1229     // presented to the audio side is: 
    1230     // m_last_timestamp - (m_framecounter-m_syt_interval)*ticks_per_sample 
    1231      
    1232     // NOTE: in fact, we don't have to check this, because it should always be the case 
    1233     // 
    1234     // WAS: however we have to make sure that we can transfer at least one period 
    1235     // therefore we first check if this is ok 
    1236      
    1237 //      if(m_framecounter > (signed int)m_period) { 
    1238  
    1239         unsigned int m_last_timestamp_ticks = CYCLE_COUNTER_TO_TICKS(m_last_timestamp); 
    1240          
    1241         // add the processing delay 
    1242         int ideal_presentation_time = m_last_timestamp_ticks + processing_delay; 
    1243         int buffer_content_ticks=((int)m_framecounter)-((int)m_syt_interval); 
    1244         buffer_content_ticks *= ticks_per_sample; 
    1245          
    1246         // if the ideal_presentation_time is smaller than buffer_content_ticks, wraparound has occurred 
    1247         // for the cycle part of m_last_timestamp. Therefore add one second worth of ticks 
    1248         // to the cycle counter, as this is the wraparound point. 
    1249         if (ideal_presentation_time < buffer_content_ticks) ideal_presentation_time += 24576000; 
    1250         // we can now safely substract these, it will always be > 0 
    1251         ideal_presentation_time -= buffer_content_ticks; 
    1252          
    1253         // FIXME: if we are sure, make ideal_presentation_time an unsigned int 
    1254 //         assert(ideal_presentation_time>=0); 
    1255          
    1256         unsigned int current_time_ticks = (m_handler->getCycleCounter() % TICKS_PER_SECOND ); 
    1257  
    1258 #ifdef DEBUG 
    1259         if(ideal_presentation_time<0) { 
    1260             debugWarning("ideal_presentation_time time is negative!\n"); 
    1261             debugOutput(DEBUG_LEVEL_VERBOSE,"Periods: %d, FC: %d, remote framerate %f\n", 
    1262                 m_PeriodStat.m_count, m_framecounter, m_ticks_per_frame); 
    1263             debugOutput(DEBUG_LEVEL_VERBOSE,"p-delay: %u, buffer_content: %d\n", 
    1264                 processing_delay, buffer_content_ticks); 
    1265             debugOutput(DEBUG_LEVEL_VERBOSE,"Timestamp : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1266                 m_last_timestamp_ticks, 
    1267                 CYCLE_COUNTER_GET_SECS(m_last_timestamp),  
    1268                 CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),  
    1269                 CYCLE_COUNTER_GET_OFFSET(m_last_timestamp) 
    1270                 ); 
    1271             debugOutput(DEBUG_LEVEL_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1272                 ideal_presentation_time, 
    1273                 TICKS_TO_SECS(ideal_presentation_time),  
    1274                 TICKS_TO_CYCLES(ideal_presentation_time), 
    1275                 TICKS_TO_OFFSET(ideal_presentation_time) 
    1276                 ); 
    1277             debugOutput(DEBUG_LEVEL_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1278                 current_time_ticks,  
    1279                 TICKS_TO_SECS(current_time_ticks),  
    1280                 TICKS_TO_CYCLES(current_time_ticks),  
    1281                 TICKS_TO_OFFSET(current_time_ticks) 
    1282                 ); 
    1283             return false; 
    1284         } 
    1285         if(ideal_presentation_time<m_last_timestamp_ticks) { 
    1286             debugWarning("ideal_presentation_time earlier than last timestamp!\n"); 
    1287             debugOutput(DEBUG_LEVEL_VERBOSE,"Periods: %d, FC: %d, remote framerate %f\n", 
    1288                 m_PeriodStat.m_count, m_framecounter, m_ticks_per_frame); 
    1289             debugOutput(DEBUG_LEVEL_VERBOSE,"p-delay: %u, buffer_content: %u\n", 
    1290                 processing_delay, buffer_content_ticks); 
    1291             debugOutput(DEBUG_LEVEL_VERBOSE,"Timestamp : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1292                 m_last_timestamp_ticks, 
    1293                 CYCLE_COUNTER_GET_SECS(m_last_timestamp),  
    1294                 CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),  
    1295                 CYCLE_COUNTER_GET_OFFSET(m_last_timestamp) 
    1296                 ); 
    1297             debugOutput(DEBUG_LEVEL_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1298                 ideal_presentation_time, 
    1299                 TICKS_TO_SECS(ideal_presentation_time),  
    1300                 TICKS_TO_CYCLES(ideal_presentation_time), 
    1301                 TICKS_TO_OFFSET(ideal_presentation_time) 
    1302                 ); 
    1303             debugOutput(DEBUG_LEVEL_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1304                 current_time_ticks,  
    1305                 TICKS_TO_SECS(current_time_ticks),  
    1306                 TICKS_TO_CYCLES(current_time_ticks),  
    1307                 TICKS_TO_OFFSET(current_time_ticks) 
    1308                 ); 
    1309                          
    1310         } 
    1311 #endif 
    1312          
    1313         // if the last signalled period lies in the future, we know we had wraparound of the clock 
    1314         // so add one second 
    1315 //         if (current_time_ticks < m_previous_signal_ticks) current_time_ticks += 24576000; 
    1316         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Periods: %d, remote framerate %f\n",m_PeriodStat.m_count, m_ticks_per_frame); 
    1317         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Timestamp : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1318             m_last_timestamp_ticks, 
    1319             CYCLE_COUNTER_GET_SECS(m_last_timestamp),  
    1320             CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),  
    1321             CYCLE_COUNTER_GET_OFFSET(m_last_timestamp) 
    1322             ); 
    1323         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1324             ideal_presentation_time, 
    1325             ideal_presentation_time/24576000,  
    1326             (ideal_presentation_time/3072) % 8000, 
    1327             ideal_presentation_time%3072 
    1328             ); 
    1329         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    1330             current_time_ticks,  
    1331             TICKS_TO_SECS(current_time_ticks),  
    1332             TICKS_TO_CYCLES(current_time_ticks),  
    1333             TICKS_TO_OFFSET(current_time_ticks) 
    1334             ); 
    1335          
    1336         int tmp=ideal_presentation_time-current_time_ticks; 
    1337          
    1338         // if current_time_ticks wraps around while ahead of the presentation time, we have  
    1339         // a problem. 
    1340         // we know however that we have to wait for at max one buffer + some transmit delay 
    1341         // therefore we clip this value at 0.5 seconds 
    1342         if (tmp > 24576000/2) tmp-=24576000; 
    1343          
    1344         if(tmp<0) { 
    1345             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT passed (%d ticks too late)\n",-tmp); 
    1346             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Periods: %d, remote ticks/frame: %f, remote framerate = %f\n", 
    1347                 m_PeriodStat.m_count, m_ticks_per_frame, 24576000.0/m_ticks_per_frame); 
    1348             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Bufferfill %d, framecounter %d\n", 
    1349                 freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension),m_framecounter); 
    1350             if (-tmp>1000000) debugWarning("SYT VERY LATE: %d!\n",-tmp); 
    1351              
    1352             m_WakeupStat.mark(m_framecounter); 
    1353              
    1354             m_one_period_passed=true; 
    1355             m_last_timestamp_at_period_ticks=ideal_presentation_time; 
    1356              
    1357             return true; 
    1358         } else { 
    1359             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Too early wait %d ticks\n",tmp); 
    1360              return false; 
    1361         } 
    1362 //      } else { 
    1363 //         return false; 
    1364 //      } 
    1365 #else 
    1366     if(m_framecounter > m_period) { 
    1367      return true; 
    1368     } else return false; 
    1369 #endif 
    1370 
    1371  
    1372 unsigned int AmdtpReceiveStreamProcessor::getPeriodTimeStamp() { 
    1373     if (m_one_period_passed) { 
    1374         return m_last_timestamp_at_period_ticks; 
    1375     } else { 
    1376         //     float ticks_per_sample=24576000.0/m_framerate; 
    1377          float ticks_per_sample=m_ticks_per_frame; 
    1378      
    1379         // we are allowed to add some constant  
    1380         // processing delay to the transfer delay 
    1381         // being the period size and some fixed delay 
    1382         //     unsigned int processing_delay=ticks_per_sample*(m_period)+RECEIVE_PROCESSING_DELAY; 
    1383         unsigned int processing_delay=ticks_per_sample*(m_period+RECEIVE_PROCESSING_DELAY_IN_SAMPLES); 
    1384          
    1385         unsigned int m_last_timestamp_ticks = CYCLE_COUNTER_TO_TICKS(m_last_timestamp); 
    1386          
    1387         // add the processing delay 
    1388         int ideal_presentation_time = m_last_timestamp_ticks + processing_delay; 
    1389         unsigned int buffer_content_ticks=(int)((m_framecounter-m_syt_interval)*ticks_per_sample); 
    1390          
    1391         // if the ideal_presentation_time is smaller than buffer_content_ticks, wraparound has occurred 
    1392         // for the cycle part of m_last_timestamp. Therefore add one second worth of ticks 
    1393         // to the cycle counter, as this is the wraparound point. 
    1394         if (ideal_presentation_time < buffer_content_ticks) ideal_presentation_time += 24576000; 
    1395         // we can now safely substract these, it will always be > 0 
    1396         ideal_presentation_time -= buffer_content_ticks; 
    1397          
    1398         return ideal_presentation_time; 
    1399     } 
     1147int64_t AmdtpReceiveStreamProcessor::getTimeUntilNextPeriodUsecs() { 
     1148    uint64_t time_at_period=getTimeAtPeriod(); 
     1149     
     1150    uint64_t cycle_timer=m_handler->getCycleTimerTicks(); 
     1151     
     1152    int64_t until_next=time_at_period-cycle_timer; 
     1153     
     1154    // the maximal difference we can allow (64secs) 
     1155    const int64_t max=TICKS_PER_SECOND*64L; 
     1156     
     1157    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11lld, TPUS=%f\n", 
     1158        time_at_period, cycle_timer, until_next, m_handler->getTicksPerUsec() 
     1159        ); 
     1160         
     1161    if(until_next > max) { 
     1162        // this means that cycle_timer has wrapped, but 
     1163        // time_at_period has not. we should unwrap cycle_timer 
     1164        // by adding TICKS_PER_SECOND*128L, meaning that we should substract 
     1165        // this value from until_next             
     1166        until_next -= TICKS_PER_SECOND*128L; 
     1167    } else if (until_next < -max) { 
     1168        // this means that time_at_period has wrapped, but 
     1169        // cycle_timer has not. we should unwrap time_at_period 
     1170        // by adding TICKS_PER_SECOND*128L, meaning that we should add 
     1171        // this value from until_next 
     1172        until_next += TICKS_PER_SECOND*128L; 
     1173    } 
     1174     
     1175    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "   TAP=%11llu, CTR=%11llu, UTN=%11lld, TPUS=%f\n", 
     1176        time_at_period, cycle_timer, until_next, m_handler->getTicksPerUsec() 
     1177        ); 
     1178     
     1179    // now convert to usecs 
     1180    // don't use the mapping function because it only works 
     1181    // for absolute times, not the relative time we are 
     1182    // using here (which can also be negative). 
     1183    return (int64_t)(((float)until_next) / m_handler->getTicksPerUsec()); 
     1184
     1185 
     1186uint64_t AmdtpReceiveStreamProcessor::getTimeAtPeriodUsecs() { 
     1187    // then we should convert this into usecs 
     1188    // FIXME: we assume that the TimeSource of the IsoHandler is 
     1189    //        in usecs. 
     1190    return m_handler->mapToTimeSource(getTimeAtPeriod()); 
     1191
     1192 
     1193uint64_t AmdtpReceiveStreamProcessor::getTimeAtPeriod() { 
     1194 
     1195    // every time a packet is received both the framecounter and the base 
     1196    // timestamp are updated. This means that at any instance of time, the  
     1197    // front of the buffer (latest sample) timestamp is known. 
     1198    // As we know the number of frames in the buffer, and we now the rate 
     1199    // in ticks/frame, we can calculate the back of buffer timestamp as: 
     1200    //    back_of_buffer_time = front_time - nbframes * rate 
     1201    // the next period boundary time lies m_period frames later: 
     1202    //    next_period_boundary = back_of_buffer_time + m_period * rate 
     1203     
     1204    // NOTE: we should account for the fact that the timestamp is not for 
     1205    //       the latest sample, but for the latest sample minus syt_interval-1 
     1206    //       because it is the timestamp for the first sample in the packet, 
     1207    //       while the complete packet contains SYT_INTERVAL samples. 
     1208    //       this makes the equation: 
     1209    //          back_of_buffer_time = front_time - (nbframes - (syt_interval - 1)) * rate 
     1210    //          next_period_boundary = back_of_buffer_time + m_period * rate 
     1211 
     1212    // NOTE: where do we add the processing delay? 
     1213    //       if we add it here: 
     1214    //          next_period_boundary += RECEIVE_PROCESSING_DELAY 
     1215     
     1216    // the complete equation now is: 
     1217    // next_period_boundary = front_time - (nbframes - (syt_interval - 1)) * rate 
     1218    //                        + m_period * rate + RECEIVE_PROCESSING_DELAY 
     1219    // since syt_interval is a constant value, we can equally well ignore it, as 
     1220    // if it were already included in RECEIVE_PROCESSING_DELAY 
     1221    // making the equation (simplified: 
     1222    // next_period_boundary = front_time + (-nbframes + m_period) * rate 
     1223    //                        + RECEIVE_PROCESSING_DELAY 
     1224    // currently this is in ticks 
     1225     
     1226    int64_t next_period_boundary =  m_last_timestamp; 
     1227    next_period_boundary     += (int64_t)(((int64_t)m_period-(int64_t)m_framecounter) * m_ticks_per_frame); 
     1228    next_period_boundary     += RECEIVE_PROCESSING_DELAY; 
     1229     
     1230    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD=%11lld, LTS=%11llu, FC=%5d, TPF=%f\n", 
     1231        next_period_boundary, m_last_timestamp, m_framecounter, m_ticks_per_frame 
     1232        ); 
     1233     
     1234    // this happens if the timestamp wraps around while there are a lot of  
     1235    // frames in the buffer. We should add the wraparound value of the ticks 
     1236    // counter 
     1237    if (next_period_boundary < 0) { 
     1238        next_period_boundary += TICKS_PER_SECOND * 128L; 
     1239    } 
     1240    // this happens when the last timestamp is near wrapping, and  
     1241    // m_framecounter is low. 
     1242    // this means: m_last_timestamp is near wrapping and have just had 
     1243    // a getPackets() from the client side. the projected next_period 
     1244    // boundary lies beyond the wrap value. 
     1245    // the action is to wrap the value. 
     1246    else if (next_period_boundary >= TICKS_PER_SECOND * 128L) { 
     1247        next_period_boundary -= TICKS_PER_SECOND * 128L; 
     1248    } 
     1249     
     1250    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "   NPD=%11lld, LTS=%11llu, FC=%5d, TPF=%f\n", 
     1251        next_period_boundary, m_last_timestamp, m_framecounter, m_ticks_per_frame 
     1252        ); 
     1253 
     1254    return next_period_boundary; 
    14001255} 
    14011256 
     
    14241279    freebob_ringbuffer_reset(m_event_buffer); 
    14251280     
    1426         // reset the last timestamp 
    1427         m_last_timestamp=0; 
    1428          
    14291281    m_PeriodStat.reset(); 
    14301282    m_PacketStat.reset(); 
    14311283    m_WakeupStat.reset(); 
    1432  
    1433     // reset the framerate estimate 
    1434      m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / m_framerate; 
    1435  
    1436      debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",m_ticks_per_frame); 
    1437          
    1438         //reset the timestamps 
    1439         m_last_timestamp=0; 
    1440         m_last_timestamp2=0; 
    1441          
    1442     m_one_period_passed=false; 
     1284     
     1285    m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); 
    14431286 
    14441287    // reset all non-device specific stuff 
     
    14911334 
    14921335    // prepare the framerate estimate 
    1493     m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / m_framerate
     1336    m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate)
    14941337 
    14951338    debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",m_ticks_per_frame); 
     
    15001343    // add the processing delay 
    15011344    debugOutput(DEBUG_LEVEL_VERBOSE,"Adding %u frames of SYT slack buffering...\n", 
    1502         RECEIVE_PROCESSING_DELAY_IN_SAMPLES); 
    1503     ringbuffer_size_frames+=RECEIVE_PROCESSING_DELAY_IN_SAMPLES
     1345        (uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame)); 
     1346    ringbuffer_size_frames+=(uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame)
    15041347     
    15051348    if( !(m_event_buffer=freebob_ringbuffer_create( 
     
    16011444} 
    16021445 
    1603 bool AmdtpReceiveStreamProcessor::transfer() { 
     1446bool AmdtpReceiveStreamProcessor::prepareForStart() { 
     1447    disable(); 
     1448    return true; 
     1449
     1450 
     1451bool AmdtpReceiveStreamProcessor::prepareForStop() { 
     1452    disable(); 
     1453    return true; 
     1454
     1455 
     1456bool AmdtpReceiveStreamProcessor::canClientTransferFrames(unsigned int nbframes) { 
     1457    return getFrameCounter() >= (int) nbframes; 
     1458
     1459 
     1460bool AmdtpReceiveStreamProcessor::getFrames(unsigned int nbframes, int64_t ts) { 
    16041461 
    16051462    m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
     
    16071464        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    16081465         
    1609 /* another naive section:        
    1610         unsigned int read_size=m_period*sizeof(quadlet_t)*m_dimension; 
    1611         char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension); 
    1612         if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) { 
    1613                 debugWarning("Could not read from event buffer\n"); 
    1614         } 
    1615  
    1616         receiveBlock(dummybuffer, m_period, 0); 
    1617  
    1618         free(dummybuffer); 
    1619 */ 
    16201466        int xrun; 
    16211467        unsigned int offset=0; 
     
    16251471        // this is period_size*dimension of events 
    16261472 
    1627         int events2read=m_period*m_dimension; 
     1473        int events2read=nbframes*m_dimension; 
    16281474        int bytes2read=events2read*sizeof(quadlet_t); 
    16291475        /* read events2read bytes from the ringbuffer  
     
    16381484         
    16391485        while(bytes2read>0) { 
    1640                 unsigned int framesread=(m_period*cluster_size-bytes2read)/cluster_size; 
     1486                unsigned int framesread=(nbframes*cluster_size-bytes2read)/cluster_size; 
    16411487                offset=framesread; 
    16421488                 
     
    16951541                assert(bytes2read%cluster_size==0); 
    16961542        } 
    1697  
    1698         return true; 
     1543         
     1544    // update the frame counter such that it reflects the new value, 
     1545    // and also update the buffer head timestamp as we pull frames 
     1546    // done in the SP base class 
     1547 
     1548    // wrap the timestamp if nescessary 
     1549    if (ts < 0) { 
     1550        ts += TICKS_PER_SECOND * 128L; 
     1551    } else if (ts >= TICKS_PER_SECOND * 128L) { 
     1552        ts -= TICKS_PER_SECOND * 128L; 
     1553    } 
     1554     
     1555    if (!StreamProcessor::getFrames(nbframes, ts)) { 
     1556        debugError("Could not do StreamProcessor::getFrames(%d, %llu)\n",nbframes, ts); 
     1557        return false; 
     1558    } 
     1559     
     1560    return true; 
    16991561} 
    17001562 
     
    17521614         
    17531615        quadlet_t *target_event=NULL; 
    1754         int j; 
     1616        unsigned int j; 
    17551617         
    17561618        for ( PortVectorIterator it = m_PacketPorts.begin(); 
  • branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.h

    r383 r384  
    3838#include <libiec61883/iec61883.h> 
    3939#include "ringbuffer.h" 
     40#include <pthread.h> 
    4041 
    4142#define AMDTP_MAX_PACKET_SIZE 2048 
     
    8889    bool reset(); 
    8990    bool prepare(); 
    90     bool transfer(); 
    91     virtual void setVerboseLevel(int l); 
    92      
    93     bool isOnePeriodReady(); 
     91     
     92    bool prepareForStop(); 
     93    bool prepareForStart(); 
     94     
     95    bool prepareForEnable(); 
     96     
     97    bool canClientTransferFrames(unsigned int nbframes); 
     98    bool putFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents from the client 
    9499 
    95100    // We have 1 period of samples = m_period 
     
    103108     
    104109    unsigned int getMaxPacketSize() {return 4 * (2 + m_syt_interval * m_dimension);};  
    105  
    106     // FIXME: do this the proper way! 
    107     AmdtpReceiveStreamProcessor *syncmaster; 
    108  
    109     // this updates the timestamp, and the 
    110     // 'bufferfill' 
    111     // should be called from the same thread 
    112     // that does the iteration 
    113     void decrementFrameCounter(); 
    114         void incrementFrameCounter(int nbframes); 
     110     
     111    int64_t getTimeUntilNextPeriodUsecs(); 
     112 
     113    uint64_t getTimeAtPeriodUsecs(); 
     114    uint64_t getTimeAtPeriod(); 
     115     
     116    void setVerboseLevel(int l); 
    115117     
    116118protected: 
     
    177179        bool reset(); 
    178180        bool prepare(); 
    179         bool transfer(); 
    180  
    181         virtual void setVerboseLevel(int l); 
    182          
    183         bool isOnePeriodReady(); 
    184          
     181         
     182    bool prepareForStop(); 
     183    bool prepareForStart(); 
     184         
     185    bool canClientTransferFrames(unsigned int nbframes); 
     186    bool getFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents to the client 
     187 
    185188    // We have 1 period of samples = m_period 
    186189    // this period takes m_period/m_framerate seconds of time 
     
    194197        unsigned int getMaxPacketSize() {return 4 * (2 + m_syt_interval * m_dimension);};  
    195198 
    196     float getTicksPerFrame() {return m_ticks_per_frame;}; 
    197     unsigned int getPeriodTimeStamp(); 
    198      
    199199    void dumpInfo(); 
    200200     
     201    int64_t getTimeUntilNextPeriodUsecs(); 
     202 
     203    uint64_t getTimeAtPeriodUsecs(); 
     204    uint64_t getTimeAtPeriod(); 
     205         
     206    void setVerboseLevel(int l); 
     207             
    201208protected: 
    202209 
     
    211218    unsigned int m_syt_interval; 
    212219     
    213     unsigned int m_last_timestamp; 
    214     unsigned int m_last_timestamp2; 
    215     unsigned int m_last_timestamp_at_period_ticks; 
    216      
    217     float m_ticks_per_frame; 
    218      
    219     bool m_one_period_passed; 
     220    uint64_t m_last_timestamp; /// last timestamp (in ticks) 
     221    uint64_t m_last_timestamp2; /// last timestamp (in ticks) 
     222    uint64_t m_last_timestamp_at_period_ticks; 
    220223     
    221224    DECLARE_DEBUG_MODULE; 
  • branches/streaming-rework/src/libstreaming/cycletimer.h

    r383 r384  
    2727 */ 
    2828  
    29 /* Definitions and utility macro's to handle the ISO cyclecounter */ 
     29/* Definitions and utility macro's to handle the ISO cycle timer */ 
    3030 
    31 #ifndef __CYCLECOUNTER_H__ 
    32 #define __CYCLECOUNTER_H__ 
     31#ifndef __CYCLETIMER_H__ 
     32#define __CYCLETIMER_H__ 
    3333 
    3434#define CSR_CYCLE_TIME            0x200 
    3535#define CSR_REGISTER_BASE  0xfffff0000000ULL 
    3636 
    37 #define CYCLES_PER_SECOND   8000 
    38 #define TICKS_PER_CYCLE     3072 
    39 #define TICKS_PER_SECOND   (CYCLES_PER_SECOND * TICKS_PER_CYCLE) 
     37#define CYCLES_PER_SECOND   8000U 
     38#define TICKS_PER_CYCLE     3072U 
     39#define TICKS_PER_SECOND    24576000UL 
    4040#define TICKS_PER_USEC     (TICKS_PER_SECOND/1000000.0) 
    4141 
    4242#define USECS_PER_TICK     (1.0/TICKS_PER_USEC) 
    4343 
    44 #define CYCLE_COUNTER_GET_SECS(x)   ((((x) & 0xFE000000) >> 25)) 
    45 #define CYCLE_COUNTER_GET_CYCLES(x) ((((x) & 0x01FFF000) >> 12)) 
    46 #define CYCLE_COUNTER_GET_OFFSET(x)  ((((x) & 0x00000FFF))) 
    47 #define CYCLE_COUNTER_TO_TICKS(x) ((CYCLE_COUNTER_GET_SECS(x)   * TICKS_PER_SECOND) +\ 
    48                                    (CYCLE_COUNTER_GET_CYCLES(x) * TICKS_PER_CYCLE ) +\ 
    49                                    (CYCLE_COUNTER_GET_OFFSET(x)            )) 
     44#define CYCLE_TIMER_GET_SECS(x)   ((((x) & 0xFE000000U) >> 25)) 
     45#define CYCLE_TIMER_GET_CYCLES(x) ((((x) & 0x01FFF000U) >> 12)) 
     46#define CYCLE_TIMER_GET_OFFSET(x)  ((((x) & 0x00000FFFU))) 
     47#define CYCLE_TIMER_TO_TICKS(x) ((CYCLE_TIMER_GET_SECS(x)   * TICKS_PER_SECOND) +\ 
     48                                   (CYCLE_TIMER_GET_CYCLES(x) * TICKS_PER_CYCLE ) +\ 
     49                                   (CYCLE_TIMER_GET_OFFSET(x)            )) 
    5050                                    
    5151// non-efficient versions, to be avoided in critical code 
     
    5454#define TICKS_TO_OFFSET(x) (((x)%TICKS_PER_CYCLE)) 
    5555 
    56 #define CYCLE_COUNTER_UNWRAP_TICKS(x) ((x) \ 
    57                                        + (127 * TICKS_PER_SECOND) \ 
     56#define TICKS_TO_CYCLE_TIMER(x) (  ((TICKS_TO_SECS(x) & 0x7F) << 25) \ 
     57                                 | ((TICKS_TO_CYCLES(x) & 0x1FFF) << 12) \ 
     58                                 | ((TICKS_TO_OFFSET(x) & 0xFFF))) 
     59                                  
     60#define TICKS_TO_SYT(x)         (((TICKS_TO_CYCLES(x) & 0xF) << 12) \ 
     61                                 | ((TICKS_TO_OFFSET(x) & 0xFFF))) 
     62 
     63#define CYCLE_TIMER_UNWRAP_TICKS(x) (((uint64_t)(x)) \ 
     64                                       + (127ULL * TICKS_PER_SECOND) \ 
    5865                                       + (CYCLES_PER_SECOND * TICKS_PER_CYCLE) \ 
    5966                                       + (TICKS_PER_CYCLE) \ 
    6067                                      ) 
     68#define CYCLE_TIMER_WRAP_TICKS(x) ((x % TICKS_PER_SECOND)) 
    6169 
    62 #endif // __CYCLECOUNTER_H__ 
     70#endif // __CYCLETIMER_H__ 
  • branches/streaming-rework/src/libstreaming/freebob_streaming.cpp

    r383 r384  
    159159 
    160160        // we are ready! 
    161          
    162161        debugOutputShort(DEBUG_LEVEL_VERBOSE, "\n\n"); 
    163162        return dev; 
     
    191190    debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Start -------------\n"); 
    192191     
    193          
    194192    // create the connections for all devices 
    195193    // iterate over the found devices 
     
    207205    } 
    208206 
    209         dev->processorManager->start(); 
    210  
    211         return 0; 
     207    if(dev->processorManager->start()) { 
     208        return 0; 
     209    } else { 
     210        freebob_streaming_stop(dev); 
     211        return -1; 
     212    } 
    212213} 
    213214 
     
    225226            assert(device); 
    226227                 
    227  
    228228            int j=0; 
    229229            for(j=0; j<device->getStreamCount();j++) { 
     
    250250        static int xruns=0; 
    251251                 
    252                 periods++; 
    253                 if(periods>periods_print) { 
    254                         debugOutput(DEBUG_LEVEL_VERBOSE, "\n"); 
    255                         debugOutput(DEBUG_LEVEL_VERBOSE, "============================================\n"); 
    256                         debugOutput(DEBUG_LEVEL_VERBOSE, "Xruns: %d\n",xruns); 
    257                         debugOutput(DEBUG_LEVEL_VERBOSE, "============================================\n"); 
    258                         dev->processorManager->dumpInfo(); 
    259 //                      debugOutput(DEBUG_LEVEL_VERBOSE, "--------------------------------------------\n"); 
    260 /*                      quadlet_t *addr=(quadlet_t*)(dev->processorManager->getPortByIndex(0, Port::E_Capture)->getBufferAddress()); 
    261                         if (addr) hexDumpQuadlets(addr,10);*/ 
    262                         debugOutput(DEBUG_LEVEL_VERBOSE, "\n"); 
    263                         periods_print+=100; 
    264                 } 
     252        periods++; 
     253        if(periods>periods_print) { 
     254                debugOutput(DEBUG_LEVEL_VERBOSE, "\n"); 
     255                debugOutput(DEBUG_LEVEL_VERBOSE, "============================================\n"); 
     256                debugOutput(DEBUG_LEVEL_VERBOSE, "Xruns: %d\n",xruns); 
     257                debugOutput(DEBUG_LEVEL_VERBOSE, "============================================\n"); 
     258                dev->processorManager->dumpInfo(); 
     259                debugOutput(DEBUG_LEVEL_VERBOSE, "\n"); 
     260                periods_print+=100; 
     261        } 
     262         
    265263        if(dev->processorManager->waitForPeriod()) { 
    266264                return dev->options.period_size; 
    267265        } else { 
    268266                debugWarning("XRUN detected\n"); 
     267                 
    269268                // do xrun recovery 
    270                  
    271269                dev->processorManager->handleXrun(); 
    272270                xruns++; 
  • branches/streaming-rework/src/libstreaming/IsoHandler.cpp

    r383 r384  
    2929#include "IsoHandler.h" 
    3030#include "IsoStream.h" 
    31 #include "cyclecounter.h" 
    32  
    33 #include "libutil/Time.h" 
     31#include "cycletimer.h" 
     32 
    3433#include "libutil/TimeSource.h" 
    3534#include "libutil/SystemTimeSource.h" 
     
    3938#include <assert.h> 
    4039#include <unistd.h> 
     40#include <string.h> 
    4141 
    4242#include <iostream> 
    4343using namespace std; 
    4444 
    45  
    46 #define CC_SLEEP_TIME_AFTER_UPDATE     100 
     45#define CC_SLEEP_TIME_AFTER_UPDATE    1000 
    4746#define CC_SLEEP_TIME_AFTER_FAILURE     10 
    48 #define CC_DLL_COEFF     ((0.01)*((float)(CC_SLEEP_TIME_AFTER_UPDATE/1000.0))) 
    49  
    50 #define CC_MAX_RATE_ERROR           (2/100.0) 
     47#define CC_DLL_COEFF     ((0.001)*((float)(CC_SLEEP_TIME_AFTER_UPDATE/1000.0))) 
     48 
     49#define CC_MAX_RATE_ERROR           (2.0/100.0) 
    5150#define CC_INIT_MAX_TRIES 10 
    5251 
     
    9695   : TimeSource(), m_handle(0), m_handle_util(0), m_port(port),  
    9796   m_buf_packets(400), m_max_packet_size(1024), m_irq_interval(-1), 
    98    m_cyclecounter_ticks(0), m_lastmeas_usecs(0), m_ticks_per_usec(24.576),  
     97   m_cycletimer_ticks(0), m_lastmeas_usecs(0), m_ticks_per_usec(24.576),  
    9998   m_ticks_per_usec_dll_err2(0), 
    100    m_packetcount(0), m_dropped(0), m_Client(0) 
    101 
    102     InitTime(); 
     99   m_packetcount(0), m_dropped(0), m_Client(0), 
     100   m_State(E_Created), m_TimeSource_LastSecs(0),m_TimeSource_NbCycleWraps(0) 
     101
    103102    m_TimeSource=new FreebobUtil::SystemTimeSource(); 
    104103} 
     
    108107   m_buf_packets(buf_packets), m_max_packet_size( max_packet_size),  
    109108   m_irq_interval(irq),  
    110    m_cyclecounter_ticks(0), m_lastmeas_usecs(0), m_ticks_per_usec(24.576), 
     109   m_cycletimer_ticks(0), m_lastmeas_usecs(0), m_ticks_per_usec(24.576), 
    111110   m_ticks_per_usec_dll_err2(0), 
    112    m_packetcount(0), m_dropped(0), m_Client(0) 
    113 
    114     InitTime(); 
     111   m_packetcount(0), m_dropped(0), m_Client(0), 
     112   m_State(E_Created), m_TimeSource_LastSecs(0),m_TimeSource_NbCycleWraps(0) 
     113
    115114    m_TimeSource=new FreebobUtil::SystemTimeSource(); 
    116115} 
    117116 
    118117IsoHandler::~IsoHandler() { 
     118 
     119// Don't call until libraw1394's raw1394_new_handle() function has been 
     120// fixed to correctly initialise the iso_packet_infos field.  Bug is 
     121// confirmed present in libraw1394 1.2.1.  In any case, 
     122// raw1394_destroy_handle() will do any iso system shutdown required. 
     123//     raw1394_iso_shutdown(m_handle); 
     124 
    119125    if(m_handle) { 
     126        if (m_State == E_Running) { 
    120127            stop(); 
     128        } 
     129         
    121130        raw1394_destroy_handle(m_handle); 
    122131    } 
     132     
    123133    if(m_handle_util) raw1394_destroy_handle(m_handle_util); 
    124134     
    125     delete m_TimeSource; 
     135    if (m_TimeSource) delete m_TimeSource; 
    126136} 
    127137 
     
    131141    debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this); 
    132142 
     143    // check the state 
     144    if(m_State != E_Created) { 
     145        debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State); 
     146        return false; 
     147    } 
     148     
     149    // the main handle for the ISO traffic 
    133150    m_handle = raw1394_new_handle_on_port( m_port ); 
    134151    if ( !m_handle ) { 
    135152        if ( !errno ) { 
    136                        cerr << "libraw1394 not compatible" << endl
     153            debugError("libraw1394 not compatible\n")
    137154        } else { 
    138                        perror( "IsoHandler::Initialize: Could not get 1394 handle" ); 
    139                        cerr << "Is ieee1394 and raw1394 driver loaded?" << endl
     155            debugError("Could not get 1394 handle: %s", strerror(errno) ); 
     156            debugError("Are ieee1394 and raw1394 drivers loaded?")
    140157        } 
    141158        return false; 
     
    147164    if ( !m_handle_util ) { 
    148165        if ( !errno ) { 
    149                        cerr << "libraw1394 not compatible" << endl
     166            debugError("libraw1394 not compatible\n")
    150167        } else { 
    151                        perror( "IsoHandler::Initialize: Could not get 1394 handle" ); 
    152                        cerr << "Is ieee1394 and raw1394 driver loaded?" << endl
     168            debugError("Could not get 1394 handle: %s", strerror(errno) ); 
     169            debugError("Are ieee1394 and raw1394 drivers loaded?")
    153170        } 
    154         return false; 
    155     } 
    156          
     171         
     172        raw1394_destroy_handle(m_handle); 
     173        return false; 
     174    } 
    157175    raw1394_set_userdata(m_handle_util, static_cast<void *>(this)); 
    158176         
     177    // bus reset handling 
    159178    if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) { 
    160179        debugWarning("Could not enable busreset notification.\n"); 
    161180        debugWarning(" Error message: %s\n",strerror(errno)); 
    162         } 
    163          
     181        debugWarning("Continuing without bus reset support.\n"); 
     182    } else { 
     183        // apparently this cannot fail 
    164184        raw1394_set_bus_reset_handler(m_handle, busreset_handler); 
     185    } 
    165186 
    166187    // initialize the local timesource 
    167188    m_TimeSource_NbCycleWraps=0; 
     189    unsigned int new_timer; 
     190     
     191#ifdef LIBRAW1394_USE_CTRREAD_API 
     192    struct raw1394_cycle_timer ctr; 
     193    int err; 
     194    err=raw1394_read_cycle_timer(m_handle_util, &ctr); 
     195    if(err) { 
     196        debugWarning("raw1394_read_cycle_timer: %s", strerror(err)); 
     197    } 
     198    new_timer=ctr.cycle_timer; 
     199#else 
     200    // normally we should be able to use the same handle 
     201    // because it is not iterated on by any other stuff 
     202    // but I'm not sure 
    168203    quadlet_t buf=0; 
    169     unsigned int new_counter; 
    170      
    171204    raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
    172205        CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
    173  
    174     new_counter= ntohl(buf) & 0xFFFFFFFF; 
    175     m_TimeSource_LastSecs=CYCLE_COUNTER_GET_SECS(new_counter); 
    176  
    177     // update the cycle counter value for initial value 
    178     initCycleCounter(); 
     206    new_timer= ntohl(buf) & 0xFFFFFFFF; 
     207#endif 
     208 
     209    m_TimeSource_LastSecs=CYCLE_TIMER_GET_SECS(new_timer); 
     210 
     211    // update the cycle timer value for initial value 
     212    initCycleTimer(); 
     213 
     214    // update the internal state 
     215    m_State=E_Initialized; 
     216     
     217    return true; 
     218
     219 
     220bool IsoHandler::prepare() 
     221
     222    debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this); 
     223 
     224    // check the state 
     225    if(m_State != E_Initialized) { 
     226        debugError("Incorrect state, expected E_Initialized, got %d\n",(int)m_State); 
     227        return false; 
     228    } 
     229     
     230    // Don't call until libraw1394's raw1394_new_handle() function has been 
     231    // fixed to correctly initialise the iso_packet_infos field.  Bug is 
     232    // confirmed present in libraw1394 1.2.1. 
     233 
     234//     raw1394_iso_shutdown(m_handle); 
     235     
     236    m_State = E_Prepared; 
     237     
     238    return true; 
     239
     240 
     241bool IsoHandler::start(int cycle) 
     242
     243    debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
     244     
     245    // check the state 
     246    if(m_State != E_Prepared) { 
     247        debugError("Incorrect state, expected E_Prepared, got %d\n",(int)m_State); 
     248        return false; 
     249    } 
     250 
     251    m_State=E_Running; 
     252 
     253    return true; 
     254
     255 
     256bool IsoHandler::stop() 
     257
     258    debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
     259     
     260    // check state 
     261    if(m_State != E_Running) { 
     262        debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State); 
     263        return false; 
     264    } 
     265     
     266    // this is put here to try and avoid the 
     267    // Runaway context problem 
     268    // don't know if it will help though. 
     269    raw1394_iso_xmit_sync(m_handle); 
     270     
     271    raw1394_iso_stop(m_handle); 
     272     
     273    m_State=E_Prepared; 
    179274     
    180275    return true; 
     
    185280{ 
    186281    m_TimeSource=t; 
    187  
    188     // update the cycle counter value for initial value 
    189     initCycleCounter(); 
    190  
    191     return true; 
    192 
    193  
    194 bool IsoHandler::stop() 
    195 
    196     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
    197     raw1394_iso_stop(m_handle); 
     282     
     283    // update the cycle timer value for initial value 
     284    initCycleTimer(); 
     285     
    198286    return true; 
    199287} 
     
    210298    // as busreset can elect a new cycle master, 
    211299    // we need to re-initialize our timing code 
    212     initCycleCounter(); 
     300    initCycleTimer(); 
    213301     
    214302    return 0; 
     
    216304 
    217305/** 
    218  * Returns the current value of the cycle counter (in ticks) 
    219  * 
    220  * @return the current value of the cycle counter (in ticks) 
     306 * Returns the current value of the cycle timer (in ticks) 
     307 * 
     308 * @return the current value of the cycle timer (in ticks) 
    221309 */ 
    222310 
    223 unsigned int IsoHandler::getCycleCounter() { 
    224     // calculate the cycle counter based upon the current time 
    225     // and the estimated tick rate 
    226     freebob_microsecs_t now=m_TimeSource->getCurrentTimeAsUsecs(); 
     311unsigned int IsoHandler::getCycleTimerTicks() { 
     312 
     313#ifdef LIBRAW1394_USE_CTRREAD_API 
     314    // the new api should be realtime safe. 
     315    // it might cause a reschedule when turning preemption, 
     316    // back on but that won't hurt us if we have sufficient  
     317    // priority  
     318    struct raw1394_cycle_timer ctr; 
     319    int err; 
     320    err=raw1394_read_cycle_timer(m_handle_util, &ctr); 
     321    if(err) { 
     322        debugWarning("raw1394_read_cycle_timer: %s", strerror(err)); 
     323    } 
     324    return CYCLE_TIMER_TO_TICKS(ctr.cycle_timer); 
     325 
     326#else 
     327    // use the estimated version 
     328    freebob_microsecs_t now; 
     329    now=m_TimeSource->getCurrentTimeAsUsecs(); 
     330    return mapToCycleTimer(now); 
     331#endif  
     332 
     333
     334 
     335/** 
     336 * Returns the current value of the cycle timer (as is) 
     337 * 
     338 * @return the current value of the cycle timer (as is) 
     339 */ 
     340 
     341unsigned int IsoHandler::getCycleTimer() { 
     342 
     343#ifdef LIBRAW1394_USE_CTRREAD_API 
     344    // the new api should be realtime safe. 
     345    // it might cause a reschedule when turning preemption, 
     346    // back on but that won't hurt us if we have sufficient  
     347    // priority  
     348    struct raw1394_cycle_timer ctr; 
     349    int err; 
     350    err=raw1394_read_cycle_timer(m_handle_util, &ctr); 
     351    if(err) { 
     352        debugWarning("raw1394_read_cycle_timer: %s", strerror(err)); 
     353    } 
     354    return ctr.cycle_timer; 
     355 
     356#else 
     357    // use the estimated version 
     358    freebob_microsecs_t now; 
     359    now=m_TimeSource->getCurrentTimeAsUsecs(); 
     360    return TICKS_TO_CYCLE_TIMER(mapToCycleTimer(now)); 
     361#endif  
     362 
     363
     364/** 
     365 * Maps a value of the active TimeSource to a Cycle Timer value. 
     366 * 
     367 * This is usefull if you know a time value and want the corresponding 
     368 * Cycle Timer value. Note that the value shouldn't be too far off 
     369 * the current time, because then the mapping can be bad. 
     370 * 
     371 * @return the value of the cycle timer (in ticks) 
     372 */ 
     373 
     374unsigned int IsoHandler::mapToCycleTimer(freebob_microsecs_t now) { 
    227375 
    228376    // linear interpolation 
     
    231379    float offset=m_ticks_per_usec * ((float)delta_usecs); 
    232380 
    233     unsigned int pred_ticks=m_cyclecounter_ticks+(unsigned int)offset; 
    234  
    235     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Get CC: d_usecs=%d, offset=%f, cc_ticks=%lu, pred_ticks=%lu\n", 
    236       delta_usecs, offset, m_cyclecounter_ticks,pred_ticks 
    237       ); 
     381    int64_t pred_ticks=(int64_t)m_cycletimer_ticks+(int64_t)offset; 
     382 
     383    if (pred_ticks < 0) { 
     384        debugWarning("Predicted ticks < 0\n"); 
     385    } 
     386    debugOutput(DEBUG_LEVEL_VERBOSE,"now=%llu, m_lastmeas_usec=%llu, delta_usec=%d\n", 
     387            now, m_lastmeas_usecs, delta_usecs); 
     388    debugOutput(DEBUG_LEVEL_VERBOSE,"t/usec=%f, offset=%f, m_cc_t=%llu, pred_ticks=%lld\n", 
     389            m_ticks_per_usec, offset, m_cycletimer_ticks, pred_ticks); 
    238390 
    239391    // if we need to wrap, do it 
    240     if (pred_ticks > TICKS_PER_SECOND * 128) { 
    241         pred_ticks -= TICKS_PER_SECOND * 128
     392    if (pred_ticks > TICKS_PER_SECOND * 128L) { 
     393        pred_ticks -= TICKS_PER_SECOND * 128L
    242394    } 
    243395     
     
    245397} 
    246398 
    247 bool IsoHandler::updateCycleCounter() { 
    248     quadlet_t buf=0; 
    249  
     399/** 
     400 * Maps a Cycle Timer value (in ticks) of the active TimeSource's unit. 
     401 * 
     402 * This is usefull if you know a Cycle Timer value and want the corresponding 
     403 * timesource value. Note that the value shouldn't be too far off 
     404 * the current cycle timer, because then the mapping can be bad. 
     405 * 
     406 * @return the mapped value  
     407 */ 
     408 
     409freebob_microsecs_t IsoHandler::mapToTimeSource(unsigned int cc) { 
     410 
     411    // linear interpolation 
     412    int delta_cc=cc-m_cycletimer_ticks; 
     413 
     414    float offset= ((float)delta_cc) / m_ticks_per_usec; 
     415 
     416    int64_t pred_time=(int64_t)m_lastmeas_usecs+(int64_t)offset; 
     417 
     418    if (pred_time < 0) { 
     419        debugWarning("Predicted time < 0\n"); 
     420        debugOutput(DEBUG_LEVEL_VERBOSE,"cc=%u, m_cycletimer_ticks=%llu, delta_cc=%d\n", 
     421                cc, m_cycletimer_ticks, delta_cc); 
     422        debugOutput(DEBUG_LEVEL_VERBOSE,"t/usec=%f, offset=%f, m_lastmeas_usecs=%llu, pred_time=%lld\n", 
     423                m_ticks_per_usec, offset, m_lastmeas_usecs, pred_time);     
     424    } 
     425 
     426 
     427    return pred_time; 
     428
     429 
     430bool IsoHandler::updateCycleTimer() { 
    250431    freebob_microsecs_t prev_usecs=m_lastmeas_usecs; 
    251     unsigned int prev_ticks=m_cyclecounter_ticks; 
     432    uint64_t prev_ticks=m_cycletimer_ticks; 
    252433     
    253434    freebob_microsecs_t new_usecs; 
    254     unsigned int new_ticks; 
    255     unsigned int new_counter; 
    256      
    257     /* To estimate the cycle counter, we implement a  
    258        DLL based routine, that maps the cycle counter 
     435    uint64_t new_ticks; 
     436    unsigned int new_timer; 
     437     
     438    /* To estimate the cycle timer, we implement a  
     439       DLL based routine, that maps the cycle timer 
    259440       on the system clock. 
    260441        
     
    270451        Basically what we do is estimate the next point (T1,CC1_est) 
    271452        based upon the previous point (T0, CC0) and the estimated rate (R). 
    272         Then we compare our estimation with the measured cycle counter 
     453        Then we compare our estimation with the measured cycle timer 
    273454        at T1 (=CC1_meas). We then calculate the estimation error on R: 
    274455        err=(CC1_meas-CC0)/(T1-T2) - (CC1_est-CC0)/(T1-T2) 
     
    288469         
    289470     */ 
    290      
     471#ifdef LIBRAW1394_USE_CTRREAD_API 
     472    struct raw1394_cycle_timer ctr; 
     473    int err; 
     474    err=raw1394_read_cycle_timer(m_handle_util, &ctr); 
     475    if(err) { 
     476        debugWarning("raw1394_read_cycle_timer: %s", strerror(err)); 
     477    } 
     478    new_usecs=(freebob_microsecs_t)ctr.local_time; 
     479    new_timer=ctr.cycle_timer; 
     480#else 
    291481    // normally we should be able to use the same handle 
    292482    // because it is not iterated on by any other stuff 
    293483    // but I'm not sure 
     484    quadlet_t buf=0; 
    294485    raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
    295486        CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
    296487    new_usecs=m_TimeSource->getCurrentTimeAsUsecs(); 
    297  
    298     new_counter= ntohl(buf) & 0xFFFFFFFF; 
    299     new_ticks=CYCLE_COUNTER_TO_TICKS(new_counter); 
     488    new_timer= ntohl(buf) & 0xFFFFFFFF; 
     489#endif     
     490 
     491    new_ticks=CYCLE_TIMER_TO_TICKS(new_timer); 
    300492 
    301493    // the difference in system time 
    302     int delta_usecs=new_usecs-prev_usecs; 
     494    int64_t delta_usecs=new_usecs-prev_usecs; 
    303495    // this cannot be 0, because m_TimeSource->getCurrentTimeAsUsecs should  
    304496    // never return the same value (maybe in future terrahz processors?) 
    305497    assert(delta_usecs); 
    306498     
    307     // the measured cycle counter difference 
    308     unsigned int delta_ticks_meas; 
    309     if (new_ticks > prev_ticks) { 
     499    // the measured cycle timer difference 
     500    int64_t delta_ticks_meas; 
     501    if (new_ticks >= prev_ticks) { 
    310502        delta_ticks_meas=new_ticks - prev_ticks; 
    311503    } else { // wraparound 
    312         delta_ticks_meas=CYCLE_COUNTER_UNWRAP_TICKS(new_ticks) - prev_ticks; 
    313     } 
    314      
    315     // the estimated cycle counter difference 
    316     unsigned int delta_ticks_est=(unsigned int)(m_ticks_per_usec * ((float)delta_usecs)); 
     504        delta_ticks_meas=CYCLE_TIMER_UNWRAP_TICKS(new_ticks) - prev_ticks; 
     505    } 
     506     
     507    // the estimated cycle timer difference 
     508    int64_t delta_ticks_est=(int64_t)(m_ticks_per_usec * ((float)delta_usecs)); 
    317509     
    318510    // the measured & estimated rate 
    319     float rate_meas=((float)delta_ticks_meas/(float)delta_usecs); 
     511    float rate_meas=((double)delta_ticks_meas/(double)delta_usecs); 
    320512    float rate_est=((float)m_ticks_per_usec); 
    321513     
     
    338530#ifdef DEBUG 
    339531 
    340         int diff=(int)delta_ticks_est; 
     532        int64_t diff=(int64_t)delta_ticks_est; 
    341533         
    342534        // calculate the difference in predicted ticks and 
     
    345537         
    346538         
    347         if (diff > 24000 || diff < -24000) { // approx +/-1 msec error 
    348             debugOutput(DEBUG_LEVEL_VERBOSE,"Bad pred (%p): diff=%d, dt_est=%u, dt_meas=%u, d=%dus, err=%fus\n", this, 
     539        if (diff > 24000L || diff < -24000L) { // approx +/-1 msec error 
     540            debugOutput(DEBUG_LEVEL_VERBOSE,"Bad pred (%p): diff=%lld, dt_est=%lld, dt_meas=%lld, d=%lldus, err=%fus\n", this, 
    349541                diff, delta_ticks_est, delta_ticks_meas, delta_usecs, (((float)diff)/24.576) 
    350542                ); 
    351543        } else { 
    352             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Good pred: diff=%d, dt_est=%u, dt_meas=%u, d=%dus, err=%fus\n", 
     544            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Good pred: diff=%lld, dt_est=%lld, dt_meas=%lld, d=%lldus, err=%fus\n", 
    353545                diff, delta_ticks_est, delta_ticks_meas, delta_usecs, (((float)diff)/24.576) 
    354546                ); 
     
    379571         
    380572        // update the internal values 
    381         // note: the next cyclecounter point is 
     573        // note: the next cycletimer point is 
    382574        //       the estimated one, not the measured one! 
    383         m_cyclecounter_ticks += delta_ticks_est; 
     575        m_cycletimer_ticks += delta_ticks_est; 
    384576        // if we need to wrap, do it 
    385         if (m_cyclecounter_ticks > TICKS_PER_SECOND * 128) { 
    386             m_cyclecounter_ticks -= TICKS_PER_SECOND * 128
     577        if (m_cycletimer_ticks > TICKS_PER_SECOND * 128L) { 
     578            m_cycletimer_ticks -= TICKS_PER_SECOND * 128L
    387579        } 
    388580 
    389581        m_lastmeas_usecs = new_usecs; 
    390582 
    391         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"U TS: %10u -> %10u, d=%7uus, dt_est=%7u,  dt_meas=%7u, erate=%6.4f, mrate=%6f\n", 
    392               prev_ticks, m_cyclecounter_ticks, delta_usecs, 
     583        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"U TS: %10llu -> %10llu, d=%7lldus, dt_est=%7lld,  dt_meas=%7lld, erate=%6.4f, mrate=%6f\n", 
     584              prev_ticks, m_cycletimer_ticks, delta_usecs, 
    393585              delta_ticks_est, delta_ticks_meas, m_ticks_per_usec, rate_meas 
    394586              ); 
     
    405597} 
    406598 
    407 void IsoHandler::initCycleCounter() { 
    408     quadlet_t buf=0; 
    409  
     599void IsoHandler::initCycleTimer() { 
    410600    freebob_microsecs_t prev_usecs; 
    411601    unsigned int prev_ticks; 
    412     unsigned int prev_counter; 
     602    unsigned int prev_timer; 
    413603     
    414604    freebob_microsecs_t new_usecs; 
    415605    unsigned int new_ticks; 
    416     unsigned int new_counter; 
     606    unsigned int new_timer; 
    417607     
    418608    float rate=0.0; 
     
    428618           || (rate < 24.576*(1.0-CC_MAX_RATE_ERROR)))) { 
    429619            
     620#ifdef LIBRAW1394_USE_CTRREAD_API 
     621        struct raw1394_cycle_timer ctr; 
     622        int err; 
     623        err=raw1394_read_cycle_timer(m_handle_util, &ctr); 
     624        if(err) { 
     625            debugWarning("raw1394_read_cycle_timer: %s", strerror(err)); 
     626        } 
     627        prev_usecs=(freebob_microsecs_t)ctr.local_time; 
     628        prev_timer=ctr.cycle_timer; 
     629#else 
    430630        // normally we should be able to use the same handle 
    431631        // because it is not iterated on by any other stuff 
    432632        // but I'm not sure 
     633        quadlet_t buf=0; 
    433634        raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
    434635            CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
    435636        prev_usecs=m_TimeSource->getCurrentTimeAsUsecs(); 
    436          
    437         prev_counter= ntohl(buf) & 0xFFFFFFFF; 
    438         prev_ticks=CYCLE_COUNTER_TO_TICKS(prev_counter); 
     637        prev_timer= ntohl(buf) & 0xFFFFFFFF; 
     638#endif                
     639        prev_ticks=CYCLE_TIMER_TO_TICKS(prev_timer); 
    439640         
    440641        usleep(CC_SLEEP_TIME_AFTER_UPDATE); 
    441642         
     643         
     644#ifdef LIBRAW1394_USE_CTRREAD_API 
     645        err=raw1394_read_cycle_timer(m_handle_util, &ctr); 
     646        if(err) { 
     647            debugWarning("raw1394_read_cycle_timer: %s", strerror(err)); 
     648        } 
     649        new_usecs=(freebob_microsecs_t)ctr.local_time; 
     650        new_timer=ctr.cycle_timer; 
     651#else 
    442652        // normally we should be able to use the same handle 
    443653        // because it is not iterated on by any other stuff 
     
    446656            CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
    447657        new_usecs=m_TimeSource->getCurrentTimeAsUsecs(); 
    448  
    449         new_counter= ntohl(buf) & 0xFFFFFFFF; 
    450         new_ticks=CYCLE_COUNTER_TO_TICKS(new_counter); 
     658        new_timer= ntohl(buf) & 0xFFFFFFFF; 
     659#endif     
     660 
     661        new_ticks=CYCLE_TIMER_TO_TICKS(new_timer); 
    451662         
    452663        unsigned int delta_ticks; 
     
    455666            delta_ticks=new_ticks - prev_ticks; 
    456667        } else { // wraparound 
    457             delta_ticks=CYCLE_COUNTER_UNWRAP_TICKS(new_ticks) - prev_ticks; 
     668            delta_ticks=CYCLE_TIMER_UNWRAP_TICKS(new_ticks) - prev_ticks; 
    458669        } 
    459670         
     
    467678         
    468679        // update the internal values 
    469         m_cyclecounter_ticks=new_ticks; 
     680        m_cycletimer_ticks=new_ticks; 
    470681        m_lastmeas_usecs=new_usecs; 
    471682         
     
    478689    // this is not fatal, the DLL will eventually correct this 
    479690    if(try_cnt == CC_INIT_MAX_TRIES) { 
    480         debugWarning("Failed to properly initialize cycle counter...\n"); 
     691        debugWarning("Failed to properly initialize cycle timer...\n"); 
    481692    } 
    482693     
     
    495706    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type    : %s\n", 
    496707            (this->getType()==EHT_Receive ? "Receive" : "Transmit")); 
    497     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %2d, %2d\n", 
     708    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %2d, %2d\n", 
    498709            m_port, channel); 
    499     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count   : %10d (%5d dropped)\n", 
     710    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count    : %10d (%5d dropped)\n", 
    500711            this->getPacketCount(), this->getDroppedCount()); 
     712             
    501713    #ifdef DEBUG 
    502     unsigned int cc=this->getCycleCounter(); 
    503        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Cycle counter  : %10lu (%03us, %04ucycles, %04uticks)\n", 
     714    unsigned int cc=this->getCycleTimerTicks(); 
     715    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Cycle timer     : %10lu (%03us, %04ucycles, %04uticks)\n", 
    504716            cc,TICKS_TO_SECS(cc),TICKS_TO_CYCLES(cc),TICKS_TO_OFFSET(cc)); 
     717              
     718/*  freebob_microsecs_t now=m_TimeSource->getCurrentTimeAsUsecs(); 
     719    cc=mapToCycleTimer(now); 
     720    freebob_microsecs_t now_mapped=mapToTimeSource(cc); 
     721     
     722    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Mapping test   : now: %14llu, cc: %10lu, mapped now: %14llu\n", 
     723            now,cc,now_mapped);*/ 
    505724    #endif 
    506     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Ticks/usec     : %8.6f (dll2: %8.6e)\n\n", 
     725    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Ticks/usec      : %8.6f (dll2: %8.6e)\n\n", 
    507726            this->getTicksPerUsec(), m_ticks_per_usec_dll_err2); 
    508727 
     
    551770/* The timesource interface */ 
    552771freebob_microsecs_t IsoHandler::getCurrentTime() { 
    553     quadlet_t buf=0; 
    554     unsigned int new_counter; 
    555      
    556     raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
    557         CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
    558      
    559     new_counter= ntohl(buf) & 0xFFFFFFFF; 
     772    unsigned int new_timer; 
     773     
     774    new_timer= getCycleTimerTicks(); 
    560775         
    561776    // this assumes that it never happens that there are more than 2 
    562777    // minutes between calls 
    563     if (CYCLE_COUNTER_GET_SECS(new_counter) < m_TimeSource_LastSecs) { 
     778    if (CYCLE_TIMER_GET_SECS(new_timer) < m_TimeSource_LastSecs) { 
    564779        m_TimeSource_NbCycleWraps++; 
    565780    } 
    566781     
    567     freebob_microsecs_t ticks=m_TimeSource_NbCycleWraps * 128 * TICKS_PER_SECOND 
    568             + CYCLE_COUNTER_TO_TICKS(new_counter); 
    569      
    570     m_TimeSource_LastSecs=CYCLE_COUNTER_GET_SECS(new_counter); 
     782    freebob_microsecs_t ticks=m_TimeSource_NbCycleWraps * 128L * TICKS_PER_SECOND 
     783            + CYCLE_TIMER_TO_TICKS(new_timer); 
     784     
     785    m_TimeSource_LastSecs=CYCLE_TIMER_GET_SECS(new_timer); 
    571786     
    572787    debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Wraps=%4u, LastSecs=%3u, nowSecs=%3u, ticks=%10u\n", 
    573788              m_TimeSource_NbCycleWraps, m_TimeSource_LastSecs, 
    574               CYCLE_COUNTER_GET_SECS(new_counter), ticks 
     789              CYCLE_TIMER_GET_SECS(new_timer), ticks 
    575790              ); 
    576791               
    577792    return  ticks; 
     793} 
     794 
     795freebob_microsecs_t IsoHandler::unWrapTime(freebob_microsecs_t t) { 
     796    return CYCLE_TIMER_UNWRAP_TICKS(t); 
     797} 
     798 
     799freebob_microsecs_t IsoHandler::wrapTime(freebob_microsecs_t t) { 
     800    return CYCLE_TIMER_WRAP_TICKS(t); 
    578801} 
    579802 
     
    608831IsoRecvHandler::~IsoRecvHandler() 
    609832{ 
    610 // Don't call until libraw1394's raw1394_new_handle() function has been 
    611 // fixed to correctly initialise the iso_packet_infos field.  Bug is 
    612 // confirmed present in libraw1394 1.2.1.  In any case, 
    613 // raw1394_destroy_handle() will do any iso system shutdown required. 
    614 //      raw1394_iso_shutdown(m_handle); 
    615         raw1394_destroy_handle(m_handle); 
    616         m_handle = NULL; 
     833 
    617834} 
    618835 
     
    628845} 
    629846 
    630 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,  
     847enum raw1394_iso_disposition IsoRecvHandler::putPacket( 
     848                    unsigned char *data, unsigned int length,  
    631849                    unsigned char channel, unsigned char tag, unsigned char sy,  
    632850                    unsigned int cycle, unsigned int dropped) { 
     
    647865bool IsoRecvHandler::prepare() 
    648866{ 
    649 // Don't call until libraw1394's raw1394_new_handle() function has been 
    650 // fixed to correctly initialise the iso_packet_infos field.  Bug is 
    651 // confirmed present in libraw1394 1.2.1. 
    652 //      raw1394_iso_shutdown(m_handle); 
     867     
     868    // prepare the generic IsoHandler 
     869    if(!IsoHandler::prepare()) { 
     870        return false; 
     871    } 
    653872 
    654873    debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p)\n",this); 
     
    658877    debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval); 
    659878 
    660         if(raw1394_iso_recv_init(m_handle,   iso_receive_handler, 
     879    if(raw1394_iso_recv_init(m_handle,    
     880                             iso_receive_handler, 
    661881                             m_buf_packets, 
    662882                             m_max_packet_size, 
     
    676896    debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle); 
    677897     
     898    // start the generic IsoHandler 
     899    if(!IsoHandler::start(cycle)) { 
     900        return false; 
     901    } 
     902     
    678903    if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) { 
    679904        debugFatal("Could not start receive handler (%s)\n",strerror(errno)); 
     
    723948IsoXmitHandler::~IsoXmitHandler() 
    724949{ 
    725 // Don't call until libraw1394's raw1394_new_handle() function has been 
    726 // fixed to correctly initialise the iso_packet_infos field.  Bug is 
    727 // confirmed present in libraw1394 1.2.1.  In any case, 
    728 // raw1394_destroy_handle() will do any iso system shutdown required. 
    729 //      raw1394_iso_shutdown(m_handle); 
    730         raw1394_destroy_handle(m_handle); 
    731         m_handle = NULL; 
     950    // handle cleanup is done in the IsoHanlder destructor 
    732951} 
    733952 
     
    742961 
    743962    return true; 
    744  
    745 } 
    746  
    747 enum raw1394_iso_disposition IsoXmitHandler::getPacket(unsigned char *data, unsigned int *length, 
    748                               unsigned char *tag, unsigned char *sy, 
    749                               int cycle, unsigned int dropped) { 
    750  
    751         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, 
    752                      "sending packet: length=%d, cycle=%d\n", 
    753                      *length, cycle ); 
    754         m_packetcount++; 
    755         m_dropped+=dropped; 
    756  
    757         if(m_Client) { 
    758         return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size); 
    759         } 
    760          
    761         return RAW1394_ISO_OK; 
    762963} 
    763964 
     
    766967    debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso transmit handler (%p, client=%p)\n",this,m_Client); 
    767968 
    768 //      raw1394_iso_shutdown(m_handle); 
     969    if(!(IsoHandler::prepare())) { 
     970        return false; 
     971    } 
     972 
    769973    debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets); 
    770974    debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size); 
     
    791995{ 
    792996    debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle); 
     997     
     998    if(!(IsoHandler::start(cycle))) { 
     999        return false; 
     1000    } 
     1001     
    7931002    if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) { 
    7941003        debugFatal("Could not start xmit handler (%s)\n",strerror(errno)); 
     
    7961005    } 
    7971006    return true; 
     1007} 
     1008 
     1009enum raw1394_iso_disposition IsoXmitHandler::getPacket( 
     1010                    unsigned char *data, unsigned int *length, 
     1011                    unsigned char *tag, unsigned char *sy, 
     1012                    int cycle, unsigned int dropped) { 
     1013 
     1014    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, 
     1015                    "sending packet: length=%d, cycle=%d\n", 
     1016                    *length, cycle ); 
     1017    m_packetcount++; 
     1018    m_dropped+=dropped; 
     1019 
     1020    if(m_Client) { 
     1021        return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size); 
     1022    } 
     1023 
     1024    return RAW1394_ISO_OK; 
    7981025} 
    7991026 
  • branches/streaming-rework/src/libstreaming/IsoHandler.h

    r383 r384  
    6868 
    6969        virtual bool init(); 
     70        virtual bool prepare(); 
     71        virtual bool start(int cycle); 
     72        virtual bool stop(); 
    7073         
    7174        int iterate() { if(m_handle) return raw1394_loop_iterate(m_handle); else return -1; }; 
     
    8689        virtual enum EHandlerType getType() = 0; 
    8790 
    88                 virtual bool start(int cycle) = 0; 
    89                 virtual bool stop(); 
    90                  
    9191        int getFileDescriptor() { return raw1394_get_fd(m_handle);}; 
    9292 
     
    102102        int getPort() {return m_port;}; 
    103103 
    104                 virtual bool prepare() = 0; 
    105                  
    106                 // get the most recent cycle counter value 
    107                 // RT safe 
    108                 unsigned int getCycleCounter(); 
    109                  
    110                 // update the cycle counter cache 
    111                 // not RT safe 
    112                 // the isohandlermanager is responsible for calling this! 
    113         bool updateCycleCounter(); 
     104        /// get the most recent cycle timer value (in ticks) 
     105        unsigned int getCycleTimerTicks(); 
     106        /// get the most recent cycle timer value (as is) 
     107        unsigned int getCycleTimer(); 
     108        /// Maps a value of the active TimeSource to a Cycle Timer value. 
     109        unsigned int mapToCycleTimer(freebob_microsecs_t now); 
     110        /// Maps a Cycle Timer value to the active TimeSource's unit. 
     111        freebob_microsecs_t mapToTimeSource(unsigned int cc); 
     112        /// update the cycle timer cache 
     113        bool updateCycleTimer(); 
    114114        float getTicksPerUsec() {return m_ticks_per_usec;}; 
    115115 
     
    125125        int             m_irq_interval; 
    126126         
    127                unsigned int        m_cyclecounter_ticks; 
    128         freebob_microsecs_t m_lastmeas_usecs; 
     127        uint64_t        m_cycletimer_ticks; 
     128        uint64_t m_lastmeas_usecs; 
    129129        float               m_ticks_per_usec; 
    130130        float               m_ticks_per_usec_dll_err2; 
     
    145145        static int busreset_handler(raw1394handle_t handle, unsigned int generation); 
    146146 
    147         void initCycleCounter(); 
     147        void initCycleTimer(); 
     148 
     149    // the state machine 
     150    private: 
     151        enum EHandlerStates { 
     152            E_Created, 
     153            E_Initialized, 
     154            E_Prepared, 
     155            E_Running, 
     156            E_Error 
     157        }; 
     158         
     159        enum EHandlerStates m_State; 
    148160 
    149161    // implement the TimeSource interface 
     
    151163        freebob_microsecs_t getCurrentTime(); 
    152164        freebob_microsecs_t getCurrentTimeAsUsecs(); 
     165        inline freebob_microsecs_t unWrapTime(freebob_microsecs_t t); 
     166        inline freebob_microsecs_t wrapTime(freebob_microsecs_t t); 
     167         
    153168    private: 
    154169        // to cope with wraparound 
     
    173188     
    174189        enum EHandlerType getType() { return EHT_Receive;}; 
    175  
    176 //              int registerStream(IsoStream *); 
    177 //              int unregisterStream(IsoStream *); 
    178190 
    179191        bool start(int cycle); 
     
    216228         
    217229        enum EHandlerType getType() { return EHT_Transmit;}; 
    218  
    219 //              int registerStream(IsoStream *); 
    220 //              int unregisterStream(IsoStream *); 
    221230 
    222231        unsigned int getPreBuffers() {return m_prebuffers;}; 
  • branches/streaming-rework/src/libstreaming/IsoHandlerManager.cpp

    r383 r384  
    3232#include <assert.h> 
    3333 
    34  
    3534namespace FreebobStreaming 
    3635{ 
     
    3938 
    4039IsoHandlerManager::IsoHandlerManager() : 
    41    m_poll_timeout(100), m_poll_fds(0), m_poll_nfds(0) 
     40   m_State(E_Created), 
     41   m_poll_timeout(1), m_poll_fds(0), m_poll_nfds(0) 
    4242{ 
    4343 
     
    5757} 
    5858 
    59 // the IsoHandlerManager thread updates the handler caches 
    60 // it doesn't iterate them !!! 
     59/** 
     60 * the IsoHandlerManager thread execute function iterates the handlers. 
     61 * 
     62 * This means that once the thread is running, streams are 
     63 * transmitted and received (if present on the bus). Make sure 
     64 * that the clients are registered & ready before starting the 
     65 * thread! 
     66 * 
     67 * The register and unregister functions are thread unsafe, so 
     68 * should not be used when the thread is running. 
     69 * 
     70 * @return false if the handlers could not be iterated. 
     71 */ 
    6172bool IsoHandlerManager::Execute() 
    6273{ 
    63     updateCycleCounters(); 
    64     usleep(USLEEP_AFTER_UPDATE); 
     74//     updateCycleTimers(); 
     75     
     76    if(!iterate()) { 
     77        debugFatal("Could not iterate the isoManager\n"); 
     78        return false; 
     79    }     
    6580     
    6681    return true; 
    6782} 
    6883 
     84/** 
     85 * Poll the handlers managed by this manager, and iterate them 
     86 * when ready 
     87 * 
     88 * @return true when successful 
     89 */ 
    6990bool IsoHandlerManager::iterate() 
    7091{ 
     
    104125} 
    105126 
    106 // updates the internal cycle counter caches of the handlers 
    107 void IsoHandlerManager::updateCycleCounters() { 
     127// updates the internal cycle timer caches of the handlers 
     128void IsoHandlerManager::updateCycleTimers() { 
    108129    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n"); 
    109130     
     
    113134    { 
    114135        int cnt=0; 
    115         while (!(*it)->updateCycleCounter() && (cnt++ < MAX_UPDATE_TRIES)) { 
     136        while (!(*it)->updateCycleTimer() && (cnt++ < MAX_UPDATE_TRIES)) { 
    116137            usleep(USLEEP_AFTER_UPDATE_FAILURE); 
    117138        } 
     
    119140     
    120141} 
    121  
    122 bool IsoHandlerManager::prepare() 
    123 { 
    124         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
    125     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
    126           it != m_IsoHandlers.end(); 
    127           ++it ) 
    128     { 
    129         if(!(*it)->prepare()) { 
    130                         debugFatal("Could not prepare handlers\n"); 
    131                         return false; 
    132         } 
    133     } 
    134  
    135         return true; 
    136 } 
    137  
    138  
    139142 
    140143bool IsoHandlerManager::registerHandler(IsoHandler *handler) 
     
    205208 
    206209void IsoHandlerManager::disablePolling(IsoStream *stream) { 
     210    int i=0; 
     211     
    207212    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Disable polling on stream %p\n",stream); 
    208     int i=0; 
     213 
    209214    for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
    210215        it != m_IsoHandlers.end(); 
     
    216221            debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling disabled\n"); 
    217222        } 
     223         
    218224        i++; 
    219225    } 
    220  
    221226} 
    222227 
    223228void IsoHandlerManager::enablePolling(IsoStream *stream) { 
     229    int i=0; 
     230     
    224231    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Enable polling on stream %p\n",stream); 
    225     int i=0; 
     232     
    226233    for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
    227234        it != m_IsoHandlers.end(); 
     
    233240            debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling enabled\n"); 
    234241        } 
     242         
    235243        i++; 
    236244    } 
     
    478486} 
    479487 
     488 
     489bool IsoHandlerManager::prepare() 
     490{ 
     491    bool retval=true; 
     492     
     493    debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
     494     
     495    // check state 
     496    if(m_State != E_Created) { 
     497        debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State); 
     498        return false; 
     499    } 
     500     
     501    for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
     502          it != m_IsoHandlers.end(); 
     503          ++it ) 
     504    { 
     505        if(!(*it)->prepare()) { 
     506            debugFatal("Could not prepare handlers\n"); 
     507            retval=false; 
     508        } 
     509    } 
     510 
     511    if (retval) { 
     512        m_State=E_Prepared; 
     513    } else { 
     514        m_State=E_Error; 
     515    } 
     516 
     517    return retval; 
     518} 
     519 
    480520bool IsoHandlerManager::startHandlers() { 
    481521    return startHandlers(-1); 
     
    483523 
    484524bool IsoHandlerManager::startHandlers(int cycle) { 
     525    bool retval=true; 
     526     
    485527    debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
     528     
     529    // check state 
     530    if(m_State != E_Prepared) { 
     531        debugError("Incorrect state, expected E_Prepared, got %d\n",(int)m_State); 
     532        return false; 
     533    } 
    486534     
    487535    for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
     
    492540        if(!(*it)->start(cycle)) { 
    493541            debugOutput( DEBUG_LEVEL_VERBOSE, " could not start handler (%p)\n",*it); 
    494                        return false; 
     542            retval=false; 
    495543        } 
    496544    } 
    497545     
    498         return true; 
     546    if (retval) { 
     547        m_State=E_Running; 
     548    } else { 
     549        m_State=E_Error; 
     550    } 
     551 
     552    return retval; 
    499553} 
    500554 
    501555bool IsoHandlerManager::stopHandlers() { 
    502556    debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
     557     
     558    // check state 
     559    if(m_State != E_Running) { 
     560        debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State); 
     561        return false; 
     562    } 
     563     
     564    bool retval=true; 
    503565     
    504566    for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
     
    509571        if(!(*it)->stop()){ 
    510572            debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it); 
    511                        return false; 
     573            retval=false; 
    512574        } 
    513575    } 
    514         return true; 
    515 
     576     
     577    if (retval) { 
     578        m_State=E_Prepared; 
     579    } else { 
     580        m_State=E_Error; 
     581    } 
     582     
     583    return retval; 
     584
     585 
     586bool IsoHandlerManager::reset() { 
     587    debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
     588     
     589    // check state 
     590    if(m_State == E_Error) { 
     591        debugFatal("Resetting from error condition not yet supported...\n"); 
     592        return false; 
     593    } 
     594     
     595    // if not in an error condition, reset means stop the handlers 
     596    return stopHandlers(); 
     597
     598 
    516599 
    517600void IsoHandlerManager::setVerboseLevel(int i) { 
     
    527610 
    528611void IsoHandlerManager::dumpInfo() { 
    529         debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n"); 
    530612    int i=0; 
    531613     
     614    debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n"); 
     615    debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State); 
     616 
    532617    for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
    533618          it != m_IsoHandlers.end(); 
  • branches/streaming-rework/src/libstreaming/IsoHandlerManager.h

    r383 r384  
    8989        bool stopHandlers(); ///< stop the managed ISO handlers  
    9090 
    91                bool reset() {return true;}; ///< reset the ISO manager and all streams 
     91        bool reset(); ///< reset the ISO manager and all streams 
    9292 
    9393        bool prepare(); ///< prepare the ISO manager and all streams 
     
    9696        void enablePolling(IsoStream *); ///< enables polling on a stream 
    9797 
    98         public: 
    99          
    100              
    10198    // RunnableInterface interface 
     99    public: 
    102100        bool Execute(); // note that this is called in we while(running) loop 
    103101        bool Init(); 
    104102         
    105             // iterate all handlers 
    106             bool iterate(); 
     103    // the state machine 
    107104    private: 
    108         // updates the cycle counter caches of all handlers 
    109         void updateCycleCounters(); 
     105        enum EHandlerStates { 
     106            E_Created, 
     107            E_Prepared, 
     108            E_Running, 
     109            E_Error 
     110        }; 
    110111         
     112        enum EHandlerStates m_State; 
     113         
     114    private: 
     115        /// iterate all child handlers 
     116        bool iterate(); 
     117    public: // FIXME: just so that SPM can do this (temp solution) 
     118        /// updates the cycle timer caches of all child handlers 
     119        void updateCycleTimers(); 
     120    private: 
    111121        // note: there is a disctinction between streams and handlers 
    112122        // because one handler can serve multiple streams (in case of  
     
    134144        bool rebuildFdMap(); 
    135145 
    136  
     146        // debug stuff 
    137147        DECLARE_DEBUG_MODULE; 
    138148 
  • branches/streaming-rework/src/libstreaming/IsoStream.cpp

    r383 r384  
    3030#include "PacketBuffer.h" 
    3131#include <assert.h> 
    32  
    3332 
    3433namespace FreebobStreaming 
     
    8382            m_port, m_channel); 
    8483 
    85 }; 
     84} 
    8685 
    8786bool IsoStream::setChannel(int c) { 
  • branches/streaming-rework/src/libstreaming/MotuStreamProcessor.cpp

    r383 r384  
    2828 */ 
    2929  
     30#ifdef ENABLE_MOTU 
    3031 
    3132#include "MotuStreamProcessor.h" 
     
    101102        m_running = true; 
    102103         
    103         // Initialise the cycle counter if this is the first time 
     104        // Initialise the cycle timer if this is the first time 
    104105        // iso data has been requested. 
    105106        if (!m_disabled && m_cycle_count<0) { 
     
    176177                m_next_cycle -= 8000; 
    177178 
    178         // Deal cleanly with potential wrap-around cycle counter conditions 
     179        // Deal cleanly with potential wrap-around cycle timer conditions 
    179180        unwrapped_cycle = cycle; 
    180181        if (m_cycle_count-cycle > 7900) 
     
    843844} 
    844845 
    845 bool MotuTransmitStreamProcessor::preparedForStop() { 
     846bool MotuTransmitStreamProcessor::prepareForStop() { 
    846847 
    847848        // If the stream is disabled or isn't running there's no need to 
     
    894895} 
    895896 
    896 bool MotuTransmitStreamProcessor::preparedForStart() { 
     897bool MotuTransmitStreamProcessor::prepareForStart() { 
    897898// Reset some critical variables required so the stream starts cleanly. This 
    898899// method is called once on every stream restart, including those during 
     
    15231524} 
    15241525 
    1525 bool MotuReceiveStreamProcessor::preparedForStop() { 
     1526bool MotuReceiveStreamProcessor::prepareForStop() { 
    15261527 
    15271528        // A MOTU receive stream can stop at any time.  However, signify 
     
    15351536} 
    15361537 
    1537 bool MotuReceiveStreamProcessor::preparedForStart() { 
     1538bool MotuReceiveStreamProcessor::prepareForStart() { 
    15381539// Reset some critical variables required so the stream starts cleanly. This 
    15391540// method is called once on every stream restart, including those during 
     
    15561557                 
    15571558} // end of namespace FreebobStreaming 
     1559#endif 
  • branches/streaming-rework/src/libstreaming/MotuStreamProcessor.h

    r312 r384  
    3535 
    3636#include "../libutil/DelayLockedLoop.h" 
     37 
     38#ifdef ENABLE_MOTU 
    3739 
    3840namespace FreebobStreaming { 
     
    7577        void setTicksPerFrameDLL(float *dll) {m_ticks_per_frame=dll;}; 
    7678 
    77         virtual bool preparedForStop(); 
    78         virtual bool preparedForStart(); 
     79        virtual bool prepareForStop(); 
     80        virtual bool prepareForStart(); 
    7981 
    8082protected: 
     
    165167        unsigned int getEventSize(void); 
    166168 
    167         virtual bool preparedForStop(); 
    168         virtual bool preparedForStart(); 
     169        virtual bool prepareForStop(); 
     170        virtual bool prepareForStart(); 
    169171 
    170172protected: 
     
    183185        unsigned int m_event_size; 
    184186 
    185         // The integrator of a Delay-Locked Loop (DLL) used to provide a 
    186         // continuously updated estimate of the number of ieee1394 frames 
    187         // per audio frame at the current sample rate. 
    188         float m_ticks_per_frame; 
    189  
    190187        signed int m_last_cycle_ofs; 
    191188        signed int m_next_cycle; 
     
    201198} // end of namespace FreebobStreaming 
    202199 
     200#endif /* ENABLE_MOTU */ 
     201 
    203202#endif /* __FREEBOB_MOTUSTREAMPROCESSOR__ */ 
    204203 
  • branches/streaming-rework/src/libstreaming/StreamProcessor.cpp

    r383 r384  
    4646        , m_framecounter(0) 
    4747        , m_framerate(framerate) 
    48         , m_manager(0) 
     48        , m_manager(NULL) 
     49        , m_SyncSource(NULL) 
     50        , m_ticks_per_frame(0) 
    4951        , m_running(false) 
    5052        , m_disabled(true) 
     
    6971    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Enabled        : %d\n", !m_disabled); 
    7072     
    71     m_PeriodStat.dumpInfo(); 
    72     m_PacketStat.dumpInfo(); 
    73     m_WakeupStat.dumpInfo(); 
    74          
    75          
     73//     m_PeriodStat.dumpInfo(); 
     74//     m_PacketStat.dumpInfo(); 
     75//     m_WakeupStat.dumpInfo(); 
     76 
    7677} 
    7778 
     
    8081    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n"); 
    8182     
     83    pthread_mutex_init(&m_framecounter_lock, NULL); 
     84 
    8285    return IsoStream::init(); 
    8386} 
     
    138141} 
    139142 
    140 bool StreamProcessor::transfer() { 
    141  
    142         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    143 // TODO: implement 
    144  
     143/** 
     144 * @brief Notify the StreamProcessor that frames were written 
     145 * 
     146 * This notifies the StreamProcessor of the fact that frames were written to the internal 
     147 * buffer. This is for framecounter & timestamp bookkeeping. 
     148 * 
     149 * @param nbframes the number of frames that are written to the internal buffers 
     150 * @param ts the new timestamp of the 'tail' of the buffer, i.e. the last sample 
     151 *           present in the buffer. 
     152 * @return true if successful 
     153 */ 
     154bool StreamProcessor::putFrames(unsigned int nbframes, int64_t ts) { 
     155 
     156        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Putting %d frames for %llu into frame buffer...\n", nbframes,ts); 
     157        incrementFrameCounter(nbframes, ts); 
     158        return true; 
     159
     160 
     161/** 
     162 * @brief Notify the StreamProcessor that frames were read 
     163 * 
     164 * This notifies the StreamProcessor of the fact that frames were read from the internal 
     165 * buffer. This is for framecounter & timestamp bookkeeping. 
     166 * 
     167 * @param nbframes the number of frames that are read from the internal buffers 
     168 * @param ts the new timestamp of the 'head' of the buffer, i.e. the first sample 
     169 *           present in the buffer. 
     170 * @return true if successful 
     171 */ 
     172bool StreamProcessor::getFrames(unsigned int nbframes, int64_t ts) { 
     173 
     174        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Getting %d frames from frame buffer...\n", nbframes); 
     175        decrementFrameCounter(nbframes, ts); 
    145176        return true; 
    146177} 
     
    157188} 
    158189 
     190bool StreamProcessor::setSyncSource(StreamProcessor *s) { 
     191    m_SyncSource=s; 
     192    return true; 
     193} 
     194 
    159195/** 
    160196 * Decrements the frame counter, in a atomic way. This 
     197 * also sets the buffer tail timestamp 
    161198 * is thread safe. 
    162199 */ 
    163 void StreamProcessor::decrementFrameCounter() { 
    164         SUBSTRACT_ATOMIC((SInt32 *)&m_framecounter,m_period); 
    165 
    166 /** 
    167  * Increments the frame counter, in a atomic way. This 
    168  * is thread safe. 
    169  */ 
    170 void StreamProcessor::incrementFrameCounter(int nbframes) { 
    171         ADD_ATOMIC((SInt32 *)&m_framecounter, nbframes); 
     200void StreamProcessor::decrementFrameCounter(int nbframes, uint64_t new_timestamp) { 
     201    pthread_mutex_lock(&m_framecounter_lock); 
     202    m_framecounter -= nbframes; 
     203    m_buffer_head_timestamp = new_timestamp; 
     204    pthread_mutex_unlock(&m_framecounter_lock); 
     205
     206 
     207/** 
     208 * Increments the frame counter, in a atomic way. 
     209 * also sets the buffer head timestamp 
     210 * This is thread safe. 
     211 */ 
     212void StreamProcessor::incrementFrameCounter(int nbframes, uint64_t new_timestamp) { 
     213    pthread_mutex_lock(&m_framecounter_lock); 
     214    m_framecounter += nbframes; 
     215    m_buffer_tail_timestamp = new_timestamp; 
     216    pthread_mutex_unlock(&m_framecounter_lock); 
     217     
     218
     219 
     220/** 
     221 * Sets the frame counter, in a atomic way.  
     222 * also sets the buffer head timestamp 
     223 * This is thread safe. 
     224 */ 
     225void StreamProcessor::setFrameCounter(int new_framecounter, uint64_t new_timestamp) { 
     226    pthread_mutex_lock(&m_framecounter_lock); 
     227    m_framecounter = new_framecounter; 
     228    m_buffer_tail_timestamp = new_timestamp; 
     229    pthread_mutex_unlock(&m_framecounter_lock); 
     230
     231 
     232/** 
     233 * Sets the buffer tail timestamp (in usecs) 
     234 * This is thread safe. 
     235 */ 
     236void StreamProcessor::setBufferTailTimestamp(uint64_t new_timestamp) { 
     237    pthread_mutex_lock(&m_framecounter_lock); 
     238    m_buffer_tail_timestamp = new_timestamp; 
     239    pthread_mutex_unlock(&m_framecounter_lock); 
     240
     241 
     242/** 
     243 * Sets the buffer head timestamp (in usecs) 
     244 * This is thread safe. 
     245 */ 
     246void StreamProcessor::setBufferHeadTimestamp(uint64_t new_timestamp) { 
     247    pthread_mutex_lock(&m_framecounter_lock); 
     248    m_buffer_head_timestamp = new_timestamp; 
     249    pthread_mutex_unlock(&m_framecounter_lock); 
     250
     251 
     252/** 
     253 * Sets both the buffer head and tail timestamps (in usecs) 
     254 * (avoids multiple mutex lock/unlock's) 
     255 * This is thread safe. 
     256 */ 
     257void StreamProcessor::setBufferTimestamps(uint64_t new_head, uint64_t new_tail) { 
     258    pthread_mutex_lock(&m_framecounter_lock); 
     259    m_buffer_head_timestamp = new_head; 
     260    m_buffer_tail_timestamp = new_tail; 
     261    pthread_mutex_unlock(&m_framecounter_lock); 
     262
     263/** 
     264 * \brief return the timestamp of the first frame in the buffer 
     265 *  
     266 * This function returns the timestamp of the very first sample in 
     267 * the StreamProcessor's buffer. This is useful for slave StreamProcessors  
     268 * to find out what the base for their timestamp generation should 
     269 * be. It also returns the framecounter value for which this timestamp 
     270 * is valid. 
     271 * 
     272 * The system is built in such a way that we assume that the processing 
     273 * of the buffers doesn't take any time. Assume we have a buffer transfer at  
     274 * time T1, meaning that the last sample of this buffer occurs at T1. As  
     275 * processing does not take time, we don't have to add anything to T1. When 
     276 * transferring the processed buffer to the xmit processor, the timestamp 
     277 * of the last sample is still T1. 
     278 * 
     279 * When starting the streams, we don't have any information on this last 
     280 * timestamp. We prefill the buffer at the xmit side, and we should find 
     281 * out what the timestamp for the last sample in the buffer is. If we sync 
     282 * on a receive SP, we know that the last prefilled sample corresponds with 
     283 * the first sample received - 1 sample duration. This is the same as if the last 
     284 * transfer from iso to client would have emptied the receive buffer. 
     285 * 
     286 * 
     287 * @param ts address to store the timestamp in 
     288 * @param fc address to store the associated framecounter in 
     289 */ 
     290void StreamProcessor::getBufferHeadTimestamp(uint64_t *ts, uint64_t *fc) { 
     291    pthread_mutex_lock(&m_framecounter_lock); 
     292    *fc = m_framecounter; 
     293    *ts = m_buffer_head_timestamp; 
     294    pthread_mutex_unlock(&m_framecounter_lock); 
     295
     296         
     297/** 
     298 * \brief return the timestamp of the last frame in the buffer 
     299 *  
     300 * This function returns the timestamp of the last frame in 
     301 * the StreamProcessor's buffer. It also returns the framecounter  
     302 * value for which this timestamp is valid. 
     303 * 
     304 * @param ts address to store the timestamp in 
     305 * @param fc address to store the associated framecounter in 
     306 */ 
     307void StreamProcessor::getBufferTailTimestamp(uint64_t *ts, uint64_t *fc) { 
     308    pthread_mutex_lock(&m_framecounter_lock); 
     309    *fc = m_framecounter; 
     310    *ts = m_buffer_tail_timestamp; 
     311    pthread_mutex_unlock(&m_framecounter_lock); 
    172312} 
    173313 
     
    177317 */ 
    178318void StreamProcessor::resetFrameCounter() { 
    179         ZERO_ATOMIC((SInt32 *)&m_framecounter); 
     319    pthread_mutex_lock(&m_framecounter_lock); 
     320    m_framecounter = 0; 
     321    pthread_mutex_unlock(&m_framecounter_lock); 
    180322} 
    181323 
  • branches/streaming-rework/src/libstreaming/StreamProcessor.h

    r383 r384  
    3434#include "PortManager.h" 
    3535#include "streamstatistics.h" 
     36 
     37#include <pthread.h> 
    3638 
    3739namespace FreebobStreaming { 
     
    7375 
    7476    bool xrunOccurred() { return (m_xruns>0);}; 
    75  
    76     /** 
    77      * This is used for implementing the synchronisation. 
    78      * As long as this function doesn't return true, the current buffer 
    79      * contents are not transfered to the packet decoders. 
    80      * 
    81      * This means that there can be more events in the buffer than 
    82      * one period worth of them, should the synchronisation mechanism  
    83      * require this 
    84      * @return  
    85      */ 
    86     virtual bool isOnePeriodReady()=0; 
    87      
    88     unsigned int getNbPeriodsReady() { if(m_period) return m_framecounter/m_period; else return 0;}; 
    89         virtual void decrementFrameCounter(); 
    90         virtual void incrementFrameCounter(int nbframes); 
    9177     
    9278    // move to private? 
    93         void resetFrameCounter(); 
    9479    void resetXrunCounter(); 
    9580 
     
    9984    bool isEnabled() {return !m_disabled;}; 
    10085 
    101     virtual bool transfer(); ///< transfer the buffer contents from/to client 
     86    virtual bool putFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents from client 
     87    virtual bool getFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents to the client 
    10288 
    10389    virtual bool reset(); ///< reset the streams & buffers (e.g. after xrun) 
     
    11197    virtual void setVerboseLevel(int l); 
    11298 
    113     virtual bool preparedForStop() {return true;}; 
    114     virtual bool preparedForStart() {return true;}; 
     99    virtual bool prepareForStop() {return true;}; 
     100    virtual bool prepareForStart() {return true;}; 
     101     
     102    virtual bool prepareForEnable() {return true;}; 
     103    virtual bool prepareForDisable() {return true;}; 
    115104 
    116105protected: 
     
    124113 
    125114    unsigned int m_xruns; 
    126         signed int m_framecounter; 
    127115 
    128116    unsigned int m_framerate; 
    129117 
    130118    StreamProcessorManager *m_manager; 
    131  
     119     
    132120    bool m_running; 
    133121    bool m_disabled; 
     
    141129    DECLARE_DEBUG_MODULE; 
    142130     
     131    // frame counter & sync stuff 
     132    public: 
     133        /** 
     134         * @brief Can this StreamProcessor handle a nframes of frames? 
     135         * 
     136         * this function indicates if the streamprocessor can handle nframes 
     137         * of frames. It is used to detect underruns-to-be. 
     138         * 
     139         * @param nframes number of frames  
     140         * @return true if the StreamProcessor can handle this amount of frames 
     141         *         false if it can't 
     142         */ 
     143        virtual bool canClientTransferFrames(unsigned int nframes) {return true;}; 
     144         
     145        int getFrameCounter() {return m_framecounter;}; 
     146     
     147        void decrementFrameCounter(int nbframes, uint64_t new_timestamp); 
     148        void incrementFrameCounter(int nbframes, uint64_t new_timestamp); 
     149        void setFrameCounter(int new_framecounter, uint64_t new_timestamp); 
     150        void resetFrameCounter(); 
     151         
     152        void setBufferTailTimestamp(uint64_t new_timestamp); 
     153        void setBufferHeadTimestamp(uint64_t new_timestamp); 
     154        void setBufferTimestamps(uint64_t new_head, uint64_t new_tail); 
     155        /** 
     156         * \brief return the time until the next period boundary (in microseconds) 
     157         * 
     158         * Return the time until the next period boundary. If this StreamProcessor  
     159         * is the current synchronization source, this function is called to  
     160         * determine when a buffer transfer can be made. When this value is 
     161         * smaller than 0, a period boundary is assumed to be crossed, hence a 
     162         * transfer can be made. 
     163         * 
     164         * \return the time in usecs 
     165         */ 
     166        virtual int64_t getTimeUntilNextPeriodUsecs() = 0; 
     167        /** 
     168         * \brief return the time of the next period boundary (in microseconds) 
     169         * 
     170         * Returns the time of the next period boundary, in microseconds. The 
     171         * goal of this function is to determine the exact point of the period 
     172         * boundary. This is assumed to be the point at which the buffer transfer should 
     173         * take place, meaning that it can be used as a reference timestamp for transmitting 
     174         * StreamProcessors 
     175         * 
     176         * \return the time in usecs 
     177         */ 
     178        virtual uint64_t getTimeAtPeriodUsecs() = 0; 
     179         
     180        /** 
     181         * \brief return the time of the next period boundary (in internal units)  
     182         * 
     183         * The same as getTimeUntilNextPeriodUsecs() but in internal units. 
     184         * 
     185         * @return the time in internal units 
     186         */ 
     187        virtual uint64_t getTimeAtPeriod() = 0; 
     188         
     189        void getBufferHeadTimestamp(uint64_t *ts, uint64_t *fc); 
     190        void getBufferTailTimestamp(uint64_t *ts, uint64_t *fc); 
     191                 
     192        bool setSyncSource(StreamProcessor *s); 
     193        float getTicksPerFrame() {return m_ticks_per_frame;}; 
     194     
     195    protected: 
     196        // the framecounter gives the number of frames in the buffer 
     197        signed int m_framecounter; 
     198         
     199        // the buffer tail timestamp gives the timestamp of the last frame 
     200        // that was put into the buffer 
     201        uint64_t   m_buffer_tail_timestamp; 
     202         
     203        // the buffer head timestamp gives the timestamp of the first frame 
     204        // that was put into the buffer 
     205        uint64_t   m_buffer_head_timestamp; 
     206         
     207         
     208        StreamProcessor *m_SyncSource; 
     209         
     210        float m_ticks_per_frame; 
     211 
     212    private: 
     213        // this mutex protects the access to the framecounter 
     214        // and the buffer head timestamp. 
     215        pthread_mutex_t m_framecounter_lock; 
    143216 
    144217}; 
  • branches/streaming-rework/src/libstreaming/StreamProcessorManager.cpp

    r383 r384  
    3939 
    4040StreamProcessorManager::StreamProcessorManager(unsigned int period, unsigned int nb_buffers) 
    41         : m_nb_buffers(nb_buffers), m_period(period), m_xruns(0), m_isoManager(0), m_nbperiods(0) { 
     41        : m_SyncSource(NULL), m_nb_buffers(nb_buffers), m_period(period), m_xruns(0),  
     42        m_isoManager(0), m_nbperiods(0) { 
    4243 
    4344} 
     
    146147} 
    147148 
     149bool StreamProcessorManager::setSyncSource(StreamProcessor *s) { 
     150    m_SyncSource=s; 
     151    return true; 
     152} 
     153 
     154StreamProcessor *StreamProcessorManager::getSyncSource() { 
     155    return m_SyncSource; 
     156} 
     157 
    148158bool StreamProcessorManager::init() 
    149159{ 
    150160        debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
    151161 
    152         // the tread that runs the packet iterators 
     162        // the tread that runs the StreamProcessor 
     163        // checking the period boundaries 
    153164        m_streamingThread=new FreebobUtil::PosixThread(this, 
    154165           m_thread_realtime, m_thread_priority+5,  
     
    169180        m_isoManager->setVerboseLevel(getDebugLevel()); 
    170181         
    171         // the tread that keeps the handler's cycle counters up to date 
    172         // NOTE: is lower priority nescessary? it can block 
    173 //      m_isoManagerThread=new FreebobUtil::PosixThread(m_isoManager, m_thread_realtime, m_thread_priority+6, PTHREAD_CANCEL_DEFERRED); 
    174  
    175     // now that we are using a DLL, we don't need to run this at RT priority 
    176     // it only serves to cope with drift 
    177     // however, in order to make the DLL fast enough, we have to increase 
    178     // its bandwidth, making it more sensitive to deviations. These deviations 
    179     // are mostly determined by the time difference between reading the cycle 
    180     // time register and the local cpu clock. 
    181      
     182        // the tread that keeps the handler's cycle timers up to date 
     183        // and performs the actual packet transfer 
     184        // needs high priority 
    182185        m_isoManagerThread=new FreebobUtil::PosixThread( 
    183186              m_isoManager,  
     
    201204 
    202205    if(sem_init(&m_period_semaphore, 0, 0)) { 
    203                debugFatal( "Cannot init packet transfer semaphore\n"); 
     206        debugFatal( "Cannot init period transfer semaphore\n"); 
    204207        debugFatal( " Error: %s\n",strerror(errno)); 
    205208        return false; 
     
    212215 
    213216        debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n"); 
    214         debugOutput( DEBUG_LEVEL_VERBOSE, " Receive processors...\n"); 
     217         
     218        // if no sync source is set, select one here 
     219        if(m_SyncSource == NULL) { 
     220           debugWarning("Sync Source is not set. Defaulting to first StreamProcessor.\n"); 
     221        } 
     222         
    215223        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    216224                it != m_ReceiveProcessors.end(); 
    217225                ++it ) { 
     226                        if(m_SyncSource == NULL) { 
     227                                debugWarning(" => Sync Source is %p.\n", *it); 
     228                                m_SyncSource = *it; 
     229                        } 
     230        } 
     231 
     232        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     233                it != m_TransmitProcessors.end(); 
     234                ++it ) { 
     235                        if(m_SyncSource == NULL) { 
     236                                debugWarning(" => Sync Source is %p.\n", *it); 
     237                                m_SyncSource = *it; 
     238                        } 
     239        } 
     240 
     241        // now do the actual preparation 
     242        debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Receive processors...\n"); 
     243        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     244                it != m_ReceiveProcessors.end(); 
     245                ++it ) { 
     246                        if(!(*it)->setSyncSource(m_SyncSource)) { 
     247                                debugFatal(  " could not set sync source (%p)...\n",(*it)); 
     248                                return false; 
     249                        } 
     250                         
    218251                        if(!(*it)->prepare()) { 
    219252                                debugFatal(  " could not prepare (%p)...\n",(*it)); 
    220253                                return false; 
    221                                  
    222                         } 
    223                 } 
    224  
    225         debugOutput( DEBUG_LEVEL_VERBOSE, " Transmit processors...\n"); 
     254                        } 
     255        } 
     256 
     257        debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Transmit processors...\n"); 
    226258        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    227259                it != m_TransmitProcessors.end(); 
    228260                ++it ) { 
     261                        if(!(*it)->setSyncSource(m_SyncSource)) { 
     262                                debugFatal(  " could not set sync source (%p)...\n",(*it)); 
     263                                return false; 
     264                        }                
    229265                        if(!(*it)->prepare()) { 
    230266                                debugFatal( " could not prepare (%p)...\n",(*it)); 
    231267                                return false; 
    232                          
    233                         } 
    234                          
    235                 } 
     268                        } 
     269        } 
    236270 
    237271    // if there are no stream processors registered,  
     
    245279} 
    246280 
     281// FIXME: this can be removed 
    247282bool StreamProcessorManager::Execute() 
    248283{ 
    249  
    250         bool period_ready=true; 
    251         bool xrun_has_occured=false; 
    252         bool this_period_ready; 
    253  
    254 //      debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "------------- EXECUTE -----------\n"); 
    255  
    256         if(!m_isoManager->iterate()) { 
    257                 debugFatal("Could not iterate the isoManager\n"); 
    258                 return false; 
    259         } 
    260          
    261         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " RCV PROC: "); 
    262         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    263                 it != m_ReceiveProcessors.end(); 
    264                 ++it ) { 
    265                  
    266                 this_period_ready = (*it)->isOnePeriodReady(); 
    267                 period_ready = period_ready && this_period_ready; 
    268 //              if (this_period_ready) { 
    269 //                  m_isoManager->disablePolling(*it); 
    270 //              } 
    271 //               
    272                 xrun_has_occured = xrun_has_occured || (*it)->xrunOccurred(); 
    273                 debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "(%d/%d/%d) ", period_ready, xrun_has_occured,(*it)->m_framecounter); 
    274         } 
    275         debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "\n"); 
    276  
    277         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " XMIT PROC: "); 
    278         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    279                 it != m_TransmitProcessors.end(); 
    280                 ++it ) { 
    281                 this_period_ready = (*it)->isOnePeriodReady(); 
    282                 period_ready = period_ready && this_period_ready; 
    283 //              if (this_period_ready) { 
    284 //                  m_isoManager->disablePolling(*it); 
    285 //              } 
    286                 xrun_has_occured = xrun_has_occured || (*it)->xrunOccurred(); 
    287                 debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "(%d/%d/%d) ", period_ready, xrun_has_occured,(*it)->m_framecounter); 
    288         } 
    289         debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "\n"); 
    290  
    291         if(xrun_has_occured) { 
    292                 // do xrun signaling/handling 
    293                 debugWarning("Streaming thread detected xrun\n"); 
    294                 m_xruns++; 
    295                 m_xrun_happened=true; 
    296                 sem_post(&m_period_semaphore); 
     284        // temp measure, polling 
     285        usleep(1000); 
     286 
     287        // FIXME: move this to an IsoHandlerManager sub-thread 
     288        // and make this private again in IHM 
     289        m_isoManager->updateCycleTimers(); 
    297290         
    298                 return false; // stop thread 
    299         } 
    300  
    301         if(period_ready) { 
    302                 // signal the waiting thread(s?) that a period is ready 
    303                 sem_post(&m_period_semaphore); 
    304                 debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "Period done...\n"); 
    305  
    306                 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    307                         it != m_ReceiveProcessors.end(); 
    308                         ++it ) { 
    309                         (*it)->decrementFrameCounter(); 
    310 //                      m_isoManager->enablePolling(*it); 
    311                          
    312                 } 
    313          
    314                 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    315                         it != m_TransmitProcessors.end(); 
    316                         ++it ) { 
    317                         (*it)->decrementFrameCounter(); 
    318 //                      m_isoManager->enablePolling(*it); 
    319                 } 
    320                  
    321                 m_nbperiods++; 
    322         } 
    323  
    324         return true; 
    325  
     291        return true; 
    326292} 
    327293 
     
    335301                it != m_ReceiveProcessors.end(); 
    336302                ++it ) { 
    337                         if (!(*it)->preparedForStart()) { 
     303                        if (!(*it)->prepareForStart()) { 
    338304                                debugOutput(DEBUG_LEVEL_VERBOSE,"Receive stream processor (%p) failed to prepare for start\n", *it); 
    339305                                return false; 
     
    343309                                return false; 
    344310                        } 
    345                          
    346                          
    347311                } 
    348312 
     
    351315                it != m_TransmitProcessors.end(); 
    352316                ++it ) { 
    353                         if (!(*it)->preparedForStart()) { 
     317                        if (!(*it)->prepareForStart()) { 
    354318                                debugOutput(DEBUG_LEVEL_VERBOSE,"Transmit stream processor (%p) failed to prepare for start\n", *it); 
    355319                                return false; 
     
    359323                                return false; 
    360324                        } 
    361                          
    362325                } 
    363326 
     
    368331        } 
    369332 
    370         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting IsoHandler...\n"); 
     333        debugOutput( DEBUG_LEVEL_VERBOSE, "Disabling StreamProcessors...\n"); 
     334        if (!disableStreamProcessors()) { 
     335                debugFatal("Could not disable StreamProcessors...\n"); 
     336                return false; 
     337        } 
     338                 
     339        debugOutput( DEBUG_LEVEL_VERBOSE, "Starting IsoHandlers...\n"); 
    371340        if (!m_isoManager->startHandlers(0)) { 
    372341                debugFatal("Could not start handlers...\n"); 
     
    374343        } 
    375344         
    376         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting streaming thread...\n"); 
    377          
     345        debugOutput( DEBUG_LEVEL_VERBOSE, "Starting streaming threads...\n"); 
     346 
     347        // note: libraw1394 doesn't like it if you poll() and/or iterate() before  
     348        //       starting the streams. 
    378349        // start the runner thread 
     350        // FIXME: maybe this should go into the isomanager itself. 
     351        m_isoManagerThread->Start(); 
     352         
     353        // start the runner thread 
     354        // FIXME: not used anymore (for updatecycletimers ATM, but that's not good) 
    379355        m_streamingThread->Start(); 
    380          
    381         // start the runner thread 
    382         m_isoManagerThread->Start(); 
    383356 
    384357        debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for all StreamProcessors to start running...\n"); 
     
    434407         
    435408        // now we reset the frame counters 
    436         // FIXME: check how we are going to do sync 
    437409        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    438410                it != m_ReceiveProcessors.end(); 
     
    467439         
    468440        debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling StreamProcessors...\n"); 
    469         // and we enable the streamprocessors 
    470         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    471                 it != m_ReceiveProcessors.end(); 
    472                 ++it ) {                
    473                 (*it)->enable()
    474                m_isoManager->enablePolling(*it); 
    475         } 
    476  
    477         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    478                it != m_TransmitProcessors.end(); 
    479                ++it ) { 
    480                 (*it)->enable(); 
    481                 m_isoManager->enablePolling(*it)
     441         
     442        debugOutput( DEBUG_LEVEL_VERBOSE, " Sync Source StreamProcessor...\n"); 
     443        if (!m_SyncSource->prepareForEnable()) { 
     444                debugFatal("Could not prepare Sync Source StreamProcessor for enable()...\n"); 
     445                return false
     446        } 
     447         
     448        m_SyncSource->enable(); 
     449 
     450        debugOutput( DEBUG_LEVEL_VERBOSE, " All StreamProcessors...\n"); 
     451        if (!enableStreamProcessors()) { 
     452                debugFatal("Could not enable StreamProcessors...\n"); 
     453                return false
    482454        } 
    483455         
     
    509481                        it != m_ReceiveProcessors.end(); 
    510482                        ++it ) { 
    511                         if(!(*it)->preparedForStop()) allReady = false; 
     483                        if(!(*it)->prepareForStop()) allReady = false; 
    512484                } 
    513485         
     
    515487                        it != m_TransmitProcessors.end(); 
    516488                        ++it ) { 
    517                         if(!(*it)->preparedForStop()) allReady = false; 
     489                        if(!(*it)->prepareForStop()) allReady = false; 
    518490                } 
    519491                usleep(1000); 
     
    560532} 
    561533 
    562 bool StreamProcessorManager::waitForPeriod() { 
    563  
    564         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n"); 
    565  
    566         // Wait for packetizer thread to signal a period completion 
    567         sem_wait(&m_period_semaphore); 
    568          
    569         if(m_xrun_happened) { 
    570            debugWarning("Detected underrun\n"); 
    571            dumpInfo(); 
    572            return false; 
    573         } 
    574          
     534/** 
     535 * Enables the registered StreamProcessors 
     536 * @return true if successful, false otherwise 
     537 */ 
     538bool StreamProcessorManager::enableStreamProcessors() { 
     539        // and we enable the streamprocessors 
     540        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     541                it != m_ReceiveProcessors.end(); 
     542                ++it ) {                 
     543                (*it)->prepareForEnable(); 
     544                (*it)->enable(); 
     545        } 
     546 
     547        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     548                it != m_TransmitProcessors.end(); 
     549                ++it ) { 
     550                (*it)->prepareForEnable(); 
     551                (*it)->enable(); 
     552        } 
    575553        return true; 
    576  
    577 
    578  
     554
     555 
     556/** 
     557 * Disables the registered StreamProcessors 
     558 * @return true if successful, false otherwise 
     559 */ 
     560bool StreamProcessorManager::disableStreamProcessors() { 
     561        // and we disable the streamprocessors 
     562        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     563                it != m_ReceiveProcessors.end(); 
     564                ++it ) { 
     565                (*it)->prepareForDisable(); 
     566                (*it)->disable(); 
     567        } 
     568 
     569        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     570                it != m_TransmitProcessors.end(); 
     571                ++it ) { 
     572                (*it)->prepareForDisable(); 
     573                (*it)->disable(); 
     574        } 
     575        return true; 
     576
     577 
     578/** 
     579 * Called upon Xrun events. This brings all StreamProcessors back 
     580 * into their starting state, and then carries on streaming. This should 
     581 * have the same effect as restarting the whole thing. 
     582 * 
     583 * @return true if successful, false otherwise 
     584 */ 
    579585bool StreamProcessorManager::handleXrun() { 
    580586 
     
    583589        /*  
    584590         * Reset means: 
    585          * 1) Stopping the packetizer thread 
     591         * 1) Disabling the SP's, so that they don't process any packets 
     592         *    note: the isomanager does keep on delivering/requesting them 
    586593         * 2) Bringing all buffers & streamprocessors into a know state 
    587594         *    - Clear all capture buffers 
    588595         *    - Put nb_periods*period_size of null frames into the playback buffers 
    589          * 3) Restarting the packetizer thread 
     596         * 3) Re-enable the SP's 
    590597         */ 
    591         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping processormanager...\n"); 
    592        if(!stop()) { 
    593            debugFatal("Could not stop.\n"); 
     598        debugOutput( DEBUG_LEVEL_VERBOSE, "Disabling StreamProcessors...\n"); 
     599        if (!disableStreamProcessors()) { 
     600               debugFatal("Could not disable StreamProcessors...\n"); 
    594601                return false; 
    595602        } 
     
    597604        debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting Processors...\n"); 
    598605         
    599         // now we reset the frame counters 
     606        // now we reset the streamprocessors 
    600607        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    601608                it != m_ReceiveProcessors.end(); 
     
    611618                        (*it)->dumpInfo(); 
    612619                } 
    613                  
    614620        } 
    615621         
     
    629635        } 
    630636 
    631         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting processormanager...\n"); 
    632  
    633         if(!start()) { 
    634            debugFatal("Could not start.\n"); 
    635                 return false; 
    636         } 
    637  
     637        debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling StreamProcessors...\n"); 
     638         
     639        debugOutput( DEBUG_LEVEL_VERBOSE, " Sync Source StreamProcessor...\n"); 
     640        if (!m_SyncSource->prepareForEnable()) { 
     641                debugFatal("Could not prepare Sync Source StreamProcessor for enable()...\n"); 
     642                return false; 
     643        } 
     644         
     645        m_SyncSource->enable(); 
     646 
     647        debugOutput( DEBUG_LEVEL_VERBOSE, " All StreamProcessors...\n"); 
     648        if (!enableStreamProcessors()) { 
     649                debugFatal("Could not enable StreamProcessors...\n"); 
     650                return false; 
     651        } 
    638652 
    639653        debugOutput( DEBUG_LEVEL_VERBOSE, "Xrun handled...\n"); 
    640654         
    641          
    642655        return true; 
    643656} 
    644657 
     658/** 
     659 * @brief Waits until the next period of samples is ready 
     660 * 
     661 * This function does not return until a full period of samples is (or should be) 
     662 * ready to be transferred.  
     663 * 
     664 * @return true if the period is ready, false if an xrun occurred 
     665 */ 
     666bool StreamProcessorManager::waitForPeriod() { 
     667    int time_till_next_period; 
     668     
     669    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n"); 
     670 
     671    assert(m_SyncSource); 
     672     
     673    time_till_next_period=m_SyncSource->getTimeUntilNextPeriodUsecs(); 
     674     
     675    while(time_till_next_period > 0) { 
     676        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "waiting for %d usecs...\n", time_till_next_period); 
     677     
     678        // wait for the period 
     679        usleep(time_till_next_period); 
     680         
     681        // check if it is still true 
     682        time_till_next_period=m_SyncSource->getTimeUntilNextPeriodUsecs(); 
     683    } 
     684     
     685    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "delayed for %d usecs...\n", time_till_next_period); 
     686     
     687    // this is to notify the client of the delay  
     688    // that we introduced  
     689    m_delayed_usecs=time_till_next_period; 
     690     
     691    // we save the 'ideal' time of the transfer at this point, 
     692    // because we can have interleaved read - process - write  
     693    // cycles making that we modify a receiving stream's buffer 
     694    // before we get to writing. 
     695    // NOTE: before waitForPeriod() is called again, both the transmit 
     696    //       and the receive processors should have done their transfer. 
     697    m_time_of_transfer=m_SyncSource->getTimeAtPeriod(); 
     698    debugOutput( DEBUG_LEVEL_VERBOSE, "transfer at %llu ticks...\n",  
     699        m_time_of_transfer); 
     700     
     701    // check if xruns occurred on the Iso side. 
     702    // also check if xruns will occur should we transfer() now 
     703    bool xrun_occurred=false; 
     704     
     705    for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     706          it != m_ReceiveProcessors.end(); 
     707          ++it ) { 
     708        // a xrun has occurred on the Iso side 
     709        xrun_occurred |= (*it)->xrunOccurred(); 
     710         
     711        // if this is true, a xrun will occur 
     712        xrun_occurred |= !((*it)->canClientTransferFrames(m_period)); 
     713         
     714#ifdef DEBUG 
     715        if ((*it)->xrunOccurred()) { 
     716            debugWarning("Xrun on RECV SP %p due to ISO xrun\n",*it); 
     717        } 
     718        if (!((*it)->canClientTransferFrames(m_period))) { 
     719            debugWarning("Xrun on RECV SP %p due to buffer xrun\n",*it); 
     720        } 
     721#endif 
     722         
     723    } 
     724    for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     725          it != m_TransmitProcessors.end(); 
     726          ++it ) { 
     727        // a xrun has occurred on the Iso side 
     728        xrun_occurred |= (*it)->xrunOccurred(); 
     729         
     730        // if this is true, a xrun will occur 
     731        xrun_occurred |= !((*it)->canClientTransferFrames(m_period)); 
     732         
     733#ifdef DEBUG 
     734        if ((*it)->xrunOccurred()) { 
     735            debugWarning("Xrun on XMIT SP %p due to ISO xrun\n",*it); 
     736        } 
     737        if (!((*it)->canClientTransferFrames(m_period))) { 
     738            debugWarning("Xrun on XMIT SP %p due to buffer xrun\n",*it); 
     739        } 
     740#endif         
     741    } 
     742     
     743    // now we can signal the client that we are (should be) ready 
     744    return !xrun_occurred; 
     745} 
     746 
     747/** 
     748 * @brief Transfer one period of frames for both receive and transmit StreamProcessors 
     749 * 
     750 * Transfers one period of frames from the client side to the Iso side and vice versa. 
     751 * 
     752 * @return true if successful, false otherwise (indicates xrun). 
     753 */ 
    645754bool StreamProcessorManager::transfer() { 
    646  
    647         debugOutput( DEBUG_LEVEL_VERBOSE, "Transferring period...\n"); 
    648  
    649         // a static cast could make sure that there is no performance 
    650         // penalty for the virtual functions (to be checked) 
    651  
    652         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    653                 it != m_ReceiveProcessors.end(); 
    654                 ++it ) {  
    655                 if(!(*it)->transfer()) { 
    656                         debugFatal("could not transfer() stream processor (%p)",*it); 
    657                         return false; 
    658                 } 
    659         } 
    660  
    661         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    662                 it != m_TransmitProcessors.end(); 
    663                 ++it ) { 
    664                 if(!(*it)->transfer()) { 
    665                         debugFatal("could not transfer() stream processor (%p)",*it); 
    666                         return false; 
    667                 } 
    668         } 
    669  
    670         return true; 
    671 
     755     
     756    debugOutput( DEBUG_LEVEL_VERBOSE, "Transferring period...\n"); 
     757 
     758    if (!transfer(StreamProcessor::E_Receive)) return false; 
     759    if (!transfer(StreamProcessor::E_Transmit)) return false; 
     760 
     761    return true; 
     762
     763 
     764/** 
     765 * @brief Transfer one period of frames for either the receive or transmit StreamProcessors 
     766 * 
     767 * Transfers one period of frames from the client side to the Iso side or vice versa. 
     768 * 
     769 * @param t The processor type to tranfer for (receive or transmit) 
     770 * @return true if successful, false otherwise (indicates xrun). 
     771 */ 
    672772 
    673773bool StreamProcessorManager::transfer(enum StreamProcessor::EProcessorType t) { 
    674  
    675         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    676  
    677         // a static cast could make sure that there is no performance 
    678         // penalty for the virtual functions (to be checked) 
    679         if (t==StreamProcessor::E_Receive) { 
    680                 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    681                         it != m_ReceiveProcessors.end(); 
    682                         ++it ) {  
    683                         if(!(*it)->transfer()) { 
    684                                 debugFatal("could not transfer() stream processor (%p)",*it); 
    685                                 return false; 
    686                         } 
    687                 } 
    688         } else { 
    689                 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    690                         it != m_TransmitProcessors.end(); 
    691                         ++it ) { 
    692                         if(!(*it)->transfer()) { 
    693                                 debugFatal("could not transfer() stream processor (%p)",*it); 
    694                                 return false; 
    695                         } 
    696                 } 
    697         } 
    698  
    699         return true; 
     774    int64_t time_of_transfer; 
     775    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
     776     
     777    // first we should find out on what time this transfer is 
     778    // supposed to be happening. this time will become the time 
     779    // stamp for the transmitted buffer. 
     780    // NOTE: maybe we should include the transfer delay here, that 
     781    //       would make it equal for all types of SP's 
     782    time_of_transfer=m_time_of_transfer; 
     783     
     784    // a static cast could make sure that there is no performance 
     785    // penalty for the virtual functions (to be checked) 
     786    if (t==StreamProcessor::E_Receive) { 
     787        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     788                it != m_ReceiveProcessors.end(); 
     789                ++it ) { 
     790            uint64_t buffer_tail_ts; 
     791            uint64_t fc; 
     792            int64_t ts; 
     793         
     794            (*it)->getBufferTailTimestamp(&buffer_tail_ts,&fc); 
     795            ts =  buffer_tail_ts; 
     796            ts += (int64_t)((-(int64_t)fc) * m_SyncSource->getTicksPerFrame()); 
     797            // NOTE: ts can be negative due to wraparound, it is the responsability of the  
     798            //       SP to deal with that. 
     799             
     800            float tmp=m_SyncSource->getTicksPerFrame(); 
     801             
     802            debugOutput(DEBUG_LEVEL_VERBOSE, "=> TS=%11lld, BLT=%11llu, FC=%5d, TPF=%f\n", 
     803                ts, buffer_tail_ts, fc, tmp 
     804                ); 
     805            debugOutput(DEBUG_LEVEL_VERBOSE, "   TPF=%f\n", tmp); 
     806              
     807            #ifdef DEBUG 
     808            { 
     809                uint64_t ts_tail=0; 
     810                uint64_t fc_tail=0; 
     811                 
     812                uint64_t ts_head=0; 
     813                uint64_t fc_head=0; 
     814                 
     815                int cnt=0; 
     816                 
     817                (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     818                (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     819                 
     820                while((fc_head != fc_tail) && (cnt++ < 10)) { 
     821                    (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     822                    (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     823                } 
     824                 
     825                debugOutput(DEBUG_LEVEL_VERBOSE,"R *  HEAD: TS=%llu, FC=%llu | TAIL: TS=%llu, FC=%llu, %d\n", 
     826                    ts_tail, fc_tail, ts_head, fc_head, cnt); 
     827            } 
     828            #endif 
     829     
     830            if(!(*it)->getFrames(m_period, ts)) { 
     831                    debugOutput(DEBUG_LEVEL_VERBOSE,"could not getFrames(%u) from stream processor (%p)", 
     832                            m_period,*it); 
     833                    return false; // buffer underrun 
     834            } 
     835             
     836            #ifdef DEBUG 
     837            { 
     838                uint64_t ts_tail=0; 
     839                uint64_t fc_tail=0; 
     840                 
     841                uint64_t ts_head=0; 
     842                uint64_t fc_head=0; 
     843                 
     844                int cnt=0; 
     845                 
     846                (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     847                (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     848             
     849                while((fc_head != fc_tail) && (cnt++ < 10)) { 
     850                    (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     851                    (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     852                } 
     853                 
     854                debugOutput(DEBUG_LEVEL_VERBOSE,"R > HEAD: TS=%llu, FC=%llu | TAIL: TS=%llu, FC=%llu, %d\n", 
     855                    ts_tail, fc_tail, ts_head, fc_head, cnt);             
     856            } 
     857            #endif 
     858     
     859        } 
     860    } else { 
     861        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     862                it != m_TransmitProcessors.end(); 
     863                ++it ) { 
     864                 
     865            #ifdef DEBUG 
     866            { 
     867                uint64_t ts_tail=0; 
     868                uint64_t fc_tail=0; 
     869                 
     870                uint64_t ts_head=0; 
     871                uint64_t fc_head=0; 
     872                 
     873                int cnt=0; 
     874                 
     875                (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     876                (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     877                 
     878                while((fc_head != fc_tail) && (cnt++ < 10)) { 
     879                    (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     880                    (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     881                } 
     882                 
     883                debugOutput(DEBUG_LEVEL_VERBOSE,"T *  HEAD: TS=%llu, FC=%llu | TAIL: TS=%llu, FC=%llu, %d\n", 
     884                    ts_tail, fc_tail, ts_head, fc_head, cnt); 
     885            } 
     886            #endif 
     887                 
     888            if(!(*it)->putFrames(m_period,time_of_transfer)) { 
     889                debugOutput(DEBUG_LEVEL_VERBOSE, "could not putFrames(%u,%llu) to stream processor (%p)", 
     890                        m_period, time_of_transfer, *it); 
     891                return false; // buffer overrun 
     892            } 
     893             
     894            #ifdef DEBUG 
     895            { 
     896                uint64_t ts_tail=0; 
     897                uint64_t fc_tail=0; 
     898                 
     899                uint64_t ts_head=0; 
     900                uint64_t fc_head=0; 
     901                 
     902                int cnt=0; 
     903                 
     904                (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     905                (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     906             
     907                while((fc_head != fc_tail) && (cnt++ < 10)) { 
     908                    (*it)->getBufferHeadTimestamp(&ts_head,&fc_head); 
     909                    (*it)->getBufferTailTimestamp(&ts_tail,&fc_tail); 
     910                } 
     911                 
     912                debugOutput(DEBUG_LEVEL_VERBOSE,"T > HEAD: TS=%llu, FC=%llu | TAIL: TS=%llu, FC=%llu, %d\n", 
     913                    ts_tail, fc_tail, ts_head, fc_head, cnt);             
     914            } 
     915            #endif 
     916        } 
     917    } 
     918 
     919    return true; 
    700920} 
    701921 
  • branches/streaming-rework/src/libstreaming/StreamProcessorManager.h

    r383 r384  
    5454                        public FreebobUtil::RunnableInterface { 
    5555 
    56         friend class StreamRunner; 
    57  
    5856public: 
    5957 
     
    6462    bool prepare(); ///< to be called after the processors are registered 
    6563 
    66     virtual void setVerboseLevel(int l); 
    67     void dumpInfo(); 
     64    bool start(); 
     65    bool stop(); 
     66 
    6867 
    6968    // this is the setup API 
    7069    bool registerProcessor(StreamProcessor *processor); ///< start managing a streamprocessor 
    7170    bool unregisterProcessor(StreamProcessor *processor); ///< stop managing a streamprocessor 
     71 
     72    bool enableStreamProcessors(); /// enable registered StreamProcessors 
     73    bool disableStreamProcessors(); /// disable registered StreamProcessors 
    7274 
    7375    void setPeriodSize(unsigned int period); 
     
    8385 
    8486    // the client-side functions 
    85     bool xrunOccurred(); 
    86     int getXrunCount() {return m_xruns;}; 
    8787 
    8888    bool waitForPeriod(); ///< wait for the next period 
     
    9090    bool transfer(); ///< transfer the buffer contents from/to client 
    9191    bool transfer(enum StreamProcessor::EProcessorType); ///< transfer the buffer contents from/to client (single processor type) 
    92  
     92     
     93    int getDelayedUsecs() {return m_delayed_usecs;}; 
     94    bool xrunOccurred(); 
     95    int getXrunCount() {return m_xruns;}; 
     96     
     97private: 
     98    int m_delayed_usecs; 
     99    // this stores the time at which the next transfer should occur 
     100    // usually this is in the past, but it is needed as a timestamp 
     101    // for the transmit SP's 
     102    uint64_t m_time_of_transfer; 
     103     
     104public: 
    93105    bool handleXrun(); ///< reset the streams & buffers after xrun 
    94  
    95     bool start(); 
    96     bool stop(); 
    97106 
    98107    bool setThreadParameters(bool rt, int priority); 
    99108 
    100         // the ISO-side functions 
     109    virtual void setVerboseLevel(int l); 
     110    void dumpInfo(); 
     111     
     112     
     113    // the sync source stuff 
     114private: 
     115    StreamProcessor *m_SyncSource; 
     116     
     117public: 
     118    bool setSyncSource(StreamProcessor *s); 
     119    StreamProcessor * getSyncSource(); 
     120 
     121     
    101122protected: 
    102123    int signalWaiters(); // call this to signal a period boundary 
     
    116137    StreamProcessorVector m_ReceiveProcessors; 
    117138    StreamProcessorVector m_TransmitProcessors; 
     139     
     140 
    118141 
    119142    unsigned int m_nb_buffers; 
  • branches/streaming-rework/src/libutil/cycles.h

    r360 r384  
    3232 
    3333/* 
    34  * Standard way to access the cycle counter on i586+ CPUs. 
     34 * Standard way to access the cycle timer on i586+ CPUs. 
    3535 * Currently only used on SMP. 
    3636 * 
  • branches/streaming-rework/src/libutil/SystemTimeSource.cpp

    r360 r384  
    3535 
    3636SystemTimeSource::SystemTimeSource() { 
    37     InitTime(); 
     37//     InitTime(); 
    3838} 
    3939 
     
    4343     
    4444freebob_microsecs_t SystemTimeSource::getCurrentTime() { 
    45     return GetMicroSeconds(); 
     45    struct timeval tv; 
     46    gettimeofday(&tv, NULL); 
     47    return tv.tv_sec * 1000000ULL + tv.tv_usec; 
     48     
     49//     return GetMicroSeconds(); 
    4650} 
    4751 
  • branches/streaming-rework/src/libutil/SystemTimeSource.h

    r360 r384  
    4646    freebob_microsecs_t getCurrentTime(); 
    4747    freebob_microsecs_t getCurrentTimeAsUsecs(); 
     48    inline freebob_microsecs_t unWrapTime(freebob_microsecs_t t) {return t;}; 
     49    inline freebob_microsecs_t wrapTime(freebob_microsecs_t t) {return t;}; 
    4850 
    4951protected: 
  • branches/streaming-rework/src/libutil/Time.h

    r360 r384  
    7272        struct timespec ts; 
    7373        clock_gettime(CLOCK_MONOTONIC, &ts); 
    74         return (freebob_microsecs_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; 
     74        return (freebob_microsecs_t)ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; 
    7575    } 
    7676#endif 
  • branches/streaming-rework/src/libutil/TimeSource.cpp

    r360 r384  
    3030#include "TimeSource.h" 
    3131 
     32#include <time.h> 
     33 
     34#include <assert.h> 
     35 
    3236#include "libutil/Time.h" 
    3337 
    3438namespace FreebobUtil { 
    3539 
    36 TimeSource::TimeSource() { 
     40IMPL_DEBUG_MODULE( TimeSource, TimeSource, DEBUG_LEVEL_NORMAL ); 
     41 
     42TimeSource::TimeSource() : 
     43    m_Master(NULL), m_last_master_time(0), m_last_time(0), 
     44    m_slave_rate(0.0), m_slave_offset(0), m_last_err(0.0) 
     45
    3746 
    3847} 
     
    4150 
    4251} 
     52/** 
     53 * (re)Initializes the TimeSource 
     54 * 
     55 * @return true if successful 
     56 */ 
     57void TimeSource::initSlaveTimeSource() { 
     58    freebob_microsecs_t my_time; 
     59    freebob_microsecs_t master_time; 
     60    freebob_microsecs_t my_time2; 
     61    freebob_microsecs_t master_time2; 
     62     
     63    if (m_Master) { 
     64        my_time=getCurrentTime(); 
     65        master_time=m_Master->getCurrentTime(); 
     66         
     67        struct timespec ts; 
     68         
     69        // sleep for ten milliseconds 
     70        ts.tv_sec=0; 
     71        ts.tv_nsec=10000000L; 
     72         
     73        nanosleep(&ts,NULL); 
     74         
     75        my_time2=getCurrentTime(); 
     76        master_time2=m_Master->getCurrentTime(); 
     77         
     78        float diff_slave=my_time2-my_time; 
     79        float diff_master=master_time2-master_time; 
     80         
     81        m_slave_rate=diff_slave/diff_master; 
     82         
     83        // average of the two offset estimates 
     84        m_slave_offset  = my_time-wrapTime((freebob_microsecs_t)(master_time*m_slave_rate)); 
     85        m_slave_offset += my_time2-wrapTime((freebob_microsecs_t)(master_time2*m_slave_rate)); 
     86        m_slave_offset /= 2; 
     87         
     88        m_last_master_time=master_time2; 
     89        m_last_time=my_time2; 
     90 
     91        debugOutput(DEBUG_LEVEL_NORMAL,"init slave: master=%lu, master2=%lu, diff=%f\n", 
     92            master_time, master_time2, diff_master); 
     93        debugOutput(DEBUG_LEVEL_NORMAL,"init slave: slave =%lu, slave2 =%lu, diff=%f\n", 
     94            my_time, my_time2, diff_slave); 
     95        debugOutput(DEBUG_LEVEL_NORMAL,"init slave: slave rate=%f, slave_offset=%lu\n", 
     96            m_slave_rate, m_slave_offset 
     97            );                 
     98    } 
     99     
     100 
     101} 
     102 
     103/** 
     104 * Maps a time point of the master to a time point  
     105 * on it's own timeline 
     106 * 
     107 * @return the mapped time point 
     108 */ 
     109freebob_microsecs_t TimeSource::mapMasterTime(freebob_microsecs_t master_time) { 
     110    if(m_Master) { 
     111        // calculate the slave based upon the master 
     112        // and the estimated rate 
     113         
     114        // linear interpolation 
     115        int delta_master=master_time-m_last_master_time; 
     116     
     117        float offset=m_slave_rate * ((float)delta_master); 
     118         
     119        freebob_microsecs_t mapped=m_last_time+(int)offset; 
     120         
     121        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"map time: master=%d, offset=%f, slave_base=%lu, pred_ticks=%lu\n", 
     122            master_time, offset, m_last_time,mapped 
     123            ); 
     124         
     125        return wrapTime(mapped); 
     126         
     127    } else { 
     128        debugOutput( DEBUG_LEVEL_VERBOSE, "Requested map for non-slave TimeSource\n"); 
     129         
     130        return master_time; 
     131    } 
     132} 
     133 
     134/** 
     135 * Update the internal state of the TimeSource 
     136 * 
     137 */ 
     138bool TimeSource::updateTimeSource() { 
     139    // update all slaves 
     140    for ( TimeSourceVectorIterator it = m_Slaves.begin(); 
     141          it != m_Slaves.end(); ++it ) { 
     142           
     143        // update the slave with the current  
     144        // master time 
     145        if (!(*it)->updateTimeSource()) return false; 
     146    } 
     147     
     148    // this TimeSource has a master 
     149    if(m_Master) { 
     150        freebob_microsecs_t my_time=getCurrentTime(); 
     151        freebob_microsecs_t master_time=m_Master->getCurrentTime(); 
     152     
     153        // we assume that the master and slave time are  
     154        // measured at the same time, but that of course is 
     155        // not really true. The DLL will have to filter this 
     156        // out. 
     157         
     158        // the difference in master time 
     159        int64_t delta_master; 
     160        if (master_time > m_last_master_time) { 
     161            delta_master=master_time-m_last_master_time; 
     162        } else { // wraparound 
     163            delta_master=m_Master->unWrapTime(master_time)-m_last_master_time; 
     164        } 
     165         
     166        // the difference in slave time 
     167        int64_t delta_slave; 
     168        if (my_time > m_last_time) { 
     169            delta_slave=my_time-m_last_time; 
     170        } else { // wraparound 
     171            delta_slave=unWrapTime(my_time)-m_last_time; 
     172        } 
     173         
     174        // the estimated slave difference 
     175        int delta_slave_est=(int)(m_slave_rate * ((double)delta_master)); 
     176         
     177        // the measured & estimated rate 
     178        double rate_meas=((double)delta_slave/(double)delta_master); 
     179        double rate_est=((double)m_slave_rate); 
     180         
     181        m_last_err=(rate_meas-rate_est); 
     182         
     183        m_slave_rate += 0.01*m_last_err; 
     184         
     185        debugOutput(DEBUG_LEVEL_VERBOSE,"update slave: master=%llu, master2=%llu, diff=%lld\n", 
     186            master_time, m_last_master_time, delta_master); 
     187        debugOutput(DEBUG_LEVEL_VERBOSE,"update slave: slave =%llu, slave2 =%llu, diff=%lld, diff_est=%d\n", 
     188            my_time, m_last_time, delta_slave, delta_slave_est); 
     189        debugOutput(DEBUG_LEVEL_VERBOSE,"update slave: slave rate meas=%f, slave rate est=%f, err=%f, slave rate=%f\n", 
     190            rate_meas, rate_est, m_last_err, m_slave_rate 
     191            ); 
     192 
     193         
     194        m_last_master_time=master_time; 
     195         
     196        int64_t tmp = delta_slave_est; 
     197        tmp += m_last_time; 
     198         
     199        m_last_time = tmp; 
     200         
     201 
     202             
     203    } 
     204 
     205    return true; 
     206} 
     207 
     208/** 
     209 * Sets the master TimeSource for this timesource. 
     210 * This TimeSource will sync to the master TimeSource, 
     211 * making that it will be able to map a time point of  
     212 * the master to a time point on it's own timeline 
     213 * 
     214 * @param ts master TimeSource   
     215 * @return true if successful 
     216 */ 
     217bool TimeSource::setMaster(TimeSource *ts) { 
     218    if (m_Master==NULL) { 
     219        m_Master=ts; 
     220         
     221        // initialize ourselves. 
     222        initSlaveTimeSource(); 
     223         
     224        return true; 
     225    } else return false; 
     226} 
     227 
     228/** 
     229 * Clears the master TimeSource for this timesource. 
     230 * 
     231 * @return true if successful 
     232 */ 
     233void TimeSource::clearMaster() { 
     234    m_Master=NULL; 
     235} 
     236 
     237/** 
     238 * Registers a slave timesource to this master. 
     239 * A slave TimeSource will sync to this TimeSource, 
     240 * making that it will be able to map a time point of  
     241 * the master (this) TimeSource to a time point on  
     242 * it's own timeline 
     243 * 
     244 * @param ts slave TimeSource to register 
     245 * @return true if successful 
     246 */ 
     247bool TimeSource::registerSlave(TimeSource *ts) { 
     248    // TODO: we should check for circular master-slave relationships. 
     249     
     250    debugOutput( DEBUG_LEVEL_VERBOSE, "Registering slave (%p)\n", ts); 
     251    assert(ts); 
     252     
     253    // inherit debug level 
     254    ts->setVerboseLevel(getDebugLevel());  
     255     
     256    if(ts->setMaster(this)) { 
     257        m_Slaves.push_back(ts); 
     258        return true; 
     259    } else { 
     260        return false; 
     261    } 
     262} 
     263 
     264/** 
     265 * Unregisters a slave TimeSource 
     266 * 
     267 * @param ts slave TimeSource to unregister 
     268 * @return true if successful 
     269 */ 
     270bool TimeSource::unregisterSlave(TimeSource *ts) { 
     271    debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering TimeSource (%p)\n", ts); 
     272    assert(ts); 
     273 
     274    for ( TimeSourceVectorIterator it = m_Slaves.begin(); 
     275          it != m_Slaves.end(); ++it ) { 
     276 
     277        if ( *it == ts ) {  
     278            m_Slaves.erase(it); 
     279            ts->clearMaster(); 
     280            return true; 
     281        } 
     282    } 
     283     
     284    debugOutput( DEBUG_LEVEL_VERBOSE, " TimeSource (%p) not found\n", ts); 
     285     
     286    return false; 
     287} 
     288 
     289/** 
     290 * Set verbosity level. 
     291 * All slave timesources get the same verbosity level 
     292 * 
     293 * @param l verbosity level 
     294 */ 
     295void TimeSource::setVerboseLevel(int l) { 
     296    setDebugLevel(l); 
     297 
     298    for ( TimeSourceVectorIterator it = m_Slaves.begin(); 
     299          it != m_Slaves.end(); ++it ) { 
     300         
     301        (*it)->setVerboseLevel(l); 
     302    } 
     303 
     304} 
     305 
     306void TimeSource::printTimeSourceInfo() { 
     307    debugOutputShort( DEBUG_LEVEL_NORMAL, "TimeSource (%p) info\n", this); 
     308    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Master           : %p\n", m_Master); 
     309    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Slave rate       : %f\n", m_slave_rate); 
     310    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Slave offset     : %lld\n", m_slave_offset); 
     311    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Last error       : %f\n", m_last_err); 
     312    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Last master time : %llu\n",m_last_master_time ); 
     313    debugOutputShort( DEBUG_LEVEL_NORMAL, "  Last slave time  : %llu\n",m_last_time ); 
     314 
     315    
     316    for ( TimeSourceVectorIterator it = m_Slaves.begin(); 
     317          it != m_Slaves.end(); ++it ) { 
     318         
     319        (*it)->printTimeSourceInfo(); 
     320    } 
     321} 
    43322 
    44323} // end of namespace FreebobUtil 
  • branches/streaming-rework/src/libutil/TimeSource.h

    r383 r384  
    3131#include "../debugmodule/debugmodule.h" 
    3232 
     33#include <vector> 
     34 
    3335typedef uint64_t freebob_microsecs_t; 
    3436 
    3537namespace FreebobUtil { 
    3638 
     39class TimeSource; 
     40typedef std::vector<TimeSource *> TimeSourceVector; 
     41typedef std::vector<TimeSource *>::iterator TimeSourceVectorIterator; 
     42 
     43/*! 
     44\brief The base class for all TimeSource's. 
     45 
     46    Any object that can act as a source of timing  
     47    information should subclass this class and implement 
     48    its virtual functions. 
     49     
     50    A TimeSource can be slaved to another TimeSource, allowing 
     51    the mapping of the master's time to the slave's time. 
     52*/ 
    3753class TimeSource { 
    3854 
     
    4460    virtual freebob_microsecs_t getCurrentTime()=0; 
    4561    virtual freebob_microsecs_t getCurrentTimeAsUsecs()=0; 
     62    virtual freebob_microsecs_t unWrapTime(freebob_microsecs_t t)=0; 
     63    virtual freebob_microsecs_t wrapTime(freebob_microsecs_t t)=0; 
     64     
     65    freebob_microsecs_t mapMasterTime(freebob_microsecs_t t); 
     66     
     67    bool updateTimeSource(); 
     68     
     69    bool registerSlave(TimeSource *ts); 
     70    bool unregisterSlave(TimeSource *ts); 
     71 
     72    virtual void setVerboseLevel(int l); 
     73     
     74    virtual void printTimeSourceInfo(); 
    4675     
    4776protected: 
     77 
     78private: 
     79    bool setMaster(TimeSource *ts); 
     80    void clearMaster(); 
     81     
     82    void initSlaveTimeSource(); 
     83     
     84    TimeSource * m_Master; 
     85    TimeSourceVector m_Slaves; 
     86     
     87    freebob_microsecs_t m_last_master_time; 
     88    freebob_microsecs_t m_last_time; 
     89     
     90    double m_slave_rate; 
     91    int64_t m_slave_offset; 
     92    double m_last_err; 
     93     
     94    DECLARE_DEBUG_MODULE; 
    4895 
    4996}; 
  • branches/streaming-rework/src/Makefile.am

    r383 r384  
    2727libfreebob_la_LIBADD = -lrt 
    2828 
    29 noinst_HEADERS =                                        \ 
    30         configrom.h                                     \ 
    31         csr1212.h                                       \ 
    32         devicemanager.h                                 \ 
    33         fbtypes.h                                       \ 
    34         bounce/bounce_avdevice.h                        \ 
    35         motu/motu_avdevice.h                            \ 
    36         rme/rme_avdevice.h 
     29noinst_HEADERS = configrom.h csr1212.h debugmodule/debugmodule.h \ 
     30        devicemanager.h fbtypes.h iavdevice.h threads.h bebob/bebob_avdevice.h \ 
     31        bebob/bebob_avdevice_subunit.h bebob/bebob_avplug.h bebob/bebob_dl_bcd.h bebob/bebob_dl_codes.h \ 
     32        bebob/bebob_dl_mgr.h bebob/bebob_functionblock.h bounce/bounce_avdevice.h \ 
     33        maudio/maudio_avdevice.h motu/motu_avdevice.h rme/rme_avdevice.h libfreebobavc/avc_connect.h \ 
     34        libfreebobavc/avc_definitions.h libfreebobavc/avc_extended_cmd_generic.h \ 
     35        libfreebobavc/avc_extended_plug_info.h libfreebobavc/avc_extended_stream_format.h \ 
     36        libfreebobavc/avc_extended_subunit_info.h libfreebobavc/avc_function_block.h libfreebobavc/avc_generic.h \ 
     37        libfreebobavc/avc_plug_info.h libfreebobavc/avc_serialize.h libfreebobavc/avc_signal_source.h \ 
     38        libfreebobavc/avc_subunit_info.h libfreebobavc/avc_unit_info.h libfreebobavc/ieee1394service.h \ 
     39        libstreaming/AmdtpPort.h libstreaming/AmdtpPortInfo.h libstreaming/AmdtpStreamProcessor.h \ 
     40        libstreaming/cip.h libstreaming/cycletimer.h libstreaming/IsoHandler.h \ 
     41        libstreaming/IsoHandlerManager.h libstreaming/IsoStream.h libstreaming/MotuPort.h \ 
     42        libstreaming/MotuPortInfo.h libstreaming/MotuStreamProcessor.h libstreaming/PacketBuffer.h \ 
     43        libstreaming/Port.h libstreaming/PortManager.h libstreaming/ringbuffer.h \ 
     44        libstreaming/StreamProcessor.h libstreaming/StreamProcessorManager.h libstreaming/streamstatistics.h \ 
     45        libutil/Atomic.h libutil/cycles.h libutil/DelayLockedLoop.h libutil/PosixThread.h \ 
     46        libutil/serialize.h libutil/SystemTimeSource.h libutil/Thread.h libutil/Time.h \ 
     47        libutil/TimeSource.h 
    3748 
    3849libfreebob_la_SOURCES = \ 
    39         iavdevice.h                                     \ 
    4050        configrom.cpp \ 
    4151        csr1212.c \ 
     
    4353        freebob.cpp \ 
    4454        xmlparser.c \ 
    45         threads.h                                       \ 
    46         bebob/bebob_avdevice.h                          \ 
    4755        bebob/bebob_avdevice.cpp \ 
    48         bebob/bebob_avdevice_xml.cpp                    \ 
    49         bebob/bebob_avdevice_subunit.h                  \ 
    5056        bebob/bebob_avdevice_subunit.cpp \ 
    51        bebob/bebob_avplug.h                           
     57        bebob/bebob_avdevice_xml.cpp
    5258        bebob/bebob_avplug.cpp \ 
    5359        bebob/bebob_avplug_xml.cpp \ 
    54         bebob/bebob_functionblock.h                     \ 
    55         bebob/bebob_functionblock.cpp                   \ 
    56         bebob/bebob_dl_mgr.h                            \ 
    57         bebob/bebob_dl_mgr.cpp                          \ 
    58         bebob/bebob_dl_codes.h                          \ 
    59         bebob/bebob_dl_codes.cpp                        \ 
    60         bebob/bebob_dl_bcd.h                            \ 
    6160        bebob/bebob_dl_bcd.cpp \ 
    62         motu/motu_avdevice.cpp                          \ 
    63         motu/motu_avdevice.h                            \ 
    64         rme/rme_avdevice.cpp                            \ 
    65         rme/rme_avdevice.h                              \ 
    66         bounce/bounce_avdevice.h                        \ 
     61        bebob/bebob_dl_codes.cpp \ 
     62        bebob/bebob_dl_mgr.cpp \ 
     63        bebob/bebob_functionblock.cpp \ 
    6764        bounce/bounce_avdevice.cpp \ 
    68         maudio/maudio_avdevice.h                        \ 
    6965        maudio/maudio_avdevice.cpp \ 
     66        motu/motu_avdevice.cpp \ 
     67        rme/rme_avdevice.cpp \ 
     68        debugmodule/debugmodule.cpp \ 
    7069        libfreebobavc/avc_connect.cpp \ 
    7170        libfreebobavc/avc_definitions.cpp \ 
     
    7574        libfreebobavc/avc_extended_subunit_info.cpp \ 
    7675        libfreebobavc/avc_function_block.cpp \ 
    77         libfreebobavc/avc_function_block.h              \ 
    7876        libfreebobavc/avc_generic.cpp \ 
    7977        libfreebobavc/avc_plug_info.cpp \ 
     78        libfreebobavc/avc_serialize.cpp \ 
    8079        libfreebobavc/avc_signal_source.cpp \ 
    8180        libfreebobavc/avc_subunit_info.cpp \ 
    8281        libfreebobavc/avc_unit_info.cpp \ 
    8382        libfreebobavc/ieee1394service.cpp \ 
    84         libfreebobavc/avc_serialize.cpp                 \ 
    85         libfreebobavc/avc_connect.h                     \ 
    86         libfreebobavc/avc_definitions.h                 \ 
    87         libfreebobavc/avc_extended_cmd_generic.h        \ 
    88         libfreebobavc/avc_extended_plug_info.h          \ 
    89         libfreebobavc/avc_extended_stream_format.h      \ 
    90         libfreebobavc/avc_extended_subunit_info.h       \ 
    91         libfreebobavc/avc_generic.h                     \ 
    92         libfreebobavc/avc_plug_info.h                   \ 
    93         libfreebobavc/avc_signal_source.h               \ 
    94         libfreebobavc/avc_subunit_info.h                \ 
    95         libfreebobavc/avc_unit_info.h                   \ 
    96         libfreebobavc/ieee1394service.h                 \ 
    97         libfreebobavc/avc_serialize.h                   \ 
    98         debugmodule/debugmodule.h                       \ 
    99         debugmodule/debugmodule.cpp                     \ 
     83        libstreaming/AmdtpPort.cpp \ 
     84        libstreaming/AmdtpPortInfo.cpp \ 
     85        libstreaming/AmdtpStreamProcessor.cpp \ 
    10086        libstreaming/cip.c \ 
    101         libstreaming/cyclecounter.h                     \ 
    10287        libstreaming/freebob_streaming.cpp \ 
    10388        libstreaming/IsoHandler.cpp \ 
    10489        libstreaming/IsoHandlerManager.cpp \ 
    10590        libstreaming/IsoStream.cpp \ 
     91        libstreaming/MotuPort.cpp \ 
     92        libstreaming/MotuPortInfo.cpp \ 
     93        libstreaming/MotuStreamProcessor.cpp \ 
    10694        libstreaming/PacketBuffer.cpp \ 
    107         libstreaming/PortManager.cpp                    \ 
    10895        libstreaming/Port.cpp \ 
     96        libstreaming/PortManager.cpp \ 
     97        libstreaming/ringbuffer.c \ 
    10998        libstreaming/StreamProcessor.cpp \ 
    11099        libstreaming/StreamProcessorManager.cpp \ 
    111         libstreaming/AmdtpPortInfo.cpp                  \ 
    112         libstreaming/AmdtpPort.cpp                      \ 
    113         libstreaming/AmdtpStreamProcessor.cpp           \ 
    114         libstreaming/ringbuffer.c                       \ 
    115100        libstreaming/streamstatistics.cpp \ 
    116         libstreaming/MotuStreamProcessor.cpp            \ 
    117         libstreaming/MotuPort.cpp                       \ 
    118         libstreaming/MotuPortInfo.cpp                   \ 
    119         libutil/DelayLockedLoop.h                       \ 
    120         libutil/Atomic.h                                \ 
    121         libutil/PosixThread.h                           \ 
    122         libutil/Thread.h                                \ 
    123101        libutil/DelayLockedLoop.cpp \ 
    124102        libutil/PosixThread.cpp \ 
    125         libutil/Time.c                                  \ 
    126         libutil/Time.h                                  \ 
    127         libutil/TimeSource.cpp                          \ 
    128         libutil/TimeSource.h                            \ 
     103        libutil/serialize.cpp \ 
    129104        libutil/SystemTimeSource.cpp \ 
    130         libutil/SystemTimeSource.h                      \ 
    131         libutil/cycles.h                                \ 
    132         libutil/serialize.h                             \ 
    133         libutil/serialize.cpp 
    134  
     105        libutil/Time.c \ 
     106        libutil/TimeSource.cpp 
    135107 
    136108libfreebob_la_LDFLAGS =                                 \ 
  • branches/streaming-rework/src/motu/motu_avdevice.cpp

    r374 r384  
    1919 * MA 02111-1307 USA. 
    2020 */ 
     21 
     22#ifdef ENABLE_MOTU 
    2123 
    2224#include "motu/motu_avdevice.h" 
     
    937939 
    938940} 
     941#endif // ENABLE_MOTU 
  • branches/streaming-rework/src/motu/motu_avdevice.h

    r336 r384  
    1919 * MA 02111-1307 USA. 
    2020 */ 
     21 
     22#ifdef ENABLE_MOTU 
    2123 
    2224#ifndef MOTUDEVICE_H 
     
    161163 
    162164#endif 
     165 
     166#endif // ENABLE_MOTU 
  • branches/streaming-rework/tests/Makefile.am

    r360 r384  
    2222 
    2323noinst_PROGRAMS = test-freebob test-extplugcmd test-fw410 freebob-server \ 
    24                 test-volume test-mixer test-cyclecounter test-sytmonitor 
     24                test-volume test-mixer test-cycletimer test-sytmonitor 
    2525 
    2626noinst_HEADERS =  
     
    5353TEST = test-freebob 
    5454 
    55 test_cyclecounter_LDADD = $(top_builddir)/src/libfreebob.la $(LIBIEC61883_LIBS) \ 
     55test_cycletimer_LDADD = $(top_builddir)/src/libfreebob.la $(LIBIEC61883_LIBS) \ 
    5656        $(LIBRAW1394_LIBS) $(LIBAVC1394_LIBS) 
    57 test_cyclecounter_SOURCES = test-cyclecounter.cpp 
     57test_cycletimer_SOURCES = test-cycletimer.cpp 
    5858 
    5959test_sytmonitor_LDADD = $(top_builddir)/src/libfreebob.la $(LIBIEC61883_LIBS) \ 
  • branches/streaming-rework/tests/SytMonitor.cpp

    r360 r384  
    6464        m_port,channel, 
    6565        cycle,syt_timestamp, 
    66         CYCLE_COUNTER_GET_SECS(syt_timestamp),  
    67         CYCLE_COUNTER_GET_CYCLES(syt_timestamp),  
    68         CYCLE_COUNTER_GET_OFFSET(syt_timestamp) 
     66        CYCLE_TIMER_GET_SECS(syt_timestamp),  
     67        CYCLE_TIMER_GET_CYCLES(syt_timestamp),  
     68        CYCLE_TIMER_GET_OFFSET(syt_timestamp) 
    6969         
    7070        ); 
    7171     
    7272    // reconstruct the full cycle 
    73     unsigned int cc_ticks=m_handler->getCycleCounter(); 
    74     unsigned int cc_cycles=TICKS_TO_CYCLES(cc_ticks); 
     73    unsigned int cc=m_handler->getCycleTimer(); 
     74    unsigned int cc_ticks=CYCLE_TIMER_TO_TICKS(cc); 
    7575     
    76     unsigned int cc_seconds=TICKS_TO_SECS(cc_ticks); 
     76    unsigned int cc_cycles=CYCLE_TIMER_GET_CYCLES(cc); 
    7777     
    78     // the cyclecounter has wrapped since this packet was received 
     78    unsigned int cc_seconds=CYCLE_TIMER_GET_SECS(cc); 
     79     
     80     
     81    // the cycletimer has wrapped since this packet was received 
    7982    // we want cc_seconds to reflect the 'seconds' at the point this  
    8083    // was received 
     
    8386     // reconstruct the top part of the timestamp using the current cycle number 
    8487    unsigned int now_cycle_masked=cycle & 0xF; 
    85     unsigned int syt_cycle=CYCLE_COUNTER_GET_CYCLES(syt_timestamp); 
     88    unsigned int syt_cycle=CYCLE_TIMER_GET_CYCLES(syt_timestamp); 
    8689     
    8790    // if this is true, wraparound has occurred, undo this wraparound 
     
    9598    unsigned int new_cycles=cycle + delta_cycles; 
    9699     
    97     // if the cycles cause a wraparound of the cycle counter, 
     100    // if the cycles cause a wraparound of the cycle timer, 
    98101    // perform this wraparound 
    99102    if(new_cycles>7999) { 
     
    113116     
    114117    // and the seconds part 
    115     // if the timestamp causes a wraparound of the cycle counter, 
     118    // if the timestamp causes a wraparound of the cycle timer, 
    116119    // the timestamp lies in the next second 
    117120    // if it didn't, the timestamp lies in this second 
     
    130133     
    131134    // now we reconstruct the presentation time 
    132     cif.pres_seconds = CYCLE_COUNTER_GET_SECS(m_full_timestamp); 
    133     cif.pres_cycle   = CYCLE_COUNTER_GET_CYCLES(m_full_timestamp); 
    134     cif.pres_offset  = CYCLE_COUNTER_GET_OFFSET(m_full_timestamp); 
    135     cif.pres_ticks   = CYCLE_COUNTER_TO_TICKS(m_full_timestamp); 
     135    cif.pres_seconds = CYCLE_TIMER_GET_SECS(m_full_timestamp); 
     136    cif.pres_cycle   = CYCLE_TIMER_GET_CYCLES(m_full_timestamp); 
     137    cif.pres_offset  = CYCLE_TIMER_GET_OFFSET(m_full_timestamp); 
     138    cif.pres_ticks   = CYCLE_TIMER_TO_TICKS(m_full_timestamp); 
    136139     
    137140    if (wraparound_occurred) { 
  • branches/streaming-rework/tests/SytMonitor.h

    r360 r384  
    3030#include "src/libstreaming/IsoStream.h" 
    3131#include "src/libstreaming/cip.h" 
    32 #include "src/libstreaming/cyclecounter.h" 
     32#include "src/libstreaming/cycletimer.h" 
    3333#include "src/libstreaming/ringbuffer.h" 
    3434 
     
    4343    unsigned int pres_cycle; 
    4444    unsigned int pres_offset; 
    45     unsigned int pres_ticks; 
     45    uint64_t    pres_ticks; 
    4646}; 
    4747 
     
    6666        bool putCycleInfo(struct cycle_info *cif); 
    6767         
     68        IsoHandler * getHandler() {return m_handler;}; 
     69         
    6870        protected: 
    6971           freebob_ringbuffer_t * m_cinfo_buffer; 
  • branches/streaming-rework/tests/test-cycletimer.cpp

    r383 r384  
    3232#include <netinet/in.h> 
    3333 
    34 #include "src/libstreaming/cyclecounter.h" 
     34#include "src/libstreaming/cycletimer.h" 
    3535 
    3636#include "src/libstreaming/IsoHandler.h" 
     
    4747 
    4848DECLARE_GLOBAL_DEBUG_MODULE; 
    49 IMPL_GLOBAL_DEBUG_MODULE( FreeBoB, DEBUG_LEVEL_VERBOSE ); 
    5049 
    5150int run; 
     
    7776} 
    7877 
    79 int do_cyclecounter_test() { 
    80      
    81     struct CYCLE_TIMER_REGISTER cycle_counter; 
    82     uint32_t *cycle_counter_as_uint=(uint32_t *)&cycle_counter; 
     78int do_cycletimer_test() { 
     79     
     80    struct CYCLE_TIMER_REGISTER cycle_timer; 
     81    uint32_t *cycle_timer_as_uint=(uint32_t *)&cycle_timer; 
    8382     
    8483    uint32_t i=0; 
     
    9190    //  
    9291     
    93     *cycle_counter_as_uint=0; 
     92    *cycle_timer_as_uint=0; 
    9493    for (i=0;i<3072;i++) { 
    95         cycle_counter.offset=i; 
    96         targetval=CYCLE_COUNTER_GET_OFFSET(ctr_to_quadlet(cycle_counter)); 
     94        cycle_timer.offset=i; 
     95        targetval=CYCLE_TIMER_GET_OFFSET(ctr_to_quadlet(cycle_timer)); 
    9796         
    9897        if(targetval != i) { 
     
    103102     
    104103    for (i=0;i<8000;i++) { 
    105         cycle_counter.cycles=i; 
    106         targetval=CYCLE_COUNTER_GET_CYCLES(ctr_to_quadlet(cycle_counter)); 
     104        cycle_timer.cycles=i; 
     105        targetval=CYCLE_TIMER_GET_CYCLES(ctr_to_quadlet(cycle_timer)); 
    107106         
    108107        if(targetval != i) { 
     
    113112     
    114113    for (i=0;i<128;i++) { 
    115         cycle_counter.seconds=i; 
    116         targetval=CYCLE_COUNTER_GET_SECS(ctr_to_quadlet(cycle_counter)); 
     114        cycle_timer.seconds=i; 
     115        targetval=CYCLE_TIMER_GET_SECS(ctr_to_quadlet(cycle_timer)); 
    117116         
    118117        if(targetval != i) { 
     
    123122     
    124123     
     124    // a value in ticks 
     125    // should be: 10sec, 1380cy, 640ticks 
     126    targetval=250000000L; 
     127    cycle_timer.seconds = TICKS_TO_SECS(targetval); 
     128    cycle_timer.cycles  = TICKS_TO_CYCLES(targetval); 
     129    cycle_timer.offset  = TICKS_TO_OFFSET(targetval); 
     130     
     131    if((cycle_timer.seconds != 10) | 
     132        (cycle_timer.cycles != 1380) | 
     133        (cycle_timer.offset != 640)) 
     134        { 
     135        debugOutput(DEBUG_LEVEL_NORMAL, "  test4 failed: (%u,10)sec (%u,1380)cy (%u,640)ticks\n", 
     136            cycle_timer.seconds,cycle_timer.cycles,cycle_timer.offset); 
     137        failures++; 
     138    } else { 
     139         debugOutput(DEBUG_LEVEL_NORMAL, "  test4 ok\n"); 
     140    } 
     141     
     142    i=TICKS_TO_CYCLE_TIMER(targetval); 
     143    if (i != 0x14564280) { 
     144         debugOutput(DEBUG_LEVEL_NORMAL, "  test5 failed: (0x%08X,0x14564280)\n", 
     145            i); 
     146        failures++;    
     147    } else { 
     148         debugOutput(DEBUG_LEVEL_NORMAL, "  test5 ok\n"); 
     149    } 
     150     
     151    targetval=CYCLE_TIMER_TO_TICKS(i); 
     152    if (targetval!=250000000L) { 
     153         debugOutput(DEBUG_LEVEL_NORMAL, "  test6 failed: (%u,250000000)\n", 
     154            targetval); 
     155        failures++;    
     156    } else { 
     157         debugOutput(DEBUG_LEVEL_NORMAL, "  test6 ok\n"); 
     158    } 
    125159     
    126160    if (failures) { 
     
    154188        signal (SIGPIPE, sighandler); 
    155189 
    156         debugOutput(DEBUG_LEVEL_NORMAL, "Freebob Cycle counter test application\n"); 
    157          
    158         debugOutput(DEBUG_LEVEL_NORMAL, "Testing cycle counter helper functions & macro's... \n"); 
    159         if(do_cyclecounter_test()) { 
     190        debugOutput(DEBUG_LEVEL_NORMAL, "Freebob Cycle timer test application\n"); 
     191         
     192        debugOutput(DEBUG_LEVEL_NORMAL, "Testing cycle timer helper functions & macro's... \n"); 
     193        if(do_cycletimer_test()) { 
    160194           debugOutput(DEBUG_LEVEL_NORMAL, " !!! FAILED !!!\n"); 
    161195           exit(1); 
     
    319353        debugOutput(DEBUG_LEVEL_NORMAL, "Bye...\n"); 
    320354 
    321     delete DebugModuleManager::instance(); 
    322          
    323355  return EXIT_SUCCESS; 
    324356} 
  • branches/streaming-rework/tests/test-sytmonitor.cpp

    r383 r384  
    3333#include <netinet/in.h> 
    3434 
    35 #include "src/libstreaming/cyclecounter.h" 
     35#include "src/libstreaming/cycletimer.h" 
    3636 
    3737#include "src/libstreaming/IsoHandlerManager.h" 
     
    3939 
    4040#include "src/libutil/PosixThread.h" 
     41#include "src/libutil/SystemTimeSource.h" 
    4142 
    4243#include "pthread.h" 
     
    4546using namespace FreebobUtil; 
    4647 
     48 
    4749DECLARE_GLOBAL_DEBUG_MODULE; 
    48 IMPL_GLOBAL_DEBUG_MODULE( FreeBoB, DEBUG_LEVEL_VERBOSE ); 
    4950 
    5051int run; 
     
    159160int main(int argc, char *argv[]) 
    160161{ 
    161         int target_port=0; 
    162         int target_channel_1=0; 
    163         int target_channel_2=0; 
    164162    bool run_realtime=false; 
    165163    int realtime_prio=20; 
     
    167165    int i; 
    168166    struct sched_param params; 
     167    uint64_t last_print_time=0; 
     168     
     169    SystemTimeSource masterTimeSource; 
    169170     
    170171    IsoHandlerManager *m_isoManager=NULL; 
     
    172173     
    173174    SytMonitor *monitors[128]; 
    174     int stream_offset_ticks[128]; 
     175    int64_t stream_offset_ticks[128]; 
    175176     
    176177    struct arguments arguments; 
     
    245246             
    246247            if(!m_isoManager->registerStream(monitors[i])) { 
    247             debugOutput(DEBUG_LEVEL_NORMAL, "Could not register SytMonitor %d\n", i); 
    248                 goto finish; 
    249             } 
    250     } 
    251              
     248                debugOutput(DEBUG_LEVEL_NORMAL, "Could not register SytMonitor %d with isoManager\n", i); 
     249                goto finish; 
     250            } 
     251             
     252            if (!masterTimeSource.registerSlave(monitors[i]->getHandler())) { 
     253                debugOutput(DEBUG_LEVEL_NORMAL, "Could not register SytMonitor %d's IsoHandler with masterTimeSource\n", i); 
     254                goto finish; 
     255                 
     256            } 
     257        } 
    252258 
    253259        debugOutput(DEBUG_LEVEL_NORMAL,   "Preparing IsoHandlerManager...\n"); 
     
    259265        debugOutput(DEBUG_LEVEL_NORMAL,   "Starting ISO manager sync update thread...\n"); 
    260266 
    261         // start the runner thread 
    262         m_isoManagerThread->Start(); 
    263267 
    264268        debugOutput(DEBUG_LEVEL_NORMAL,   "Starting IsoHandlers...\n"); 
     
    267271                goto finish; 
    268272        } 
     273         
     274        // start the runner thread 
     275        m_isoManagerThread->Start(); 
    269276         
    270277        if (arguments.realtime) { 
     
    278285        // do the actual work 
    279286        nb_iter=0; 
     287         
    280288        while(run) { 
    281289        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"--- Iterate ---\n"); 
    282290         
    283         if(!m_isoManager->iterate()) { 
    284             debugFatal("Could not iterate the isoManager\n"); 
     291//         if(!m_isoManager->iterate()) { 
     292//             debugFatal("Could not iterate the isoManager\n"); 
     293//             return false; 
     294//         } 
     295         
     296        if(!masterTimeSource.updateTimeSource()) { 
     297            debugFatal("Could not update the masterTimeSource\n"); 
    285298            return false; 
    286299        } 
     
    334347                                // detect seconds wraparound 
    335348                                if ((master_cif.pres_seconds==0) && (cif.pres_seconds==127)) { 
    336                                     master_cif.pres_ticks += TICKS_PER_SECOND*128
     349                                    master_cif.pres_ticks += TICKS_PER_SECOND*128LL
    337350                                } 
    338351                                if ((master_cif.pres_seconds==127) && (cif.pres_seconds==0)) { 
    339                                     cif.pres_ticks += TICKS_PER_SECOND*128
     352                                    cif.pres_ticks += TICKS_PER_SECOND*128LL
    340353                                } 
    341354                            // average out the offset 
    342                                 int err=(((long)master_cif.pres_ticks) - ((long)cif.pres_ticks)); 
     355                                int64_t err=(((uint64_t)master_cif.pres_ticks) - ((uint64_t)cif.pres_ticks)); 
    343356                                 
    344357                                err = err - stream_offset_ticks[i]; 
     
    357370                                        "             [%04us %04uc, %04X (%02uc %04ut)]\n", 
    358371                                        master_cif.seconds,master_cif.cycle, 
    359                                         master_cif.syt, CYCLE_COUNTER_GET_CYCLES(master_cif.syt), 
    360                                         CYCLE_COUNTER_GET_OFFSET(master_cif.syt)); 
     372                                        master_cif.syt, CYCLE_TIMER_GET_CYCLES(master_cif.syt), 
     373                                        CYCLE_TIMER_GET_OFFSET(master_cif.syt)); 
    361374                                         
    362375                                    debugOutput(DEBUG_LEVEL_NORMAL, 
     
    368381                                        "             [%04us %04uc, %04X (%02uc %04ut)]\n", 
    369382                                        cif.seconds,cif.cycle, 
    370                                         cif.syt, CYCLE_COUNTER_GET_CYCLES(cif.syt), 
    371                                         CYCLE_COUNTER_GET_OFFSET(cif.syt)); 
     383                                        cif.syt, CYCLE_TIMER_GET_CYCLES(cif.syt), 
     384                                        CYCLE_TIMER_GET_OFFSET(cif.syt)); 
    372385                                    debugOutput(DEBUG_LEVEL_NORMAL,"\n"); 
    373386                                } 
     
    420433         
    421434            // show info every x iterations 
    422         if ((nb_iter++ % 4000)==0) { 
     435            if (masterTimeSource.getCurrentTimeAsUsecs()  
     436                - last_print_time > 1000000L) { 
     437                 
    423438                m_isoManager->dumpInfo(); 
    424439                for (i=0;i<arguments.nb_combos;i++) { 
    425440                    monitors[i]->dumpInfo(); 
    426                 debugOutput(DEBUG_LEVEL_NORMAL,"    ==> Stream offset: %10d ticks\n",stream_offset_ticks[i]); 
     441                    debugOutputShort(DEBUG_LEVEL_NORMAL,"    ==> Stream offset: %10lld ticks (%6.4f ms)\n", 
     442                    stream_offset_ticks[i], (1.0*((double)stream_offset_ticks[i]))/24576.0); 
    427443                } 
    428             } 
     444                masterTimeSource.printTimeSourceInfo(); 
     445                last_print_time=masterTimeSource.getCurrentTimeAsUsecs(); 
     446            } 
     447             
     448            // 125us/packet, so sleep for a while 
     449            usleep(100); 
    429450        } 
    430451 
     
    455476finish: 
    456477        debugOutput(DEBUG_LEVEL_NORMAL, "Bye...\n"); 
    457      delete DebugModuleManager::instance(); 
    458           
     478 
    459479return EXIT_SUCCESS; 
    460480}