Class: SerialProtocol::RCA2006
- Inherits:
-
Object
- Object
- SerialProtocol::RCA2006
- Defined in:
- lib/protocol/rca2006.rb
Overview
Serial protocol Roboterclub Aachen 2006 www.roboterclub.rwth-aachen.de/
Packet format:
[0x65, 0xEB, <type:8>, <counter:8>, <length:8>, data:length>, <crc:16>]
<type> is one of the following:
0b00000000 --> Data packet, discard on checksum mismatch
0b00011111 --> Data packet, resend on checksum mismatch
0b11100011 --> ACK packet
0b11111100 --> NACK packet
Direct Known Subclasses
Constant Summary collapse
- STARTBYTES =
"\x65\xeb"
- TYPE =
{ :data_no_crc => 0, :data => 0b00011111, :ack => 0b11100011, :nack => 0b11111100 }
Instance Method Summary collapse
-
#add_char_to_packet(char) ⇒ Object
Big and ugly state machine that does most of the work.
-
#initialize(send_callback, receive_callback, options = {}) ⇒ RCA2006
constructor
A new instance of RCA2006.
-
#on_raw_receive(&block) ⇒ Object
Set callbacks whenever a packet is sent or received.
- #on_raw_send(&block) ⇒ Object
- #receive_handler(type, counter, data, checksum) ⇒ Object
-
#send_packet(data, options = {}) ⇒ Object
Wrap a string into a packet.
Constructor Details
#initialize(send_callback, receive_callback, options = {}) ⇒ RCA2006
Returns a new instance of RCA2006.
24 25 26 27 28 29 |
# File 'lib/protocol/rca2006.rb', line 24 def initialize(send_callback, receive_callback, = {}) @rec_queue = Queue.new @state = :first_startbyte @send_callback = send_callback @receive_callback = receive_callback end |
Instance Method Details
#add_char_to_packet(char) ⇒ Object
Big and ugly state machine that does most of the work
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 |
# File 'lib/protocol/rca2006.rb', line 74 def add_char_to_packet(char) @state = :first_checksum if (@state == 0) case @state when :first_startbyte @data = "" @state = ((char == STARTBYTES[0]) ? :second_startbyte : :first_startbyte) when :second_startbyte @state = (char == STARTBYTES[1]) ? :type : # special case: first startbyte is repeated (char == STARTBYTES[0] ? :second_startbyte : :first_startbyte) when :type @type = TYPE.invert[char] @state = :counter when :counter @counter = char @state = :length when :length @length = char @state = @length when Integer @data << char @state -= 1 when :first_checksum @checksum = (char << 8) @state = :second_checksum when :second_checksum @checksum = @checksum + char @state = :first_startbyte crc = ("" << @counter << @length << @data).crc_xmodem # received a valid packet if @type == :data || @type == :data_no_crc if @checksum == crc # send ACK send_packet(nil, :type => :ack, :counter => @counter) receive_handler(@type, @counter, @data,@checksum) else # send NACK and discard packet send_packet(nil, :type => :nack, :counter => @counter) raise ChecksumMismatch, "ChecksumMismatch, expected #{crc}, was #{@checksum}" end else # the packet is ACK, NACK or unknown, call receive-handler # data may be mangled since the checksum is not checked # receive_handler(@type, @counter, @data, @checksum) end end end |
#on_raw_receive(&block) ⇒ Object
Set callbacks whenever a packet is sent or received.
33 34 35 |
# File 'lib/protocol/rca2006.rb', line 33 def on_raw_receive(&block) @raw_receive_callback = block end |
#on_raw_send(&block) ⇒ Object
36 37 38 |
# File 'lib/protocol/rca2006.rb', line 36 def on_raw_send(&block) @raw_send_callback = block end |
#receive_handler(type, counter, data, checksum) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/protocol/rca2006.rb', line 59 def receive_handler(type, counter, data, checksum) @raw_receive_callback.call(type,counter,data,checksum) if @raw_receive_callback case type when :ack when :nack when :data @receive_callback.call(data) when :data_no_crc @receive_callback.call(data) end end |
#send_packet(data, options = {}) ⇒ Object
Wrap a string into a packet
the options-hash can be used to override the default packet format
44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/protocol/rca2006.rb', line 44 def send_packet(data, = {}) str = data.to_s type = TYPE[ [:type] || :data_no_crc].chr counter = [:counter] || 0 checksum = [:checksum] || ("" << counter << str.length << str).crc_xmodem @raw_send_callback.call(type, counter, data, checksum) if @raw_send_callback p = "" << STARTBYTES << type << counter << str.length << str << [checksum].pack("S").reverse # send the packet, using the callback # @send_callback.call(p) end |