diff --git a/DataSources/AtcaIop/AtcaIopADC.h b/DataSources/AtcaIop/AtcaIopADC.h
index 062df6a..858d950 100644
--- a/DataSources/AtcaIop/AtcaIopADC.h
+++ b/DataSources/AtcaIop/AtcaIopADC.h
@@ -2,7 +2,8 @@
* @file AtcaIopADC.h
* @brief Header file for class AtcaIopADC
* @date 19/10/2023
- * @author Andre Neto / Bernardo Carvalho
+ * @author Andre Neto
+ * @author Bernardo Carvalho
*
* Based on Example:
* https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2-demos-padova/-/tree/master/DataSources/ADCSimulator
@@ -15,7 +16,7 @@
* 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,
+ * @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.
@@ -36,424 +37,439 @@
/* Project header includes */
/*---------------------------------------------------------------------------*/
#include "DataSourceI.h"
-#include "EventSem.h"
#include "EmbeddedServiceMethodBinderI.h"
-#include "SingleThreadService.h"
+#include "EventSem.h"
#include "MessageI.h"
#include "RegisteredMethodsMessageFilter.h"
+#include "SingleThreadService.h"
/*---------------------------------------------------------------------------*/
/* Class declaration */
/*---------------------------------------------------------------------------*/
namespace MARTe {
- /**
- * The number of signals (2 time signals + ).
- */
+/**
+ * The number of signals (2 time signals + ).
+ */
// const uint32 ATCA_IOP_MAX_CHANNELS = 32u;
-
- const uint32 ATCA_IOP_N_TIMCNT = 4u;
- const uint32 ATCA_IOP_N_ADCs = 16u;
- const uint32 ATCA_IOP_N_INTEGRALS = ATCA_IOP_N_ADCs;
- const uint32 ATCA_IOP_N_SIGNALS = (ATCA_IOP_N_TIMCNT + 2); //ATCA_IOP_N_ADCs +
- //ATCA_IOP_N_INTEGRALS);
- /**
- * The number of buffers to synchronise with the DMA
- */
- const uint32 NUMBER_OF_BUFFERS = 8u;
- /**
- * @brief A DataSource that simulates an ADC board
- * TODO
- *
- * +AtcaIopADC = {
- * Class = "AtcaIop::AtcaIopADC"
- * CPUMask = "0x040"
- * StackSize = "1048576"
- * DeviceName = "/dev/atca_v6"
- * BoardId = 9
- * DeviceDmaName = "/dev/atca_v6_dmart_2"
- * NumberOfChannels = "12"
- * IsMaster = "1"
- * SleepNature = "Busy"
- * SleepPercentage = "15"
- * ADCFrequency = "2000000"
- * RTDecimation = "200"
- * ChopperPeriod = "2000"
- * ElectricalOffsets = {"-151" "110" "-417" "-35" "-204" "0" "134" "-59" "-227" "-308" "-120" "-175" "0" "0" "0" "0"}
- * WiringOffsets = {"0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0"}
- * //WiringOffsets = {0.354 0.288 -0.010 -0.083 0.347 0.228 0.088 0.186 -0.297 -0.101 0.025 -0.012 0.0 0.0 0.0 0.0}
- * //WiringOffsets = {"0.271" "0.211" "0.098" "0.141" "0.312" "0.203" "0.212" "0.361" "-0.546" "-0.433" "-0.598" "1.362"}
- * Signals = {
- * Counter = {
- * Type = "uint32"
- * }
- * Time = {
- * Type = "uint32"
- * }
- * TimeoutCount = {
- * Type = "uint32"
- * }
- * TimeoutMax = {
- * Type = "uint32"
- * }
- * ADCDecim = {
- * DataSource = "AtcaIopAdc_DS"
- * Type = "int32"
- * NumberOfElements = 16
- * NumberOfDimensions = 1
- * }
- * ADCInt = {
- * DataSource = "AtcaIopAdc_DS"
- * Type = "int64"
- * NumberOfElements = 16
- * NumberOfDimensions = 1
- * }
- * Idle_Thread1_CycleTime = {
- * DataSource = "Timings"
- * Alias = "Idle.Thread1_CycleTime"
- * Type = "uint32"
- * }
- * Run_Thread1_CycleTime = {
- * DataSource = "Timings"
- * Alias = "Online.Thread1_CycleTime"
- * Type = "uint32"
- * }
- * }
- * }
- *
- */
- class AtcaIopADC: public DataSourceI, public MessageI, public EmbeddedServiceMethodBinderI {
- public:
- CLASS_REGISTER_DECLARATION()
- /**
- * @brief Default constructor
- * @post
- * Counter = 0
- * Time = 0
- */
- AtcaIopADC ();
+const uint32 ATCA_IOP_N_TIMCNT = 4u;
+const uint32 ATCA_IOP_N_ADCs = 16u;
+const uint32 ATCA_IOP_N_INTEGRALS = ATCA_IOP_N_ADCs;
+const uint32 ATCA_IOP_N_SIGNALS =
+ (ATCA_IOP_N_TIMCNT + 2); // ATCA_IOP_N_ADCs +
+ // ATCA_IOP_N_INTEGRALS);
+/**
+ * The number of buffers to synchronise with the DMA
+ */
+const uint32 NUMBER_OF_BUFFERS = 8u;
- /**
- * @brief Destructor. Stops the EmbeddedThread.
- */
- virtual ~AtcaIopADC();
+/**
+ * @brief A DataSource that simulates an ADC board
+ * TODO
+ *
+ * +AtcaIopADC = {
+ * Class = "AtcaIop::AtcaIopADC"
+ * CPUMask = "0x040"
+ * StackSize = "1048576"
+ * DeviceName = "/dev/atca_v6"
+ * BoardId = 9
+ * DeviceDmaName = "/dev/atca_v6_dmart_2"
+ * NumberOfChannels = "12"
+ * IsMaster = "1"
+ * SleepNature = "Busy"
+ * SleepPercentage = "15"
+ * ADCFrequency = "2000000"
+ * RTDecimation = "200"
+ * ChopperPeriod = "2000"
+ * ElectricalOffsets = {"-151" "110" "-417" "-35" "-204" "0" "134" "-59" "-227"
+ * "-308" "-120" "-175" "0" "0" "0" "0"} WiringOffsets = {"0.0" "0.0" "0.0"
+ * "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0" "0.0"
+ * "0.0"}
+ * //WiringOffsets = {0.354 0.288 -0.010 -0.083 0.347 0.228 0.088 0.186 -0.297
+ * -0.101 0.025 -0.012 0.0 0.0 0.0 0.0}
+ * //WiringOffsets = {"0.271" "0.211" "0.098" "0.141" "0.312" "0.203" "0.212"
+ * "0.361" "-0.546" "-0.433" "-0.598" "1.362"} Signals = { Counter = { Type =
+ * "uint32"
+ * }
+ * Time = {
+ * Type = "uint32"
+ * }
+ * TimeoutCount = {
+ * Type = "uint32"
+ * }
+ * TimeoutMax = {
+ * Type = "uint32"
+ * }
+ * ADCDecim = {
+ * DataSource = "AtcaIopAdc_DS"
+ * Type = "int32"
+ * NumberOfElements = 16
+ * NumberOfDimensions = 1
+ * }
+ * ADCInt = {
+ * DataSource = "AtcaIopAdc_DS"
+ * Type = "int64"
+ * NumberOfElements = 16
+ * NumberOfDimensions = 1
+ * }
+ * Idle_Thread1_CycleTime = {
+ * DataSource = "Timings"
+ * Alias = "Idle.Thread1_CycleTime"
+ * Type = "uint32"
+ * }
+ * Run_Thread1_CycleTime = {
+ * DataSource = "Timings"
+ * Alias = "Online.Thread1_CycleTime"
+ * Type = "uint32"
+ * }
+ * }
+ * }
+ *
+ */
+class AtcaIopADC : public DataSourceI,
+ public MessageI,
+ public EmbeddedServiceMethodBinderI {
+public:
+ CLASS_REGISTER_DECLARATION()
+ /**
+ * @brief Default constructor
+ * @post
+ * Counter = 0
+ * Time = 0
+ */
+ AtcaIopADC();
- /**
- * @brief See DataSourceI::AllocateMemory.
- */
- virtual bool AllocateMemory();
+ /**
+ * @brief Destructor. Stops the EmbeddedThread.
+ */
+ virtual ~AtcaIopADC();
- /**
- gg* @brief See DataSourceI::GetNumberOfMemoryBuffers.
- * @return 1.
- */
- virtual uint32 GetNumberOfMemoryBuffers();
+ /**
+ * @brief See DataSourceI::AllocateMemory.
+ */
+ virtual bool AllocateMemory();
- /**
- * @brief See DataSourceI::GetNumberOfMemoryBuffers.
- */
- virtual bool GetSignalMemoryBuffer(const uint32 signalIdx,
- const uint32 bufferIdx,
- void *&signalAddress);
+ /**
+ gg* @brief See DataSourceI::GetNumberOfMemoryBuffers.
+ * @return 1.
+ */
+ virtual uint32 GetNumberOfMemoryBuffers();
- /**
- * @brief See DataSourceI::GetNumberOfMemoryBuffers.
- * @details Only InputSignals are supported.
- * @return MemoryMapSynchronisedInputBroker if frequency > 0, MemoryMapInputBroker otherwise.
- */
- virtual const char8 *GetBrokerName(StructuredDataI &data,
- const SignalDirection direction);
+ /**
+ * @brief See DataSourceI::GetNumberOfMemoryBuffers.
+ */
+ virtual bool GetSignalMemoryBuffer(const uint32 signalIdx,
+ const uint32 bufferIdx,
+ void *&signalAddress);
- /**
- * @brief Waits on an EventSem for the period given by 1/Frequency to elapse on Execute.
- * @return true if the semaphore is successfully posted.
- */
- virtual bool Synchronise();
+ /**
+ * @brief See DataSourceI::GetNumberOfMemoryBuffers.
+ * @details Only InputSignals are supported.
+ * @return MemoryMapSynchronisedInputBroker if frequency > 0,
+ * MemoryMapInputBroker otherwise.
+ */
+ virtual const char8 *GetBrokerName(StructuredDataI &data,
+ const SignalDirection direction);
- /**
- if (boardFileDescriptor != -1) {
- close(boardFileDescriptor);
- }
- * @brief Callback function for an EmbeddedThread.
- * @details Sleeps (Busy or Default) for the period given by 1/Frequency and post an EventSem which is waiting on
- * the Synchronise method.
- * @param[in] info not used.
- * @return NoError if the EventSem can be successfully posted.
- */
- virtual ErrorManagement::ErrorType Execute(ExecutionInfo & info);
+ /**
+ * @brief Waits on an EventSem for the period given by 1/Frequency to elapse
+ * on Execute.
+ * @return true if the semaphore is successfully posted.
+ */
+ virtual bool Synchronise();
- /**
- * @brief Resets the counter and the timer to zero and starts the EmbeddedThread.
- * @details See StatefulI::PrepareNextState. Starts the EmbeddedThread (if it was not already started) and loops
- * on the ExecuteMethod.
- * @return true if the EmbeddedThread can be successfully started.
- */
- virtual bool PrepareNextState(const char8 * const currentStateName,
- const char8 * const nextStateName);
+ /**
+ if (boardFileDescriptor != -1) {
+ close(boardFileDescriptor);
+ }
+ * @brief Callback function for an EmbeddedThread.
+ * @details Sleeps (Busy or Default) for the period given by 1/Frequency and
+ post an EventSem which is waiting on
+ * the Synchronise method.
+ * @param[in] info not used.
+ * @return NoError if the EventSem can be successfully posted.
+ */
+ virtual ErrorManagement::ErrorType Execute(ExecutionInfo &info);
- /**
- * @brief Initialises the AtcaIopADC
- * @param[in] data configuration in the form:
- * +AtcaIopADC = {
- * Class = AtcaIopADC
- * Signals = {
- * Counter = {
- * Type = uint32 //int32 also supported
- * }
- * Time = {
- * Type = uint32 //int32 also supported
- * Frequency = 10000
- * }
- * ADC0 = {
- * Type = uint32
- * }
- * ADC1 = {
- * Type = uint32
- * }
- * ADC2 = {
- * Type = uint32
- * }
- * ADC3 = {
- * Type = uint32
- * }
- * }
- * }
- * @return TODO
- */
- virtual bool Initialise(StructuredDataI & data);
+ /**
+ * @brief Resets the counter and the timer to zero and starts the
+ * EmbeddedThread.
+ * @details See StatefulI::PrepareNextState. Starts the EmbeddedThread (if it
+ * was not already started) and loops on the ExecuteMethod.
+ * @return true if the EmbeddedThread can be successfully started.
+ */
+ virtual bool PrepareNextState(const char8 *const currentStateName,
+ const char8 *const nextStateName);
- /**
- * @brief Verifies that two, and only two, signal are set with the correct type.
- * @details Verifies that two, and only two, signal are set; that the signals are
- * 32 bits in size with a SignedInteger or UnsignedInteger type and that a Frequency > 0 was set in one of the two signals.
- * @param[in] data see DataSourceI::SetConfiguredDatabase
- * @return true if the rules above are met.
- */
- virtual bool SetConfiguredDatabase(StructuredDataI & data);
+ /**
+ * @brief Initialises the AtcaIopADC
+ * @param[in] data configuration in the form:
+ * +AtcaIopADC = {
+ * Class = AtcaIopADC
+ * Signals = {
+ * Counter = {
+ * Type = uint32 //int32 also supported
+ * }
+ * Time = {
+ * Type = uint32 //int32 also supported
+ * Frequency = 10000
+ * }
+ * ADC0 = {
+ * Type = uint32
+ * }
+ * ADC1 = {
+ * Type = uint32
+ * }
+ * ADC2 = {
+ * Type = uint32
+ * }
+ * ADC3 = {
+ * Type = uint32
+ * }
+ * }
+ * }
+ * @return TODO
+ */
+ virtual bool Initialise(StructuredDataI &data);
- /**
- * @brief Gets the affinity of the thread which is going to be used to asynchronously wait for the time to elapse.
- * @return the affinity of the thread which is going to be used to asynchronously wait for the time to elapse.
- */
- const ProcessorType& GetCPUMask() const;
+ /**
+ * @brief Verifies that two, and only two, signal are set with the correct
+ * type.
+ * @details Verifies that two, and only two, signal are set; that the signals
+ * are 32 bits in size with a SignedInteger or UnsignedInteger type and that a
+ * Frequency > 0 was set in one of the two signals.
+ * @param[in] data see DataSourceI::SetConfiguredDatabase
+ * @return true if the rules above are met.
+ */
+ virtual bool SetConfiguredDatabase(StructuredDataI &data);
- /**
- * @brief Gets the stack size of the thread which is going to be used to asynchronously wait for the time to elapse.
- * @return the stack size of the thread which is going to be used to asynchronously wait for the time to elapse.
- */
- uint32 GetStackSize() const;
+ /**
+ * @brief Gets the affinity of the thread which is going to be used to
+ * asynchronously wait for the time to elapse.
+ * @return the affinity of the thread which is going to be used to
+ * asynchronously wait for the time to elapse.
+ */
+ const ProcessorType &GetCPUMask() const;
- /**
- * @brief Gets the percentage of the time to sleep using the OS sleep (i.e. the non-busy Sleep).
- * @return the percentage of the time to sleep using the OS sleep (i.e. the non-busy Sleep).
- */
- uint32 GetSleepPercentage() const;
+ /**
+ * @brief Gets the stack size of the thread which is going to be used to
+ * asynchronously wait for the time to elapse.
+ * @return the stack size of the thread which is going to be used to
+ * asynchronously wait for the time to elapse.
+ */
+ uint32 GetStackSize() const;
- /**
- * Find the currentDMABufferIndex and synchronize on data arrival
- */
-// int32 CurrentBufferIndex(uint64 waitLimitUs) const;
+ /**
+ * @brief Gets the percentage of the time to sleep using the OS sleep (i.e.
+ * the non-busy Sleep).
+ * @return the percentage of the time to sleep using the OS sleep (i.e. the
+ * non-busy Sleep).
+ */
+ uint32 GetSleepPercentage() const;
- private:
- /**
- * The board identifier
- */
- uint32 boardId;
- /**
- * The numberOfChannels
- */
- uint32 numberOfChannels;
- /**
- * The FPGA ADC Decimation factor from 2MSPS
- */
- uint32 rtDecimation;
- /**
- * The board device name
- */
- StreamString deviceName;
- /**
- * The board device name
- */
- //StreamString deviceDmaName;
- /**
- * The board file descriptor
- */
- int32 boardFileDescriptor;
+ /**
+ * Find the currentDMABufferIndex and synchronize on data arrival
+ */
+ // int32 CurrentBufferIndex(uint64 waitLimitUs) const;
- /**
- * The board Dma descriptor
- */
- int32 boardDmaDescriptor;
+private:
+ /**
+ * The board identifier
+ */
+ uint32 boardId;
+ /**
+ * The numberOfChannels
+ */
+ uint32 numberOfChannels;
+ /**
+ * The FPGA ADC Decimation factor from 2MSPS
+ */
+ uint32 rtDecimation;
+ /**
+ * The board device name
+ */
+ StreamString deviceName;
+ /**
+ * The board device name
+ */
+ // StreamString deviceDmaName;
+ /**
+ * The board file descriptor
+ */
+ int32 boardFileDescriptor;
- /**
- * The two supported sleep natures.
- */
- enum AtcaIopADCSleepNature {
- Default = 0,
- Busy = 1
- };
+ /**
+ * The board Dma descriptor
+ */
+ int32 boardDmaDescriptor;
- /**
- * The non-busy sleep percentage. Valid if
- * AtcaIopADCSleepNature == Busy
- */
- uint32 sleepPercentage;
+ /**
+ * The two supported sleep natures.
+ */
+ enum AtcaIopADCSleepNature { Default = 0, Busy = 1 };
- /**
- * The selected sleep nature.
- */
- AtcaIopADCSleepNature sleepNature;
+ /**
+ * The non-busy sleep percentage. Valid if
+ * AtcaIopADCSleepNature == Busy
+ */
+ uint32 sleepPercentage;
- /**
- * Debugging
- */
- //uint32 execCounter;
- //uint32 pollTimout;
+ /**
+ * The selected sleep nature.
+ */
+ AtcaIopADCSleepNature sleepNature;
- /**
- * Current counter and timer
- */
- uint32 counterAndTimer[2];
+ /**
+ * Debugging
+ */
+ // uint32 execCounter;
+ // uint32 pollTimout;
- /**
- * Timeout counter
- */
- uint32 timeoutCount;
+ /**
+ * Current counter and timer
+ */
+ uint32 counterAndTimer[2];
- /**
- * Timeout counter
- */
- uint32 timeoutMax;
+ /**
+ * Timeout counter
+ */
+ uint32 timeoutCount;
- /**
- * ADC values
- */
- //int32 adcValues[ATCA_IOP_N_ADCs];
- int32 *adcValues;
+ /**
+ * Timeout counter
+ */
+ uint32 timeoutMax;
- /**
- * ADC Integral values
- */
- int64 adcIntegralValues[ATCA_IOP_N_ADCs];
+ /**
+ * ADC values
+ */
+ // int32 adcValues[ATCA_IOP_N_ADCs];
+ int32 *adcValues;
- /**
- * Number of samples to read on each cycle
- */
- uint32 adcSamplesPerCycle;
-
- /**
- * The semaphore for the synchronisation between the EmbeddedThread and the Synchronise method.
- */
- EventSem synchSem;
+ /**
+ * ADC Integral values
+ */
+ int64 adcIntegralValues[ATCA_IOP_N_ADCs];
- /**
- * The EmbeddedThread where the Execute method waits for the period to elapse.
- */
- SingleThreadService executor;
+ /**
+ * Number of samples to read on each cycle
+ */
+ uint32 adcSamplesPerCycle;
- /**
- * HighResolutionTimer::Counter() value after the last Sleep.
- */
- uint64 lastTimeTicks;
+ /**
+ * The semaphore for the synchronisation between the EmbeddedThread and the
+ * Synchronise method.
+ */
+ EventSem synchSem;
- /**
- * Sleeping period in units of ticks.
- */
- uint64 sleepTimeTicks;
+ /**
+ * The EmbeddedThread where the Execute method waits for the period to elapse.
+ */
+ SingleThreadService executor;
- /**
- * Sleeping period.
- */
- uint32 timerPeriodUsecTime;
+ /**
+ * HighResolutionTimer::Counter() value after the last Sleep.
+ */
+ uint64 lastTimeTicks;
- /**
- * Index of the function which has the signal that synchronises on this DataSourceI.
- */
- uint32 synchronisingFunctionIdx;
+ /**
+ * Sleeping period in units of ticks.
+ */
+ uint64 sleepTimeTicks;
- /**
- * The affinity of the thread that asynchronously generates the time.
- */
- ProcessorType cpuMask;
+ /**
+ * Sleeping period.
+ */
+ uint32 timerPeriodUsecTime;
- /**
- * The size of the stack of the thread that asynchronously generates the time.
- */
- uint32 stackSize;
+ /**
+ * Index of the function which has the signal that synchronises on this
+ * DataSourceI.
+ */
+ uint32 synchronisingFunctionIdx;
- /**
- * The simulated signals frequencies.
- */
- //float32 signalsFrequencies[4];
+ /**
+ * The affinity of the thread that asynchronously generates the time.
+ */
+ ProcessorType cpuMask;
- /**
- * The simulated signals gains.
- */
+ /**
+ * The size of the stack of the thread that asynchronously generates the time.
+ */
+ uint32 stackSize;
- /**
- * The Electrical Offset Parameters.
- */
- int32 electricalOffsets[ATCA_IOP_N_ADCs];
+ /**
+ * The simulated signals frequencies.
+ */
+ // float32 signalsFrequencies[4];
- /**
- * The Wiring Offset Parameters.
- */
- float32 wiringOffsets[ATCA_IOP_N_ADCs];
+ /**
+ * The simulated signals gains.
+ */
- /**
- * The ADC chopping period in samples
- */
- uint16 chopperPeriod;
+ /**
+ * The Electrical Offset Parameters.
+ */
+ int32 electricalOffsets[ATCA_IOP_N_ADCs];
- /**
- * The simulated ADC frequency
- */
- uint32 adcFrequency;
+ /**
+ * The Wiring Offset Parameters.
+ */
+ float32 wiringOffsets[ATCA_IOP_N_ADCs];
- /**
- * The simulated ADC period
- */
- float64 adcPeriod;
+ /**
+ * The ADC chopping period in samples
+ */
+ uint16 chopperPeriod;
- /**
- * For the ATCA Master board
- */
- uint32 isMaster;
- /**
- * Pointer to mapped memory
- */
- //int32 * mappedDmaBase;
- void * mappedDmaBase;
- uint32 mappedDmaSize;
- /**
- * The last written buffer
- */
- uint8 currentBufferIdx;
+ /**
+ * The simulated ADC frequency
+ */
+ uint32 adcFrequency;
- /**
- * The oldest written DMA buffer index
- */
- uint8 oldestBufferIdx;
- /**
- * The last read buffer index
- */
- uint8 lastBufferIdx;
+ /**
+ * The simulated ADC period
+ */
+ float64 adcPeriod;
- /*
- * Find the latest completed buffer without synchronization
- */
- int32 GetLatestBufferIndex() const;
- uint32 GetOldestBufferIdx() const;
- int32 PollDmaBuff(uint64 maxWaitTicks) const;
+ /**
+ * For the ATCA Master board
+ */
+ uint32 isMaster;
+ /**
+ * Pointer to mapped memory
+ */
+ // int32 * mappedDmaBase;
+ void *mappedDmaBase;
+ uint32 mappedDmaSize;
+ /**
+ * The last written buffer
+ */
+ uint8 currentBufferIdx;
- /**
- * filter to receive the RPC which ...
- */
- ReferenceT filter;
+ /**
+ * The oldest written DMA buffer index
+ */
+ uint8 oldestBufferIdx;
+ /**
+ * The last read buffer index
+ */
+ uint8 lastBufferIdx;
- };
-}
+ /*
+ * Find the latest completed buffer without synchronization
+ */
+ int32 GetLatestBufferIndex() const;
+ uint32 GetOldestBufferIdx() const;
+ int32 PollDmaBuff(uint64 maxWaitTicks) const;
+
+ /**
+ * filter to receive the RPC which ...
+ */
+ ReferenceT filter;
+};
+} // namespace MARTe
/*---------------------------------------------------------------------------*/
/* Inline method definitions */
diff --git a/DataSources/PSUCommunicator/Makefile.cov b/DataSources/PSUCommunicator/Makefile.cov
new file mode 100644
index 0000000..5e0ca6d
--- /dev/null
+++ b/DataSources/PSUCommunicator/Makefile.cov
@@ -0,0 +1,28 @@
+#############################################################
+#
+# 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
+#
+# 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 for the specific language governing
+# permissions and limitations under the Licence.
+#
+#############################################################
+
+TARGET=cov
+
+include Makefile.inc
+
diff --git a/DataSources/PSUCommunicator/Makefile.gcc b/DataSources/PSUCommunicator/Makefile.gcc
new file mode 100644
index 0000000..a9d0599
--- /dev/null
+++ b/DataSources/PSUCommunicator/Makefile.gcc
@@ -0,0 +1,27 @@
+#############################################################
+#
+# 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
+#
+# 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 for the specific language governing
+# permissions and limitations under the Licence.
+#
+#############################################################
+
+
+include Makefile.inc
+
diff --git a/DataSources/PSUCommunicator/Makefile.inc b/DataSources/PSUCommunicator/Makefile.inc
new file mode 100644
index 0000000..cc782a8
--- /dev/null
+++ b/DataSources/PSUCommunicator/Makefile.inc
@@ -0,0 +1,57 @@
+#############################################################
+#
+# 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
+#
+# 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 for the specific language governing
+# permissions and limitations under the Licence.
+#
+#############################################################
+
+OBJSX=PSUCommunicatorTX.x UARTConfig.x
+
+PACKAGE=Components/DataSources
+
+ROOT_DIR=../..
+MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
+include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
+
+INCLUDES += -I.
+INCLUDES += -I./include
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
+INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L1Portability
+//INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L3Streams
+
+
+all: $(OBJS) \
+ $(BUILD_DIR)/PSUCommunicator$(LIBEXT) \
+ $(BUILD_DIR)/PSUCommunicator$(DLLEXT)
+ echo $(OBJS)
+
+include depends.$(TARGET)
+
+include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
+
diff --git a/DataSources/PSUCommunicator/PSUCommunicatorTX.cpp b/DataSources/PSUCommunicator/PSUCommunicatorTX.cpp
new file mode 100644
index 0000000..625a41e
--- /dev/null
+++ b/DataSources/PSUCommunicator/PSUCommunicatorTX.cpp
@@ -0,0 +1,441 @@
+/**
+ * @file PSUCommunicatorTX.cpp
+ * @brief Source file for class PSUCommunicatorTX
+ * @date 19/01/2024
+ * @author Andre Neto / Bernardo Carvalho
+ *
+ * @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.
+
+ * @details This source file contains the definition of all the methods for
+ * the class PSUCommunicatorTX (public, protected, and private). Be aware
+ that some
+ * methods, such as those inline could be defined on the header file, instead.
+ *
+ * https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2-components/-/blob/master/Source/Components/DataSources/NI6259/NI6259DAC.cpp
+ */
+
+#define DLL_API
+
+/*---------------------------------------------------------------------------*/
+/* Standard header includes */
+/*---------------------------------------------------------------------------*/
+#include
+
+#include
+#include // for close()
+
+/*---------------------------------------------------------------------------*/
+/* Project header includes */
+/*---------------------------------------------------------------------------*/
+#include "AdvancedErrorManagement.h"
+#include "MemoryMapSynchronisedOutputBroker.h"
+#include "PSUCommunicatorTX.h"
+#include "PSUMessages.h"
+
+/*---------------------------------------------------------------------------*/
+/* Static definitions */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Method definitions */
+/*---------------------------------------------------------------------------*/
+namespace MARTe {
+const float32 DAC_RANGE = 20.0;
+// const float32 ATCA_IOP_MAX_DAC_RANGE = 20.0;
+PSUCommunicatorTX::PSUCommunicatorTX() : DataSourceI(), MessageI() {
+ // boardFileDescriptor = -1;
+ // numberOfDACsEnabled = 0u;
+ // isMaster = 0u;
+ // deviceName = "";
+ // boardId = 2u;
+ triggerSet = false;
+ uint32 n;
+ // for (n = 0u; n < ATCA_IOP_MAX_DAC_CHANNELS; n++) {
+ // dacEnabled[n] = false;
+ outputRange = DAC_RANGE;
+ //}
+
+ // channelsMemory = NULL_PTR(float32 *);
+ channelValue = 0.0; // NULL_PTR(float32 *);
+ currentStep = 0.0;
+ pointOfZeroCurrent = 0.0;
+
+ filter = ReferenceT(
+ GlobalObjectsDatabase::Instance()->GetStandardHeap());
+ filter->SetDestination(this);
+ ErrorManagement::ErrorType ret = MessageI::InstallMessageFilter(filter);
+ if (!ret.ErrorsCleared()) {
+ REPORT_ERROR(ErrorManagement::FatalError,
+ "Failed to install message filters");
+ }
+}
+
+/*lint -e{1551} the destructor must guarantee that the Timer SingleThreadService
+ * is stopped.*/
+PSUCommunicatorTX::~PSUCommunicatorTX() {
+ // REPORT_ERROR(ErrorManagement::Information, " Close Device Status Reg %d,
+ // 0x%x", rc, statusReg); close(boardFileDescriptor);
+ serial.Close();
+ REPORT_ERROR_PARAMETERS(ErrorManagement::Information, "Close %s OK.",
+ portName);
+ /*
+ if (channelsMemory != NULL_PTR(float32 *)) {
+ delete[] channelsMemory;
+ }
+ */
+}
+
+bool PSUCommunicatorTX::AllocateMemory() { return true; }
+
+uint32 PSUCommunicatorTX::GetNumberOfMemoryBuffers() { return 1u; }
+
+/*lint -e{715} [MISRA C++ Rule 0-1-11], [MISRA C++ Rule 0-1-12]. Justification:
+ * The memory buffer is independent of the bufferIdx.*/
+bool PSUCommunicatorTX::GetSignalMemoryBuffer(const uint32 signalIdx,
+ const uint32 bufferIdx,
+ void *&signalAddress) {
+ bool ok = (signalIdx < (UART_MAX_CHANNELS));
+ if (ok) {
+ // if (channelsMemory != NULL_PTR(float32 *)) {
+ signalAddress = &channelValue;
+ //}
+ }
+ return ok;
+}
+
+const char8 *PSUCommunicatorTX::GetBrokerName(StructuredDataI &data,
+ const SignalDirection direction) {
+ const char8 *brokerName = NULL_PTR(const char8 *);
+ if (direction == OutputSignals) {
+ uint32 trigger = 0u;
+ if (!data.Read("Trigger", trigger)) {
+ trigger = 0u;
+ }
+
+ if (trigger == 1u) {
+ brokerName = "MemoryMapSynchronisedOutputBroker";
+ triggerSet = true;
+ } else {
+ brokerName = "MemoryMapOutputBroker";
+ }
+ } else {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "DataSource not compatible with InputSignals");
+ }
+ return brokerName;
+}
+bool PSUCommunicatorTX::GetInputBrokers(ReferenceContainer &inputBrokers,
+ const char8 *const functionName,
+ void *const gamMemPtr) {
+ return false;
+}
+
+bool PSUCommunicatorTX::GetOutputBrokers(ReferenceContainer &outputBrokers,
+ const char8 *const functionName,
+ void *const gamMemPtr) {
+ // Check if there is a Trigger signal for this function.
+ uint32 functionIdx = 0u;
+ uint32 nOfFunctionSignals = 0u;
+ uint32 i;
+ bool triggerGAM = false;
+ bool ok = GetFunctionIndex(functionIdx, functionName);
+
+ if (ok) {
+ ok = GetFunctionNumberOfSignals(OutputSignals, functionIdx,
+ nOfFunctionSignals);
+ }
+ uint32 trigger = 0u;
+ for (i = 0u; (i < nOfFunctionSignals) && (ok) && (!triggerGAM); i++) {
+ ok = GetFunctionSignalTrigger(OutputSignals, functionIdx, i, trigger);
+ triggerGAM = (trigger == 1u);
+ }
+ if ((ok) && (triggerGAM)) {
+ ReferenceT broker(
+ "MemoryMapSynchronisedOutputBroker");
+ ok = broker.IsValid();
+
+ if (ok) {
+ ok = broker->Init(OutputSignals, *this, functionName, gamMemPtr);
+ }
+ if (ok) {
+ ok = outputBrokers.Insert(broker);
+ }
+ // Must also add the signals which are not triggering but that belong to the
+ // same GAM...
+ if (ok) {
+ if (nOfFunctionSignals > 1u) {
+ ReferenceT brokerNotSync(
+ "MemoryMapOutputBroker");
+ ok = brokerNotSync.IsValid();
+ if (ok) {
+ ok = brokerNotSync->Init(OutputSignals, *this, functionName,
+ gamMemPtr);
+ }
+ if (ok) {
+ ok = outputBrokers.Insert(brokerNotSync);
+ }
+ }
+ }
+ } else {
+ ReferenceT brokerNotSync("MemoryMapOutputBroker");
+ ok = brokerNotSync.IsValid();
+ if (ok) {
+ ok = brokerNotSync->Init(OutputSignals, *this, functionName, gamMemPtr);
+ }
+ if (ok) {
+ ok = outputBrokers.Insert(brokerNotSync);
+ }
+ }
+ return ok;
+}
+
+/*lint -e{715} [MISRA C++ Rule 0-1-11], [MISRA C++ Rule 0-1-12]. Justification:
+ * the counter and the timer are always reset irrespectively of the states being
+ * changed.*/
+bool PSUCommunicatorTX::PrepareNextState(const char8 *const currentStateName,
+ const char8 *const nextStateName) {
+ return true;
+}
+
+bool PSUCommunicatorTX::Initialise(StructuredDataI &data) {
+ bool ok = DataSourceI::Initialise(data);
+ // StreamString portName;
+ if (ok) {
+ ok = data.Read("PortName", portName);
+ if (ok) {
+ REPORT_ERROR_PARAMETERS(ErrorManagement::Information,
+ "The port name is set to %s", portName.Buffer());
+ } else {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "The port name property shall be set");
+ }
+ }
+ uint32 baudRate = 0u;
+ if (ok) {
+ ok = data.Read("BaudRate", baudRate);
+ if (ok) {
+ REPORT_ERROR_PARAMETERS(ErrorManagement::Information,
+ "The baud rate is set to %d", baudRate);
+ } else {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "The baud rate property shall be set");
+ }
+ }
+ if (ok) {
+ ok = data.Read("CurrentStep", currentStep);
+ if (ok) {
+ REPORT_ERROR_PARAMETERS(ErrorManagement::Information,
+ "The CurrentStep is set to %.2f", currentStep);
+ } else {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "The CurrentStep rate property shall be set");
+ }
+ }
+ if (ok) {
+ ok = data.Read("PointOfZeroCurrent", pointOfZeroCurrent);
+ if (ok) {
+ REPORT_ERROR_PARAMETERS(ErrorManagement::Information,
+ "The PointOfZeroCurrent is set to %.2f",
+ currentStep);
+ } else {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "The PointOfZeroCurrent rate property shall be set");
+ }
+ }
+ if (ok) {
+ if (!data.Read("Timeout", timeout)) {
+ timeout = 1000u;
+ }
+ }
+ /*
+ if (ok) {
+ ok = data.Read("SerialTimeout", serialTimeout);
+ if (ok) {
+ REPORT_ERROR(ErrorManagement::Information, "The serial timeout is set to
+ %d", serialTimeout);
+ }
+ else {
+ REPORT_ERROR(ErrorManagement::ParametersError, "The serial timeout
+ property shall be set");
+ }
+ }
+ */
+ if (ok) {
+ ok = serial.SetSpeed(baudRate);
+ }
+ if (ok) {
+ ok = serial.Open(portName.Buffer());
+ }
+ if (!ok) {
+ REPORT_ERROR_PARAMETERS(ErrorManagement::ParametersError,
+ "The port %s Not opened.", portName);
+ }
+
+ // Get individual signal parameters
+ uint32 i = 0u;
+ if (ok) {
+ ok = data.MoveRelative("Signals");
+ if (!ok) {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "Could not move to the Signals section");
+ }
+ // Do not allow to add signals in run-time
+ if (ok) {
+ ok = signalsDatabase.MoveRelative("Signals");
+ }
+ if (ok) {
+ ok = signalsDatabase.Write("Locked", 1u);
+ }
+ if (ok) {
+ ok = signalsDatabase.MoveToAncestor(1u);
+ }
+ // while ((i < ATCA_IOP_MAX_DAC_CHANNELS) && (ok)) {
+ if (data.MoveRelative(data.GetChildName(0))) {
+ // uint32 channelId;
+ float64 range;
+ ok = data.Read("OutputRange", range);
+ if (ok) {
+ // if (data.Read("OutputRange", range)) {
+ ok = (range > 0.0) && (range <= DAC_RANGE);
+ if (!ok) {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "Invalid OutputRange specified.");
+ }
+ if (ok) {
+ outputRange = range;
+ REPORT_ERROR_PARAMETERS(ErrorManagement::Information,
+ " Parameter DAC Output Range %f", range);
+ // dacEnabled[i] = true;
+ // numberOfDACsEnabled++;
+ }
+ } else {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "The OutputRange shall be specified.");
+ }
+ if (ok) {
+ ok = data.MoveToAncestor(1u);
+ }
+ }
+ }
+ if (ok) {
+ ok = data.MoveToAncestor(1u);
+ if (!ok) {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "Could not move to the parent section");
+ }
+ }
+
+ // REPORT_ERROR_PARAMETERS(ErrorManagement::Information, "numberOfDACsEnabled
+ // %d", numberOfDACsEnabled);
+ return ok;
+}
+
+bool PSUCommunicatorTX::SetConfiguredDatabase(StructuredDataI &data) {
+ uint32 i;
+ bool ok = DataSourceI::SetConfiguredDatabase(data);
+
+ if (ok) {
+ ok = triggerSet;
+ }
+ if (!ok) {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "At least one Trigger signal shall be set.");
+ }
+ if (ok) {
+ // for (i = 0u; (i < numberOfDACsEnabled) && (ok); i++) {
+ ok = (GetSignalType(0u) == Float32Bit);
+ //}
+ if (!ok) {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "All the DAC signals shall be of type Float32Bit");
+ }
+ }
+
+ uint32 nOfFunctions = GetNumberOfFunctions();
+ uint32 functionIdx;
+ // Check that the number of samples for all the signals is one
+ for (functionIdx = 0u; (functionIdx < nOfFunctions) && (ok); functionIdx++) {
+ uint32 nOfSignals = 0u;
+ ok = GetFunctionNumberOfSignals(OutputSignals, functionIdx, nOfSignals);
+
+ for (i = 0u; (i < nOfSignals) && (ok); i++) {
+ uint32 nSamples = 0u;
+ ok = GetFunctionSignalSamples(OutputSignals, functionIdx, i, nSamples);
+ if (ok) {
+ ok = (nSamples == 1u);
+ }
+ if (!ok) {
+ REPORT_ERROR(ErrorManagement::ParametersError,
+ "The number of samples shall be exactly one");
+ }
+ }
+ }
+
+ return ok;
+}
+
+// Create/Decode current packet
+bool PSUCommunicatorTX::CreateCurrentPacket(float32 current, char8 *packet) {
+
+ // Calculate the point in the scale of the current
+ int16 pointOfCurrent = (int16)(pointOfZeroCurrent + current / currentStep);
+
+ // Saturate current
+ if (pointOfCurrent < FA_SCALE_MIN)
+ pointOfCurrent = FA_SCALE_MIN;
+ if (pointOfCurrent > FA_SCALE_MAX)
+ pointOfCurrent = FA_SCALE_MAX;
+
+ // Build packets
+ uint16 pc = (uint16)pointOfCurrent;
+ uint16 nc = ~pc;
+ packet[0] = (char8)(0x0000 | ((nc & 0x03C0) >> 5) | ((pc & 0x0007) << 5));
+ packet[1] = (char8)(0x0001 | ((pc & 0x03F8) >> 2));
+
+ return true;
+}
+
+bool PSUCommunicatorTX::Synchronise() {
+ uint32 i;
+ int32 w = 24;
+ bool ok = true;
+ char8 text[] = "ola";
+ // if (channelsMemory != NULL_PTR(float32 *)) {
+
+ // value = channelsMemory[0] / DAC_RANGE;
+ // for (i = 0u; (i < numberOfDACsEnabled ) && (ok); i++) {
+ int32 ser_value = channelValue / outputRange * 1000000.0;
+ REPORT_ERROR_PARAMETERS(ErrorManagement::Information,
+ "Synchronise called. value: %f, %d", channelValue,
+ ser_value);
+ // w = SetDacReg(i, value);
+ char8 *data = reinterpret_cast(&ser_value);
+ serial.Write(data, sizeof(int32));
+ // serial.Write(text, 4);
+ // write(boardFileDescriptor, &w, 4);
+ // value = channelsMemory[1] / DAC_RANGE;
+ // value = channelsMemory[1] / DAC_RANGE * pow(2,17);
+ // w = SetDacReg(1, value);
+ // w = 0x000FFFFF & static_cast(value);
+ // write(boardFileDescriptor, &w, 4);
+ // REPORT_ERROR(ErrorManagement::Information, " Writing DAC 0 0x%x", w);
+ /*
+
+ w = dacValues[i];
+ }
+ */
+ return ok;
+}
+CLASS_REGISTER(PSUCommunicatorTX, "1.0")
+} // namespace MARTe
+ // vim: syntax=cpp ts=2 sw=2 sts=2 sr et
diff --git a/DataSources/PSUCommunicator/PSUCommunicatorTX.h b/DataSources/PSUCommunicator/PSUCommunicatorTX.h
new file mode 100644
index 0000000..d57bb74
--- /dev/null
+++ b/DataSources/PSUCommunicator/PSUCommunicatorTX.h
@@ -0,0 +1,273 @@
+/**
+ * @file PSUCommunicatorTX.h
+ * @brief Header file for class PSUCommunicatorTX
+ * @date 19/01/2024
+ * @author Andre Neto / Bernardo Carvalho
+ *
+ * Based on Example:
+ * https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2-demos-padova/-/tree/master/DataSources/ADCSimulator
+ *
+ *
+ * @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.
+
+ * @details This header file contains the declaration of the class
+ PSUCommunicatorTX
+ * with all of its public, protected and private members. It may also include
+ * definitions for inline methods which need to be visible to the compiler.
+ */
+
+#ifndef PSUCOMMUNICATOR_TX_H
+#define PSUCOMMUNICATOR_TX_H
+
+/*---------------------------------------------------------------------------*/
+/* Standard header includes */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Project header includes */
+/*---------------------------------------------------------------------------*/
+#include "DataSourceI.h"
+#include "EmbeddedServiceMethodBinderI.h"
+#include "EventSem.h"
+#include "MessageI.h"
+#include "RegisteredMethodsMessageFilter.h"
+#include "SingleThreadService.h"
+
+#include "UARTConfig.h"
+/*---------------------------------------------------------------------------*/
+/* Class declaration */
+/*---------------------------------------------------------------------------*/
+namespace MARTe {
+
+/**
+ * The number of signals
+ */
+
+const uint32 UART_MAX_CHANNELS = 1u;
+
+/**
+ * @brief A DataSource which provides an analogue output interface to the ATCA
+ IOP boards.
+ * @details The configuration syntax is (names are only given as an example):
+ *
+ *
+ * +AtcaIop_UartOut = {
+ * Class = PSUCommunicator::PSUCommunicatorTX
+ * PortName = "/dev/ttyUSB0" //Name of the UART port, Mandatory
+ * BaudRate = 115200 //BAUD UART rate
+ * //Timeout = 200000 //Maximum time to wait for data
+ * CPUMask = 8 //Affinity of the CPU of where to read data from
+ * CurrentStep =
+ * PointOfZeroCurrent =
+ * Signals = {
+ * SerialOut = {
+ * Type = float32//Mandatory. Only type that is supported.
+ * OutputRange = 10.0 //Mandatory. The channel Module Output Range
+ in volt.
+ * //OutputPolarity = Bipolar //Optional. Possible values: Bipolar,
+ Unipolar. Default value Unipolar.
+ * }
+ * Packet = { //Actual data to write
+ * Type = uint8
+ * NumberOfElements = 15
+ * }
+
+ * }
+ * }
+ *
+ * Note that at least one of the GAMs writing to this DataSource must have set
+ one of the signals with Trigger=1 (which forces the writing of all the signals
+ to the DAC).
+ */
+class PSUCommunicatorTX : public DataSourceI, public MessageI {
+public:
+ CLASS_REGISTER_DECLARATION()
+ /**
+ * @brief Default constructor
+ * @post
+ * Counter = 0
+ * Time = 0
+ */
+ PSUCommunicatorTX();
+
+ /**
+ * @brief Destructor. Stops the EmbeddedThread.
+ */
+ virtual ~PSUCommunicatorTX();
+
+ /**
+ * @brief See DataSourceI::AllocateMemory.
+ * * @return true.
+ */
+ virtual bool AllocateMemory();
+
+ /**
+ gg* @brief See DataSourceI::GetNumberOfMemoryBuffers.
+ * @return 1.
+ */
+ virtual uint32 GetNumberOfMemoryBuffers();
+
+ /**
+ * @brief See DataSourceI::GetSignalMemoryBuffer.
+ */
+ virtual bool GetSignalMemoryBuffer(const uint32 signalIdx,
+ const uint32 bufferIdx,
+ void *&signalAddress);
+
+ /**
+ * @brief See DataSourceI::GetNumberOfMemoryBuffers.
+ * @details Only OutputSignals are supported.
+ * @return MemoryMapSynchronisedOutputBroker if Trigger == 1 for any of the
+ * signals, MemoryMapOutputBroker otherwise.
+ */
+ virtual const char8 *GetBrokerName(StructuredDataI &data,
+ const SignalDirection direction);
+
+ /**
+ * @brief See DataSourceI::GetInputBrokers.
+ * @return false.
+ */
+ virtual bool GetInputBrokers(ReferenceContainer &inputBrokers,
+ const char8 *const functionName,
+ void *const gamMemPtr);
+
+ /**
+ * @brief See DataSourceI::GetOutputBrokers.
+ * @details If the functionName is one of the functions which requested a
+ * Trigger, it adds a MemoryMapSynchronisedOutputBroker instance to the
+ * outputBrokers, otherwise it adds a MemoryMapOutputBroker instance to the
+ * outputBrokers.
+ * @param[out] outputBrokers where the BrokerI instances have to be added to.
+ * @param[in] functionName name of the function being queried.
+ * @param[in] gamMemPtr the GAM memory where the signals will be read from.
+ * @return true if the outputBrokers can be successfully configured.
+ */
+ virtual bool GetOutputBrokers(ReferenceContainer &outputBrokers,
+ const char8 *const functionName,
+ void *const gamMemPtr);
+
+ /**
+ * @brief See StatefulI::PrepareNextState.
+ * @details NOOP.
+ * @return true.
+ */
+ virtual bool PrepareNextState(const char8 *const currentStateName,
+ const char8 *const nextStateName);
+
+ /**
+ * @brief Loads and verifies the configuration parameters detailed in the
+ * class description.
+ * @return true if all the mandatory parameters are correctly specified and if
+ * the specified optional parameters have valid values.
+ */
+
+ virtual bool Initialise(StructuredDataI &data);
+
+ /**
+ * @brief Final verification of all the parameters and setup of the board
+ * configuration.
+ * @details This method verifies that all the parameters (e.g. number of
+ * samples) requested by the GAMs interacting with this DataSource are valid
+ * and consistent with the board parameters set during the initialisation
+ * phase. In particular the following conditions shall be met:
+ * - At least one triggering signal was requested by a GAM (with the property
+ * Trigger = 1)
+ * - All the DAC channels have type float32.
+ * - The number of samples of all the DAC channels is exactly one.
+ * @return true if all the parameters are valid and consistent with the board
+ * parameters and if the board can be successfully configured with these
+ * parameters.
+ */
+ virtual bool SetConfiguredDatabase(StructuredDataI &data);
+
+ /**
+ * @details Writes the value of all the DAC channels to the board.
+ * @return true if the writing of all the channels is successful.
+ */
+ virtual bool Synchronise();
+
+private:
+ /**
+ * The board device name
+ */
+ StreamString portName;
+ /**
+ * The board identifier
+ */
+ uint32 boardId;
+ /**
+ * The board file descriptor
+ */
+ // int32 boardFileDescriptor;
+ /**
+ * The UART interface.
+ */
+ UARTConfig serial;
+
+ /**
+ * Timeout to wait for data to be available.
+ */
+ // uint32 serialTimeout;
+
+ /**
+ */
+ uint32 timeout;
+
+ /**
+ * DAC values
+ */
+ // int32 dacValues[ATCA_IOP_N_DACs];
+
+ /**
+ * The signal memory
+ */
+ float32 channelValue;
+ float32 currentStep;
+ float32 pointOfZeroCurrent;
+ /**
+ * The DACs that are enabled
+ */
+ // bool dacEnabled[ATCA_IOP_MAX_DAC_CHANNELS];
+
+ /**
+ * The board individual channel output ranges
+ */
+ float32 outputRange;
+
+ /**
+ * The number of enabled DACs
+ */
+ uint32 numberOfDACsEnabled;
+
+ /**
+ * Filter to receive the RPC which allows to change the...
+ */
+ ReferenceT filter;
+
+ /**
+ * True if at least one trigger was set.
+ */
+ bool triggerSet;
+
+ // int32 SetDacReg(uint32 channel, float32 val) const;
+ bool CreateCurrentPacket(float32 current, char8 *packet);
+};
+} // namespace MARTe
+
+/*---------------------------------------------------------------------------*/
+/* Inline method definitions */
+/*---------------------------------------------------------------------------*/
+
+#endif /* PSUCOMMUNICATOR_TX_H */
+
+// vim: syntax=cpp ts=2 sw=2 sts=2 sr et
diff --git a/DataSources/PSUCommunicator/PSUMessages.h b/DataSources/PSUCommunicator/PSUMessages.h
new file mode 100644
index 0000000..45814db
--- /dev/null
+++ b/DataSources/PSUCommunicator/PSUMessages.h
@@ -0,0 +1,74 @@
+/**
+ * @file PSUMessages.h
+ * @brief Header file
+ * @date 25/10/2025
+ * @author Bernardo Carvalho
+ *
+ *
+ * @copyright Copyright 2025 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.
+
+ * @details This header file contains the declaration of the class AtcaIopADC
+ * with all of its public, protected and private members. It may also include
+ * definitions for inline methods which need to be visible to the compiler.
+ */
+#define FA_CHARGE_MESSAGE_1 0x6C
+#define FA_CHARGE_MESSAGE_2 0x6D
+#define FA_SHUTDOWN_MESSAGE_1 0x92
+#define FA_SHUTDOWN_MESSAGE_2 0x93
+#define FA_STARTOP_MESSAGE_1 0xFE
+#define FA_STARTOP_MESSAGE_2 0xFF
+#define FA_STOPOP_MESSAGE_1 0x00
+#define FA_STOPOP_MESSAGE_2 0x01
+
+#define FA_STARTED_MESSAGE_1 0xFE
+#define FA_STARTED_MESSAGE_2 0xFF
+#define FA_STOPPED_MESSAGE_1 0x00
+#define FA_STOPPED_MESSAGE_2 0x01
+#define FA_STOP_ERROR_MESSAGE_1 0x24
+#define FA_STOP_ERROR_MESSAGE_2 0x25
+#define FA_COMM_ERROR_MESSAGE_1 0xDA
+#define FA_COMM_ERROR_MESSAGE_2 0xDB
+
+#define FA_COMMUNICATION_MAX_PACKETS 4
+#define FA_FRAMING_BIT_MASK 0x01
+
+#define FA_SCALE_MIN 0
+#define FA_SCALE_MAX 1023
+
+#define LOG_CHARGE 1
+#define LOG_SHUTDOWN 2
+#define LOG_STARTOP 3
+#define LOG_STOPOP 4
+#define LOG_TEMPERATURE_FAULT 5
+#define LOG_24V_FAULT 6
+#define LOG_CHARGED 7
+#define LOG_NOT_CHARGED 8
+#define LOG_STARTED 9
+#define LOG_STOPPED 10
+#define LOG_STOP_FAULT 11
+#define LOG_COMMUNICATION_FAULT 12
+#define LOG_CURRENT_VALUE 13
+
+// Logging #defines
+// #define __FA_COM_LOG_RECEIVED_MESSAGES
+// #define ___FA_COM_LOG_SENT_MESSAGES
+#define __FA_COM_LOG_LEVEL InitialisationError
+
+// Communicator Online Stages
+#define FA_COMMUNICATOR_ONLINE_IDLE 0
+#define FA_COMMUNICATOR_ONLINE_WAIT_CODAC_TRIGGER 1
+#define FA_COMMUNICATOR_ONLINE_DISCHARGE 2
+#define FA_COMMUNICATOR_ONLINE_STOP_OPERATION 3
+#define FA_COMMUNICATOR_ONLINE_ERROR 4
+
+#define FA_COMMUNICATOR_MAXIMUM_ATTEMPTS 5
diff --git a/DataSources/PSUCommunicator/UARTConfig.cpp b/DataSources/PSUCommunicator/UARTConfig.cpp
new file mode 100644
index 0000000..ef3f7d6
--- /dev/null
+++ b/DataSources/PSUCommunicator/UARTConfig.cpp
@@ -0,0 +1,375 @@
+/**
+ * @file UARTConfig.cpp
+ * @brief Source file for class UARTConfig.
+ * @date 07/08/2018
+ * @author Andre Neto
+ * @author Pedro Lourenco
+ *
+ * @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.
+ *
+ * @details This source file contains the definition of all the methods for
+ * the class UARTConfig (public, protected, and private). Be aware that some
+ * methods, such as those inline could be defined on the header file, instead.
+ */
+
+/*---------------------------------------------------------------------------*/
+/* Standard header includes */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Project header includes */
+/*---------------------------------------------------------------------------*/
+#include "UARTConfig.h"
+
+/*---------------------------------------------------------------------------*/
+/* Static definitions */
+/*---------------------------------------------------------------------------*/
+/*lint -e628 []. Justification: Argument 'errno' of 'strerror()' provided
+ via .*/
+/*lint -e10 []. Justification: '}' present.*/
+
+/*lint -e{9141} [MISRA C++ Rule 7-3-1]. Justification: 'SpeedTable' declared "
+ "as global.*/
+struct SpeedTable {
+ MARTe::int32 code;
+ MARTe::uint32 speed;
+};
+
+/*lint -e{9141} [MISRA C++ Rule 7-3-1]. Justification: 'speedTable' declared "
+ "as global.*/
+const SpeedTable speedTable[] = {{B0, 0u},
+ {B50, 50u},
+ {B75, 75u},
+ {B110, 110u},
+ {B134, 134u},
+ {B150, 150u},
+ {B200, 200u},
+ {B300, 300u},
+ {B600, 600u},
+ {B1200, 1200u},
+ {B1800, 1800u},
+ {B2400, 2400u},
+ {B4800, 4800u},
+ {B9600, 9600u},
+ {B19200, 19200u},
+ {B38400, 38400u},
+ {B57600, 57600u},
+ {B115200, 115200u},
+ {B230400, 230400u},
+ {B460800, 460800u},
+ {B500000, 500000u},
+ {B576000, 576000u},
+ {B921600, 921600u},
+ {B1000000, 1000000u},
+ {B1152000, 1152000u},
+ {B1500000, 1500000u},
+ {B2000000, 2000000u},
+ {B2500000, 2500000u},
+ {B3000000, 3000000u},
+ {B3500000, 3500000u},
+ {B4000000, 4000000u}};
+
+/*---------------------------------------------------------------------------*/
+/* Method definitions */
+/*---------------------------------------------------------------------------*/
+namespace MARTe {
+
+/*lint -e{1401} [MISRA C++ Rule 8-5-1]. Justification: FD_ZERO arguments
+ correctly initialised.*/
+UARTConfig::UARTConfig() {
+
+ properties.fileDescriptor = -1;
+ properties.speedCode = B19200;
+ FD_ZERO(&properties.readFDS);
+ FD_ZERO(&properties.readFDS_done);
+ FD_ZERO(&properties.writeFDS);
+ FD_ZERO(&properties.writeFDS_done);
+}
+
+UARTConfig::~UARTConfig() {
+ /*lint -e{1551} []. Justification: thrown exception non critical.*/
+ Close();
+}
+
+bool UARTConfig::SetSpeed(const uint32 speed) {
+
+ bool ok = (properties.fileDescriptor == -1);
+ if (ok) {
+ int32 ix = 0;
+ while ((speedTable[ix].code != __MAX_BAUD) &&
+ (speed > speedTable[ix].speed)) {
+ ix++;
+ }
+ properties.speedCode = speedTable[ix].code;
+ ok = (speed == speedTable[ix].speed);
+ }
+
+ return ok;
+}
+/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'name'
+ kept as non const.*/
+bool UARTConfig::Open(const char8 *name) {
+
+ // Info from termios.h:
+ // c_iflag - input modes;
+ // c_oflag - output modes;
+ // c_cflag - control modes;
+ // c_lflag - local modes;
+ // c_cc[NCCS] - special characters.
+
+ bool ok = (properties.fileDescriptor == -1);
+ if (ok) {
+ ok = (name != NULL);
+ }
+ if (ok) {
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operation over signed type.*/
+ properties.fileDescriptor = open(name, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (properties.fileDescriptor == -1) {
+ REPORT_ERROR_STATIC(ErrorManagement::OSError,
+ "UARTConfig::Open - "
+ "cannot open serial device %s.",
+ name);
+ ok = false;
+ }
+ FD_SET(properties.fileDescriptor, &properties.readFDS);
+ FD_SET(properties.fileDescriptor, &properties.writeFDS);
+ }
+ if (ok) {
+ struct termios newtio;
+ // Clean all settings
+ cfmakeraw(&newtio);
+ // Eight Data bits
+ // CSIZE - Character size mask. Values are CS5, CS6, CS7, or CS8.
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operations over signed types.*/
+ /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness
+ change due to implicit conversion.*/
+ /*lint -e{737} []. Justification: Known loss of signedness.*/
+ newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | properties.speedCode;
+ // CLOCAL - Ignore modem control lines.
+ // CREAD - Enable receiver.
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operations over signed types.*/
+ /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness
+ change due to implicit conversion.*/
+ newtio.c_cflag |= (CLOCAL | CREAD);
+ // Parity Odd:
+ // PARENB - Enable parity generation on output and parity checking for
+ // input.
+ // PARODD - If set, then parity for input and output is odd; otherwise
+ // even parity is used.
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operations over signed types.*/
+ /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness
+ change due to implicit conversion.*/
+ newtio.c_cflag |= (PARENB | PARODD);
+ // No hardware handshake:
+ // CRTSCTS - Enable RTS/CTS (hardware) flow control.
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operations over signed types.*/
+ /*lint -e{9105} [MISRA C++ Rule 2-13-3]. Justification: Known U suffix
+ missing.*/
+ newtio.c_cflag &= ~CRTSCTS;
+ // Two stopbit:
+ // CSTOPB - Set two stop bits, rather than one.
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operations over signed types.*/
+ /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness
+ change due to implicit conversion.*/
+ newtio.c_cflag |= CSTOPB;
+ // IGNBRK - Ignore BREAK condition on input.
+ // newtio.c_iflag = IGNBRK;
+ // Software handshake:
+ // IXON - Enable XON/XOFF flow control on output.
+ // IXANY - Typing any character will restart stopped output.
+ // IXOFF - Enable XON/XOFF flow control on input.
+ // newtio.c_iflag |= (IXON | IXOFF | IXANY);
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operations over signed types.*/
+ /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness
+ change due to implicit conversion.*/
+ newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
+ // Non cannonical mode
+ // ICANON - Enable canonical mode.
+ // ECHO - Echo input characters.
+ // ECHOE - If ICANON is also set, the ERASE character erases the
+ // preceding input character, and WERASE erases the preceding word.
+ // ISIG - When any of the characters INTR, QUIT, SUSP, or DSUSP are
+ // received, generate the corresponding signal.
+ /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise
+ operations over signed types.*/
+ /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness
+ change due to implicit conversion.*/
+ newtio.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ newtio.c_lflag = 0u;
+ newtio.c_oflag = 0u;
+ // VMIN - Minimum number of characters for noncanonical read (MIN).
+ newtio.c_cc[VMIN] = 1u;
+ // VTIME - Timeout in deciseconds for noncanonical read (TIME).
+ newtio.c_cc[VTIME] = 5u;
+
+ ok = (cfsetspeed(&newtio, static_cast(properties.speedCode)) == 0);
+ ErrorManagement::ErrorType errorCode =
+ ok ? ErrorManagement::Information : ErrorManagement::OSError;
+ REPORT_ERROR_STATIC(errorCode,
+ "UARTConfig::Open - %s serial device %s "
+ "speed to %u.",
+ ok ? "successfully set" : "could not set", name,
+ properties.speedCode);
+
+ if (ok) {
+ ok = (tcsetattr(properties.fileDescriptor, TCSANOW, &newtio) != -1);
+ errorCode = ok ? ErrorManagement::Information : ErrorManagement::OSError;
+ REPORT_ERROR_STATIC(errorCode,
+ "UARTConfig::Open - %s serial device "
+ "parameters.",
+ ok ? "successfully set" : "could not set");
+ }
+ }
+
+ return ok;
+}
+
+void UARTConfig::Close() {
+
+ if (properties.fileDescriptor != -1) {
+ int32 err = close(properties.fileDescriptor);
+ bool ok = (err == 0);
+ ErrorManagement::ErrorType errorCode =
+ ok ? ErrorManagement::Information : ErrorManagement::OSError;
+ REPORT_ERROR_STATIC(errorCode,
+ "UARTConfig::Close - %s serial "
+ "interface.",
+ ok ? "closed" : "failed to close");
+ properties.fileDescriptor = -1;
+ }
+}
+
+/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'buffer' kept
+ as non const.*/
+/*lint -e{1762} [MISRA C++ Rule 9-3-3]. Justification: Member function :Read()
+ kept as non const.*/
+bool UARTConfig::Read(char8 *buffer, uint32 &size) {
+
+ size_t readSize = static_cast(size);
+ ssize_t readBytes = read(properties.fileDescriptor, buffer, readSize);
+ size = static_cast(readBytes);
+ bool ok = (readBytes == static_cast(size));
+
+ // ErrorManagement::ErrorType errorCode = ok ?
+ // ErrorManagement::Information :
+ // ErrorManagement::OSError;
+ // REPORT_ERROR_STATIC(errorCode, "UARTConfig::Read - read %d bytes, "
+ // "requested %u.", static_cast(readBytes),
+ // static_cast(readSize));
+
+ return ok;
+}
+
+/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'buffer' kept
+ as non const.*/
+bool UARTConfig::Read(char8 *buffer, uint32 &size, const uint32 timeoutUsec) {
+
+ bool ok = true;
+ size_t leftToRead = static_cast(size);
+ void *rbuffer = &buffer[0u];
+ while ((leftToRead > 0u) && (ok)) {
+ ok = WaitRead(timeoutUsec);
+ if (ok) {
+ ssize_t readBytes = read(properties.fileDescriptor, rbuffer, leftToRead);
+ ok = (readBytes > 0);
+ if (ok) {
+ leftToRead -= static_cast(readBytes);
+ uint32 idx = size - static_cast(leftToRead);
+ rbuffer = &buffer[idx];
+ }
+ ErrorManagement::ErrorType errorCode =
+ ok ? ErrorManagement::Information : ErrorManagement::OSError;
+ StreamString errorMessage;
+ /*lint -e{1055} [MISRA C++ Rule 14-8-2]. Justification: Symbol
+ 'strerror' declared.*/
+ /*lint -e{746} []. Justification: Prototype not present in
+ MARTe::strerror().*/
+ (void)errorMessage.Printf(" with error %s.", strerror(errno));
+ // Error only verbosity, comment condition if needed.
+ if (!ok) {
+ /*lint -e{578} [MISRA C++ Rule 2-10-2]. Justification: Symbol
+ 'Buffer' has an identical name as a global
+ symbol 'buffer'.*/
+ REPORT_ERROR_STATIC(errorCode,
+ "UARTConfig::Read - %s read %d "
+ "bytes%s",
+ ok ? "" : "failed to",
+ static_cast(readBytes),
+ ok ? "." : errorMessage.Buffer());
+ }
+ }
+ }
+ size = (size - static_cast(leftToRead));
+
+ return ok;
+}
+
+/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'size' kept as
+ non const.*/
+/*lint -e{1762} [MISRA C++ Rule 9-3-3]. Justification: Member function :Read()
+ kept as non const.*/
+/*lint -e{818} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'size' kept as
+ non const.*/
+bool UARTConfig::Write(char8 *buffer, uint32 size) {
+
+ size_t writeSize = static_cast(size);
+ ssize_t writtenBytes = write(properties.fileDescriptor, buffer, writeSize);
+ bool ok = (writtenBytes == static_cast(writeSize));
+
+ // ErrorManagement::ErrorType errorCode = ok ?
+ // ErrorManagement::Information :
+ // ErrorManagement::OSError;
+ // REPORT_ERROR_STATIC(errorCode, "UARTConfig::Write - wrote %d bytes, "
+ // "requested %u.", static_cast(writtenBytes), size);
+
+ return ok;
+}
+
+bool UARTConfig::WaitRead(const uint32 timeoutUsec) {
+
+ struct timeval timeWait;
+ uint32 tmp = timeoutUsec / 1000000u;
+ timeWait.tv_sec = static_cast(tmp);
+ tmp = timeoutUsec % 1000000u;
+ timeWait.tv_usec = static_cast(tmp);
+ properties.readFDS_done = properties.readFDS;
+ int32 readyCount =
+ select(properties.fileDescriptor + 1, &properties.readFDS_done,
+ NULL_PTR(fd_set *), NULL_PTR(fd_set *), &timeWait);
+
+ return (readyCount > 0);
+}
+
+bool UARTConfig::WaitWrite(const uint32 timeoutUsec) {
+
+ struct timeval timeWait;
+ uint32 tmp = timeoutUsec / 1000000u;
+ timeWait.tv_sec = static_cast(tmp);
+ tmp = timeoutUsec % 1000000u;
+ timeWait.tv_usec = static_cast(tmp);
+ properties.writeFDS_done = properties.writeFDS;
+ int32 readyCount =
+ select(properties.fileDescriptor + 1, NULL_PTR(fd_set *),
+ &properties.writeFDS_done, NULL_PTR(fd_set *), &timeWait);
+
+ return (readyCount > 0);
+}
+
+} // namespace MARTe
diff --git a/DataSources/PSUCommunicator/UARTConfig.h b/DataSources/PSUCommunicator/UARTConfig.h
new file mode 100644
index 0000000..81446fd
--- /dev/null
+++ b/DataSources/PSUCommunicator/UARTConfig.h
@@ -0,0 +1,164 @@
+/**
+ * @file UARTConfig.h
+ * @brief Header file for class UARTConfig.
+ * @date 16/08/2021
+ * @author Filippo Sartori
+ * @author Pedro Lourenco
+ *
+ * @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.
+ *
+ * @details This header file contains the declaration of the class UARTConfig
+ * with all of its public, protected and private members. It may also include
+ * definitions for inline methods which need to be visible to the compiler.
+ */
+
+#ifndef UARTCONFIG_H_
+#define UARTCONFIG_H_
+
+/*---------------------------------------------------------------------------*/
+/* Standard header includes */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Project header includes */
+/*---------------------------------------------------------------------------*/
+#include "AdvancedErrorManagement.h"
+#include "CompilerTypes.h"
+#include "GeneralDefinitions.h"
+#include "StreamString.h"
+#include INCLUDE_FILE_ENVIRONMENT(FileSystem, L1Portability, ENVIRONMENT, BasicUARTProperties.h)
+
+/*---------------------------------------------------------------------------*/
+/* Class declaration */
+/*---------------------------------------------------------------------------*/
+
+namespace MARTe {
+
+/**
+ * @brief UART implementation based on the Linux general terminal interface
+ * that is provided to control asynchronous communications ports.
+ * @details Some of termio parameters are hard-coded as follows:
+ * - eight data bits;
+ * - no parity bit;
+ * - one stop bit;
+ * - noncanonical input processing mode.
+ */
+class DLL_API UARTConfig {
+public:
+ /**
+ * @brief Default constructor.
+ * @details FD_ZERO the file descriptors.
+ */
+ UARTConfig();
+
+ /**
+ * @brief Destructor.
+ * @details Calls Close().
+ */
+ virtual ~UARTConfig();
+
+ /**
+ * @brief Sets the speed of the UART. Shall be called before the Open
+ * method.
+ * @param[in] serial the speed to set.
+ * @return true if the speed was successfully updated.
+ */
+ bool SetSpeed(const uint32 speed);
+
+ /**
+ * @brief Opens the UART described by the provided \a name.
+ * @details The UART is open in read/write mode. Many of the UART
+ * properties are hard-coded for the CRIO use-case.
+ * @param[in] name the UART file descriptor location.
+ * @pre
+ * SetSpeed
+ */
+ bool Open(const char8 *name);
+
+ /**
+ * @brief Closes the UART.
+ * @pre
+ * Open
+ */
+ void Close();
+
+ /**
+ * @brief Reads \a size bytes into the \a buffer.
+ * @param[in] buffer the memory where to write the read bytes.
+ * @param[in,out] size the number of bytes to read and the number of bytes
+ * that were actually read.
+ * @return true if the Read operation completes successfully (and reads all
+ * the requested bytes).
+ * @pre
+ * Open
+ */
+ bool Read(char8 *buffer, uint32 &size);
+
+ /**
+ * @brief Reads \a size bytes into the \a buffer within \a timeoutUsec
+ * micro-seconds.
+ * @param[in] buffer the memory where to write the read bytes.
+ * @param[in,out] size the number of bytes to read and the number of bytes
+ * that were actually read.
+ * @param[in] timeoutUsec the maximum time to complete the read operation.
+ * @return true if the Read operation completes successfully within the
+ * timeout (and reads all the requested bytes).
+ * @pre
+ * Open
+ */
+ bool Read(char8 *buffer, uint32 &size, const uint32 timeoutUsec);
+
+ /**
+ * @brief Waits \a timeoutUsec micro-seconds for data to be available for
+ * reading in the UART.
+ * @param[in] timeoutUsec the maximum time to wait for data to be
+ * available.
+ * @return true if data is available to be read within the timeout.
+ */
+ bool WaitRead(const uint32 timeoutUsec);
+
+ /**
+ * @brief Writes \a size bytes from the \a buffer.
+ * @param[in] buffer the memory where to read the bytes to write.
+ * @param[in] size the number of bytes to write.
+ * @param[in] timeoutUsec the maximum time to complete the read operation.
+ * @return true if the Read operation completes successfully within the
+ * timeout (and reads all the requested bytes).
+ * @pre
+ * Open
+ */
+ bool Write(char8 *buffer, uint32 size);
+
+ /**
+ * @brief Waits \a timeoutUsec micro-seconds for the UART to be available
+ * for writing data.
+ * @param[in] timeoutUsec the maximum time to wait for the write to be
+ * available.
+ * @return true if the UART is available to write within the timeout.
+ */
+ bool WaitWrite(const uint32 timeoutUsec);
+
+private:
+ /**
+ * Structure with variables/parameters for different Environments.
+ */
+ BasicUARTProperties properties;
+};
+
+} // namespace MARTe
+
+/*---------------------------------------------------------------------------*/
+/* Inline method definitions */
+/*---------------------------------------------------------------------------*/
+
+#endif /* UARTCONFIG_H_ */