Subversion Repositories HomeAutomation

Rev

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