Subversion Repositories HomeAutomation

Rev

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

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