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