Subversion Repositories HomeAutomation

Rev

Rev 1916 | Rev 2004 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 1916 Rev 1987
Line 1... Line 1...
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>
-
 
25
#include <streambuf>
24
#include <stdexcept>
26
#include <stdexcept>
25
#include <algorithm>
27
#include <algorithm>
26
 
28
 
27
#include <boost/algorithm/string.hpp>
29
#include <boost/algorithm/string.hpp>
28
 
30
 
29
#include "common/common.h"
31
#include "common/common.h"
-
 
32
#include "common/log.h"
30
 
33
 
31
namespace atom {
34
namespace atom {
32
namespace control {
35
namespace control {
33
 
36
 
34
#define MAX_BUFFER_SIZE  5200000
37
#define MAX_BUFFER_SIZE  5200000
35
   
38
 
36
// Intel HEX record types
39
// Intel HEX record types
37
#define INTELHEX_RT_DATA 0x00
40
#define INTELHEX_RT_DATA 0x00
38
#define INTELHEX_RT_END  0x01
41
#define INTELHEX_RT_END  0x01
39
   
42
 
40
Code::Code() : data_(MAX_BUFFER_SIZE), LOG("control::code")
43
static const std::string log_module_ = "control::code";
-
 
44
 
-
 
45
Code::Code()
41
{
46
{
-
 
47
  LOG_DEBUG_ENTER;
-
 
48
 
42
    this->Reset();
49
  this->Reset();
-
 
50
  //this->data_.insert(this->data_.begin(), 0xFF, MAX_BUFFER_SIZE);
-
 
51
 
-
 
52
  LOG_DEBUG_EXIT;
43
}
53
}
44
 
54
 
45
Code::~Code()
55
Code::~Code()
46
{
56
{
47
 
-
 
-
 
57
  LOG_DEBUG_ENTER;
-
 
58
  LOG_DEBUG_EXIT;
48
}
59
}
49
 
60
 
50
void Code::Reset()
61
void Code::Reset()
51
{
62
{
-
 
63
  LOG_DEBUG_ENTER;
-
 
64
 
52
    this->address_lower_ = MAX_BUFFER_SIZE;
65
  this->address_lower_  = MAX_BUFFER_SIZE;
53
    this->address_upper_ = 0;
66
  this->address_upper_  = 0;
54
    this->data_.SetSize(0);
67
  this->is_valid_       = false;
55
    this->data_.Fill(0xFF);
68
 
56
    this->is_valid_ = false;
69
  LOG_DEBUG_EXIT;
57
}
70
}
58
 
71
 
59
void Code::CalculateChecksum()
72
void Code::CalculateChecksum()
60
{
73
{
-
 
74
  LOG_DEBUG_ENTER;
-
 
75
 
61
    this->checksum_ = 0;
76
  this->checksum_ = 0;
62
   
77
 
63
    for (unsigned int n = this->address_lower_; n <= this->address_upper_; n++)
78
  for (unsigned int n = this->address_lower_; n <= this->address_upper_; n++)
64
    {
79
  {
65
        this->checksum_ ^= this->data_[n];
80
    this->checksum_ ^= this->data_[n];
66
       
81
 
67
        for (unsigned int c = 0; c < 8; c++)
82
    for (unsigned int c = 0; c < 8; c++)
68
        {
83
    {
69
            if ((this->checksum_ & 1) != 0)
84
      if ((this->checksum_ & 1) != 0)
70
            {
85
      {
71
                this->checksum_ = (this->checksum_ >> 1) ^ 0xA001;
86
        this->checksum_ = (this->checksum_ >> 1) ^ 0xA001;
72
            }
87
      }
73
            else
88
      else
74
            {
89
      {
75
                this->checksum_ = (this->checksum_ >> 1);
90
        this->checksum_ = (this->checksum_ >> 1);
76
            }
-
 
77
        }
91
      }
78
    }
92
    }
79
   
93
  }
-
 
94
 
80
    this->checksum_ &= 0xFFFF;
95
  this->checksum_ &= 0xFFFF;
-
 
96
 
-
 
97
  LOG_DEBUG_EXIT;
81
}
98
}
82
 
99
 
83
void Code::AddByte(unsigned char byte)
100
void Code::AddByte(unsigned char byte)
84
{
101
{
-
 
102
  LOG_DEBUG_ENTER;
-
 
103
 
85
    this->data_.Append(byte);
104
  this->data_.push_back(byte);
86
   
105
 
87
    this->address_lower_ = 0;
106
  this->address_lower_  = 0;
88
    this->address_upper_ = this->data_.GetSize() - 1;
107
  this->address_upper_  = this->data_.size();
89
    this->is_valid_ = true;
108
  this->is_valid_       = true;
90
   
109
 
91
    this->CalculateChecksum();
110
  this->CalculateChecksum();
-
 
111
 
-
 
112
  LOG_DEBUG_EXIT;
92
}
113
}
-
 
114
 
-
 
115
bool Code::LoadIntelHexFile(std::string filename)
-
 
116
{
-
 
117
  LOG_DEBUG_ENTER;
-
 
118
 
-
 
119
  std::ifstream file(filename.data());
93
 
120
 
94
bool Code::LoadIntelHexFile(std::string filename)
-
 
95
{
-
 
96
    std::ifstream file(filename.data());
-
 
97
   
-
 
98
    if (!file.is_open())
121
  if (!file.is_open())
99
    {
122
  {
100
        return false;
123
    return false;
101
    }
124
  }
102
   
125
 
103
    std::string buffer = "";
126
  std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
104
    std::string line;
-
 
105
   
127
 
106
    while (!file.eof())
128
  file.close();
107
    {
129
 
108
        std::getline(file, line);
130
  bool result = this->ParseIntelHex(buffer);
109
       
-
 
110
        if (file.eof())
-
 
111
        {
-
 
112
            break;
-
 
113
        }
-
 
114
       
-
 
115
        buffer += line + "\n";
-
 
116
    }
-
 
117
   
131
 
118
    file.close();
132
  LOG_DEBUG_EXIT;
119
   
133
 
120
    return this->ParseIntelHex(buffer);
134
  return result;
121
}
135
}
122
 
136
 
123
bool Code::ParseIntelHex(std::string data)
137
bool Code::ParseIntelHex(std::string data)
124
{
138
{
-
 
139
  LOG_DEBUG_ENTER;
-
 
140
 
125
    common::StringList lines;
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]);
126
   
154
   
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++)
155
    if (lines[n].length() >= 11 && lines[n][0] == ':')
136
    {
156
    {
-
 
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));
137
        LOG.Debug("line[" + boost::lexical_cast<std::string>(n) + "]=" + lines[n]);
159
      log::Debug(log_module_, "byte_count=" + boost::lexical_cast<std::string>(byte_count));
-
 
160
     
138
        if (lines[n].length() >= 11 && lines[n][0] == ':')
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:
139
        {
170
        {
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);
171
          this->address_lower_ = std::min(this->address_lower_, addess);
153
                    this->address_upper_ = std::max(this->address_upper_, addess + byte_count - 1);
172
          this->address_upper_ = std::max(this->address_upper_, addess + byte_count - 1);
154
                   
-
 
-
 
173
 
155
                    for (unsigned int c = 0; c < byte_count; c++)
174
          for (unsigned int c = 0; c < byte_count; c++)
156
                    {
175
          {
157
                        //LOG.Debug("D:" + lines[n].substr(c * 2 + 9, 2));
176
            //log::Debug(log_module_, "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));
177
            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));
178
            //this->data[addess + c] = (unsigned char)common::FromHex(lines[n].substr(c * 2 + 9, 2));
160
                    }
-
 
161
                   
-
 
162
                    break;
-
 
163
                }
179
          }
164
                case INTELHEX_RT_END:
-
 
165
                {
-
 
166
                    this->is_valid_ = true;
-
 
167
                    break;
-
 
168
                }  
-
 
-
 
180
 
169
            }
