Class: Cosmos::CrcProtocol
- Defined in:
- lib/cosmos/interfaces/protocols/crc_protocol.rb
Overview
Creates a CRC on write and verifies a CRC on read
Constant Summary collapse
- ERROR =
on CRC mismatch
"ERROR"
- DISCONNECT =
on CRC mismatch
"DISCONNECT"
Instance Attribute Summary
Attributes inherited from Protocol
Instance Method Summary collapse
-
#initialize(write_item_name = nil, strip_crc = false, bad_strategy = "ERROR", bit_offset = -32,, bit_size = 32, endianness = 'BIG_ENDIAN', poly = nil, seed = nil, xor = nil, reflect = nil, allow_empty_data = nil) ⇒ CrcProtocol
constructor
A new instance of CrcProtocol.
- #read_data(data) ⇒ Object
- #write_data(data) ⇒ Object
- #write_packet(packet) ⇒ Object
Methods inherited from Protocol
#connect_reset, #disconnect_reset, #post_write_interface, #read_packet, #reset
Constructor Details
#initialize(write_item_name = nil, strip_crc = false, bad_strategy = "ERROR", bit_offset = -32,, bit_size = 32, endianness = 'BIG_ENDIAN', poly = nil, seed = nil, xor = nil, reflect = nil, allow_empty_data = nil) ⇒ CrcProtocol
Returns a new instance of CrcProtocol.
42 43 44 45 46 47 48 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/cosmos/interfaces/protocols/crc_protocol.rb', line 42 def initialize( write_item_name = nil, strip_crc = false, bad_strategy = "ERROR", bit_offset = -32, bit_size = 32, endianness = 'BIG_ENDIAN', poly = nil, seed = nil, xor = nil, reflect = nil, allow_empty_data = nil ) super(allow_empty_data) @write_item_name = ConfigParser.handle_nil(write_item_name) @strip_crc = ConfigParser.handle_true_false(strip_crc) raise "Invalid strip CRC of '#{strip_crc}'. Must be TRUE or FALSE." unless !!@strip_crc == @strip_crc case bad_strategy when ERROR, DISCONNECT @bad_strategy = bad_strategy else raise "Invalid bad CRC strategy of #{bad_strategy}. Must be ERROR or DISCONNECT." end case endianness.to_s.upcase when 'BIG_ENDIAN' @endianness = :BIG_ENDIAN # Convert to symbol for use in BinaryAccessor.write when 'LITTLE_ENDIAN' @endianness = :LITTLE_ENDIAN # Convert to symbol for use in BinaryAccessor.write else raise "Invalid endianness '#{endianness}'. Must be BIG_ENDIAN or LITTLE_ENDIAN." end begin @bit_offset = Integer(bit_offset) rescue raise "Invalid bit offset of #{bit_offset}. Must be a number." end raise "Invalid bit offset of #{bit_offset}. Must be divisible by 8." if @bit_offset % 8 != 0 poly = ConfigParser.handle_nil(poly) begin poly = Integer(poly) if poly rescue raise "Invalid polynomial of #{poly}. Must be a number." end seed = ConfigParser.handle_nil(seed) begin seed = Integer(seed) if seed rescue raise "Invalid seed of #{seed}. Must be a number." end xor = ConfigParser.handle_true_false_nil(xor) raise "Invalid XOR value of '#{xor}'. Must be TRUE or FALSE." if xor && !!xor != xor reflect = ConfigParser.handle_true_false_nil(reflect) if reflect raise "Invalid reflect value of '#{reflect}'. Must be TRUE or FALSE." if reflect && !!reflect != reflect # Built the CRC arguments array. All subsequent arguments are dependent # on the previous ones so we build it up incrementally. args = [] if poly args << poly if seed args << seed unless xor.nil? # Can't check raw variable because it could be false args << xor unless reflect.nil? # Can't check raw variable because it could be false args << reflect end end end end @bit_size = bit_size.to_i case @bit_size when 16 @pack = (@endianness == :BIG_ENDIAN) ? 'n' : 'v' if args.empty? @crc = Crc16.new else @crc = Crc16.new(*args) end when 32 @pack = (@endianness == :BIG_ENDIAN) ? 'N' : 'V' if args.empty? @crc = Crc32.new else @crc = Crc32.new(*args) end when 64 @pack = (@endianness == :BIG_ENDIAN) ? 'N' : 'V' if args.empty? @crc = Crc64.new else @crc = Crc64.new(*args) end else raise "Invalid bit size of #{bit_size}. Must be 16, 32, or 64." end end |
Instance Method Details
#read_data(data) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/cosmos/interfaces/protocols/crc_protocol.rb', line 147 def read_data(data) return super(data) if data.length <= 0 crc = BinaryAccessor.read(@bit_offset, @bit_size, :UINT, data, @endianness) calculated_crc = @crc.calc(data[0...(@bit_offset / 8)]) if calculated_crc != crc Logger.error "#{@interface ? @interface.name : ""}: Invalid CRC detected! Calculated 0x#{calculated_crc.to_s(16).upcase} vs found 0x#{crc.to_s(16).upcase}." if @bad_strategy == DISCONNECT return :DISCONNECT end end if @strip_crc new_data = data.dup new_data = new_data[0...(@bit_offset / 8)] end_range = (@bit_offset + @bit_size) / 8 new_data << data[end_range..-1] if end_range != 0 return new_data end return data end |
#write_data(data) ⇒ Object
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/cosmos/interfaces/protocols/crc_protocol.rb', line 177 def write_data(data) unless @write_item_name if @bit_size == 64 crc = @crc.calc(data) data << ("\x00" * 8) BinaryAccessor.write((crc >> 32), -64, 32, :UINT, data, @endianness, :ERROR) BinaryAccessor.write((crc & 0xFFFFFFFF), -32, 32, :UINT, data, @endianness, :ERROR) else crc = @crc.calc(data) data << ("\x00" * (@bit_size / 8)) BinaryAccessor.write(crc, -@bit_size, @bit_size, :UINT, data, @endianness, :ERROR) end end data end |
#write_packet(packet) ⇒ Object
168 169 170 171 172 173 174 175 |
# File 'lib/cosmos/interfaces/protocols/crc_protocol.rb', line 168 def write_packet(packet) if @write_item_name end_range = packet.get_item(@write_item_name).bit_offset / 8 crc = @crc.calc(packet.buffer(false)[0...end_range]) packet.write(@write_item_name, crc) end packet end |