• Non ci sono risultati.

W INDOWS E THER CAT S LAVE (C/C++ SOURCE C ODE )

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