Subversion Repositories HomeAutomation

Rev

Rev 1987 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  *
  3.  *  Copyright (C) 2010  Mattias Runge
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License along
  16.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  17.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18.  *
  19.  */
  20.  
  21. #include "Code.h"
  22.  
  23. #include <fstream>
  24. #include <string>
  25. #include <streambuf>
  26. #include <stdexcept>
  27. #include <algorithm>
  28.  
  29. #include <boost/algorithm/string.hpp>
  30.  
  31. #include "common/common.h"
  32. #include "common/log.h"
  33.  
  34. namespace atom {
  35. namespace control {
  36.  
  37. #define MAX_BUFFER_SIZE  5200000
  38.  
  39. // Intel HEX record types
  40. #define INTELHEX_RT_DATA 0x00
  41. #define INTELHEX_RT_END  0x01
  42.  
  43. static const std::string log_module_ = "control::code";
  44.  
  45. Code::Code()
  46. {
  47.   LOG_DEBUG_ENTER;
  48.  
  49.   this->Reset();
  50.   //this->data_.insert(this->data_.begin(), 0xFF, MAX_BUFFER_SIZE);
  51.  
  52.   LOG_DEBUG_EXIT;
  53. }
  54.  
  55. Code::~Code()
  56. {
  57.   LOG_DEBUG_ENTER;
  58.   LOG_DEBUG_EXIT;
  59. }
  60.  
  61. void Code::Reset()
  62. {
  63.   LOG_DEBUG_ENTER;
  64.  
  65.   this->address_lower_  = MAX_BUFFER_SIZE;
  66.   this->address_upper_  = 0;
  67.   this->is_valid_       = false;
  68.  
  69.   this->data_.reserve(MAX_BUFFER_SIZE);
  70.   std::fill(this->data_.begin(), this->data_.begin() + MAX_BUFFER_SIZE, 0xFF);
  71.  
  72.   LOG_DEBUG_EXIT;
  73. }
  74.  
  75. void Code::CalculateChecksum()
  76. {
  77.   LOG_DEBUG_ENTER;
  78.  
  79.   this->checksum_ = 0;
  80.  
  81.   for (unsigned int n = this->address_lower_; n <= this->address_upper_; n++)
  82.   {
  83.     this->checksum_ ^= this->data_[n];
  84.  
  85.     for (unsigned int c = 0; c < 8; c++)
  86.     {
  87.       if ((this->checksum_ & 1) != 0)
  88.       {
  89.         this->checksum_ = (this->checksum_ >> 1) ^ 0xA001;
  90.       }
  91.       else
  92.       {
  93.         this->checksum_ = (this->checksum_ >> 1);
  94.       }
  95.     }
  96.   }
  97.  
  98.   this->checksum_ &= 0xFFFF;
  99.  
  100.   LOG_DEBUG_EXIT;
  101. }
  102.  
  103. void Code::AddByte(unsigned char byte)
  104. {
  105.   LOG_DEBUG_ENTER;
  106.  
  107.   this->data_.push_back(byte);
  108.  
  109.   this->address_lower_  = 0;
  110.   this->address_upper_  = this->data_.size();
  111.   this->is_valid_       = true;
  112.  
  113.   this->CalculateChecksum();
  114.  
  115.   LOG_DEBUG_EXIT;
  116. }
  117.  
  118. bool Code::LoadIntelHexFile(std::string filename)
  119. {
  120.   LOG_DEBUG_ENTER;
  121.  
  122.   std::ifstream file(filename.data());
  123.  
  124.   if (!file.is_open())
  125.   {
  126.     return false;
  127.   }
  128.  
  129.   std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
  130.  
  131.   file.close();
  132.  
  133.   bool result = this->ParseIntelHex(buffer);
  134.  
  135.   LOG_DEBUG_EXIT;
  136.  
  137.   return result;
  138. }
  139.  
  140. bool Code::ParseIntelHex(std::string data)
  141. {
  142.   LOG_DEBUG_ENTER;
  143.  
  144.   common::StringList lines;
  145.  
  146.   boost::algorithm::split(lines, data, boost::is_any_of("\n"), boost::algorithm::token_compress_on);
  147.  
  148.   this->Reset();
  149.  
  150.   unsigned int byte_count;
  151.   unsigned int addess;
  152.   unsigned int record_type;
  153.  
  154.   for (unsigned int n = 0; n < lines.size(); n++)
  155.   {
  156.     log::Debug(log_module_, "line[" + boost::lexical_cast<std::string> (n) + "]=" + lines[n]);
  157.    
  158.     if (lines[n].length() >= 11 && lines[n][0] == ':')
  159.     {
  160.       //log::Debug(log_module_, "A:" + lines[n].substr(1, 2));
  161.       byte_count = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(1, 2)); //common::FromHex(lines[n].substr(1, 2));
  162.       log::Debug(log_module_, "byte_count=" + boost::lexical_cast<std::string>(byte_count));
  163.      
  164.       //log::Debug(log_module_, "B:" + lines[n].substr(3, 4));
  165.       addess = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(3, 4)) & 0xFFFF; //common::FromHex(lines[n].substr(3, 4)) & 0xFFFF;
  166.       log::Debug(log_module_, "addess=" +  boost::lexical_cast<std::string> (addess));
  167.      
  168.       record_type = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(7, 2)); //common::FromHex(lines[n].substr(7, 2));
  169.  
  170.       switch (record_type)
  171.       {
  172.         case INTELHEX_RT_DATA:
  173.         {
  174.           this->address_lower_ = std::min(this->address_lower_, addess);
  175.           this->address_upper_ = std::max(this->address_upper_, addess + byte_count - 1);
  176.  
  177.           for (unsigned int c = 0; c < byte_count; c++)
  178.           {
  179.             //log::Debug(log_module_, "D:" + lines[n].substr(c * 2 + 9, 2));
  180.             this->data_[addess + c] = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(c * 2 + 9, 2));
  181.             //this->data[addess + c] = (unsigned char)common::FromHex(lines[n].substr(c * 2 + 9, 2));
  182.           }
  183.  
  184.           break;
  185.         }
  186.         case INTELHEX_RT_END:
  187.         {
  188.           this->is_valid_ = true;
  189.           break;
  190.         }
  191.       }
  192.     }
  193.   }
  194.  
  195.   if (this->is_valid_)
  196.   {
  197.     this->CalculateChecksum();
  198.  
  199.     log::Info(log_module_, "Successfully parsed Intel HEX file.");
  200.   }
  201.  
  202.   LOG_DEBUG_EXIT;
  203.  
  204.   return this->is_valid_;
  205. }
  206.  
  207. unsigned int Code::GetAddressLower()
  208. {
  209.   LOG_DEBUG_ENTER;
  210.   LOG_DEBUG_EXIT;
  211.  
  212.   return this->address_lower_;
  213. }
  214.  
  215. unsigned int Code::GetAddressUpper()
  216. {
  217.   LOG_DEBUG_ENTER;
  218.   LOG_DEBUG_EXIT;
  219.  
  220.   return this->address_upper_;
  221. }
  222.  
  223. unsigned char Code::GetByte(unsigned int address)
  224. {
  225.   LOG_DEBUG_ENTER;
  226.   LOG_DEBUG_EXIT;
  227.  
  228.   return this->data_[address];
  229. }
  230.  
  231. unsigned int Code::GetChecksum()
  232. {
  233.   LOG_DEBUG_ENTER;
  234.   LOG_DEBUG_EXIT;
  235.  
  236.   return this->checksum_;
  237. }
  238.  
  239. unsigned int Code::GetLength()
  240. {
  241.   LOG_DEBUG_ENTER;
  242.   LOG_DEBUG_EXIT;
  243.  
  244.   return this->address_upper_ - this->address_lower_ + 1;
  245. }
  246.  
  247. bool Code::IsValid()
  248. {
  249.   LOG_DEBUG_ENTER;
  250.   LOG_DEBUG_EXIT;
  251.  
  252.   return this->is_valid_;
  253. }
  254.  
  255. }; // namespace control
  256. }; // namespace atom
  257.