/* Cesar project {{{ * * Copyright (C) 2009 Spidcom * * <<>> * * }}} */ /** * \file cl/src/data_rate.c * \brief Data rate functions. * \ingroup cl */ #include "common/std.h" #include "cl/data_rate.h" #include "hal/phy/phy.h" #if defined (ECOS) && ECOS # include #endif #define div(a, b) ((a+((b)/2))/(b)) void data_rate_update_info (cl_data_rate_t *p_dr, uint data_size) { static u32 period_tck = 0; static u64 period_rtc = 0; u64 new_time_rtc_date; /* in ecos tick */ u32 new_time_date; /* in phy ticks (40ns so far) */ u32 interval_tck; /* delay between last time and now (in phy ticks) */ u64 new_rate; /* in octets per phy ticks */ /* This is the period (in ns) over which the data rate is evaluated */ u32 period_ns = 1000000000; if (!period_tck) { /* evaluate the periods phy tick counts only once for all */ #if defined (ECOS) && ECOS /* period_rtc is calculated on a u64 to avoid overflow and keep * maximum precision when the division is done. */ cyg_resolution_t res = cyg_clock_get_resolution (cyg_real_time_clock ()); period_rtc = (u32) div((u64)period_ns * res.divisor, res.dividend); #else period_rtc = 1000; #endif period_tck = div(period_ns, 40); } /* Get delay between last time data rate was evaluated and now */ #if defined (ECOS) && ECOS new_time_rtc_date = cyg_current_time (); #else new_time_rtc_date = 0; #endif new_time_date = phy_date (); if (((p_dr->data_rate == CL_DATA_RATE_REQ_INIT) || (new_time_rtc_date - p_dr->data_rate_rtc_date) > period_rtc)) { /* maximise the delay when the interval is larger than the period * and when it's the first data for this data rate. */ interval_tck = period_tck; } else { /* mesure delay with phy time */ interval_tck = new_time_date - p_dr->data_rate_date; } if (interval_tck >= period_tck) { /* mesure the new rate over one period */ new_rate = data_size; } else { /* fine mesure of the delay with phy clock */ new_rate = (u64)(p_dr->data_rate) * (period_tck - interval_tck); new_rate = div(new_rate, period_tck) + data_size; } /* update the data_rate structure */ p_dr->data_rate = (u32)new_rate; p_dr->data_rate_date = new_time_date; p_dr->data_rate_rtc_date = new_time_rtc_date; }