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 <stdexcept>
  25. #include <algorithm>
  26.  
  27. #include <boost/algorithm/string.hpp>
  28.  
  29. #include "common/common.h"
  30.  
  31. namespace atom {
  32. namespace control {
  33.  
  34. #define MAX_BUFFER_SIZE  5200000
  35.    
  36. // Intel HEX record types
  37. #define INTELHEX_RT_DATA 0x00
  38. #define INTELHEX_RT_END  0x01
  39.    
  40. Code::Code() : LOG("control::code"), data_(MAX_BUFFER_SIZE)
  41. {
  42.     this->Reset();
  43. }
  44.  
  45. Code::~Code()
  46. {
  47.  
  48. }
  49.  
  50. void Code::Reset()
  51. {
  52.     this->address_lower_ = MAX_BUFFER_SIZE;
  53.     this->address_upper_ = 0;
  54.     this->data_.SetSize(0);
  55.     this->data_.Fill(0xFF);
  56.     this->is_valid_ = false;
  57. }
  58.  
  59. void Code::CalculateChecksum()
  60. {
  61.     this->checksum_ = 0;
  62.    
  63.     for (unsigned int n = this->address_lower_; n <= this->address_upper_; n++)
  64.     {
  65.         this->checksum_ ^= this->data_[n];
  66.        
  67.         for (unsigned int c = 0; c < 8; c++)
  68.         {
  69.             if ((this->checksum_ & 1) != 0)
  70.             {
  71.                 this->checksum_ = (this->checksum_ >> 1) ^ 0xA001;
  72.             }
  73.             else
  74.             {
  75.                 this->checksum_ = (this->checksum_ >> 1);
  76.             }
  77.         }
  78.     }
  79.    
  80.     this->checksum_ &= 0xFFFF;
  81. }
  82.  
  83. void Code::AddByte(unsigned char byte)
  84. {
  85.     this->data_.Append(byte);
  86.    
  87.     this->address_lower_ = 0;
  88.     this->address_upper_ = this->data_.GetSize() - 1;
  89.     this->is_valid_ = true;
  90.    
  91.     this->CalculateChecksum();
  92. }
  93.  
  94. bool Code::LoadIntelHexFile(std::string filename)
  95. {
  96.     std::ifstream file(filename.data());
  97.    
  98.     if (!file.is_open())
  99.     {
  100.         return false;
  101.     }
  102.    
  103.     std::string buffer = "";
  104.     std::string line;
  105.    
  106.     while (!file.eof())
  107.     {
  108.         std::getline(file, line);
  109.        
  110.         if (file.eof())
  111.         {
  112.             break;
  113.         }
  114.        
  115.         buffer += line + "\n";
  116.     }
  117.    
  118.     file.close();
  119.    
  120.     return this->ParseIntelHex(buffer);
  121. }
  122.  
  123. bool Code::ParseIntelHex(std::string data)
  124. {
  125.     common::StringList lines;
  126.    
  127.     boost::algorithm::split(lines, data, boost::is_any_of("\n"), boost::algorithm::token_compress_on);
  128.    
  129.     this->Reset();
  130.    
  131.     unsigned int byte_count;
  132.     unsigned int addess;
  133.     unsigned int record_type;
  134.    
  135.     for (unsigned int n = 0; n < lines.size(); n++)
  136.     {
  137.         LOG.Debug("line[" + boost::lexical_cast<std::string>(n) + "]=" + lines[n]);
  138.         if (lines[n].length() >= 11 && lines[n][0] == ':')
  139.         {
  140.             //LOG.Debug("A:" + lines[n].substr(1, 2));
  141.             byte_count = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(1, 2));//common::FromHex(lines[n].substr(1, 2));
  142.             LOG.Debug("byte_count=" + boost::lexical_cast<std::string>(byte_count));
  143.             //LOG.Debug("B:" + lines[n].substr(3, 4));
  144.             addess = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(3, 4)) & 0xFFFF;//common::FromHex(lines[n].substr(3, 4)) & 0xFFFF;
  145.             LOG.Debug("addess=" +  boost::lexical_cast<std::string>(addess));
  146.             record_type = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(7, 2));//common::FromHex(lines[n].substr(7, 2));
  147.            
  148.             switch (record_type)
  149.             {
  150.                 case INTELHEX_RT_DATA:
  151.                 {
  152.                     this->address_lower_ = std::min(this->address_lower_, addess);
  153.                     this->address_upper_ = std::max(this->address_upper_, addess + byte_count - 1);
  154.                    
  155.                     for (unsigned int c = 0; c < byte_count; c++)
  156.                     {
  157.                         //LOG.Debug("D:" + lines[n].substr(c * 2 + 9, 2));
  158.                         this->data_[addess + c] = boost::lexical_cast<common::HexTo<unsigned int> >("0x" + lines[n].substr(c * 2 + 9, 2));
  159.                         //this->data[addess + c] = (unsigned char)common::FromHex(lines[n].substr(c * 2 + 9, 2));
  160.                     }
  161.                    
  162.                     break;
  163.                 }
  164.                 case INTELHEX_RT_END:
  165.                 {
  166.                     this->is_valid_ = true;
  167.                     break;
  168.                 }  
  169.             }
  170.         }
  171.     }
  172.  
  173.     if (this->is_valid_)
  174.     {
  175.        this->CalculateChecksum();
  176.        
  177.         LOG.Info("Successfully parsed Intel HEX file.");
  178.     }
  179.    
  180.     return this->is_valid_;
  181. }
  182.  
  183. unsigned int Code::GetAddressLower()
  184. {
  185.     return this->address_lower_;
  186. }
  187.  
  188. unsigned int Code::GetAddressUpper()
  189. {
  190.     return this->address_upper_;
  191. }
  192.  
  193. unsigned char Code::GetByte(unsigned int address)
  194. {
  195.     return this->data_[address];
  196. }
  197.  
  198. unsigned int Code::GetChecksum()
  199. {
  200.     return this->checksum_;
  201. }
  202.  
  203. unsigned int Code::GetLength()
  204. {
  205.     return this->address_upper_ - this->address_lower_ + 1;
  206. }
  207.  
  208. bool Code::IsValid()
  209. {
  210.     return this->is_valid_;
  211. }
  212.  
  213. }; // namespace control
  214. }; // namespace atom
  215.