Subversion Repositories HomeAutomation

Rev

Rev 1916 | Rev 2004 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1642 runge 1
/*
1987 runge 2
 *
1642 runge 3
 *  Copyright (C) 2010  Mattias Runge
1987 runge 4
 *
1642 runge 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.
1987 runge 9
 *
1642 runge 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.
1987 runge 14
 *
1642 runge 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.
1987 runge 18
 *
1642 runge 19
 */
20
 
21
#include "Code.h"
22
 
23
#include <fstream>
1987 runge 24
#include <string>
25
#include <streambuf>
1642 runge 26
#include <stdexcept>
27
#include <algorithm>
28
 
29
#include <boost/algorithm/string.hpp>
30
 
31
#include "common/common.h"
1987 runge 32
#include "common/log.h"
1642 runge 33
 
34
namespace atom {
35
namespace control {
36
 
37
#define MAX_BUFFER_SIZE  5200000
1987 runge 38
 
1642 runge 39
// Intel HEX record types
40
#define INTELHEX_RT_DATA 0x00
41
#define INTELHEX_RT_END  0x01
1987 runge 42
 
43
static const std::string log_module_ = "control::code";
44
 
45
Code::Code()
1642 runge 46
{
1987 runge 47
  LOG_DEBUG_ENTER;
48
 
49
  this->Reset();
50
  //this->data_.insert(this->data_.begin(), 0xFF, MAX_BUFFER_SIZE);
51
 
52
  LOG_DEBUG_EXIT;
1642 runge 53
}
54
 
55
Code::~Code()
56
{
1987 runge 57
  LOG_DEBUG_ENTER;
58
  LOG_DEBUG_EXIT;
1642 runge 59
}
60
 
61
void Code::Reset()
62
{
1987 runge 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;
1642 runge 70
}
71
 
72
void Code::CalculateChecksum()
73
{
1987 runge 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++)
1642 runge 83
    {
1987 runge 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
      }
1642 runge 92
    }
1987 runge 93
  }
94
 
95
  this->checksum_ &= 0xFFFF;
96
 
97
  LOG_DEBUG_EXIT;
1642 runge 98
}
99
 
100
void Code::AddByte(unsigned char byte)
101
{
1987 runge 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;
1642 runge 113
}
114
 
115
bool Code::LoadIntelHexFile(std::string filename)
116
{
1987 runge 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;
1642 runge 135
}
136
 
137
bool Code::ParseIntelHex(std::string data)
138
{
1987 runge 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]);
1642 runge 154
 
1987 runge 155
    if (lines[n].length() >= 11 && lines[n][0] == ':')
1642 runge 156
    {
1987 runge 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:
1642 runge 170
        {
1987 runge 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;
1642 runge 182
        }
1987 runge 183
        case INTELHEX_RT_END:
184
        {
185
          this->is_valid_ = true;
186
          break;
187
        }
188
      }
1642 runge 189
    }
1987 runge 190
  }
1642 runge 191
 
1987 runge 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_;
1642 runge 202
}
203
 
204
unsigned int Code::GetAddressLower()
205
{
1987 runge 206
  LOG_DEBUG_ENTER;
207
  LOG_DEBUG_EXIT;
208
 
209
  return this->address_lower_;
1642 runge 210
}
211
 
212
unsigned int Code::GetAddressUpper()
213
{
1987 runge 214
  LOG_DEBUG_ENTER;
215
  LOG_DEBUG_EXIT;
216
 
217
  return this->address_upper_;
1642 runge 218
}
219
 
220
unsigned char Code::GetByte(unsigned int address)
221
{
1987 runge 222
  LOG_DEBUG_ENTER;
223
  LOG_DEBUG_EXIT;
224
 
225
  return this->data_[address];
1642 runge 226
}
227
 
228
unsigned int Code::GetChecksum()
229
{
1987 runge 230
  LOG_DEBUG_ENTER;
231
  LOG_DEBUG_EXIT;
232
 
233
  return this->checksum_;
1642 runge 234
}
235
 
236
unsigned int Code::GetLength()
237
{
1987 runge 238
  LOG_DEBUG_ENTER;
239
  LOG_DEBUG_EXIT;
240
 
241
  return this->address_upper_ - this->address_lower_ + 1;
1642 runge 242
}
243
 
244
bool Code::IsValid()
245
{
1987 runge 246
  LOG_DEBUG_ENTER;
247
  LOG_DEBUG_EXIT;
248
 
249
  return this->is_valid_;
1642 runge 250
}
251
 
252
}; // namespace control
253
}; // namespace atom