X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=SCX%2FReader.pm;h=72dcb2542e3993c9b2cfcb348b2ffe312aed6e98;hb=d311baf05cce488606946a68ffee19980681030b;hp=c60ec95ea6f7fe65a949f90381efb6b44a690e0c;hpb=32547a84e1959917750d2ce8fe4b6157c2c33a09;p=slotcarman.git diff --git a/SCX/Reader.pm b/SCX/Reader.pm index c60ec95..72dcb25 100644 --- a/SCX/Reader.pm +++ b/SCX/Reader.pm @@ -2,8 +2,12 @@ package SCX::Reader; +use strict; + use Time::HiRes qw(gettimeofday tv_interval); use FileHandle; +use IO::Handle; +use POSIX; use SCX::CRC; our $PACKET_SIZE = 9; # 9 bytes + 0x05 @@ -12,9 +16,6 @@ our $LOG_ROTATE = 600; sub new { my ($class, $args) = @_; - my $callback = $args->{callback} - or die "callback arg not defined"; - my $portname = $args->{portname} or die "portname not specified"; @@ -23,7 +24,7 @@ sub new { die "stty died with code $? (no permissions?)"; } - open my $tty, '<:raw', $portname + sysopen(my $fh, $portname, O_RDONLY|O_NONBLOCK) or die "Can't open $portname: $!"; my $logfile = $args->{logfile}; @@ -36,13 +37,13 @@ sub new { my $self = { portname => $portname, - fh => $tty, + fh => $fh, logfile => $logfile, logfh => $logfh, log_gen => $log_gen, log_start => $now, starttime => $now, - callback => $callback, + track => $args->{track}, bytes => [], }; @@ -53,6 +54,8 @@ sub new { sub fh { return shift->{fh}; } +sub track { return shift->{track}; } + sub read { my ($self) = @_; @@ -63,6 +66,7 @@ sub read { my @bytes = unpack("C*", $data); + # print join(' ', map { sprintf(" %02x", $_) } @bytes), "\n"; push @{ $self->{bytes} }, @bytes; @bytes = @{ $self->{bytes} }; @@ -88,10 +92,15 @@ sub read { } my @packet = splice @bytes, 0, $PACKET_SIZE+1; - my $rv = &{ $self->{callback} }(@packet); - $self->log_bytes(@packet, $rv); + my $rv = $self->handle_packet(@packet); + $self->log_bytes(\@packet, $rv); + } + if (@bad_bytes) { + while (@bytes && $bytes[0] != 0x55) { + push @bad_bytes, shift @bytes; + } + $self->log_bytes(\@bad_bytes, "cannot parse packet"); } - $self->log_bad_bytes(\@bad_bytes, "Cannot parse packet"); @{ $self->{bytes} } = @bytes; } @@ -108,8 +117,8 @@ sub log_bytes { if ($now - $self->{log_start} >= $LOG_ROTATE) { close $self->{logfh}; $self->{log_gen} = $self->{log_gen} ? 0 : 1; - open my $fh, '>', $logfile . '.' . $self->{log_gen} - or die "Can't open $logfile.$self->{log_gen}: $!"; + open my $fh, '>', $self->{logfile} . '.' . $self->{log_gen} + or die "Can't open $self->{logfile}.$self->{log_gen}: $!"; $self->{logfh} = $fh; $self->{log_start} = $now; } @@ -117,6 +126,7 @@ sub log_bytes { $self->{logfh}->print(sprintf('% 10.3f', $now - $self->{starttime}), (map { sprintf(" %02x", $_) } @$bytes), $msg, "\n"); + $self->{logfh}->flush; } our %COMMANDS = ( @@ -140,7 +150,7 @@ sub handle_packet { my ($self, @data) = @_; my $cmd = $data[1]; - my @args = $data[2..7]; + my @args = @data[2..7]; my $sub = $COMMANDS{$cmd}; return "Unknown packet" @@ -165,7 +175,7 @@ sub car_programming_packet { my ($self, @bytes) = @_; my $msg = 'Strange car programming packet' - if $bytes[0] & 0xF8 != 0 || $bytes[0] & 0x07 > 5 + if ($bytes[0] & 0xF8) != 0 || ($bytes[0] & 0x07) > 5 || $bytes[1] != 0xFE || $bytes[2] != 0xFF || $bytes[3] != 0xFF @@ -191,12 +201,16 @@ sub standings_packet { my ($self, @bytes) = @_; my $msg = 'Strange standings packet' - if $bytes[0] & 0x07 > 5 - || $bytes[1] & 0x07 > 5 - || $bytes[2] & 0x07 > 5 - || $bytes[3] & 0x07 > 5 - || $bytes[4] & 0x07 > 5 - || $bytes[5] & 0x07 > 5; + if ($bytes[0] != 0xFF && ($bytes[0] & 0x07) > 5) + || ($bytes[1] != 0xFF && ($bytes[1] & 0x07) > 5) + || ($bytes[2] != 0xFF && ($bytes[2] & 0x07) > 5) + || ($bytes[3] != 0xFF && ($bytes[3] & 0x07) > 5) + || ($bytes[4] != 0xFF && ($bytes[4] & 0x07) > 5) + || ($bytes[5] != 0xFF && ($bytes[5] & 0x07) > 5); + + my @standings; + + push @standings, map { $_ != 0xFF ? $_ & (0x07) : () } @bytes; return $msg; # FIXME - to be implemented } @@ -208,11 +222,34 @@ sub lap_time_packet { if $bytes[0] > 5 || $bytes[1] & 0x01 || $bytes[2] & 0x01 - || $bytes[3] & 0xF8 != 0 + || ($bytes[3] & 0xF0) != 0 || $bytes[4] & 0x01 || $bytes[5] & 0x01; - return $msg; # FIXME - to be implemented + my $nonzero = grep { $_ != 0 } @bytes; + + my $car = $bytes[0]; + my $round = 256*$bytes[1] + $bytes[2] + + ($bytes[3] & 2 ? 256 : 0) + + ($bytes[3] & 1 ? 1 : 0); + my $time = 256*$bytes[4] + $bytes[5] + + ($bytes[3] & 8 ? 256 : 0) + + ($bytes[3] & 4 ? 1 : 0); + if ($time == 65535) { + $self->track->car($car)->enter_pit_lane; + } else { + $time *= 0.01024; + + if ($nonzero) { + $self->track->car($car)->set_lap($round); + $self->track->car($car)->set_laptime($time); + } else { + # FIXME - probably reset race time or whatever + # all-zeros packet is sent after the race setup + } + } + + return $msg; } @@ -227,6 +264,12 @@ sub race_setup_packet { || $bytes[4] != 0xFF || $bytes[5] != 0xFF; + $self->track->race_setup($bytes[0] == 0x00 + ? 0 + : $bytes[1] & 0x0F * 256 + + $bytes[2] & 0x0F * 16 + + $bytes[3] & 0x0F); + return $msg; # FIXME - to be implemented } @@ -236,30 +279,24 @@ sub fuel_level_packet { my $msg = 'Strange fuel_level packet' if ($bytes[0] >> 4) > 8 - || $bytes[0] & 0x0F > 8 + || ($bytes[0] & 0x0F) > 8 || ($bytes[1] >> 4) > 8 - || $bytes[1] & 0x0F > 8 + || ($bytes[1] & 0x0F) > 8 || ($bytes[2] >> 4) > 8 - || $bytes[2] & 0x0F > 8 + || ($bytes[2] & 0x0F) > 8 || ($bytes[5] != 0xAA && $bytes[5] != 0xFF); -=comment - my @fuel = (0, - $data[1] >> 4, $data[1] & 0x0f, - $data[2] >> 4, $data[2] & 0x0f, - $data[3] >> 4, $data[3] & 0x0f, - ); - for my $car (1..6) { - next if defined $controllers[$car-1] - &&$controllers[$car-1] == $fuel[$car]; - - my $progressbar = $builder->get_object( - 'progressbar_fuel'.$car); - $progressbar->set_fraction($fuel[$car]/8); - } -=cut + my @fuel = ( + $bytes[0] >> 4, $bytes[0] & 0x0f, + $bytes[1] >> 4, $bytes[1] & 0x0f, + $bytes[2] >> 4, $bytes[2] & 0x0f, + ); - return $msg; # FIXME - to be implemented + for my $car (0..5) { + $self->track->car($car)->set_fuel($fuel[$car]); + } + + return $msg; } @@ -281,6 +318,11 @@ sub qualification_packet { || $bytes[4] != 0xFF || $bytes[5] != 0xFF; + for my $car (0..5) { + $self->track->car($car)->set_lap(undef); + $self->track->car($car)->set_laptime(undef); + } + return $msg; # FIXME - to be implemented } @@ -296,6 +338,8 @@ sub end_of_race_packet { || $bytes[4] != 0xFF || $bytes[5] != 0xFF; + $self->track->race_end; + return $msg; # FIXME - to be implemented } @@ -311,6 +355,8 @@ sub race_start_packet { || $bytes[4] != 0xAA || $bytes[5] != 0xAA; + $self->track->race_start; + return $msg; # FIXME - to be implemented } @@ -345,48 +391,69 @@ sub finish_line_packet { my $msg = 'Strange finish_line packet' if $fail; + my $pit_lane_entry; + my $too_fast; + my @cars_finished; + for my $i (0..5) { + my $byte = $bytes[$i]; + + $pit_lane_entry = 1 if $byte == 0xF0; + $too_fast = 1 if $byte == 0xFF; + + push @cars_finished, $i if $byte == 0xE7; + } + + if ($pit_lane_entry) { + for my $car (@cars_finished) { + $self->track->car($car)->enter_pit_lane; + } + } else { + for my $car (@cars_finished) { + $self->track->car($car)->leave_pit_lane; + } + } + return $msg; # FIXME - to be implemented } - sub controller_status_packet { my ($self, @bytes) = @_; my $fail; for my $byte (@bytes) { + next if $byte == 0xAA; $fail = 1 - if $byte & 0xC0 != 0xC0 - || $byte & 0x0F > 12 + if ($byte & 0xC0) != 0xC0 + || ($byte & 0x0F) > 12 } my $msg = 'Strange controller_status packet' if $fail; -=comment - for my $controller (1..6) { - my $byte = $data[$controller]; - next if defined $controllers[$controller-1] - && $controllers[$controller-1] == $byte; - $controllers[$controller-1] = $byte; - - my $progressbar = $builder->get_object( - 'progressbar_controller'.$controller); - if ($byte == 0xaa) { - $progressbar->set_text('inactive'); - $progressbar->set_fraction(0); - next; - } - my $light = !($byte & 0x20); - my $backbutton = !($byte & 0x10); - my $speed = $byte & 0x0f; - - my $text = ($backbutton ? '+' : '') . $speed; - $progressbar->set_text($text); - $progressbar->set_fraction($speed / 12); + my @fuel = ( + $bytes[1] >> 4, $bytes[1] & 0x0f, + $bytes[2] >> 4, $bytes[2] & 0x0f, + $bytes[3] >> 4, $bytes[3] & 0x0f, + ); + + for my $car (0..5) { + my $byte = $bytes[$car]; + + if ($byte == 0xAA) { + $self->track->car($car)->set_throttle(undef); + next; } -=cut - return $msg; # FIXME - to be implemented + my $light = !($byte & 0x20); + my $backbutton = !($byte & 0x10); + my $throttle = $byte & 0x0f; + + $self->track->car($car)->set_throttle($throttle); + $self->track->car($car)->set_light($light); + $self->track->car($car)->set_backbutton($backbutton); + } + + return $msg; } 1;