ss_time_lib.c

00001 
00002 #include "edtinc.h"
00003 #include "edt_ss_vco.h"
00004 #include "edt_bitload.h"
00005 #include "edt_threads.h"
00006 
00007 #include <sys/timeb.h>
00008 
00009 #ifdef WIN32
00010 #include <process.h>
00011 #endif
00012 
00013 
00014 #include <math.h>
00015 
00016 #include "ss_time_lib.h"
00017 
00018 
00019 
00020 #define USECS_FACTOR  (1000000.0 / (double) (1 << 20))
00021 
00022 /*
00023  * return the microseconds value for the current second 
00024  *
00025  */
00026 
00027 #ifdef WIN32
00028 
00029 static int usecs_difference = 0;
00030 static int usecs_calibrated = 0;
00031 static double realtime_diff = 0.0;
00032 
00033 #define POLL_MARGIN 975
00034 
00035 void edt_calibrate_usecs()
00036 
00037 {
00038     int i;
00039     int loops = 1;
00040     time_t t, t1;
00041     struct timeb tb1;
00042     double sum = 0.0, dtsum = 0.0, whole, frac, last_frac = 0,
00043             trend = 0, dt;
00044     /* look for zero-crossing */
00045 
00046 
00047     /*  uses edt_timestamp() */
00048 
00049     for (i=0;i<loops;i++)
00050     {
00051         ftime(&tb1);
00052 
00053         if (tb1.millitm < POLL_MARGIN)
00054             Sleep(POLL_MARGIN - tb1.millitm);
00055 
00056         t1 = time(&t);
00057 
00058         do {
00059             t = time(&t);
00060             dt = edt_timestamp();
00061         } while (t == t1);
00062 
00063         frac = modf(dt, &whole);
00064         trend = frac - last_frac;
00065         last_frac = frac;
00066         printf("frac = %f trend= %f\n", frac, trend);
00067         sum += frac;
00068         dtsum += (dt - t);
00069 
00070     }
00071 
00072     usecs_difference = (u_int) ((sum / (double) loops) * 1000000.0);
00073     realtime_diff = (dtsum / (double) loops);
00074     printf("usecs_difference = %d realtime_diff = %f\n", usecs_difference, realtime_diff);
00075     usecs_calibrated = 1;
00076 
00077 }
00078 
00079 #if 0
00080 
00081 void edt_calibrate_usecs_mm()
00082 
00083 {
00084     int i;
00085     int loops = 1;
00086     time_t t, t1;
00087     double sum = 0.0, dtsum = 0.0, whole, frac,dt;
00088     struct timeb tb1;
00089     int ms1, ms2;
00090 
00091     /* look for zero-crossing */
00092  
00093     /* uses timeGetTime at 1 ms accuracy */
00094 
00095     for (i=0;i<loops;i++)
00096     {
00097         ftime(&tb1);
00098 
00099         if (tb1.millitm < POLL_MARGIN)
00100             Sleep(POLL_MARGIN - tb1.millitm);
00101 
00102         t1 = time(&t1);
00103 
00104         do {
00105             
00106             ms1 = timeGetTime();
00107             t = time(&t);
00108             ms2 = timeGetTime();
00109 
00110         } while (t == t1);
00111 
00112         /* average  */
00113         dt = (double) ms1 * 0.001;
00114 
00115         frac = modf(dt, &whole);
00116         printf("frac = %f\n", frac);
00117         sum += frac;
00118         dtsum += (dt - t);
00119 
00120     }
00121 
00122     usecs_difference = (u_int) ((sum / (double) loops) * 1000000.0);
00123     realtime_diff = (dtsum / (double) loops);
00124 
00125     printf("usecs_difference = %d realtime_diff = %f\n", usecs_difference, realtime_diff);
00126     usecs_calibrated = 1;
00127 
00128 }
00129 
00130 #endif
00131 
00132 double
00133 edt_sys_timestamp()
00134 
00135 {
00136 #ifdef USE_MM_TIMER
00137     int ms;
00138 #endif
00139 
00140     double t;
00141 
00142     if (!usecs_calibrated)
00143         edt_calibrate_usecs();
00144 
00145 #ifdef USE_MM_TIMER
00146     ms = timeGetTime();
00147 
00148     t = ((double) ms * 0.001);
00149 #else
00150     t = edt_timestamp();
00151 #endif
00152 
00153     return t - realtime_diff;
00154 
00155 }
00156 
00157 
00158 
00159 #else
00160 
00161 #define edt_sys_timestamp edt_timestamp
00162 
00163 #endif
00164 
00172 int 
00173 edt_usecs()
00174 
00175 {
00176 
00177 #ifdef WIN32
00178     
00179     double t;
00180 
00181     if (!usecs_calibrated)
00182         edt_calibrate_usecs();
00183 
00184     t = (edt_sys_timestamp() * 1000000.0);
00185     t = fmod(t, 1000000.0);
00186 
00187     return (int) t;
00188 
00189 #elif defined(VXWORKS)
00190 
00191     struct timespec     endtime ;
00192     clock_gettime(CLOCK_REALTIME,&endtime);
00193     return endtime.tv_nsec / 1000;
00194 
00195 #else                           /* _NT_ */
00196     struct timeval endtime;
00197 
00198     gettimeofday(&endtime, (void *) NULL);
00199 
00200     return endtime.tv_usec;
00201 
00202 #endif                          /* _NT_ */
00203 
00204 }
00205 
00206 /* used to compensate for time between end of wait and 
00207    actual zero-crossing */
00208 
00209 static int wait_zero_offset = 0;
00210 static int wait_zero_calibrated = 0;
00211 
00212 /*
00213  *
00214  * Wait for system time zero-crossing 
00215  * margin is #of microseconds before zero to satisfy wait
00216  * (normally wait_zero_offset)
00217  *
00218  */
00219 
00220  
00221 static void
00222 edt_wait_for_zero(int margin)
00223 
00224 {
00225     int usec;
00226     int lastusec = 0;
00227 
00228     int test = 1000000 - margin;
00229 
00230     usec = edt_usecs();
00231 
00232     edt_msleep(1000 - (usec/1000) - 100);
00233     while (usec < test && usec >= lastusec)
00234     {
00235         lastusec = usec;
00236         
00237         usec = edt_usecs();
00238     }
00239 }
00240 
00249 void 
00250 edt_sstm_setup(EdtDev *edt_p, char *bitfile)
00251 
00252 {
00253 
00254     if (bitfile)
00255         edt_bitload(edt_p, ".", bitfile, 0, 0);
00256     else 
00257         edt_bitload(edt_p, ".", "c3_demux.bit", 0, 0);
00258 }
00259 
00279 void edt_sstm_strobe(EdtDev *edt_p, unsigned int bits)
00280 
00281 {
00282     int cmd;
00283     int count = 0;
00284 
00285     do
00286     {
00287         cmd = edt_reg_read(edt_p, EDT_SSTM_CMD);
00288         if (cmd & EDT_SSTM_CMD_LOCK)
00289             edt_msleep(0);
00290     } while (cmd & EDT_SSTM_CMD_LOCK && (count++ < 5));
00291 
00292     
00293     cmd &= 0x70;
00294     
00295     edt_reg_write(edt_p, EDT_SSTM_CMD, cmd | EDT_SSTM_CMD_LOCK);
00296 
00297     edt_reg_write(edt_p, EDT_SSTM_CMD, cmd | bits);
00298 }
00299 
00300 /*
00301  *
00302  * attempt to find the delta between the zero crossing and setting the 
00303  * strobe register value, to offset the wait to be as close to 
00304  * zero as possible 
00305  * uses ZERO_OFFSET_MAX check to avoid occasional snoozes
00306  *
00307  */
00308 
00309 static void
00310 edt_sstm_calibrate_wait(EdtDev *edt_p)
00311 
00312 {
00313 
00314     int i1, i2;
00315 
00316     if (wait_zero_calibrated)
00317         return;
00318 
00319     do 
00320     {
00321         edt_wait_for_zero(0);
00322 
00323         i1 = edt_usecs();
00324 
00325         edt_sstm_strobe(edt_p, 0);
00326 
00327         i2  = edt_usecs();
00328 
00329         wait_zero_offset = (i1+i2)/2;
00330         printf("wait_zero_offset = (%d + %d) / 2 = %d\n", 
00331                i1, i2, wait_zero_offset);
00332   
00333     } while (wait_zero_offset > EDT_SSTM_ZERO_OFFSET_MAX);
00334         
00335 }
00336 
00342 void edt_sstm_latch_time(EdtDev *edt_p)
00343 
00344 {
00345     edt_sstm_strobe(edt_p, EDT_SSTM_LATCH);
00346 }
00347 
00354 int edt_sstm_get_adjust_enabled(EdtDev *edt_p)
00355 
00356 {
00357     int cfg = edt_reg_read(edt_p, EDT_SSTM_CMD);
00358 
00359     if (cfg & EDT_SSTM_ADJ_EN)
00360         return 1;
00361     else
00362         return 0;
00363  
00364 }
00365 
00373 int edt_sstm_get_adjust_sign(EdtDev *edt_p)
00374 
00375 {
00376     int cfg = edt_reg_read(edt_p, EDT_SSTM_CMD);
00377 
00378     if (cfg & EDT_SSTM_ADJ_PLUS)
00379         return 1;
00380     else
00381         return -1;
00382  
00383 }
00384 
00390 u_int edt_sstm_get_adjust_ticks(EdtDev *edt_p)
00391 
00392 {
00393      
00394     return edt_sstm_get_adjust_sign(edt_p) *
00395             edt_reg_read(edt_p, EDT_SSTM_ADJ_VALUE);
00396 }
00397 
00398 
00404 u_int edt_sstm_get_seconds(EdtDev *edt_p)
00405 
00406 {
00407     return edt_reg_read(edt_p, EDT_SSTM_SECS);
00408 }
00409 
00416 u_int edt_sstm_get_counts(EdtDev *edt_p)
00417 
00418 {
00419     return edt_reg_read(edt_p, EDT_SSTM_COUNTS) >> 12;
00420 }
00421 
00432 u_int 
00433 edt_sstm_get_usecs(EdtDev *edt_p)
00434 
00435 {
00436     u_int count = edt_sstm_get_counts(edt_p);
00437     
00438     return (u_int) (count * USECS_FACTOR);
00439     
00440 }
00441 
00453 void 
00454 edt_sstm_get_time_parts(EdtDev *edt_p, u_int *seconds, u_int *usecs)
00455 
00456 {
00457     edt_sstm_latch_time(edt_p);
00458 
00459     *seconds = edt_sstm_get_seconds(edt_p);
00460     *usecs = edt_sstm_get_usecs(edt_p);
00461 }
00462 
00470 double 
00471 edt_sstm_timestamp(EdtDev *edt_p)
00472 
00473 {
00474 
00475     edt_sstm_latch_time(edt_p);
00476         
00477     return (double) edt_sstm_get_seconds(edt_p) + 
00478         (0.000001) * (USECS_FACTOR) * edt_sstm_get_counts(edt_p);
00479 }
00480 
00491 void edt_sstm_set_secs(EdtDev *edt_p, unsigned int second)
00492 
00493 {
00494     edt_reg_write(edt_p, EDT_SSTM_SET, second);
00495     edt_sstm_strobe(edt_p, EDT_SSTM_COPY);
00496 }
00497 
00498 
00508 void edt_sstm_set(EdtDev *edt_p, unsigned int second)
00509 
00510 {
00511     edt_reg_write(edt_p, EDT_SSTM_SET, second+1);
00512     edt_wait_for_zero(wait_zero_offset);
00513     edt_sstm_strobe(edt_p, EDT_SSTM_COPY);
00514 }
00515 
00523 void edt_sstm_set_to_sys(EdtDev *edt_p)
00524 
00525 {
00526     time_t t;
00527     edt_sstm_calibrate_wait(edt_p);
00528     edt_wait_for_zero(0);
00529     edt_msleep(500);
00530     t = time(&t);
00531     edt_sstm_set(edt_p, (u_int) t);
00532 }
00533 
00542 void edt_sstm_set_to_sys_error(EdtDev *edt_p, int error)
00543 
00544 {
00545     time_t t;
00546     edt_sstm_calibrate_wait(edt_p);
00547     edt_wait_for_zero(0);
00548     edt_msleep(500);
00549     t = time(&t);
00550     if (error < 0)
00551     {
00552         edt_reg_write(edt_p, EDT_SSTM_SET, (uint_t) (t + ( error / 1000 )) );
00553         edt_wait_for_zero(wait_zero_offset);
00554 
00555         edt_msleep(1000 - (abs(error) % 1000));
00556         edt_sstm_strobe(edt_p, EDT_SSTM_COPY);
00557 
00558     }
00559     else
00560     {
00561 
00562         edt_reg_write(edt_p, EDT_SSTM_SET, (uint_t) (t + 1 + error / 1000));
00563         edt_wait_for_zero(wait_zero_offset);
00564 
00565         edt_msleep(error % 1000);
00566 
00567         edt_sstm_strobe(edt_p, EDT_SSTM_COPY);
00568 
00569     }
00570 }
00571 
00578 void edt_sstm_disable_adjust(EdtDev *edt_p)
00579 
00580 {
00581     edt_reg_and(edt_p, EDT_SSTM_CMD, ~EDT_SSTM_ADJ_EN);
00582 }
00583 
00590 void edt_sstm_enable_adjust(EdtDev *edt_p)
00591 
00592 {
00593     edt_reg_or(edt_p, EDT_SSTM_CMD,  EDT_SSTM_ADJ_EN );
00594 }
00595 
00603 void edt_sstm_set_adj_sign(EdtDev *edt_p, int positive)
00604 
00605 {
00606     edt_reg_and(edt_p, EDT_SSTM_CMD, ~EDT_SSTM_ADJ_PLUS);
00607     edt_reg_or(edt_p, EDT_SSTM_CMD,  ((positive)?EDT_SSTM_ADJ_PLUS:0));
00608 }
00609 
00623 void edt_sstm_set_adj_ticks(EdtDev *edt_p, int ticks, int positive)
00624 
00625 {
00626     edt_reg_write(edt_p, EDT_SSTM_SET, abs(ticks));
00627  
00628     edt_sstm_disable_adjust(edt_p);
00629     edt_sstm_strobe(edt_p, EDT_SSTM_COPY_ADJ );
00630     edt_sstm_set_adj_sign(edt_p, positive);
00631     edt_sstm_enable_adjust(edt_p);
00632 
00633     printf("set adj to %d\n", ticks);
00634 }
00635 
00648 double edt_sstm_sys_error(EdtDev *edt_p)
00649 
00650 {
00651     double t1, t2, st1;
00652     t1 = edt_sstm_timestamp(edt_p);
00653     st1 = edt_sys_timestamp();
00654     t2 = edt_sstm_timestamp(edt_p);
00655     return ((t1 + t2) * 0.5) - st1;
00656 }
00657 
00667 char *
00668 edt_printable_time(double sys_t, char *buf)
00669 
00670 {
00671     time_t t;
00672     struct tm *ltime;
00673     int usecs;
00674     double whole;
00675     static char sbuf[17];
00676     char *cp = buf;
00677 
00678     if (!cp)
00679         cp = sbuf;
00680 
00681     t = (time_t) sys_t;
00682     
00683     ltime = localtime(&t);
00684 
00685     if (!ltime)
00686         return buf;
00687 
00688     usecs = (int) (modf(sys_t,&whole) * 1000000.0);
00689 
00690     sprintf(cp, "%02d:%02d:%02d.%06d",
00691            ltime->tm_hour, ltime->tm_min, ltime->tm_sec, usecs);
00692 
00693     return cp;
00694 }
00695 
00696 
00705 double
00706 edt_sstm_print(EdtDev *edt_p)
00707 
00708 {
00709     double error, sys_t;
00710     char printbuf[32];
00711 
00712     sys_t = edt_sys_timestamp();
00713  
00714     error = edt_sstm_sys_error(edt_p);  
00715 
00716     printf("%s    %.6f\n", edt_printable_time(sys_t, printbuf),error);
00717 
00718     return error;
00719 
00720 }
00721 
00722 
00723 static double
00724 double_mean(double *v, int n)
00725 
00726 {
00727     double sum = 0.0;
00728     int i;
00729 
00730     for (i=0;i<n;i++)
00731         sum += v[i];
00732 
00733     return (sum / (double) n);
00734 }
00735 
00736 static int
00737 double_compare(const void *p1, const void *p2)
00738 
00739 {
00740     double d1 = *(double *) p1;
00741     double d2 = *(double *) p2;
00742 
00743     return (d1 > d2)?1:((d1 == d2)?0:-1);
00744 }
00745 
00746 
00747 
00748 static int adj_sample_seconds = 3;
00749 static int adj_samples = 10;
00750 
00758 void edt_sstm_set_drift_sampling(int seconds, int samples)
00759 
00760 {
00761     adj_sample_seconds = seconds;
00762     adj_samples = samples;
00763 }
00764 
00773 int edt_sstm_get_adj_sample_secs()
00774 
00775 {
00776     return adj_sample_seconds;
00777 }
00778 
00787 int edt_sstm_get_adj_samples()
00788 
00789 {
00790     return adj_samples;
00791 }
00792 
00793 
00794 
00801 int edt_sstm_ticks_from_drift(double drift)
00802 
00803 {
00804     int ticks;
00805 
00806     if (drift == 0.0)
00807         return EDT_SSTM_MAX_ADJ;
00808 
00809     ticks = (int) ((1000000.0 / drift) * USECS_FACTOR);
00810 
00811     return ticks;
00812 }
00813 
00822 void edt_sstm_set_adj_from_drift(EdtDev *edt_p, double drift)
00823 
00824 {
00825     int ticks = (int) edt_sstm_ticks_from_drift(drift);
00826 
00827     edt_sstm_set_adj_ticks(edt_p, ticks, (drift >= 0.0));
00828 
00829    
00830 }
00831 
00842 double edt_sstm_measure_drift(EdtDev *edt_p)
00843 
00844 {
00845     
00846     double t1 = 0, t2 = 0, st1 = 0, st2 = 0;
00847 
00848     double *d1_v = NULL, *d2_v = NULL, *st1_v = NULL, *st2_v = NULL;
00849 
00850     double d1, d2;
00851     double drift;
00852     double extraticks;
00853 
00854     int i;
00855     int count;
00856     int adj_state = edt_reg_read(edt_p, EDT_SSTM_CMD) & EDT_SSTM_ADJ_EN;
00857     int sleep_interval = adj_sample_seconds * 1000000;
00858 
00859     edt_sstm_timestamp(edt_p);
00860 
00861     edt_sstm_disable_adjust(edt_p);
00862 
00863 
00864     d1_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00865     d2_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00866     st1_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00867     st2_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00868 
00869 
00870     printf("Sampling basic error rate ...\n");
00871     edt_usleep(100);
00872 
00873     t1 = 0;
00874     st1 = 0;
00875     t2 = 0;
00876     st2 = 0;
00877     d1 = 0;
00878     d2 = 0;
00879 
00880     t1 = edt_sstm_timestamp(edt_p);
00881     count = 0;
00882 
00883     for (i=0;i<adj_samples;i++)
00884     {
00885         st1 = edt_sys_timestamp();
00886         d1_v[count] = (st1 - t1);
00887         t1 = edt_sstm_timestamp(edt_p);
00888         d1_v[count+1] = (st1 - t1);
00889         count += 2;
00890         st1_v[i] = st1;
00891     }
00892 
00893     edt_usleep(sleep_interval);
00894             
00895     t2 = edt_sstm_timestamp(edt_p);
00896        
00897     count = 0;
00898 
00899     for (i=0;i<adj_samples;i++)
00900     {
00901         st2 = edt_sys_timestamp();
00902         d2_v[count] = (st2 - t2);
00903         t2 = edt_sstm_timestamp(edt_p);
00904         d2_v[count+1] = (st2 - t2);
00905         count += 2;
00906         st2_v[i] = st2;
00907     }
00908     
00909     /* calc means, remove outliers, then recalc */
00910     /* first sort arrays */
00911     qsort(d1_v, adj_samples * 2, sizeof(double), double_compare);
00912     qsort(d2_v, adj_samples * 2, sizeof(double), double_compare);
00913     qsort(st1_v, adj_samples, sizeof(double), double_compare);
00914     qsort(st2_v, adj_samples, sizeof(double), double_compare);
00915 
00916     /* find median of each array */
00917     /* toss out high and low */
00918 
00919     d1 = double_mean(d1_v + 2, (adj_samples-2) * 2);
00920     d2 = double_mean(d2_v + 2, (adj_samples-2) * 2);
00921     st1 = double_mean(st1_v + 1, adj_samples-2);
00922     st2 = double_mean(st2_v + 1, adj_samples-2);
00923  
00924 
00925     d1 *= 1000000.0;
00926     d2 *= 1000000.0;
00927 
00928     drift = (d2 - d1) / (st2 - st1);
00929 
00930 #ifdef VERBOSE
00931 
00932     printf("d1 = %.6f d2 = %.6f\n",     d1, d2);
00933     printf("st1 = %.6f st2 = %.6f\n",   st1, st2);
00934 
00935     for (i=0;i<adj_samples*2;i++)
00936     {
00937         printf("d1_v[%d] = %.5f d2_v[%d] = %.6f\n",
00938                 i, d1_v[i], i, d2_v[i]);
00939     }
00940 
00941     for (i=0;i<adj_samples;i++)
00942     {
00943         printf("st1_v[%d] = %.5f st2_v[%d] = %.6f\n",
00944                 i, st1_v[i], i, st2_v[i]);
00945     }
00946 #endif
00947 
00948     extraticks = edt_sstm_ticks_from_drift(drift);
00949 
00950     printf("drift in %.0f secs = %.1f ticks = %.0f\n", 
00951            (st2 - st1), 
00952            drift, 
00953            extraticks);
00954 
00955     /* turn asjust back to start value */
00956     if (adj_state)
00957         edt_reg_or(edt_p, EDT_SSTM_CMD, EDT_SSTM_ADJ_EN);
00958         
00959     free(d1_v);
00960     free(d2_v);
00961     free(st1_v);
00962     free(st2_v);
00963 
00964     return drift;
00965 }
00966 
00967 
00968 
00980 double edt_sstm_calc_convergence(EdtDev *edt_p, 
00981                              int revert_secs,
00982                              double drift)
00983 
00984 {
00985     double errordrift = 0.0;
00986     
00987     if (revert_secs)
00988     {
00989         /* find total error */
00990 
00991         double error = -edt_sstm_sys_error(edt_p);
00992 
00993         errordrift = (error * 1000000.0 / (double) revert_secs) + drift;
00994 
00995         printf("error = %.6f drift = %.0f converge with %.0f\n",
00996                 error, drift, errordrift);
00997     }
00998 
00999     return errordrift;
01000 }  
01001 
01017 double edt_sstm_adjust(EdtDev *edt_p,
01018                               double converge, 
01019                               double drift,
01020                               int *active)
01021                             
01022 {
01023     int sign,
01024         start_sign;
01025     double err;
01026     double lasterr;
01027     double convergecheck;
01028     int go = 1;
01029     int duration;
01030     int i;
01031 
01032     err = edt_sstm_sys_error(edt_p);
01033     sign = start_sign = err > 0;
01034     err = fabs(err);
01035 
01036     convergecheck = fabs(converge)*0.000001;
01037 
01038     duration = (int) (err/convergecheck) * 5;
01039 
01040     printf("duration = %d\n", duration);
01041 
01042     edt_sstm_set_adj_from_drift(edt_p, converge);
01043 
01044     for (i=0;i<duration  && 
01045         (err > convergecheck) && go && (sign == start_sign);i++)
01046     {
01047 
01048         edt_msleep(200);
01049         lasterr = err;
01050         err = edt_sstm_sys_error(edt_p);
01051         sign = err > 0;
01052         err = fabs(err);
01053 
01054         /* only check active flag if non-NULL */
01055         if (active)
01056             go = *active;
01057         
01058     } 
01059 
01060     printf("done with i = %d err = %.6f check = %.6f sign = %d\n",
01061             i, err, convergecheck, sign);
01062 
01063     edt_sstm_set_adj_from_drift(edt_p, drift);
01064 
01065     return err;
01066 }
01067 
01083 void edt_sstm_iterate_adjust(EdtDev *edt_p, 
01084                              int revert_secs,
01085                              int maxiterations,
01086                              int tolerance,
01087                              int *active)
01088 
01089 {
01090     double converge, drift;
01091     int iter = 0;
01092     double err;
01093     double test = (double)tolerance * 0.000001;
01094 
01095     drift = edt_sstm_measure_drift(edt_p);
01096 
01097     do {
01098 
01099         converge = edt_sstm_calc_convergence(edt_p, revert_secs,drift);
01100 
01101         err = edt_sstm_adjust(edt_p, converge, drift, active);
01102 
01103         iter ++ ;
01104                 
01105         printf("Loop %d error %.6f\n", iter, err);
01106 
01107     } while (err > test && iter < maxiterations);
01108 
01109 }
01110 
01111 THREAD_FUNC_DECLARE 
01112 edt_sstm_adjust_thread(void *p)
01113 
01114 {
01115     EdtSSTimeAdjuster *adj_p = (EdtSSTimeAdjuster *) p;
01116 
01117     int iterations;
01118     int count;
01119     double err;
01120     double max_err;
01121     int loop = 0;
01122 
01123     if (adj_p == NULL)
01124         return (THREAD_RETURN) -1;
01125 
01126     max_err = adj_p->max_error * 0.000001;
01127     iterations = adj_p->iterations;
01128     if (!iterations)
01129         iterations = 1;
01130     adj_p->done = 0;
01131 
01132     while (adj_p->active)
01133     {
01134 
01135         printf("Going to auto_adjust\n");
01136 
01137         edt_sstm_print(adj_p->edt_p);
01138 
01139         err = edt_sstm_sys_error(adj_p->edt_p);
01140 
01141         if (fabs(err) > max_err)
01142         {
01143 
01144             edt_sstm_iterate_adjust(adj_p->edt_p, 
01145                 adj_p->revert_seconds, 
01146                 adj_p->iterations,
01147                 adj_p->tolerance, 
01148                 &adj_p->active);
01149 
01150             printf("Adjusted\n");
01151             edt_sstm_print(adj_p->edt_p);
01152 
01153         }
01154         else
01155             printf("Within tolerance %d\n", adj_p->max_error);
01156 
01157         count = 0;
01158 
01159 
01160         if (adj_p->loops != 0)
01161         {
01162             loop ++;
01163             if (loop >= adj_p->loops)
01164                 adj_p->active = FALSE;
01165         }
01166 
01167         /* sleep for 200 ms */
01168 
01169         while (adj_p->active && (count < adj_p->check_interval * 5))
01170         {
01171             edt_msleep(200);
01172             count ++;
01173         }
01174 
01175     }
01176 
01177     adj_p->done = 1;
01178 
01179     return (THREAD_RETURN) 0;
01180 }
01181 
01182 
01198 EdtSSTimeAdjuster *
01199 edt_sstm_launch_adjuster(EdtDev *edt_p, 
01200                             int check, 
01201                             int revert, 
01202                             int iterations, 
01203                             int max_usec_error,
01204                             int tolerance,
01205                             int loops)
01206 
01207 {
01208     EdtSSTimeAdjuster *adj_p;
01209     thread_t thread;
01210 
01211     adj_p = (EdtSSTimeAdjuster *) calloc(1, sizeof(EdtSSTimeAdjuster));
01212 
01213     adj_p->edt_p = edt_p;
01214 
01215     adj_p->check_interval = check; /* seconds */
01216     adj_p->revert_seconds= revert;
01217     adj_p->iterations = iterations;    /* how many times to auto adjust */
01218     adj_p->active = TRUE;
01219     adj_p->max_error = max_usec_error;
01220     adj_p->tolerance = tolerance;
01221     adj_p->loops = loops;
01222 
01223 
01224     LaunchThread(thread, edt_sstm_adjust_thread, (void *) adj_p);
01225     adj_p->thread = thread;
01226 
01227     return adj_p;
01228 
01229 }
01230 
01240 void
01241 edt_sstm_adjuster_stop(EdtSSTimeAdjuster *adj_p)
01242 
01243 {
01244     adj_p->active = 0;
01245     while (!adj_p->done)
01246         edt_msleep(100);
01247 }
01248 
01257 void
01258 edt_sstm_adjuster_start(EdtSSTimeAdjuster *adj_p)
01259 
01260 {
01261     thread_t thread;
01262     if (!adj_p->done)
01263         return;
01264 
01265     adj_p->active = TRUE;
01266 
01267     LaunchThread(thread, edt_sstm_adjust_thread, (void *) adj_p);
01268     adj_p->thread = thread;
01269 
01270 }

Generated on Mon May 12 16:38:59 2008 by  doxygen 1.5.1