Changeset 1456

Show
Ignore:
Timestamp:
11/22/08 11:22:57 (12 years ago)
Author:
ppalmers
Message:

fix cycle timer register read retry operation

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/libffado-2.0/src/libieee1394/CycleTimerHelper.cpp

    r1341 r1456  
    357357    uint64_t local_time; 
    358358    int64_t usecs_late; 
    359     int ntries=4
     359    int ntries=10
    360360    uint64_t cycle_timer_ticks; 
    361     double diff_ticks; 
    362  
    363     // if the difference between the predicted value and the 
     361    int64_t err_ticks; 
     362    bool not_good; 
     363 
     364    // if the difference between the predicted value at readout time and the 
    364365    // actual value seems to be too large, retry reading the cycle timer 
    365366    // some host controllers return bogus values on some reads 
     
    373374        usecs_late = local_time - m_sleep_until; 
    374375        cycle_timer_ticks = CYCLE_TIMER_TO_TICKS(cycle_timer); 
    375         diff_ticks = diffTicks(cycle_timer_ticks, (int64_t)m_next_time_ticks); 
     376 
     377        // calculate the CTR_TICKS we expect to read at "local_time" 
     378        // then calculate the difference with what we actually read, 
     379        // taking wraparound into account. If these deviate too much 
     380        // from eachother then read the register again (bogus read). 
     381        int64_t expected_ticks = getCycleTimerTicks(local_time); 
     382        err_ticks = diffTicks(cycle_timer_ticks, expected_ticks); 
    376383 
    377384        // check for unrealistic CTR reads (NEC controller does that sometimes) 
    378         if(diff_ticks < -((double)TICKS_PER_HALFCYCLE)) { 
    379             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,  
    380                         "(%p) have to retry CTR read, diff unrealistic: diff: %f, max: %f (try: %d)\n",  
    381                         this, diff_ticks, -((double)TICKS_PER_HALFCYCLE), ntries); 
    382         } 
    383  
    384     } while( diff_ticks < -((double)TICKS_PER_HALFCYCLE)  
    385              && --ntries && !m_first_run && !m_unhandled_busreset); 
     385        not_good = (-err_ticks > 1*TICKS_PER_HALFCYCLE || err_ticks > 1*TICKS_PER_HALFCYCLE); 
     386        if(not_good) { 
     387            debugOutput(DEBUG_LEVEL_VERBOSE,  
     388                        "(%p) have to retry CTR read, diff unrealistic: diff: %lld, max: +/- %ld (try: %d) %lld\n",  
     389                        this, err_ticks, 10*TICKS_PER_CYCLE, ntries, expected_ticks); 
     390            // sleep half a cycle to make sure the hardware moved on 
     391            Util::SystemTimeSource::SleepUsecRelative(USECS_PER_CYCLE/2); 
     392        } 
     393 
     394    } while(not_good && --ntries && !m_first_run && !m_unhandled_busreset); 
    386395 
    387396    // grab the lock after sleeping, otherwise we can't be interrupted by 
     
    390399    // wakeup and read is as small as possible 
    391400    Util::MutexLockHelper lock(*m_update_lock); 
     401 
     402    // the difference between the measured and the expected time 
     403    int64_t diff_ticks = diffTicks(cycle_timer_ticks, (int64_t)m_next_time_ticks); 
    392404 
    393405    // // simulate a random scheduling delay between (0-10ms) 
     
    418430        } 
    419431        m_first_run = false; 
    420     } else if (diff_ticks > 20.0*m_ticks_per_update) { 
     432    } else if (diff_ticks > m_ticks_per_update * 20) { 
    421433        debugOutput(DEBUG_LEVEL_VERBOSE, 
    422                     "re-init dll due to too large tick diff: %f >> %f\n", 
    423                     diff_ticks, (float)(20.0*m_ticks_per_update)); 
     434                    "re-init dll due to too large tick diff: %lld >> %f\n", 
     435                    diff_ticks, (float)(m_ticks_per_update * 20)); 
    424436        if(!initDLL()) { 
    425437            debugError("(%p) Could not init DLL\n", this); 
     
    442454        // the corrected difference between predicted and actual ctr 
    443455        // i.e. DLL error signal 
    444         double diff_ticks_corr; 
     456        int64_t diff_ticks_corr; 
    445457        if (ticks_late > 0) { 
    446458            diff_ticks_corr = diff_ticks - ticks_late; 
    447459            debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE, 
    448                                "diff_ticks_corr=%f, diff_ticks = %f, ticks_late = %lld\n", 
     460                               "diff_ticks_corr=%lld, diff_ticks = %lld, ticks_late = %lld\n", 
    449461                               diff_ticks_corr, diff_ticks, ticks_late); 
    450462        } else { 
     
    487499        // and coeff_b < 1, hence tmp is not near wrapping 
    488500 
    489         double step_ticks = (coeff_b * diff_ticks_corr); 
     501        double diff_ticks_corr_d =  (double)diff_ticks_corr; 
     502        double step_ticks = (coeff_b * diff_ticks_corr_d); 
    490503        debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, 
    491504                           "diff_ticks_corr=%f, step_ticks=%f\n", 
    492                            diff_ticks_corr, step_ticks); 
     505                           diff_ticks_corr_d, step_ticks); 
    493506 
    494507        // the same goes for m_dll_e2, which should be approx equal 
     
    515528 
    516529        // update the DLL state 
    517         m_dll_e2 += coeff_c * diff_ticks_corr
     530        m_dll_e2 += coeff_c * diff_ticks_corr_d
    518531 
    519532        // update the y-axis values 
     
    525538                           m_current_time_usecs, m_next_time_usecs, usecs_late, ticks_late); 
    526539        debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, 
    527                            " ticks: current: %f next: %f diff=%f\n", 
     540                           " ticks: current: %f next: %f diff=%lld\n", 
    528541                           m_current_time_ticks, m_next_time_ticks, diff_ticks); 
    529542        debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,