class IntelHex::Record

Constants

TYPES
TYPE_DATA_LENGTH
TYPE_MAP

Attributes

checksum[R]
data[R]
length[R]
line[R]
offset[R]
type[R]

Public Class Methods

data(data) click to toggle source
# File lib/intel_hex/record.rb, line 54
def self.data(data)
  record = Record.new(:data)
  record.data = data
  record
end
ela(value) click to toggle source
# File lib/intel_hex/record.rb, line 78
def self.ela(value)
  type_with_value(:ela, value)
end
eof() click to toggle source
# File lib/intel_hex/record.rb, line 60
def self.eof
  Record.new(:eof)
end
esa(value) click to toggle source
# File lib/intel_hex/record.rb, line 70
def self.esa(value)
  type_with_value(:esa, value)
end
new(type, length = 0, offset = 0, data = [], checksum = nil, line: nil, validate: false) click to toggle source

rubocop:disable Metrics/ParameterLists

# File lib/intel_hex/record.rb, line 89
def initialize(type, length = 0, offset = 0, data = [], checksum = nil, line: nil, validate: false)
  @type = type
  @length = length
  @offset = offset
  @data = data
  @calculated_checksum = nil
  @checksum = checksum || calculate_checksum
  @line = line

  self.validate if validate
end
parse(line) click to toggle source
# File lib/intel_hex/record.rb, line 39
def self.parse(line)
  raise MisformattedFileError, 'Expected \':\' at start of line' unless line[0] == ':'
  raise MisformattedFileError, 'Line length incorrect' unless line.size >= (1 + 2 + 4 + 2)

  length = line[1..2].to_i(16)
  data_end = (9 + length * 2)

  offset = line[3..6].to_i(16)
  type = TYPES[line[7..8].to_i(16)]
  data = line[9...data_end].chars.each_slice(2).map { |a| a.join.to_i(16) }
  checksum = line[data_end..(data_end + 2)].to_i(16)

  Record.new(type, length, offset, data, checksum, line: line, validate: true)
end
sla(value) click to toggle source
# File lib/intel_hex/record.rb, line 82
def self.sla(value)
  type_with_value(:sla, value)
end
ssa(value) click to toggle source
# File lib/intel_hex/record.rb, line 74
def self.ssa(value)
  type_with_value(:ssa, value)
end
type_with_value(type, value) click to toggle source
# File lib/intel_hex/record.rb, line 64
def self.type_with_value(type, value)
  record = Record.new(type)
  record.send("#{type}=".to_sym, value)
  record
end

Public Instance Methods

calculate_checksum() click to toggle source
# File lib/intel_hex/record.rb, line 126
def calculate_checksum
  return @calculated_checksum if @calculated_checksum

  sum = length + ((offset & 0xff00) >> 8) + (offset & 0x00ff) + TYPE_MAP[type]
  sum += data.sum

  @calculated_checksum = (((sum & 0xff) ^ 0xff) + 1) & 0xff
end
data=(value) click to toggle source
# File lib/intel_hex/record.rb, line 201
def data=(value)
  raise 'Incorrect data type' unless value.is_a?(Array)
  raise InvalidLengthError, "Data length #{value.size} too large" unless value.size <= 255

  @data = value
  @length = data.size
  @checksum = recalculate_checksum
end
data_s() click to toggle source

rubocop:enable Metrics/ParameterLists

# File lib/intel_hex/record.rb, line 102
def data_s
  "[#{data.map { |b| '%02x' % b }.join(' ')}]"
end
data_to_uint16(offset = 0) click to toggle source
# File lib/intel_hex/record.rb, line 210
def data_to_uint16(offset = 0)
  (data[offset + 0] << 8) | data[offset + 1]
end
Also aliased as: esa, ela
data_to_uint32(offset = 0) click to toggle source
# File lib/intel_hex/record.rb, line 223
def data_to_uint32(offset = 0)
  (data[offset + 0] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]
