/**
 * @file SineArrayGAM.cpp
 * @brief Source file for class SineArrayGAM
 * @date 15/05/2026
 * @author Martino Ferrari
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing,
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/
#include <cmath>

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "SineArrayGAM.h"

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/

namespace MARTe {

SineArrayGAM::SineArrayGAM() :
        GAM(),
        frequency(1.0),
        amplitude(1.0),
        offset(0.0),
        phase(0.0),
        samplingRate(1000000.0),
        nElements(0u),
        sampleOffset(0ull),
        outputBuf(NULL_PTR(float32 *)) {
}

SineArrayGAM::~SineArrayGAM() {
}

bool SineArrayGAM::Initialise(StructuredDataI &data) {
    bool ok = GAM::Initialise(data);
    if (ok) {
        if (!data.Read("Frequency", frequency)) {
            frequency = 1.0;
        }
        if (!data.Read("Amplitude", amplitude)) {
            amplitude = 1.0;
        }
        if (!data.Read("Offset", offset)) {
            offset = 0.0;
        }
        if (!data.Read("Phase", phase)) {
            phase = 0.0;
        }
        if (!data.Read("SamplingRate", samplingRate)) {
            samplingRate = 1000000.0;
        }
        if (samplingRate <= 0.0) {
            REPORT_ERROR(ErrorManagement::InitialisationError,
                         "SineArrayGAM: SamplingRate must be greater than zero");
            ok = false;
        }
    }
    return ok;
}

bool SineArrayGAM::Setup() {
    bool ok = (GetNumberOfOutputSignals() == 1u);
    if (!ok) {
        REPORT_ERROR(ErrorManagement::InitialisationError,
                     "SineArrayGAM: exactly one output signal is required");
        return false;
    }

    uint32 sz = 0u;
    ok = GetSignalByteSize(OutputSignals, 0u, sz);
    if (ok) {
        nElements  = sz / static_cast<uint32>(sizeof(float32));
        outputBuf  = reinterpret_cast<float32 *>(GetOutputSignalMemory(0u));
        ok = (outputBuf != NULL_PTR(float32 *)) && (nElements > 0u);
        if (!ok) {
            REPORT_ERROR(ErrorManagement::InitialisationError,
                         "SineArrayGAM: failed to resolve output signal memory");
        }
    }
    return ok;
}

bool SineArrayGAM::Execute() {
    static const float64 TWO_PI = 6.28318530717958647692;
    const float64 twoPiF  = TWO_PI * frequency;
    const float64 invSr   = 1.0 / samplingRate;

    for (uint32 i = 0u; i < nElements; i++) {
        float64 t      = static_cast<float64>(sampleOffset + static_cast<uint64>(i)) * invSr;
        outputBuf[i]   = static_cast<float32>(amplitude * std::sin(twoPiF * t + phase) + offset);
    }
    sampleOffset += static_cast<uint64>(nElements);
    return true;
}

CLASS_REGISTER(SineArrayGAM, "1.0")

} /* namespace MARTe */
