Changeset 863

Show
Ignore:
Timestamp:
01/19/08 14:36:47 (13 years ago)
Author:
ppalmers
Message:

fix cycle timer DLL code

Files:

Legend:

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

    r862 r863  
    4242#define DEBUG_IMPLEMENT_BACKLOG 0 
    4343 
    44 #define IEEE1394SERVICE_USE_CYCLETIMER_DLL  0 
     44#define IEEE1394SERVICE_USE_CYCLETIMER_DLL  1 
     45#define IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC 50000 
    4546#define IEEE1394SERVICE_MAX_FIREWIRE_PORTS  16 
    4647 
  • trunk/libffado/src/libieee1394/CycleTimerHelper.cpp

    r807 r863  
    2828#include "libutil/PosixThread.h" 
    2929 
    30 #define DLL_BANDWIDTH (0.01) 
     30#define DLL_BANDWIDTH (0.1) 
    3131#define DLL_PI        (3.141592653589793238) 
    3232#define DLL_SQRT2     (1.414213562373095049) 
     
    3535#define DLL_COEFF_C   (DLL_OMEGA * DLL_OMEGA) 
    3636 
     37#define OFFSET_AVERAGE_COEFF 0.01 
    3738/* 
    3839#define ENTER_CRITICAL_SECTION { \ 
     
    6364    , m_next_time_ticks ( 0 ) 
    6465    , m_first_run ( true ) 
     66    , m_sleep_until ( 0 ) 
    6567    , m_Thread ( NULL ) 
    6668    , m_realtime ( false ) 
     
    8183    , m_next_time_ticks ( 0 ) 
    8284    , m_first_run ( true ) 
     85    , m_sleep_until ( 0 ) 
    8386    , m_Thread ( NULL ) 
    8487    , m_realtime ( rt ) 
     
    143146} 
    144147 
     148#if IEEE1394SERVICE_USE_CYCLETIMER_DLL 
    145149float 
    146150CycleTimerHelper::getRate() 
     
    158162} 
    159163 
    160 #if IEEE1394SERVICE_USE_CYCLETIMER_DLL 
    161  
    162164bool 
    163165CycleTimerHelper::Execute() 
    164166{ 
    165167    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Execute %p...\n", this); 
     168    if (!m_first_run) { 
     169        // wait for the next update period 
     170        ffado_microsecs_t now = m_TimeSource.getCurrentTimeAsUsecs(); 
     171        int sleep_time = m_sleep_until - now; 
     172        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p) Sleep until %lld/%f (now: %lld, diff=%d) ...\n", 
     173                    this, m_sleep_until, m_next_time_usecs, now, sleep_time); 
     174        m_TimeSource.SleepUsecAbsolute(m_sleep_until); 
     175        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " (%p) back...\n", this); 
     176    } 
     177 
    166178    uint32_t cycle_timer; 
    167179    uint64_t local_time; 
     
    173185                    cycle_timer, local_time); 
    174186 
    175     double usecs_late; 
    176187    if (m_first_run) { 
    177         usecs_late = 0.0
     188        m_sleep_until = local_time + m_usecs_per_update
    178189        m_dll_e2 = m_ticks_per_update; 
    179190        m_current_time_usecs = local_time; 
     
    188199        m_first_run = false; 
    189200    } else { 
    190  
    191         double diff = m_next_time_usecs - m_current_time_usecs; 
    192         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " usecs: local: %11llu current: %f next: %f, diff: %f\n", 
    193                     local_time, m_current_time_usecs, m_next_time_usecs, diff); 
    194  
     201        m_sleep_until += m_usecs_per_update; 
    195202        uint64_t cycle_timer_ticks = CYCLE_TIMER_TO_TICKS(cycle_timer); 
    196         usecs_late = ((double)local_time) - (m_next_time_usecs); 
    197  
    198         // we update the x-axis values 
     203        double usecs_late = ((double)local_time) - (m_next_time_usecs); 
     204 
     205        // update the x-axis values 
     206        double diff_ticks = diffTicks(cycle_timer_ticks, (int64_t)m_next_time_ticks); 
     207        m_current_time_ticks = m_next_time_ticks; 
     208        // do the calculation in 'tick space' 
     209        int64_t tmp = (uint64_t)(DLL_COEFF_B * diff_ticks); 
     210        if(m_dll_e2 > 0) { 
     211            tmp = addTicks(tmp, (uint64_t)m_dll_e2); 
     212        } else { 
     213            tmp = substractTicks(tmp, (uint64_t)(-m_dll_e2)); 
     214        } 
     215        if(tmp < 0) { 
     216            debugWarning("negative slope: %lld!\n", tmp); 
     217        } 
     218        m_next_time_ticks = addTicks((uint64_t)m_current_time_ticks, tmp); 
     219 
     220        // it should be ok to not do this in tick space since it's value 
     221        // is approx equal to the rate, being 24.576 ticks/usec 
     222        m_dll_e2 += DLL_COEFF_C * diff_ticks; 
     223 
     224        // update the y-axis values 
    199225        m_current_time_usecs = m_next_time_usecs; 
    200         m_next_time_usecs = (local_time - usecs_late) + m_usecs_per_update; 
     226        m_next_time_usecs = local_time + m_usecs_per_update; 
     227 
    201228        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " usecs: current: %f next: %f usecs_late=%f\n", 
    202229                    m_current_time_usecs, m_next_time_usecs, usecs_late); 
    203  
    204         // and the y-axis values 
    205         double diff_ticks = diffTicks(cycle_timer_ticks, (int64_t)m_next_time_ticks); 
    206         m_current_time_ticks = m_next_time_ticks; 
    207         m_next_time_ticks = addTicks((uint64_t)m_current_time_ticks, 
    208                                      (uint64_t)((DLL_COEFF_B * diff_ticks) + m_dll_e2)); 
    209         m_dll_e2 += DLL_COEFF_C * diff_ticks; 
    210230        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " ticks: current: %f next: %f diff=%f\n", 
    211231                    m_current_time_ticks, m_next_time_ticks, diff_ticks); 
     
    215235    } 
    216236 
    217     // track the average wakeup delay 
    218     m_avg_wakeup_delay += 0.01 * usecs_late; 
    219  
    220237    // FIXME: priority inversion! 
    221238    ENTER_CRITICAL_SECTION; 
    222     m_current_vars.ticks = m_current_time_ticks
    223     m_current_vars.usecs = m_current_time_usecs; 
     239    m_current_vars.ticks = (uint64_t)(m_current_time_ticks);// + m_average_offset_ticks)
     240    m_current_vars.usecs = (uint64_t)m_current_time_usecs; 
    224241    m_current_vars.rate = getRate(); 
    225242    EXIT_CRITICAL_SECTION; 
    226243 
    227     // wait for the next update period 
    228     int64_t time_to_sleep = (int64_t)m_next_time_usecs - m_Parent.getCurrentTimeAsUsecs(); 
    229     time_to_sleep -= (int64_t)m_avg_wakeup_delay; 
    230     //int64_t time_to_sleep = m_usecs_per_update; 
    231     if (time_to_sleep > 0) { 
    232         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " sleeping %lld usecs (avg delay: %f)\n", time_to_sleep, m_avg_wakeup_delay); 
    233         usleep(time_to_sleep); 
    234     } 
    235244    return true; 
    236245} 
     
    254263    EXIT_CRITICAL_SECTION; 
    255264 
    256     double time_diff = now - my_vars.usecs; 
    257     double y_step_in_ticks = time_diff * my_vars.rate; 
     265    int64_t time_diff = now - my_vars.usecs; 
     266    double y_step_in_ticks = ((double)time_diff) * my_vars.rate; 
    258267    int64_t y_step_in_ticks_int = (int64_t)y_step_in_ticks; 
    259     uint64_t offset_in_ticks_int = (uint64_t)my_vars.ticks; 
     268    uint64_t offset_in_ticks_int = my_vars.ticks; 
    260269 
    261270    if (y_step_in_ticks_int > 0) { 
     
    277286CycleTimerHelper::getCycleTimer() 
    278287{ 
    279     return TICKS_TO_CYCLE_TIMER(getCycleTimerTicks()); 
     288    uint64_t now = m_Parent.getCurrentTimeAsUsecs(); 
     289    return getCycleTimer(now); 
    280290} 
    281291 
     
    283293CycleTimerHelper::getCycleTimer(uint64_t now) 
    284294{ 
    285     return TICKS_TO_CYCLE_TIMER(getCycleTimerTicks(now)); 
     295    uint32_t ticks = getCycleTimerTicks(now); 
     296    uint32_t result = TICKS_TO_CYCLE_TIMER(ticks); 
     297#ifdef DEBUG 
     298    if(CYCLE_TIMER_TO_TICKS(result) != ticks) { 
     299        debugWarning("Bad ctr conversion"); 
     300    } 
     301#endif 
     302    return result; 
    286303} 
    287304 
    288305#else 
     306 
     307float 
     308CycleTimerHelper::getRate() 
     309{ 
     310    return getNominalRate(); 
     311} 
     312 
     313float 
     314CycleTimerHelper::getNominalRate() 
     315{ 
     316    float rate = ((double)TICKS_PER_SECOND) / 1000000.0; 
     317    return rate; 
     318} 
    289319 
    290320bool 
     
    309339CycleTimerHelper::getCycleTimerTicks(uint64_t now) 
    310340{ 
     341    debugWarning("not implemented!\n"); 
    311342    return getCycleTimerTicks(); 
    312343} 
     
    327358CycleTimerHelper::getCycleTimer(uint64_t now) 
    328359{ 
     360    debugWarning("not implemented!\n"); 
    329361    return getCycleTimer(); 
    330362} 
  • trunk/libffado/src/libieee1394/CycleTimerHelper.h

    r752 r863  
    2121 * 
    2222 */ 
    23  
    24 #include "libutil/Thread.h" 
    25 #include "cycletimer.h" 
     23#ifndef __CYCLETIMERHELPER_H__ 
     24#define __CYCLETIMERHELPER_H__ 
    2625 
    2726/** 
     
    5049 * different clock domains to operate together. 
    5150 */ 
    52 #ifndef __CYCLETIMERTHREAD_H__ 
    53 #define __CYCLETIMERTHREAD_H__ 
     51 
     52#include "libutil/Thread.h" 
     53#include "libutil/SystemTimeSource.h" 
     54#include "cycletimer.h" 
    5455 
    5556#include "debugmodule/debugmodule.h" 
    5657 
    5758class Ieee1394Service; 
    58 namespace Util { 
    59     class TimeSource; 
    60     class Thread; 
    61 } 
    6259 
    6360class CycleTimerHelper : public Util::RunnableInterface 
     
    105102private: 
    106103    Ieee1394Service &m_Parent; 
     104    Util::SystemTimeSource m_TimeSource; 
    107105    // parameters 
    108106    uint32_t m_ticks_per_update; 
     
    119117    double m_next_time_ticks; 
    120118    bool m_first_run; 
     119    ffado_microsecs_t m_sleep_until; 
    121120 
    122121    // cached vars used for computation 
    123122    struct compute_vars { 
    124         double usecs; 
    125         double ticks; 
     123        uint64_t usecs; 
     124        uint64_t ticks; 
    126125        double rate; 
    127126    }; 
  • trunk/libffado/src/libieee1394/ieee1394service.cpp

    r807 r863  
    5353    , m_base_priority ( 0 ) 
    5454    , m_pIsoManager( new IsoHandlerManager( *this ) ) 
    55     , m_pCTRHelper ( new CycleTimerHelper( *this, 10000 ) ) 
     55    , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC ) ) 
    5656    , m_have_new_ctr_read ( false ) 
    5757    , m_pTimeSource ( new Util::SystemTimeSource() ) 
     
    7777    , m_base_priority ( prio ) 
    7878    , m_pIsoManager( new IsoHandlerManager( *this, rt, prio + IEEE1394SERVICE_ISOMANAGER_PRIO_INCREASE ) ) 
    79     , m_pCTRHelper ( new CycleTimerHelper( *this, 1000, rt, prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE ) ) 
     79    , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC, 
     80                                           rt, prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE ) ) 
    8081    , m_have_new_ctr_read ( false ) 
    8182    , m_pTimeSource ( new Util::SystemTimeSource() ) 
     
    318319} 
    319320 
     321/** 
     322 * Returns the current value of the cycle timer (in ticks) 
     323 * for a specific time instant (usecs since epoch) 
     324 * @return the current value of the cycle timer (in ticks) 
     325 */ 
     326 
     327uint32_t 
     328Ieee1394Service::getCycleTimerTicks(uint64_t t) { 
     329    return m_pCTRHelper->getCycleTimerTicks(t); 
     330} 
     331 
     332/** 
     333 * Returns the current value of the cycle timer (as is) 
     334 * for a specific time instant (usecs since epoch) 
     335 * @return the current value of the cycle timer (as is) 
     336 */ 
     337uint32_t 
     338Ieee1394Service::getCycleTimer(uint64_t t) { 
     339    return m_pCTRHelper->getCycleTimer(t); 
     340} 
     341 
    320342bool 
    321343Ieee1394Service::readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time) 
     
    10651087Ieee1394Service::show() 
    10661088{ 
     1089    uint32_t cycle_timer; 
     1090    uint64_t local_time; 
     1091    if(!readCycleTimerReg(&cycle_timer, &local_time)) { 
     1092        debugWarning("Could not read cycle timer register\n"); 
     1093    } 
     1094    uint64_t ctr = CYCLE_TIMER_TO_TICKS( cycle_timer ); 
     1095 
    10671096    debugOutput( DEBUG_LEVEL_VERBOSE, "Port:  %d\n", getPort() ); 
    10681097    debugOutput( DEBUG_LEVEL_VERBOSE, " Name: %s\n", getPortName().c_str() ); 
     1098    debugOutput( DEBUG_LEVEL_VERBOSE, " Time: %011llu (%03us %04ucy %04uticks)\n", 
     1099                ctr, 
     1100                (unsigned int)TICKS_TO_SECS( ctr ), 
     1101                (unsigned int)TICKS_TO_CYCLES( ctr ), 
     1102                (unsigned int)TICKS_TO_OFFSET( ctr ) ); 
    10691103    debugOutputShort( DEBUG_LEVEL_NORMAL, "Iso handler info:\n"); 
    10701104    if (m_pIsoManager) m_pIsoManager->dumpInfo(); 
  • trunk/libffado/src/libieee1394/ieee1394service.h

    r752 r863  
    115115     */ 
    116116    uint32_t getCycleTimer(); 
     117 
     118    /** 
     119     * @brief get the cycle timer value for a specific time instant (in ticks) 
     120     * 
     121     * @note Uses the most appropriate method for getting the cycle timer 
     122     *       which is not necessarily a direct read (could be DLL) 
     123     */ 
     124    uint32_t getCycleTimerTicks(uint64_t t); 
     125 
     126    /** 
     127     * @brief get the cycle timer value for a specific time instant (in CTR format) 
     128     * 
     129     * @note Uses the most appropriate method for getting the cycle timer 
     130     *       which is not necessarily a direct read (could be DLL) 
     131     */ 
     132    uint32_t getCycleTimer(uint64_t t); 
    117133 
    118134    /** 
  • trunk/libffado/src/libutil/SystemTimeSource.cpp

    r787 r863  
    2525#include "Time.h" 
    2626 
     27// needed for clock_nanosleep 
     28#ifndef _GNU_SOURCE 
     29    #define _GNU_SOURCE 
     30#endif 
     31 
     32#include <time.h> 
     33 
    2734namespace Util { 
    2835 
     
    3744void 
    3845SystemTimeSource::SleepUsecRelative(ffado_microsecs_t usecs) { 
    39     usleep(usecs); 
     46    //usleep(usecs); 
     47    struct timespec ts; 
     48    ts.tv_sec = usecs / (1000000LL); 
     49    ts.tv_nsec = (usecs % (1000000LL)) * 1000LL; 
     50    clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL); 
    4051} 
    4152 
    4253void 
    43 SystemTimeSource::SleepUsecAbsolute(ffado_microsecs_t wake_at) { 
    44     // FIXME: not implemented yet 
     54SystemTimeSource::SleepUsecAbsolute(ffado_microsecs_t wake_at_usec) { 
     55    struct timespec ts; 
     56    ts.tv_sec = wake_at_usec / (1000000LL); 
     57    ts.tv_nsec = (wake_at_usec % (1000000LL)) * 1000LL; 
     58    clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL); 
    4559} 
    4660 
     
    5064//     return tv.tv_sec * 1000000ULL + tv.tv_usec; 
    5165    struct timespec ts; 
    52     clock_gettime(CLOCK_MONOTONIC, &ts); 
     66    clock_gettime(CLOCK_REALTIME, &ts); 
    5367    return (ffado_microsecs_t)(ts.tv_sec * 1000000LL + ts.tv_nsec / 1000LL); 
    5468} 
  • trunk/libffado/tests/test-ieee1394service.cpp

    r862 r863  
    4747 
    4848 
    49     #define NB_THREADS 3 
    50     #define THREAD_RT true 
    51     #define THREAD_PRIO 90 
    52     #define THREAD_SLEEP_US 100 
     49    #define NB_THREADS 1 
     50    #define THREAD_RT true 
     51    #define THREAD_PRIO 51 
     52    #define THREAD_SLEEP_US 2000 
    5353     
    5454using namespace Util; 
     
    5656DECLARE_GLOBAL_DEBUG_MODULE; 
    5757 
    58 #define DIFF_CONSIDERED_LARGE 30720 
    59 int PORT_TO_USE = 0; 
     58#define DIFF_CONSIDERED_LARGE (3027/2) 
     59int PORT_TO_USE = 1; 
     60 
     61int max_diff=-99999; 
     62int min_diff= 99999; 
    6063 
    6164int run=1; 
     
    130133     
    131134    ctr = CYCLE_TIMER_TO_TICKS( cycle_timer ); 
    132     ctr_dll = m_service->getCycleTimerTicks(); 
     135    ctr_dll = m_service->getCycleTimerTicks(local_time); 
    133136 
    134137    if(err) { 
     
    149152    int64_t diff = diffTicks(ctr, ctr_dll); 
    150153    uint64_t abs_diff; 
     154 
     155    // not 100% thread safe, but will do 
     156    if (diff > max_diff) max_diff = diff; 
     157    if (diff < min_diff) min_diff = diff; 
    151158 
    152159    if (diff < 0) { 
     
    255262 
    256263    m_service = new Ieee1394Service(); 
    257     m_service->setVerboseLevel(DEBUG_LEVEL_VERBOSE ); 
     264    m_service->setVerboseLevel(DEBUG_LEVEL_VERBOSE); 
    258265    m_service->initialize(PORT_TO_USE); 
    259     m_service->setThreadParameters(true, 20); 
     266    m_service->setThreadParameters(true, 60); 
    260267 
    261268    MyFunctor *test_busreset=new MyFunctor(); 
     
    315322    while(run) { 
    316323        i++; 
    317         debugOutput(DEBUG_LEVEL_NORMAL, "%08d: alive...\n", i); 
     324        debugOutput(DEBUG_LEVEL_NORMAL, "%08d: alive, (max: %6d, min: %6d)\n", i, max_diff, min_diff); 
     325        m_service->show(); 
    318326        sleep(5); 
    319327    }