#include #include #include "icsneo/icsneocpp.h" #include "icsneo/device/extensions/flexray/cluster.h" /* Modifiable Configuration Variables*/ static size_t NumMessages = 300; static size_t FramePayloadSize = 134; static uint16_t SlotOne = 1; static uint16_t SlotTwo = 3; static bool SuppressRxTxDebugMessages = true; static const icsneo::FlexRay::Controller::Configuration DefaultControllerConfig { 160, // uint16_t AcceptStartupRangeMicroticks INIT(0); // pdAcceptedStartupRange true, // bool AllowHaltDueToClock INIT(false); // pAllowHaltDueToClock 15, // uint8_t AllowPassiveToActiveCyclePairs INIT(0); // pAllowPassiveToActive 2, // uint8_t ClusterDriftDamping INIT(0); // pClusterDriftDamping true, // bool ChannelA INIT(false); // pChannels true, // bool ChannelB INIT(false); // pChannels 56, // uint8_t DecodingCorrectionMicroticks INIT(0); // pDecodingCorrection 28, // uint8_t DelayCompensationAMicroticks INIT(0); // pDelayCompensation[A] 28, // uint8_t DelayCompensationBMicroticks INIT(0); // pDelayCompensation[B] 0, // uint8_t ExternOffsetCorrectionControl INIT(0); // pExternOffsetControl 0, // uint8_t ExternRateCorrectionControl INIT(0); // pExternRateControl 0, // uint8_t ExternOffsetCorrectionMicroticks INIT(0); // pExternOffsetCorrection 0, // uint8_t ExternRateCorrectionMicroticks INIT(0); // pExternRateCorrection 0, // uint16_t KeySlotID INIT(0); false, // bool KeySlotOnlyEnabled INIT(false); // pSingleSlotEnabled (TSM) true, // bool KeySlotUsedForStartup INIT(false); // pKeySlotUsedForStartup (TXST) true, // bool KeySlotUsedForSync INIT(false); // pKeySlotUsedForSync (TXSY) 226, // uint16_t LatestTxMinislot INIT(0); // pLatestTx 401202, // uint32_t ListenTimeout INIT(0); // pdListenTimeout 7, // uint8_t MacroInitialOffsetA INIT(0); // pMacroInitialOffset[A], Valid 2..72 7, // uint8_t MacroInitialOffsetB INIT(0); // pMacroInitialOffset[B], Valid 2..72 36, // uint8_t MicroInitialOffsetA INIT(0); // pMicroInitialOffset[A], Valid 0..240 36, // uint8_t MicroInitialOffsetB INIT(0); // pMicroInitialOffset[B], Valid 0..240 200000, // uint32_t MicroPerCycle INIT(0); // pMicroPerCycle false, // bool MTSOnA INIT(false); false, // bool MTSOnB INIT(false); 189, // uint16_t OffsetCorrectionOutMicroticks INIT(0); // pOffsetCorrectionOut 601, // uint16_t RateCorrectionOutMicroticks INIT(0); // pdMaxDrift and pRateCorrectionOut 0, // uint16_t SecondKeySlotID INIT(0); false, // bool TwoKeySlotMode INIT(false); 55, // uint8_t WakeupPattern INIT(0); false, // bool WakeupOnChannelB INIT(false); // pWakeupChannel }; namespace Cluster = icsneo::FlexRay::Cluster; static const Cluster::Configuration DefaultClusterConfig { Cluster::SpeedType::FLEXRAY_BAUDRATE_10M, // neoflexray_speed_t Speed INIT(FLEXRAY_BAUDRATE_10M /* = 0 */); // gdSampleClockPeriod, pSamplesPerMicrotick, Baud Rate Prescaler Cluster::SPPType::FLEXRAY_SPP_5, // neoflexray_spp_t StrobePointPosition INIT(FLEXRAY_SPP_5 /* = 0 */); 4, // uint8_t ActionPointOffset INIT(0); // gdActionPointOffset 64, // uint8_t CASRxLowMax INIT(0); // gdCASRxLowMax 8, // uint8_t ColdStartAttempts INIT(0); // gColdStartAttempts 5000, // uint16_t CycleDurationMicroSec INIT(0); // gdCycle 1, // uint8_t DynamicSlotIdlePhaseMinislots INIT(0); // gdDynamicSlotIdlePhase, In Minislot increments [0..2] 4, // uint8_t ListenNoiseMacroticks INIT(0); // gListenNoise 5000, // uint16_t MacroticksPerCycle INIT(0); // gMacroPerCycle 1, // uint8_t MacrotickDurationMicroSec INIT(0); // gdMacroTick 2, // uint8_t MaxWithoutClockCorrectionFatal INIT(0); // gMaxWithoutClockCorrectionFatal 2, // uint8_t MaxWithoutClockCorrectionPassive INIT(0); // gMaxWithoutClockCorrectionPassive 4, // uint8_t MinislotActionPointOffsetMacroticks INIT(0); // gdMinislotActionPointOffset 10, // uint32_t MinislotDurationMacroticks INIT(0); // gdMinislot 40, // uint32_t NetworkIdleTimeMacroticks INIT(0); // gdNIT 1, // uint8_t NetworkManagementVectorLengthBytes INIT(0); // gNetworkManagementVectorLength 0, // uint32_t NumberOfMinislots INIT(0); // gNumberOfMinislots 32, // uint16_t NumberOfStaticSlots INIT(0); // gdNumberOfStaticSlots 4991, // uint32_t OffsetCorrectionStartMacroticks INIT(0); // gOffsetCorrectionStart 67, // uint8_t PayloadLengthOfStaticSlotInWords INIT(0); // gPayloadLengthStatic 155, // uint16_t StaticSlotMacroticks INIT(0); // gdStaticSlot 0, // uint32_t SymbolWindowMacroticks INIT(0); // gdSymbolWindow 0, // uint32_t SymbolWindowActionPointOffsetMacroticks INIT(0); 15, // uint16_t SyncFrameIDCountMax INIT(0); // gSyncNodeMax 11, // uint8_t TransmissionStartSequenceDurationBits INIT(0); // gdTSSTransmitter 40, // uint8_t WakeupRxIdleBits INIT(0); // gdWakeupSymbolRxIdle 40, // uint8_t WakeupRxLowBits INIT(0); // gdWakeupSymbolRxLow 301, // uint16_t WakeupRxWindowBits INIT(0); // gdWakeupSymbolRxWindow 60, // uint8_t WakeupTxActiveBits INIT(0); // gdWakeupSymbolTxLow (active = low here) 180, // uint8_t WakeupTxIdleBits INIT(0); // gdWakeupSymbolTxIdle }; static std::condition_variable cv; static std::mutex msgRcvdMutex; void configureFlexRayDevice(std::shared_ptr device) { auto controllers = device->getFlexRayControllers(); for (uint16_t i = 0; i < controllers.size(); i++) { auto controller = controllers[i]; icsneo::FlexRay::Cluster::Configuration clusterConfig = DefaultClusterConfig; icsneo::FlexRay::Controller::Configuration controllerConfig = DefaultControllerConfig; controller->setAllowColdstart(true); controllerConfig.KeySlotID = (i == 0) ? SlotOne : SlotTwo; controller->setConfiguration(clusterConfig, controllerConfig); controller->setStartWhenGoingOnline(true); } } std::vector> makeDummyFlexRayMessages(size_t msgCount, size_t msgLen) { std::vector> messages; messages.reserve(msgCount); std::random_device rd; std::mt19937 engine(rd()); std::uniform_int_distribution dist(0, 255); for (size_t i = 0; i < msgCount; i++) { auto msg = std::make_shared(); msg->network = icsneo::Network::NetID::FLEXRAY_01; msg->cycleRepetition = 1; msg->channel = icsneo::FlexRay::Channel::AB; msg->data.reserve(msgLen); for (size_t j = 0; j < msgLen; j++) { msg->data.push_back(static_cast(dist(engine))); } msg->slotid = (i % 2 == 0) ? SlotOne : SlotTwo; messages.push_back(msg); } return messages; } int main() { auto devices = icsneo::FindAllDevices(); std::shared_ptr flexrayDevice = nullptr; for (auto&& device : devices) { if (device->getExtension("FlexRay")) { flexrayDevice = device; } } if (flexrayDevice) { std::cout << "Found device " << flexrayDevice->getProductName() << " " << flexrayDevice->getSerial() << " which supports FlexRay." << std::endl; auto&& controllers = flexrayDevice->getFlexRayControllers(); if (controllers.size() > 0) { std::vector> messages; size_t currentMessage = 0; auto filter = std::make_shared(icsneo::Network::NetID::FLEXRAY_01); auto rxCallback = [&messages, ¤tMessage](std::shared_ptr message) -> void { std::unique_lock lk(msgRcvdMutex); auto frmsg = std::static_pointer_cast(message); if (currentMessage < messages.size() && frmsg->data.size() > 1 && frmsg->data == messages[currentMessage]->data) { if (!SuppressRxTxDebugMessages) { std::cout << "Message Number " << currentMessage + 1 << " received." << std::endl; } currentMessage++; lk.unlock(); cv.notify_all(); } }; auto cb = std::make_shared(rxCallback, filter); auto cbId = flexrayDevice->addMessageCallback(cb); messages = makeDummyFlexRayMessages(NumMessages, FramePayloadSize); configureFlexRayDevice(flexrayDevice); if (!flexrayDevice->open()) { std::cerr << "Device open failed." << std::endl; return -1; } if (!flexrayDevice->goOnline()) { std::cerr << "Device go online failed." << std::endl; return -1; } std::cout << "Transmitting " << NumMessages << " FlexRay frames." << std::endl; for (auto msg : messages) { std::unique_lock lk(msgRcvdMutex); if (!flexrayDevice->transmit(msg)) { std::cerr << "Failed to transmit message." << std::endl; return -1; } else if (!SuppressRxTxDebugMessages) { std::cout << "Message Number " << currentMessage + 1 << " transmitted." << std::endl; } cv.wait(lk); lk.unlock(); } std::cout << "All transmitted frames received." << std::endl; flexrayDevice->removeMessageCallback(cbId); } } else { std::cerr << "Unable to find a device which supports FlexRay." << std::endl; return -1; } std::cout << "Finished." << std::endl; return 0; }