• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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