blob: 858786a98e0c5324f8bf126063ecab6fc7c34640 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/media/audio/lib/clock/pid_control.h"
#include <lib/syslog/cpp/macros.h>
namespace media::audio::clock {
// Reset the PID controller; set the initial result & time
void PidControl::Start(zx::time start_time) {
tune_time_ = start_time;
total_pid_contribution_ = 0.0;
current_error_ = accum_error_ = 0.0;
}
double PidControl::Read() const { return total_pid_contribution_; }
// Factor in the most current error reading
void PidControl::TuneForError(zx::time time_of_error, double error) {
// If our previous update was at this time, ignore it.
// This occurs if Start then TuneForError are called, with the same zx::time.
if (time_of_error == tune_time_) {
return;
}
FX_CHECK(time_of_error > tune_time_)
<< "Time for tuning (" << time_of_error.get() << ") is earlier than previous update ("
<< tune_time_.get() << ")";
// TODO(fxbug.dev/47778): normalize from 1ns units to 10ns, if accum_error_ becomes so large that
// lost precision impacts accuracy (as a double, accum_error_ has 54 bits of precision).
auto duration = (time_of_error - tune_time_).get();
tune_time_ = time_of_error;
delta_error_ = (error - current_error_) / duration;
accum_error_ += (error * duration);
current_error_ = error;
prop_contrib_ = current_error_ * proportional_factor_;
integ_contrib_ = accum_error_ * integral_factor_;
deriv_contrib_ = delta_error_ * derivative_factor_;
total_pid_contribution_ = prop_contrib_ + integ_contrib_ + deriv_contrib_;
}
void PidControl::DisplayCoefficients() {
FX_LOGS(INFO) << "Factors: P " << proportional_factor_ << ", I " << integral_factor_ << ", D "
<< derivative_factor_ << "; Contributions of p " << prop_contrib_ << ", i "
<< integ_contrib_ << ", d " << deriv_contrib_ << "; Total Contrib "
<< total_pid_contribution_ << "\n";
}
} // namespace media::audio::clock