1. Introduction and objectives
8.2 W INDOWS E THER CAT S LAVE (C/C++ SOURCE C ODE )
119
23) POUs: MASTER_MAIN (PRG)
1 // This is the main program executed in task with cycle time of one millisecond.
2 // It generates all the ramps and the rectangular boolean signals, 3 // the signals are periodic with the periodo equal to one second 4
5 PROGRAM MASTER_MAIN 6 VAR
7 iTimeTick : INT := 0;
8 END_VAR 9
10 IF iTimeTick = GVL_MASTER.MAX_TICK_COUNT THEN 11 // reset the time tick when the max is reached 12 iTimeTick := 0;
13 END_IF 14
15 IF (iTimeTick MOD ((GVL_MASTER.MAX_TICK_COUNT + 1) / 2) = 0) THEN 16 GVL_MASTER.bSawtoothBoolOut := NOT(GVL_MASTER.bSawtoothBoolOut);
17 END_IF 18
19 // Generate the periodic signals 20
21 // Real sawtooths
22 GVL_MASTER.fSawtoothRealOut := fcGenerateRealSawtoothSignal(1.0, iTimeTick);
23 fcGenerateRealSawtoohSignals(GVL_MASTER.fSawToothRealOutArray, iTimeTick);
24
25 // signed integer sawtooths
26 GVL_MASTER.iSawtooth8BitsIntOut := fcGenerate8BitsIntSawtoothSignal(1, iTimeTick);
27 fcGenerate8BitsIntSawtoothSignals(GVL_MASTER.iSawtooth8BitIntOutArray, iTimeTick);
28
29 GVL_MASTER.iSawtooth16BitsIntOut := fcGenerate16BitsIntSawtoothSignal(1, iTimeTick);
30 fcGenerate16BitsIntSawtoothSignals(GVL_MASTER.iSawtooth16BitIntOutArray, iTimeTick);
31
32 GVL_MASTER.iSawtooth32BitsIntOut := fcGenerate32BitsIntSawtoothSignal(1, iTimeTick);
33 fcGenerate32BitsIntSawtoothSignals(GVL_MASTER.iSawtooth32BitIntOutArray, iTimeTick);
34
35 // unsigned integer sawtooths
36 GVL_MASTER.uiSawtooth8BitsIntOut := fcGenerate8BitsUIntSawtoothSignal(1, iTimeTick);
37 fcGenerate8BitsUIntSawtoothSignals(GVL_MASTER.uiSawtooth8BitUIntOutArray, iTimeTick);
38
39 GVL_MASTER.uiSawtooth16BitsIntOut := fcGenerate16BitsUIntSawtoothSignal(1, iTimeTick);
40 fcGenerate16BitsUIntSawtoothSignals(GVL_MASTER.uiSawtooth16BitUIntOutArray, iTimeTick);
41
42 GVL_MASTER.uiSawtooth32BitsIntOut := fcGenerate32BitsUIntSawtoothSignal(1, iTimeTick);
43 fcGenerate32BitsUIntSawtoothSignals(GVL_MASTER.uiSawtooth32BitUIntOutArray, iTimeTick);
44
45 // update the time tick 46 iTimeTick := iTimeTick + 1;
120
32 APPL_AbccHandlerStatusType;
33 34
35 // EXPORTED INTERFACE 36
37 // Initialize the hardware
38 // Returns 0 in case of success, > 0 in case of failure 39 ABCC_ErrorCodeType InitHardware(char* pszHardwareSerial);
40
41 void RegisterNotifyer(APPL_Notify notifier);
42 43
44 // Set the slave configuration
45 // Return 0 in case of success, > 0 in case of failure 46 int InitConfiguration(const AD_AdiEntryType* psAdiEntry,
47 const AD_DefaultMapType* psDefaultMap, UINT16 iNumAdi);
48
49 // Execute the slave loop operations 50 void ManageSlave();
51
52 // Shoutdown the driver 53 void ShutdownDriver();
54
55 // Release the hardware
56 ABCC_ErrorCodeType ReleaseHardware();
57 58
59 #endif // IDLINTERFACE_H_
2) IDL_interface.c
1 // This file contains the implementation of the IDL interface 2
3 #include "IDL_interface.h"
4
5 #include "abcc.h"
6 #include "appl_adimap_config.h"
7 #include "appl_state.h"
8
9 #define LOOP_RUN 0 10 #define LOOP_QUIT 1 11 #define LOOP_RESET 2 12
13 static UINT8 RunUi();
14
15 APPL_Notify notifierFunc = NULL;
16
17 ABCC_ErrorCodeType InitHardware(char* pszHardwareSerial) 18 {
19 return ABCC_HwInit(FALSE, pszHardwareSerial);
20 } 21
22 void RegisterNotifyer(APPL_Notify notifier) 23 {
24 notifierFunc = notifier;
25 } 26
27 int InitConfiguration(const AD_AdiEntryType* psAdiEntry,
28 const AD_DefaultMapType* psDefaultMap, UINT16 iNumAdi)
29 {
30 return ConfigureApplicationData(psAdiEntry, psDefaultMap, iNumAdi);
31 } 32
33 void ManageSlave() 34 {
35 UINT8 bLoopState = LOOP_RUN;
36 APPL_AbccHandlerStatusType eAbccHandlerStatus = APPL_MODULE_NO_ERROR;
37 const UINT16 iSleepTimeMS = 1;
38 while (LOOP_QUIT != bLoopState) 39 {
40 bLoopState = LOOP_RUN;
41
42 eAbccHandlerStatus = APPL_HandleAbcc();
43
44 switch (eAbccHandlerStatus) 45 {
46 case APPL_MODULE_NO_ERROR:
47 break;
48 case APPL_MODULE_RESET:
49 APPL_RestartAbcc();
50 break;
51 default:
52 bLoopState = LOOP_QUIT;
53 break;
54 } 55
121
56 if (bLoopState == LOOP_RUN) 57 {
58 bLoopState = RunUi();
59 } 60
61 switch (bLoopState) 62 {
63 case LOOP_RESET:
64 APPL_RestartAbcc();
65 bLoopState = LOOP_RUN;
66 break;
67 case LOOP_RUN:
68 if (notifierFunc && GetAppState() == APPL_RUN) notifierFunc();
69 case LOOP_QUIT:
70 default:
71 break;
72 } 73
74 if (bLoopState == LOOP_RUN) 75 {
76 Sleep(iSleepTimeMS);
77 ABCC_RunTimerSystem(iSleepTimeMS);
78 } 79 } 80
81 return;
82 } 83 84
85 void ShutdownDriver() { 86 ABCC_ShutdownDriver();
87 return;
88 } 89 90
91 ABCC_ErrorCodeType ReleaseHardware() { 92 return ABCC_HwRelease();
93 } 94
95 static UINT8 RunUi(void) 96 {
97 static char cNewInput;
98
99 BOOL8 fKbInput = FALSE;
100 BOOL8 fRun = TRUE;
101 UINT8 bRet = LOOP_RUN;
102
103 if (_kbhit()) 104 {
105 cNewInput = (char)_getch();
106 fKbInput = TRUE;
107
108 if ((cNewInput == 'q') || (cNewInput == 'Q')) 109 {
110 /*
111 ** Q is for quit.
112 */
113 fRun = FALSE;
114 bRet = LOOP_QUIT;
115 }
116 else if ((cNewInput == 'r') || (cNewInput == 'R')) 117 {
118 /*
119 ** Q is for quit.
120 */
121 fRun = FALSE;
122 bRet = LOOP_RESET;
123 } 124 else 125 {
126 // Add here action on other characters if necessary 127 }
128 } 129
130 fKbInput = FALSE;
131 return bRet;
132 }
122
3) ApplicationData.h 1 // macro definition
2 constexpr auto DATAIN = "in";
3 constexpr auto DATAOUT = "out";
4
5 constexpr auto STR_DATABOOL = "bool";
6 constexpr auto STR_DATAUINT8 = "uint8";
7 constexpr auto STR_DATAINT8 = "int8";
8 constexpr auto STR_DATAUINT16 = "uint16";
9 constexpr auto STR_DATAINT16 = "int16";
10 constexpr auto STR_DATAUINT32 = "uint32";
11 constexpr auto STR_DATAINT32 = "int32";
12 constexpr auto STR_DATAFLOAT = "float";
13 14
15 // enumerates the type of application data direction 16 enum class eAppDataDirection : int {
17 in = PD_READ, 18 out = PD_WRITE, 19 all
20 };
21
22 // enumerates the type of ABP data direction 23 enum class eAbpDataDirection : int {
24 in = ABP_APPD_DESCR_GET_ACCESS | ABP_APPD_DESCR_MAPPABLE_READ_PD, 25 out = ABP_APPD_DESCR_GET_ACCESS | ABP_APPD_DESCR_MAPPABLE_WRITE_PD, 26 };
27
28 // enumerates the application data types 29 enum class eAppDataType : int {
30 boolData = ABP_BOOL, 31 uint8Data = ABP_UINT8, 32 int8Data = ABP_SINT8, 33 uint16Data = ABP_UINT16, 34 int16Data = ABP_SINT16, 35 uint32Data = ABP_UINT32, 36 int32Data = ABP_SINT32, 37 floatData = ABP_FLOAT, 38 };
39 40
41 // The following struct contains the application configuration data 42 struct stAppConfigData {
43 std::string variableName;
44 eAppDataDirection dataDirection;
45 eAppDataType dataType;
46 };
47
48 using ConfigDataVect = std::vector<stAppConfigData>;
49 using ConfigDataItr = ConfigDataVect::iterator;
50 using ConstConfigDataItr = ConfigDataVect::const_iterator;
51
52 using AdiEntriesVect = std::vector<AD_AdiEntryType>;
53 using AdDefaultMapsVect = std::vector<AD_DefaultMapType>;
54
55 #endif // APPLICATIONDATA_H
4) CommandLineParser.h
1 // This class parses the command line arguments if any in order to extract the configuration file name.
2 // The configuration file name is passed by the option -c if no option is provided or no argument after the ooption
3 // a default file name is returned by the class. The file is named "configuration.cfg"
4
5 #ifndef COMMANDLINEPARSER_H_
6 #define COMMANDLINEPARSER_H_
7
8 #include <string>
9
10 class CommandLineParser 11 {
12 public:
13 CommandLineParser();
14 ~CommandLineParser() = default;
15 void ParseCommandLine(int argc, char ** argv);
16 const std::string& GetConfigurationFileName() const;
17 const std::string& GetInterfaceSerialNo() const;
18 19 private:
20 std::string mConfigurationFileName;
21 std::string mIntefaceSerialNo;
22 };
23
24 #endif // COMMANDLIEPARSER_H
123
5) CommandLineParser.cpp
1 #include "CommandLineParser.h"
2 #include "getopt.h"
3
4 constexpr char sDefaultConfigFile[] = "configuration.cfg";
5 constexpr char sConfigFileOptionStr[] = "c:s:";
6 constexpr char sConfigFileOpt = 'c';
7 constexpr char sConfigIntefaceSnOpt = 's';
8
9 CommandLineParser::CommandLineParser()
10 : mConfigurationFileName(sDefaultConfigFile) 11 , mIntefaceSerialNo("")
12 {
13 return;
14 } 15
16 void CommandLineParser::ParseCommandLine(int argc, char** argv) { 17 if (argc < 3) {
18 // not enough parameters to be parsed
19 return;
20 } 21
22 // seach for the configuration file parameter 23 int opt;
24 while ((opt = getopt(argc, argv, sConfigFileOptionStr)) != -1) 25 {
26 switch (opt) {
27 case sConfigFileOpt:
28 mConfigurationFileName.assign(optarg);
29 break;
30 case sConfigIntefaceSnOpt:
31 mIntefaceSerialNo.assign(optarg);
32 break;
33 default:
34 break;
35 }
36 } 37
38 return;
39 } 40
41 const std::string& CommandLineParser::GetConfigurationFileName() const 42 {
43 return mConfigurationFileName;
44 } 45
46 const std::string& CommandLineParser::GetInterfaceSerialNo() const 47 {
48 return mIntefaceSerialNo;
49 }
124
6) ConfigurationLoader.h
1 // This class loads the configuration from the provided configuration file name.
2 // The configuration file contains the interface serial number for the slave interface and the 3 // variable declaration. We use simple data types no structured data type is supported so far 4
5 #ifndef CONFIGURATIONLOADER_H_
6 #define CONFIGURATIONLOADER_H_
7
8 #include <string>
9 #include <vector>
10 #include <unordered_map>
11 #include <sstream>
12 #include "ApplicationData.h"
13 #include "Logger.h"
14 15
16 class ConfigurationLoader 17 {
18 public:
19 explicit ConfigurationLoader(const SharedLogger& logger, const std::string&
configurationFileName = "", const std::string& insterfaceSerialNo = "");
20 ~ConfigurationLoader();
21 const std::string GetInterfaceSerialNo() const;
22 const char* GetInterfaceSerialNoAsCString() const;
23 void SetConfigurationFileName(const std::string& configurationFileName);
24 const bool LoadConfiguration();
25 const ConfigDataVect& GetConfigData() const;
26 27 private:
28 void clearConfiguration();
29 void parseConfigurationLine(const std::string& configurationLine);
30 const bool isCommentLine(const std::string& line);
31 const bool isCommentLineNoEcho(const std::string& line);
32 const bool checkVariableNameForDuplication(const std::string& variableName) const;
33 const int checkDataDirection(const std::string& dataDirection) const;
34 const int checkDataType(const std::string& dataType) const;
35 36 private:
37 SharedLogger mLogger;
38 std::string mConfigurationFileName;
39 std::string mInterfaceSerialNo;
40 ConfigDataVect mConfigData;
41 42 private:
43 static const char cCommentLineMarker;
44 static const char cCommentLineNoEchoMarker;
45 static const char cSeparator;
46 static const std::string cFileExtension;
47 static const std::string cInterface;
48 static const std::vector<std::string> cDataDirections;
49 static const std::unordered_map<std::string, eAppDataType> cDataTypes;
50 };
51
52 #endif // CONFIGURATIONLOADER_H_
7) ConfigurationLoader.cpp
1 #include "ConfigurationLoader.h"
2
3 #include <fstream>
4 #include <iostream>
5 #include <sstream>
6 #include "FileSystemHelper.h"
7 #include "Util.h"
8
9 constexpr auto FIRST_TOKEN = 1;
10 constexpr auto SECOND_TOKEN = 2;
11 constexpr auto THIRD_TOKEN = 3;
12 constexpr auto ALL_TOKEN_FOUND = 4;
13
14 static std::unordered_map<std::string, eAppDataType> sInitUnorderedtMap() 15 {
16 std::unordered_map<std::string, eAppDataType> map;
17 map[STR_DATABOOL] = eAppDataType::boolData;
18 map[STR_DATAUINT8] = eAppDataType::uint8Data;
19 map[STR_DATAINT8] = eAppDataType::int8Data;
20 map[STR_DATAUINT16] = eAppDataType::uint16Data;
21 map[STR_DATAINT16] = eAppDataType::int16Data;
22 map[STR_DATAUINT32] = eAppDataType::uint32Data;
23 map[STR_DATAINT32] = eAppDataType::int32Data;
24 map[STR_DATAFLOAT] = eAppDataType::floatData;
25 return map;
26 } 27
28 const char ConfigurationLoader::cCommentLineMarker = '#';
125
29 const char ConfigurationLoader::cCommentLineNoEchoMarker = '@';
30 const char ConfigurationLoader::cSeparator = ':';
31 const std::string ConfigurationLoader::cFileExtension = "cfg";
32 const std::string ConfigurationLoader::cInterface = "interface";
33 const std::vector<std::string> ConfigurationLoader::cDataDirections = { DATAIN, DATAOUT };
34 const std::unordered_map<std::string, eAppDataType> ConfigurationLoader::cDataTypes = sInitUnorderedtMap();
35 36
37 ConfigurationLoader::ConfigurationLoader(const SharedLogger& logger, const std::string&
configurationFileName, const std::string& interfaceSerialNo) 38 : mLogger(logger)
39 , mConfigurationFileName(configurationFileName) 40 , mInterfaceSerialNo(interfaceSerialNo) 41 {
42 mLogger->Log(std::string("Initial data for loader: ") + configurationFileName + "\n\t" + interfaceSerialNo);
43 return;
44 } 45
46 ConfigurationLoader::~ConfigurationLoader() 47 {
48 return;
49 } 50
51 const std::string ConfigurationLoader::GetInterfaceSerialNo() const 52 {
53 return mInterfaceSerialNo;
54 } 55
56 const char* ConfigurationLoader::GetInterfaceSerialNoAsCString() const 57 {
58 return mInterfaceSerialNo.c_str();
59 } 60 61
62 void ConfigurationLoader::SetConfigurationFileName(const std::string& configurationFileName) 63 {
64 mConfigurationFileName = configurationFileName;
65 return;
66 } 67
68 const bool ConfigurationLoader::LoadConfiguration() 69 {
70 bool isConfigValid = false;
71 // check for the expected file extension
72 if(filesystemhelper::CheckFilenameExtension(mConfigurationFileName, cFileExtension) == false ) 73 {
74 mLogger->Log(std::string("Invalid file extension; ") + mConfigurationFileName + "
Exptected: *." + cFileExtension);
75 return isConfigValid;
76 } 77
78 // open the file and read it
79 std::ifstream configFileStream(mConfigurationFileName);
80 if (configFileStream.is_open()) {
81 // clear any previous configuration
82 mLogger->Log(std::string("Load configuration from: ") + mConfigurationFileName);
83 std::string line;
84 while (std::getline(configFileStream, line)) {
85 parseConfigurationLine(line);
86 }
87 } 88 else {
89 mLogger->Log(std::string("Could not open the file:") + mConfigurationFileName );
90 return isConfigValid;
91 }
92 isConfigValid = mConfigData.size() > 0;
93 if (isConfigValid == false) {
94 mLogger->Log("No varibles have been configured");
95 }
96 return isConfigValid;
97 } 98
99 const ConfigDataVect& ConfigurationLoader::GetConfigData() const 100 {
101 return mConfigData;
102 } 103
104 void ConfigurationLoader::clearConfiguration() 105 {
106 mInterfaceSerialNo.clear();
107 mConfigData.clear();
108 return;
109 } 110
111 void ConfigurationLoader::parseConfigurationLine(const std::string& configurationLine) 112 {
126
113 // check for empty line and just ignore it 114 if (configurationLine.length() == 0) return;
115 // check for comment line
116 if (isCommentLine(configurationLine) == true || isCommentLineNoEcho(configurationLine) == true) return;
117 // tokenize the configuration line parsing
118 std::stringstream lineStream(configurationLine, std::ios_base::in);
119 std::string token;
120 int tokenNumber = 1;
121 stAppConfigData configData;
122 bool interfaceSnFound = false;
123 while (std::getline(lineStream, token, cSeparator)) 124 {
125 token = util::Trim(token);
126 int infoIdx = -1;
127 switch (tokenNumber) { 128 case FIRST_TOKEN:
129 // look for inteface number
130 if (token == cInterface) {
131 if (mInterfaceSerialNo.length() == 0) {
132 interfaceSnFound = true;
133 }
134 else {
135 mLogger->Log(std::string("Interface S/N already provided: ") + mInterfaceSerialNo );
136 return;
137 }
138 }
139 else {
140 // check if it is a new variable name
141 if (checkVariableNameForDuplication(token) == false) {
142 configData.variableName = token;
143 }
144 else {
145 return;
146 }
147 }
148 break;
149 case SECOND_TOKEN:
150 // it can be the serial number or the data type
151 if (interfaceSnFound) {
152 mInterfaceSerialNo = token;
153 mLogger->Log(std::string("Interface S/N: ") + token);
154 return;
155 }
156 else if ((infoIdx = util::GetValue<std::string>(cDataTypes, token)) >= 0) { 157 configData.dataType = (eAppDataType) infoIdx;
158 }
159 else {
160 mLogger->Log(std::string("Unknown data type: ") + token + ", for variable:
" + configData.variableName);
161 return;
162 }
163 break;
164 case THIRD_TOKEN:
165 // this case is entered only for the data direction
166 if ((infoIdx = util::GetIndex<std::string>(cDataDirections, token)) >= 0) { 167 configData.dataDirection = (eAppDataDirection) infoIdx;
168 }
169 else {
170 mLogger->Log(std::string("Unknown data direction: ") + token + ", for variable: " + configData.variableName);
171 return;
172 }
173 break;
174 default:
175 mLogger->Log(std::string("Too many attributes for variable: ") + configData.variableName);
176 return;
177 }
178 ++tokenNumber;
179 }
180 // once the execution arrived here the variable definition could be incomplete 181 if (tokenNumber == ALL_TOKEN_FOUND) {
182 mConfigData.push_back(configData);
183 mLogger->Log(std::string("[OK] ") + util::PrintableAppConfigData(configData) );
184 } 185 else {
186 mLogger->Log(std::string("Invalid variable definition: ") + configData.variableName);
187 } 188 return;
189 } 190
191 const bool ConfigurationLoader::isCommentLine(const std::string& line) 192 {
193 if (line[0] == cCommentLineMarker) {
194 mLogger->Log(std::string("Found comment: ") + line);
195 return true;
127
196 }
197 return false;
198 } 199
200 const bool ConfigurationLoader::isCommentLineNoEcho(const std::string& line) 201 {
202 return line[0] == cCommentLineNoEchoMarker;
203 } 204
205 const bool ConfigurationLoader::checkVariableNameForDuplication(const std::string& variableName) const
206 {
207 auto it = std::find_if(mConfigData.begin(), mConfigData.end(), [&variableName](const stAppConfigData& configData) {
208 return (variableName == configData.variableName);
209 });
210
211 if (it != mConfigData.end()) {
212 mLogger->Log(std::string("Duplicate varibale name: ") + variableName);
213 return true;
214 } 215
216 return false;
217 } 218
219 const int ConfigurationLoader::checkDataDirection(const std::string& dataDirection) const 220 {
221 return util::GetIndex<std::string>(cDataDirections, dataDirection);
222 } 223
224 const int ConfigurationLoader::checkDataType(const std::string& dataType) const 225 {
226 return util::GetValue<std::string>(cDataTypes, dataType);
227 }
128
8) ConsoleLogger.h
1 #ifndef CONSOLELOGGER_H 2 #define CONSOLELOGGER_H 3
4 #include "Logger.h"
5 6 class ConsoleLogger : 7 public Logger 8 {
9 public:
10 ConsoleLogger() = default;
11 ~ConsoleLogger() = default;
12 virtual void Log(const std::string& message) override;
13 virtual void Log(const std::vector<std::string>& messages) override;
14 };
15
16 #endif // CONSOLELOGGER_H
9) ConsoleLogger.cpp
1 #include "ConsoleLogger.h"
2 #include <iostream>
3
4 void ConsoleLogger::Log(const std::string& message) 5 {
6 std::cout << message << std::endl;
7 return;
8 } 9 10
11 void ConsoleLogger::Log(const std::vector<std::string>& messages) 12 {
13 for( const std::string& message : messages ) 14 {
15 Log(message);
16 } 17 return;
18 }
10) DataReader.h
1 // Class for reading a given variable if it exists
2 // the value si provided back as a string, if the typed value 3 // is needed it will be necessary to ask for the underling object 4 // that contains the data
5
6 #include<sstream>
7 #include "DataWrapper.h"
8
9 class DataReader 10 {
11 public:
12 DataReader(INamedDataWrapperUmap dataContainerUmap);
13 ~DataReader();
14 const std::string GetDataValue(const std::string& dataName);
15 const std::string GetAllDataValues();
16 private:
17 void addDataStringValue(std::stringstream& ss, const IDataWrapperShPtr& dataContainer);
18
19 void addBoolValue(std::stringstream& ss, const void * dataPtr);
20 void addFloatValue(std::stringstream& ss, const void* dataPtr);
21 void addInt16Value(std::stringstream& ss, const void* dataPtr);
22 void addInt32Value(std::stringstream& ss, const void* dataPtr);
23 void addInt8Value(std::stringstream& ss, const void* dataPtr);
24 void addUint16Value(std::stringstream& ss, const void* dataPtr);
25 void addUint32Value(std::stringstream& ss, const void* dataPtr);
26 void addUint8Value(std::stringstream& ss, const void* dataPtr);
27 private:
28 INamedDataWrapperUmap mDataContainer;
29 };
129
11) DataReader.cpp
1 #include "DataReader.h"
2
3 DataReader::DataReader(INamedDataWrapperUmap dataContainerUmap) 4 : mDataContainer(dataContainerUmap)
5 {
6 return;
7 } 8
9 DataReader::~DataReader() 10 {
11 } 12
13 const std::string DataReader::GetDataValue(const std::string & dataName) 14 {
15 std::stringstream ss;
16 auto it = mDataContainer.find(dataName);
17 if (it != mDataContainer.end())
18 addDataStringValue(ss, it->second);
19 else
20 ss << dataName << ": Does not exist";
21 return ss.str();
22 } 23
24 const std::string DataReader::GetAllDataValues() 25 {
26 std::stringstream ss;
27 for (auto it : mDataContainer) { 28 addDataStringValue(ss, it.second);
29 ss << "\n";
30 }
31 return ss.str();
32 } 33
34 void DataReader::addDataStringValue(std::stringstream& ss, const IDataWrapperShPtr& dataContainer) 35 {
36 void* dataPtr = dataContainer->GetDataPtr();
37 ss << dataContainer->GetDataName() << ": ";
38 switch (dataContainer->GetDataType()) { 39 case eAppDataType::boolData:
40 addBoolValue(ss, dataPtr);
41 break;
42 case eAppDataType::floatData:
43 addFloatValue(ss, dataPtr);
44 break;
45 case eAppDataType::int16Data:
46 addInt16Value(ss, dataPtr);
47 break;
48 case eAppDataType::int32Data:
49 addInt32Value(ss, dataPtr);
50 break;
51 case eAppDataType::int8Data:
52 addInt8Value(ss, dataPtr);
53 break;
54 case eAppDataType::uint16Data:
55 addUint16Value(ss, dataPtr);
56 break;
57 case eAppDataType::uint32Data:
58 addUint32Value(ss, dataPtr);
59 break;
60 case eAppDataType::uint8Data:
61 addUint8Value(ss, dataPtr);
62 break;
63 default:
64 ss << "Unknown data type";
65 break;
66 } 67 return;
68 } 69
70 void DataReader::addBoolValue(std::stringstream& ss, const void* dataPtr) 71 {
72 ss << (*(BOOL*)dataPtr) ? "true" : "false";
73 return;
74 } 75
76 void DataReader::addFloatValue(std::stringstream& ss, const void* dataPtr) 77 {
78 ss << *(FLOAT*)dataPtr;
79 return;
80 } 81
82 void DataReader::addInt16Value(std::stringstream& ss, const void* dataPtr) 83 {
84 ss << *(INT16*)dataPtr;
85 return;
130
86 } 87
88 void DataReader::addInt32Value(std::stringstream& ss, const void* dataPtr) 89 {
90 ss << *(INT32*)dataPtr;
91 return;
92 } 93
94 void DataReader::addInt8Value(std::stringstream& ss, const void* dataPtr) 95 {
96 ss << (int)*(INT8*)dataPtr;
97 return;
98 } 99
100 void DataReader::addUint16Value(std::stringstream& ss, const void* dataPtr) 101 {
102 ss << *(UINT16*)dataPtr;
103 return;
104 } 105
106 void DataReader::addUint32Value(std::stringstream& ss, const void* dataPtr) 107 {
108 ss << *(UINT32*)dataPtr;
109 return;
110 } 111
112 void DataReader::addUint8Value(std::stringstream& ss, const void* dataPtr) 113 {
114 ss << (int)*(UINT8*)dataPtr;
115 return;
116 }
131
12) DataValuesGenerator.h
1 // Generates random values for the different data 2 // configured in the EtherCAT Slave inteface 3
4 #ifndef DATAVALUESGENERATOR_H_
5 #define DATAVALUESGENERATOR_H_
6
7 #include "DataWrapper.h"
8
9 class DataValuesGenerator 10 {
11 public:
12 DataValuesGenerator(INamedDataWrapperUmap dataContainerUmap);
13 virtual ~DataValuesGenerator() = default;
14 void GeneratDataValues();
15 private:
16 void generateValues(IDataWrapperShPtr data);
17 void generateBool(void* data);
18 void generateFloat(void* data);
19 void generateInt16(void* data);
20 void generateInt32(void* data);
21 void generateInt8(void* data);
22 void generateUint16(void* data);
23 void generateUint32(void* data);
24 void generateUint8(void* data);
25 26 private:
27 INamedDataWrapperUmap mDataContainer;
28 29 };
30
31 #endif // DATAVALUESGENERATOR_H_
13) DataValuesGenerator.cpp
1 #include "DataValuesGenerator.h"
2
3 constexpr auto MIN_FLOAT_VALUE = -10.0f;
4 constexpr auto MAX_FLOAT_VALUE = 10.0f;
5 constexpr auto MAX_INT_VALUE = 100;
6 constexpr auto MIN_INT_VALUE = -100;
7 constexpr auto MAX_UINT_VALUE = 200;
8 constexpr auto MIN_UINT_VALUE = 0;
9
10 constexpr auto FLOAT_INCREMENT = 0.1f;
11
12 DataValuesGenerator::DataValuesGenerator(INamedDataWrapperUmap dataContainerUmap) 13 : mDataContainer(dataContainerUmap)
14 {
15 return;
16 } 17
18 void DataValuesGenerator::GeneratDataValues() 19 {
20 for (auto it : mDataContainer) { 21 generateValues(it.second);
22 } 23 return;
24 } 25
26 void DataValuesGenerator::generateValues(IDataWrapperShPtr dataWrapper) 27 {
28 void* data = dataWrapper->GetDataPtr();
29 switch (dataWrapper->GetDataType()) { 30 case eAppDataType::boolData:
31 generateBool(data);
32 break;
33 case eAppDataType::floatData:
34 generateFloat(data);
35 break;
36 case eAppDataType::int16Data:
37 generateInt16(data);
38 break;
39 case eAppDataType::int32Data:
40 generateInt32(data);
41 break;
42 case eAppDataType::int8Data:
43 generateInt8(data);
44 break;
45 case eAppDataType::uint16Data:
46 generateUint16(data);
47 break;
48 case eAppDataType::uint32Data:
49 generateUint32(data);
132
50 break;
51 case eAppDataType::uint8Data:
52 generateUint8(data);
53 break;
54 55 } 56
57 return;
58 } 59
60 void DataValuesGenerator::generateBool(void* data) 61 {
62 *((BOOL*)data) = !(*((BOOL*)data));
63
64 return;
65 } 66
67 void DataValuesGenerator::generateFloat(void* data) 68 {
69 if ((*(PFLOAT)data) > MAX_FLOAT_VALUE) 70 *(PFLOAT)data = MIN_FLOAT_VALUE;
71 else
72 *(PFLOAT)data += FLOAT_INCREMENT;
73
74 return;
75 } 76
77 void DataValuesGenerator::generateInt16(void* data) 78 {
79 if ((*(PINT16)data) > MAX_INT_VALUE) 80 *(PINT16)data = MIN_INT_VALUE;
81 else
82 ++(*(PINT16)data);
83
84 return;
85 } 86
87 void DataValuesGenerator::generateInt32(void* data) 88 {
89 if ((*(PINT32)data) > MAX_INT_VALUE) 90 *(PINT32)data = MIN_INT_VALUE;
91 else
92 ++(*(PINT32)data);
93
94 return;
95 } 96
97 void DataValuesGenerator::generateInt8(void* data) 98 {
99 if ((*(PINT8)data) > MAX_INT_VALUE) 100 *(PINT8)data = MIN_INT_VALUE;
101 else
102 ++(*(PINT8)data);
103
104 return;
105 } 106
107 void DataValuesGenerator::generateUint16(void* data) 108 {
109 if ((*(PUINT16)data) > MAX_UINT_VALUE) 110 *(PUINT16)data = MIN_UINT_VALUE;
111 else
112 ++(*(PUINT16)data);
113
114 return;
115 } 116
117 void DataValuesGenerator::generateUint32(void* data) 118 {
119 if ((*(PUINT32)data) > MAX_UINT_VALUE) 120 *(PUINT32)data = MIN_UINT_VALUE;
121 else
122 ++(*(PUINT32)data);
123
124 return;
125 } 126
127 void DataValuesGenerator::generateUint8(void* data) 128 {
129 if ((*(PUINT8)data) > MAX_UINT_VALUE) 130 *(PUINT8)data = MIN_UINT_VALUE;
131 else
132 ++(*(PUINT8)data);
133
134 return;
135 }
133
14) DataWrapper.h
1 #ifndef DATAWRAPPER_H_
2 #define DATAWRAPPER_H_
3
4 #include "IDataWrapper.h"
5 6 template<typename T>
7 class DataWrapper : 8 public IDataWrapper 9 {
10 public:
11 DataWrapper(const stAppConfigData& configData);
12 virtual ~DataWrapper() = default;
13 T getDataValue() const;
14 void setDataValue(const T& dataValue);
15 private:
16 T mDataValue;
17 };
18
19 #include "DataWrapper_i.h"
20
21 template<typename T>
22 using DataWrapperShPtr = std::shared_ptr<DataWrapper<T>>;
23
24 #endif // DATAWRAPPER_H_
15) DataWrapper_i.h
1 // Contains inline methods implementations 2 #ifndef DATAWRAPPER_I_H_
3 #define DATAWRAPPER_I_H_
4
5 #include "DataWrapper.h"
6
7 template<typename T>
8 inline DataWrapper<T>::DataWrapper(const stAppConfigData& configData) 9 : IDataWrapper(configData)
10 , mDataValue( (T) 0) 11 {
12 mDataPtr = &mDataValue;
13 return;
14 } 15
16 template<typename T>
17 inline T DataWrapper<T>::getDataValue() const 18 {
19 return mDataValue;
20 } 21
22 template<typename T>
23 inline void DataWrapper<T>::setDataValue(const T& dataValue) 24 {
25 mDataValue = dataValue;
26 return;
27 } 28
29 #endif // DATAWRAPPER_I_H_
134
16) IDataWrapper.h
1 // This class represents the inteface to a data wrapper 2
3 #ifndef IDATAWRAPPER_H_
4 #define IDATAWRAPPER_H_
5 6 #include <vector>
7 #include <memory>
8 #include <unordered_map>
9 #include "ApplicationData.h"
10
11 class IDataWrapper 12 {
13 public:
14 std::string GetDataName() const;
15 eAppDataType GetDataType() const;
16 eAppDataDirection GetDataDirection() const;
17 virtual ~IDataWrapper() = default;
18 void* GetDataPtr() const;
19 protected:
20 IDataWrapper(const stAppConfigData& configData);
21 protected:
22 void* mDataPtr;
23 private:
24 stAppConfigData mConfigData;
25 };
26
27 // Shared pointer to an IDataWrapper
28 using IDataWrapperShPtr = std::shared_ptr<IDataWrapper>;
29 // Vector of IDataWrappers
30 using IDataWrapperVect = std::vector<IDataWrapper>;
31 // Vector of shared pointers to IDataWrapper
32 using IDataWrapperShPtrVect = std::vector<IDataWrapperShPtr>;
33 // Shared pointer to a vector of shared pointers to IDataWrapper 34 using IDataWrapperVectShPtr = std::shared_ptr<IDataWrapperVect>;
35 // Unordered map to named shared pointer to IDataWrapper
36 using INamedDataWrapperUmap = std::unordered_map<std::string, IDataWrapperShPtr>;
37 #endif // IDATAWRAPPER_H_
17) IDataWrapper.cpp
1 #include "IDataWrapper.h"
2 3 std::string IDataWrapper::GetDataName() const 4 {
5 return mConfigData.variableName;
6 } 7
8 eAppDataType IDataWrapper::GetDataType() const 9 {
10 return mConfigData.dataType;
11 } 12
13 eAppDataDirection IDataWrapper::GetDataDirection() const 14 {
15 return mConfigData.dataDirection;
16 } 17
18 void* IDataWrapper::GetDataPtr() const 19 {
20 return mDataPtr;
21 } 22
23 IDataWrapper::IDataWrapper(const stAppConfigData& configData) 24 : mDataPtr(nullptr)
25 , mConfigData(configData) 26 {
27 return;
28 }
135
18) Logger.h
1 // Defines the interface for data logging 2
3 #ifndef LOGGER_H 4 #define LOGGER_H 5 6 #include <string>
7 #include <vector>
8 #include <memory>
9
10 class Logger 11 {
12 public:
13 virtual ~Logger() = default;
14 virtual void Log(const std::string& message) = 0;
15 virtual void Log(const std::vector<std::string>& messages) = 0;
16 };
17
18 using SharedLogger = std::shared_ptr<Logger>;
19
20 #endif // LOGGER_H
19) SlaveConfigurator.h
1 // This class configures the application ADI to flash into
2 // the interface depending on the data achieved from the configuration file 3
4 #ifndef SLAVECONFIGURATOR_H_
5 #define SLAVECONFIGURATOR_H_
6
7 #include<iostream>
8 #include<vector>
9 #include "Logger.h"
10 #include "ApplicationData.h"
11 #include "DataWrapper.h"
12 13
14 class SlaveConfigurator 15 {
16 public:
17 SlaveConfigurator(const SharedLogger& logger);
18 SlaveConfigurator(const SlaveConfigurator&) = delete;
19 SlaveConfigurator(SlaveConfigurator&&) = delete;
20 SlaveConfigurator& operator=(const SlaveConfigurator&) = delete;
21 SlaveConfigurator& operator=(SlaveConfigurator&&) = delete;
22 virtual ~SlaveConfigurator();
23 bool ConfigureSlave(const ConfigDataVect& configData);
24 UINT16 GetNumberOfAdis() const;
25 AD_AdiEntry* GetAdis();
26 AD_DefaultMapType* GetObjMap();
27 const INamedDataWrapperUmap GetReadableDataMap() const;
28 const INamedDataWrapperUmap GetWritableDataMap() const;
29 const INamedDataWrapperUmap GetAllDataMap() const;
30 private:
31 const IDataWrapperShPtr createShDataWrapper(const stAppConfigData& configData) const;
32 const INamedDataWrapperUmap getDataMap(const eAppDataDirection direction) const;
33 private:
34 SharedLogger mLogger;
35 AdiEntriesVect mAdiEntries;
36 AdDefaultMapsVect mAdObjMaps;
37 IDataWrapperShPtrVect mDataWrappers;
38 };
39
40 #endif // SLAVECONFIGURATOR_H
136
20) SlaveConfigurator.cpp 1 #include<utility>
2 #include "SlaveConfigurator.h"
3 #include "abcc_ad_if.h"
4
5 SlaveConfigurator::SlaveConfigurator(const SharedLogger& logger) 6 : mLogger(logger)
7 {
8 return;
9 } 10
11 SlaveConfigurator::~SlaveConfigurator() 12 {
13 return;
14 } 15
16 bool SlaveConfigurator::ConfigureSlave(const ConfigDataVect& configData) 17 {
18 bool ret = false;
19
20 if (configData.size() == 0) {
21 mLogger->Log(std::string("[Slave Configuration] Nothing to configure!") );
22 return ret;
23 } 24
25 UINT16 instanceNo = 1;
26
27 for(const stAppConfigData& cData : configData) {
28 IDataWrapperShPtr dataWrapper = createShDataWrapper(cData);
29 uDataType dataT;
30 dataT.sVOID.pxValuePtr = dataWrapper->GetDataPtr();
31 dataT.sVOID.pxValueProps = NULL;
32
33 AD_AdiEntryType adiEntry = { instanceNo, const_cast<char*>(cData.variableName.c_str()), (UINT8)cData.dataType, 1, 0, dataT };
34 AD_DefaultMapType defaultMap = { instanceNo, static_cast<PD_DirType>(cData.dataDirection), 1, 0 };
35 mAdiEntries.push_back(adiEntry);
36 mAdObjMaps.push_back(defaultMap);
37 mDataWrappers.push_back(std::move(dataWrapper));
38 ++instanceNo;
39 } 40
41 if ((ret = mAdObjMaps.size() > 0))
42 mAdObjMaps.push_back({ AD_DEFAULT_MAP_END_ENTRY });
43 else
44 mLogger->Log(std::string("[Slave Configuration] Could no configure the slave"));
45
46 return ret;
47 } 48
49 UINT16 SlaveConfigurator::GetNumberOfAdis() const 50 {
51 return (UINT16)mAdiEntries.size();
52 } 53
54 AD_AdiEntry* SlaveConfigurator::GetAdis() 55 {
56 return mAdiEntries.data();
57 } 58
59 AD_DefaultMapType* SlaveConfigurator::GetObjMap() 60 {
61 return mAdObjMaps.data();
62 } 63
64 const INamedDataWrapperUmap SlaveConfigurator::GetReadableDataMap() const 65 {
66 return getDataMap(eAppDataDirection::in);
67 } 68
69 const INamedDataWrapperUmap SlaveConfigurator::GetWritableDataMap() const 70 {
71 return getDataMap(eAppDataDirection::out);
72 } 73
74 const INamedDataWrapperUmap SlaveConfigurator::GetAllDataMap() const 75 {
76 return getDataMap(eAppDataDirection::all);
77 } 78
79 const IDataWrapperShPtr SlaveConfigurator::createShDataWrapper(const stAppConfigData& configData) const
80 {
81 switch (configData.dataType) { 82 case eAppDataType::boolData:
137
83 return IDataWrapperShPtr( new DataWrapper<BOOL>(configData) );
84 case eAppDataType::floatData:
85 return IDataWrapperShPtr( new DataWrapper<FLOAT>(configData) );
86 case eAppDataType::int16Data:
87 return IDataWrapperShPtr( new DataWrapper<INT16>(configData) );
88 case eAppDataType::int32Data:
89 return IDataWrapperShPtr( new DataWrapper<INT32>(configData) );
90 case eAppDataType::int8Data:
91 return IDataWrapperShPtr( new DataWrapper<INT8>(configData) );
92 case eAppDataType::uint16Data:
93 return IDataWrapperShPtr( new DataWrapper<UINT16>(configData) );
94 case eAppDataType::uint32Data:
95 return IDataWrapperShPtr( new DataWrapper<UINT32>(configData) );
96 case eAppDataType::uint8Data:
97 return IDataWrapperShPtr( new DataWrapper<UINT8>(configData) );
98 } 99
100 return IDataWrapperShPtr();
101 } 102 103
104 const INamedDataWrapperUmap SlaveConfigurator::getDataMap(const eAppDataDirection direction) const 105 {
106 INamedDataWrapperUmap namedDataWrapperUmap;
107
108 for (IDataWrapperShPtr dataWrapper : mDataWrappers) {
109 if (direction == eAppDataDirection::all || direction == dataWrapper->GetDataDirection()) {
110 namedDataWrapperUmap.insert(std::make_pair(dataWrapper->GetDataName(), dataWrapper));
111 }
112 } 113
114 return namedDataWrapperUmap;
115 }
138
21) main.cpp
1 #include <iostream>
2 #include <memory>
3 #include <windows.h>
4 #include <stdio.h>
5
6 #ifdef __cplusplus 7 extern "C" { 8 #endif
9 #include "IDL_interface.h"
10 #ifdef __cplusplus 11 }
12 #endif 13
14 #include "CommandLineParser.h"
15 #include "ConsoleLogger.h"
16 #include "ConfigurationLoader.h"
17 #include "SlaveConfigurator.h"
18 #include "DataReader.h"
19 #include "DataValuesGenerator.h"
20 21
22 SharedLogger appLogger = SharedLogger(new ConsoleLogger);
23 std::unique_ptr<DataReader> pDataReader;
24 std::unique_ptr<DataValuesGenerator> pDataWriter;
25
26 extern "C" void UpdateInterface() { 27 system("cls");
28 appLogger->Log(pDataReader->GetAllDataValues());
29 pDataWriter->GeneratDataValues();
30 return;
31 } 32 33 /**
34 Slave application entry point 35 */
36 int main(int argc, char* argv[]) 37 {
38 int outcome = 1;
39
40 appLogger->Log("EtherCAT slave stared");
41 42 //
43 // parse the command line to retrieve the configuration file indication 44 //
45 std::unique_ptr<CommandLineParser> CmdLineParser = std::unique_ptr<CommandLineParser>(new CommandLineParser);
46 CmdLineParser->ParseCommandLine(argc, argv);
47
48 // load the configuration from file
49 std::shared_ptr<ConfigurationLoader> cfgLoader = std::shared_ptr<ConfigurationLoader>(new ConfigurationLoader(appLogger, CmdLineParser->GetConfigurationFileName(),
50 CmdLineParser->GetInterfaceSerialNo()));
51 if (cfgLoader->LoadConfiguration() == false) { 52 return outcome;
53 } 54
55 outcome = 0;
56
57 if (InitHardware(const_cast<char*>(cfgLoader->GetInterfaceSerialNoAsCString())) ==
ABCC_EC_NO_ERROR) 58 {
59 appLogger->Log(std::string("\n[OK] Hardware interface initialized"));
60 // initialize the object to create slave configuration
61 std::unique_ptr<SlaveConfigurator> slaveConfigurator = std::unique_ptr<SlaveConfigurator>(new SlaveConfigurator(appLogger));
62 slaveConfigurator->ConfigureSlave(cfgLoader->GetConfigData());
63
64 RegisterNotifyer(UpdateInterface);
65
66 if (InitConfiguration( slaveConfigurator->GetAdis(), 67 slaveConfigurator->GetObjMap(),
68 slaveConfigurator->GetNumberOfAdis())) { 69 outcome = 3;
70 } 71
72 pDataReader = std::unique_ptr<DataReader>(new
DataReader(slaveConfigurator->GetReadableDataMap()));
73 pDataWriter = std::unique_ptr<DataValuesGenerator>( new
DataValuesGenerator(slaveConfigurator->GetWritableDataMap()));
74
75 // ETC slave FSM managment and notifier calling if any 76 ManageSlave();
77
78 appLogger->Log(std::string("\n[->] Shutdown the driver"));
139
79 ShutdownDriver();
80
81 appLogger->Log(std::string("\n[->] Release the hardware interface"));
82 ReleaseHardware();
83 } 84 else {
85 appLogger->Log(std::string("\n[FAIL] Hardware inteface could not be initialized"));
86 outcome = 2;
87 } 88
89 return outcome;
90
91 } /* End of main() */
140