Subversion Repositories HomeAutomation

Rev

Rev 1916 | 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.   LOG_DEBUG_EXIT;
  70. }
  71.  
  72. void Code::CalculateChecksum()
  73. {
  74.   LOG_DEBUG_ENTER;
  75.  
  76.   this->checksum_ = 0;
  77.  
  78.   for (unsigned int n = this->address_lower_; n <= this->address_upper_; n++)
  79.   {
  80.     this->checksum_ ^= this->data_[n];
  81.  
  82.     for (unsigned int c = 0; c < 8; c++)
  83.     {
  84.       if ((this->checksum_ & 1) != 0)
  85.       {
  86.         this->checksum_ = (this->checksum_ >> 1) ^ 0xA001;
  87.       }
  88.       else
  89.       {
  90.         this->checksum_ = (this->checksum_ >> 1);
  91.       }
  92.     }
  93.   }
  94.  
  95.   this->checksum_ &= 0xFFFF;
  96.  
  97.   LOG_DEBUG_EXIT;
  98. }
  99.  
  100. void Code::AddByte(unsigned char byte)
  101. {
  102.   LOG_DEBUG_ENTER;
  103.  
  104.   this->data_.push_back(byte);
  105.  
  106.   this->address_lower_  = 0;
  107.   this->address_upper_  = this->data_.size();
  108.   this->is_valid_       = true;
  109.  
  110.   this->CalculateChecksum();
  111.  
  112.   LOG_DEBUG_EXIT;
  113. }
  114.  
  115. bool Code::LoadIntelHexFile(std::string filename)
  116. {
  117.   LOG_DEBUG_ENTER;
  118.  
  119.   std::ifstream file(filename.data());
  120.  
  121.   if (!file.is_open())
  122.   {
  123.     return false;
  124.   }
  125.  
  126.   std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
  127.  
  128.   file.close();
  129.  
  130.   bool result = this->ParseIntelHex(buffer);
  131.  
  132.   LOG_DEBUG_EXIT;
  133.  
  134.   return result;
  135. }
  136.  
  137. bool Code::ParseIntelHex(std::string data)
  138. {
  139.   LOG_DEBUG_ENTER;
  140.  
  141.   common::StringList lines;
  142.  
  143.   boost::algorithm::split(lines, data, boost::is_any_of("\n"), boost::algorithm::token_compress_on);
  144.  
  145.   this->Reset();
  146.  
  147.   unsigned int byte_count;
  148.   unsigned int addess;
  149.   unsigned int record_type;
  150.  
  151.   for (unsigned int n = 0; n < lines.size(); n++)
  152.   {
  153.     log::Debug(log_module_, "line[" + boost::lexical_cast<std::string> (n) + "]=" + lines[n]);
  154.    
  155.     if (lines[n].length() >= 11 && lines[n][0] == ':')
  156.     {
  157.       //log::Debug(log_module_, "A:" + lines[n].substr(1, 2));
  158.       byte_count = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(1, 2)); //common::FromHex(lines[n].substr(1, 2));
  159.       log::Debug(log_module_, "byte_count=" + boost::lexical_cast<std::string>(byte_count));
  160.      
  161.       //log::Debug(log_module_, "B:" + lines[n].substr(3, 4));
  162.       addess = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(3, 4)) & 0xFFFF; //common::FromHex(lines[n].substr(3, 4)) & 0xFFFF;
  163.       log::Debug(log_module_, "addess=" +  boost::lexical_cast<std::string> (addess));
  164.      
  165.       record_type = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(7, 2)); //common::FromHex(lines[n].substr(7, 2));
  166.  
  167.       switch (record_type)
  168.       {
  169.         case INTELHEX_RT_DATA:
  170.         {
  171.           this->address_lower_ = std::min(this->address_lower_, addess);
  172.           this->address_upper_ = std::max(this->address_upper_, addess + byte_count - 1);
  173.  
  174.           for (unsigned int c = 0; c < byte_count; c++)
  175.           {
  176.             //log::Debug(log_module_, "D:" + lines[n].substr(c * 2 + 9, 2));
  177.             this->data_[addess + c] = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(c * 2 + 9, 2));
  178.             //this->data[addess + c] = (unsigned char)common::FromHex(lines[n].substr(c * 2 + 9, 2));
  179.           }
  180.  
  181.           break;
  182.         }
  183.         case INTELHEX_RT_END:
  184.         {
  185.           this->is_valid_ = true;
  186.           break;
  187.         }
  188.       }
  189.     }
  190.   }
  191.  
  192.   if (this->is_valid_)
  193.   {
  194.     this->CalculateChecksum();
  195.  
  196.     log::Info(log_module_, "Successfully parsed Intel HEX file.");
  197.   }
  198.  
  199.   LOG_DEBUG_EXIT;
  200.  
  201.   return this->is_valid_;
  202. }
  203.  
  204. unsigned int Code::GetAddressLower()
  205. {
  206.   LOG_DEBUG_ENTER;
  207.   LOG_DEBUG_EXIT;
  208.  
  209.   return this->address_lower_;
  210. }
  211.  
  212. unsigned int Code::GetAddressUpper()
  213. {
  214.   LOG_DEBUG_ENTER;
  215.   LOG_DEBUG_EXIT;
  216.  
  217.   return this->address_upper_;
  218. }
  219.  
  220. unsigned char Code::GetByte(unsigned int address)
  221. {
  222.   LOG_DEBUG_ENTER;
  223.   LOG_DEBUG_EXIT;
  224.  
  225.   return this->data_[address];
  226. }
  227.  
  228. unsigned int Code::GetChecksum()
  229. {
  230.   LOG_DEBUG_ENTER;
  231.   LOG_DEBUG_EXIT;
  232.  
  233.   return this->checksum_;
  234. }
  235.  
  236. unsigned int Code::GetLength()
  237. {
  238.   LOG_DEBUG_ENTER;
  239.   LOG_DEBUG_EXIT;
  240.  
  241.   return this->address_upper_ - this->address_lower_ + 1;
  242. }
  243.  
  244. bool Code::IsValid()
  245. {
  246.   LOG_DEBUG_ENTER;
  247.   LOG_DEBUG_EXIT;
  248.  
  249.   return this->is_valid_;
  250. }
  251.  
  252. }; // namespace control
  253. }; // namespace atom
  254.