Class: OpenC3::LengthProtocol

Inherits:
BurstProtocol show all
Defined in:
lib/openc3/interfaces/protocols/length_protocol.rb

Overview

Protocol which delineates packets using a length field at a fixed location in each packet.

Instance Attribute Summary

Attributes inherited from Protocol

#allow_empty_data, #extra, #interface

Instance Method Summary collapse

Methods inherited from BurstProtocol

#handle_sync_pattern, #log_discard, #read_data, #reset

Methods inherited from Protocol

#connect_reset, #disconnect_reset, #post_write_interface, #protocol_cmd, #read_data, #read_packet, #reset

Constructor Details

#initialize(length_bit_offset = 0, length_bit_size = 16, length_value_offset = 0, length_bytes_per_count = 1, length_endianness = 'BIG_ENDIAN', discard_leading_bytes = 0, sync_pattern = nil, max_length = nil, fill_length_and_sync_pattern = false, allow_empty_data = nil) ⇒ LengthProtocol

Returns a new instance of LengthProtocol.

Parameters:

  • length_bit_offset (Integer) (defaults to: 0)

    The bit offset of the length field

  • length_bit_size (Integer) (defaults to: 16)

    The size in bits of the length field

  • length_value_offset (Integer) (defaults to: 0)

    The offset to apply to the length value once it has been read from the packet. The value in the length field itself plus the length value offset MUST equal the total bytes including any discarded bytes. For example: if your length field really means "length - 1" this value should be 1.

  • length_bytes_per_count (Integer) (defaults to: 1)

    The number of bytes per each length field 'count'. This is used if the units of the length field is something other than bytes, for example words.

  • length_endianness (String) (defaults to: 'BIG_ENDIAN')

    The endianness of the length field. Must be either BIG_ENDIAN or LITTLE_ENDIAN.

  • max_length (Integer) (defaults to: nil)

    The maximum allowed value of the length field

  • fill_length_and_sync_pattern (Boolean) (defaults to: false)

    Fill the length field and sync pattern when writing packets

  • allow_empty_data (true/false/nil) (defaults to: nil)

    See Protocol#initialize

  • discard_leading_bytes (Integer) (defaults to: 0)

    The number of bytes to discard from the binary data after reading. Note that this is often used to remove a sync pattern from the final packet data.

  • sync_pattern (String) (defaults to: nil)

    String representing a hex number ("0x1234") that will be searched for in the raw data. Bytes encountered before this pattern is found are discarded.



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
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 49

def initialize(
  length_bit_offset = 0,
  length_bit_size = 16,
  length_value_offset = 0,
  length_bytes_per_count = 1,
  length_endianness = 'BIG_ENDIAN',
  discard_leading_bytes = 0,
  sync_pattern = nil,
  max_length = nil,
  fill_length_and_sync_pattern = false,
  allow_empty_data = nil
)
  super(discard_leading_bytes, sync_pattern, fill_length_and_sync_pattern, allow_empty_data)

  # Save length field attributes
  @length_bit_offset = Integer(length_bit_offset)
  @length_bit_size = Integer(length_bit_size)
  @length_value_offset = Integer(length_value_offset)
  @length_bytes_per_count = Integer(length_bytes_per_count)

  # Save endianness
  if length_endianness.to_s.upcase == 'LITTLE_ENDIAN'
    @length_endianness = :LITTLE_ENDIAN
  else
    @length_endianness = :BIG_ENDIAN
  end

  # Derive number of bytes required to contain entire length field
  if @length_endianness == :BIG_ENDIAN or ((@length_bit_offset % 8) == 0)
    length_bits_needed = @length_bit_offset + @length_bit_size
    length_bits_needed += 8 if (length_bits_needed % 8) != 0
    @length_bytes_needed = ((length_bits_needed - 1) / 8) + 1
  else
    @length_bytes_needed = (length_bit_offset / 8) + 1
  end

  # Save max length setting
  @max_length = ConfigParser.handle_nil(max_length)
  @max_length = Integer(@max_length) if @max_length
end

Instance Method Details

#write_data(data, extra = nil) ⇒ String

Called to perform modifications on write data before making it into a packet

Parameters:

  • data (String)

    Raw packet data

Returns:

  • (String)

    Potentially modified packet data



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 115

def write_data(data, extra = nil)
  data, extra = super(data, extra)
  if @fill_fields
    # If the start of the length field is before what we discard, then the
    # length field is outside the packet
    if @length_bit_offset < (@discard_leading_bytes * 8)
      BinaryAccessor.write(calculate_length(data.length), @length_bit_offset, @length_bit_size, :UINT,
                           data, @length_endianness, :ERROR)
    end
  end
  return data, extra
end

#write_packet(packet) ⇒ Packet

Called to perform modifications on a command packet before it is send

Parameters:

  • packet (Packet)

    Original packet

Returns:

  • (Packet)

    Potentially modified packet



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 94

def write_packet(packet)
  if @fill_fields
    # If the start of the length field is past what we discard, then the
    # length field is inside the packet
    if @length_bit_offset >= (@discard_leading_bytes * 8)
      length = calculate_length(packet.buffer(false).length + @discard_leading_bytes)
      # Subtract off the discarded bytes since they haven't been added yet
      # Adding bytes happens in the write_data method
      offset = @length_bit_offset - (@discard_leading_bytes * 8)
      # Directly write the packet buffer and fill in the length
      BinaryAccessor.write(length, offset, @length_bit_size, :UINT,
                           packet.buffer(false), @length_endianness, :ERROR)
    end
  end
  return super(packet) # Allow burst_protocol to set the sync if needed
end