Class: IntelHex::Record

Inherits:
Object
  • Object
show all
Defined in:
lib/intel_hex/record.rb,
lib/intel_hex/record/ela.rb,
lib/intel_hex/record/eof.rb,
lib/intel_hex/record/esa.rb,
lib/intel_hex/record/sla.rb,
lib/intel_hex/record/ssa.rb,
lib/intel_hex/record/data.rb,
lib/intel_hex/record/value_record_uint16.rb,
lib/intel_hex/record/value_record_uint32.rb

Direct Known Subclasses

Data, Eof, ValueRecordUint16, ValueRecordUint32

Defined Under Namespace

Classes: Data, Ela, Eof, Esa, Sla, Ssa, ValueRecordUint16, ValueRecordUint32

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(length = 0, offset = 0, data = [], checksum = nil, line: nil, validate: false) ⇒ Record

Returns a new instance of Record.



74
75
76
77
78
79
80
81
82
83
# File 'lib/intel_hex/record.rb', line 74

def initialize(length = 0, offset = 0, data = [], checksum = nil, line: nil, validate: false)
  @length = length
  @offset = offset
  @data = data
  @calculated_checksum = nil
  @checksum = checksum || calculate_checksum
  @line = line

  self.validate if validate
end

Class Attribute Details

.type_by_idObject (readonly)

Returns the value of attribute type_by_id.



31
32
33
# File 'lib/intel_hex/record.rb', line 31

def type_by_id
  @type_by_id
end

.type_by_nameObject (readonly)

Returns the value of attribute type_by_name.



31
32
33
# File 'lib/intel_hex/record.rb', line 31

def type_by_name
  @type_by_name
end

Instance Attribute Details

#checksumObject (readonly)

Returns the value of attribute checksum.



72
73
74
# File 'lib/intel_hex/record.rb', line 72

def checksum
  @checksum
end

#dataObject

Returns the value of attribute data.



72
73
74
# File 'lib/intel_hex/record.rb', line 72

def data
  @data
end

#lengthObject (readonly)

Returns the value of attribute length.



72
73
74
# File 'lib/intel_hex/record.rb', line 72

def length
  @length
end

#lineObject (readonly)

Returns the value of attribute line.



72
73
74
# File 'lib/intel_hex/record.rb', line 72

def line
  @line
end

#offsetObject (readonly)

Returns the value of attribute offset.



72
73
74
# File 'lib/intel_hex/record.rb', line 72

def offset
  @offset
end

Class Method Details

.data(data = []) ⇒ Object



29
30
31
32
33
# File 'lib/intel_hex/record/data.rb', line 29

def self.data(data = [])
  record = Data.new
  record.data = data
  record
end

.ela(value = nil) ⇒ Object



17
18
19
20
21
# File 'lib/intel_hex/record/ela.rb', line 17

def self.ela(value = nil)
  record = Ela.new
  record.value = value if value
  record
end

.eofObject



19
20
21
# File 'lib/intel_hex/record/eof.rb', line 19

def self.eof
  Eof.new
end

.esa(value = nil) ⇒ Object



17
18
19
20
21
# File 'lib/intel_hex/record/esa.rb', line 17

def self.esa(value = nil)
  record = Esa.new
  record.value = value if value
  record
end

.inherited(subclass) ⇒ Object



63
64
65
66
67
# File 'lib/intel_hex/record.rb', line 63

def inherited(subclass)
  super

  subclass.instance_eval { public_class_method :new }
end

.parse(line) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/intel_hex/record.rb', line 45

def 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_id = 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)

  raise InvalidTypeError, "Unknown type #{type_id}" unless type_by_id.include?(type_id)

  type = type_by_id[type_id]
  type.new(length, offset, data, checksum, line: line, validate: true)
end

.register_type(type) ⇒ Object



20
21
22
23
24
25
26
27
28
29
# File 'lib/intel_hex/record.rb', line 20

def register_type(type)
  @type_by_id ||= {}
  @type_by_name ||= {}

  raise "Type name #{type.type_name} is not a symbol" unless type.type_name.is_a?(Symbol)
  raise "Type name #{type.type_name} redefined" if @type_by_name.include?(type.type_name)
  raise "Type id #{type.type_id} redefined" if @type_by_id.include?(type.type_id)

  @type_by_id[type.type_id] = @type_by_name[type.type_name] = type
end

.sla(value = nil) ⇒ Object



17
18
19
20
21
# File 'lib/intel_hex/record/sla.rb', line 17

def self.sla(value = nil)
  record = Sla.new
  record.value = value if value
  record
end

.ssa(value = nil) ⇒ Object



17
18
19
20
21
# File 'lib/intel_hex/record/ssa.rb', line 17

