Hi,
I have a small program, that reads data from a serial port and chops
it into packets. A Packet has the following format:
[0x65, 0xEB, <type:8>, <counter:8>, <length:8>, data:length>, <crc:16>]
I have a thread that reads the data from an IO object:
@receiver_thread = Thread.new do
Thread.abort_on_exception = true
loop do
begin
char = @io.readchar
add_char_to_packet(char) if char
rescue EOFError
Thread.pass # there is currently nothing to read
end
end
and a state machine, that decodes the format:
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
[...]
This works, but the code is ugly and also a little slow because I have
to process each byte seperately. Is there a better way?
Thank you,
Levin