Subversion Repositories HomeAutomation

Rev

Rev 1987 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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