diff options
Diffstat (limited to 'libs/common_time/common_clock.cpp')
-rw-r--r-- | libs/common_time/common_clock.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/libs/common_time/common_clock.cpp b/libs/common_time/common_clock.cpp new file mode 100644 index 0000000..c9eb388 --- /dev/null +++ b/libs/common_time/common_clock.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define __STDC_LIMIT_MACROS + +#define LOG_TAG "common_time" +#include <utils/Log.h> + +#include <stdint.h> + +#include <utils/Errors.h> +#include <utils/LinearTransform.h> + +#include "common_clock.h" + +namespace android { + +CommonClock::CommonClock() { + cur_slew_ = 0; + cur_trans_valid_ = false; + + cur_trans_.a_zero = 0; + cur_trans_.b_zero = 0; + cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 1; + cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 1; + duration_trans_ = cur_trans_; +} + +bool CommonClock::init(uint64_t local_freq) { + Mutex::Autolock lock(&lock_); + + if (!local_freq) + return false; + + uint64_t numer = kCommonFreq; + uint64_t denom = local_freq; + + LinearTransform::reduce(&numer, &denom); + if ((numer > UINT32_MAX) || (denom > UINT32_MAX)) { + ALOGE("Overflow in CommonClock::init while trying to reduce %lld/%lld", + kCommonFreq, local_freq); + return false; + } + + cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = + static_cast<uint32_t>(numer); + cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = + static_cast<uint32_t>(denom); + duration_trans_ = cur_trans_; + + return true; +} + +status_t CommonClock::localToCommon(int64_t local, int64_t *common_out) const { + Mutex::Autolock lock(&lock_); + + if (!cur_trans_valid_) + return INVALID_OPERATION; + + if (!cur_trans_.doForwardTransform(local, common_out)) + return INVALID_OPERATION; + + return OK; +} + +status_t CommonClock::commonToLocal(int64_t common, int64_t *local_out) const { + Mutex::Autolock lock(&lock_); + + if (!cur_trans_valid_) + return INVALID_OPERATION; + + if (!cur_trans_.doReverseTransform(common, local_out)) + return INVALID_OPERATION; + + return OK; +} + +int64_t CommonClock::localDurationToCommonDuration(int64_t localDur) const { + int64_t ret; + duration_trans_.doForwardTransform(localDur, &ret); + return ret; +} + +void CommonClock::setBasis(int64_t local, int64_t common) { + Mutex::Autolock lock(&lock_); + + cur_trans_.a_zero = local; + cur_trans_.b_zero = common; + cur_trans_valid_ = true; +} + +void CommonClock::resetBasis() { + Mutex::Autolock lock(&lock_); + + cur_trans_.a_zero = 0; + cur_trans_.b_zero = 0; + cur_trans_valid_ = false; +} + +status_t CommonClock::setSlew(int64_t change_time, int32_t ppm) { + Mutex::Autolock lock(&lock_); + + int64_t new_local_basis; + int64_t new_common_basis; + + if (cur_trans_valid_) { + new_local_basis = change_time; + if (!cur_trans_.doForwardTransform(change_time, &new_common_basis)) { + ALOGE("Overflow when attempting to set slew rate to %d", ppm); + return INVALID_OPERATION; + } + } else { + new_local_basis = 0; + new_common_basis = 0; + } + + cur_slew_ = ppm; + uint32_t n1 = local_to_common_freq_numer_; + uint32_t n2 = 1000000 + cur_slew_; + + uint32_t d1 = local_to_common_freq_denom_; + uint32_t d2 = 1000000; + + // n1/d1 has already been reduced, no need to do so here. + LinearTransform::reduce(&n1, &d2); + LinearTransform::reduce(&n2, &d1); + LinearTransform::reduce(&n2, &d2); + + cur_trans_.a_zero = new_local_basis; + cur_trans_.b_zero = new_common_basis; + cur_trans_.a_to_b_numer = n1 * n2; + cur_trans_.a_to_b_denom = d1 * d2; + + return OK; +} + +} // namespace android |