ADTF_DEVICE_TOOLBOX  3.12.1 (ADTF 3.18.3)
Source Code for Demo CAN Generator
Location
./src/examples/src/can_generator/
This example shows:
Header
#pragma once
#include <adtf_filtersdk.h>
#include <adtf_base.h>
#include <adtf_systemsdk.h>
#include <adtf_devicetb_sdk.h>
class cCanGenerator : public adtf::filter::cSampleStreamingSource
{
public:
ADTF_CLASS_ID_NAME(cCanGenerator, "demo_can_generator.streaming_source.devicetb.cid","Demo CAN Generator");
ADTF_CLASS_DEPENDENCIES(REQUIRE_INTERFACE(adtf::services::IReferenceClock),
cCanGenerator();
tResult Init() override;
tResult StartStreaming() override;
tResult StopStreaming() override;
tResult ProcessSample();
private:
adtf::base::property_variable<tUInt> m_nTimer = 50;
adtf::base::property_variable<tUInt32> m_nMessageID = 0x30b;
adtf::base::property_variable<tUInt8> m_nChannelID = 1;
adtf::system::kernel_timer m_oLooper;
adtf::ucom::object_ptr<adtf::services::IReferenceClock> m_pClock;
adtf::streaming::ISampleWriter* m_pWriter;
adtf::ucom::object_ptr<adtf::devicetb::sdk::can::axle::ICANDatabase> m_pCanDb;
adtf::ucom::object_ptr<adtf::devicetb::sdk::can::axle::ICANCoder> m_pMediaCoderCan;
adtf::ucom::object_ptr<adtf::streaming::ISample> m_pSample;
adtf::ucom::object_ptr_locked<adtf::streaming::ISampleBuffer> m_pBufferLock;
};
Implementation
#include "demo_can_generator.h"
using namespace adtf;
using namespace adtf::util;
using namespace adtf::ucom;
using namespace adtf::streaming;
ADTF_PLUGIN_VERSION("Can generator",
devicetb,
DEVICETB_VERSION_MAJOR,
DEVICETB_VERSION_MINOR,
DEVICETB_VERSION_PATCH,
cCanGenerator)
constexpr const char* description =
R"(Use this Streaming Source to generate a in source predefined CAN Sample.
)";
cCanGenerator::cCanGenerator():
m_pWriter(CreateOutputPin("can_output", stream_meta_type_can()))
{
SetDescription("can_output", "The outcoming CAN sample stream containing the configured message.");
m_nTimer.SetDescription("Generation rate in [ms]");
RegisterPropertyVariable("Timer", m_nTimer);
m_nMessageID.SetDescription("The ID of the message.");
RegisterPropertyVariable("CAN Message ID", m_nMessageID);
m_nChannelID.SetDescription("The channel and database which should be used.");
RegisterPropertyVariable("CAN Channel ID", m_nChannelID);
SetDescription(description);
SetHelpLink("$(ADTF_DEVICE_TOOLBOX_DIR)/doc/adtf_device_toolbox_html/page_example_source_can_generator.html");
}
tResult cCanGenerator::Init()
{
object_ptr<ICANSupport> pCANSrv;
RETURN_IF_FAILED(_runtime->GetObject(m_pClock));
RETURN_IF_FAILED(_runtime->GetObject(pCANSrv));
RETURN_IF_FAILED(pCANSrv->GetDatabase(m_nChannelID, m_pCanDb));
RETURN_IF_FAILED(pCANSrv->CreateCoder(m_pMediaCoderCan));
return cSampleStreamingSource::Init();
}
tResult cCanGenerator::StartStreaming()
{
auto strMyName = get_named_graph_object_full_name(*this);
m_oLooper = system::kernel_timer(strMyName, m_nTimer * 1000, 0, &cCanGenerator::ProcessSample, this);
return cSampleStreamingSource::StartStreaming();
}
tResult cCanGenerator::StopStreaming()
{
m_oLooper.Stop();
return cSampleStreamingSource::StopStreaming();
}
tResult cCanGenerator::ProcessSample()
{
const tMessageInfo* oMessageInfo = nullptr;
RETURN_IF_FAILED(alloc_sample(m_pSample));
RETURN_IF_FAILED(m_pSample->WriteLock(m_pBufferLock, sizeof(tCANData)));
cMemoryBlock::MemZero(m_pBufferLock->GetPtr(), m_pBufferLock->GetSize());
RETURN_IF_FAILED(m_pSample->SetTime(m_pClock->GetStreamTime()));
RETURN_IF_FAILED(m_pMediaCoderCan->Begin(m_pBufferLock.Get()));
RETURN_IF_FAILED(m_pCanDb->GetMessageInfo(m_nMessageID, tTrue, &oMessageInfo));
RETURN_IF_FAILED(m_pMediaCoderCan->SetMessageInfo(m_nChannelID, m_nMessageID, oMessageInfo->bCANExtended));
for (tUInt32 nSignalCounter = 0; nSignalCounter < oMessageInfo->nSignalCount; nSignalCounter++)
{
tSignalInfo oSignalInfo = oMessageInfo->psSignalInfo[nSignalCounter];
auto oSignalValue = getSignalValueFromSignalInfo(oSignalInfo);
if (IS_FAILED(m_pMediaCoderCan->SetSignalValue(oSignalInfo.nSignalID, &oSignalValue)))
LOG_ERROR("could not set signal value for signal %s", oSignalInfo.strSignalName);
}
RETURN_IF_FAILED(m_pMediaCoderCan->End());
RETURN_IF_FAILED(m_pWriter->Write(m_pSample));
return m_pWriter->ManualTrigger();
}
tSignalValue cCanGenerator::getSignalValueFromSignalInfo(const tSignalInfo &oSignalInfo) const
{
tSignalValue oSignalValue;
switch (oSignalInfo.nType)
{
case tSignalRawDataType::DT_CAN_UNSIGNED:
oSignalValue.nTypeTag = tSignalValue::TAG_UINT64;
oSignalValue.nui64Value = (tUInt64)oSignalInfo.nStartRawValue;
break;
case tSignalRawDataType::DT_CAN_SIGNED:
oSignalValue.nTypeTag = tSignalValue::TAG_INT64;
oSignalValue.ni64Value = (tInt64)oSignalInfo.nStartRawValue;
break;
case tSignalRawDataType::DT_CAN_IEEE_FLOAT:
oSignalValue.nTypeTag = tSignalValue::TAG_FLOAT32;
oSignalValue.f32Value = (tFloat32)oSignalInfo.nStartRawValue;
break;
case tSignalRawDataType::DT_CAN_IEEE_DOUBLE:
oSignalValue.nTypeTag = tSignalValue::TAG_FLOAT64;
oSignalValue.f64Value = (tFloat64)oSignalInfo.nStartRawValue;
break;
default: break;
}
return oSignalValue;
}
Namespace for functionality provided by V3.0.0.
axle::tMessageInfo tMessageInfo
Definition: can_types.h:302
axle::tSignalValue tSignalValue
Definition: can_types.h:301
axle::tSignalInfo tSignalInfo
Definition: can_types.h:300
axle::tCANData tCANData
The CAN data structure is used by CAN MediaSamples use following code within your filter:
Definition: can_types.h:294
axle::stream_meta_type_can stream_meta_type_can
Definition of Stream Meta Type CAN Messages.
ADTF - Namespace.