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