Subversion Repositories HomeAutomation

Rev

Rev 1642 | Rev 1987 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

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