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 int usecs_difference = 0;
00030 int usecs_calibrated = 0;
00031 double realtime_diff = 0.0;
00032 double mean_trend = 0.0;
00033
00034 #define POLL_MARGIN 975
00035 void edt_calibrate_usecs(int test_loops)
00036
00037 {
00038 int i;
00039 int loops = 1;
00040 double sum = 0.0, whole, msec, diff = 0, t, testms, last_diff;
00041
00042
00043 FILETIME ft;
00044 uint64_t dt;
00045 SYSTEMTIME tm;
00046 uint64_t dt_1970;
00047
00048 if (test_loops > 1)
00049 loops = test_loops;
00050
00051
00052 tm.wYear = 1970;
00053 tm.wMonth = 1;
00054 tm.wHour = 0;
00055 tm.wMinute = 0;
00056 tm.wSecond = 0;
00057 tm.wMilliseconds = 0;
00058 tm.wDay = 1;
00059 tm.wDayOfWeek = 1;
00060
00061 SystemTimeToFileTime(&tm, &ft);
00062
00063 dt_1970 = (uint64_t) ft.dwHighDateTime << 32 | (uint64_t)ft.dwLowDateTime;
00064
00065
00066
00067
00068
00069
00070 mean_trend = 0;
00071
00072
00073 for (i=0;i<loops;i++)
00074 {
00075 Sleep(10);
00076
00077 t = edt_timestamp();
00078
00079 msec = 1000000.0 * modf(t, &whole);
00080
00081 GetSystemTimeAsFileTime(&ft);
00082 dt = (uint64_t) ft.dwHighDateTime << 32 | (uint64_t)ft.dwLowDateTime;
00083
00084 dt -= dt_1970;
00085
00086 testms = dt * 0.0000001;
00087
00088 diff = t - testms;
00089
00090 sum += diff;
00091
00092 if (i>0)
00093 mean_trend += diff - last_diff;
00094
00095 last_diff = diff;
00096
00097 }
00098
00099 realtime_diff = (sum / (double) loops);
00100 if (loops > 1)
00101 mean_trend /= (loops - 1);
00102
00103 usecs_calibrated = 1;
00104
00105 }
00106
00107 void old_edt_calibrate_usecs()
00108
00109 {
00110 int i;
00111 int loops = 1;
00112 time_t t, t1;
00113 struct timeb tb1;
00114 double sum = 0.0, dtsum = 0.0, whole, frac, last_frac = 0,
00115 trend = 0, dt;
00116
00117
00118
00119
00120
00121 for (i=0;i<loops;i++)
00122 {
00123 ftime(&tb1);
00124
00125 if (tb1.millitm < POLL_MARGIN)
00126 Sleep(POLL_MARGIN - tb1.millitm);
00127
00128 t1 = time(&t);
00129
00130 do {
00131 t = time(&t);
00132 dt = edt_timestamp();
00133 } while (t == t1);
00134
00135 frac = modf(dt, &whole);
00136 trend = frac - last_frac;
00137 last_frac = frac;
00138 printf("frac = %f trend= %f\n", frac, trend);
00139 sum += frac;
00140 dtsum += (dt - t);
00141
00142 }
00143
00144 usecs_difference = (u_int) ((sum / (double) loops) * 1000000.0);
00145 realtime_diff = (dtsum / (double) loops);
00146 printf("usecs_difference = %d realtime_diff = %f\n", usecs_difference, realtime_diff);
00147 usecs_calibrated = 1;
00148
00149 }
00150
00151
00152 double
00153 edt_sys_timestamp()
00154
00155 {
00156
00157
00158 double t;
00159
00160 if (!usecs_calibrated)
00161 edt_calibrate_usecs(0);
00162
00163
00164 t = edt_timestamp();
00165
00166 return t - realtime_diff;
00167
00168 }
00169
00170
00171
00172 #else
00173
00174 #define edt_sys_timestamp edt_timestamp
00175
00176 #endif
00177
00185 int
00186 edt_usecs()
00187
00188 {
00189
00190 #ifdef WIN32
00191
00192 double t;
00193
00194 if (!usecs_calibrated)
00195 edt_calibrate_usecs(0);
00196
00197 t = (edt_sys_timestamp() * 1000000.0);
00198 t = fmod(t, 1000000.0);
00199
00200 return (int) t;
00201
00202 #elif defined(VXWORKS)
00203
00204 struct timespec endtime ;
00205 clock_gettime(CLOCK_REALTIME,&endtime);
00206 return endtime.tv_nsec / 1000;
00207
00208 #else
00209 struct timeval endtime;
00210
00211 gettimeofday(&endtime, (struct timezone *) NULL);
00212
00213 return endtime.tv_usec;
00214
00215 #endif
00216
00217 }
00218
00219
00220
00221
00222 static int wait_zero_offset = 0;
00223 static int wait_zero_calibrated = 0;
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 static void
00235 edt_wait_for_zero(int margin)
00236
00237 {
00238 int usec;
00239 int lastusec = 0;
00240
00241 int test = 1000000 - margin;
00242
00243 usec = edt_usecs();
00244
00245 edt_usleep(1000 - (usec/1000) - 100);
00246 while (usec < test && usec >= lastusec)
00247 {
00248 lastusec = usec;
00249
00250 usec = edt_usecs();
00251 }
00252 }
00253
00262 void
00263 edt_sstm_setup(EdtTimeController *tm, char *bitfile)
00264
00265 {
00266
00267 if (bitfile)
00268 edt_bitload(tm->dev_p, ".", bitfile, 0, 0);
00269 else
00270 edt_bitload(tm->dev_p, ".", "c3_demux.bit", 0, 0);
00271 }
00272
00292 void edt_sstm_strobe(EdtTimeController *tm, unsigned int bits)
00293
00294 {
00295 int cmd;
00296 int count = 0;
00297
00298 do
00299 {
00300 cmd = edt_reg_read(tm->dev_p, tm->cmd);
00301 if (cmd & EDT_SSTM_CMD_LOCK)
00302 edt_msleep(0);
00303 } while (cmd & EDT_SSTM_CMD_LOCK && (count++ < 5));
00304
00305
00306 cmd &= 0x70;
00307
00308 edt_reg_write(tm->dev_p, tm->cmd, cmd | EDT_SSTM_CMD_LOCK);
00309
00310 edt_reg_write(tm->dev_p, tm->cmd, cmd | bits);
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 static void
00323 edt_sstm_calibrate_wait(EdtTimeController *tm)
00324
00325 {
00326
00327 int i1, i2;
00328
00329 if (wait_zero_calibrated)
00330 return;
00331
00332 do
00333 {
00334 edt_wait_for_zero(0);
00335
00336 i1 = edt_usecs();
00337
00338 edt_sstm_strobe(tm, 0);
00339
00340 i2 = edt_usecs();
00341
00342 wait_zero_offset = (i1+i2)/2;
00343 printf("wait_zero_offset = (%d + %d) / 2 = %d\n",
00344 i1, i2, wait_zero_offset);
00345
00346 } while (wait_zero_offset > EDT_SSTM_ZERO_OFFSET_MAX);
00347
00348 }
00349
00355 void edt_sstm_latch_time(EdtTimeController *tm)
00356
00357 {
00358 edt_sstm_strobe(tm, EDT_SSTM_LATCH);
00359 }
00360
00367 int edt_sstm_get_adjust_enabled(EdtTimeController *tm)
00368
00369 {
00370 int cfg = edt_reg_read(tm->dev_p, tm->cmd);
00371
00372 if (cfg & EDT_SSTM_ADJ_EN)
00373 return 1;
00374 else
00375 return 0;
00376
00377 }
00378
00386 int edt_sstm_get_adjust_sign(EdtTimeController *tm)
00387
00388 {
00389 int cfg = edt_reg_read(tm->dev_p, tm->cmd);
00390
00391 if (cfg & EDT_SSTM_ADJ_PLUS)
00392 return 1;
00393 else
00394 return -1;
00395
00396 }
00397
00403 u_int edt_sstm_get_adjust_ticks(EdtTimeController *tm)
00404
00405 {
00406
00407 return edt_sstm_get_adjust_sign(tm) *
00408 edt_reg_read(tm->dev_p, tm->adj_value);
00409 }
00410
00411
00417 u_int edt_sstm_get_seconds(EdtTimeController *tm)
00418
00419 {
00420 return edt_reg_read(tm->dev_p, tm->secs);
00421 }
00422
00429 u_int edt_sstm_get_counts(EdtTimeController *tm)
00430
00431 {
00432 return edt_reg_read(tm->dev_p, tm->counts) >> 12;
00433 }
00434
00445 u_int
00446 edt_sstm_get_usecs(EdtTimeController *tm)
00447
00448 {
00449 u_int count = edt_sstm_get_counts(tm);
00450
00451 return (u_int) (count * USECS_FACTOR);
00452
00453 }
00454
00466 void
00467 edt_sstm_get_time_parts(EdtTimeController *tm, u_int *seconds, u_int *usecs)
00468
00469 {
00470 edt_sstm_latch_time(tm);
00471
00472 *seconds = edt_sstm_get_seconds(tm);
00473 *usecs = edt_sstm_get_usecs(tm);
00474 }
00475
00483 double
00484 edt_sstm_timestamp(EdtTimeController *tm)
00485
00486 {
00487
00488 edt_sstm_latch_time(tm);
00489
00490 return (double) edt_sstm_get_seconds(tm) +
00491 (0.000001) * (USECS_FACTOR) * edt_sstm_get_counts(tm);
00492 }
00493
00504 void edt_sstm_set_secs(EdtTimeController *tm, unsigned int second)
00505
00506 {
00507 edt_reg_write(tm->dev_p, tm->set, second);
00508 edt_sstm_strobe(tm, EDT_SSTM_COPY);
00509 }
00510
00511
00521 void edt_sstm_set(EdtTimeController *tm, unsigned int second)
00522
00523 {
00524 printf("Setting seconds to %d\n", second);
00525
00526 edt_reg_write(tm->dev_p, tm->set, second+1);
00527 edt_wait_for_zero(wait_zero_offset);
00528 edt_sstm_strobe(tm, EDT_SSTM_COPY);
00529 }
00530
00538 void edt_sstm_set_to_sys(EdtTimeController *tm)
00539
00540 {
00541 time_t t;
00542 edt_sstm_calibrate_wait(tm);
00543 edt_wait_for_zero(0);
00544 edt_msleep(500);
00545 t = time(&t);
00546 edt_sstm_set(tm, (u_int) t);
00547 }
00548
00557 void edt_sstm_set_to_sys_error(EdtTimeController *tm, int error)
00558
00559 {
00560 time_t t;
00561 edt_sstm_calibrate_wait(tm);
00562 edt_wait_for_zero(0);
00563 edt_msleep(500);
00564 t = time(&t);
00565 if (error < 0)
00566 {
00567 edt_reg_write(tm->dev_p, tm->set, (uint_t) (t + ( error / 1000 )) );
00568 edt_wait_for_zero(wait_zero_offset);
00569
00570 edt_msleep(1000 - (abs(error) % 1000));
00571 edt_sstm_strobe(tm, EDT_SSTM_COPY);
00572
00573 }
00574 else
00575 {
00576
00577 edt_reg_write(tm->dev_p, tm->set, (uint_t) (t + 1 + error / 1000));
00578 edt_wait_for_zero(wait_zero_offset);
00579
00580 edt_msleep(error % 1000);
00581
00582 edt_sstm_strobe(tm, EDT_SSTM_COPY);
00583
00584 }
00585 }
00586
00593 void edt_sstm_disable_adjust(EdtTimeController *tm)
00594
00595 {
00596 edt_reg_and(tm->dev_p, tm->cmd, ~EDT_SSTM_ADJ_EN);
00597 }
00598
00605 void edt_sstm_enable_adjust(EdtTimeController *tm)
00606
00607 {
00608 edt_reg_or(tm->dev_p, tm->cmd, EDT_SSTM_ADJ_EN );
00609 }
00610
00618 void edt_sstm_set_adj_sign(EdtTimeController *tm, int positive)
00619
00620 {
00621 edt_reg_and(tm->dev_p, tm->cmd, ~EDT_SSTM_ADJ_PLUS);
00622 edt_reg_or(tm->dev_p, tm->cmd, ((positive)?EDT_SSTM_ADJ_PLUS:0));
00623 }
00624
00632 int edt_sstm_get_adj_sign(EdtTimeController *tm)
00633
00634 {
00635 edt_reg_and(tm->dev_p, tm->cmd, ~EDT_SSTM_ADJ_PLUS);
00636 return edt_reg_read(tm->dev_p, tm->cmd) & EDT_SSTM_ADJ_PLUS;
00637 }
00638
00652 void edt_sstm_set_adj_ticks(EdtTimeController *tm, int ticks, int positive)
00653
00654 {
00655 edt_reg_write(tm->dev_p, tm->set, abs(ticks));
00656
00657 edt_sstm_disable_adjust(tm);
00658 edt_sstm_strobe(tm, EDT_SSTM_COPY_ADJ );
00659 edt_sstm_set_adj_sign(tm, positive);
00660 edt_sstm_enable_adjust(tm);
00661
00662 tm->ticks = ticks;
00663
00664 printf("set adj to %d\n", ticks);
00665 }
00666
00679 double edt_sstm_sys_error(EdtTimeController *tm)
00680
00681 {
00682 double t1, t2, st1;
00683 t1 = edt_sstm_timestamp(tm);
00684 st1 = edt_sys_timestamp();
00685 t2 = edt_sstm_timestamp(tm);
00686 return ((t1 + t2) * 0.5) - st1;
00687 }
00688
00698 char *
00699 edt_printable_time(double sys_t, char *buf)
00700
00701 {
00702 time_t t;
00703 struct tm *ltime;
00704 int usecs;
00705 double whole;
00706 static char sbuf[17];
00707 char *cp = buf;
00708
00709 if (!cp)
00710 cp = sbuf;
00711
00712 t = (time_t) sys_t;
00713
00714 ltime = localtime(&t);
00715
00716 if (!ltime)
00717 return buf;
00718
00719 usecs = (int) (modf(sys_t,&whole) * 1000000.0);
00720
00721 sprintf(cp, "%02d:%02d:%02d.%06d",
00722 ltime->tm_hour, ltime->tm_min, ltime->tm_sec, usecs);
00723
00724 return cp;
00725 }
00726
00727
00736 double
00737 edt_sstm_print(EdtTimeController *tm)
00738
00739 {
00740 double error, sys_t;
00741 char printbuf[32];
00742
00743 sys_t = edt_sys_timestamp();
00744
00745 error = edt_sstm_sys_error(tm);
00746
00747 printf("%s %.6f\n", edt_printable_time(sys_t, printbuf),error);
00748
00749 return error;
00750
00751 }
00752
00753
00754 static double
00755 double_mean(double *v, int n)
00756
00757 {
00758 double sum = 0.0;
00759 int i;
00760
00761 for (i=0;i<n;i++)
00762 sum += v[i];
00763
00764 return (sum / (double) n);
00765 }
00766
00767 static int
00768 double_compare(const void *p1, const void *p2)
00769
00770 {
00771 double d1 = *(double *) p1;
00772 double d2 = *(double *) p2;
00773
00774 return (d1 > d2)?1:((d1 == d2)?0:-1);
00775 }
00776
00777
00778
00779 static int adj_sample_seconds = 3;
00780 static int adj_samples = 10;
00781
00789 void edt_sstm_set_drift_sampling(int seconds, int samples)
00790
00791 {
00792 adj_sample_seconds = seconds;
00793 adj_samples = samples;
00794 }
00795
00804 int edt_sstm_get_adj_sample_secs()
00805
00806 {
00807 return adj_sample_seconds;
00808 }
00809
00818 int edt_sstm_get_adj_samples()
00819
00820 {
00821 return adj_samples;
00822 }
00823
00824
00825
00832 int edt_sstm_ticks_from_drift(double drift)
00833
00834 {
00835 double t;
00836
00837 if (drift == 0.0)
00838 return 0;
00839
00840 t = USECS_FACTOR;
00841
00842 t = (int) (1000000.0 / drift);
00843
00844 return (int) t;
00845 }
00846
00855 void edt_sstm_set_adj_from_drift(EdtTimeController *tm, double drift)
00856
00857 {
00858 int ticks = (int) edt_sstm_ticks_from_drift(drift);
00859
00860 edt_sstm_set_adj_ticks(tm, ticks, (drift >= 0.0));
00861
00862
00863 }
00864
00875 double edt_sstm_measure_drift(EdtTimeController *tm)
00876
00877 {
00878
00879 double t1 = 0, t2 = 0, st1 = 0, st2 = 0;
00880
00881 double *d1_v = NULL, *d2_v = NULL, *st1_v = NULL, *st2_v = NULL;
00882
00883 double d1, d2;
00884 double drift;
00885 double extraticks;
00886
00887 int i;
00888 int count;
00889 int adj_state = edt_reg_read(tm->dev_p, tm->cmd) & EDT_SSTM_ADJ_EN;
00890 int sleep_interval = adj_sample_seconds * 1000000;
00891
00892 edt_sstm_timestamp(tm);
00893
00894 edt_sstm_disable_adjust(tm);
00895
00896
00897 d1_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00898 d2_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00899 st1_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00900 st2_v = (double *) calloc(2*adj_samples +1 , sizeof(double));
00901
00902
00903 printf("Sampling basic error rate ...\n");
00904 edt_usleep(100);
00905
00906 t1 = 0;
00907 st1 = 0;
00908 t2 = 0;
00909 st2 = 0;
00910 d1 = 0;
00911 d2 = 0;
00912
00913
00914 for (i=0;i<adj_samples;i++)
00915 {
00916 t1 = edt_sstm_timestamp(tm);
00917 st1 = edt_sys_timestamp();
00918 t2 = edt_sstm_timestamp(tm);
00919 d1_v[i] = st1 - ((t1 + t2) * 0.5);
00920 st1_v[i] = st1;
00921 }
00922
00923 edt_usleep(sleep_interval);
00924
00925
00926 count = 0;
00927
00928 for (i=0;i<adj_samples;i++)
00929 {
00930 t1 = edt_sstm_timestamp(tm);
00931 st1 = edt_sys_timestamp();
00932 t2 = edt_sstm_timestamp(tm);
00933 d2_v[i] = st1 - ((t1 + t2) * 0.5);
00934 st2_v[i] = st1;
00935 }
00936
00937
00938
00939 qsort(d1_v, adj_samples, sizeof(double), double_compare);
00940 qsort(d2_v, adj_samples, sizeof(double), double_compare);
00941 qsort(st1_v, adj_samples, sizeof(double), double_compare);
00942 qsort(st2_v, adj_samples, sizeof(double), double_compare);
00943
00944
00945
00946
00947 d1 = double_mean(d1_v + 1, (adj_samples-2));
00948 d2 = double_mean(d2_v + 1, (adj_samples-2));
00949 st1 = double_mean(st1_v + 1, adj_samples-2);
00950 st2 = double_mean(st2_v + 1, adj_samples-2);
00951
00952
00953 d1 *= 1000000.0;
00954 d2 *= 1000000.0;
00955
00956 drift = (d2 - d1) / (st2 - st1);
00957
00958
00959 #ifdef VERBOSE
00960
00961 printf("d1 = %.6f d2 = %.6f\n", d1, d2);
00962 printf("st1 = %.6f st2 = %.6f\n", st1, st2);
00963
00964 for (i=0;i<adj_samples*2;i++)
00965 {
00966 printf("d1_v[%d] = %.5f d2_v[%d] = %.6f\n",
00967 i, d1_v[i], i, d2_v[i]);
00968 }
00969
00970 for (i=0;i<adj_samples;i++)
00971 {
00972 printf("st1_v[%d] = %.5f st2_v[%d] = %.6f\n",
00973 i, st1_v[i], i, st2_v[i]);
00974 }
00975 #endif
00976
00977 extraticks = edt_sstm_ticks_from_drift(drift);
00978
00979 printf("drift in %.0f secs = %.1f ticks = %.0f\n",
00980 (st2 - st1),
00981 drift,
00982 extraticks);
00983
00984
00985 if (adj_state)
00986 edt_reg_or(tm->dev_p, tm->cmd, EDT_SSTM_ADJ_EN);
00987
00988 free(d1_v);
00989 free(d2_v);
00990 free(st1_v);
00991 free(st2_v);
00992
00993 return drift;
00994 }
00995
00996 THREAD_FUNC_DECLARE
00997 edt_sstm_adjust_thread(void *p)
00998
00999 {
01000 EdtTimeController *tm = (EdtTimeController *) p;
01001
01002 double max_err;
01003 int ticks;
01004 int sign;
01005 int delta;
01006
01007 double last_error;
01008 double drift_values[5];
01009 int nvalues = 0;
01010 int start_ticks;
01011
01012 if (tm == NULL)
01013 return (THREAD_RETURN) -1;
01014
01015 max_err = tm->max_error * 0.000001;
01016
01017 tm->done = 0;
01018
01019 tm->err = edt_sstm_sys_error(tm);
01020
01021
01022
01023 start_ticks = edt_sstm_get_adjust_ticks(tm);
01024
01025 while (tm->active)
01026 {
01027
01028 last_error = tm->err;
01029
01030
01031 tm->err = edt_sstm_sys_error(tm);
01032
01033 drift_values[nvalues % 5] = tm->err - last_error;
01034 nvalues++;
01035
01036 tm->adjust_drift = double_mean(drift_values, (nvalues > 5)?5:nvalues);
01037
01038 ticks = edt_sstm_get_adjust_ticks(tm);
01039 sign = (edt_sstm_get_adjust_sign(tm) > 0);
01040
01041 delta = (int)(-tm->err * 1000000 * tm->adjustment_scalar);
01042
01043
01044 if (sign)
01045 ticks = start_ticks + delta;
01046 else
01047 ticks = start_ticks - delta;
01048 printf("adjusting drift = %f err = %f delta = %d\n", tm->adjust_drift, tm->err, delta);
01049
01050 edt_sstm_set_adj_ticks(tm, ticks, sign);
01051 edt_sstm_enable_adjust(tm);
01052
01053
01054 edt_msleep(tm->adjust_sample);
01055
01056 }
01057
01058 tm->done = 1;
01059
01060 return (THREAD_RETURN) 0;
01061 }
01062
01063
01072 EdtTimeController *
01073 edt_sstm_launch_adjuster(EdtTimeController *tm)
01074
01075 {
01076
01077 #ifdef __APPLE__
01078 mac_thread_t thread;
01079 #else
01080 thread_t thread;
01081 #endif
01082
01083 LaunchThread(thread, edt_sstm_adjust_thread, (void *) tm);
01084 tm->thread = thread;
01085
01086 return tm;
01087
01088 }
01089
01099 void
01100 edt_sstm_adjuster_stop(EdtTimeController *tm)
01101
01102 {
01103 if (!tm->active)
01104 return;
01105
01106 tm->active = 0;
01107 while (!tm->done)
01108 edt_msleep(100);
01109 }
01110
01119 void
01120 edt_sstm_adjuster_start(EdtTimeController *tm)
01121 {
01122 #ifdef __APPLE__
01123 mac_thread_t thread;
01124 #else
01125 thread_t thread;
01126 #endif
01127 int ticks;
01128
01129 if (tm->active)
01130 return;
01131
01132
01133
01134 tm->done = 0;
01135 tm->active = TRUE;
01136
01137
01138
01139 tm->drift = edt_sstm_measure_drift(tm);
01140 ticks = edt_sstm_ticks_from_drift(tm->drift);
01141 edt_sstm_set_adj_ticks(tm, ticks, (ticks >= 0.0));
01142
01143
01144
01145 edt_sstm_set_to_sys(tm);
01146
01147 LaunchThread(thread, edt_sstm_adjust_thread, (void *) tm);
01148 tm->thread = thread;
01149
01150 }
01151
01152 EDTAPI void edt_init_time_controller(EdtTimeController *tm,
01153 EdtDev *edt_p,
01154 u_int address_base)
01155
01156 {
01157 tm->dev_p = edt_p;
01158 tm->counts = address_base + (EDT_SSTM_COUNTS & 0xf0000ff);
01159 tm->secs = address_base + (EDT_SSTM_SECS & 0xf0000ff);
01160 tm->set = address_base + (EDT_SSTM_SET & 0xf0000ff);
01161 tm->adj_value = address_base + (EDT_SSTM_ADJ_VALUE & 0xf0000ff);
01162 tm->cmd = address_base + (EDT_SSTM_CMD & 0xf0000ff);
01163 }
01164
01165