Changeset 360 for trunk

Show
Ignore:
Timestamp:
12/30/06 11:49:46 (17 years ago)
Author:
pieterpalmers
Message:

- temporary commit to backup some work

- Started a framework to synchronize IsoHandlers? to

any generic TimeSource?. The idea is to introduce
one overall time reference, and resynchronize all
other timed events to this time source.
This will, on the long run, allow:

  • combining devices on multiple FW busses together,
    as these are not synched by hardware.
  • synchronizing to the system clock
  • synchronizing to any other time source (e.g.
    when implementing a jackd client, i.e. using
    the freebob devices as jackd clients).

- Implemented a realtime safe way to read the cycle

timer for an IsoHandler?. (+ test application)

- Implemented tests/test-sytmonitor:

Monitors 2 or more channels and reports the average
SYT timestamp difference between both.

- Messed around with SYT timestamping for AMDTP. Doesn't

work (yet).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libfreebob/config.h.in

    r358 r360  
    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 
  • trunk/libfreebob/src/bebob/bebob_avdevice.cpp

    r336 r360  
    110110    {0x000a92, 0x00010066},  // Presonous FirePOD 
    111111 
     112    {0x000aac, 0x00000003},  // TerraTec Electronic GmbH, Phase 88 FW  
    112113    {0x000aac, 0x00000004},  // TerraTec Electronic GmbH, Phase X24 FW (model version 4) 
    113114    {0x000aac, 0x00000007},  // TerraTec Electronic GmbH, Phase X24 FW (model version 7) 
  • trunk/libfreebob/src/debugmodule/debugmodule.cpp

    r336 r360  
    5454DebugModule::~DebugModule() 
    5555{ 
     56    cerr << "Unregistering "  
     57         << this->getName() 
     58         << " at DebugModuleManager" 
     59         << endl; 
    5660    if ( !DebugModuleManager::instance()->unregisterModule( *this ) ) { 
    5761        cerr << "Could not unregister DebugModule at DebugModuleManager" 
     
    139143          ++it ) 
    140144    { 
    141         fprintf(stderr,"Cleaning up leftover debug module: %s",(*it)->getName().c_str()); 
     145        fprintf(stderr,"Cleaning up leftover debug module: %s\n",(*it)->getName().c_str()); 
    142146        m_debugModules.erase( it ); 
    143147        delete *it; 
  • trunk/libfreebob/src/libstreaming/AmdtpStreamProcessor.cpp

    r268 r360  
    3131#include "AmdtpPort.h" 
    3232 
     33#include "cyclecounter.h" 
     34 
    3335#include <netinet/in.h> 
    3436#include <assert.h> 
    3537 
    36 #define CYCLE_COUNTER_GET_SECS(x)   (((x & 0xFE000000) >> 25)) 
    37 #define CYCLE_COUNTER_GET_CYCLES(x) (((x & 0x01FFF000) >> 12)) 
    38 #define CYCLE_COUNTER_GET_TICKS(x)  (((x & 0x00000FFF))) 
    39 #define CYCLE_COUNTER_TO_TICKS(x) ((CYCLE_COUNTER_GET_SECS(x)   * 24576000) +\ 
    40                                    (CYCLE_COUNTER_GET_CYCLES(x) *     3072) +\ 
    41                                    (CYCLE_COUNTER_GET_TICKS(x)            )) 
    42  
    43 // this is one milisecond of processing delay 
    44 #define TICKS_PER_SECOND 24576000 
     38#define RECEIVE_PROCESSING_DELAY_IN_SAMPLES 100 
     39#define RECEIVE_DLL_INTEGRATION_COEFFICIENT 0.015 
     40 
    4541#define RECEIVE_PROCESSING_DELAY (TICKS_PER_SECOND * 2/1000) 
    46 #define TRANSMIT_PROCESSING_DELAY RECEIVE_PROCESSING_DELAY 
     42 
     43// in ticks 
     44#define TRANSMIT_TRANSFER_DELAY 10000 
     45 
     46//#define DO_SYT_SYNC 
    4747 
    4848namespace FreebobStreaming { 
     
    5454/* transmit */ 
    5555AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(int port, int framerate, int dimension) 
    56         : TransmitStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0) 
    57         , m_dbc(0) { 
     56        : TransmitStreamProcessor(port, framerate), m_dimension(dimension) 
     57        , m_last_timestamp(0), m_dbc(0), m_ringbuffer_size_frames(0) 
     58        { 
    5859 
    5960 
     
    9596        struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    9697        unsigned int nevents=0; 
    97          
    98         unsigned long in_time=debugGetCurrentTSC(); 
    9998         
    10099    packet->eoh0 = 0; 
     
    171170         
    172171    // FIXME: if m_last_bufferfill > 0 
    173     int ticks_per_frame=syncmaster->getTicksPerFrame()*1024
     172    float ticks_per_frame=syncmaster->getTicksPerFrame()
    174173 
    175174    // m_last_timestamp is the moment upon which the last 'period signal'   
     
    178177    // not from the moment the signal was actually given) 
    179178     
    180     // at a period boundary, we expect nb_buffers * period frames to 
     179    // at a period boundary, we expect m_ringbuffer_size_frames frames to 
    181180    // be in the buffers. 'right after' the transfer(), all of these  
    182181    // frames should be in the xmit buffers (if transfer() finishes  
    183182    // before new packets are received) 
    184183    // therefore the last sample of the xmit buffer lies at  
    185     // T1 = timestamp + (nb_buffers * period) * ticks_per_frame 
    186     int T1 = m_last_timestamp + (m_nb_buffers * m_period) * ticks_per_frame/1024; 
     184    // T1 = timestamp + (m_ringbuffer_size_frames) * ticks_per_frame 
    187185     
    188186    // in reality however life is multithreaded, and we don't know 
     
    192190     
    193191    // this means that the current sample has timestamp 
    194     // T2 = T1 - (nb_frames_in_buffer) * ticks_per_frame 
    195     int buffer_fill=freebob_ringbuffer_read_space(m_event_buffer)/m_dimension/sizeof(quadlet_t); 
    196      
    197     int T2 = T1 - buffer_fill * (ticks_per_frame/1024); 
    198      
    199     // normally:  nb_buffers * period > nb_frames_in_buffer 
    200     // making T2 > timestamp 
    201     // however, this isn't always the case, due to ISO buffering etc. 
    202     // we therefore need to add some extra delay to T2: 
    203     // T3 = T2 + Tiso 
    204     // This Tiso has to cope with the prebuffering that has been done 
    205     // by the ISO layer: e.g. if 100 packets are prebuffered, this 
    206     // callback is executed approximately 100 packets before the  
    207     // actual transmission, hence we have to add 100 * 3072 ticks to 
    208     // the timestamp 
    209     // we know that one packet occurrs every 1/8000 secs, 
    210     // therefore the average nb of samples in a packet is m_framerate/8000 
    211     // making that these 100 packets contain 600 frames, and that 
    212     // we therefore need to advance the timestamp with the equivalent of  
    213     // 600 frames (600*ticks_per_frame) 
    214     int T3 = T2 + (m_handler->getBuffersize() * m_framerate * ticks_per_frame/1024) / 8000; 
    215      
    216     // we then need to add the processing delay for the receiving 
     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 
    217201    // device to this time to determine the xmit timestamp 
    218     // TSTAMP = T3 + PROCESSING_DELAY 
     202    // TSTAMP = T2 + TRANSFER_DELAY 
    219203     
    220204    // we should determine when to 'queue' this sample to 
    221205    // the ISO xmit layer, based upon the cycle parameter 
    222206    // we can define the ideal time at which to send the sample as 
    223     // TSEND = TSTAMP - PROCESSING_DELAY 
    224     // being T3 
    225     // however, this might make things a little too tight, as it can  
    226     // be that we are pre-queueing things. We have to make sure that  
    227     // T3 > timestamp (causality on our side) 
    228     // and that TSTAMP > timestamp (causality on the receiver's side) 
    229      
    230     // so we define TSEND as: 
    231     // TSEND = T3 + Tslack 
    232     // Tslack tbd 
    233      
    234     // note: Tslack=0 packets 
    235     int TSEND = T3; 
    236      
    237     // the xmit timestamp should then be the TSEND + PROCESSING_DELAY 
    238     int timestamp = TSEND + TRANSMIT_PROCESSING_DELAY; 
     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; 
    239215     
    240216    // if we take a look at TSEND we can determine if we are to send 
     
    251227    int cycle_wo_wraparound=cycle; 
    252228     
    253     // arbitrary 
    254     if (cycle_wo_wraparound - (TSEND/3072) < -4000) { 
    255         cycle_wo_wraparound +=8000; 
    256 //         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"wraparound detected: %d %d %d\n",cycle, cycle_wo_wraparound, cycle - (TSEND/3072)); 
     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); 
    257254    } 
    258255   
    259     if (TSEND < cycle_wo_wraparound*3072) { 
     256    if (TSEND_cycle_wo_wraparound < cycle_wo_wraparound) { 
    260257        nevents=m_syt_interval; 
    261258        m_dbc += m_syt_interval; 
    262 #ifdef DEBUG 
    263         if(timestamp<cycle_wo_wraparound*3072) { 
    264             unsigned int tmpsyt_cycles=timestamp/3072; 
    265             unsigned int tmpsyt_ticks=timestamp%3072; 
    266             unsigned int tmpsyt = (tmpsyt_cycles << 12) | tmpsyt_ticks; 
    267          
    268             debugWarning("Timestamp for cycle %d lies %d ticks in the past: %2u cycles + %04u ticks!\n",  
    269                 cycle, cycle_wo_wraparound*3072-timestamp, 
    270                 CYCLE_COUNTER_GET_CYCLES(tmpsyt), 
    271                 CYCLE_COUNTER_GET_TICKS(tmpsyt)); 
    272         } 
    273 #endif 
    274          
     259 
    275260    } else { // no-data 
    276261   
     
    286271                *tag = IEC61883_TAG_WITH_CIP; 
    287272                *sy = 0; 
    288                  
    289         if(packet->dbs) { 
     273 
     274//         if(packet->dbs) { 
    290275//             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
    291276//                 "XMT %04d: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",  
     
    297282//                 *length, 
    298283//                 ((*length / sizeof (quadlet_t)) - 2)/packet->dbs); 
    299         } 
     284//         } 
    300285         
    301286                debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Sending empty packet on cycle %d\n", cycle); 
     
    348333        } 
    349334         
    350          
    351335        // we can forget the seconds for the cycle counter 
    352336        // because we are masking with 0xFFFF 
    353         unsigned int timestamp_cycles=timestamp/3072; 
    354         unsigned int timestamp_ticks=timestamp%3072; 
    355         timestamp_cycles %= 8000; 
    356          
    357         unsigned int timestamp_cyclecounter = (timestamp_cycles << 12) | timestamp_ticks; 
    358          
    359         packet->syt = ntohs(timestamp_cyclecounter & 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); 
    360342         
    361343//         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"XMIT %d EVENTS, SYT %04X for cycle %2d: %08d (%2u cycles + %04u ticks)\n", 
    362 //           nevents, timestamp_cyclecounter & 0xFFFF, cycle, 
    363 //           CYCLE_COUNTER_TO_TICKS(timestamp_cyclecounter), 
    364 //           CYCLE_COUNTER_GET_CYCLES(timestamp_cyclecounter), 
    365 //           CYCLE_COUNTER_GET_TICKS(timestamp_cyclecounter) 
     344//           nevents, timestamp_SYT & 0xFFFF, cycle, timestamp_SYT 
     345//           CYCLE_COUNTER_GET_CYCLES(timestamp_SYT), 
     346//           CYCLE_COUNTER_GET_OFFSET(timestamp_SYT) 
    366347//           ); 
    367348    } 
     
    391372#endif 
    392373 
    393     m_PacketStat.mark(debugGetCurrentTSC()-in_time); 
    394 //     m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    395 //      debugOutput(DEBUG_LEVEL_VERBOSE, "XMIT took: %d\n",debugGetCurrentTSC()-in_time); 
    396374    return retval; 
    397375 
     
    426404    //return (m_framecounter > m_period);  
    427405} 
    428   
     406 
    429407bool AmdtpTransmitStreamProcessor::prefill() { 
    430     int i=m_nb_buffers; 
     408 
     409    if(!transferSilence(m_ringbuffer_size_frames)) { 
     410        debugFatal("Could not prefill transmit stream\n"); 
     411        return false; 
     412    } 
     413 
     414/*    int i=m_nb_buffers; 
    431415    while(i--) { 
    432416        if(!transferSilence(m_period)) { 
     
    438422    // and we should also provide enough prefill for the 
    439423    // SYT processing delay 
    440 //     if(!transferSilence((m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND)) { 
    441 //         debugFatal("Could not prefill transmit stream\n"); 
    442 //         return false; 
    443 //     } 
    444      
     424    if(!transferSilence(RECEIVE_PROCESSING_DELAY_IN_SAMPLES)) { 
     425        debugFatal("Could not prefill transmit stream (2)\n"); 
     426        return false; 
     427    } 
     428*/     
    445429    // the framecounter should be pulled back to 
    446430    // make sure the ISO buffering is used  
     
    538522 
    539523    // allocate the event buffer 
    540     unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
     524    m_ringbuffer_size_frames=m_nb_buffers * m_period; 
    541525     
    542526    // add the processing delay 
    543     ringbuffer_size_frames+=(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND
     527    m_ringbuffer_size_frames+=RECEIVE_PROCESSING_DELAY_IN_SAMPLES
    544528     
    545529    if( !(m_event_buffer=freebob_ringbuffer_create( 
    546             (m_dimension * ringbuffer_size_frames) * sizeof(quadlet_t)))) { 
     530            (m_dimension * m_ringbuffer_size_frames) * sizeof(quadlet_t)))) { 
    547531        debugFatal("Could not allocate memory event ringbuffer"); 
    548532//              return -ENOMEM; 
     
    1005989 
    1006990AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int framerate, int dimension) 
    1007     : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0)
     991    : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0), m_one_period_passed(false)
    1008992 
    1009993 
     
    10531037        // signal that we're running 
    10541038                if(nevents) m_running=true; 
    1055          
    1056         // don't process the stream when it is not enabled. 
     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         
     1047        m_last_timestamp2=m_last_timestamp; 
     1048         
     1049        unsigned int syt_timestamp=ntohs(packet->syt); 
     1050         // reconstruct the top part of the timestamp using the current cycle number 
     1051        unsigned int now_cycle_masked=cycle & 0xF; 
     1052        unsigned int syt_cycle=CYCLE_COUNTER_GET_CYCLES(syt_timestamp); 
     1053         
     1054        // if this is true, wraparound has occurred, undo this wraparound 
     1055        if(syt_cycle<now_cycle_masked) syt_cycle += 0x10; 
     1056         
     1057        unsigned int delta_cycles=syt_cycle-now_cycle_masked; 
     1058         
     1059        // reconstruct the cycle part of the timestamp 
     1060        unsigned int new_cycles=cycle + delta_cycles; 
     1061         
     1062        if(new_cycles>7999) { 
     1063            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Detected wraparound: %d + %d = %d\n",cycle,delta_cycles,new_cycles); 
     1064             
     1065            new_cycles-=8000; // wrap around 
     1066            wraparound_occurred=true; 
     1067        } 
     1068         
     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))); 
     1083             
     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; 
     1091            } 
     1092             
     1093            // implement a 1st order DLL to estimate the framerate 
     1094            // this is the number of ticks between two samples 
     1095            float f=measured_difference; 
     1096            float err = f / (1.0*m_syt_interval) - m_ticks_per_frame; 
     1097             
     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); 
     1099 
     1100#ifdef DEBUG 
     1101            if(f > 1.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) { 
     1102                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); 
     1104            } 
     1105            if(f < 0.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) { 
     1106                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); 
     1108            } 
     1109#endif 
     1110 
     1111            // integrate the error 
     1112            m_ticks_per_frame += RECEIVE_DLL_INTEGRATION_COEFFICIENT*err; 
     1113             
     1114        } 
     1115         
     1116         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n", 
     1117         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 
     1122         ); 
     1123              
     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. 
    10571138        if(m_disabled) { 
    10581139            return RAW1394_ISO_DEFER; 
     
    10781159                retval=RAW1394_ISO_DEFER; 
    10791160            } 
    1080              
    1081             // do the time stamp processing 
    1082             // put the last time stamp a variable 
    1083             // this will allow us to determine the  
    1084             // actual presentation time later 
    1085             if (packet->syt != 0xFFFF) { 
    1086  
    1087                 bool wraparound_occurred=false; 
    1088                  
    1089                 m_last_timestamp2=m_last_timestamp; 
    1090                  
    1091                 unsigned int syt_timestamp=ntohs(packet->syt); 
    1092                  // reconstruct the top part of the timestamp using the current cycle number 
    1093                 unsigned int now_cycle_masked=cycle & 0xF; 
    1094                 unsigned int syt_cycle=CYCLE_COUNTER_GET_CYCLES(syt_timestamp); 
    1095                  
    1096                 // if this is true, wraparound has occurred, undo this wraparound 
    1097                 if(syt_cycle<now_cycle_masked) syt_cycle += 0x10; 
    1098                  
    1099                 unsigned int delta_cycles=syt_cycle-now_cycle_masked; 
    1100                  
    1101                 // reconstruct the cycle part of the timestamp 
    1102                 unsigned int new_cycles=cycle + delta_cycles; 
    1103                  
    1104                 if(new_cycles>7999) { 
    1105                     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Detected wraparound: %d + %d = %d\n",cycle,delta_cycles,new_cycles); 
    1106                      
    1107                     new_cycles-=8000; // wrap around 
    1108                     wraparound_occurred=true; 
    1109                 } 
    1110                  
    1111                 m_last_timestamp = (new_cycles) << 12; 
    1112                  
    1113                 // now add the offset part on top of that 
    1114                 m_last_timestamp |= (syt_timestamp & 0xFFF); 
    1115                  
    1116                 // mask off the seconds field 
    1117                  
    1118                 // m_last_timestamp timestamp now contains all info, 
    1119                 // including cycle number 
    1120                  
    1121                 if (m_last_timestamp & m_last_timestamp2) { 
    1122                     // try and estimate the frame rate from the device: 
    1123                     int timestamp_difference=((int)(CYCLE_COUNTER_TO_TICKS(m_last_timestamp))) 
    1124                                              -((int)(CYCLE_COUNTER_TO_TICKS(m_last_timestamp2))); 
    1125                                               
    1126                     // handle wrap around of the cycle variable if nescessary 
    1127                     // it can be that two successive timestamps cause wraparound (if the difference between time 
    1128                     // stamps is larger than 2 cycles), thus it isn't always nescessary 
    1129                     if (wraparound_occurred & (m_last_timestamp<m_last_timestamp2)) { 
    1130                         debugOutput(DEBUG_LEVEL_VERY_VERBOSE," => correcting for timestamp difference wraparound\n"); 
    1131                         timestamp_difference+=TICKS_PER_SECOND; 
    1132                     } 
    1133                      
    1134                     // implement a 1st order DLL to estimate the framerate 
    1135                     // this is the number of ticks between two samples 
    1136                     float f=timestamp_difference; 
    1137                     float err = timestamp_difference / m_syt_interval; 
    1138                     // now it contains the error between our estimate 
    1139                     // and the current measurement 
    1140                     err=err-m_ticks_per_frame; 
    1141                      
    1142                     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); 
    1143  
    1144 #ifdef DEBUG 
    1145                     if(f > 1.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) { 
    1146                         debugWarning("Timestamp diff more than 50%% of the nominal diff too large!\n"); 
    1147                         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); 
    1148                     } 
    1149                     if(f < 0.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) { 
    1150                         debugWarning("Timestamp diff more than 50%% of the nominal diff too small!\n"); 
    1151                         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); 
    1152                     } 
    1153 #endif 
    1154  
    1155                     const float coeff=0.0005; 
    1156                     // integrate the error 
    1157                     m_ticks_per_frame += coeff*err; 
    1158                      
    1159                 } 
    1160                  
    1161                  debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n", 
    1162                  cycle,now_cycle_masked,delta_cycles, 
    1163                  CYCLE_COUNTER_TO_TICKS(m_last_timestamp), 
    1164                  CYCLE_COUNTER_GET_CYCLES(m_last_timestamp), 
    1165                  CYCLE_COUNTER_GET_TICKS(m_last_timestamp), 
    1166                  ntohs(packet->syt),m_last_timestamp&0xFFFF, dropped 
    1167                  ); 
    1168                   
    1169 #ifdef DEBUG 
    1170                 if(m_last_timestamp<m_last_timestamp2) { 
    1171                     if(wraparound_occurred) { 
    1172                         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);                    
    1173                     } else { 
    1174                         debugWarning("timestamp not sequential for cycle %d! %08X %08X %08X\n", cycle, syt_timestamp, m_last_timestamp, m_last_timestamp2); 
    1175                          
    1176                         // the DLL will recover from this. 
    1177                         m_last_timestamp2=m_last_timestamp; 
    1178                     } 
    1179                 } 
    1180 #endif 
    1181  
    1182             } 
     1161 
    11831162        } 
    11841163 
     
    12231202// this uses SYT to determine if one period is ready 
    12241203bool AmdtpReceiveStreamProcessor::isOnePeriodReady() {  
    1225 #define DO_SYT_SYNC 
     1204 
    12261205#ifdef DO_SYT_SYNC 
    12271206 // this code is not ready yet 
     
    12321211    // therefore the number of ticks per sample is 24576000 / Fs 
    12331212    // NOTE: this will be rounded!! 
    1234     float ticks_per_sample=24576000.0/m_framerate; 
     1213//     float ticks_per_sample=24576000.0/m_framerate; 
     1214     float ticks_per_sample=m_ticks_per_frame; 
    12351215 
    12361216    // we are allowed to add some constant  
    12371217    // processing delay to the transfer delay 
    12381218    // being the period size and some fixed delay 
    1239     unsigned int processing_delay=ticks_per_sample*(m_period)+RECEIVE_PROCESSING_DELAY; 
    1240      
     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); 
    12411221     
    12421222    // the number of events in the buffer is 
     
    12501230    // m_last_timestamp - (m_framecounter-m_syt_interval)*ticks_per_sample 
    12511231     
    1252     // however we have to make sure that we can transfer at least one period 
     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 
    12531235    // therefore we first check if this is ok 
    12541236     
    1255      if(m_framecounter > (signed int)m_period) { 
    1256         // we make this signed, because this can be < 0 
     1237//      if(m_framecounter > (signed int)m_period) { 
     1238 
    12571239        unsigned int m_last_timestamp_ticks = CYCLE_COUNTER_TO_TICKS(m_last_timestamp); 
    12581240         
    12591241        // add the processing delay 
    12601242        int ideal_presentation_time = m_last_timestamp_ticks + processing_delay; 
    1261         unsigned int buffer_content_ticks=(int)((m_framecounter-m_syt_interval)*ticks_per_sample); 
     1243        int buffer_content_ticks=((int)m_framecounter)-((int)m_syt_interval); 
     1244        buffer_content_ticks *= ticks_per_sample; 
    12621245         
    12631246        // if the ideal_presentation_time is smaller than buffer_content_ticks, wraparound has occurred 
     
    12701253        // FIXME: if we are sure, make ideal_presentation_time an unsigned int 
    12711254//         assert(ideal_presentation_time>=0); 
     1255         
     1256        unsigned int current_time_ticks = (m_handler->getCycleCounter() % TICKS_PER_SECOND ); 
     1257 
    12721258#ifdef DEBUG 
    12731259        if(ideal_presentation_time<0) { 
    12741260            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                         
    12751310        } 
    12761311#endif 
    12771312         
    1278         unsigned int current_time=m_handler->getCycleCounter() & 0x1FFFFFF; 
    1279         unsigned int current_time_ticks = CYCLE_COUNTER_TO_TICKS(current_time); 
    1280  
    12811313        // if the last signalled period lies in the future, we know we had wraparound of the clock 
    12821314        // so add one second 
     
    12871319            CYCLE_COUNTER_GET_SECS(m_last_timestamp),  
    12881320            CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),  
    1289             CYCLE_COUNTER_GET_TICKS(m_last_timestamp) 
     1321            CYCLE_COUNTER_GET_OFFSET(m_last_timestamp) 
    12901322            ); 
    12911323        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n", 
     
    12971329        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
    12981330            current_time_ticks,  
    1299             CYCLE_COUNTER_GET_SECS(current_time),  
    1300             CYCLE_COUNTER_GET_CYCLES(current_time),  
    1301             CYCLE_COUNTER_GET_TICKS(current_time
     1331            TICKS_TO_SECS(current_time_ticks),  
     1332            TICKS_TO_CYCLES(current_time_ticks),  
     1333            TICKS_TO_OFFSET(current_time_ticks
    13021334            ); 
    13031335         
     
    13121344        if(tmp<0) { 
    13131345            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT passed (%d ticks too late)\n",-tmp); 
    1314             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Periods: %d, remote ticks/frame: %f, remote framerate = %f\n",m_PeriodStat.m_count, m_ticks_per_frame, 24576000.0/m_ticks_per_frame); 
     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); 
    13151350            if (-tmp>1000000) debugWarning("SYT VERY LATE: %d!\n",-tmp); 
    13161351             
     1352            m_WakeupStat.mark(m_framecounter); 
     1353             
     1354            m_one_period_passed=true; 
    13171355            m_last_timestamp_at_period_ticks=ideal_presentation_time; 
    1318                  return true; 
     1356             
     1357            return true; 
    13191358        } else { 
    13201359            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Too early wait %d ticks\n",tmp); 
    13211360             return false; 
    13221361        } 
    1323      } else { 
    1324         return false; 
    1325      } 
     1362//      } else { 
     1363//         return false; 
     1364//      } 
    13261365#else 
    13271366    if(m_framecounter > m_period) { 
     
    13311370} 
    13321371 
     1372unsigned 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    } 
     1400} 
     1401 
    13331402void AmdtpReceiveStreamProcessor::dumpInfo() 
    13341403{ 
     
    13711440        m_last_timestamp2=0; 
    13721441         
     1442        m_one_period_passed=false; 
    13731443         
    13741444        // reset all non-device specific stuff 
     
    14291499     
    14301500    // add the processing delay 
    1431     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding %u frames of SYT slack buffering...\n",(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND); 
    1432     ringbuffer_size_frames+=(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND; 
     1501    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; 
    14331504     
    14341505    if( !(m_event_buffer=freebob_ringbuffer_create( 
    14351506            (m_dimension * ringbuffer_size_frames) * sizeof(quadlet_t)))) { 
    14361507                debugFatal("Could not allocate memory event ringbuffer"); 
    1437 //              return -ENOMEM; 
    14381508                return false; 
    14391509        } 
     
    14431513                debugFatal("Could not allocate temporary cluster buffer"); 
    14441514                freebob_ringbuffer_free(m_event_buffer); 
    1445 //              return -ENOMEM; 
    14461515                return false; 
    14471516        } 
  • trunk/libfreebob/src/libstreaming/AmdtpStreamProcessor.h

    r266 r360  
    141141                                   unsigned int offset, unsigned int nevents); 
    142142 
    143     unsigned int m_last_timestamp; 
     143    unsigned long m_last_timestamp; 
    144144 
    145145    unsigned int m_dbc; 
     146     
     147    unsigned int m_ringbuffer_size_frames; 
    146148 
    147149    DECLARE_DEBUG_MODULE; 
     
    193195 
    194196    float getTicksPerFrame() {return m_ticks_per_frame;}; 
    195     unsigned int getPeriodTimeStamp() {return m_last_timestamp_at_period_ticks;}
    196  
     197    unsigned int getPeriodTimeStamp()
     198     
    197199    void dumpInfo(); 
    198200     
     
    215217    float m_ticks_per_frame; 
    216218     
     219    bool m_one_period_passed; 
     220     
    217221    DECLARE_DEBUG_MODULE; 
    218222 
  • trunk/libfreebob/src/libstreaming/freebob_streaming.cpp

    r336 r360  
    8686        if ( !dev->m_deviceManager ) { 
    8787                debugFatal( "Could not allocate device manager\n" ); 
    88                        delete dev; 
     88                delete dev; 
    8989                return 0; 
    9090        } 
     
    9292                debugFatal( "Could not initialize device manager\n" ); 
    9393                delete dev->m_deviceManager; 
    94                        delete dev; 
     94                delete dev; 
    9595                return 0; 
    9696        } 
     
    101101        if(!dev->processorManager) { 
    102102                debugFatal("Could not create StreamProcessorManager\n"); 
    103                delete dev->m_deviceManager; 
     103        delete dev->m_deviceManager; 
    104104                delete dev; 
    105105                return 0; 
     
    112112                debugFatal("Could not init StreamProcessorManager\n"); 
    113113                delete dev->processorManager; 
    114                delete dev->m_deviceManager; 
     114        delete dev->m_deviceManager; 
    115115                delete dev; 
    116116                return 0; 
     
    120120        if(!dev->m_deviceManager->discover(DEBUG_LEVEL_NORMAL)) { 
    121121                debugOutput(DEBUG_LEVEL_VERBOSE, "Could not discover devices\n"); 
     122                delete dev->processorManager; 
     123        delete dev->m_deviceManager; 
     124                delete dev;              
    122125                return 0; 
    123126        } 
     
    131134                // Set the device's sampling rate to that requested 
    132135                // FIXME: does this really belong here?  If so we need to handle errors. 
    133                 device->setSamplingFrequency(parseSampleRate(dev->options.sample_rate)); 
     136                if (!device->setSamplingFrequency(parseSampleRate(dev->options.sample_rate))) { 
     137                  // try again: 
     138                  if (!device->setSamplingFrequency(parseSampleRate(dev->options.sample_rate))) { 
     139                delete dev->processorManager; 
     140                delete dev->m_deviceManager; 
     141                delete dev; 
     142                debugFatal("Could not set sampling frequency to %d\n",dev->options.sample_rate); 
     143                return 0; 
     144                  } 
     145                } 
    134146 
    135147                // prepare the device 
     
    156168        debugOutput(DEBUG_LEVEL_VERBOSE, "Preparing...\n"); 
    157169         
    158         dev->processorManager->prepare(); 
     170        if (!dev->processorManager->prepare()) { 
     171           debugFatal("Could not prepare streaming...\n"); 
     172           return false; 
     173        } 
    159174 
    160175        return true; 
  • trunk/libfreebob/src/libstreaming/IsoHandler.cpp

    r341 r360  
    2929#include "IsoHandler.h" 
    3030#include "IsoStream.h" 
     31#include "cyclecounter.h" 
     32 
     33#include "libutil/Time.h" 
     34#include "libutil/TimeSource.h" 
     35#include "libutil/SystemTimeSource.h" 
     36 
    3137#include <errno.h> 
    3238#include <netinet/in.h> 
     
    3642#include <iostream> 
    3743using namespace std; 
     44 
     45 
     46#define CC_SLEEP_TIME_AFTER_UPDATE     100 
     47#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) 
     51#define CC_INIT_MAX_TRIES 10 
    3852 
    3953 
     
    7993 
    8094/* Base class implementation */ 
     95IsoHandler::IsoHandler(int port) 
     96   : TimeSource(), m_handle(0), m_handle_util(0), m_port(port),  
     97   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),  
     99   m_ticks_per_usec_dll_err2(0), 
     100   m_packetcount(0), m_dropped(0), m_Client(0) 
     101{ 
     102    InitTime(); 
     103    m_TimeSource=new FreebobUtil::SystemTimeSource(); 
     104} 
     105 
     106IsoHandler::IsoHandler(int port, unsigned int buf_packets, unsigned int max_packet_size, int irq) 
     107   : TimeSource(), m_handle(0), m_port(port),  
     108   m_buf_packets(buf_packets), m_max_packet_size( max_packet_size),  
     109   m_irq_interval(irq),  
     110   m_cyclecounter_ticks(0), m_lastmeas_usecs(0), m_ticks_per_usec(24.576), 
     111   m_ticks_per_usec_dll_err2(0), 
     112   m_packetcount(0), m_dropped(0), m_Client(0) 
     113{ 
     114    InitTime(); 
     115    m_TimeSource=new FreebobUtil::SystemTimeSource(); 
     116} 
    81117 
    82118IsoHandler::~IsoHandler() { 
     
    87123    if(m_handle_util) raw1394_destroy_handle(m_handle_util); 
    88124     
     125    delete m_TimeSource; 
    89126} 
    90127 
     
    127164        raw1394_set_bus_reset_handler(m_handle, busreset_handler); 
    128165 
     166    // initialize the local timesource 
     167    m_TimeSource_NbCycleWraps=0; 
     168    quadlet_t buf=0; 
     169    unsigned int new_counter; 
     170     
     171    raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
     172        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 
    129177    // update the cycle counter value for initial value 
    130     updateCycleCounter(); 
    131  
    132         return true; 
     178    initCycleCounter(); 
     179 
     180        return true; 
     181
     182 
     183bool 
     184IsoHandler::setSyncMaster(FreebobUtil::TimeSource *t) 
     185
     186    m_TimeSource=t; 
     187     
     188    // update the cycle counter value for initial value 
     189    initCycleCounter(); 
     190     
     191    return true; 
    133192} 
    134193 
     
    141200 
    142201/** 
    143  * Returns the current value of the cycle counter 
     202 * Bus reset handler 
    144203 * 
    145  * @return the current value of the cycle counter 
     204 * @return ? 
    146205 */ 
    147 #define CSR_CYCLE_TIME            0x200 
    148 #define CSR_REGISTER_BASE  0xfffff0000000ULL 
    149  
    150 #define CYCLE_COUNTER_GET_SECS(x)   (((x & 0xFE000000) >> 25)) 
    151 #define CYCLE_COUNTER_GET_CYCLES(x) (((x & 0x01FFF000) >> 12)) 
    152 #define CYCLE_COUNTER_GET_TICKS(x)  (((x & 0x00000FFF))) 
    153 #define CYCLE_COUNTER_TO_TICKS(x) ((CYCLE_COUNTER_GET_SECS(x)   * 24576000) +\ 
    154                                    (CYCLE_COUNTER_GET_CYCLES(x) *     3072) +\ 
    155                                    (CYCLE_COUNTER_GET_TICKS(x)            )) 
     206  
     207int IsoHandler::handleBusReset(unsigned int generation) { 
     208        debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n"); 
     209         
     210        // as busreset can elect a new cycle master, 
     211        // we need to re-initialize our timing code 
     212    initCycleCounter(); 
     213     
     214        return 0; 
     215
     216 
     217/** 
     218 * Returns the current value of the cycle counter (in ticks) 
     219 * 
     220 * @return the current value of the cycle counter (in ticks) 
     221 */ 
    156222 
    157223unsigned int IsoHandler::getCycleCounter() { 
    158      return m_cyclecounter; 
    159 
    160  
    161 void IsoHandler::updateCycleCounter() { 
     224    // calculate the cycle counter based upon the current time 
     225    // and the estimated tick rate 
     226    freebob_microsecs_t now=m_TimeSource->getCurrentTimeAsUsecs(); 
     227     
     228    // linear interpolation 
     229    int delta_usecs=now-m_lastmeas_usecs; 
     230 
     231    float offset=m_ticks_per_usec * ((float)delta_usecs); 
     232     
     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      ); 
     238       
     239    // if we need to wrap, do it 
     240    if (pred_ticks > TICKS_PER_SECOND * 128) { 
     241        pred_ticks -= TICKS_PER_SECOND * 128; 
     242    } 
     243     
     244    return pred_ticks; 
     245
     246 
     247bool IsoHandler::updateCycleCounter() { 
    162248    quadlet_t buf=0; 
     249     
     250    freebob_microsecs_t prev_usecs=m_lastmeas_usecs; 
     251    unsigned int prev_ticks=m_cyclecounter_ticks; 
     252     
     253    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 
     259       on the system clock. 
     260        
     261       For more info, refer to: 
     262        "Using a DLL to filter time" 
     263        Fons Adriaensen 
     264         
     265        Can be found at: 
     266        http://users.skynet.be/solaris/linuxaudio/downloads/usingdll.pdf 
     267        or maybe at: 
     268        http://www.kokkinizita.net/linuxaudio 
     269     
     270        Basically what we do is estimate the next point (T1,CC1_est) 
     271        based upon the previous point (T0, CC0) and the estimated rate (R). 
     272        Then we compare our estimation with the measured cycle counter 
     273        at T1 (=CC1_meas). We then calculate the estimation error on R: 
     274        err=(CC1_meas-CC0)/(T1-T2) - (CC1_est-CC0)/(T1-T2) 
     275        and try to minimize this on average (DLL) 
     276         
     277        Note that in order to have a contignous mapping, we should 
     278        update CC0<=CC1_est instead of CC0<=CC1_meas. The measurement  
     279        serves only to correct the error 'on average'. 
     280         
     281        In the code, the following variable names are used: 
     282        T0=prev_usecs 
     283        T1=next_usecs 
     284         
     285        CC0=prev_ticks 
     286        CC1_est=est_ticks 
     287        CC1_meas=meas_ticks 
     288         
     289     */ 
    163290     
    164291    // normally we should be able to use the same handle 
     
    167294    raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
    168295        CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
    169      
    170     m_cyclecounter= ntohl(buf) & 0xFFFFFFFF; 
    171      
    172 //     debugOutput(DEBUG_LEVEL_VERBOSE,"Updating timestamp: %08X (%2u sec + %2u cycles + %04u ticks)\n", 
    173 //           m_cyclecounter,  
    174 //           CYCLE_COUNTER_GET_SECS(m_cyclecounter), 
    175 //           CYCLE_COUNTER_GET_CYCLES(m_cyclecounter), 
    176 //           CYCLE_COUNTER_GET_TICKS(m_cyclecounter) 
    177 //           );     
    178      
    179      
    180     usleep(100); 
     296    new_usecs=m_TimeSource->getCurrentTimeAsUsecs(); 
     297     
     298    new_counter= ntohl(buf) & 0xFFFFFFFF; 
     299    new_ticks=CYCLE_COUNTER_TO_TICKS(new_counter); 
     300     
     301    // the difference in system time 
     302    int delta_usecs=new_usecs-prev_usecs; 
     303    // this cannot be 0, because m_TimeSource->getCurrentTimeAsUsecs should  
     304    // never return the same value (maybe in future terrahz processors?) 
     305    assert(delta_usecs); 
     306     
     307    // the measured cycle counter difference 
     308    unsigned int delta_ticks_meas; 
     309    if (new_ticks > prev_ticks) { 
     310        delta_ticks_meas=new_ticks - prev_ticks; 
     311    } 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)); 
     317     
     318    // the measured & estimated rate 
     319    float rate_meas=((float)delta_ticks_meas/(float)delta_usecs); 
     320    float rate_est=((float)m_ticks_per_usec); 
     321     
     322    // these make sure we don't update when the measurement is 
     323    // bad. We know the nominal rate, and it can't be that far 
     324    // off. The thing is that there is a problem in measuring 
     325    // both usecs and ticks at the same time (no provision in 
     326    // the kernel. 
     327    // We know that there are some tolerances on both 
     328    // the system clock and the firewire clock such that the  
     329    // actual difference is rather small. So we discard values  
     330    // that are too far from the nominal rate.  
     331    // Otherwise the DLL has to have a very low bandwidth, in  
     332    // order not to be desturbed too much by these bad measurements 
     333    // resulting in very slow locking. 
     334     
     335    if (   (rate_meas < 24.576*(1.0+CC_MAX_RATE_ERROR))  
     336        && (rate_meas > 24.576*(1.0-CC_MAX_RATE_ERROR))) { 
     337 
     338#ifdef DEBUG 
     339 
     340        int diff=(int)delta_ticks_est; 
     341         
     342        // calculate the difference in predicted ticks and 
     343        // measured ticks 
     344        diff -= delta_ticks_meas; 
     345         
     346         
     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, 
     349                diff, delta_ticks_est, delta_ticks_meas, delta_usecs, (((float)diff)/24.576) 
     350                ); 
     351        } else { 
     352            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Good pred: diff=%d, dt_est=%u, dt_meas=%u, d=%dus, err=%fus\n", 
     353                diff, delta_ticks_est, delta_ticks_meas, delta_usecs, (((float)diff)/24.576) 
     354                ); 
     355        } 
     356#endif 
     357        // DLL the error to obtain the rate. 
     358        // (note: the DLL makes the error=0) 
     359        // only update the DLL if the rate is within 10% of the expected 
     360        // rate 
     361        float err=rate_meas-rate_est; 
     362         
     363        // 2nd order DLL update 
     364//         const float w=6.28*0.0001; 
     365//         const float b=w*1.45; 
     366//         const float c=w*w; 
     367//          
     368//         m_ticks_per_usec += b*err + m_ticks_per_usec_dll_err2; 
     369//         m_ticks_per_usec_dll_err2 += c * err; 
     370 
     371        // first order DLL update 
     372         m_ticks_per_usec += CC_DLL_COEFF*err; 
     373     
     374        if (   (m_ticks_per_usec > 24.576*(1.0+CC_MAX_RATE_ERROR))  
     375            || (m_ticks_per_usec < 24.576*(1.0-CC_MAX_RATE_ERROR))) { 
     376            debugOutput(DEBUG_LEVEL_VERBOSE, "Warning: DLL ticks/usec near clipping (%8.4f)\n", 
     377                        m_ticks_per_usec); 
     378        } 
     379         
     380        // update the internal values 
     381        // note: the next cyclecounter point is 
     382        //       the estimated one, not the measured one! 
     383        m_cyclecounter_ticks += delta_ticks_est; 
     384        // if we need to wrap, do it 
     385        if (m_cyclecounter_ticks > TICKS_PER_SECOND * 128) { 
     386            m_cyclecounter_ticks -= TICKS_PER_SECOND * 128; 
     387        } 
     388             
     389        m_lastmeas_usecs = new_usecs; 
     390 
     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, 
     393              delta_ticks_est, delta_ticks_meas, m_ticks_per_usec, rate_meas 
     394              ); 
     395 
     396        // the estimate is good 
     397        return true; 
     398    } else { 
     399        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"U TS: Not updating, rate out of range (%6.4f)\n", 
     400              rate_meas 
     401              ); 
     402        return false; 
     403 
     404    } 
     405
     406 
     407void IsoHandler::initCycleCounter() { 
     408    quadlet_t buf=0; 
     409 
     410    freebob_microsecs_t prev_usecs; 
     411    unsigned int prev_ticks; 
     412    unsigned int prev_counter; 
     413     
     414    freebob_microsecs_t new_usecs; 
     415    unsigned int new_ticks; 
     416    unsigned int new_counter; 
     417     
     418    float rate=0.0; 
     419     
     420    unsigned int try_cnt=0; 
     421     
     422    // make sure that we start with a decent rate, 
     423    // meaning that we want two successive (usecs,ticks) 
     424    // points that make sense. 
     425     
     426    while ( (try_cnt++ < CC_INIT_MAX_TRIES) && 
     427           (   (rate > 24.576*(1.0+CC_MAX_RATE_ERROR))  
     428           || (rate < 24.576*(1.0-CC_MAX_RATE_ERROR)))) { 
     429            
     430        // normally we should be able to use the same handle 
     431        // because it is not iterated on by any other stuff 
     432        // but I'm not sure 
     433        raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
     434            CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
     435        prev_usecs=m_TimeSource->getCurrentTimeAsUsecs(); 
     436         
     437        prev_counter= ntohl(buf) & 0xFFFFFFFF; 
     438        prev_ticks=CYCLE_COUNTER_TO_TICKS(prev_counter); 
     439         
     440        usleep(CC_SLEEP_TIME_AFTER_UPDATE); 
     441         
     442        // normally we should be able to use the same handle 
     443        // because it is not iterated on by any other stuff 
     444        // but I'm not sure 
     445        raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
     446            CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
     447        new_usecs=m_TimeSource->getCurrentTimeAsUsecs(); 
     448         
     449        new_counter= ntohl(buf) & 0xFFFFFFFF; 
     450        new_ticks=CYCLE_COUNTER_TO_TICKS(new_counter); 
     451         
     452        unsigned int delta_ticks; 
     453         
     454        if (new_ticks > prev_ticks) { 
     455            delta_ticks=new_ticks - prev_ticks; 
     456        } else { // wraparound 
     457            delta_ticks=CYCLE_COUNTER_UNWRAP_TICKS(new_ticks) - prev_ticks; 
     458        } 
     459         
     460        int delta_usecs=new_usecs-prev_usecs; 
     461         
     462        // this cannot be 0, because m_TimeSource->getCurrentTimeAsUsecs should  
     463        // never return the same value (maybe in future terrahz processors?) 
     464        assert(delta_usecs); 
     465         
     466        rate=((float)delta_ticks/(float)delta_usecs); 
     467         
     468        // update the internal values 
     469        m_cyclecounter_ticks=new_ticks; 
     470        m_lastmeas_usecs=new_usecs; 
     471         
     472        debugOutput(DEBUG_LEVEL_VERBOSE,"Try %d: rate=%6.4f\n", 
     473            try_cnt,rate 
     474            ); 
     475 
     476    } 
     477     
     478    // this is not fatal, the DLL will eventually correct this 
     479    if(try_cnt == CC_INIT_MAX_TRIES) { 
     480        debugWarning("Failed to properly initialize cycle counter...\n"); 
     481    } 
     482     
     483    // initialize this to the nominal value 
     484    m_ticks_per_usec = 24.576; 
     485    m_ticks_per_usec_dll_err2 = 0; 
     486     
    181487} 
    182488 
     
    189495        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type    : %s\n", 
    190496             (this->getType()==EHT_Receive ? "Receive" : "Transmit")); 
    191         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %d, %d\n", 
     497        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %2d, %2d\n", 
    192498             m_port, channel); 
    193         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count   : %d (%d dropped)\n\n", 
     499        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count   : %10d (%5d dropped)\n", 
    194500             this->getPacketCount(), this->getDroppedCount()); 
     501    #ifdef DEBUG 
     502    unsigned int cc=this->getCycleCounter(); 
     503        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Cycle counter  : %10lu (%03us, %04ucycles, %04uticks)\n", 
     504             cc,TICKS_TO_SECS(cc),TICKS_TO_CYCLES(cc),TICKS_TO_OFFSET(cc)); 
     505        #endif 
     506        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Ticks/usec     : %8.6f (dll2: %8.6e)\n\n", 
     507             this->getTicksPerUsec(), m_ticks_per_usec_dll_err2); 
    195508 
    196509}; 
     
    235548 
    236549} 
     550 
     551/* The timesource interface */ 
     552freebob_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; 
     560         
     561    // this assumes that it never happens that there are more than 2 
     562    // minutes between calls 
     563    if (CYCLE_COUNTER_GET_SECS(new_counter) < m_TimeSource_LastSecs) { 
     564        m_TimeSource_NbCycleWraps++; 
     565    } 
     566     
     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); 
     571     
     572    debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Wraps=%4u, LastSecs=%3u, nowSecs=%3u, ticks=%10u\n", 
     573              m_TimeSource_NbCycleWraps, m_TimeSource_LastSecs, 
     574              CYCLE_COUNTER_GET_SECS(new_counter), ticks 
     575              ); 
     576               
     577    return  ticks; 
     578} 
     579 
     580freebob_microsecs_t IsoHandler::getCurrentTimeAsUsecs() { 
     581    float tmp=getCurrentTime(); 
     582    float tmp2 = tmp * USECS_PER_TICK; 
     583    freebob_microsecs_t retval=(freebob_microsecs_t)tmp2; 
     584     
     585    debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"tmp=%f, tmp2=%f, retval=%u\n", 
     586              tmp, tmp2,retval 
     587              ); 
     588     
     589    return retval; 
     590} 
     591 
     592 
    237593 
    238594/* Child class implementations */ 
     
    329685int IsoRecvHandler::handleBusReset(unsigned int generation) { 
    330686        debugOutput( DEBUG_LEVEL_VERBOSE, "handle bus reset...\n"); 
     687         
    331688        //TODO: implement busreset 
     689         
     690        // pass on the busreset signal 
     691        if(IsoHandler::handleBusReset(generation)) { 
     692                return -1; 
     693        } 
    332694        return 0; 
    333695} 
     
    439801        debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n"); 
    440802        //TODO: implement busreset 
     803         
     804        // pass on the busreset signal 
     805        if(IsoHandler::handleBusReset(generation)) { 
     806                return -1; 
     807        } 
     808         
    441809        return 0; 
    442810} 
  • trunk/libfreebob/src/libstreaming/IsoHandler.h

    r341 r360  
    3131#include "../debugmodule/debugmodule.h" 
    3232 
     33#include "libutil/TimeSource.h" 
     34 
    3335#include <libraw1394/raw1394.h> 
    3436 
     
    3941 
    4042class IsoStream; 
    41  
    4243/*! 
    4344\brief The Base Class for ISO Handlers 
     
    4950*/ 
    5051 
    51 class IsoHandler 
     52class IsoHandler : public FreebobUtil::TimeSource 
    5253{ 
    5354        protected: 
     
    6061                }; 
    6162         
    62                 IsoHandler(int port)  
    63                    : m_handle(0), m_handle_util(0), m_port(port),  
    64                    m_buf_packets(400), m_max_packet_size(1024), m_irq_interval(-1), 
    65                    m_packetcount(0), m_dropped(0), m_Client(0) 
    66                 {} 
    67  
    68                 IsoHandler(int port, unsigned int buf_packets, unsigned int max_packet_size, int irq)  
    69                    : m_handle(0), m_port(port),  
    70                    m_buf_packets(buf_packets), m_max_packet_size( max_packet_size),  
    71                    m_irq_interval(irq), m_packetcount(0), m_dropped(0), m_Client(0) 
    72                 {} 
     63                IsoHandler(int port); 
     64 
     65                IsoHandler(int port, unsigned int buf_packets, unsigned int max_packet_size, int irq); 
    7366 
    7467                virtual ~IsoHandler(); 
     
    118111                // not RT safe 
    119112                // the isohandlermanager is responsible for calling this! 
    120         void updateCycleCounter(); 
    121  
     113        bool updateCycleCounter(); 
     114        float getTicksPerUsec() {return m_ticks_per_usec;}; 
     115 
     116        // register a master timing source 
     117        bool setSyncMaster(FreebobUtil::TimeSource *t); 
     118     
    122119        protected: 
    123120            raw1394handle_t m_handle; 
     
    127124                unsigned int    m_max_packet_size; 
    128125                int             m_irq_interval; 
    129                 unsigned int    m_cyclecounter; 
    130  
     126                 
     127                unsigned int        m_cyclecounter_ticks; 
     128        freebob_microsecs_t m_lastmeas_usecs; 
     129        float               m_ticks_per_usec; 
     130        float               m_ticks_per_usec_dll_err2; 
     131         
    131132                int m_packetcount; 
    132133                int m_dropped; 
     
    134135                IsoStream *m_Client; 
    135136 
    136                 virtual int handleBusReset(unsigned int generation) = 0; 
     137        FreebobUtil::TimeSource *m_TimeSource; 
     138 
     139                virtual int handleBusReset(unsigned int generation); 
     140 
    137141 
    138142                DECLARE_DEBUG_MODULE; 
     
    141145                static int busreset_handler(raw1394handle_t handle, unsigned int generation); 
    142146 
     147        void initCycleCounter(); 
     148 
     149    // implement the TimeSource interface 
     150    public: 
     151        freebob_microsecs_t getCurrentTime(); 
     152        freebob_microsecs_t getCurrentTimeAsUsecs(); 
     153    private: 
     154        // to cope with wraparound 
     155        unsigned int m_TimeSource_LastSecs; 
     156        unsigned int m_TimeSource_NbCycleWraps; 
    143157 
    144158}; 
     
    167181                bool prepare(); 
    168182 
     183        protected: 
     184                int handleBusReset(unsigned int generation); 
     185 
    169186        private: 
    170                 int handleBusReset(unsigned int generation); 
    171  
    172187                static enum raw1394_iso_disposition  
    173188                iso_receive_handler(raw1394handle_t handle, unsigned char *data,  
     
    212227                bool prepare(); 
    213228 
     229    protected: 
     230        int handleBusReset(unsigned int generation); 
     231 
    214232        private: 
    215  
    216                 int handleBusReset(unsigned int generation); 
    217  
    218233                static enum raw1394_iso_disposition iso_transmit_handler(raw1394handle_t handle, 
    219234                                unsigned char *data, unsigned int *length, 
  • trunk/libfreebob/src/libstreaming/IsoHandlerManager.cpp

    r341 r360  
    6262{ 
    6363    updateCycleCounters(); 
     64    usleep(USLEEP_AFTER_UPDATE); 
     65     
    6466    return true; 
    6567} 
     
    110112          ++it ) 
    111113    { 
    112         (*it)->updateCycleCounter(); 
     114        int cnt=0; 
     115        while (!(*it)->updateCycleCounter() && (cnt++ < MAX_UPDATE_TRIES)) { 
     116            usleep(USLEEP_AFTER_UPDATE_FAILURE); 
     117        } 
    113118    } 
     119     
    114120} 
    115121 
     
    528534          ++it ) 
    529535    { 
    530                 debugOutputShort( DEBUG_LEVEL_NORMAL, " Stream %d (%p)\n",i++,*it); 
     536                debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it); 
    531537 
    532538                (*it)->dumpInfo(); 
  • trunk/libfreebob/src/libstreaming/IsoHandlerManager.h

    r341 r360  
    3636 
    3737#include <vector> 
     38 
     39#define USLEEP_AFTER_UPDATE_FAILURE 10 
     40#define USLEEP_AFTER_UPDATE 100 
     41#define MAX_UPDATE_TRIES 10 
    3842 
    3943namespace FreebobStreaming 
     
    9296                void enablePolling(IsoStream *); ///< enables polling on a stream 
    9397 
    94         protected
     98        public
    9599         
    96100             
     
    101105            // iterate all handlers 
    102106            bool iterate(); 
    103          
     107    private: 
    104108        // updates the cycle counter caches of all handlers 
    105109        void updateCycleCounters(); 
  • trunk/libfreebob/src/libstreaming/StreamProcessorManager.cpp

    r341 r360  
    151151 
    152152        // the tread that runs the packet iterators 
    153         m_streamingThread=new FreebobUtil::PosixThread(this, m_thread_realtime, m_thread_priority+5, PTHREAD_CANCEL_DEFERRED); 
     153        m_streamingThread=new FreebobUtil::PosixThread(this, 
     154           m_thread_realtime, m_thread_priority+5,  
     155           PTHREAD_CANCEL_DEFERRED); 
     156            
    154157        if(!m_streamingThread) { 
    155158                debugFatal("Could not create streaming thread\n"); 
     
    168171        // the tread that keeps the handler's cycle counters up to date 
    169172        // NOTE: is lower priority nescessary? it can block 
    170         m_isoManagerThread=new FreebobUtil::PosixThread(m_isoManager, m_thread_realtime, m_thread_priority+6, PTHREAD_CANCEL_DEFERRED); 
     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        m_isoManagerThread=new FreebobUtil::PosixThread( 
     183              m_isoManager,  
     184              m_thread_realtime, m_thread_priority+6, 
     185              PTHREAD_CANCEL_DEFERRED); 
     186               
    171187        if(!m_isoManagerThread) { 
    172188                debugFatal("Could not create iso manager thread\n"); 
     
    218234                         
    219235                } 
     236 
     237    // if there are no stream processors registered,  
     238    // fail 
     239    if (m_ReceiveProcessors.size() + m_TransmitProcessors.size() == 0) { 
     240        debugFatal("No stream processors registered, can't do anything usefull\n"); 
     241        return false; 
     242    } 
    220243 
    221244        return true; 
  • trunk/libfreebob/src/Makefile.am

    r358 r360  
    2424 
    2525lib_LTLIBRARIES = libfreebob.la 
     26 
     27libfreebob_la_LIBADD = -lrt 
     28 
    2629noinst_HEADERS =                                        \ 
    2730        configrom.h                                     \ 
     
    97100        debugmodule/debugmodule.h                       \ 
    98101        debugmodule/debugmodule.cpp                     \ 
    99         libstreaming/cip.c                              \ 
    100         libstreaming/freebob_streaming.cpp              \ 
    101         libstreaming/IsoHandler.cpp                     \ 
    102         libstreaming/IsoHandlerManager.cpp              \ 
    103         libstreaming/IsoStream.cpp                      \ 
    104         libstreaming/PacketBuffer.cpp                   \ 
    105         libstreaming/PortManager.cpp                    \ 
    106         libstreaming/Port.cpp                           \ 
    107         libstreaming/StreamProcessor.cpp                \ 
    108         libstreaming/StreamProcessorManager.cpp         \ 
    109         libstreaming/AmdtpPortInfo.cpp                  \ 
    110         libstreaming/AmdtpPort.cpp                      \ 
    111         libstreaming/AmdtpStreamProcessor.cpp           \ 
    112         libstreaming/ringbuffer.c                       \ 
    113         libstreaming/streamstatistics.cpp               \ 
    114         libstreaming/MotuStreamProcessor.cpp            \ 
    115         libstreaming/MotuPort.cpp                       \ 
    116         libstreaming/MotuPortInfo.cpp                   \ 
    117         libutil/DelayLockedLoop.h                       \ 
    118         libutil/Atomic.h                                \ 
    119         libutil/PosixThread.h                           \ 
    120         libutil/Thread.h                                \ 
    121         libutil/DelayLockedLoop.cpp                     \ 
    122         libutil/PosixThread.cpp  
     102        libstreaming/cip.c      \ 
     103        libstreaming/cyclecounter.h \ 
     104        libstreaming/freebob_streaming.cpp      \ 
     105        libstreaming/IsoHandler.cpp     \ 
     106        libstreaming/IsoHandlerManager.cpp      \ 
     107        libstreaming/IsoStream.cpp      \ 
     108        libstreaming/PacketBuffer.cpp   \ 
     109        libstreaming/PortManager.cpp    \ 
     110        libstreaming/Port.cpp   \ 
     111        libstreaming/StreamProcessor.cpp        \ 
     112        libstreaming/StreamProcessorManager.cpp \ 
     113        libstreaming/AmdtpPortInfo.cpp  \ 
     114        libstreaming/AmdtpPort.cpp      \ 
     115        libstreaming/AmdtpStreamProcessor.cpp   \ 
     116        libstreaming/ringbuffer.c       \ 
     117        libstreaming/streamstatistics.cpp       \ 
     118        libstreaming/MotuStreamProcessor.cpp    \ 
     119        libstreaming/MotuPort.cpp       \ 
     120        libstreaming/MotuPortInfo.cpp \ 
     121        libutil/DelayLockedLoop.h       \ 
     122        libutil/Atomic.h        \ 
     123        libutil/PosixThread.h   \ 
     124        libutil/Thread.h        \ 
     125        libutil/DelayLockedLoop.cpp     \ 
     126        libutil/PosixThread.cpp \ 
     127        libutil/Time.c  \ 
     128        libutil/Time.h  \ 
     129        libutil/TimeSource.cpp \ 
     130        libutil/TimeSource.h \ 
     131        libutil/SystemTimeSource.cpp \ 
     132        libutil/SystemTimeSource.h \ 
     133        libutil/cycles.h 
    123134 
    124135libfreebob_la_LDFLAGS =                                 \ 
    125136        -version-info $(LT_VERSION) $(LIBRAW1394_LIBS)  \ 
    126137        $(LIBIEC61883_LIBS) $(LIBAVC1394_LIBS)          \ 
    127         $(LIBXML_LIBS) $(LIBXMLCPP_LIBS) -lpthread 
     138        $(LIBXML_LIBS) $(LIBXMLCPP_LIBS) -lpthread -lrt 
    128139 
    129140nobase_dist_pkgdata_DATA =                              \ 
     
    141152        $(LIBIEC61883_LIBS)                             \ 
    142153        $(LIBAVC1394_LIBS)                              \ 
    143        -lpthread 
     154        -lpthread 
    144155 
    145156freebob_sync_SOURCES =                                  \ 
     
    150161        $(LIBIEC61883_LIBS)                             \ 
    151162        $(LIBAVC1394_LIBS)                              \ 
    152        -lpthread 
     163        -lpthread 
    153164 
    154 noinst_PROGRAMS = test-dll test-debugmodule 
     165noinst_PROGRAMS = test-dll test-debugmodule bebob_unittests 
    155166 
    156167test_dll_SOURCES = libutil/test-dll.cpp 
     
    160171test_debugmodule_LDADD = libfreebob.la 
    161172 
    162 noinst_PROGRAMS = bebob_unittests 
    163  
    164173bebob_unittests_SOURCES = bebob/bebob_unittests.cpp 
    165174bebob_unittests_LDADD   = $(top_builddir)/src/libfreebob.la \ 
    166175        $(LIBXMLCPP_LIBS) $(LIBAVC1394_LIBS) $(LIBIEC61883_LIBS) 
     176 
  • trunk/libfreebob/support/jack/freebob_driver.c

    r312 r360  
    196196} 
    197197 
    198 static int 
     198static int  
    199199freebob_driver_detach (freebob_driver_t *driver) 
    200200{ 
     
    449449        float delayed_usecs=0.0; 
    450450 
    451         jack_nframes_t nframes = freebob_driver_wait (driver, -1, &wait_status, 
    452                                                   &delayed_usecs); 
     451        jack_nframes_t nframes = freebob_driver_wait (driver, -1, 
     452           &wait_status, &delayed_usecs); 
    453453         
    454454        if ((wait_status < 0)) { 
  • trunk/libfreebob/tests/Makefile.am

    r336 r360  
    1616# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
    1717 
    18 SUBDIRS = streaming 
     18# SUBDIRS = streaming 
    1919 
    2020INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src $(LIBXML_CFLAGS) \ 
     
    2222 
    2323noinst_PROGRAMS = test-freebob test-extplugcmd test-fw410 freebob-server \ 
    24         test-volume test-mixer 
     24                test-volume test-mixer test-cyclecounter test-sytmonitor 
     25 
    2526noinst_HEADERS =  
    2627 
     
    5152#TESTS_ENVIRONMENT 
    5253TEST = test-freebob 
     54 
     55test_cyclecounter_LDADD = $(top_builddir)/src/libfreebob.la $(LIBIEC61883_LIBS) \ 
     56        $(LIBRAW1394_LIBS) $(LIBAVC1394_LIBS) 
     57test_cyclecounter_SOURCES = test-cyclecounter.cpp 
     58 
     59test_sytmonitor_LDADD = $(top_builddir)/src/libfreebob.la $(LIBIEC61883_LIBS) \ 
     60        $(LIBRAW1394_LIBS) $(LIBAVC1394_LIBS) 
     61test_sytmonitor_SOURCES = test-sytmonitor.cpp SytMonitor.cpp \ 
     62                          SytMonitor.h 
  • trunk/libfreebob/tests/streaming/test-isohandling.cpp

    r250 r360  
    2727 
    2828#include <signal.h> 
    29 #include "debugmodule/debugmodule.h" 
     29#include "src/debugmodule/debugmodule.h" 
    3030 
    3131#include <netinet/in.h> 
    3232 
    33 #include "IsoHandler.h" 
    34 #include "IsoStream.h" 
    35 #include "StreamProcessorManager.h" 
    36 #include "AmdtpStreamProcessor.h" 
    37 #include "IsoHandlerManager.h" 
    38 #include "PosixThread.h" 
    39 #include "AmdtpPort.h" 
     33#include "src/libstreaming/IsoHandler.h" 
     34#include "src/libstreaming/IsoStream.h" 
     35#include "src/libstreaming/StreamProcessorManager.h" 
     36#include "src/libstreaming/AmdtpStreamProcessor.h" 
     37#include "src/libstreaming/IsoHandlerManager.h" 
     38#include "src/libutil/PosixThread.h" 
     39#include "src/libstreaming/AmdtpPort.h" 
    4040 
    4141using namespace FreebobStreaming;