#include "demo_canfd_coder_generator.h"
ADTF_PLUGIN_VERSION("CAN FD coder generator",
devicetb,
DEVICETB_VERSION_MAJOR,
DEVICETB_VERSION_MINOR,
DEVICETB_VERSION_PATCH,
cCANFDCoderGenerator)
namespace
{
{
std::vector<tPDUID> oPduIds;
if (pPduInfo)
{
oPduIds.push_back(pPduInfo->nId);
for (size_t nTransformIndex = 0; nTransformIndex < pPduInfo->nTransformationCount; ++nTransformIndex)
{
const auto nChildPdu = pPduInfo->pTransformations[nTransformIndex].nChildPduId;
THROW_IF_FAILED(oDB.GetPduInfo(nChildPdu, &pChildPduInfo));
const auto oChildIds = get_pdu_ids(pChildPduInfo, oDB);
oPduIds.insert(oPduIds.end(), oChildIds.begin(), oChildIds.end());
}
}
return oPduIds;
}
{
std::unordered_map<tPDUID, tMessageID> oMessageIds;
THROW_IF_FAILED(oDB.GetClusterFrames(ucom::make_function([&](
const tFrameInfo* pFrameInfo)
{
for (const auto nPduId: get_pdu_ids(pFrameInfo->pPduInfo, oDB))
{
oMessageIds[nPduId] = pFrameInfo->nMessageId;
}
})));
tMessageID nMessageId = ignition::INVALID_MESSAGE_ID;
THROW_IF_FAILED(oDB.GetPdusBySignal(nSignalID, ucom::make_function([&](
const tPduInfo* pPduInfo)
{
const auto itMessageId = oMessageIds.find(pPduInfo->nId);
if (itMessageId != oMessageIds.end())
{
nMessageId = itMessageId->second;
}
})));
if (nMessageId == ignition::INVALID_MESSAGE_ID)
{
THROW_ERROR_DESC(ERR_NOT_FOUND, "Unable to find message id for frame that contains the signal %d", nSignalID);
}
return nMessageId;
}
}
cCANFDCoderGenerator::cCANFDCoderGenerator() :
{
SetDescription("canfd_output", "The outcoming CAN FD sample stream containing the configured signal and value.");
m_nTimer.SetDescription("Generation rate in [ms]");
RegisterPropertyVariable("Timer", m_nTimer);
m_strSignal.SetDescription("The name of the signal.");
RegisterPropertyVariable("Signal", m_strSignal);
m_nChannelID.SetDescription("The channel and database which should be used.");
RegisterPropertyVariable("ChannelID", m_nChannelID);
m_nSignalValue.SetDescription("The value for the signal.");
RegisterPropertyVariable("Signalvalue", m_nSignalValue);
SetDescription("Use this Streaming Source to generate CAN FD data for a specific signal from a CAN FD database.");
SetHelpLink("$(ADTF_DEVICE_TOOLBOX_DIR)/doc/adtf_device_toolbox_html/page_example_source_canfd_coder_generator.html");
}
ucom::object_ptr<streaming::IStreamType> create_canfd_stream_type(tChannelID nChannel,
ICANFDDatabase& oDatabase)
{
ucom::object_ptr<streaming::IStreamType> pStreamType = ucom::make_object_ptr<streaming::stream_type<stream_meta_type_canfd>>();
streaming::set_property<std::string>(*pStreamType.Get(), stream_meta_type_canfd::CanFdChannelNumber, std::to_string(nChannel));
const tChar* strClusterName;
THROW_IF_FAILED(oDatabase.GetClusterName(&strClusterName));
streaming::set_property<util::cString>(*pStreamType.Get(), stream_meta_type_canfd::CanFdNetworkName, strClusterName);
return pStreamType;
}
tResult cCANFDCoderGenerator::Init()
{
RETURN_IF_FAILED(cSampleStreamingSource::Init());
if (m_strSignal->IsEmpty())
{
RETURN_ERROR_DESC(ERR_INVALID_ARG, "Please set a signal name");
}
RETURN_IF_FAILED(_runtime->GetObject(m_pClock));
adtf::ucom::object_ptr<ICANFDSupport> pCanFdSupport;
RETURN_IF_FAILED(_runtime->GetObject(pCanFdSupport));
adtf::ucom::object_ptr<ICANFDDatabase> pDatabase;
RETURN_IF_FAILED(pCanFdSupport->GetDatabase(static_cast<tChannelID>(m_nChannelID), pDatabase));
RETURN_IF_FAILED(pDatabase->GetSignalInfo(*m_strSignal, &pInfo));
m_nSignalId = pInfo->nId;
RETURN_IF_FAILED(pCanFdSupport->CreateCoder(m_pCoder));
RETURN_IF_FAILED(m_pCoder->CreateMessage(get_message_id_for_signal(m_nSignalId, *pDatabase), static_cast<tChannelID>(m_nChannelID)));
m_pWriter->ChangeType(create_canfd_stream_type(static_cast<tChannelID>(m_nChannelID), *pDatabase));
RETURN_NOERROR;
}
tResult cCANFDCoderGenerator::StartStreaming()
{
RETURN_IF_FAILED(cSampleStreamingSource::StartStreaming());
auto strMyName = adtf::streaming::get_named_graph_object_full_name(*this);
m_oLooper = system::kernel_timer(strMyName, m_nTimer * 1000, 0, &cCANFDCoderGenerator::CreateSample, this);
RETURN_NOERROR;
}
tResult cCANFDCoderGenerator::StopStreaming()
{
m_oLooper.Stop();
return cSampleStreamingSource::StopStreaming();
}
tResult cCANFDCoderGenerator::CreateSample()
{
const auto tmNow = m_pClock->GetStreamTimeNs();
RETURN_IF_FAILED(m_pCoder->SetPhysicalSignalValue(m_nSignalId, m_nSignalValue));
streaming::output_sample_data<tCANFDData> oSample(tmNow);
RETURN_IF_FAILED(m_pCoder->GetMessageData(oSample.GetDataPtr()));
oSample->sHeader.tmTimeStamp = base::duration_cast<tTimeStamp>(tmNow);
m_pWriter->Write(oSample.Release());
return m_pWriter->ManualTrigger();
}
Copyright 2024 CARIAD SE.
axle::tSignalInfo tSignalInfo
Namespace for CAN FD in ADTF-Devicetoolbox.
ignition::tFrameInfo tFrameInfo
Frame structure which encapsulates one or more PDUs including its specific information.
jack::ICANFDDatabase ICANFDDatabase
The ICANFDDatabase interface.
ignition::tMessageID tMessageID
axle::stream_meta_type_canfd stream_meta_type_canfd
Definition of Stream Meta Type CANFD Messages.
ignition::tPduInfo tPduInfo
Message/PDU structure which contain all information about one specific message.