181
          break;
170
        }
182
        }
-
 
183
        case INTELHEX_RT_END:
-
 
184
        {
-
 
185
          this->is_valid_ = true;
-
 
186
          break;
-
 
187
        }
-
 
188
      }
171
    }
189
    }
-
 
190
  }
172
 
191
 
173
    if (this->is_valid_)
192
  if (this->is_valid_)
174
    {
193
  {
175
       this->CalculateChecksum();
194
    this->CalculateChecksum();
176
       
195
 
177
        LOG.Info("Successfully parsed Intel HEX file.");
196
    log::Info(log_module_, "Successfully parsed Intel HEX file.");
178
    }
197
  }
-
 
198
 
-
 
199
  LOG_DEBUG_EXIT;
179
   
200
 
180
    return this->is_valid_;
201
  return this->is_valid_;
181
}
202
}
182
 
203
 
183
unsigned int Code::GetAddressLower()
204
unsigned int Code::GetAddressLower()
184
{
205
{
-
 
206
  LOG_DEBUG_ENTER;
-
 
207
  LOG_DEBUG_EXIT;
-
 
208
 
185
    return this->address_lower_;
209
  return this->address_lower_;
186
}
210
}
187
 
211
 
188
unsigned int Code::GetAddressUpper()
212
unsigned int Code::GetAddressUpper()
189
{
213
{
-
 
214
  LOG_DEBUG_ENTER;
-
 
215
  LOG_DEBUG_EXIT;
-
 
216
 
190
    return this->address_upper_;
217
  return this->address_upper_;
191
}
218
}
192
 
219
 
193
unsigned char Code::GetByte(unsigned int address)
220
unsigned char Code::GetByte(unsigned int address)
194
{
221
{
-
 
222
  LOG_DEBUG_ENTER;
-
 
223
  LOG_DEBUG_EXIT;
-
 
224
 
195
    return this->data_[address];
225
  return this->data_[address];
196
}
226
}
197
 
227
 
198
unsigned int Code::GetChecksum()
228
unsigned int Code::GetChecksum()
199
{
229
{
-
 
230
  LOG_DEBUG_ENTER;
-
 
231
  LOG_DEBUG_EXIT;
-
 
232
 
200
    return this->checksum_;
233
  return this->checksum_;
201
}
234
}
202
 
235
 
203
unsigned int Code::GetLength()
236
unsigned int Code::GetLength()
204
{
237
{
-
 
238
  LOG_DEBUG_ENTER;
-
 
239
  LOG_DEBUG_EXIT;
-
 
240
 
205
    return this->address_upper_ - this->address_lower_ + 1;
241
  return this->address_upper_ - this->address_lower_ + 1;
206
}
242
}
207
 
243
 
208
bool Code::IsValid()
244
bool Code::IsValid()
209
{
245
{
-
 
246
  LOG_DEBUG_ENTER;
-
 
247
  LOG_DEBUG_EXIT;
-
 
248
 
210
    return this->is_valid_;
249
  return this->is_valid_;
211
}
250
}
212
 
251
 
213
}; // namespace control
252
}; // namespace control
214
}; // namespace atom
253
}; // namespace atom