loading
Generated 2021-04-05T08:10:49-07:00

All Files ( 96.58% covered at 30.03 hits/line )

6 files in total.
234 relevant lines, 226 lines covered and 8 lines missed. ( 96.58% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line
lib/origen_memory_image.rb 100.00 % 43 23 23 0 9.78
lib/origen_memory_image/base.rb 97.62 % 96 42 41 1 45.55
lib/origen_memory_image/binary.rb 87.50 % 69 32 28 4 53.84
lib/origen_memory_image/hex.rb 100.00 % 60 30 30 0 27.27
lib/origen_memory_image/intel_hex.rb 94.64 % 98 56 53 3 8.29
lib/origen_memory_image/s_record.rb 100.00 % 239 51 51 0 36.94

lib/origen_memory_image.rb

100.0% lines covered

23 relevant lines. 23 lines covered and 0 lines missed.
    
  1. 1 require 'origen'
  2. 1 require_relative '../config/application.rb'
  3. 1 module OrigenMemoryImage
  4. 1 autoload :Base, 'origen_memory_image/base'
  5. 1 autoload :SRecord, 'origen_memory_image/s_record'
  6. 1 autoload :Hex, 'origen_memory_image/hex'
  7. 1 autoload :Binary, 'origen_memory_image/binary'
  8. 1 autoload :IntelHex, 'origen_memory_image/intel_hex'
  9. 1 def self.new(file, options = {})
  10. 31 unless options[:source] == String
  11. 29 file = Origen.file_handler.clean_path_to(file)
  12. end
  13. 31 find_type(file, options).new(file, options)
  14. end
  15. # Returns the class of the image manager for the given file
  16. 1 def self.find_type(file, options = {})
  17. # Read first 10 lines
  18. 31 if options[:source] == String
  19. 2 snippet = file.split("\n")
  20. else
  21. 29 snippet = File.foreach(file.to_s).first(10)
  22. end
  23. case
  24. # Always do the binary first since the others won't be able to process
  25. # a binary snippet
  26. 31 when options[:type] == :binary || (options[:source] != String && Binary.match?(file))
  27. 1 Binary
  28. when options[:source] == String && Binary.match?(snippet, true)
  29. 1 Binary
  30. when options[:type] == :srecord || SRecord.match?(snippet)
  31. 17 SRecord
  32. when options[:type] == :intel_hex || IntelHex.match?(snippet)
  33. 5 IntelHex
  34. when options[:type] == :hex || Hex.match?(snippet)
  35. 6 Hex
  36. else
  37. 1 fail "Unknown format for image file: #{file}"
  38. end
  39. end
  40. end

lib/origen_memory_image/base.rb

97.62% lines covered

42 relevant lines. 41 lines covered and 1 lines missed.
    
  1. 1 module OrigenMemoryImage
  2. 1 class Base
  3. 1 attr_reader :file, :source
  4. 1 def initialize(file, options = {})
  5. 30 if options[:source] == String
  6. 2 @source = file
  7. else
  8. 28 @file = file
  9. end
  10. 30 @ljust_partial_data = options[:ljust_partial_data]
  11. end
  12. # Returns the code execution start address as an int
  13. 1 def start_address
  14. fail "#{self.class} has not implemented the start_address method!"
  15. end
  16. # Returns true if a start (jump address) record exists
  17. 1 def has_start_record
  18. 9 start_address unless @start_address
  19. 9 @start_record_found = false if @start_record_found.nil?
  20. 9 @start_record_found
  21. end
  22. # Returns the s-record as an array of addresses and data
  23. #
  24. # @param [hash] options, allows the selection of endianness swapping - ie the output will have the endianness changed
  25. #
  26. # The output is a 2D array, with each element being an array with element zero being the
  27. # address of the data and element one being one word of data
  28. # like this [[ADDR0, DATA0], [ADDR1, DATA1], [ADDR2, DATA2]...]
  29. #
  30. # The block header data and end of block value are not interpreted in any way and
  31. # the checksum bits are disregarded
  32. 1 def to_a(options = {})
  33. options = {
  34. 29 flip_endianness: false,
  35. data_width_in_bytes: 4,
  36. crop: []
  37. }.merge(options)
  38. 29 data = extract_addr_data(options)
  39. 28 if options[:crop].count > 0
  40. 7 cropped_data = []
  41. 7 data.each do |addr, data|
  42. 129 case options[:crop].count
  43. when 1
  44. 64 cropped_data.push([addr, data]) if addr >= options[:crop][0]
  45. when 2
  46. 64 cropped_data.push([addr, data]) if addr >= options[:crop][0] && addr <= options[:crop][1]
  47. else
  48. 1 fail 'crop option can only be array of size 1 or 2'
  49. end
  50. end
  51. 6 data = cropped_data
  52. end
  53. 27 if options[:flip_endianness] || options[:endianness_change]
  54. 5 data.map do |v|
  55. 94 [v[0], flip_endianness(v[1], options[:data_width_in_bytes])]
  56. end
  57. else
  58. 22 data
  59. end
  60. end
  61. 1 alias_method :to_array, :to_a
  62. # Reverse the endianness of the given data value, the width of it in bytes must
  63. # be supplied as the second argument
  64. #
  65. # @example
  66. # flip_endianness(0x12345678, 4) # => 0x78563412
  67. 1 def flip_endianness(data, width_in_bytes)
  68. 94 v = 0
  69. 94 width_in_bytes.times do |i|
  70. # data[7:0] => data[15:8]
  71. 448 start = 8 * i
  72. 448 v += data[(start + 7)..start] << ((width_in_bytes - i - 1) * 8)
  73. end
  74. 94 v
  75. end
  76. 1 def file_name
  77. 3 file || 'From source string'
  78. end
  79. 1 def lines
  80. 46 if file
  81. 43 File.readlines(file)
  82. else
  83. 3 source.split("\n")
  84. end
  85. end
  86. end
  87. end

lib/origen_memory_image/binary.rb

87.5% lines covered

32 relevant lines. 28 lines covered and 4 lines missed.
    
  1. 1 module OrigenMemoryImage
  2. 1 class Binary < Base
  3. 1 def self.match?(file, snippet = false)
  4. 31 if snippet
  5. 7 file.all? { |l| l.strip =~ /^[01]*$/ }
  6. else
  7. # detect whether the data is mostly not alpha numeric
  8. 29 filedata = (File.read(file, 256) || '')
  9. 29 (filedata.gsub(/\s+/, '').gsub(/\w/, '').length.to_f / filedata.length.to_f) > 0.3
  10. end
  11. end
  12. # Always returns 0 since binary files do not contain addresses
  13. 1 def start_address
  14. 3 0
  15. end
  16. 1 def create_test_file
  17. data = [
  18. 0x1EE0021C, 0x22401BE0, 0x021C2243,
  19. 0x18E0021C, 0x5A780A43, 0x03E0034B,
  20. 0xF7215A78, 0x0A400020, 0x22E08442,
  21. 0x22D31FE0, 0x84421FD9, 0x1CE08442,
  22. 0x002B20D1, 0x03E0012A, 0x01D1002B,
  23. 0x1BD00223, 0x2340022A, 0x02D1002B,
  24. 0x15D103E0, 0x032A01D1, 0x78000018,
  25. 0x7C000018, 0x82000018, 0x88000018
  26. ]
  27. data = data.map { |d| d.to_s(2).rjust(32, '0') }.join
  28. File.open('examples/bin1.bin', 'wb') do |output|
  29. output.write [data].pack('B*')
  30. end
  31. end
  32. 1 private
  33. # Returns an array containing all address/data from the given s-record
  34. # No address manipulation is performed, that is left to the caller to apply
  35. # any scrambling as required by the target system
  36. 1 def extract_addr_data(options = {})
  37. options = {
  38. 9 data_width_in_bytes: 4
  39. }.merge(options)
  40. 9 result = []
  41. 9 width = options[:data_width_in_bytes]
  42. 9 address = 0
  43. 9 if file
  44. 8 raw = File.binread(file)
  45. 8 bytes = raw.unpack('C*')
  46. else
  47. 1 raw = lines.map(&:strip).join
  48. 17 bytes = raw.scan(/.{1,8}/).map { |s| s.to_i(2) }
  49. end
  50. 9 bytes.each_slice(width) do |d|
  51. 184 v = 0
  52. 184 width.times do |i|
  53. 784 v |= d[i] << ((width - 1 - i) * 8) if d[i]
  54. end
  55. 184 result << [address, v]
  56. 184 address += width
  57. end
  58. 9 result
  59. end
  60. end
  61. end

lib/origen_memory_image/hex.rb

100.0% lines covered

30 relevant lines. 30 lines covered and 0 lines missed.
    
  1. 1 module OrigenMemoryImage
  2. 1 class Hex < Base
  3. 1 def self.match?(snippet)
  4. 6 snippet.any? do |line|
  5. # Match a line like:
  6. # @180000F0
  7. 15 line =~ /^@[0-9a-fA-F]+\s?$/
  8. end
  9. end
  10. # The first in the file will be taken as the start address
  11. 1 def start_address
  12. 4 @start_address ||= begin
  13. 4 lines.each do |line|
  14. 4 if line =~ /^@([0-9a-fA-F]+)\s?$/
  15. 4 return Regexp.last_match[1].to_i(16)
  16. end
  17. end
  18. end
  19. end
  20. 1 private
  21. # Returns an array containing all address/data from the given s-record
  22. # No address manipulation is performed, that is left to the caller to apply
  23. # any scrambling as required by the target system
  24. 1 def extract_addr_data(options = {})
  25. options = {
  26. 9 data_width_in_bytes: 4
  27. }.merge(options)
  28. 9 result = []
  29. 9 lines.each do |line|
  30. # Only if the line is an s-record with data...
  31. 67 if line =~ /^@([0-9a-fA-F]+)\s?$/
  32. 22 @address = Regexp.last_match[1].to_i(16)
  33. 45 elsif line =~ /^[0-9A-F]/
  34. 45 unless @address
  35. 1 fail "Hex data found before an @address line in #{file_name}"
  36. end
  37. 44 data = line.strip.gsub(/\s/, '')
  38. 44 data_matcher = '\w\w' * options[:data_width_in_bytes]
  39. 44 data.scan(/#{data_matcher}/).each do |data_packet|
  40. 190 result << [@address, data_packet.to_i(16)]
  41. 190 @address += options[:data_width_in_bytes]
  42. end
  43. # If a partial word is left over
  44. 44 if (remainder = data.length % (2 * options[:data_width_in_bytes])) > 0
  45. 2 if @ljust_partial_data
  46. 1 result << [@address, data[data.length - remainder..data.length].ljust(options[:data_width_in_bytes] * 2, '0').to_i(16)]
  47. else
  48. 1 result << [@address, data[data.length - remainder..data.length].to_i(16)]
  49. end
  50. end
  51. end
  52. end
  53. 8 result
  54. end
  55. end
  56. end

lib/origen_memory_image/intel_hex.rb

94.64% lines covered

56 relevant lines. 53 lines covered and 3 lines missed.
    
  1. 1 module OrigenMemoryImage
  2. 1 class IntelHex < Base
  3. 1 def self.match?(snippet)
  4. 12 snippet.all? do |line|
  5. 41 line.empty? || line =~ /^:[0-9A-Fa-f]{6}0[0-5]/
  6. end
  7. end
  8. 1 def start_address
  9. 3 @start_address ||= begin
  10. 3 addrs = []
  11. 3 lines.each do |line|
  12. 21 line = line.strip
  13. 21 if start_linear_address?(line)
  14. 2 addrs << decode(line)[:data].to_i(16)
  15. end
  16. end
  17. 3 addrs.last || 0
  18. end
  19. end
  20. 1 private
  21. 1 def decode(line)
  22. 12 d = {}
  23. 12 if line =~ /^:([0-9A-Fa-f]{2})([0-9A-Fa-f]{4})(\d\d)([0-9A-Fa-f]+)([0-9A-Fa-f]{2})$/
  24. 12 d[:byte_count] = Regexp.last_match(1).to_i(16)
  25. 12 d[:address] = Regexp.last_match(2).to_i(16)
  26. 12 d[:record_type] = Regexp.last_match(3).to_i(16)
  27. 12 d[:data] = Regexp.last_match(4)
  28. 12 d[:checksum] = Regexp.last_match(5).to_i(16)
  29. else
  30. fail "Invalid line encountered in Intel Hex formatted file: #{line}"
  31. end
  32. 12 d
  33. end
  34. 1 def data?(line)
  35. 11 !!(line =~ /^:[0-9A-Fa-f]{6}00/)
  36. end
  37. 1 def extended_segment_address?(line)
  38. 13 !!(line =~ /^:[0-9A-Fa-f]{6}02/)
  39. end
  40. 1 def extended_linear_address?(line)
  41. 13 !!(line =~ /^:[0-9A-Fa-f]{6}04/)
  42. end
  43. 1 def start_linear_address?(line)
  44. 21 !!(line =~ /^:[0-9A-Fa-f]{6}05/)
  45. end
  46. 1 def upper_addr
  47. 8 @upper_addr || 0
  48. end
  49. 1 def segment_address
  50. 8 @segment_address || 0
  51. end
  52. # Returns an array containing all address/data from the given s-record
  53. # No address manipulation is performed, that is left to the caller to apply
  54. # any scrambling as required by the target system
  55. 1 def extract_addr_data(options = {})
  56. options = {
  57. 2 data_width_in_bytes: 4
  58. }.merge(options)
  59. 2 result = []
  60. 2 lines.each do |line|
  61. 13 line = line.strip
  62. 13 if extended_segment_address?(line)
  63. @segment_address = decode(line)[:data].to_i(16) * 16
  64. 13 elsif extended_linear_address?(line)
  65. 2 @upper_addr = (decode(line)[:data].to_i(16)) << 16
  66. 11 elsif data?(line)
  67. 8 d = decode(line)
  68. 8 addr = d[:address] + segment_address + upper_addr
  69. 8 data = d[:data]
  70. 8 data_matcher = '\w\w' * options[:data_width_in_bytes]
  71. 8 data.scan(/#{data_matcher}/).each do |data_packet|
  72. 32 result << [addr, data_packet.to_i(16)]
  73. 32 addr += options[:data_width_in_bytes]
  74. end
  75. # If a partial word is left over
  76. 8 if (remainder = data.length % (2 * options[:data_width_in_bytes])) > 0
  77. result << [addr, data[data.length - remainder..data.length].to_i(16)]
  78. end
  79. end
  80. end
  81. 2 result
  82. end
  83. end
  84. end

lib/origen_memory_image/s_record.rb

100.0% lines covered

51 relevant lines. 51 lines covered and 0 lines missed.
    
  1. 1 module OrigenMemoryImage
  2. # An S-record file consists of a sequence of specially formatted ASCII character strings. An S-record will
  3. # be less than or equal to 78 bytes in length.
  4. # The order of S-records within a file is of no significance and no particular order may be assumed.
  5. #
  6. # The general format of an S-record follows:
  7. #
  8. # +-------------------//------------------//-----------------------+
  9. # | type | count | address | data | checksum |
  10. # +-------------------//------------------//-----------------------+
  11. #
  12. # type
  13. # : A char[2] field. These characters describe the type of record (S0, S1, S2, S3, S5, S7, S8, or S9).
  14. #
  15. # count
  16. # : A char[2] field. These characters when paired and interpreted as a hexadecimal value, display
  17. # the count of remaining character pairs in the record.
  18. #
  19. # address
  20. # : A char[4,6, or 8] field. These characters grouped and interpreted as a hexadecimal value,
  21. # display the address at which the data field is to be loaded into memory. The length of the field depends
  22. # on the number of bytes necessary to hold the address. A 2-byte address uses 4 characters, a 3-byte
  23. # address uses 6 characters, and a 4-byte address uses 8 characters.
  24. #
  25. # data
  26. # : A char [0-64] field. These characters when paired and interpreted as hexadecimal values represent
  27. # the memory loadable data or descriptive information.
  28. #
  29. # checksum
  30. # : A char[2] field. These characters when paired and interpreted as a hexadecimal value display
  31. # the least significant byte of the ones complement of the sum of the byte values represented by the pairs
  32. # of characters making up the count, the address, and the data fields.
  33. #
  34. # Each record is terminated with a line feed. If any additional or different record terminator(s) or delay
  35. # characters are needed during transmission to the target system it is the responsibility of the
  36. # transmitting program to provide them.
  37. #
  38. # #### S0 Record
  39. #
  40. # The type of record is 'S0' (0x5330). The address field is unused and will be filled with zeros
  41. # (0x0000). The header information within the data field is divided into the following subfields.
  42. #
  43. # * mname is char[20] and is the module name.
  44. # * ver is char[2] and is the version number.
  45. # * rev is char[2] and is the revision number.
  46. # * description is char[0-36] and is a text comment.
  47. #
  48. # Each of the subfields is composed of ASCII bytes whose associated characters, when paired, represent one
  49. # byte hexadecimal values in the case of the version and revision numbers, or represent the hexadecimal
  50. # values of the ASCII characters comprising the module name and description.
  51. #
  52. # #### S1 Record
  53. #
  54. # The type of record field is 'S1' (0x5331). The address field is intrepreted as a 2-byte
  55. # address. The data field is composed of memory loadable data.
  56. #
  57. # #### S2 Record
  58. #
  59. # The type of record field is 'S2' (0x5332). The address field is intrepreted as a 3-byte
  60. # address. The data field is composed of memory loadable data.
  61. #
  62. # #### S3 Record
  63. #
  64. # The type of record field is 'S3' (0x5333). The address field is intrepreted as a 4-byte
  65. # address. The data field is composed of memory loadable data.
  66. #
  67. # #### S5 Record
  68. #
  69. # The type of record field is 'S5' (0x5335). The address field is intrepreted as a 2-byte value
  70. # and contains the count of S1, S2, and S3 records previously transmitted. There is no data field.
  71. #
  72. # #### S7 Record
  73. #
  74. # The type of record field is 'S7' (0x5337). The address field contains the starting execution
  75. # address and is intrepreted as 4-byte address. There is no data field.
  76. #
  77. # #### S8 Record
  78. #
  79. # The type of record field is 'S8' (0x5338). The address field contains the starting execution
  80. # address and is intrepreted as 3-byte address. There is no data field.
  81. #
  82. # #### S9 Record
  83. #
  84. # The type of record field is 'S9' (0x5339). The address field contains the starting execution
  85. # address and is intrepreted as 2-byte address. There is no data field.
  86. #
  87. # ### Example
  88. #
  89. # Shown below is a typical S-record format file.
  90. #
  91. # S00600004844521B
  92. # S1130000285F245F2212226A000424290008237C2A
  93. # S11300100002000800082629001853812341001813
  94. # S113002041E900084E42234300182342000824A952
  95. # S107003000144ED492
  96. # S5030004F8
  97. # S9030000FC
  98. #
  99. # The file consists of one S0 record, four S1 records, one S5 record and an S9 record.
  100. #
  101. # The S0 record is comprised as follows:
  102. #
  103. # * S0 S-record type S0, indicating it is a header record.
  104. # * 06 Hexadecimal 06 (decimal 6), indicating that six character pairs (or ASCII bytes) follow.
  105. # * 00 00 Four character 2-byte address field, zeroes in this example.
  106. # * 48 44 52 ASCII H, D, and R - "HDR".
  107. # * 1B The checksum.
  108. #
  109. # The first S1 record is comprised as follows:
  110. #
  111. # * S1 S-record type S1, indicating it is a data record to be loaded at a 2-byte address.
  112. # * 13 Hexadecimal 13 (decimal 19), indicating that nineteen character pairs, representing a 2 byte address,
  113. # * 16 bytes of binary data, and a 1 byte checksum, follow.
  114. # * 00 00 Four character 2-byte address field; hexidecimal address 0x0000, where the data which follows is to
  115. # be loaded.
  116. # * 28 5F 24 5F 22 12 22 6A 00 04 24 29 00 08 23 7C Sixteen character pairs representing the actual binary
  117. # data.
  118. # * 2A The checksum.
  119. # * The second and third S1 records each contain 0x13 (19) character pairs and are ended with checksums of 13
  120. # and 52, respectively. The fourth S1 record contains 07 character pairs and has a checksum of 92.
  121. #
  122. # The S5 record is comprised as follows:
  123. #
  124. # * S5 S-record type S5, indicating it is a count record indicating the number of S1 records
  125. # * 03 Hexadecimal 03 (decimal 3), indicating that three character pairs follow.
  126. # * 00 04 Hexadecimal 0004 (decimal 4), indicating that there are four data records previous to this record.
  127. # * F8 The checksum.
  128. #
  129. # The S9 record is comprised as follows:
  130. #
  131. # * S9 S-record type S9, indicating it is a termination record.
  132. # * 03 Hexadecimal 03 (decimal 3), indicating that three character pairs follow.
  133. # * 00 00 The address field, hexadecimal 0 (decimal 0) indicating the starting execution address.
  134. # * FC The checksum.
  135. #
  136. # ### Additional Notes
  137. #
  138. # There isn't any evidence that Motorola ever has made use of the header information within the data field
  139. # of the S0 record, as described above. This must have been used by some third party vendors.
  140. # This is the only place that a 78-byte limit on total record length or 64-byte limit on data length is
  141. # documented. These values shouldn't be trusted for the general case.
  142. #
  143. # The count field can have values in the range of 0x3 (2 bytes of address + 1 byte checksum = 3, a not
  144. # very useful record) to 0xff; this is the count of remaining character pairs, including checksum.
  145. # If you write code to convert S-Records, you should always assume that a record can be as long as 514
  146. # (decimal) characters in length (255 * 2 = 510, plus 4 characters for the type and count fields), plus
  147. # any terminating character(s).
  148. #
  149. # That is, in establishing an input buffer in C, you would declare it to be
  150. # an array of 515 chars, thus leaving room for the terminating null character.
  151. 1 class SRecord < Base
  152. 1 def self.match?(snippet)
  153. 29 snippet.all? do |line|
  154. 129 line.empty? || line =~ /^S[01235789]/
  155. end
  156. end
  157. 1 def start_address
  158. 18 if @call_order_warn
  159. 1 Origen.log.warn 'Previously srec.start_address returned the lowest address when to_a was called first. Now the start record is always returned if present.'
  160. 1 @call_order_warn = false
  161. end
  162. 18 lowest_address = nil
  163. 18 @start_address ||= begin
  164. 18 lines.each do |line|
  165. 124 if line =~ /^S([789])(.*)/
  166. 16 @start_record_found = true
  167. 16 type = Regexp.last_match[1]
  168. 16 case type
  169. when '7'
  170. 10 return line.slice(4, 8).to_i(16)
  171. when '8'
  172. 4 return line.slice(4, 6).to_i(16)
  173. when '9'
  174. 2 return line.slice(4, 4).to_i(16)
  175. end
  176. end
  177. 108 if line =~ /^S([1-3])/
  178. 90 type = Regexp.last_match[1].to_i(16) # S-record type, 1-3
  179. # Set the matcher to capture x number of bytes dependent on the s-rec type
  180. 90 addr_matcher = '\w\w' * (1 + type)
  181. 90 line.strip =~ /^S\d\w\w(#{addr_matcher})(\w*)\w\w$/ # $1 = address, $2 = data
  182. 90 addr = Regexp.last_match[1].to_i(16)
  183. 90 lowest_address ||= addr
  184. 90 lowest_address = addr if addr < lowest_address
  185. end
  186. end
  187. # if no start_address record is found, return lowest address
  188. 2 @start_record_found = false
  189. 2 lowest_address
  190. end
  191. end
  192. 1 private
  193. # Returns an array containing all address/data from the given s-record
  194. # No address manipulation is performed, that is left to the caller to apply
  195. # any scrambling as required by the target system
  196. 1 def extract_addr_data(options = {})
  197. options = {
  198. 9 data_width_in_bytes: 4
  199. }.merge(options)
  200. # guarantee that the start_address will be the jump address if provided
  201. 9 if @start_address.nil?
  202. 9 start_address
  203. 9 @call_order_warn = @start_record_found ? true : false
  204. end
  205. 9 result = []
  206. 9 lines.each do |line|
  207. # Only if the line is an s-record with data...
  208. 63 if line =~ /^S([1-3])/
  209. 45 type = Regexp.last_match[1].to_i(16) # S-record type, 1-3
  210. # Set the matcher to capture x number of bytes dependent on the s-rec type
  211. 45 addr_matcher = '\w\w' * (1 + type)
  212. 45 line.strip =~ /^S\d\w\w(#{addr_matcher})(\w*)\w\w$/ # $1 = address, $2 = data
  213. 45 addr = Regexp.last_match[1].to_i(16)
  214. 45 data = Regexp.last_match[2]
  215. 45 data_matcher = '\w\w' * options[:data_width_in_bytes]
  216. 45 data.scan(/#{data_matcher}/).each do |data_packet|
  217. 158 result << [addr, data_packet.to_i(16)]
  218. 158 addr += options[:data_width_in_bytes]
  219. end
  220. # If a partial word is left over
  221. 45 if (remainder = data.length % (2 * options[:data_width_in_bytes])) > 0
  222. 2 if @ljust_partial_data
  223. 1 result << [addr, data[data.length - remainder..data.length].ljust(options[:data_width_in_bytes] * 2, '0').to_i(16)]
  224. else
  225. 1 result << [addr, data[data.length - remainder..data.length].to_i(16)]
  226. end
  227. end
  228. end
  229. end
  230. 9 result
  231. end
  232. end
  233. end