16c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen/*
26c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Copyright (C) 2012 The Android Open Source Project
36c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *
46c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Licensed under the Apache License, Version 2.0 (the "License");
56c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * you may not use this file except in compliance with the License.
66c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * You may obtain a copy of the License at
76c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *
86c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *      http://www.apache.org/licenses/LICENSE-2.0
96c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen *
106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * Unless required by applicable law or agreed to in writing, software
116c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * distributed under the License is distributed on an "AS IS" BASIS,
126c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * See the License for the specific language governing permissions and
146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen * limitations under the License.
156c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen */
166c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
176c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#define __STDC_LIMIT_MACROS
186c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
196c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#define LOG_TAG "common_time"
206c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/Log.h>
216c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
226c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <stdint.h>
236c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
246c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/Errors.h>
256c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include <utils/LinearTransform.h>
266c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
276c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen#include "common_clock.h"
286c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
296c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chennamespace android {
306c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
316c929510474caa14dc9d56826b2c65552861d6b3Mike J. ChenCommonClock::CommonClock() {
326c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_slew_        = 0;
336c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_valid_ = false;
346c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
356c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_zero = 0;
366c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.b_zero = 0;
376c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 1;
386c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 1;
396c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    duration_trans_ = cur_trans_;
406c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
416c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
426c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenbool CommonClock::init(uint64_t local_freq) {
436c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    Mutex::Autolock lock(&lock_);
446c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
456c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!local_freq)
466c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return false;
476c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
486c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    uint64_t numer = kCommonFreq;
496c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    uint64_t denom = local_freq;
506c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
516c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    LinearTransform::reduce(&numer, &denom);
526c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if ((numer > UINT32_MAX) || (denom > UINT32_MAX)) {
536c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        ALOGE("Overflow in CommonClock::init while trying to reduce %lld/%lld",
546c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen             kCommonFreq, local_freq);
556c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return false;
566c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
576c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
586c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_to_b_numer = local_to_common_freq_numer_ =
596c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        static_cast<uint32_t>(numer);
606c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_to_b_denom = local_to_common_freq_denom_ =
616c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        static_cast<uint32_t>(denom);
626c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    duration_trans_ = cur_trans_;
636c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
646c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return true;
656c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
666c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
676c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenstatus_t CommonClock::localToCommon(int64_t local, int64_t *common_out) const {
686c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    Mutex::Autolock lock(&lock_);
696c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
706c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!cur_trans_valid_)
716c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return INVALID_OPERATION;
726c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
736c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!cur_trans_.doForwardTransform(local, common_out))
746c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return INVALID_OPERATION;
756c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
766c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return OK;
776c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
786c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
796c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenstatus_t CommonClock::commonToLocal(int64_t common, int64_t *local_out) const {
806c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    Mutex::Autolock lock(&lock_);
816c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
826c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!cur_trans_valid_)
836c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return INVALID_OPERATION;
846c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
856c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (!cur_trans_.doReverseTransform(common, local_out))
866c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        return INVALID_OPERATION;
876c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
886c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return OK;
896c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
906c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
916c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenint64_t CommonClock::localDurationToCommonDuration(int64_t localDur) const {
926c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    int64_t ret;
936c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    duration_trans_.doForwardTransform(localDur, &ret);
946c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return ret;
956c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
966c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
976c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenvoid CommonClock::setBasis(int64_t local, int64_t common) {
986c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    Mutex::Autolock lock(&lock_);
996c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1006c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_zero = local;
1016c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.b_zero = common;
1026c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_valid_ = true;
1036c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
1046c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1056c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenvoid CommonClock::resetBasis() {
1066c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    Mutex::Autolock lock(&lock_);
1076c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1086c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_zero = 0;
1096c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.b_zero = 0;
1106c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_valid_ = false;
1116c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
1126c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1136c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chenstatus_t CommonClock::setSlew(int64_t change_time, int32_t ppm) {
1146c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    Mutex::Autolock lock(&lock_);
1156c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1166c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    int64_t new_local_basis;
1176c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    int64_t new_common_basis;
1186c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1196c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    if (cur_trans_valid_) {
1206c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        new_local_basis = change_time;
1216c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        if (!cur_trans_.doForwardTransform(change_time, &new_common_basis)) {
1226c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            ALOGE("Overflow when attempting to set slew rate to %d", ppm);
1236c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen            return INVALID_OPERATION;
1246c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        }
1256c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    } else {
1266c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        new_local_basis = 0;
1276c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen        new_common_basis = 0;
1286c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    }
1296c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1306c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_slew_ = ppm;
1316c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    uint32_t n1 = local_to_common_freq_numer_;
1326c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    uint32_t n2 = 1000000 + cur_slew_;
1336c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1346c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    uint32_t d1 = local_to_common_freq_denom_;
1356c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    uint32_t d2 = 1000000;
1366c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1376c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    // n1/d1 has already been reduced, no need to do so here.
1386c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    LinearTransform::reduce(&n1, &d2);
1396c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    LinearTransform::reduce(&n2, &d1);
1406c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    LinearTransform::reduce(&n2, &d2);
1416c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1426c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_zero = new_local_basis;
1436c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.b_zero = new_common_basis;
1446c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_to_b_numer = n1 * n2;
1456c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    cur_trans_.a_to_b_denom = d1 * d2;
1466c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1476c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen    return OK;
1486c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}
1496c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen
1506c929510474caa14dc9d56826b2c65552861d6b3Mike J. Chen}  // namespace android
151