1e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer/*
2e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Copyright (C) 2015 The Android Open Source Project
3e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer *
4e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Licensed under the Apache License, Version 2.0 (the "License");
5e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * you may not use this file except in compliance with the License.
6e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * You may obtain a copy of the License at
7e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer *
8e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer *      http://www.apache.org/licenses/LICENSE-2.0
9e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer *
10e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Unless required by applicable law or agreed to in writing, software
11e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * distributed under the License is distributed on an "AS IS" BASIS,
12e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * See the License for the specific language governing permissions and
14e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * limitations under the License.
15e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer */
16e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
17e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include "sync_clock.h"
18e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
19e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <asm/byteorder.h>
20e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <errno.h>
21e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <fcntl.h>
22e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <inttypes.h>
23e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <linux/usbdevice_fs.h>
24e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <stdio.h>
25e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <stdlib.h>
26e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <string.h>
27e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <sys/inotify.h>
28e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <sys/ioctl.h>
29e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <sys/time.h>
30e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <time.h>
31e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <unistd.h>
32e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
33e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
34e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#ifdef __ANDROID__
35e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    #include <android/log.h>
36e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    #define  LOGD(...)  __android_log_print(ANDROID_LOG_VERBOSE, "ClockSyncNative", __VA_ARGS__)
37e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#else
38e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    #define  LOGD(...)  printf(__VA_ARGS__)
39e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#endif
40e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
41e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
42e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// How many times to repeat the 1..9 digit sequence it's a tradeoff between
43e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// precision and how long it takes.
44e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// TODO: investigate better combination of constants for repeats and wait times
45e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerconst int kSyncRepeats = 7;
46e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerconst int kMillion = 1000000;
47e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
48e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
49e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer/**
50e76dcf96b0c451e46cddfa695de8feeb92533937Andrew LehmeruptimeMicros() - returns microseconds elapsed since boot.
51e76dcf96b0c451e46cddfa695de8feeb92533937Andrew LehmerSame time as Android's SystemClock.uptimeMillis() but in microseconds.
52e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
53e76dcf96b0c451e46cddfa695de8feeb92533937Andrew LehmerAdapted from Android:
54e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerplatform/system/core/libutils/Timers.cpp
55e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerplatform/system/core/include/utils/Timers.h
56e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
57e76dcf96b0c451e46cddfa695de8feeb92533937Andrew LehmerSee:
58e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerhttp://developer.android.com/reference/android/os/SystemClock.html
59e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerhttps://android.googlesource.com/platform/system/core/+/master/libutils/Timers.cpp
60e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer*/
61e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerint64_t uptimeMicros() {
62ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer    struct timespec ts;
63e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clock_gettime(CLOCK_MONOTONIC, &ts);
64e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    return ((int64_t)ts.tv_sec) * kMillion + ts.tv_nsec / 1000;
65e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
66e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
67e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
68e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Sleeps us microseconds
69e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerint microsleep(int us) {
70ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer    struct timespec ts;
71e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    ts.tv_sec = us / kMillion;
72e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    us %= kMillion;
73e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    ts.tv_nsec = us*1000;
74ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer    return nanosleep(&ts, NULL);
75e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
76e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
77e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
78e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// *********************** Generic USB functions *******************************
79e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
80e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic int send_char_async(int fd, int endpoint, char msg, char * label) {
81e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // TODO: Do we really need a buffer longer than 1 char here?
82e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    char buffer[256] = {0};
83e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    buffer[0] = msg;
84e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int length = 1;
85e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
86e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // TODO: free() the memory used for URBs.
87e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Circular buffer of URBs? Cleanup at the end of clock sync?
88e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Several may be used simultaneously, no signal when done.
89e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb));
90e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    memset(urb, 0, sizeof(struct usbdevfs_urb));
91e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
92e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int res;
93e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    urb->status = -1;
94e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    urb->buffer = buffer;
95e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    urb->buffer_length = length;
96e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    urb->endpoint = endpoint;
97e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    urb->type = USBDEVFS_URB_TYPE_BULK;
98e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    urb->usercontext = label; // This is hackish
99e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    do {
100e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        res = ioctl(fd, USBDEVFS_SUBMITURB, urb);
101e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    } while((res < 0) && (errno == EINTR));
102e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    return res;
103e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
104e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
105e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
106e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Send or read using USBDEVFS_BULK. Allows to set a timeout.
107e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic int bulk_talk(int fd, int endpoint, char * buffer, int length) {
108e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Set some reasonable timeout. 20ms is plenty time for most transfers but
109e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // short enough to fail quickly if all transfers and retries fail with
110e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // timeout.
111e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    const int kTimeoutMs = 20;
112ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer    struct usbdevfs_bulktransfer ctrl;
113e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // TODO: need to limit request size to avoid EINVAL
114e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
115e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    ctrl.ep = endpoint;
116e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    ctrl.len = length;
117e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    ctrl.data = buffer;
118e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    ctrl.timeout = kTimeoutMs;
119e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int ret = ioctl(fd, USBDEVFS_BULK, &ctrl);
120e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    return ret;
121e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
122e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
123e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
124e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer/*******************************************************************************
125e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer* Clock sync specific stuff below.
126e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer* Most data is stored in the clock_connection struct variable.
127e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer*/
128e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
129e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Send a single character to the remote in a blocking mode
130e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerint send_cmd(struct clock_connection *clk, char cmd) {
131e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    return bulk_talk(clk->fd, clk->endpoint_out, &cmd, 1);
132e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
133e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
134e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Schedule a single character to be sent to the remote - async.
135e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerint send_async(struct clock_connection *clk, char cmd) {
136e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    return send_char_async(clk->fd, clk->endpoint_out, cmd, NULL);
137e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
138e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
139e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
140e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerint bulk_read(struct clock_connection *clk) {
141e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    memset(clk->buffer, 0, sizeof(clk->buffer));
142e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int ret = bulk_talk(clk->fd, clk->endpoint_in, clk->buffer, sizeof(clk->buffer));
143e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    return ret;
144e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
145e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
146e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// microseconds elapsed since clk->t_base
147e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerint micros(struct clock_connection *clk) {
148e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    return uptimeMicros() - clk->t_base;
149e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
150e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
151e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Clear all incoming data that's already waiting somewhere in kernel buffers
152e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// and discard it.
153e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid flush_incoming(struct clock_connection *clk) {
154e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // When bulk_read times out errno = ETIMEDOUT=110, retval =-1
155e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // should we check for this?
156e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
157e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    while(bulk_read(clk) >= 0) {
158e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        // TODO: fail nicely if waiting too long to avoid hangs
159e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
160e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
161e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
162e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Ask the remote to send its timestamps
163e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// for the digits previously sent to it.
164e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid read_remote_timestamps(struct clock_connection *clk, int * times_remote) {
165e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int i;
166e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int t_remote;
167e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Go over the digits [1, 2 ... 9]
168e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    for (i = 0; i < 9; i++) {
169e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        char digit = i + '1';
170e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        send_cmd(clk, CMD_SYNC_READOUT);
171e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        bulk_read(clk);
172e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        if (clk->buffer[0] != digit) {
173e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer            LOGD("Error, bad reply for R%d: %s", i+1, clk->buffer);
174e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        }
175e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        // The reply string looks like digit + space + timestamp
176e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        // Offset by 2 to ignore the digit and the space
177e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        t_remote = atoi(clk->buffer + 2);
178e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        times_remote[i] = t_remote;
179e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
180e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
181e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
182e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
183e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Preliminary rough sync with a single message - CMD_SYNC_ZERO = 'Z'.
184e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// This is not strictly necessary but greatly simplifies debugging
185e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// by removing the need to look at very long numbers.
186e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid zero_remote(struct clock_connection *clk) {
187e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    flush_incoming(clk);
188e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->t_base = uptimeMicros();
189e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    send_cmd(clk, CMD_SYNC_ZERO);
190e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    bulk_read(clk); // TODO, make sure we got 'z'
191e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->maxE = micros(clk);
192e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->minE = 0;
193e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
194e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    LOGD("Sent a 'Z', reply '%c' in %d us\n", clk->buffer[0], clk->maxE);
195e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
196e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
197e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
198e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
199e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid improve_minE(struct clock_connection *clk) {
200e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int times_local_sent[9] = {0};
201e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int times_remote_received[9] = {0};
202e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
203e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Set sleep time as 1/kSleepTimeDivider of the current bounds interval,
204e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // but never less or more than k(Min/Max)SleepUs. All pretty random
205e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // numbers that could use some tuning and may behave differently on
206e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // different devices.
207e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    const int kMaxSleepUs = 700;
208e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    const int kMinSleepUs = 70;
209e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    const int kSleepTimeDivider = 10;
210e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int minE = clk->minE;
211e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int sleep_time = (clk->maxE - minE) / kSleepTimeDivider;
212e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    if(sleep_time > kMaxSleepUs) sleep_time = kMaxSleepUs;
213e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    if(sleep_time < kMinSleepUs) sleep_time = kMinSleepUs;
214e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
215e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    flush_incoming(clk);
216e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Send digits to remote side
217e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int i;
218e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    for (i = 0; i < 9; i++) {
219e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        char c = i + '1';
220e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        times_local_sent[i] = micros(clk);
221e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        send_async(clk, c);
222e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        microsleep(sleep_time);
223e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
224e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
225e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Read out receive times from the other side
226e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    read_remote_timestamps(clk, times_remote_received);
227e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
228e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Do stats
229e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    for (i = 0; i < 9; i++) {
230e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int tls = times_local_sent[i];
231e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int trr = times_remote_received[i];
232e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
233e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int dt;
234e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
235e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        // Look at outgoing digits
236e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        dt = tls - trr;
237e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        if (tls != 0 && trr != 0 && dt > minE) {
238e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer            minE = dt;
239e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        }
240e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
241e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
242e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
243e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->minE = minE;
244e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
245e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    LOGD("E is between %d and %d us, sleep_time=%d\n", clk->minE, clk->maxE, sleep_time);
246e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
247e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
248e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid improve_maxE(struct clock_connection *clk) {
249e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int times_remote_sent[9] = {0};
250e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int times_local_received[9] = {0};
251e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
252e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Tell the remote to send us digits with delays
253e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // TODO: try tuning / configuring the delay time on remote side
254e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    send_async(clk, CMD_SYNC_SEND);
255e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
256e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Read and timestamp the incoming digits, they may arrive out of order.
257e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // TODO: Try he same with USBDEVFS_REAPURB, it might be faster
258e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int i;
259e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    for (i = 0; i < 9; ++i) {
260e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int retval = bulk_read(clk);
261e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        // TODO: deal with retval = (bytes returned) > 1. shouldn't happen.
262e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        // Can it happen on some devices?
263e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int t_local = micros(clk);
264e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int digit = atoi(clk->buffer);
265e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        if (digit <=0 || digit > 9) {
266e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer            LOGD("Error, bad incoming digit: %s\n", clk->buffer);
267e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        }
268e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        times_local_received[digit-1] = t_local;
269e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
270e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
271e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Flush whatever came after the digits. As of this writing, it's usually
272e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // a single linefeed character.
273e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    flush_incoming(clk);
274e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Read out the remote timestamps of when the digits were sent
275e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    read_remote_timestamps(clk, times_remote_sent);
276e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
277e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Do stats
278e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int maxE = clk->maxE;
279e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    for (i = 0; i < 9; i++) {
280e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int trs = times_remote_sent[i];
281e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int tlr = times_local_received[i];
282e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        int dt = tlr - trs;
283e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        if (tlr != 0 && trs != 0 && dt < maxE) {
284e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer            maxE = dt;
285e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        }
286e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
287e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
288e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->maxE = maxE;
289e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
290e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    LOGD("E is between %d and %d us\n", clk->minE, clk->maxE);
291e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
292e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
293e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
294e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid improve_bounds(struct clock_connection *clk) {
295e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    improve_minE(clk);
296e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    improve_maxE(clk);
297e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
298e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
299e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// get minE and maxE again after some time to check for clock drift
300e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid update_bounds(struct clock_connection *clk) {
301e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Reset the bounds to some unrealistically large numbers
302e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int i;
303e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->minE = -1e7;
304e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->maxE =  1e7;
305e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Talk to remote to get bounds on minE and maxE
306e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    for (i=0; i < kSyncRepeats; i++) {
307e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        improve_bounds(clk);
308e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
309e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
310e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
311e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid sync_clocks(struct clock_connection *clk) {
312e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Send CMD_SYNC_ZERO to remote for rough initial sync
313e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    zero_remote(clk);
314e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
315e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    int rep;
316e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    for (rep=0; rep < kSyncRepeats; rep++) {
317e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer        improve_bounds(clk);
318e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    }
319e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
320e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    // Shift the base time to set minE = 0
321e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->t_base += clk->minE;
322e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->maxE -= clk->minE;
323e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    clk->minE = 0;
324e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer    LOGD("Base time shifted for zero minE\n");
325e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer}
326e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
327e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer
328