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