end
Also aliased as: ssa, sla
each_byte_with_address() { |byte, offset + i| ... } click to toggle source
# File lib/intel_hex/record.rb, line 191
def each_byte_with_address
  return Enumerator.new(self, :each_byte_with_address) unless block_given?

  data.each_with_index do |byte, i|
    yield byte, offset + i
  end

  nil
end
ela(offset = 0)
Alias for: data_to_uint16
ela=(value, offset = 0)
Alias for: uint16_to_data
esa(offset = 0)
Alias for: data_to_uint16
esa=(value, offset = 0)
Alias for: uint16_to_data
recalculate_checksum() click to toggle source
# File lib/intel_hex/record.rb, line 135
def recalculate_checksum
  @calculated_checksum = nil
  calculate_checksum
end
sla(offset = 0)
Alias for: data_to_uint32
sla=(value, offset = 0)
Alias for: uint32_to_data
ssa(offset = 0)
Alias for: data_to_uint32
ssa=(value, offset = 0)
Alias for: uint32_to_data
to_ascii() click to toggle source
# File lib/intel_hex/record.rb, line 116
def to_ascii
  ':%02X%04X%02X%s%02X' % [
    length,
    offset,
    TYPE_MAP[type],
    data.map { |b| '%02X' % b }.join,
    checksum,
  ]
end
to_s() click to toggle source
# File lib/intel_hex/record.rb, line 112
def to_s
  "#<#{self.class.name} type=#{type} offset=#{offset} length=#{length} #{value_s}>"
end
uint16_to_data(value, offset = 0) click to toggle source
# File lib/intel_hex/record.rb, line 214
def uint16_to_data(value, offset = 0)
  data[(offset...(offset + 2))] = [
    (value & 0xff00) >> 8,
    value & 0x00ff,
  ]
  @length = data.size
  @checksum = recalculate_checksum
end
Also aliased as: esa=, ela=
uint32_to_data(value, offset = 0) click to toggle source
# File lib/intel_hex/record.rb, line 227
def uint32_to_data(value, offset = 0)
  data[(offset...(offset + 4))] = [
    (value & 0xff000000) >> 24,
    (value & 0x00ff0000) >> 16,
    (value & 0x0000ff00) >> 8,
    value & 0x000000ff,
  ]
  @length = data.size
  @checksum = recalculate_checksum
end
Also aliased as: ssa=, sla=
valid?() click to toggle source
# File lib/intel_hex/record.rb, line 140
def valid?
  validate
  true
rescue ValidationError
  false
end
validate() click to toggle source
# File lib/intel_hex/record.rb, line 147
def validate
  validate_type
  validate_length
  validate_offset
  validate_data
  validate_checksum
end
validate_checksum() click to toggle source
# File lib/intel_hex/record.rb, line 185
def validate_checksum
  return if calculate_checksum == checksum

  raise InvalidChecksumError, "Checksum value #{checksum} does not match expected checksum #{calculate_checksum}"
end
validate_data() click to toggle source
# File lib/intel_hex/record.rb, line 179
def validate_data
  return if data.size == length

  raise InvalidDataError, "Data length #{data.size} does not match length #{length}"
end
validate_length() click to toggle source
# File lib/intel_hex/record.rb, line 166
def validate_length
  valid_length = TYPE_DATA_LENGTH[type]

  case valid_length
  when Integer
    return if length == valid_length
  when Range
    return if valid_length.include?(length)
  end

  raise InvalidLengthError, "Length for type #{type} must be #{valid_length}; #{length} given"
end
validate_offset() click to toggle source
# File lib/intel_hex/record.rb, line 161
def validate_offset
  raise InvalidOffsetError, "Offset #{offset} is negative" unless offset >= 0
  raise InvalidOffsetError, "Offset #{offset} is too large" unless offset < 2**16
end
validate_type() click to toggle source
# File lib/intel_hex/record.rb, line 155
def validate_type
  return if TYPE_MAP.include?(type)

  raise InvalidTypeError, "Type #{type} is invalid"
end
value_s() click to toggle source
# File lib/intel_hex/record.rb, line 106
def value_s
  return '' if type == :eof

  "#{type}=#{type == :data ? data_s : send(type)}"
end