#include "ihex_loader.h" #include #include #include #include #include static inline void ltrim(std::string& s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isspace(c); })); } static inline void rtrim(std::string& s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c) { return !std::isspace(c); }).base(), s.end()); } static inline void trim(std::string& s) { ltrim(s); rtrim(s); } uint8_t ihex_loader::calc_crc8(std::string number) const { uint8_t crc8 = 0; for (uint32_t i = 0; i < number.size(); i += 2) { uint8_t byte_x = std::stoi(number.substr(i, 2), nullptr, 16); crc8 += byte_x; } return ((~crc8 + 1) & 0xFF); } bool ihex_loader::check_ihex_crc(std::string line) const { uint8_t line_crc = ihex_loader::calc_crc8(line.substr(1, line.size() - 3)); // skip the initial ':' and leave off the final two characters return (std::stoi(line.substr(line.size() - 2, std::string::npos), nullptr, 16)) == line_crc; } uint8_t ihex_loader::mycrc(std::string line) const { uint8_t crc = 0; for (uint32_t i = 1; i < line.size(); i += 2) { crc += std::stoi(line.substr(i, 2), nullptr, 16); } return ((~crc + 1) & 0xFF); } bool ihex_loader::load_ihex(std::string filename) { std::ifstream ihexfile; ihexfile.open(filename, std::ios::in); if (!ihexfile.is_open()) { std::cout << "Could not open hex file: " << filename << std::endl; } else { uint32_t base_address = 0; uint32_t current_address = 0; uint32_t address = 0; bool first = true; while (!ihexfile.eof()) { std::string newline; std::getline(ihexfile, newline); //std::cout << newline << std::endl; // check that the line is valid trim(newline); if ((newline.size() > 0) && (newline.compare(0, 1, ":") == 0)) { if (check_ihex_crc(newline)) { // this line passes checksum, decode it uint32_t data_length = std::stoi(newline.substr(1, 2), nullptr, 16); uint32_t data_address = std::stoi(newline.substr(3, 4), nullptr, 16); uint32_t data_type = std::stoi(newline.substr(7, 2), nullptr, 16); std::vector data; for (uint32_t i = 0; i < data_length; i++) { data.push_back(std::stoi(newline.substr(9 + (i * 2), 2), nullptr, 16)); } if (data_type == static_cast(IHex_Tags::DataRecord)) { address = base_address + data_address; if (first) { first = false; _start_address = address; current_address = address; } // Fill blanks between last data and this new one if (address > current_address) { std::vector fill_region(address - current_address); _application.insert(_application.end(), fill_region.begin(), fill_region.end()); } // Append the new data _application.insert(_application.end(), data.begin(), data.end()); current_address = address + data_length; } if (data_type == static_cast(IHex_Tags::Eof)) { // End of file, just return // Only way this function can return a successful result return true; } if (data_type == static_cast(IHex_Tags::Esar)) { base_address = (static_cast(data[0]) << 12) + (static_cast(data[1]) << 4); } if (data_type == static_cast(IHex_Tags::Elar)) { base_address = (static_cast(data[0]) << 24) + (static_cast(data[1]) << 16); } if (data_type == static_cast(IHex_Tags::Slar)) { base_address = (static_cast(data[0]) << 24) + (static_cast(data[1]) << 16); } } else { return false; // failed to read file due to bad checksum } } } } return false; }