]> www.fi.muni.cz Git - slotcarman.git/blobdiff - SCX/Reader.pm
First implementation of qualification.
[slotcarman.git] / SCX / Reader.pm
index e3431ad425ad40e66acd33832eb2e73ed097082a..010647648b3d5e7e94383f2be529eb085153ee9c 100644 (file)
@@ -11,7 +11,7 @@ use POSIX;
 use SCX::CRC;
 
 our $PACKET_SIZE = 9; # 9 bytes + 0x05
-our $LOG_ROTATE  = 600;
+our $LOG_FILE_LIMIT = 10_000_000; # bytes
 
 sub new {
        my ($class, $args) = @_;
@@ -33,16 +33,12 @@ sub new {
        open my $logfh, '>', "$logfile.$log_gen"
        or die "Can't open $logfile.$log_gen: $!";
 
-       my $now = gettimeofday;
-
        my $self = {
                portname  => $portname,
                fh        => $fh,
                logfile   => $logfile,
                logfh     => $logfh,
                log_gen   => $log_gen,
-               log_start => $now,
-               starttime => $now,
                track     => $args->{track},
                bytes     => [],
        };
@@ -64,6 +60,8 @@ sub read {
        die "Read error on $self->{portname}: $!"
                if !$bytes_read;
 
+       $self->{last_read_time} = gettimeofday;
+
        my @bytes = unpack("C*", $data);
 
        # print join(' ', map { sprintf(" %02x", $_) } @bytes), "\n";
@@ -94,7 +92,9 @@ sub read {
                my @packet = splice @bytes, 0, $PACKET_SIZE+1;
                my $rv = $self->handle_packet(@packet);
                $self->log_bytes(\@packet, $rv);
+               $self->track->packet_received($self->{last_read_time});
        }
+
        if (@bad_bytes) {
                while (@bytes && $bytes[0] != 0x55) {
                        push @bad_bytes, shift @bytes;
@@ -105,30 +105,40 @@ sub read {
        @{ $self->{bytes} } = @bytes;
 }
 
-sub log_bytes {
-       my ($self, $bytes, $msg) = @_;
-
-       return if !@$bytes;
-
-       $msg = defined $msg ? ' # ' . $msg : '';
+sub log_print {
+       my ($self, @data) = @_;
 
-       my $now = gettimeofday;
+       my $size = $self->{logfh}->tell;
 
-       if ($now - $self->{log_start} >= $LOG_ROTATE) {
+       if ($size >= $LOG_FILE_LIMIT) {
                close $self->{logfh};
                $self->{log_gen} = $self->{log_gen} ? 0 : 1;
                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;
        }
 
-       $self->{logfh}->print(sprintf('% 10.3f', $now - $self->{starttime}),
-               (map { sprintf(" %02x", $_) } @$bytes),
-               $msg, "\n");
+       $self->{logfh}->print(sprintf('% 10.3f ', $self->{last_read_time}),
+               join(' ', @data, "\n"));
        $self->{logfh}->flush;
 }
 
+sub log_bytes {
+       my ($self, $bytes, $msg) = @_;
+
+       return if !@$bytes;
+
+       $msg = defined $msg ? '# ' . $msg : '';
+
+       $self->log_print((map { sprintf("%02x", $_) } @$bytes), $msg);
+}
+
+sub log_cmd {
+       my ($self, @args) = @_;
+
+       $self->log_print('cmd', @args);
+}
+
 our %COMMANDS = (
        0xAA => \&bus_free_time_packet,
        0xCC => \&car_programming_packet,
@@ -182,7 +192,7 @@ sub car_programming_packet {
                || $bytes[4] != 0xFF
                || $bytes[5] != 0xFF;
 
-       return $msg;
+       return $msg; # No need to handle this
 }
 
 sub reset_packet {
@@ -194,7 +204,10 @@ sub reset_packet {
                || $bytes[4] != 0xAA
                || $bytes[5] != 0xAA;
 
-       return $msg; # FIXME - to be implemented
+       $self->log_cmd('reset');
+       $self->track->reset;
+
+       return $msg;
 }
 
 sub standings_packet {
@@ -212,7 +225,7 @@ sub standings_packet {
 
        push @standings, map { $_ != 0xFF ? $_ & (0x07) : () } @bytes;
 
-       return $msg; # FIXME - to be implemented
+       return $msg; # We do internal standings handling
 }
 
 sub lap_time_packet {
@@ -226,10 +239,9 @@ sub lap_time_packet {
                || $bytes[4] & 0x01
                || $bytes[5] & 0x01;
 
-       return $msg; # FIXME - to be implemented
+       return $msg;
 }
 
-
 sub race_setup_packet {
        my ($self, @bytes) = @_;
 
@@ -241,9 +253,17 @@ sub race_setup_packet {
                || $bytes[4] != 0xFF
                || $bytes[5] != 0xFF;
 
-       return $msg; # FIXME - to be implemented
-}
+       my $rounds = $bytes[0] == 0x00
+               ? 0
+               : ($bytes[1] & 0x0F) * 256
+                       + ($bytes[2] & 0x0F) * 16
+                       + ($bytes[3] & 0x0F);
 
+       $self->log_cmd('race_setup', $rounds);
+       $self->track->race_setup($rounds, $self->{last_read_time});
+
+       return $msg;
+}
 
 sub fuel_level_packet {
        my ($self, @bytes) = @_;
@@ -263,6 +283,7 @@ sub fuel_level_packet {
                $bytes[2] >> 4, $bytes[2] & 0x0f,
        );
 
+       $self->log_cmd('fuel', @fuel);
        for my $car (0..5) {
                $self->track->car($car)->set_fuel($fuel[$car]);
        }
@@ -285,11 +306,19 @@ sub qualification_packet {
                if $bytes[0] & 0xF0
                || $bytes[1] & 0xF0
                || $bytes[2] & 0xF0
-               || $bytes[3] > 5
+               || $bytes[3] > 6
                || $bytes[4] != 0xFF
                || $bytes[5] != 0xFF;
 
-       return $msg; # FIXME - to be implemented
+       my $rounds = ($bytes[0] & 0x0F) * 256
+                       + ($bytes[1] & 0x0F) * 16
+                       + ($bytes[2] & 0x0F);
+       my $cars = $bytes[3];
+       $self->log_cmd('qualification_start', $rounds, $cars);
+       $self->track->qualification_setup($rounds, $cars,
+               $self->{last_read_time});
+
+       return $msg;
 }
 
 
@@ -304,7 +333,10 @@ sub end_of_race_packet {
                || $bytes[4] != 0xFF
                || $bytes[5] != 0xFF;
 
-       return $msg; # FIXME - to be implemented
+       $self->log_cmd('race_end');
+       $self->track->race_end;
+
+       return $msg;
 }
 
 
@@ -319,7 +351,10 @@ sub race_start_packet {
                || $bytes[4] != 0xAA
                || $bytes[5] != 0xAA;
 
-       return $msg; # FIXME - to be implemented
+       $self->log_cmd('race_start');
+       $self->track->race_start($self->{last_read_time});
+
+       return $msg;
 }
 
 
@@ -353,16 +388,33 @@ sub finish_line_packet {
        my $msg = 'Strange finish_line packet'
                if $fail;
 
-       return $msg; # FIXME - to be implemented
-}
+       my $regular = 1;
+       my @cars_finished;
+       for my $i (0..5) {
+               my $byte = $bytes[$i];
+
+               $regular = 0
+                       if $byte != 0xAA && $byte != 0xE7 && $byte != 0xFE;
+
+               push @cars_finished, $i if $byte == 0xE7;
+       }
+
+       $self->log_cmd('finish_line', $regular, @cars_finished);
+       $self->track->finish_line(
+               $self->{last_read_time},
+               $regular,
+               @cars_finished
+       );
 
+       return $msg;
+}
 
 sub controller_status_packet {
        my ($self, @bytes) = @_;
 
        my $fail;
        for my $byte (@bytes) {
-               next if $byte == 0xA0;
+               next if $byte == 0xAA;
                $fail = 1
                        if ($byte & 0xC0) != 0xC0
                        || ($byte & 0x0F) > 12
@@ -371,17 +423,15 @@ sub controller_status_packet {
        my $msg = 'Strange controller_status packet'
                if $fail;
 
-       my @fuel = (
-               $bytes[1] >> 4, $bytes[1] & 0x0f,
-               $bytes[2] >> 4, $bytes[2] & 0x0f,
-               $bytes[3] >> 4, $bytes[3] & 0x0f,
-       );
+       my @log_data;
 
        for my $car (0..5) {
                my $byte = $bytes[$car];
 
                if ($byte == 0xAA) {
-                       $self->track->car($car)->set_throttle(undef);
+                       $self->track->car($car)->set_throttle(undef, undef,
+                               $self->{last_read_time});
+                       push @log_data, 'undef', '0';
                        next;
                }
 
@@ -389,11 +439,14 @@ sub controller_status_packet {
                my $backbutton = !($byte & 0x10);
                my $throttle = $byte & 0x0f;
 
-               $self->track->car($car)->set_throttle($throttle);
+               push @log_data, $throttle, $backbutton ? 1 : 0;
+               $self->track->car($car)->set_throttle($throttle, $backbutton,
+                       $self->{last_read_time});
                $self->track->car($car)->set_light($light);
-               $self->track->car($car)->set_backbutton($backbutton);
        }
 
+       $self->log_cmd('throttle', @log_data);
+
        return $msg;
 }