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
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
00045
00046
00047
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
00092
00093
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
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
00196 struct timeval endtime;
00197
00198 gettimeofday(&endtime, (void *) NULL);
00199
00200 return endtime.tv_usec;
00201
00202 #endif
00203
00204 }
00205
00206
00207
00208
00209 static int wait_zero_offset = 0;
00210 static int wait_zero_calibrated = 0;
00211
00212
00213
00214
00215
00216
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
00303
00304
00305
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
00910
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
00917
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
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
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
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
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;
01216 adj_p->revert_seconds= revert;
01217 adj_p->iterations = iterations;
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 }