forked from iNavFlight/inav
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintelhex.rb
100 lines (84 loc) · 2.91 KB
/
intelhex.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
##
## This file is part of INAV.
##
## INAV is free software. You can redistribute this software
## and/or modify this software under the terms of the
## GNU General Public License as published by the Free Software
## Foundation, either version 3 of the License, or (at your option)
## any later version.
##
## INAV is distributed in the hope that they will be
## useful, but WITHOUT ANY WARRANTY; without even the implied
## warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this software.
##
## If not, see <http://www.gnu.org/licenses/>.
##
class IntelHex
class Section < Struct.new(:address, :io); end
def initialize address = 0, bin_io = nil, start_address = nil
@sections = Array.new
@start_address = start_address == true ? address : start_address
add_section address, bin_io if bin_io
end
def add_section address, io
sections << Section.new(address, io)
end
def write io
sections.each { |section| write_section section, io }
write_start_linear_address start_address, io if start_address
write_end_of_file io
nil
end
attr_reader :sections
attr_accessor :start_address
private
def calc_crc address, record_type, data
sum = 0
sum += (address & 0xFF00) >> 8
sum += (address & 0x00FF)
sum += record_type
if data.is_a? Integer
sum += data > 0xFFFF ? 4 : 2
sum += (data & 0xFF000000) >> 24
sum += (data & 0x00FF0000) >> 16
sum += (data & 0x0000FF00) >> 8
sum += (data & 0x000000FF)
else
sum += data.bytesize
sum += data.each_byte.sum
end
((sum ^ 0xFF) + 1) & 0xFF
end
def write_end_of_file io
io.puts ":00000001FF"
end
def write_start_linear_address address, io
crc = calc_crc 0, 5, address
io.printf ":04000005%08X%02X\n", address, crc
end
def write_extended_linear_address address, io
address_msw = (address & 0xffff0000) >> 16
crc = calc_crc 0, 4, address_msw
io.printf ":02000004%04X%02X\n", address_msw, crc
end
def write_data address, data, io
address &= 0xFFFF
hex_data = data.each_byte.map { |byte| "%02X" % byte }.join
crc = calc_crc address, 0, data
io.printf ":%02X%04X00%s%02X\n", data.bytesize, address, hex_data, crc
end
def write_section section, io
previous_address = 0
address = section.address
while data = section.io.read(16)
write_extended_linear_address address, io if (previous_address & 0xFFFF0000) != (address & 0xFFFF0000)
previous_address = address
write_data address, data, io
address += data.bytesize
end
end
end