16c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen/* 26c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Copyright (C) 2011 The Android Open Source Project 36c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * 46c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Licensed under the Apache License, Version 2.0 (the "License"); 56c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * you may not use this file except in compliance with the License. 66c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * You may obtain a copy of the License at 76c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * 86c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * http://www.apache.org/licenses/LICENSE-2.0 96c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * 106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Unless required by applicable law or agreed to in writing, software 116c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * distributed under the License is distributed on an "AS IS" BASIS, 126c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * See the License for the specific language governing permissions and 146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * limitations under the License. 156c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen */ 166c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 176c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#ifndef __CLOCK_RECOVERY_H__ 186c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#define __CLOCK_RECOVERY_H__ 196c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 206c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <stdint.h> 216c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <common_time/ICommonClock.h> 226c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/LinearTransform.h> 236c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/threads.h> 246c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 256c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#ifdef TIME_SERVICE_DEBUG 266c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include "diag_thread.h" 276c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#endif 286c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 29c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman#include "utils.h" 30c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman 316c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chennamespace android { 326c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 336c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenclass CommonClock; 346c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenclass LocalClock; 356c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 366c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenclass ClockRecoveryLoop { 376c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen public: 386c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen ClockRecoveryLoop(LocalClock* local_clock, CommonClock* common_clock); 396c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen ~ClockRecoveryLoop(); 406c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 416c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen void reset(bool position, bool frequency); 426c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen bool pushDisciplineEvent(int64_t local_time, 436c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int64_t nominal_common_time, 446c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int64_t data_point_rtt); 456c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int32_t getLastErrorEstimate(); 466c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 47c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // Applies the next step in any ongoing slew change operation. Returns a 48c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // timeout suitable for use with poll/select indicating the number of mSec 49c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // until the next change should be applied. 50c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman int applyRateLimitedSlew(); 51c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman 526c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen private: 5311bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 5411bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Tuned using the "Good Gain" method. 5511bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // See: 5611bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // http://techteach.no/publications/books/dynamics_and_control/tuning_pid_controller.pdf 5711bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 5811bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Controller period (1Hz for now). 5911bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float dT; 6011bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 6111bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Controller gain, positive and unitless. Larger values converge faster, 6211bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // but can cause instability. 6311bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float Kc; 6411bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 6511bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Integral reset time. Smaller values cause loop to track faster, but can 6611bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // also cause instability. 6711bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float Ti; 6811bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 6911bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Controller output filter time constant. Range (0-1). Smaller values make 7011bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // output smoother, but slow convergence. 7111bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float Tf; 7211bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 7311bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Low-pass filter for bias tracker. 7411bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float bias_Fc; // HZ 7511bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float bias_RC; // Computed in constructor. 7611bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float bias_Alpha; // Computed inconstructor. 7711bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 7811bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // The maximum allowed error (as indicated by a pushDisciplineEvent) before 7911bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // we panic. 8011bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const int64_t panic_thresh_; 8111bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 8211bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // The maximum allowed error rtt time for packets to be used for control 8311bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // feedback, unless the packet is the best in recent memory. 8411bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const int64_t control_thresh_; 856c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 866c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen typedef struct { 876c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int64_t local_time; 886c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int64_t observed_common_time; 896c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int64_t nominal_common_time; 906c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int64_t rtt; 916c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen bool point_used; 926c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen } DisciplineDataPoint; 936c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 946c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen static uint32_t findMinRTTNdx(DisciplineDataPoint* data, uint32_t count); 956c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 966c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen void reset_l(bool position, bool frequency); 97c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman void setTargetCorrection_l(int32_t tgt); 98c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman bool applySlew_l(); 996c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 1006c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen // The local clock HW abstraction we use as the basis for common time. 1016c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen LocalClock* local_clock_; 1026c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen bool local_clock_can_slew_; 1036c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 1046c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen // The common clock we end up controlling along with the lock used to 1056c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen // serialize operations. 1066c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen CommonClock* common_clock_; 1076c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen Mutex lock_; 1086c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 1096c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen // parameters maintained while running and reset during a reset 1106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen // of the frequency correction. 11179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman bool last_error_est_valid_; 11279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman int32_t last_error_est_usec_; 11311bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk float last_delta_f_; 1146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen int32_t integrated_error_; 115c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman int32_t tgt_correction_; 116c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman int32_t cur_correction_; 117c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman LinearTransform time_to_cur_slew_; 118c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman int64_t slew_change_end_time_; 119c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman Timeout next_slew_change_timeout_; 1206c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 12111bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Contoller Output. 12211bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk float CO; 12311bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 12411bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Bias tracking for trajectory estimation. 12511bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk float CObias; 12611bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk float lastCObias; 12711bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 12811bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // Controller output bounds. The controller will not try to 12911bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk // slew faster that +/-100ppm offset from center per interation. 13011bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float COmin; 13111bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const float COmax; 13211bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk 1336c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen // State kept for filtering the discipline data. 13411bc45fcba96cf7ccc5f67b3c47088c2c89c8e7aKent Ryhorchuk static const uint32_t kFilterSize = 16; 1356c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen DisciplineDataPoint filter_data_[kFilterSize]; 1366c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen uint32_t filter_wr_; 1376c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen bool filter_full_; 1386c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 1396c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen static const uint32_t kStartupFilterSize = 4; 1406c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen DisciplineDataPoint startup_filter_data_[kStartupFilterSize]; 1416c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen uint32_t startup_filter_wr_; 1426c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 143c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // Minimum number of milliseconds over which we allow a full range change 144c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // (from rail to rail) of the VCXO control signal. This is the rate 145c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // limiting factor which keeps us from changing the clock rate so fast that 146c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // we get in trouble with certain HDMI sinks. 147c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman static const uint32_t kMinFullRangeSlewChange_mSec; 148c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman 149c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman // How much time (in msec) to wait 150c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman static const int kSlewChangeStepPeriod_mSec; 151c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman 1526c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#ifdef TIME_SERVICE_DEBUG 1536c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen sp<DiagThread> diag_thread_; 1546c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#endif 1556c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}; 1566c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 1576c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen} // namespace android 1586c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen 1596c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#endif // __CLOCK_RECOVERY_H__ 160