Subversion Repositories HomeAutomation

Rev

Rev 2004 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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