5 #include "../ErrorReporting.h"
15 std::optional<std::vector<std::byte>>
17 std::uint16_t startAddress,
18 std::uint16_t endAddress)
const
20 bool pdiHadEEPROMControl =
static_cast<bool>(ec_slave[slaveIndex].eep_pdi);
21 if (ec_eeprom2master(slaveIndex) == 0)
24 "Failed to read ESI of slave at index %u - could not get control of the EEPROM.",
29 std::vector<std::byte> result = readFromEEPROM(
30 slaveIndex, startAddress, endAddress, ec_slave[slaveIndex].eep_8byte > 0);
32 if (pdiHadEEPROMControl)
34 ec_eeprom2pdi(slaveIndex);
37 return std::move(result);
40 std::vector<std::byte>
41 ESIHandler::readFromEEPROM(std::uint16_t slaveIndex,
42 std::uint16_t startAddress,
43 std::uint16_t endAddress,
44 bool has64BitPackets)
const
48 std::vector<std::byte> result;
52 std::uint16_t addressIncr = 2;
58 result.reserve((endAddress - startAddress) * addressIncr * 2);
62 for (std::uint16_t currentAddress = startAddress; currentAddress < endAddress;
63 currentAddress += addressIncr)
65 std::uint64_t eepromData =
69 for (
int i = 0; i < addressIncr * 2; ++i)
71 static const int byteLength = 8;
72 static const int byteMask = 0xFF;
73 result.push_back(std::byte((eepromData >> (i * byteLength)) & byteMask));
82 getU8(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
84 if (esiBinary.size() <
static_cast<std::size_t
>(address + 1))
86 return static_cast<std::uint8_t
>(esiBinary.at(address));
90 getU16(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
92 if (esiBinary.size() <
static_cast<std::size_t
>(address + 2))
94 const std::uint16_t byteSize = 8;
95 return static_cast<std::uint16_t
>(esiBinary.at(address)) &
96 (
static_cast<std::uint16_t
>(esiBinary.at(address + 1)) << byteSize);
100 get16(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
102 auto unsignedValue =
getU16(esiBinary, address);
103 return *
reinterpret_cast<std::int16_t*
>(&unsignedValue);
107 getU16W(
const std::vector<std::byte>& esiBinary, std::uint16_t wordAddress)
109 return getU16(esiBinary, wordAddress * 2);
113 getU32(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
115 if (esiBinary.size() <
static_cast<std::size_t
>(address + 4))
117 const auto byteSize = 8;
118 return static_cast<std::uint32_t
>(esiBinary.at(address)) +
119 (
static_cast<std::uint32_t
>(esiBinary.at(address + 1)) << byteSize) +
120 (
static_cast<std::uint32_t
>(esiBinary.at(address + 2)) << 2 * byteSize) +
121 (
static_cast<std::uint32_t
>(esiBinary.at(address + 3)) << 3 * byteSize);
125 getU32W(
const std::vector<std::byte>& esiBinary, std::uint16_t wordAddress)
127 return getU32(esiBinary, wordAddress * 2);
135 std::uint16_t categoryOffset = 0x0040;
136 auto categoryType =
getU16W(esiBinary, categoryOffset);
138 categoryType &= (1 << 15) - 1;
139 auto categorySize =
getU16W(esiBinary, categoryOffset + 1);
140 while (categoryType != 0x7fff)
142 switch (categoryType)
150 esiData.strings =
parseStrings(esiBinary, categoryOffset + 2);
158 esiData.general =
parseGeneral(esiBinary, categoryOffset + 2);
162 esiData.fmmu =
parseFMMU(esiBinary, categoryOffset + 2, categorySize);
166 esiData.syncM =
parseSyncM(esiBinary, categoryOffset + 2, categorySize);
170 esiData.txPDO =
parsePDOs(esiBinary, categoryOffset + 2, categorySize);
174 esiData.rxPDO =
parsePDOs(esiBinary, categoryOffset + 2, categorySize);
178 categoryOffset += 2 + categorySize;
179 categoryType =
getU16W(esiBinary, categoryOffset);
181 categoryType &= (1 << 15) - 1;
182 categorySize =
getU16W(esiBinary, categoryOffset + 1);
215 std::vector<std::string>
218 std::vector<std::string> strings;
219 auto nStrings =
getU8(esiBinary, 2 * wordOffset);
220 strings.reserve(nStrings);
221 std::uint16_t currentOffset = 2 * wordOffset + 1;
222 for (
auto i = 0; i < nStrings; ++i)
226 len =
static_cast<std::uint8_t
>(esiBinary.at(currentOffset));
228 if (currentOffset + len > esiBinary.size())
229 ARMARX_FATAL <<
"The ESI binary ended unexpectedly while reading a string!";
230 tmp.assign(
reinterpret_cast<const char*
>(&esiBinary[currentOffset]), len);
231 strings.emplace_back(tmp);
232 currentOffset += len;
241 std::uint16_t offset = 2 * wordOffset;
243 esiGeneral.
imgIdx =
getU8(esiBinary, offset + 0x0001);
252 esiGeneral.
flags =
getU8(esiBinary, offset + 0x000b);
261 std::uint16_t wordOffset,
264 std::uint16_t count = 2 * len;
266 esiFmmu.reserve(count);
267 for (std::uint16_t i = 0; i < count; ++i)
269 esiFmmu.emplace_back(
getU8(esiBinary, 2 * wordOffset + i));
276 std::uint16_t wordOffset,
279 const std::uint16_t syncMElementLen = 8;
280 const std::uint16_t count = 2 * len / syncMElementLen;
282 esiSyncM.reserve(count);
283 std::uint16_t currentOffset = 2 * wordOffset;
284 for (
size_t i = 0; i < count; ++i)
288 elem.
length =
getU16(esiBinary, currentOffset + 0x0002);
293 esiSyncM.emplace_back(elem);
294 currentOffset += syncMElementLen;
299 std::vector<ESIPDOObject>
301 std::uint16_t wordOffset,
304 std::vector<ESIPDOObject> esiPDOs;
305 std::uint16_t currentOffset = 2 * wordOffset;
306 while (currentOffset < 2 * (wordOffset + len))
313 pdoObject.
nameIdx =
getU8(esiBinary, currentOffset + 0x0005);
314 pdoObject.
flags =
getU16(esiBinary, currentOffset + 0x0006);
317 for (
int i = 0; i < pdoObject.
entryCount; ++i)
320 pdoEntry.
index =
getU16(esiBinary, currentOffset + 0x0000);
321 pdoEntry.
subIndex =
getU8(esiBinary, currentOffset + 0x0002);
322 pdoEntry.
nameIdx =
getU8(esiBinary, currentOffset + 0x0003);
323 pdoEntry.
dataType =
getU8(esiBinary, currentOffset + 0x0004);
325 pdoEntry.
flags =
getU16(esiBinary, currentOffset + 0x0006);
326 pdoObject.
entries.emplace_back(pdoEntry);
329 esiPDOs.emplace_back(pdoObject);