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));
81 getU8(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
83 if (esiBinary.size() <
static_cast<std::size_t
>(address + 1))
85 return static_cast<std::uint8_t
>(esiBinary.at(address));
89 getU16(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
91 if (esiBinary.size() <
static_cast<std::size_t
>(address + 2))
93 const std::uint16_t byteSize = 8;
94 return static_cast<std::uint16_t
>(esiBinary.at(address)) &
95 (
static_cast<std::uint16_t
>(esiBinary.at(address + 1)) << byteSize);
99 get16(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
101 auto unsignedValue =
getU16(esiBinary, address);
102 return *
reinterpret_cast<std::int16_t*
>(&unsignedValue);
106 getU16W(
const std::vector<std::byte>& esiBinary, std::uint16_t wordAddress)
108 return getU16(esiBinary, wordAddress * 2);
112 getU32(
const std::vector<std::byte>& esiBinary, std::uint16_t address)
114 if (esiBinary.size() <
static_cast<std::size_t
>(address + 4))
116 const auto byteSize = 8;
117 return static_cast<std::uint32_t
>(esiBinary.at(address)) +
118 (
static_cast<std::uint32_t
>(esiBinary.at(address + 1)) << byteSize) +
119 (
static_cast<std::uint32_t
>(esiBinary.at(address + 2)) << 2 * byteSize) +
120 (
static_cast<std::uint32_t
>(esiBinary.at(address + 3)) << 3 * byteSize);
124 getU32W(
const std::vector<std::byte>& esiBinary, std::uint16_t wordAddress)
126 return getU32(esiBinary, wordAddress * 2);
134 std::uint16_t categoryOffset = 0x0040;
135 auto categoryType =
getU16W(esiBinary, categoryOffset);
137 categoryType &= (1 << 15) - 1;
138 auto categorySize =
getU16W(esiBinary, categoryOffset + 1);
139 while (categoryType != 0x7fff)
141 switch (categoryType)
149 esiData.strings =
parseStrings(esiBinary, categoryOffset + 2);
157 esiData.general =
parseGeneral(esiBinary, categoryOffset + 2);
161 esiData.fmmu =
parseFMMU(esiBinary, categoryOffset + 2, categorySize);
165 esiData.syncM =
parseSyncM(esiBinary, categoryOffset + 2, categorySize);
169 esiData.txPDO =
parsePDOs(esiBinary, categoryOffset + 2, categorySize);
173 esiData.rxPDO =
parsePDOs(esiBinary, categoryOffset + 2, categorySize);
177 categoryOffset += 2 + categorySize;
178 categoryType =
getU16W(esiBinary, categoryOffset);
180 categoryType &= (1 << 15) - 1;
181 categorySize =
getU16W(esiBinary, categoryOffset + 1);
214 std::vector<std::string>
217 std::vector<std::string> strings;
218 auto nStrings =
getU8(esiBinary, 2 * wordOffset);
219 strings.reserve(nStrings);
220 std::uint16_t currentOffset = 2 * wordOffset + 1;
221 for (
auto i = 0; i < nStrings; ++i)
225 len =
static_cast<std::uint8_t
>(esiBinary.at(currentOffset));
227 if (currentOffset + len > esiBinary.size())
228 ARMARX_FATAL <<
"The ESI binary ended unexpectedly while reading a string!";
229 tmp.assign(
reinterpret_cast<const char*
>(&esiBinary[currentOffset]), len);
230 strings.emplace_back(tmp);
231 currentOffset += len;
240 std::uint16_t offset = 2 * wordOffset;
242 esiGeneral.
imgIdx =
getU8(esiBinary, offset + 0x0001);
251 esiGeneral.
flags =
getU8(esiBinary, offset + 0x000b);
260 std::uint16_t wordOffset,
263 std::uint16_t count = 2 * len;
265 esiFmmu.reserve(count);
266 for (std::uint16_t i = 0; i < count; ++i)
268 esiFmmu.emplace_back(
getU8(esiBinary, 2 * wordOffset + i));
275 std::uint16_t wordOffset,
278 const std::uint16_t syncMElementLen = 8;
279 const std::uint16_t count = 2 * len / syncMElementLen;
281 esiSyncM.reserve(count);
282 std::uint16_t currentOffset = 2 * wordOffset;
283 for (
size_t i = 0; i < count; ++i)
287 elem.
length =
getU16(esiBinary, currentOffset + 0x0002);
292 esiSyncM.emplace_back(elem);
293 currentOffset += syncMElementLen;
298 std::vector<ESIPDOObject>
300 std::uint16_t wordOffset,
303 std::vector<ESIPDOObject> esiPDOs;
304 std::uint16_t currentOffset = 2 * wordOffset;
305 while (currentOffset < 2 * (wordOffset + len))
312 pdoObject.
nameIdx =
getU8(esiBinary, currentOffset + 0x0005);
313 pdoObject.
flags =
getU16(esiBinary, currentOffset + 0x0006);
316 for (
int i = 0; i < pdoObject.
entryCount; ++i)
319 pdoEntry.
index =
getU16(esiBinary, currentOffset + 0x0000);
320 pdoEntry.
subIndex =
getU8(esiBinary, currentOffset + 0x0002);
321 pdoEntry.
nameIdx =
getU8(esiBinary, currentOffset + 0x0003);
322 pdoEntry.
dataType =
getU8(esiBinary, currentOffset + 0x0004);
324 pdoEntry.
flags =
getU16(esiBinary, currentOffset + 0x0006);
325 pdoObject.
entries.emplace_back(pdoEntry);
328 esiPDOs.emplace_back(pdoObject);