1b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner/*
2a9be2d378b7ad84e679a48efa81f42fb54f85d9aJean-Michel Trivi * Copyright (c) 2011-2015, Intel Corporation
3b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * All rights reserved.
4b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner *
5b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * Redistribution and use in source and binary forms, with or without modification,
6b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * are permitted provided that the following conditions are met:
7b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner *
8b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * 1. Redistributions of source code must retain the above copyright notice, this
9b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * list of conditions and the following disclaimer.
10b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner *
11b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * 2. Redistributions in binary form must reproduce the above copyright notice,
12b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * this list of conditions and the following disclaimer in the documentation and/or
13b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * other materials provided with the distribution.
14b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner *
15b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * 3. Neither the name of the copyright holder nor the names of its contributors
16b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * may be used to endorse or promote products derived from this software without
17b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * specific prior written permission.
18b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner *
19b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28b76c9d6de717a9a1cfd94e7a8eca7ee4a2035cd7David Wagner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2968a912857707864bbaaff9808717813105072a6ePatrick Benavoli */
3068a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include "FixedPointParameterType.h"
3168a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include <stdlib.h>
3268a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include <sstream>
336ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli#include <iomanip>
346ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli#include <assert.h>
35258c6f5ae24de2e96ac0a0a842483bdc60b6b063Frederic Boisnard#include <math.h>
3668a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include "Parameter.h"
3768a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include "ParameterAccessContext.h"
3868a912857707864bbaaff9808717813105072a6ePatrick Benavoli#include "ConfigurationAccessContext.h"
39a9be2d378b7ad84e679a48efa81f42fb54f85d9aJean-Michel Trivi#include "Utility.h"
408b01852701d50869318663f568270f977d93dbdfFrederic Boisnard#include <errno.h>
418ef87a1fe5d2f05557856efa6faf070bb9b03337David Wagner#include <convert.hpp>
4268a912857707864bbaaff9808717813105072a6ePatrick Benavoli
4368a912857707864bbaaff9808717813105072a6ePatrick Benavoli#define base CParameterType
4468a912857707864bbaaff9808717813105072a6ePatrick Benavoli
45d9526499d6ab53b7d13d1434f748f6f2161c2e0aSebastien Gonzalveusing std::string;
46d9526499d6ab53b7d13d1434f748f6f2161c2e0aSebastien Gonzalve
479368eea42a1afb01dd44110582f997115b50e742François GaffieCFixedPointParameterType::CFixedPointParameterType(const string &strName) : base(strName)
4868a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
4968a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
5068a912857707864bbaaff9808717813105072a6ePatrick Benavoli
5168a912857707864bbaaff9808717813105072a6ePatrick Benavolistring CFixedPointParameterType::getKind() const
5268a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
5368a912857707864bbaaff9808717813105072a6ePatrick Benavoli    return "FixedPointParameter";
5468a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
5568a912857707864bbaaff9808717813105072a6ePatrick Benavoli
562ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli// Element properties
579368eea42a1afb01dd44110582f997115b50e742François Gaffievoid CFixedPointParameterType::showProperties(string &strResult) const
582ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli{
592ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli    base::showProperties(strResult);
602ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli
612ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli    // Notation
622ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli    strResult += "Notation: Q";
639368eea42a1afb01dd44110582f997115b50e742François Gaffie    strResult += std::to_string(_uiIntegral);
642ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli    strResult += ".";
659368eea42a1afb01dd44110582f997115b50e742François Gaffie    strResult += std::to_string(_uiFractional);
662ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli    strResult += "\n";
672ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli}
682ecf900ad8c30ce9f8e81f57977a1a80a6f6d8afPatrick Benavoli
6968a912857707864bbaaff9808717813105072a6ePatrick Benavoli// XML Serialization value space handling
7068a912857707864bbaaff9808717813105072a6ePatrick Benavoli// Value space handling for configuration import
719368eea42a1afb01dd44110582f997115b50e742François Gaffievoid CFixedPointParameterType::handleValueSpaceAttribute(
729368eea42a1afb01dd44110582f997115b50e742François Gaffie    CXmlElement &xmlConfigurableElementSettingsElement,
739368eea42a1afb01dd44110582f997115b50e742François Gaffie    CConfigurationAccessContext &configurationAccessContext) const
7468a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
7568a912857707864bbaaff9808717813105072a6ePatrick Benavoli    // Direction?
7668a912857707864bbaaff9808717813105072a6ePatrick Benavoli    if (!configurationAccessContext.serializeOut()) {
7768a912857707864bbaaff9808717813105072a6ePatrick Benavoli
789368eea42a1afb01dd44110582f997115b50e742François Gaffie        string strValueSpace;
799368eea42a1afb01dd44110582f997115b50e742François Gaffie        xmlConfigurableElementSettingsElement.getAttribute("ValueSpace", strValueSpace);
809368eea42a1afb01dd44110582f997115b50e742François Gaffie        configurationAccessContext.setValueSpaceRaw(strValueSpace == "Raw");
8168a912857707864bbaaff9808717813105072a6ePatrick Benavoli    } else {
8268a912857707864bbaaff9808717813105072a6ePatrick Benavoli        // Provide value space only if not the default one
8368a912857707864bbaaff9808717813105072a6ePatrick Benavoli        if (configurationAccessContext.valueSpaceIsRaw()) {
8468a912857707864bbaaff9808717813105072a6ePatrick Benavoli
859368eea42a1afb01dd44110582f997115b50e742François Gaffie            xmlConfigurableElementSettingsElement.setAttribute("ValueSpace", "Raw");
8668a912857707864bbaaff9808717813105072a6ePatrick Benavoli        }
8768a912857707864bbaaff9808717813105072a6ePatrick Benavoli    }
8868a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
8968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
909368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::fromXml(const CXmlElement &xmlElement,
919368eea42a1afb01dd44110582f997115b50e742François Gaffie                                       CXmlSerializingContext &serializingContext)
9268a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
9368a912857707864bbaaff9808717813105072a6ePatrick Benavoli    // Size
949368eea42a1afb01dd44110582f997115b50e742François Gaffie    size_t sizeInBits = 0;
959368eea42a1afb01dd44110582f997115b50e742François Gaffie    xmlElement.getAttribute("Size", sizeInBits);
9668a912857707864bbaaff9808717813105072a6ePatrick Benavoli
9768a912857707864bbaaff9808717813105072a6ePatrick Benavoli    // Q notation
989368eea42a1afb01dd44110582f997115b50e742François Gaffie    xmlElement.getAttribute("Integral", _uiIntegral);
999368eea42a1afb01dd44110582f997115b50e742François Gaffie    xmlElement.getAttribute("Fractional", _uiFractional);
10068a912857707864bbaaff9808717813105072a6ePatrick Benavoli
10168a912857707864bbaaff9808717813105072a6ePatrick Benavoli    // Size vs. Q notation integrity check
1029368eea42a1afb01dd44110582f997115b50e742François Gaffie    if (sizeInBits < getUtilSizeInBits()) {
10368a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1049368eea42a1afb01dd44110582f997115b50e742François Gaffie        std::string size;
1059368eea42a1afb01dd44110582f997115b50e742François Gaffie        xmlElement.getAttribute("Size", size);
1069368eea42a1afb01dd44110582f997115b50e742François Gaffie        serializingContext.setError(
1079368eea42a1afb01dd44110582f997115b50e742François Gaffie            "Inconsistent Size vs. Q notation for " + getKind() + " " + xmlElement.getPath() +
1089368eea42a1afb01dd44110582f997115b50e742François Gaffie            ": Summing (Integral + _uiFractional + 1) should not exceed given Size (" + size + ")");
10968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
11068a912857707864bbaaff9808717813105072a6ePatrick Benavoli        return false;
11168a912857707864bbaaff9808717813105072a6ePatrick Benavoli    }
11268a912857707864bbaaff9808717813105072a6ePatrick Benavoli
11368a912857707864bbaaff9808717813105072a6ePatrick Benavoli    // Set the size
1149368eea42a1afb01dd44110582f997115b50e742François Gaffie    setSize(sizeInBits / 8);
11568a912857707864bbaaff9808717813105072a6ePatrick Benavoli
11668a912857707864bbaaff9808717813105072a6ePatrick Benavoli    return base::fromXml(xmlElement, serializingContext);
11768a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
11868a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1199368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::toBlackboard(const string &strValue, uint32_t &uiValue,
1209368eea42a1afb01dd44110582f997115b50e742François Gaffie                                            CParameterAccessContext &parameterAccessContext) const
12168a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
1229368eea42a1afb01dd44110582f997115b50e742François Gaffie    bool bValueProvidedAsHexa = utility::isHexadecimal(strValue);
12368a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1246ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli    // Check data integrity
1256ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli    if (bValueProvidedAsHexa && !parameterAccessContext.valueSpaceIsRaw()) {
12668a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1279368eea42a1afb01dd44110582f997115b50e742François Gaffie        parameterAccessContext.setError("Hexadecimal values are not supported for " + getKind() +
1289368eea42a1afb01dd44110582f997115b50e742François Gaffie                                        " when selected value space is real:");
12968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1306ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli        return false;
13168a912857707864bbaaff9808717813105072a6ePatrick Benavoli    }
13268a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1336ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli    if (parameterAccessContext.valueSpaceIsRaw()) {
13468a912857707864bbaaff9808717813105072a6ePatrick Benavoli
135a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        if (bValueProvidedAsHexa) {
1368b01852701d50869318663f568270f977d93dbdfFrederic Boisnard
137a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie            return convertFromHexadecimal(strValue, uiValue, parameterAccessContext);
1388b01852701d50869318663f568270f977d93dbdfFrederic Boisnard        }
139a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        return convertFromDecimal(strValue, uiValue, parameterAccessContext);
140a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    }
141a24e61fddaf09d2989fff25785e329454c842d7fMattijs Korpershoek    return convertFromQnm(strValue, uiValue, parameterAccessContext);
142a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie}
14368a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1449368eea42a1afb01dd44110582f997115b50e742François Gaffievoid CFixedPointParameterType::setOutOfRangeError(
1459368eea42a1afb01dd44110582f997115b50e742François Gaffie    const string &strValue, CParameterAccessContext &parameterAccessContext) const
146a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie{
1479368eea42a1afb01dd44110582f997115b50e742François Gaffie    std::ostringstream stream;
148a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie
1499368eea42a1afb01dd44110582f997115b50e742François Gaffie    stream << "Value " << strValue << " standing out of admitted ";
150a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie
151a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    if (!parameterAccessContext.valueSpaceIsRaw()) {
152a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie
153a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        // Min/Max computation
154a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        double dMin = 0;
155a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        double dMax = 0;
156a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        getRange(dMin, dMax);
15768a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1589368eea42a1afb01dd44110582f997115b50e742François Gaffie        stream << std::fixed << std::setprecision(_uiFractional) << "real range [" << dMin << ", "
1599368eea42a1afb01dd44110582f997115b50e742François Gaffie               << dMax << "]";
1606ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli    } else {
1616ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
162a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        // Min/Max computation
163a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        int32_t iMax = getMaxValue<uint32_t>();
164a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        int32_t iMin = -iMax - 1;
16568a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1669368eea42a1afb01dd44110582f997115b50e742François Gaffie        stream << "raw range [";
1678b01852701d50869318663f568270f977d93dbdfFrederic Boisnard
1689368eea42a1afb01dd44110582f997115b50e742François Gaffie        if (utility::isHexadecimal(strValue)) {
1699368eea42a1afb01dd44110582f997115b50e742François Gaffie
1709368eea42a1afb01dd44110582f997115b50e742François Gaffie            stream << std::hex << std::uppercase << std::setw(static_cast<int>(getSize()) * 2)
1719368eea42a1afb01dd44110582f997115b50e742François Gaffie                   << std::setfill('0');
1728b01852701d50869318663f568270f977d93dbdfFrederic Boisnard
173a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie            // Format Min
1749368eea42a1afb01dd44110582f997115b50e742François Gaffie            stream << "0x" << makeEncodable(iMin);
175a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie            // Format Max
1769368eea42a1afb01dd44110582f997115b50e742François Gaffie            stream << ", 0x" << makeEncodable(iMax);
17768a912857707864bbaaff9808717813105072a6ePatrick Benavoli
178a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        } else {
1798b01852701d50869318663f568270f977d93dbdfFrederic Boisnard
1809368eea42a1afb01dd44110582f997115b50e742François Gaffie            stream << iMin << ", " << iMax;
181a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        }
18268a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1839368eea42a1afb01dd44110582f997115b50e742François Gaffie        stream << "]";
184a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    }
1859368eea42a1afb01dd44110582f997115b50e742François Gaffie    stream << " for " << getKind();
186a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie
1879368eea42a1afb01dd44110582f997115b50e742François Gaffie    parameterAccessContext.setError(stream.str());
18868a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
18968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1909368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::fromBlackboard(string &strValue, const uint32_t &value,
1919368eea42a1afb01dd44110582f997115b50e742François Gaffie                                              CParameterAccessContext &parameterAccessContext) const
19268a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
1938b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    // Check encodability
1949368eea42a1afb01dd44110582f997115b50e742François Gaffie    assert(isEncodable(value, false));
19568a912857707864bbaaff9808717813105072a6ePatrick Benavoli
19668a912857707864bbaaff9808717813105072a6ePatrick Benavoli    // Format
1979368eea42a1afb01dd44110582f997115b50e742François Gaffie    std::ostringstream stream;
19868a912857707864bbaaff9808717813105072a6ePatrick Benavoli
1996ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli    // Raw formatting?
20068a912857707864bbaaff9808717813105072a6ePatrick Benavoli    if (parameterAccessContext.valueSpaceIsRaw()) {
2016ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli        // Hexa formatting?
2026ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli        if (parameterAccessContext.outputRawFormatIsHex()) {
2039368eea42a1afb01dd44110582f997115b50e742François Gaffie            uint32_t data = static_cast<uint32_t>(value);
2046ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
2059368eea42a1afb01dd44110582f997115b50e742François Gaffie            stream << "0x" << std::hex << std::uppercase
2069368eea42a1afb01dd44110582f997115b50e742François Gaffie                   << std::setw(static_cast<int>(getSize() * 2)) << std::setfill('0') << data;
2076ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli        } else {
2089368eea42a1afb01dd44110582f997115b50e742François Gaffie            int32_t data = value;
2096ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
2105901c1d3f448af5d0506d889b0543d9e0de0c2ceGuillaume Denneulin            // Sign extend
2119368eea42a1afb01dd44110582f997115b50e742François Gaffie            signExtend(data);
2125901c1d3f448af5d0506d889b0543d9e0de0c2ceGuillaume Denneulin
2139368eea42a1afb01dd44110582f997115b50e742François Gaffie            stream << data;
2146ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli        }
21568a912857707864bbaaff9808717813105072a6ePatrick Benavoli    } else {
2169368eea42a1afb01dd44110582f997115b50e742François Gaffie        int32_t data = value;
21768a912857707864bbaaff9808717813105072a6ePatrick Benavoli
218258c6f5ae24de2e96ac0a0a842483bdc60b6b063Frederic Boisnard        // Sign extend
2199368eea42a1afb01dd44110582f997115b50e742François Gaffie        signExtend(data);
220258c6f5ae24de2e96ac0a0a842483bdc60b6b063Frederic Boisnard
221065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli        // Conversion
2229368eea42a1afb01dd44110582f997115b50e742François Gaffie        stream << std::fixed << std::setprecision(_uiFractional) << binaryQnmToDouble(data);
22368a912857707864bbaaff9808717813105072a6ePatrick Benavoli    }
22468a912857707864bbaaff9808717813105072a6ePatrick Benavoli
2259368eea42a1afb01dd44110582f997115b50e742François Gaffie    strValue = stream.str();
226065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
227065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    return true;
228065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli}
229065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
230065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli// Value access
2319368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::toBlackboard(double dUserValue, uint32_t &uiValue,
2329368eea42a1afb01dd44110582f997115b50e742François Gaffie                                            CParameterAccessContext &parameterAccessContext) const
233065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli{
2348b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    // Check that the value is within the allowed range for this type
2358b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    if (!checkValueAgainstRange(dUserValue)) {
236065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
237065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli        // Illegal value provided
238065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli        parameterAccessContext.setError("Value out of range");
239065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
240065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli        return false;
241065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    }
242065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
2438b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    // Do the conversion
244a24e61fddaf09d2989fff25785e329454c842d7fMattijs Korpershoek    int32_t iData = doubleToBinaryQnm(dUserValue);
2458b01852701d50869318663f568270f977d93dbdfFrederic Boisnard
2468b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    // Check integrity
2478b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    assert(isEncodable((uint32_t)iData, true));
2488b01852701d50869318663f568270f977d93dbdfFrederic Boisnard
249065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    uiValue = iData;
250065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
251065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    return true;
252065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli}
253065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
2549368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::fromBlackboard(double &dUserValue, uint32_t uiValue,
2559368eea42a1afb01dd44110582f997115b50e742François Gaffie                                              CParameterAccessContext & /*ctx*/) const
256065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli{
257065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    int32_t iData = uiValue;
258065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
2598b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    // Check unsigned value is encodable
2608b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    assert(isEncodable(uiValue, false));
261065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
262065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    // Sign extend
263065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    signExtend(iData);
264065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
265a24e61fddaf09d2989fff25785e329454c842d7fMattijs Korpershoek    dUserValue = binaryQnmToDouble(iData);
266065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
267065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    return true;
26868a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
26968a912857707864bbaaff9808717813105072a6ePatrick Benavoli
27068a912857707864bbaaff9808717813105072a6ePatrick Benavoli// Util size
2719368eea42a1afb01dd44110582f997115b50e742François Gaffiesize_t CFixedPointParameterType::getUtilSizeInBits() const
27268a912857707864bbaaff9808717813105072a6ePatrick Benavoli{
27368a912857707864bbaaff9808717813105072a6ePatrick Benavoli    return _uiIntegral + _uiFractional + 1;
27468a912857707864bbaaff9808717813105072a6ePatrick Benavoli}
2756ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
2768b01852701d50869318663f568270f977d93dbdfFrederic Boisnard// Compute the range for the type (minimum and maximum values)
2779368eea42a1afb01dd44110582f997115b50e742François Gaffievoid CFixedPointParameterType::getRange(double &dMin, double &dMax) const
2786ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli{
2799368eea42a1afb01dd44110582f997115b50e742François Gaffie    dMax = ((1U << (_uiIntegral + _uiFractional)) - 1) / double(1U << _uiFractional);
2809368eea42a1afb01dd44110582f997115b50e742François Gaffie    dMin = -((1U << (_uiIntegral + _uiFractional)) / double(1U << _uiFractional));
281a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie}
2826ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
2839368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::convertFromHexadecimal(
2849368eea42a1afb01dd44110582f997115b50e742François Gaffie    const string &strValue, uint32_t &uiValue,
2859368eea42a1afb01dd44110582f997115b50e742François Gaffie    CParameterAccessContext &parameterAccessContext) const
286a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie{
287a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    // For hexadecimal representation, we need full 32 bit range conversion.
2889368eea42a1afb01dd44110582f997115b50e742François Gaffie    if (!convertTo(strValue, uiValue) || !isEncodable(uiValue, false)) {
2896ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
290a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        setOutOfRangeError(strValue, parameterAccessContext);
291a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        return false;
292a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    }
2939368eea42a1afb01dd44110582f997115b50e742François Gaffie    signExtend(reinterpret_cast<int32_t &>(uiValue));
2946ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
295a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    // check that the data is encodable and can been safely written to the blackboard
2969368eea42a1afb01dd44110582f997115b50e742François Gaffie    assert(isEncodable(uiValue, true));
2978b01852701d50869318663f568270f977d93dbdfFrederic Boisnard
298a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    return true;
299a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie}
3006ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
3019368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::convertFromDecimal(
3029368eea42a1afb01dd44110582f997115b50e742François Gaffie    const string &strValue, uint32_t &uiValue,
3039368eea42a1afb01dd44110582f997115b50e742François Gaffie    CParameterAccessContext &parameterAccessContext) const
304a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie{
3059368eea42a1afb01dd44110582f997115b50e742François Gaffie    if (!convertTo(strValue, reinterpret_cast<int32_t &>(uiValue)) || !isEncodable(uiValue, true)) {
3066ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
307a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        setOutOfRangeError(strValue, parameterAccessContext);
308a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        return false;
309a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    }
310a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    return true;
311a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie}
3126ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
3139368eea42a1afb01dd44110582f997115b50e742François Gaffiebool CFixedPointParameterType::convertFromQnm(const string &strValue, uint32_t &uiValue,
3149368eea42a1afb01dd44110582f997115b50e742François Gaffie                                              CParameterAccessContext &parameterAccessContext) const
315a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie{
3169368eea42a1afb01dd44110582f997115b50e742François Gaffie    double dData = 0;
3176ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
318a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    if (!convertTo(strValue, dData) || !checkValueAgainstRange(dData)) {
3196ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
320a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        setOutOfRangeError(strValue, parameterAccessContext);
321a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie        return false;
3226ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli    }
323a24e61fddaf09d2989fff25785e329454c842d7fMattijs Korpershoek    uiValue = static_cast<uint32_t>(doubleToBinaryQnm(dData));
3246ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli
325a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    // check that the data is encodable and has been safely written to the blackboard
326a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    assert(isEncodable(uiValue, true));
327a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie
328a17d5a584a9b681e2eb48465815d275eb5fccb8fFrancois Gaffie    return true;
3296ba361d96bc2581667b3400f87ff89fae6449e1fPatrick Benavoli}
3301387bda01b089d8e8df06339d9c15d53b3de6725Patrick Benavoli
3318b01852701d50869318663f568270f977d93dbdfFrederic Boisnard// Check that the value is within available range for this type
3328b01852701d50869318663f568270f977d93dbdfFrederic Boisnardbool CFixedPointParameterType::checkValueAgainstRange(double dValue) const
3331387bda01b089d8e8df06339d9c15d53b3de6725Patrick Benavoli{
3348b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    double dMin = 0;
3358b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    double dMax = 0;
3368b01852701d50869318663f568270f977d93dbdfFrederic Boisnard    getRange(dMin, dMax);
33711e6498a4fa3b27ca34d2fcb76bd6365da9d5c1bPatrick Benavoli
338d9406eea67ae1d88b36e356d10d491f3bf0dfe1bMattijs Korpershoek    return (dValue <= dMax) && (dValue >= dMin);
3391387bda01b089d8e8df06339d9c15d53b3de6725Patrick Benavoli}
3401387bda01b089d8e8df06339d9c15d53b3de6725Patrick Benavoli
341065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli// Data conversion
342a24e61fddaf09d2989fff25785e329454c842d7fMattijs Korpershoekint32_t CFixedPointParameterType::doubleToBinaryQnm(double dValue) const
343065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli{
34459cc1e33810c55e6fa1e3bd320e1cf29e24d23beDavid Wagner    // For Qn.m number, multiply by 2^n and round to the nearest integer
3459368eea42a1afb01dd44110582f997115b50e742François Gaffie    int32_t iData = static_cast<int32_t>(round(dValue * double(1UL << _uiFractional)));
346065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    // Left justify
34759cc1e33810c55e6fa1e3bd320e1cf29e24d23beDavid Wagner    // For a Qn.m number, shift 32 - (n + m + 1) bits to the left (the rest of
34859cc1e33810c55e6fa1e3bd320e1cf29e24d23beDavid Wagner    // the bits aren't used)
349065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    iData <<= getSize() * 8 - getUtilSizeInBits();
350065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
351065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    return iData;
352065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli}
353065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli
354a24e61fddaf09d2989fff25785e329454c842d7fMattijs Korpershoekdouble CFixedPointParameterType::binaryQnmToDouble(int32_t iValue) const
355065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli{
356065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    // Unjustify
357065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli    iValue >>= getSize() * 8 - getUtilSizeInBits();
3589368eea42a1afb01dd44110582f997115b50e742François Gaffie    return static_cast<double>(iValue) / double(1UL << _uiFractional);
359065264a93ce9c63b6a5c95e985188ee33ba587d3Patrick Benavoli}
360326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron
361326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron// From IXmlSource
3629368eea42a1afb01dd44110582f997115b50e742François Gaffievoid CFixedPointParameterType::toXml(CXmlElement &xmlElement,
3639368eea42a1afb01dd44110582f997115b50e742François Gaffie                                     CXmlSerializingContext &serializingContext) const
364326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron{
365326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron    // Size
3669368eea42a1afb01dd44110582f997115b50e742François Gaffie    xmlElement.setAttribute("Size", getSize() * 8);
367326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron
368326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron    // Integral
3699368eea42a1afb01dd44110582f997115b50e742François Gaffie    xmlElement.setAttribute("Integral", _uiIntegral);
370326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron
371326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron    // Fractional
3729368eea42a1afb01dd44110582f997115b50e742François Gaffie    xmlElement.setAttribute("Fractional", _uiFractional);
373326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron
374326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron    base::toXml(xmlElement, serializingContext);
375326a31df0dd401283de6170ed09bcf605f61ef7dGeorges-Henri Baron}
376