Changeset 263

Show
Ignore:
Timestamp:
06/15/06 09:07:47 (16 years ago)
Author:
pieterpalmers
Message:

- implementation of correct SYT behaviour for transmit streams

[Work-in-progress: these changes introduce a bug, but I don't [[BR]]

want to lose this]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.cpp

    r261 r263  
    5353/* transmit */ 
    5454AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(int port, int framerate, int dimension) 
    55         : TransmitStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0) { 
     55        : TransmitStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0) 
     56        , m_dbc(0) { 
    5657 
    5758 
     
    8687} 
    8788 
    88  
    8989enum raw1394_iso_disposition 
    9090AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length, 
     
    9393 
    9494        struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    95          
    96          
     95        unsigned int nevents=0; 
     96         
     97    packet->eoh0 = 0; 
     98 
     99    /* Our node ID can change after a bus reset, so it is best to fetch 
     100     * our node ID for each packet. */ 
     101    packet->sid = getNodeId() & 0x3f; 
     102 
     103    packet->dbs = m_dimension; 
     104    packet->fn = 0; 
     105    packet->qpc = 0; 
     106    packet->sph = 0; 
     107    packet->reserved = 0; 
     108    packet->dbc = m_dbc; 
     109    packet->eoh1 = 2; 
     110    packet->fmt = IEC61883_FMT_AMDTP; 
     111 
    97112        // signal that we are running (a transmit stream is always 'runnable') 
    98113        m_running=true; 
     
    102117        // that means that we'll send NODATA packets FIXME: check!! 
    103118        if(m_disabled) { 
    104                 iec61883_cip_fill_header_nodata(getNodeId(), &m_cip_status, packet); 
    105                 *length = 0; // this is to disable sending 
     119           // no-data packets have syt=0xFFFF 
     120           // and have the usual amount of events as dummy data  
     121        packet->fdf = IEC61883_FDF_NODATA; 
     122        packet->syt = 0xffff; 
     123         
     124        // the dbc is incremented even with no data packets 
     125        m_dbc += m_syt_interval; 
     126 
     127                *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 
    106128                *tag = IEC61883_TAG_WITH_CIP; 
    107129                *sy = 0; 
    108                 m_last_timestamp=4.0*9000.0 + cycle * 3072.0; 
    109130                return RAW1394_ISO_OK; 
    110131        } 
    111          
    112      debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 
    113          
    114         // keep the old cip, in case we don't have enough events left in the buffer. 
    115         struct iec61883_cip old_cip; 
    116         memcpy(&old_cip,&m_cip_status,sizeof(struct iec61883_cip)); 
    117                  
     132     
     133    packet->fdf = m_fdf; 
     134         
     135    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 
     136         
    118137        // construct the packet cip 
     138        // NOTE: maybe a little outdated 
    119139        // FIXME: this should be done differently: 
    120140        // first we should determine the timestamp of the first sample in this block 
     
    138158//      <<compile error here>> 
    139159         
    140         int nevents = iec61883_cip_fill_header (getNodeId(), &m_cip_status, packet); 
    141          
    142          
    143         unsigned int timestamp_ticks=m_last_timestamp; // fixed transfer delay 
    144         timestamp_ticks += 9000; 
    145          
    146         // if there are dropped packets, incorporate them into the delay 
    147         // FIXME: we don't know how many samples were lost 
     160    // FIXME: if m_last_bufferfill > 0 
     161    double ticks_per_frame=syncmaster->getTicksPerFrame(); 
     162 
     163    // m_last_timestamp is the moment upon which the last 'period signal'   
     164    // should have been given (note: should have been because 
     165    // the timestamp is derrived from the incoming packets, 
     166    // not from the moment the signal was actually given) 
     167     
     168    // at a period boundary, we expect nb_buffers * period frames to 
     169    // be in the buffers. 'right after' the transfer(), all of these  
     170    // frames should be in the xmit buffers (if transfer() finishes  
     171    // before new packets are received) 
     172    // therefore the last sample of the xmit buffer lies at  
     173    // T1 = timestamp + (nb_buffers * period) * ticks_per_frame 
     174    int T1 = m_last_timestamp + (m_nb_buffers * m_period) * ticks_per_frame; 
     175     
     176    // in reality however life is multithreaded, and we don't know 
     177    // exactly how many samples there are in the buffer. but we know 
     178    // how many there should be, so we say that the last frame put  
     179    // into the buffer (by transfer) has the timestamp T1 
     180     
     181    // this means that the current sample has timestamp 
     182    // T2 = T1 - (nb_frames_in_buffer) * ticks_per_frame 
     183    int buffer_fill=freebob_ringbuffer_read_space(m_event_buffer)/m_dimension/sizeof(quadlet_t); 
     184     
     185    int T2 = T1 - buffer_fill * ticks_per_frame; 
     186     
     187    // normally:  nb_buffers * period > nb_frames_in_buffer 
     188    // making T2 > timestamp 
     189    // however, this isn't always the case, due to ISO buffering etc. 
     190    // we therefore need to add some extra delay to T2: 
     191    // T3 = T2 + Tiso 
     192    // This Tiso has to cope with the prebuffering that has been done 
     193    // by the ISO layer: e.g. if 100 packets are prebuffered, this 
     194    // callback is executed approximately 100 packets before the  
     195    // actual transmission, hence we have to add 100 * 3072 ticks to 
     196    // the timestamp 
     197    // we know that one packet occurrs every 1/8000 secs, 
     198    // therefore the average nb of samples in a packet is m_framerate/8000 
     199    // making that these 100 packets contain 600 frames, and that 
     200    // we therefore need to advance the timestamp with the equivalent of  
     201    // 600 frames (600*ticks_per_frame) 
     202    int T3 = T2 + (m_handler->getBuffersize() * m_framerate * ticks_per_frame) / 8000; 
     203     
     204    // we then need to add the processing delay for the receiving 
     205    // device to this time to determine the xmit timestamp 
     206    // TSTAMP = T3 + PROCESSING_DELAY 
     207     
     208    // we should determine when to 'queue' this sample to 
     209    // the ISO xmit layer, based upon the cycle parameter 
     210    // we can define the ideal time at which to send the sample as 
     211    // TSEND = TSTAMP - PROCESSING_DELAY 
     212    // being T3 
     213    // however, this might make things a little too tight, as it can  
     214    // be that we are pre-queueing things. We have to make sure that  
     215    // T3 > timestamp (causality on our side) 
     216    // and that TSTAMP > timestamp (causality on the receiver's side) 
     217     
     218    // so we define TSEND as: 
     219    // TSEND = T3 + Tslack 
     220    // Tslack tbd 
     221     
     222    // note: Tslack=0 packets 
     223    int TSEND = T3; 
     224     
     225    // if we take a look at TSEND we can determine if we are to send 
     226    // the sample or not: 
     227    // if  
     228    // CYCLES(TSEND) < cycle 
     229    // then the time at which to send the packet has passed (note: wraparound!) 
     230    // we should send the sample 
     231    // if it hasn't passed, we should send an empty packet 
     232    // 
     233    // this should automatically catch up 
     234     
     235    // FIXME: wraparound! 
     236    int cycle_wo_wraparound=cycle; 
     237     
     238    // arbitrary 
     239    if (cycle_wo_wraparound - (TSEND/3072) < -4000) { 
     240        cycle_wo_wraparound +=8000; 
     241        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"wraparound detected: %d %d %d\n",cycle, cycle_wo_wraparound, cycle - (TSEND/3072)); 
     242    } 
     243     
     244    if (TSEND < cycle_wo_wraparound*3072) { 
     245        nevents=m_syt_interval; 
     246        m_dbc += m_syt_interval; 
     247    } else { // no-data 
     248           // no-data packets have syt=0xFFFF 
     249           // and have the usual amount of events as dummy data  
     250        packet->fdf = IEC61883_FDF_NODATA; 
     251        packet->syt = 0xffff; 
     252         
     253        // the dbc is incremented even with no data packets 
     254        m_dbc += m_syt_interval; 
     255         
     256                *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 
     257                *tag = IEC61883_TAG_WITH_CIP; 
     258                *sy = 0; 
    148259                 
    149         unsigned int timestamp=(((timestamp_ticks/3072) << 12) & 0xF000); 
    150         timestamp |= ((timestamp_ticks % 3072)) & 0xFFF; 
    151          
    152         timestamp = htons(timestamp); 
    153          
    154         m_last_timestamp += nevents*syncmaster->getTicksPerFrame(); 
    155    
    156     if (nevents==0) { 
    157         timestamp=0xFFFF; 
    158     } 
     260                debugOutput(DEBUG_LEVEL_VERBOSE,"Sending empty packet\n"); 
     261 
     262                return RAW1394_ISO_OK; 
     263    } 
     264     
     265    // the xmit timestamp should then be the TSEND + PROCESSING_DELAY 
     266    int timestamp = TSEND + 3*3072; 
     267 
     268    debugOutput(DEBUG_LEVEL_VERBOSE,"Now=%4d/%8d, Tstamp=%8d, DT=%8d, T2=%8d, T3=%8d, last TS=%d, BF=%d\n", 
     269        cycle,(cycle*3072), 
     270        timestamp, 
     271        timestamp-(cycle*3072), 
     272        T2,T3, 
     273        m_last_timestamp, 
     274        buffer_fill); 
    159275     
    160276        enum raw1394_iso_disposition retval = RAW1394_ISO_OK; 
    161277 
    162         if (!(nevents > 0)) { 
    163                  
    164                 if (m_cip_status.mode == IEC61883_MODE_BLOCKING_EMPTY) { 
    165                         *length = 8; 
    166                         return RAW1394_ISO_OK ; 
    167                 } 
    168                 else { 
    169                         nevents = m_cip_status.syt_interval; 
    170                 } 
    171         } 
    172          
    173278        int read_size=nevents*sizeof(quadlet_t)*m_dimension; 
    174279 
     
    182287         
    183288        // signal underrun 
    184 //         m_xruns++; 
     289        m_xruns++; 
    185290 
    186291        retval=RAW1394_ISO_DEFER; 
     
    199304        } 
    200305         
    201         unsigned int timestamp2=ntohs(timestamp); 
    202          debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"XMIT %d EVENTS, SYT %04X (was: %04X) for cycle %2d: %5u ticks (%2u cycles + %04u ticks)\n", 
    203          nevents, timestamp, packet->syt, cycle, 
    204          CYCLE_COUNTER_TO_TICKS(timestamp2), 
    205          CYCLE_COUNTER_GET_CYCLES(timestamp2), 
    206          CYCLE_COUNTER_GET_TICKS(timestamp2) 
    207          ); 
     306         
     307        // we can forget the seconds for the cycle counter 
     308        // because we are masking with 0xFFFF 
     309        unsigned int timestamp_cycles=timestamp/3072; 
     310        unsigned int timestamp_ticks=timestamp%3072; 
     311        timestamp_cycles %= 8000; 
     312         
     313        unsigned int timestamp_cyclecounter = (timestamp_cycles << 12) | timestamp_ticks; 
     314         
     315        packet->syt = ntohs(timestamp_cyclecounter & 0xffff); 
     316         
     317        debugOutput(DEBUG_LEVEL_VERBOSE,"XMIT %d EVENTS, SYT %04X for cycle %2d: %08d (%2u cycles + %04u ticks)\n", 
     318          nevents, timestamp_cyclecounter & 0xFFFF, cycle, 
     319          CYCLE_COUNTER_TO_TICKS(timestamp_cyclecounter), 
     320          CYCLE_COUNTER_GET_CYCLES(timestamp_cyclecounter), 
     321          CYCLE_COUNTER_GET_TICKS(timestamp_cyclecounter) 
     322          ); 
    208323    } 
    209324     
     
    211326    *sy = 0; 
    212327     
    213     // FIXME: do this directly 
    214     packet->syt=timestamp; 
    215      
    216328    // update the frame counter 
    217329    incrementFrameCounter(nevents); 
     330     
    218331    if(m_framecounter>m_period) { 
    219332       retval=RAW1394_ISO_DEFER; 
     
    222335#ifdef DEBUG 
    223336    if(packet->dbs) { 
    224         debugOutput(DEBUG_LEVEL_VERBOSE,  
     337        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
    225338            "XMT: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",  
    226339            m_channel, packet->fdf, 
     
    232345            ((*length / sizeof (quadlet_t)) - 2)/packet->dbs); 
    233346    } 
    234 #endif     
    235      
     347#endif 
     348 
    236349    m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    237350         
    238351    return retval; 
    239352 
     353} 
     354 
     355void AmdtpTransmitStreamProcessor::decrementFrameCounter() { 
     356    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "decrement frame counter...\n"); 
     357 
     358#ifdef DEBUG 
     359    int xmit_bufferspace=freebob_ringbuffer_read_space(m_event_buffer)/m_dimension/4; 
     360    int recv_bufferspace=freebob_ringbuffer_read_space(syncmaster->m_event_buffer)/syncmaster->m_dimension/4; 
     361     
     362    debugOutput(DEBUG_LEVEL_VERBOSE,"XMT: %5d | RCV: %5d | DIFF: %5d | SUM: %5d \n", xmit_bufferspace, recv_bufferspace, xmit_bufferspace - recv_bufferspace, xmit_bufferspace + recv_bufferspace); 
     363#endif 
     364 
     365    // update the timestamp 
     366     
     367    m_last_timestamp=syncmaster->getPeriodTimeStamp(); 
     368     
     369    StreamProcessor::decrementFrameCounter(); 
     370} 
     371 
     372void AmdtpTransmitStreamProcessor::incrementFrameCounter(int nbframes) { 
     373    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "increment frame counter by %d...\n", nbframes); 
     374     
     375    StreamProcessor::incrementFrameCounter(nbframes); 
    240376} 
    241377 
    242378bool AmdtpTransmitStreamProcessor::isOnePeriodReady() 
    243379{  
    244     //return true; 
    245     return (m_framecounter > (int)m_period);  
     380    return true; 
     381    //return (m_framecounter > (int)m_period);  
    246382} 
    247383  
     
    9651101#endif 
    9661102 
    967                     const double coeff=0.0001
     1103                    const double coeff=0.0005
    9681104                    // integrate the error 
    9691105                    m_ticks_per_frame += coeff*err; 
     
    9711107                } 
    9721108                 
    973                  debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n", 
     1109                 debugOutput(DEBUG_LEVEL_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n", 
    9741110                 cycle,now_cycle_masked,delta_cycles, 
    9751111                 CYCLE_COUNTER_TO_TICKS(m_last_timestamp), 
     
    9971133#ifdef DEBUG 
    9981134        if(packet->dbs) { 
    999             debugOutput(DEBUG_LEVEL_VERBOSE,  
     1135            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
    10001136                "RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",  
    10011137                channel, packet->fdf, 
     
    11191255            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); 
    11201256            if (-tmp>1000000) debugWarning("SYT VERY LATE: %d!\n",-tmp); 
    1121 //                 return true; 
     1257             
     1258            m_last_timestamp_at_period_ticks=ideal_presentation_time; 
     1259                 return true; 
    11221260        } else { 
    11231261            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Too early wait %d ticks\n",tmp); 
    1124 //             return false; 
     1262             return false; 
    11251263        } 
    1126      }  
    1127 //      else return false; 
    1128 // #else 
     1264     } else { 
     1265        return false; 
     1266     } 
     1267#else 
    11291268    if(m_framecounter > (int)m_period) { 
    11301269     return true; 
  • branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.h

    r255 r263  
    7373 
    7474public: 
    75  
     75    // FIXME: debug 
     76    friend class AmdtpReceiveStreamProcessor; 
     77     
    7678        AmdtpTransmitStreamProcessor(int port, int framerate, int dimension); 
    7779 
     
    105107    AmdtpReceiveStreamProcessor *syncmaster; 
    106108 
     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); 
     115     
    107116protected: 
    108117 
     
    132141                                   unsigned int offset, unsigned int nevents); 
    133142 
    134     double m_last_timestamp; 
    135  
     143    unsigned int m_last_timestamp; 
     144 
     145    unsigned int m_dbc; 
    136146 
    137147    DECLARE_DEBUG_MODULE; 
     
    150160 
    151161public: 
     162    // FIXME: debug 
     163    friend class AmdtpTransmitStreamProcessor; 
    152164 
    153165        AmdtpReceiveStreamProcessor(int port, int framerate, int dimension); 
     
    181193 
    182194    double getTicksPerFrame() {return m_ticks_per_frame;}; 
    183      
     195    unsigned int getPeriodTimeStamp() {return m_last_timestamp_at_period_ticks;}; 
     196 
    184197    void dumpInfo(); 
    185198     
     
    198211    unsigned int m_last_timestamp; 
    199212    unsigned int m_last_timestamp2; 
     213    unsigned int m_last_timestamp_at_period_ticks; 
    200214     
    201215    double m_ticks_per_frame; 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessor.h

    r249 r263  
    8787         
    8888        unsigned int getNbPeriodsReady() { if(m_period) return m_framecounter/m_period; else return 0;}; 
    89         void decrementFrameCounter(); 
    90         void incrementFrameCounter(int nbframes); 
     89        virtual void decrementFrameCounter(); 
     90        virtual void incrementFrameCounter(int nbframes); 
    9191         
    9292        // move to private?