1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef __CLOCK_RECOVERY_H__ 18 #define __CLOCK_RECOVERY_H__ 19 20 #include <stdint.h> 21 #include <common_time/ICommonClock.h> 22 #include <utils/LinearTransform.h> 23 #include <utils/threads.h> 24 25 #ifdef TIME_SERVICE_DEBUG 26 #include "diag_thread.h" 27 #endif 28 29 #include "utils.h" 30 31 namespace android { 32 33 class CommonClock; 34 class LocalClock; 35 36 class ClockRecoveryLoop { 37 public: 38 ClockRecoveryLoop(LocalClock* local_clock, CommonClock* common_clock); 39 ~ClockRecoveryLoop(); 40 41 void reset(bool position, bool frequency); 42 bool pushDisciplineEvent(int64_t local_time, 43 int64_t nominal_common_time, 44 int64_t data_point_rtt); 45 int32_t getLastErrorEstimate(); 46 47 // Applies the next step in any ongoing slew change operation. Returns a 48 // timeout suitable for use with poll/select indicating the number of mSec 49 // until the next change should be applied. 50 int applyRateLimitedSlew(); 51 52 private: 53 54 // Tuned using the "Good Gain" method. 55 // See: 56 // http://techteach.no/publications/books/dynamics_and_control/tuning_pid_controller.pdf 57 58 // Controller period (1Hz for now). 59 static const float dT; 60 61 // Controller gain, positive and unitless. Larger values converge faster, 62 // but can cause instability. 63 static const float Kc; 64 65 // Integral reset time. Smaller values cause loop to track faster, but can 66 // also cause instability. 67 static const float Ti; 68 69 // Controller output filter time constant. Range (0-1). Smaller values make 70 // output smoother, but slow convergence. 71 static const float Tf; 72 73 // Low-pass filter for bias tracker. 74 static const float bias_Fc; // HZ 75 static const float bias_RC; // Computed in constructor. 76 static const float bias_Alpha; // Computed inconstructor. 77 78 // The maximum allowed error (as indicated by a pushDisciplineEvent) before 79 // we panic. 80 static const int64_t panic_thresh_; 81 82 // The maximum allowed error rtt time for packets to be used for control 83 // feedback, unless the packet is the best in recent memory. 84 static const int64_t control_thresh_; 85 86 typedef struct { 87 int64_t local_time; 88 int64_t observed_common_time; 89 int64_t nominal_common_time; 90 int64_t rtt; 91 bool point_used; 92 } DisciplineDataPoint; 93 94 static uint32_t findMinRTTNdx(DisciplineDataPoint* data, uint32_t count); 95 96 void reset_l(bool position, bool frequency); 97 void setTargetCorrection_l(int32_t tgt); 98 bool applySlew_l(); 99 100 // The local clock HW abstraction we use as the basis for common time. 101 LocalClock* local_clock_; 102 bool local_clock_can_slew_; 103 104 // The common clock we end up controlling along with the lock used to 105 // serialize operations. 106 CommonClock* common_clock_; 107 Mutex lock_; 108 109 // parameters maintained while running and reset during a reset 110 // of the frequency correction. 111 bool last_error_est_valid_; 112 int32_t last_error_est_usec_; 113 float last_delta_f_; 114 int32_t tgt_correction_; 115 int32_t cur_correction_; 116 LinearTransform time_to_cur_slew_; 117 int64_t slew_change_end_time_; 118 Timeout next_slew_change_timeout_; 119 120 // Contoller Output. 121 float CO; 122 123 // Bias tracking for trajectory estimation. 124 float CObias; 125 float lastCObias; 126 127 // Controller output bounds. The controller will not try to 128 // slew faster that +/-100ppm offset from center per interation. 129 static const float COmin; 130 static const float COmax; 131 132 // State kept for filtering the discipline data. 133 static const uint32_t kFilterSize = 16; 134 DisciplineDataPoint filter_data_[kFilterSize]; 135 uint32_t filter_wr_; 136 bool filter_full_; 137 138 static const uint32_t kStartupFilterSize = 4; 139 DisciplineDataPoint startup_filter_data_[kStartupFilterSize]; 140 uint32_t startup_filter_wr_; 141 142 // Minimum number of milliseconds over which we allow a full range change 143 // (from rail to rail) of the VCXO control signal. This is the rate 144 // limiting factor which keeps us from changing the clock rate so fast that 145 // we get in trouble with certain HDMI sinks. 146 static const uint32_t kMinFullRangeSlewChange_mSec; 147 148 // How much time (in msec) to wait 149 static const int kSlewChangeStepPeriod_mSec; 150 151 #ifdef TIME_SERVICE_DEBUG 152 sp<DiagThread> diag_thread_; 153 #endif 154 }; 155 156 } // namespace android 157 158 #endif // __CLOCK_RECOVERY_H__ 159