def self.ssa(value = nil)
  record = Ssa.new
  record.value = value if value
  record
end

.type_data_lengthObject

Raises:

  • (NotImplementedError)


41
42
43
# File 'lib/intel_hex/record.rb', line 41

def type_data_length
  raise NotImplementedError
end

.type_idObject

Raises:

  • (NotImplementedError)


33
34
35
# File 'lib/intel_hex/record.rb', line 33

def type_id
  raise NotImplementedError
end

.type_nameObject

Raises:

  • (NotImplementedError)


37
38
39
# File 'lib/intel_hex/record.rb', line 37

def type_name
  raise NotImplementedError
end

Instance Method Details

#calculate_checksumObject



141
142
143
144
145
146
147
148
# File 'lib/intel_hex/record.rb', line 141

def calculate_checksum
  return @calculated_checksum if @calculated_checksum

  sum = length + ((offset & 0xff00) >> 8) + (offset & 0x00ff) + type_id
  sum += data.sum

  @calculated_checksum = (((sum & 0xff) ^ 0xff) + 1) & 0xff
end

#each_byte_with_addressObject



199
200
201
202
203
204
205
206
207
# File 'lib/intel_hex/record.rb', line 199

def each_byte_with_address
  return enum_for(:each_byte_with_address) unless block_given?

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

  nil
end

#recalculate_checksumObject



150
151
152
153
# File 'lib/intel_hex/record.rb', line 150

def recalculate_checksum
  @calculated_checksum = nil
  calculate_checksum
end

#to_asciiObject



130
131
132
133
134
135
136
137
138
139
# File 'lib/intel_hex/record.rb', line 130

def to_ascii
  format(
    ":%02X%04X%02X%s%02X",
    length,
    offset,
    type_id,
    data.map { |b| format("%02X", b) }.join,
    checksum
  )
end

#to_hObject



121
122
123
124
125
126
127
128
# File 'lib/intel_hex/record.rb', line 121

def to_h
  {
    type: type,
    offset: offset,
    length: length,
    checksum: checksum,
  }.merge({ type => value })
end

#to_sObject



116
117
118
119
# File 'lib/intel_hex/record.rb', line 116

def to_s
  type_value = value ? "#{type}=#{value_s}" : ""
  "#<#{self.class.name} type=#{type_name} offset=#{offset} length=#{length} #{type_value}>"
end

#type_data_lengthObject



95
96
97
# File 'lib/intel_hex/record.rb', line 95

def type_data_length
  self.class.type_data_length
end

#type_idObject



85
86
87
# File 'lib/intel_hex/record.rb', line 85

def type_id
  self.class.type_id
end

#type_nameObject Also known as: type



89
90
91
# File 'lib/intel_hex/record.rb', line 89

def type_name
  self.class.type_name
end

#valid?Boolean

Returns:

  • (Boolean)


155
156
157
158
159
160
# File 'lib/intel_hex/record.rb', line 155

def valid?
  validate
  true
rescue ValidationError
  false
end

#validateObject



162
163
164
165
166
167
# File 'lib/intel_hex/record.rb', line 162

def validate
  validate_length
  validate_offset
  validate_data
  validate_checksum
end

#validate_checksumObject



193
194
195
196
197
# File 'lib/intel_hex/record.rb', line 193

def validate_checksum
  return if calculate_checksum == checksum

  raise InvalidChecksumError, "Checksum value #{checksum} does not match expected checksum #{calculate_checksum}"
end

#validate_dataObject

Raises:



187
188
189
190
191
# File 'lib/intel_hex/record.rb', line 187

def validate_data
  return if data.size == length

  raise InvalidDataError, "Data length #{data.size} does not match length #{length}"
end

#validate_lengthObject

Raises:



174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/intel_hex/record.rb', line 174

def validate_length
  case type_data_length
  when Integer
    return if length == type_data_length
  when Range
    return if type_data_length.include?(length)
  else
    raise InvalidTypeError, "Length for type #{type} is unhandled by validation"
  end

  raise InvalidLengthError, "Length for type #{type} must be #{type_data_length}; #{length} given"
end

#validate_offsetObject

Raises:



169
170
171
172
# File 'lib/intel_hex/record.rb', line 169

def validate_offset
  raise InvalidOffsetError, "Offset #{offset} is negative" unless offset >= 0
  raise InvalidOffsetError, "Offset #{offset} is too large" unless offset < 2**16
end

#valueObject



108
109
110
# File 'lib/intel_hex/record.rb', line 108

def value
  nil
end

#value_sObject



112
113
114
# File 'lib/intel_hex/record.rb', line 112

def value_s
  value.to_s
end